Browse Source

Fix loading things in instance_extra for old instances

If we don't have db_inst['extra'] then we can't load those things. We
should just set them to None instead of exploding.

Conflicts:
	nova/objects/instance.py

Change-Id: I2ace62158faaa0b6a7df3c32f2cb9f235d178013
Closes-Bug: #1446082
(cherry picked from commit 1bfb65d5ac)
tags/2015.1.1
Dan Smith 4 years ago
parent
commit
8ba0159a0e
2 changed files with 57 additions and 7 deletions
  1. 25
    7
      nova/objects/instance.py
  2. 32
    0
      nova/tests/unit/objects/test_instance.py

+ 25
- 7
nova/objects/instance.py View File

@@ -445,8 +445,9 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
445 445
         if flavor_implied:
446 446
             # This instance is from before flavors were migrated out of
447 447
             # system_metadata. Make sure that we honor that.
448
-            if db_inst['extra']['flavor'] is not None:
449
-                self._flavor_from_db(db_inst['extra']['flavor'])
448
+            instance_extra = db_inst.get('extra') or {}
449
+            if instance_extra.get('flavor') is not None:
450
+                self._flavor_from_db(instance_extra['flavor'])
450 451
                 sysmeta = self.system_metadata
451 452
                 flavors.save_flavor_info(sysmeta, self.flavor)
452 453
                 del self.flavor
@@ -488,6 +489,13 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
488 489
             else:
489 490
                 instance[field] = db_inst[field]
490 491
 
492
+        # NOTE(danms): We can be called with a dict instead of a
493
+        # SQLAlchemy object, so we have to be careful here
494
+        if hasattr(db_inst, '__dict__'):
495
+            have_extra = 'extra' in db_inst.__dict__ and db_inst['extra']
496
+        else:
497
+            have_extra = 'extra' in db_inst and db_inst['extra']
498
+
491 499
         if 'metadata' in expected_attrs:
492 500
             instance['metadata'] = utils.instance_meta(db_inst)
493 501
         if 'system_metadata' in expected_attrs:
@@ -497,13 +505,23 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
497 505
                 objects.InstanceFault.get_latest_for_instance(
498 506
                     context, instance.uuid))
499 507
         if 'numa_topology' in expected_attrs:
500
-            instance._load_numa_topology(
501
-                db_inst.get('extra').get('numa_topology'))
508
+            if have_extra:
509
+                instance._load_numa_topology(
510
+                    db_inst['extra'].get('numa_topology'))
511
+            else:
512
+                instance.numa_topology = None
502 513
         if 'pci_requests' in expected_attrs:
503
-            instance._load_pci_requests(
504
-                db_inst.get('extra').get('pci_requests'))
514
+            if have_extra:
515
+                instance._load_pci_requests(
516
+                    db_inst['extra'].get('pci_requests'))
517
+            else:
518
+                instance.pci_requests = None
505 519
         if 'vcpu_model' in expected_attrs:
506
-            instance._load_vcpu_model(db_inst.get('extra').get('vcpu_model'))
520
+            if have_extra:
521
+                instance._load_vcpu_model(
522
+                    db_inst['extra'].get('vcpu_model'))
523
+            else:
524
+                instance.vcpu_model = None
507 525
         if 'info_cache' in expected_attrs:
508 526
             if db_inst['info_cache'] is None:
509 527
                 instance.info_cache = None

+ 32
- 0
nova/tests/unit/objects/test_instance.py View File

@@ -1158,6 +1158,38 @@ class _TestInstanceObject(object):
1158 1158
         self.assertTrue(inst.obj_attr_is_set('flavor'))
1159 1159
         self.assertEqual(flavor.flavorid, inst.flavor.flavorid)
1160 1160
 
1161
+    def test_without_extra_record(self):
1162
+        flavor = flavors.get_default_flavor()
1163
+        db_inst = fake_instance.fake_db_instance()
1164
+        db_inst['system_metadata'] = flavors.save_flavor_info({}, flavor)
1165
+        del db_inst['extra']
1166
+        with mock.patch('nova.db.instance_get_by_uuid') as mock_get:
1167
+            mock_get.return_value = db_inst
1168
+            inst = objects.Instance.get_by_uuid(
1169
+                self.context, uuid='foo',
1170
+                expected_attrs=['numa_topology', 'pci_requests', 'vcpu_model',
1171
+                                'flavor'])
1172
+            for field in ('numa_topology', 'pci_requests', 'vcpu_model'):
1173
+                self.assertTrue(inst.obj_attr_is_set(field))
1174
+                self.assertIsNone(getattr(inst, field))
1175
+            self.assertTrue(inst.obj_attr_is_set('flavor'))
1176
+
1177
+    def test_with_null_extra_record(self):
1178
+        flavor = flavors.get_default_flavor()
1179
+        db_inst = fake_instance.fake_db_instance()
1180
+        db_inst['system_metadata'] = flavors.save_flavor_info({}, flavor)
1181
+        db_inst['extra'] = None
1182
+        with mock.patch('nova.db.instance_get_by_uuid') as mock_get:
1183
+            mock_get.return_value = db_inst
1184
+            inst = objects.Instance.get_by_uuid(
1185
+                self.context, uuid='foo',
1186
+                expected_attrs=['numa_topology', 'pci_requests', 'vcpu_model',
1187
+                                'flavor'])
1188
+            for field in ('numa_topology', 'pci_requests', 'vcpu_model'):
1189
+                self.assertTrue(inst.obj_attr_is_set(field))
1190
+                self.assertIsNone(getattr(inst, field))
1191
+            self.assertTrue(inst.obj_attr_is_set('flavor'))
1192
+
1161 1193
 
1162 1194
 class TestInstanceObject(test_objects._LocalTest,
1163 1195
                          _TestInstanceObject):

Loading…
Cancel
Save