summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Smith <danms@us.ibm.com>2013-06-18 13:58:33 -0700
committerDan Smith <danms@us.ibm.com>2013-06-26 08:03:14 -0700
commit9c99ba9ac7195627b8eaf679e80c92a80fbbc5e2 (patch)
tree391082b97758d7f0b55138dc9450ca6206bc768e
parent60aa25d0b4765f54e0700a801ff3a423c3874a6c (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.py34
-rw-r--r--nova/tests/objects/test_instance.py43
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):