diff --git a/nova/compute/manager.py b/nova/compute/manager.py index ae53984a13ab..95a35565c119 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -442,6 +442,11 @@ def object_compat(function): def decorated_function(self, context, *args, **kwargs): def _load_instance(instance_or_dict): if isinstance(instance_or_dict, dict): + # try to get metadata and system_metadata for most cases but + # only attempt to load those if the db instance already has + # those fields joined + metas = [meta for meta in ('metadata', 'system_metadata') + if meta in instance_or_dict] instance = objects.Instance._from_db_object( context, objects.Instance(), instance_or_dict, expected_attrs=metas) @@ -449,7 +454,6 @@ def object_compat(function): return instance return instance_or_dict - metas = ['metadata', 'system_metadata'] try: kwargs['instance'] = _load_instance(kwargs['instance']) except KeyError: diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index d5ae8c82de08..f76ccaab0a01 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -1352,6 +1352,24 @@ class ComputeTestCase(BaseTestCase): def test_fn(_self, context, instance): self.assertIsInstance(instance, objects.Instance) self.assertEqual(instance.uuid, db_inst['uuid']) + self.assertEqual(instance.metadata, db_inst['metadata']) + self.assertEqual(instance.system_metadata, + db_inst['system_metadata']) + test_fn(None, self.context, instance=db_inst) + + def test_object_compat_no_metas(self): + # Tests that we don't try to set metadata/system_metadata on the + # instance object using fields that aren't in the db object. + db_inst = fake_instance.fake_db_instance() + db_inst.pop('metadata', None) + db_inst.pop('system_metadata', None) + + @compute_manager.object_compat + def test_fn(_self, context, instance): + self.assertIsInstance(instance, objects.Instance) + self.assertEqual(instance.uuid, db_inst['uuid']) + self.assertNotIn('metadata', instance) + self.assertNotIn('system_metadata', instance) test_fn(None, self.context, instance=db_inst) def test_object_compat_more_positional_args(self): @@ -1361,6 +1379,9 @@ class ComputeTestCase(BaseTestCase): def test_fn(_self, context, instance, pos_arg_1, pos_arg_2): self.assertIsInstance(instance, objects.Instance) self.assertEqual(instance.uuid, db_inst['uuid']) + self.assertEqual(instance.metadata, db_inst['metadata']) + self.assertEqual(instance.system_metadata, + db_inst['system_metadata']) self.assertEqual(pos_arg_1, 'fake_pos_arg1') self.assertEqual(pos_arg_2, 'fake_pos_arg2')