From bd6c98faced86f6d150d31297a6281d824f9f482 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 22 Jul 2013 09:06:12 -0700 Subject: [PATCH] Add ObjectActionFailed exception and make Instance use it The obj_load_attr() code in Instance slipped through review with just a "raise Exception()" for the case where the load cannot complete. This adds a new exception for the case, fixes the Instance.obj_load_attr() method, and adds a test to verify it. Related to blueprint compute-api-objects Change-Id: I73c966deb3c498019370eb83ade64bff2c48aec0 --- nova/exception.py | 4 ++++ nova/objects/instance.py | 9 +++++++-- nova/tests/objects/test_instance.py | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/nova/exception.py b/nova/exception.py index 0068fe7f8e60..b323c5703c58 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1290,6 +1290,10 @@ class IncompatibleObjectVersion(NovaException): msg_fmt = _('Version %(objver)s of %(objname)s is not supported') +class ObjectActionError(NovaException): + msg_fmt = _('Object action %(action)s failed because: %(reason)s') + + class CoreAPIMissing(NovaException): msg_fmt = _("Core API extensions are missing: %(missing_apis)s") diff --git a/nova/objects/instance.py b/nova/objects/instance.py index 323cec2b9404..ca2323575ce9 100644 --- a/nova/objects/instance.py +++ b/nova/objects/instance.py @@ -17,6 +17,7 @@ import copy from nova.cells import opts as cells_opts from nova.cells import rpcapi as cells_rpcapi from nova import db +from nova import exception from nova import notifications from nova.objects import base from nova.objects import instance_fault @@ -394,7 +395,9 @@ class Instance(base.NovaObject): extra.append('fault') if not extra: - raise Exception('Cannot load "%s" from instance' % attrname) + raise exception.ObjectActionError( + action='obj_load_attr', + reason='attribute %s not lazy-loadable' % attrname) # NOTE(danms): This could be optimized to just load the bits we need instance = self.__class__.get_by_uuid(self._context, @@ -405,7 +408,9 @@ class Instance(base.NovaObject): if hasattr(instance, base.get_attrname(attrname)): self[attrname] = instance[attrname] else: - raise Exception('Cannot load "%s" from instance' % attrname) + raise exception.ObjectActionError( + action='obj_load_attr', + reason='loading %s requires recursion' % attrname) def _make_instance_list(context, inst_list, db_inst_list, expected_attrs): diff --git a/nova/tests/objects/test_instance.py b/nova/tests/objects/test_instance.py index 460085a1b812..1ad09df6c332 100644 --- a/nova/tests/objects/test_instance.py +++ b/nova/tests/objects/test_instance.py @@ -21,6 +21,7 @@ import netaddr from nova.cells import rpcapi as cells_rpcapi from nova import context from nova import db +from nova import exception from nova.network import model as network_model from nova.objects import base from nova.objects import instance @@ -155,6 +156,11 @@ class _TestInstanceObject(object): self.assertEqual(sys_meta2, {'foo': 'bar'}) self.assertRemotes() + def test_load_invalid(self): + inst = instance.Instance() + self.assertRaises(exception.ObjectActionError, + inst.obj_load_attr, 'foo') + def test_get_remote(self): # isotime doesn't have microseconds and is always UTC ctxt = context.get_admin_context()