diff options
| author | Dan Smith <danms@us.ibm.com> | 2013-06-18 13:58:33 -0700 |
|---|---|---|
| committer | Dan Smith <danms@us.ibm.com> | 2013-06-26 08:03:14 -0700 |
| commit | 9c99ba9ac7195627b8eaf679e80c92a80fbbc5e2 (patch) | |
| tree | 391082b97758d7f0b55138dc9450ca6206bc768e | |
| parent | 60aa25d0b4765f54e0700a801ff3a423c3874a6c (diff) | |
Add Instance.fault
This makes Instance load fault as an optional attribute, if
requested. I didn't implement save for this, as I'm not sure
we will (want to) support setting instance faults via that
interface.
Related to unified-object-model
Fixes bug 1192004
Change-Id: I581e1f49c4c593ece97cf32dc7cea3f7a7cbd953
| -rw-r--r-- | nova/objects/instance.py | 34 | ||||
| -rw-r--r-- | nova/tests/objects/test_instance.py | 43 |
2 files changed, 73 insertions, 4 deletions
diff --git a/nova/objects/instance.py b/nova/objects/instance.py index 3691e7282..4f1db6302 100644 --- a/nova/objects/instance.py +++ b/nova/objects/instance.py @@ -15,6 +15,7 @@ from nova import db from nova import notifications from nova.objects import base +from nova.objects import instance_fault from nova.objects import instance_info_cache from nova.objects import security_group from nova.objects import utils as obj_utils @@ -27,11 +28,11 @@ CONF = cfg.CONF # These are fields that can be specified as expected_attrs -INSTANCE_OPTIONAL_FIELDS = ['metadata', 'system_metadata'] +INSTANCE_OPTIONAL_FIELDS = ['metadata', 'system_metadata', 'fault'] # These are fields that are always joined by the db right now INSTANCE_IMPLIED_FIELDS = ['info_cache', 'security_groups'] # These are fields that are optional but don't translate to db columns -INSTANCE_OPTIONAL_NON_COLUMNS = [] +INSTANCE_OPTIONAL_NON_COLUMNS = ['fault'] class Instance(base.NovaObject): @@ -114,6 +115,10 @@ class Instance(base.NovaObject): 'security_groups': obj_utils.nested_object_or_none( security_group.SecurityGroupList), + + 'fault': obj_utils.nested_object_or_none( + instance_fault.InstanceFault), + } obj_extra_fields = ['name'] @@ -190,6 +195,10 @@ class Instance(base.NovaObject): if 'system_metadata' in expected_attrs: instance['system_metadata'] = utils.metadata_to_dict( db_inst['system_metadata']) + if 'fault' in expected_attrs: + instance['fault'] = ( + instance_fault.InstanceFault.get_latest_for_instance( + context, instance.uuid)) # NOTE(danms): info_cache and security_groups are almost always joined # in the DB layer right now, so check to see if they're filled instead # of looking at expected_attrs @@ -234,6 +243,10 @@ class Instance(base.NovaObject): for secgroup in self.security_groups: secgroup.save(context) + def _save_instance_fault(self, context): + # NOTE(danms): I don't think we need to worry about this, do we? + pass + @base.remotable def save(self, context, expected_task_state=None): """Save updates to this instance @@ -295,6 +308,8 @@ class Instance(base.NovaObject): extra.append('info_cache') elif attrname == 'security_groups': extra.append('security_groups') + elif attrname == 'fault': + extra.append('fault') if not extra: raise Exception('Cannot load "%s" from instance' % attrname) @@ -307,11 +322,24 @@ class Instance(base.NovaObject): def _make_instance_list(context, inst_list, db_inst_list, expected_attrs): + get_fault = expected_attrs and 'fault' in expected_attrs + inst_faults = {} + if get_fault: + # Build an instance_uuid:latest-fault mapping + expected_attrs.remove('fault') + instance_uuids = [inst['uuid'] for inst in db_inst_list] + faults = instance_fault.InstanceFaultList.get_by_instance_uuids( + context, instance_uuids) + for fault in faults: + if fault.instance_uuid not in inst_faults: + inst_faults[fault.instance_uuid] = fault + inst_list.objects = [] for db_inst in db_inst_list: inst_obj = Instance._from_db_object(context, Instance(), db_inst, expected_attrs=expected_attrs) - inst_obj._context = context + if get_fault: + inst_obj.fault = inst_faults.get(inst_obj.uuid, None) inst_list.objects.append(inst_obj) inst_list.obj_reset_changes() return inst_list diff --git a/nova/tests/objects/test_instance.py b/nova/tests/objects/test_instance.py index 3a2486f9e..f886e2f41 100644 --- a/nova/tests/objects/test_instance.py +++ b/nova/tests/objects/test_instance.py @@ -24,6 +24,8 @@ from nova.objects import security_group from nova.openstack.common import timeutils from nova import test from nova.tests.api.openstack import fakes +from nova.tests import fake_instance +from nova.tests.objects import test_instance_fault from nova.tests.objects import test_objects @@ -105,7 +107,7 @@ class _TestInstanceObject(object): self.mox.StubOutWithMock(db, 'instance_get_by_uuid') db.instance_get_by_uuid( ctxt, 'uuid', - instance.INSTANCE_OPTIONAL_FIELDS).AndReturn(self.fake_instance) + ['metadata', 'system_metadata']).AndReturn(self.fake_instance) self.mox.ReplayAll() inst = instance.Instance.get_by_uuid( ctxt, 'uuid', expected_attrs=instance.INSTANCE_OPTIONAL_FIELDS) @@ -250,6 +252,24 @@ class _TestInstanceObject(object): inst.save() self.assertEqual(inst.security_groups.obj_what_changed(), set()) + def test_with_fault(self): + ctxt = context.get_admin_context() + fake_inst = dict(self.fake_instance) + fake_uuid = fake_inst['uuid'] + fake_faults = [dict(x, instance_uuid=fake_uuid) + for x in test_instance_fault.fake_faults['fake-uuid']] + self.mox.StubOutWithMock(db, 'instance_get_by_uuid') + self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids') + db.instance_get_by_uuid(ctxt, fake_uuid, []).AndReturn( + self.fake_instance) + db.instance_fault_get_by_instance_uuids(ctxt, [fake_uuid]).AndReturn( + {fake_uuid: fake_faults}) + self.mox.ReplayAll() + inst = instance.Instance.get_by_uuid(ctxt, fake_uuid, + expected_attrs=['fault']) + self.assertEqual(fake_faults[0], dict(inst.fault.items())) + self.assertRemotes() + def test_iteritems_with_extra_attrs(self): self.stubs.Set(instance.Instance, 'name', 'foo') inst = instance.Instance() @@ -375,6 +395,27 @@ class _TestInstanceListObject(object): self.assertEqual(inst_list.objects[i].uuid, fakes[i]['uuid']) self.assertRemotes() + def test_with_fault(self): + ctxt = context.get_admin_context() + fake_insts = [ + fake_instance.fake_db_instance(uuid='fake-uuid', host='host'), + fake_instance.fake_db_instance(uuid='fake-inst2', host='host'), + ] + fake_faults = test_instance_fault.fake_faults + self.mox.StubOutWithMock(db, 'instance_get_all_by_host') + self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids') + db.instance_get_all_by_host(ctxt, 'host', columns_to_join=[] + ).AndReturn(fake_insts) + db.instance_fault_get_by_instance_uuids( + ctxt, [x['uuid'] for x in fake_insts]).AndReturn(fake_faults) + self.mox.ReplayAll() + instances = instance.InstanceList.get_by_host(ctxt, 'host', + expected_attrs=['fault']) + self.assertEqual(2, len(instances)) + self.assertEqual(fake_faults['fake-uuid'][0], + dict(instances[0].fault.iteritems())) + self.assertEqual(None, instances[1].fault) + class TestInstanceListObject(test_objects._LocalTest, _TestInstanceListObject): |
