Merge "Add obj_make_compatible()"

This commit is contained in:
Jenkins 2013-10-24 01:08:59 +00:00 committed by Gerrit Code Review
commit 8f62dd1f05
3 changed files with 40 additions and 5 deletions

View File

@ -577,8 +577,13 @@ class ConductorManager(manager.Manager):
"""Perform a classmethod action on an object."""
objclass = nova_object.NovaObject.obj_class_from_name(objname,
objver)
return self._object_dispatch(objclass, objmethod, context,
args, kwargs)
result = self._object_dispatch(objclass, objmethod, context,
args, kwargs)
# NOTE(danms): The RPC layer will convert to primitives for us,
# but in this case, we need to honor the version the client is
# asking for, so we do it before returning here.
return (result.obj_to_primitive(target_version=objver)
if isinstance(result, nova_object.NovaObject) else result)
def object_action(self, context, objinst, objmethod, args, kwargs):
"""Perform an action on an object."""

View File

@ -259,7 +259,23 @@ class NovaObject(object):
"""Create a copy."""
return copy.deepcopy(self)
def obj_to_primitive(self):
def obj_make_compatible(self, primitive, target_version):
"""Make an object representation compatible with a target version.
This is responsible for taking the primitive representation of
an object and making it suitable for the given target_version.
This may mean converting the format of object attributes, removing
attributes that have been added since the target version, etc.
:param:primitive: The result of self.obj_to_primitive()
:param:target_version: The version string requested by the recipient
of the object.
:param:raises: nova.exception.UnsupportedObjectError if conversion
is not possible for some reason.
"""
pass
def obj_to_primitive(self, target_version=None):
"""Simple base-case dehydration.
This calls to_primitive() for each item in fields.
@ -269,9 +285,11 @@ class NovaObject(object):
if self.obj_attr_is_set(name):
primitive[name] = field.to_primitive(self, name,
getattr(self, name))
if target_version:
self.obj_make_compatible(primitive, target_version)
obj = {'nova_object.name': self.obj_name(),
'nova_object.namespace': 'nova',
'nova_object.version': self.VERSION,
'nova_object.version': target_version or self.VERSION,
'nova_object.data': primitive}
if self.obj_what_changed():
obj['nova_object.changes'] = list(self.obj_what_changed())

View File

@ -81,6 +81,12 @@ class MyObj(base.NovaPersistentObject, base.NovaObject):
self.save()
self.foo = 42
def obj_make_compatible(self, primitive, target_version):
# NOTE(danms): Simulate an older version that had a different
# format for the 'bar' attribute
if target_version == '1.1':
primitive['bar'] = 'old%s' % primitive['bar']
class MyObj2(object):
@classmethod
@ -363,7 +369,8 @@ class _RemoteTest(_BaseTestCase):
kwargs.get('objmethod')))
with things_temporarily_local():
result = orig_object_class_action(*args, **kwargs)
return result
return (base.NovaObject.obj_from_primitive(result, context=args[0])
if isinstance(result, base.NovaObject) else result)
self.stubs.Set(self.conductor_service.manager, 'object_class_action',
fake_object_class_action)
@ -659,6 +666,11 @@ class TestRemoteObject(_RemoteTest, _TestObject):
self.assertEqual(obj.bar, 'bar')
self.assertRemotes()
def test_compat(self):
MyObj2.VERSION = '1.1'
obj = MyObj2.query(self.context)
self.assertEqual('oldbar', obj.bar)
class TestObjectListBase(test.TestCase):
def test_list_like_operations(self):