diff --git a/nova/objects/instance.py b/nova/objects/instance.py index 68f1a0cc3665..48c831bd07e6 100644 --- a/nova/objects/instance.py +++ b/nova/objects/instance.py @@ -51,7 +51,7 @@ _INSTANCE_OPTIONAL_NON_COLUMN_FIELDS = ['fault', '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'] + 'keypairs', 'device_metadata'] # These are fields that applied/drooped by migration_context _MIGRATION_CONTEXT_ATTRS = ['numa_topology', 'pci_requests', 'pci_devices'] @@ -99,7 +99,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject, # Version 2.0: Initial version # Version 2.1: Added services # Version 2.2: Added keypairs - VERSION = '2.2' + # Version 2.3: Added device_metadata + VERSION = '2.3' fields = { 'id': fields.IntegerField(), @@ -190,6 +191,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject, nullable=True), 'pci_requests': fields.ObjectField('InstancePCIRequests', nullable=True), + 'device_metadata': fields.ObjectField('InstanceDeviceMetadata', + nullable=True), 'tags': fields.ObjectField('TagList'), 'flavor': fields.ObjectField('Flavor'), 'old_flavor': fields.ObjectField('Flavor', nullable=True), @@ -206,6 +209,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, 3) and 'device_metadata' in primitive: + del primitive['device_metadata'] if target_version < (2, 2) and 'keypairs' in primitive: del primitive['keypairs'] if target_version < (2, 1) and 'services' in primitive: @@ -336,6 +341,12 @@ class Instance(base.NovaPersistentObject, base.NovaObject, db_inst['extra'].get('pci_requests')) else: instance.pci_requests = None + if 'device_metadata' in expected_attrs: + if have_extra: + instance._load_device_metadata( + db_inst['extra'].get('device_metadata')) + else: + instance.device_metadata = None if 'vcpu_model' in expected_attrs: if have_extra: instance._load_vcpu_model( @@ -456,6 +467,13 @@ class Instance(base.NovaPersistentObject, base.NovaObject, pci_requests.to_json()) else: updates['extra']['pci_requests'] = None + device_metadata = updates.pop('device_metadata', None) + expected_attrs.append('device_metadata') + if device_metadata: + updates['extra']['device_metadata'] = ( + device_metadata._to_json()) + else: + updates['extra']['device_metadata'] = None flavor = updates.pop('flavor', None) if flavor: expected_attrs.append('flavor') @@ -799,6 +817,16 @@ class Instance(base.NovaPersistentObject, base.NovaObject, objects.InstancePCIRequests.get_by_instance_uuid( self._context, self.uuid) + def _load_device_metadata(self, db_requests=None): + if db_requests is not None: + self.device_metadata = \ + objects.InstanceDeviceMetadata.obj_from_db( + self._context, db_requests) + else: + self.device_metadata = \ + objects.InstanceDeviceMetadata.get_by_instance_uuid( + self._context, self.uuid) + def _load_flavor(self): instance = self.__class__.get_by_uuid( self._context, uuid=self.uuid, @@ -961,6 +989,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject, self._load_fault() elif attrname == 'numa_topology': self._load_numa_topology() + elif attrname == 'device_metadata': + self._load_device_metadata() elif attrname == 'pci_requests': self._load_pci_requests() elif attrname == 'vcpu_model': diff --git a/nova/tests/functional/db/test_build_request.py b/nova/tests/functional/db/test_build_request.py index 4aa04bf13ab7..62d326aa0db2 100644 --- a/nova/tests/functional/db/test_build_request.py +++ b/nova/tests/functional/db/test_build_request.py @@ -84,7 +84,7 @@ class BuildRequestTestCase(test.NoDBTestCase): 'pci_devices', 'security_groups', 'info_cache', 'ec2_ids', 'migration_context', 'metadata', 'vcpu_model', 'services', 'system_metadata', - 'tags', 'fault'], + 'tags', 'fault', 'device_metadata'], comparators={'flavor': obj_comp, 'created_at': date_comp, 'keypairs': obj_comp}) diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index d3abe7c93a37..43e628ebbe1a 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -2911,6 +2911,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): instance.numa_topology = None instance.pci_requests = None instance.pci_devices = None + instance.device_metadata = None instance.task_state = task_states.REBUILDING instance.save(expected_task_state=[task_states.REBUILDING]) self.compute._rebuild_default_impl(self.context, diff --git a/nova/tests/unit/fake_instance.py b/nova/tests/unit/fake_instance.py index 55280ddc01d2..085878858938 100644 --- a/nova/tests/unit/fake_instance.py +++ b/nova/tests/unit/fake_instance.py @@ -73,6 +73,7 @@ def fake_db_instance(**updates): 'flavor': flavorinfo, 'numa_topology': None, 'vcpu_model': None, + 'device_metadata': None, }, 'tags': [], 'services': [] diff --git a/nova/tests/unit/objects/test_instance.py b/nova/tests/unit/objects/test_instance.py index f701437f2f7b..60ad90fb97b3 100644 --- a/nova/tests/unit/objects/test_instance.py +++ b/nova/tests/unit/objects/test_instance.py @@ -37,6 +37,7 @@ from nova.objects import pci_device from nova.objects import security_group from nova import test from nova.tests.unit import fake_instance +from nova.tests.unit.objects import test_instance_device_metadata from nova.tests.unit.objects import test_instance_fault from nova.tests.unit.objects import test_instance_info_cache from nova.tests.unit.objects import test_instance_numa_topology @@ -143,15 +144,19 @@ class _TestInstanceObject(object): exp_cols.remove('ec2_ids') exp_cols.remove('migration_context') exp_cols.remove('keypairs') + exp_cols.remove('device_metadata') exp_cols = list(filter(lambda x: 'flavor' not in x, exp_cols)) exp_cols.extend(['extra', 'extra.numa_topology', 'extra.pci_requests', 'extra.flavor', 'extra.vcpu_model', - 'extra.migration_context', 'extra.keypairs']) + 'extra.migration_context', 'extra.keypairs', + 'extra.device_metadata']) fake_topology = (test_instance_numa_topology. fake_db_topology['numa_topology']) fake_requests = jsonutils.dumps(test_instance_pci_requests. fake_pci_requests) + fake_devices_metadata = \ + test_instance_device_metadata.fake_devices_metadata fake_flavor = jsonutils.dumps( {'cur': objects.Flavor().obj_to_primitive(), 'old': None, 'new': None}) @@ -176,6 +181,7 @@ class _TestInstanceObject(object): extra={ 'numa_topology': fake_topology, 'pci_requests': fake_requests, + 'device_metadata': fake_devices_metadata, 'flavor': fake_flavor, 'vcpu_model': fake_vcpu_model, 'migration_context': fake_mig_context, @@ -987,6 +993,7 @@ class _TestInstanceObject(object): 'vcpu_model': None, 'numa_topology': None, 'pci_requests': None, + 'device_metadata': None, }} fake_inst = fake_instance.fake_db_instance(**vals) mock_create.return_value = fake_inst @@ -1014,6 +1021,7 @@ class _TestInstanceObject(object): 'vcpu_model': None, 'numa_topology': None, 'pci_requests': None, + 'device_metadata': None, }} fake_inst = fake_instance.fake_db_instance(**vals) mock_create.return_value = fake_inst @@ -1028,11 +1036,12 @@ class _TestInstanceObject(object): def test_create(self, mock_create): extras = {'vcpu_model': None, 'numa_topology': None, - 'pci_requests': None} + 'pci_requests': None, + 'device_metadata': None} mock_create.return_value = self.fake_instance - inst = objects.Instance(context=self.context) inst.create() + self.assertEqual(self.fake_instance['id'], inst.id) self.assertIsNotNone(inst.ec2_ids) mock_create.assert_called_once_with(self.context, {'extra': extras}) @@ -1107,6 +1116,7 @@ class _TestInstanceObject(object): 'vcpu_model': None, 'numa_topology': None, 'pci_requests': None, + 'device_metadata': None, }, }) diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index d73fc7e0f90a..7ce84ec91035 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1130,7 +1130,7 @@ object_data = { 'IDEDeviceBus': '1.0-29d4c9f27ac44197f01b6ac1b7e16502', 'ImageMeta': '1.8-642d1b2eb3e880a367f37d72dd76162d', 'ImageMetaProps': '1.14-cc8f96454cdb0feadcb2fc9e63974016', - 'Instance': '2.2-ab450ec9c1f4d429755c48d492b823f0', + 'Instance': '2.3-4f98ab23f4b0a25fabb1040c8f5edecc', 'InstanceAction': '1.1-f9f293e526b66fca0d05c3b3a2d13914', 'InstanceActionEvent': '1.1-e56a64fa4710e43ef7af2ad9d6028b33', 'InstanceActionEventList': '1.1-13d92fb953030cdbfee56481756e02be',