summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nova/objects/__init__.py1
-rw-r--r--nova/objects/instance.py33
-rw-r--r--nova/objects/trusted_certs.py36
-rw-r--r--nova/tests/unit/fake_instance.py1
-rw-r--r--nova/tests/unit/objects/test_instance.py17
-rw-r--r--nova/tests/unit/objects/test_objects.py3
-rw-r--r--nova/tests/unit/objects/test_trusted_certs.py43
7 files changed, 129 insertions, 5 deletions
diff --git a/nova/objects/__init__.py b/nova/objects/__init__.py
index 380b102561..08c8cd03dc 100644
--- a/nova/objects/__init__.py
+++ b/nova/objects/__init__.py
@@ -69,6 +69,7 @@ def register_all():
__import__('nova.objects.selection')
__import__('nova.objects.service')
__import__('nova.objects.task_log')
+ __import__('nova.objects.trusted_certs')
__import__('nova.objects.vcpu_model')
__import__('nova.objects.virt_cpu_topology')
__import__('nova.objects.virtual_interface')
diff --git a/nova/objects/instance.py b/nova/objects/instance.py
index 90dd3f7612..b9094c2342 100644
--- a/nova/objects/instance.py
+++ b/nova/objects/instance.py
@@ -57,7 +57,7 @@ _INSTANCE_OPTIONAL_NON_COLUMN_FIELDS = ['flavor', 'old_flavor',
# These are fields that are optional and in instance_extra
_INSTANCE_EXTRA_FIELDS = ['numa_topology', 'pci_requests',
'flavor', 'vcpu_model', 'migration_context',
- 'keypairs', 'device_metadata']
+ 'keypairs', 'device_metadata', 'trusted_certs']
# These are fields that applied/drooped by migration_context
_MIGRATION_CONTEXT_ATTRS = ['numa_topology', 'pci_requests',
'pci_devices']
@@ -112,7 +112,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
# Version 2.1: Added services
# Version 2.2: Added keypairs
# Version 2.3: Added device_metadata
- VERSION = '2.3'
+ # Version 2.4: Added trusted_certs
+ VERSION = '2.4'
fields = {
'id': fields.IntegerField(),
@@ -212,6 +213,7 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
'migration_context': fields.ObjectField('MigrationContext',
nullable=True),
'keypairs': fields.ObjectField('KeyPairList'),
+ 'trusted_certs': fields.ObjectField('TrustedCerts', nullable=True),
}
obj_extra_fields = ['name']
@@ -219,6 +221,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
def obj_make_compatible(self, primitive, target_version):
super(Instance, self).obj_make_compatible(primitive, target_version)
target_version = versionutils.convert_version_to_tuple(target_version)
+ if target_version < (2, 4) and 'trusted_certs' in primitive:
+ del primitive['trusted_certs']
if target_version < (2, 3) and 'device_metadata' in primitive:
del primitive['device_metadata']
if target_version < (2, 2) and 'keypairs' in primitive:
@@ -453,6 +457,12 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
if 'keypairs' in expected_attrs:
if have_extra:
instance._load_keypairs(db_inst['extra'].get('keypairs'))
+ if 'trusted_certs' in expected_attrs:
+ if have_extra:
+ instance._load_trusted_certs(
+ db_inst['extra'].get('trusted_certs'))
+ else:
+ instance.trusted_certs = None
if any([x in expected_attrs for x in ('flavor',
'old_flavor',
'new_flavor')]):
@@ -560,6 +570,13 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
jsonutils.dumps(vcpu_model.obj_to_primitive()))
else:
updates['extra']['vcpu_model'] = None
+ trusted_certs = updates.pop('trusted_certs', None)
+ expected_attrs.append('trusted_certs')
+ if trusted_certs:
+ updates['extra']['trusted_certs'] = jsonutils.dumps(
+ trusted_certs.obj_to_primitive())
+ else:
+ updates['extra']['trusted_certs'] = None
db_inst = db.instance_create(self._context, updates)
self._from_db_object(self._context, self, db_inst, expected_attrs)
@@ -977,6 +994,16 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
self.tags = objects.TagList.get_by_resource_id(
self._context, self.uuid)
+ def _load_trusted_certs(self, db_trusted_certs=_NO_DATA_SENTINEL):
+ if db_trusted_certs is None:
+ self.trusted_certs = None
+ elif db_trusted_certs is _NO_DATA_SENTINEL:
+ self.trusted_certs = objects.TrustedCerts.get_by_instance_uuid(
+ self._context, self.uuid)
+ else:
+ self.trusted_certs = objects.TrustedCerts.obj_from_primitive(
+ jsonutils.loads(db_trusted_certs))
+
def apply_migration_context(self):
if self.migration_context:
self._set_migration_context_to_instance(prefix='new_')
@@ -1072,6 +1099,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
# NOTE(danms): Let keypairs control its own destiny for
# resetting changes.
return self._load_keypairs()
+ elif attrname == 'trusted_certs':
+ return self._load_trusted_certs()
elif attrname == 'security_groups':
self._load_security_groups()
elif attrname == 'pci_devices':
diff --git a/nova/objects/trusted_certs.py b/nova/objects/trusted_certs.py
new file mode 100644
index 0000000000..e4dd7e46c2
--- /dev/null
+++ b/nova/objects/trusted_certs.py
@@ -0,0 +1,36 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_serialization import jsonutils
+
+from nova import db
+from nova.objects import base
+from nova.objects import fields
+
+
+@base.NovaObjectRegistry.register
+class TrustedCerts(base.NovaObject):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ fields = {
+ 'ids': fields.ListOfStringsField(nullable=False),
+ }
+
+ @base.remotable_classmethod
+ def get_by_instance_uuid(cls, context, instance_uuid):
+ db_extra = db.instance_extra_get_by_instance_uuid(
+ context, instance_uuid, columns=['trusted_certs'])
+ if not db_extra or not db_extra['trusted_certs']:
+ return None
+ return cls.obj_from_primitive(
+ jsonutils.loads(db_extra['trusted_certs']))
diff --git a/nova/tests/unit/fake_instance.py b/nova/tests/unit/fake_instance.py
index 934fdd2441..39d94a029b 100644
--- a/nova/tests/unit/fake_instance.py
+++ b/nova/tests/unit/fake_instance.py
@@ -74,6 +74,7 @@ def fake_db_instance(**updates):
'numa_topology': None,
'vcpu_model': None,
'device_metadata': None,
+ 'trusted_certs': None,
},
'tags': [],
'services': []
diff --git a/nova/tests/unit/objects/test_instance.py b/nova/tests/unit/objects/test_instance.py
index 488fdf3a96..97edcf4fbe 100644
--- a/nova/tests/unit/objects/test_instance.py
+++ b/nova/tests/unit/objects/test_instance.py
@@ -70,6 +70,7 @@ class _TestInstanceObject(object):
db_inst['user_id'] = self.context.user_id
db_inst['project_id'] = self.context.project_id
db_inst['tags'] = []
+ db_inst['trusted_certs'] = []
db_inst['info_cache'] = dict(test_instance_info_cache.fake_info_cache,
instance_uuid=db_inst['uuid'])
@@ -144,11 +145,12 @@ class _TestInstanceObject(object):
exp_cols.remove('migration_context')
exp_cols.remove('keypairs')
exp_cols.remove('device_metadata')
+ exp_cols.remove('trusted_certs')
exp_cols = [exp_col for exp_col in exp_cols if 'flavor' not in exp_col]
exp_cols.extend(['extra', 'extra.numa_topology', 'extra.pci_requests',
'extra.flavor', 'extra.vcpu_model',
'extra.migration_context', 'extra.keypairs',
- 'extra.device_metadata'])
+ 'extra.device_metadata', 'extra.trusted_certs'])
fake_topology = (test_instance_numa_topology.
fake_db_topology['numa_topology'])
@@ -167,6 +169,8 @@ class _TestInstanceObject(object):
objects.KeyPair(name='foo')])
fake_keypairs = jsonutils.dumps(
fake_keypairlist.obj_to_primitive())
+ fake_trusted_certs = jsonutils.dumps(
+ objects.TrustedCerts(ids=['123foo']).obj_to_primitive())
fake_service = {'created_at': None, 'updated_at': None,
'deleted_at': None, 'deleted': False, 'id': 123,
'host': 'fake-host', 'binary': 'nova-compute',
@@ -185,6 +189,7 @@ class _TestInstanceObject(object):
'vcpu_model': fake_vcpu_model,
'migration_context': fake_mig_context,
'keypairs': fake_keypairs,
+ 'trusted_certs': fake_trusted_certs,
})
mock_get.return_value = fake_instance
@@ -199,6 +204,7 @@ class _TestInstanceObject(object):
self.assertTrue(inst.obj_attr_is_set(attr))
self.assertEqual(123, inst.services[0].id)
self.assertEqual('foo', inst.keypairs[0].name)
+ self.assertEqual(['123foo'], inst.trusted_certs.ids)
mock_get.assert_called_once_with(self.context, 'uuid',
columns_to_join=exp_cols)
@@ -1028,6 +1034,7 @@ class _TestInstanceObject(object):
'numa_topology': None,
'pci_requests': None,
'device_metadata': None,
+ 'trusted_certs': None,
}}
fake_inst = fake_instance.fake_db_instance(**vals)
mock_create.return_value = fake_inst
@@ -1057,6 +1064,7 @@ class _TestInstanceObject(object):
'numa_topology': None,
'pci_requests': None,
'device_metadata': None,
+ 'trusted_certs': None,
}}
fake_inst = fake_instance.fake_db_instance(**vals)
mock_create.return_value = fake_inst
@@ -1072,7 +1080,9 @@ class _TestInstanceObject(object):
extras = {'vcpu_model': None,
'numa_topology': None,
'pci_requests': None,
- 'device_metadata': None}
+ 'device_metadata': None,
+ 'trusted_certs': None,
+ }
mock_create.return_value = self.fake_instance
inst = objects.Instance(context=self.context)
inst.create()
@@ -1108,6 +1118,7 @@ class _TestInstanceObject(object):
objects.InstancePCIRequest(count=123,
spec=[])]),
vcpu_model=test_vcpu_model.fake_vcpumodel,
+ trusted_certs=objects.TrustedCerts(ids=['123foo']),
)
inst.create()
self.assertIsNotNone(inst.numa_topology)
@@ -1124,6 +1135,7 @@ class _TestInstanceObject(object):
vcpu_model = objects.VirtCPUModel.get_by_instance_uuid(
self.context, inst.uuid)
self.assertEqual('fake-model', vcpu_model.model)
+ self.assertEqual(['123foo'], inst.trusted_certs.ids)
def test_recreate_fails(self):
inst = objects.Instance(context=self.context,
@@ -1161,6 +1173,7 @@ class _TestInstanceObject(object):
'numa_topology': None,
'pci_requests': None,
'device_metadata': None,
+ 'trusted_certs': None,
},
})
diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py
index 60bcc0e032..4ad627dd72 100644
--- a/nova/tests/unit/objects/test_objects.py
+++ b/nova/tests/unit/objects/test_objects.py
@@ -1095,7 +1095,7 @@ object_data = {
'IDEDeviceBus': '1.0-29d4c9f27ac44197f01b6ac1b7e16502',
'ImageMeta': '1.8-642d1b2eb3e880a367f37d72dd76162d',
'ImageMetaProps': '1.19-dc9581ff2b80d8c33462889916b82df0',
- 'Instance': '2.3-4f98ab23f4b0a25fabb1040c8f5edecc',
+ 'Instance': '2.4-4437eb8b2737c3054ea579b8efe31dc5',
'InstanceAction': '1.1-f9f293e526b66fca0d05c3b3a2d13914',
'InstanceActionEvent': '1.1-e56a64fa4710e43ef7af2ad9d6028b33',
'InstanceActionEventList': '1.1-13d92fb953030cdbfee56481756e02be',
@@ -1158,6 +1158,7 @@ object_data = {
'TaskLogList': '1.0-cc8cce1af8a283b9d28b55fcd682e777',
'Tag': '1.1-8b8d7d5b48887651a0e01241672e2963',
'TagList': '1.1-55231bdb671ecf7641d6a2e9109b5d8e',
+ 'TrustedCerts': '1.0-dcf528851e0f868c77ee47e90563cda7',
'USBDeviceBus': '1.0-e4c7dd6032e46cd74b027df5eb2d4750',
'VirtCPUFeature': '1.0-ea2464bdd09084bd388e5f61d5d4fc86',
'VirtCPUModel': '1.0-5e1864af9227f698326203d7249796b5',
diff --git a/nova/tests/unit/objects/test_trusted_certs.py b/nova/tests/unit/objects/test_trusted_certs.py
new file mode 100644
index 0000000000..d056244a78
--- /dev/null
+++ b/nova/tests/unit/objects/test_trusted_certs.py
@@ -0,0 +1,43 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import mock
+
+from nova.objects import trusted_certs
+from nova.tests.unit.objects import test_objects
+from oslo_serialization import jsonutils
+
+fake_trusted_certs = trusted_certs.TrustedCerts(ids=['fake-trusted-cert-1',
+ 'fake-trusted-cert-2'])
+fake_instance_extras = {
+ 'trusted_certs': jsonutils.dumps(fake_trusted_certs.obj_to_primitive())
+}
+
+
+class _TestTrustedCertsObject(object):
+
+ @mock.patch('nova.db.instance_extra_get_by_instance_uuid')
+ def test_get_by_instance_uuid(self, mock_get):
+ mock_get.return_value = fake_instance_extras
+ certs = trusted_certs.TrustedCerts.get_by_instance_uuid(
+ self.context, 'fake_uuid')
+ self.assertEqual(certs.ids, fake_trusted_certs.ids)
+
+
+class TestTrustedCertsObject(test_objects._LocalTest,
+ _TestTrustedCertsObject):
+ pass
+
+
+class TestRemoteTrustedCertsObject(test_objects._RemoteTest,
+ _TestTrustedCertsObject):
+ pass