Remove references to Nova
Remove remaining references to "Nova" where possible, code cleanup. Also removed IP fields Co-Authored-By: Michal Jastrzebski (inc0) <michal.jastrzebski@intel.com> Change-Id: Ibad8f9fc6453321055029ad69b0374261509b9d5 Closes-Bug: 1417287
This commit is contained in:
committed by
Dan Smith
parent
5e79ffca1d
commit
c330f938c8
@@ -24,36 +24,4 @@ def register_all():
|
||||
# NOTE(danms): You must make sure your object gets imported in this
|
||||
# function in order for it to be registered by services that may
|
||||
# need to receive it via RPC.
|
||||
__import__('nova.objects.agent')
|
||||
__import__('nova.objects.aggregate')
|
||||
__import__('nova.objects.bandwidth_usage')
|
||||
__import__('nova.objects.block_device')
|
||||
__import__('nova.objects.compute_node')
|
||||
__import__('nova.objects.dns_domain')
|
||||
__import__('nova.objects.ec2')
|
||||
__import__('nova.objects.external_event')
|
||||
__import__('nova.objects.fixed_ip')
|
||||
__import__('nova.objects.flavor')
|
||||
__import__('nova.objects.floating_ip')
|
||||
__import__('nova.objects.hv_spec')
|
||||
__import__('nova.objects.instance')
|
||||
__import__('nova.objects.instance_action')
|
||||
__import__('nova.objects.instance_fault')
|
||||
__import__('nova.objects.instance_group')
|
||||
__import__('nova.objects.instance_info_cache')
|
||||
__import__('nova.objects.instance_numa_topology')
|
||||
__import__('nova.objects.instance_pci_requests')
|
||||
__import__('nova.objects.keypair')
|
||||
__import__('nova.objects.migration')
|
||||
__import__('nova.objects.network')
|
||||
__import__('nova.objects.network_request')
|
||||
__import__('nova.objects.numa')
|
||||
__import__('nova.objects.pci_device')
|
||||
__import__('nova.objects.pci_device_pool')
|
||||
__import__('nova.objects.tag')
|
||||
__import__('nova.objects.quotas')
|
||||
__import__('nova.objects.security_group')
|
||||
__import__('nova.objects.security_group_rule')
|
||||
__import__('nova.objects.service')
|
||||
__import__('nova.objects.virt_cpu_topology')
|
||||
__import__('nova.objects.virtual_interface')
|
||||
pass
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Nova common internal object model"""
|
||||
"""Common internal object model"""
|
||||
|
||||
import collections
|
||||
import contextlib
|
||||
@@ -159,13 +159,13 @@ def remotable_classmethod(fn):
|
||||
"""Decorator for remotable classmethods."""
|
||||
@functools.wraps(fn)
|
||||
def wrapper(cls, context, *args, **kwargs):
|
||||
if NovaObject.indirection_api:
|
||||
result = NovaObject.indirection_api.object_class_action(
|
||||
if VersionedObject.indirection_api:
|
||||
result = VersionedObject.indirection_api.object_class_action(
|
||||
context, cls.obj_name(), fn.__name__, cls.VERSION,
|
||||
args, kwargs)
|
||||
else:
|
||||
result = fn(cls, context, *args, **kwargs)
|
||||
if isinstance(result, NovaObject):
|
||||
if isinstance(result, VersionedObject):
|
||||
result._context = context
|
||||
return result
|
||||
|
||||
@@ -188,16 +188,16 @@ def remotable(fn):
|
||||
if ctxt is None:
|
||||
raise exception.OrphanedObjectError(method=fn.__name__,
|
||||
objtype=self.obj_name())
|
||||
if NovaObject.indirection_api:
|
||||
updates, result = NovaObject.indirection_api.object_action(
|
||||
if VersionedObject.indirection_api:
|
||||
updates, result = VersionedObject.indirection_api.object_action(
|
||||
ctxt, self, fn.__name__, args, kwargs)
|
||||
for key, value in updates.iteritems():
|
||||
if key in self.fields:
|
||||
field = self.fields[key]
|
||||
# NOTE(ndipanov): Since NovaObjectSerializer will have
|
||||
# NOTE(ndipanov): Since VersionedObjectSerializer will have
|
||||
# deserialized any object fields into objects already,
|
||||
# we do not try to deserialize them again here.
|
||||
if isinstance(value, NovaObject):
|
||||
if isinstance(value, VersionedObject):
|
||||
self[key] = value
|
||||
else:
|
||||
self[key] = field.from_primitive(self, key, value)
|
||||
@@ -212,7 +212,7 @@ def remotable(fn):
|
||||
return wrapper
|
||||
|
||||
|
||||
class NovaObject(object):
|
||||
class VersionedObject(object):
|
||||
"""Base class and object factory.
|
||||
|
||||
This forms the base of all objects that can be remoted or instantiated
|
||||
@@ -327,8 +327,8 @@ class NovaObject(object):
|
||||
self = cls()
|
||||
self._context = context
|
||||
self.VERSION = objver
|
||||
objdata = primitive['nova_object.data']
|
||||
changes = primitive.get('nova_object.changes', [])
|
||||
objdata = primitive['versioned_object.data']
|
||||
changes = primitive.get('versioned_object.changes', [])
|
||||
for name, field in self.fields.items():
|
||||
if name in objdata:
|
||||
setattr(self, name, field.from_primitive(self, name,
|
||||
@@ -339,14 +339,14 @@ class NovaObject(object):
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context=None):
|
||||
"""Object field-by-field hydration."""
|
||||
if primitive['nova_object.namespace'] != 'nova':
|
||||
if primitive['versioned_object.namespace'] != 'versionedobjects':
|
||||
# NOTE(danms): We don't do anything with this now, but it's
|
||||
# there for "the future"
|
||||
raise exception.UnsupportedObjectError(
|
||||
objtype='%s.%s' % (primitive['nova_object.namespace'],
|
||||
primitive['nova_object.name']))
|
||||
objname = primitive['nova_object.name']
|
||||
objver = primitive['nova_object.version']
|
||||
objtype='%s.%s' % (primitive['versioned_object.namespace'],
|
||||
primitive['versioned_object.name']))
|
||||
objname = primitive['versioned_object.name']
|
||||
objver = primitive['versioned_object.version']
|
||||
objclass = cls.obj_class_from_name(objname, objver)
|
||||
return objclass._obj_from_primitive(context, objver, primitive)
|
||||
|
||||
@@ -391,17 +391,18 @@ class NovaObject(object):
|
||||
obj = getattr(self, field)
|
||||
if not obj:
|
||||
return
|
||||
if isinstance(obj, NovaObject):
|
||||
if isinstance(obj, VersionedObject):
|
||||
obj.obj_make_compatible(
|
||||
primitive[field]['nova_object.data'],
|
||||
primitive[field]['versioned_object.data'],
|
||||
to_version)
|
||||
primitive[field]['nova_object.version'] = to_version
|
||||
primitive[field]['versioned_object.version'] = to_version
|
||||
elif isinstance(obj, list):
|
||||
for i, element in enumerate(obj):
|
||||
element.obj_make_compatible(
|
||||
primitive[field][i]['nova_object.data'],
|
||||
primitive[field][i]['versioned_object.data'],
|
||||
to_version)
|
||||
primitive[field][i]['nova_object.version'] = to_version
|
||||
primitive[field][i][
|
||||
'versioned_object.version'] = to_version
|
||||
|
||||
target_version = utils.convert_version_to_tuple(target_version)
|
||||
for index, versions in enumerate(self.obj_relationships[field]):
|
||||
@@ -448,8 +449,8 @@ class NovaObject(object):
|
||||
:param:primitive: The result of self.obj_to_primitive()
|
||||
:param:target_version: The version string requested by the recipient
|
||||
of the object
|
||||
:raises: nova.exception.UnsupportedObjectError if conversion
|
||||
is not possible for some reason
|
||||
:raises: oslo_versionedobjects.exception.UnsupportedObjectError
|
||||
if conversion is not possible for some reason
|
||||
"""
|
||||
for key, field in self.fields.items():
|
||||
if not isinstance(field, (fields.ObjectField,
|
||||
@@ -477,12 +478,12 @@ class NovaObject(object):
|
||||
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': target_version or self.VERSION,
|
||||
'nova_object.data': primitive}
|
||||
obj = {'versioned_object.name': self.obj_name(),
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': target_version or self.VERSION,
|
||||
'versioned_object.data': primitive}
|
||||
if self.obj_what_changed():
|
||||
obj['nova_object.changes'] = list(self.obj_what_changed())
|
||||
obj['versioned_object.changes'] = list(self.obj_what_changed())
|
||||
return obj
|
||||
|
||||
def obj_set_defaults(self, *attrs):
|
||||
@@ -520,7 +521,7 @@ class NovaObject(object):
|
||||
changes = set(self._changed_fields)
|
||||
for field in self.fields:
|
||||
if (self.obj_attr_is_set(field) and
|
||||
isinstance(getattr(self, field), NovaObject) and
|
||||
isinstance(getattr(self, field), VersionedObject) and
|
||||
getattr(self, field).obj_what_changed()):
|
||||
changes.add(field)
|
||||
return changes
|
||||
@@ -560,7 +561,7 @@ class NovaObject(object):
|
||||
return self.fields.keys() + self.obj_extra_fields
|
||||
|
||||
|
||||
class NovaObjectDictCompat(object):
|
||||
class VersionedObjectDictCompat(object):
|
||||
"""Mix-in to provide dictionary key access compat
|
||||
|
||||
If an object needs to support attribute access using
|
||||
@@ -631,7 +632,7 @@ class NovaObjectDictCompat(object):
|
||||
setattr(self, key, value)
|
||||
|
||||
|
||||
class NovaPersistentObject(object):
|
||||
class VersionedPersistentObject(object):
|
||||
"""Mixin class for Persistent objects.
|
||||
This adds the fields that we use in common for all persistent objects.
|
||||
"""
|
||||
@@ -675,7 +676,7 @@ class ObjectListBase(object):
|
||||
serialization of the list of objects automatically.
|
||||
"""
|
||||
fields = {
|
||||
'objects': fields.ListOfObjectsField('NovaObject'),
|
||||
'objects': fields.ListOfObjectsField('VersionedObject'),
|
||||
}
|
||||
|
||||
# This is a dictionary of my_version:child_version mappings so that
|
||||
@@ -702,7 +703,7 @@ class ObjectListBase(object):
|
||||
if isinstance(index, slice):
|
||||
new_obj = self.__class__()
|
||||
new_obj.objects = self.objects[index]
|
||||
# NOTE(danms): We must be mixed in with a NovaObject!
|
||||
# NOTE(danms): We must be mixed in with a VersionedObject!
|
||||
new_obj.obj_reset_changes()
|
||||
new_obj._context = self._context
|
||||
return new_obj
|
||||
@@ -728,9 +729,10 @@ class ObjectListBase(object):
|
||||
child_target_version = self.child_versions.get(target_version, '1.0')
|
||||
for index, item in enumerate(self.objects):
|
||||
self.objects[index].obj_make_compatible(
|
||||
primitives[index]['nova_object.data'],
|
||||
primitives[index]['versioned_object.data'],
|
||||
child_target_version)
|
||||
primitives[index]['nova_object.version'] = child_target_version
|
||||
primitives[index][
|
||||
'versioned_object.version'] = child_target_version
|
||||
|
||||
def obj_what_changed(self):
|
||||
changes = set(self._changed_fields)
|
||||
@@ -740,13 +742,13 @@ class ObjectListBase(object):
|
||||
return changes
|
||||
|
||||
|
||||
class NovaObjectSerializer(messaging.NoOpSerializer):
|
||||
"""A NovaObject-aware Serializer.
|
||||
class VersionedObjectSerializer(messaging.NoOpSerializer):
|
||||
"""A VersionedObject-aware Serializer.
|
||||
|
||||
This implements the Oslo Serializer interface and provides the
|
||||
ability to serialize and deserialize NovaObject entities. Any service
|
||||
that needs to accept or return NovaObjects as arguments or result values
|
||||
should pass this to its RPCClient and RPCServer objects.
|
||||
ability to serialize and deserialize VersionedObject entities. Any service
|
||||
that needs to accept or return VersionedObjects as arguments or result
|
||||
values should pass this to its RPCClient and RPCServer objects.
|
||||
"""
|
||||
|
||||
@property
|
||||
@@ -758,13 +760,14 @@ class NovaObjectSerializer(messaging.NoOpSerializer):
|
||||
|
||||
def _process_object(self, context, objprim):
|
||||
try:
|
||||
objinst = NovaObject.obj_from_primitive(objprim, context=context)
|
||||
objinst = VersionedObject.obj_from_primitive(
|
||||
objprim, context=context)
|
||||
except exception.IncompatibleObjectVersion as e:
|
||||
objver = objprim['nova_object.version']
|
||||
objver = objprim['versioned_object.version']
|
||||
if objver.count('.') == 2:
|
||||
# NOTE(danms): For our purposes, the .z part of the version
|
||||
# should be safe to accept without requiring a backport
|
||||
objprim['nova_object.version'] = \
|
||||
objprim['versioned_object.version'] = \
|
||||
'.'.join(objver.split('.')[:2])
|
||||
return self._process_object(context, objprim)
|
||||
objinst = self.conductor.object_backport(context, objprim,
|
||||
@@ -803,7 +806,7 @@ class NovaObjectSerializer(messaging.NoOpSerializer):
|
||||
return entity
|
||||
|
||||
def deserialize_entity(self, context, entity):
|
||||
if isinstance(entity, dict) and 'nova_object.name' in entity:
|
||||
if isinstance(entity, dict) and 'versioned_object.name' in entity:
|
||||
entity = self._process_object(context, entity)
|
||||
elif isinstance(entity, (tuple, list, set, dict)):
|
||||
entity = self._process_iterable(context, self.deserialize_entity,
|
||||
@@ -814,12 +817,12 @@ class NovaObjectSerializer(messaging.NoOpSerializer):
|
||||
def obj_to_primitive(obj):
|
||||
"""Recursively turn an object into a python primitive.
|
||||
|
||||
A NovaObject becomes a dict, and anything that implements ObjectListBase
|
||||
becomes a list.
|
||||
A VersionedObject becomes a dict, and anything that implements
|
||||
ObjectListBase becomes a list.
|
||||
"""
|
||||
if isinstance(obj, ObjectListBase):
|
||||
return [obj_to_primitive(x) for x in obj]
|
||||
elif isinstance(obj, NovaObject):
|
||||
elif isinstance(obj, VersionedObject):
|
||||
result = {}
|
||||
for key in obj.obj_fields:
|
||||
if obj.obj_attr_is_set(key) or key in obj.obj_extra_fields:
|
||||
@@ -841,7 +844,7 @@ def obj_make_list(context, list_obj, item_cls, db_list, **extra_args):
|
||||
|
||||
:param:context: Request context
|
||||
:param:list_obj: An ObjectListBase object
|
||||
:param:item_cls: The NovaObject class of the objects within the list
|
||||
:param:item_cls: The VersionedObject class of the objects within the list
|
||||
:param:db_list: The list of primitives to convert to objects
|
||||
:param:extra_args: Extra arguments to pass to _from_db_object()
|
||||
:returns: list_obj
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Nova base exception handling.
|
||||
"""VersionedObjects base exception handling.
|
||||
|
||||
Includes decorator for re-raising Nova-type exceptions.
|
||||
Includes decorator for re-raising VersionedObjects-type exceptions.
|
||||
|
||||
SHOULD include dedicated exception logging.
|
||||
|
||||
@@ -91,8 +91,8 @@ def wrap_exception(notifier=None, get_notifier=None):
|
||||
return inner
|
||||
|
||||
|
||||
class NovaException(Exception):
|
||||
"""Base Nova Exception
|
||||
class VersionedObjectsException(Exception):
|
||||
"""Base VersionedObjects Exception
|
||||
|
||||
To correctly use this class, inherit from it and define
|
||||
a 'msg_fmt' property. That msg_fmt will get printf'd
|
||||
@@ -131,33 +131,34 @@ class NovaException(Exception):
|
||||
# at least get the core message out if something happened
|
||||
message = self.msg_fmt
|
||||
|
||||
super(NovaException, self).__init__(message)
|
||||
super(VersionedObjectsException, self).__init__(message)
|
||||
|
||||
def format_message(self):
|
||||
# NOTE(mrodden): use the first argument to the python Exception object
|
||||
# which should be our full NovaException message, (see __init__)
|
||||
# which should be our full VersionedObjectsException message,
|
||||
# (see __init__)
|
||||
return self.args[0]
|
||||
|
||||
|
||||
class ObjectActionError(NovaException):
|
||||
class ObjectActionError(VersionedObjectsException):
|
||||
msg_fmt = _('Object action %(action)s failed because: %(reason)s')
|
||||
|
||||
|
||||
class ObjectFieldInvalid(NovaException):
|
||||
class ObjectFieldInvalid(VersionedObjectsException):
|
||||
msg_fmt = _('Field %(field)s of %(objname)s is not an instance of Field')
|
||||
|
||||
|
||||
class OrphanedObjectError(NovaException):
|
||||
class OrphanedObjectError(VersionedObjectsException):
|
||||
msg_fmt = _('Cannot call %(method)s on orphaned %(objtype)s object')
|
||||
|
||||
|
||||
class IncompatibleObjectVersion(NovaException):
|
||||
class IncompatibleObjectVersion(VersionedObjectsException):
|
||||
msg_fmt = _('Version %(objver)s of %(objname)s is not supported')
|
||||
|
||||
|
||||
class ReadOnlyFieldError(NovaException):
|
||||
class ReadOnlyFieldError(VersionedObjectsException):
|
||||
msg_fmt = _('Cannot modify readonly field %(field)s')
|
||||
|
||||
|
||||
class UnsupportedObjectError(NovaException):
|
||||
class UnsupportedObjectError(VersionedObjectsException):
|
||||
msg_fmt = _('Unsupported object type %(objtype)s')
|
||||
|
||||
109
oslo_versionedobjects/fields.py
Normal file → Executable file
109
oslo_versionedobjects/fields.py
Normal file → Executable file
@@ -16,7 +16,6 @@ import abc
|
||||
import datetime
|
||||
|
||||
import iso8601
|
||||
import netaddr
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
|
||||
@@ -54,7 +53,7 @@ class AbstractFieldType(object):
|
||||
This method should convert the value given into the designated type,
|
||||
or throw an exception if this is not possible.
|
||||
|
||||
:param:obj: The NovaObject on which an attribute is being set
|
||||
:param:obj: The VersionedObject on which an attribute is being set
|
||||
:param:attr: The name of the attribute being set
|
||||
:param:value: The value being set
|
||||
:returns: A properly-typed value
|
||||
@@ -68,7 +67,7 @@ class AbstractFieldType(object):
|
||||
This method should deserialize a value from the form given by
|
||||
to_primitive() to the designated type.
|
||||
|
||||
:param:obj: The NovaObject on which the value is to be set
|
||||
:param:obj: The VersionedObject on which the value is to be set
|
||||
:param:attr: The name of the attribute which will hold the value
|
||||
:param:value: The serialized form of the value
|
||||
:returns: The natural form of the value
|
||||
@@ -82,7 +81,7 @@ class AbstractFieldType(object):
|
||||
This method should serialize a value to the form expected by
|
||||
from_primitive().
|
||||
|
||||
:param:obj: The NovaObject on which the value is set
|
||||
:param:obj: The VersionedObject on which the value is set
|
||||
:param:attr: The name of the attribute holding the value
|
||||
:param:value: The natural form of the value
|
||||
:returns: The serialized form of the value
|
||||
@@ -304,76 +303,6 @@ class DateTime(FieldType):
|
||||
return timeutils.isotime(value)
|
||||
|
||||
|
||||
class IPAddress(FieldType):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
try:
|
||||
return netaddr.IPAddress(value)
|
||||
except netaddr.AddrFormatError as e:
|
||||
raise ValueError(six.text_type(e))
|
||||
|
||||
def from_primitive(self, obj, attr, value):
|
||||
return self.coerce(obj, attr, value)
|
||||
|
||||
@staticmethod
|
||||
def to_primitive(obj, attr, value):
|
||||
return str(value)
|
||||
|
||||
|
||||
class IPV4Address(IPAddress):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
result = IPAddress.coerce(obj, attr, value)
|
||||
if result.version != 4:
|
||||
raise ValueError(_('Network "%s" is not valid') % value)
|
||||
return result
|
||||
|
||||
|
||||
class IPV6Address(IPAddress):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
result = IPAddress.coerce(obj, attr, value)
|
||||
if result.version != 6:
|
||||
raise ValueError(_('Network "%s" is not valid') % value)
|
||||
return result
|
||||
|
||||
|
||||
class IPV4AndV6Address(IPAddress):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
result = IPAddress.coerce(obj, attr, value)
|
||||
if result.version != 4 and result.version != 6:
|
||||
raise ValueError(_('Network "%s" is not valid') % value)
|
||||
return result
|
||||
|
||||
|
||||
class IPNetwork(IPAddress):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
try:
|
||||
return netaddr.IPNetwork(value)
|
||||
except netaddr.AddrFormatError as e:
|
||||
raise ValueError(six.text_type(e))
|
||||
|
||||
|
||||
class IPV4Network(IPNetwork):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
try:
|
||||
return netaddr.IPNetwork(value, version=4)
|
||||
except netaddr.AddrFormatError as e:
|
||||
raise ValueError(six.text_type(e))
|
||||
|
||||
|
||||
class IPV6Network(IPNetwork):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
try:
|
||||
return netaddr.IPNetwork(value, version=6)
|
||||
except netaddr.AddrFormatError as e:
|
||||
raise ValueError(six.text_type(e))
|
||||
|
||||
|
||||
class CompoundFieldType(FieldType):
|
||||
def __init__(self, element_type, **field_args):
|
||||
self._element_type = Field(element_type, **field_args)
|
||||
@@ -517,9 +446,9 @@ class Object(FieldType):
|
||||
from oslo_versionedobjects import base as obj_base
|
||||
# NOTE (ndipanov): If they already got hydrated by the serializer, just
|
||||
# pass them back unchanged
|
||||
if isinstance(value, obj_base.NovaObject):
|
||||
if isinstance(value, obj_base.VersionedObject):
|
||||
return value
|
||||
return obj_base.NovaObject.obj_from_primitive(value, obj._context)
|
||||
return obj_base.VersionedObject.obj_from_primitive(value, obj._context)
|
||||
|
||||
def describe(self):
|
||||
return "Object<%s>" % self._obj_name
|
||||
@@ -568,34 +497,6 @@ class DateTimeField(AutoTypedField):
|
||||
AUTO_TYPE = DateTime()
|
||||
|
||||
|
||||
class IPAddressField(AutoTypedField):
|
||||
AUTO_TYPE = IPAddress()
|
||||
|
||||
|
||||
class IPV4AddressField(AutoTypedField):
|
||||
AUTO_TYPE = IPV4Address()
|
||||
|
||||
|
||||
class IPV6AddressField(AutoTypedField):
|
||||
AUTO_TYPE = IPV6Address()
|
||||
|
||||
|
||||
class IPV4AndV6AddressField(AutoTypedField):
|
||||
AUTO_TYPE = IPV4AndV6Address()
|
||||
|
||||
|
||||
class IPNetworkField(AutoTypedField):
|
||||
AUTO_TYPE = IPNetwork()
|
||||
|
||||
|
||||
class IPV4NetworkField(AutoTypedField):
|
||||
AUTO_TYPE = IPV4Network()
|
||||
|
||||
|
||||
class IPV6NetworkField(AutoTypedField):
|
||||
AUTO_TYPE = IPV6Network()
|
||||
|
||||
|
||||
class DictOfStringsField(AutoTypedField):
|
||||
AUTO_TYPE = Dict(String())
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ CONF = cfg.CONF
|
||||
# CONF.set_override('use_stderr', False)
|
||||
|
||||
logging.register_options(CONF)
|
||||
logging.setup(CONF, 'nova')
|
||||
logging.setup(CONF, 'versionedobjects')
|
||||
|
||||
# NOTE(comstud): Make sure we have all of the objects loaded. We do this
|
||||
# at module import time, because we may be using mock decorators in our
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Fixtures for Nova tests."""
|
||||
"""Fixtures for VersionedObject tests."""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import gettext
|
||||
@@ -44,7 +44,7 @@ class ServiceFixture(fixtures.Fixture):
|
||||
name = name
|
||||
host = host or uuid.uuid4().hex
|
||||
kwargs.setdefault('host', host)
|
||||
kwargs.setdefault('binary', 'nova-%s' % name)
|
||||
kwargs.setdefault('binary', 'versionedobjects-%s' % name)
|
||||
self.kwargs = kwargs
|
||||
|
||||
def setUp(self):
|
||||
|
||||
90
oslo_versionedobjects/tests/test_fields.py
Normal file → Executable file
90
oslo_versionedobjects/tests/test_fields.py
Normal file → Executable file
@@ -15,7 +15,6 @@
|
||||
import datetime
|
||||
|
||||
import iso8601
|
||||
import netaddr
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from oslo_versionedobjects import base as obj_base
|
||||
@@ -133,49 +132,6 @@ class TestDateTime(TestField):
|
||||
tzinfo=iso8601.iso8601.Utc())))
|
||||
|
||||
|
||||
class TestIPAddress(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPAddress, self).setUp()
|
||||
self.field = fields.IPAddressField()
|
||||
self.coerce_good_values = [('1.2.3.4', netaddr.IPAddress('1.2.3.4')),
|
||||
('::1', netaddr.IPAddress('::1')),
|
||||
(netaddr.IPAddress('::1'),
|
||||
netaddr.IPAddress('::1'))]
|
||||
self.coerce_bad_values = ['1-2', 'foo']
|
||||
self.to_primitive_values = [(netaddr.IPAddress('1.2.3.4'), '1.2.3.4'),
|
||||
(netaddr.IPAddress('::1'), '::1')]
|
||||
self.from_primitive_values = [('1.2.3.4',
|
||||
netaddr.IPAddress('1.2.3.4')),
|
||||
('::1',
|
||||
netaddr.IPAddress('::1'))]
|
||||
|
||||
|
||||
class TestIPAddressV4(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPAddressV4, self).setUp()
|
||||
self.field = fields.IPV4AddressField()
|
||||
self.coerce_good_values = [('1.2.3.4', netaddr.IPAddress('1.2.3.4')),
|
||||
(netaddr.IPAddress('1.2.3.4'),
|
||||
netaddr.IPAddress('1.2.3.4'))]
|
||||
self.coerce_bad_values = ['1-2', 'foo', '::1']
|
||||
self.to_primitive_values = [(netaddr.IPAddress('1.2.3.4'), '1.2.3.4')]
|
||||
self.from_primitive_values = [('1.2.3.4',
|
||||
netaddr.IPAddress('1.2.3.4'))]
|
||||
|
||||
|
||||
class TestIPAddressV6(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPAddressV6, self).setUp()
|
||||
self.field = fields.IPV6AddressField()
|
||||
self.coerce_good_values = [('::1', netaddr.IPAddress('::1')),
|
||||
(netaddr.IPAddress('::1'),
|
||||
netaddr.IPAddress('::1'))]
|
||||
self.coerce_bad_values = ['1.2', 'foo', '1.2.3.4']
|
||||
self.to_primitive_values = [(netaddr.IPAddress('::1'), '::1')]
|
||||
self.from_primitive_values = [('::1',
|
||||
netaddr.IPAddress('::1'))]
|
||||
|
||||
|
||||
class TestDict(TestField):
|
||||
def setUp(self):
|
||||
super(TestDict, self).setUp()
|
||||
@@ -332,7 +288,7 @@ class TestObject(TestField):
|
||||
super(TestObject, self).setUp()
|
||||
|
||||
@obj_base.VersionedObjectRegistry.register
|
||||
class TestableObject(obj_base.NovaObject):
|
||||
class TestableObject(obj_base.VersionedObject):
|
||||
fields = {
|
||||
'uuid': fields.StringField(),
|
||||
}
|
||||
@@ -343,7 +299,7 @@ class TestObject(TestField):
|
||||
# just want to make sure the right type of object is re-created
|
||||
return value.__class__.__name__ == TestableObject.__name__
|
||||
|
||||
class OtherTestableObject(obj_base.NovaObject):
|
||||
class OtherTestableObject(obj_base.VersionedObject):
|
||||
pass
|
||||
|
||||
test_inst = TestableObject()
|
||||
@@ -360,45 +316,3 @@ class TestObject(TestField):
|
||||
obj = self._test_cls(uuid='fake-uuid')
|
||||
self.assertEqual('TestableObject(fake-uuid)',
|
||||
self.field.stringify(obj))
|
||||
|
||||
|
||||
class TestIPNetwork(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPNetwork, self).setUp()
|
||||
self.field = fields.Field(fields.IPNetwork())
|
||||
good = ['192.168.1.0/24', '0.0.0.0/0', '::1/128', '::1/64', '::1/0']
|
||||
self.coerce_good_values = [(x, netaddr.IPNetwork(x)) for x in good]
|
||||
self.coerce_bad_values = ['192.168.0.0/f', '192.168.0.0/foo',
|
||||
'::1/129', '192.168.0.0/-1']
|
||||
self.to_primitive_values = [(netaddr.IPNetwork(x), x)
|
||||
for x in good]
|
||||
self.from_primitive_values = [(x, netaddr.IPNetwork(x))
|
||||
for x in good]
|
||||
|
||||
|
||||
class TestIPV4Network(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPV4Network, self).setUp()
|
||||
self.field = fields.Field(fields.IPV4Network())
|
||||
good = ['192.168.1.0/24', '0.0.0.0/0']
|
||||
self.coerce_good_values = [(x, netaddr.IPNetwork(x)) for x in good]
|
||||
self.coerce_bad_values = ['192.168.0.0/f', '192.168.0.0/foo',
|
||||
'::1/129', '192.168.0.0/-1']
|
||||
self.to_primitive_values = [(netaddr.IPNetwork(x), x)
|
||||
for x in good]
|
||||
self.from_primitive_values = [(x, netaddr.IPNetwork(x))
|
||||
for x in good]
|
||||
|
||||
|
||||
class TestIPV6Network(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPV6Network, self).setUp()
|
||||
self.field = fields.Field(fields.IPV6Network())
|
||||
good = ['::1/128', '::1/64', '::1/0']
|
||||
self.coerce_good_values = [(x, netaddr.IPNetwork(x)) for x in good]
|
||||
self.coerce_bad_values = ['192.168.0.0/f', '192.168.0.0/foo',
|
||||
'::1/129', '192.168.0.0/-1']
|
||||
self.to_primitive_values = [(netaddr.IPNetwork(x), x)
|
||||
for x in good]
|
||||
self.from_primitive_values = [(x, netaddr.IPNetwork(x))
|
||||
for x in good]
|
||||
|
||||
215
oslo_versionedobjects/tests/test_objects.py
Normal file → Executable file
215
oslo_versionedobjects/tests/test_objects.py
Normal file → Executable file
@@ -27,13 +27,10 @@ from oslo_serialization import jsonutils
|
||||
from oslo_utils import timeutils
|
||||
from testtools import matchers
|
||||
|
||||
# from nova.conductor import rpcapi as conductor_rpcapi
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import exception
|
||||
from oslo_versionedobjects import fields
|
||||
# from nova import rpc
|
||||
from oslo_versionedobjects import test
|
||||
# from nova.tests.unit import fake_notifier
|
||||
from oslo_versionedobjects import utils
|
||||
|
||||
|
||||
@@ -49,14 +46,14 @@ def is_test_object(cls):
|
||||
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyOwnedObject(base.NovaPersistentObject, base.NovaObject):
|
||||
class MyOwnedObject(base.VersionedPersistentObject, base.VersionedObject):
|
||||
VERSION = '1.0'
|
||||
fields = {'baz': fields.Field(fields.Integer())}
|
||||
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyObj(base.NovaPersistentObject, base.NovaObject,
|
||||
base.NovaObjectDictCompat):
|
||||
class MyObj(base.VersionedPersistentObject, base.VersionedObject,
|
||||
base.VersionedObjectDictCompat):
|
||||
VERSION = '1.6'
|
||||
fields = {'foo': fields.Field(fields.Integer(), default=1),
|
||||
'bar': fields.Field(fields.String()),
|
||||
@@ -134,7 +131,7 @@ class MyObjDiffVers(MyObj):
|
||||
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyObj2(base.NovaObject):
|
||||
class MyObj2(base.VersionedObject):
|
||||
@classmethod
|
||||
def obj_name(cls):
|
||||
return 'MyObj'
|
||||
@@ -210,14 +207,14 @@ class TestRegistry(test.TestCase):
|
||||
def test_field_checking(self):
|
||||
def create_class(field):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class TestField(base.NovaObject):
|
||||
class TestField(base.VersionedObject):
|
||||
VERSION = '1.5'
|
||||
fields = {'foo': field()}
|
||||
return TestField
|
||||
|
||||
create_class(fields.IPV4AndV6AddressField)
|
||||
create_class(fields.DateTimeField)
|
||||
self.assertRaises(exception.ObjectFieldInvalid,
|
||||
create_class, fields.IPV4AndV6Address)
|
||||
create_class, fields.DateTime)
|
||||
self.assertRaises(exception.ObjectFieldInvalid,
|
||||
create_class, int)
|
||||
|
||||
@@ -226,7 +223,7 @@ class TestObjToPrimitive(test.TestCase):
|
||||
|
||||
def test_obj_to_primitive_list(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyObjElement(base.NovaObject):
|
||||
class MyObjElement(base.VersionedObject):
|
||||
fields = {'foo': fields.IntegerField()}
|
||||
|
||||
def __init__(self, foo):
|
||||
@@ -234,7 +231,7 @@ class TestObjToPrimitive(test.TestCase):
|
||||
self.foo = foo
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyList(base.ObjectListBase, base.NovaObject):
|
||||
class MyList(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('MyObjElement')}
|
||||
|
||||
mylist = MyList()
|
||||
@@ -249,7 +246,7 @@ class TestObjToPrimitive(test.TestCase):
|
||||
|
||||
def test_obj_to_primitive_recursive(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyList(base.ObjectListBase, base.NovaObject):
|
||||
class MyList(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('MyObj')}
|
||||
|
||||
mylist = MyList(objects=[MyObj(), MyObj()])
|
||||
@@ -258,22 +255,12 @@ class TestObjToPrimitive(test.TestCase):
|
||||
self.assertEqual([{'foo': 0}, {'foo': 1}],
|
||||
base.obj_to_primitive(mylist))
|
||||
|
||||
def test_obj_to_primitive_with_ip_addr(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class TestObject(base.NovaObject):
|
||||
fields = {'addr': fields.IPAddressField(),
|
||||
'cidr': fields.IPNetworkField()}
|
||||
|
||||
obj = TestObject(addr='1.2.3.4', cidr='1.1.1.1/16')
|
||||
self.assertEqual({'addr': '1.2.3.4', 'cidr': '1.1.1.1/16'},
|
||||
base.obj_to_primitive(obj))
|
||||
|
||||
|
||||
class TestObjMakeList(test.TestCase):
|
||||
|
||||
def test_obj_make_list(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyList(base.ObjectListBase, base.NovaObject):
|
||||
class MyList(base.ObjectListBase, base.VersionedObject):
|
||||
pass
|
||||
|
||||
db_objs = [{'foo': 1, 'bar': 'baz', 'missing': 'banana'},
|
||||
@@ -290,13 +277,13 @@ class TestObjMakeList(test.TestCase):
|
||||
|
||||
def compare_obj(test, obj, db_obj, subs=None, allow_missing=None,
|
||||
comparators=None):
|
||||
"""Compare a NovaObject and a dict-like database object.
|
||||
"""Compare a VersionedObject and a dict-like database object.
|
||||
|
||||
This automatically converts TZ-aware datetimes and iterates over
|
||||
the fields of the object.
|
||||
|
||||
:param:test: The TestCase doing the comparison
|
||||
:param:obj: The NovaObject to examine
|
||||
:param:obj: The VersionedObject to examine
|
||||
:param:db_obj: The dict-like database object to use as reference
|
||||
:param:subs: A dict of objkey=dbkey field substitutions
|
||||
:param:allow_missing: A list of fields that may not be in db_obj
|
||||
@@ -370,7 +357,7 @@ class _LocalTest(_BaseTestCase):
|
||||
def setUp(self):
|
||||
super(_LocalTest, self).setUp()
|
||||
# Just in case
|
||||
base.NovaObject.indirection_api = None
|
||||
base.VersionedObject.indirection_api = None
|
||||
|
||||
def assertRemotes(self):
|
||||
self.assertEqual(self.remote_object_calls, [])
|
||||
@@ -380,10 +367,10 @@ class _LocalTest(_BaseTestCase):
|
||||
def things_temporarily_local():
|
||||
# Temporarily go non-remote so the conductor handles
|
||||
# this request directly
|
||||
_api = base.NovaObject.indirection_api
|
||||
base.NovaObject.indirection_api = None
|
||||
_api = base.VersionedObject.indirection_api
|
||||
base.VersionedObject.indirection_api = None
|
||||
yield
|
||||
base.NovaObject.indirection_api = _api
|
||||
base.VersionedObject.indirection_api = _api
|
||||
|
||||
|
||||
class _RemoteTest(_BaseTestCase):
|
||||
@@ -402,8 +389,9 @@ class _RemoteTest(_BaseTestCase):
|
||||
kwargs.get('objmethod')))
|
||||
with things_temporarily_local():
|
||||
result = orig_object_class_action(*args, **kwargs)
|
||||
return (base.NovaObject.obj_from_primitive(result, context=args[0])
|
||||
if isinstance(result, base.NovaObject) else result)
|
||||
return (base.VersionedObject.obj_from_primitive(result,
|
||||
context=args[0])
|
||||
if isinstance(result, base.VersionedObject) else result)
|
||||
self.stubs.Set(self.conductor_service.manager, 'object_class_action',
|
||||
fake_object_class_action)
|
||||
|
||||
@@ -418,7 +406,7 @@ class _RemoteTest(_BaseTestCase):
|
||||
|
||||
# Things are remoted by default in this session
|
||||
# FIXME(dhellmann): See work items in adopt-oslo-versionedobjects.
|
||||
# base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
|
||||
# base.VersionedObject.indirection_api =conductor_rpcapi.ConductorAPI()
|
||||
|
||||
# To make sure local and remote contexts match
|
||||
# FIXME(dhellmann): See work items in adopt-oslo-versionedobjects.
|
||||
@@ -449,17 +437,17 @@ class _TestObject(object):
|
||||
# self.assertEqual('1.6', objects.MyObj.VERSION)
|
||||
|
||||
def test_hydration_type_error(self):
|
||||
primitive = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.5',
|
||||
'nova_object.data': {'foo': 'a'}}
|
||||
primitive = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.5',
|
||||
'versioned_object.data': {'foo': 'a'}}
|
||||
self.assertRaises(ValueError, MyObj.obj_from_primitive, primitive)
|
||||
|
||||
def test_hydration(self):
|
||||
primitive = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.5',
|
||||
'nova_object.data': {'foo': 1}}
|
||||
primitive = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.5',
|
||||
'versioned_object.data': {'foo': 1}}
|
||||
real_method = MyObj._obj_from_primitive
|
||||
|
||||
def _obj_from_primitive(*args):
|
||||
@@ -472,27 +460,27 @@ class _TestObject(object):
|
||||
self.assertEqual(obj.foo, 1)
|
||||
|
||||
def test_hydration_version_different(self):
|
||||
primitive = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.2',
|
||||
'nova_object.data': {'foo': 1}}
|
||||
primitive = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.2',
|
||||
'versioned_object.data': {'foo': 1}}
|
||||
obj = MyObj.obj_from_primitive(primitive)
|
||||
self.assertEqual(obj.foo, 1)
|
||||
self.assertEqual('1.2', obj.VERSION)
|
||||
|
||||
def test_hydration_bad_ns(self):
|
||||
primitive = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'foo',
|
||||
'nova_object.version': '1.5',
|
||||
'nova_object.data': {'foo': 1}}
|
||||
primitive = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'foo',
|
||||
'versioned_object.version': '1.5',
|
||||
'versioned_object.data': {'foo': 1}}
|
||||
self.assertRaises(exception.UnsupportedObjectError,
|
||||
MyObj.obj_from_primitive, primitive)
|
||||
|
||||
def test_hydration_additional_unexpected_stuff(self):
|
||||
primitive = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.5.1',
|
||||
'nova_object.data': {
|
||||
primitive = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.5.1',
|
||||
'versioned_object.data': {
|
||||
'foo': 1,
|
||||
'unexpected_thing': 'foobar'}}
|
||||
obj = MyObj.obj_from_primitive(primitive)
|
||||
@@ -506,10 +494,10 @@ class _TestObject(object):
|
||||
self.assertEqual('1.5.1', obj.VERSION)
|
||||
|
||||
def test_dehydration(self):
|
||||
expected = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.6',
|
||||
'nova_object.data': {'foo': 1}}
|
||||
expected = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.6',
|
||||
'versioned_object.data': {'foo': 1}}
|
||||
obj = MyObj(foo=1)
|
||||
obj.obj_reset_changes()
|
||||
self.assertEqual(obj.obj_to_primitive(), expected)
|
||||
@@ -539,7 +527,7 @@ class _TestObject(object):
|
||||
|
||||
def test_load_in_base(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Foo(base.NovaObject):
|
||||
class Foo(base.VersionedObject):
|
||||
fields = {'foobar': fields.Field(fields.Integer())}
|
||||
obj = Foo()
|
||||
with self.assertRaisesRegex(NotImplementedError, ".*foobar.*"):
|
||||
@@ -549,40 +537,41 @@ class _TestObject(object):
|
||||
obj = MyObj(foo=1)
|
||||
obj.obj_reset_changes()
|
||||
self.assertEqual(obj.bar, 'loaded!')
|
||||
expected = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.6',
|
||||
'nova_object.changes': ['bar'],
|
||||
'nova_object.data': {'foo': 1,
|
||||
'bar': 'loaded!'}}
|
||||
expected = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.6',
|
||||
'versioned_object.changes': ['bar'],
|
||||
'versioned_object.data': {'foo': 1,
|
||||
'bar': 'loaded!'}}
|
||||
self.assertEqual(obj.obj_to_primitive(), expected)
|
||||
|
||||
def test_changes_in_primitive(self):
|
||||
obj = MyObj(foo=123)
|
||||
self.assertEqual(obj.obj_what_changed(), set(['foo']))
|
||||
primitive = obj.obj_to_primitive()
|
||||
self.assertIn('nova_object.changes', primitive)
|
||||
self.assertIn('versioned_object.changes', primitive)
|
||||
obj2 = MyObj.obj_from_primitive(primitive)
|
||||
self.assertEqual(obj2.obj_what_changed(), set(['foo']))
|
||||
obj2.obj_reset_changes()
|
||||
self.assertEqual(obj2.obj_what_changed(), set())
|
||||
|
||||
def test_obj_class_from_name(self):
|
||||
obj = base.NovaObject.obj_class_from_name('MyObj', '1.5')
|
||||
obj = base.VersionedObject.obj_class_from_name('MyObj', '1.5')
|
||||
self.assertEqual('1.5', obj.VERSION)
|
||||
|
||||
def test_obj_class_from_name_latest_compatible(self):
|
||||
obj = base.NovaObject.obj_class_from_name('MyObj', '1.1')
|
||||
obj = base.VersionedObject.obj_class_from_name('MyObj', '1.1')
|
||||
self.assertEqual('1.6', obj.VERSION)
|
||||
|
||||
def test_unknown_objtype(self):
|
||||
self.assertRaises(exception.UnsupportedObjectError,
|
||||
base.NovaObject.obj_class_from_name, 'foo', '1.0')
|
||||
base.VersionedObject.obj_class_from_name,
|
||||
'foo', '1.0')
|
||||
|
||||
def test_obj_class_from_name_supported_version(self):
|
||||
error = None
|
||||
try:
|
||||
base.NovaObject.obj_class_from_name('MyObj', '1.25')
|
||||
base.VersionedObject.obj_class_from_name('MyObj', '1.25')
|
||||
except exception.IncompatibleObjectVersion as error:
|
||||
pass
|
||||
|
||||
@@ -637,7 +626,7 @@ class _TestObject(object):
|
||||
|
||||
def test_changed_with_sub_object(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class ParentObject(base.NovaObject):
|
||||
class ParentObject(base.VersionedObject):
|
||||
fields = {'foo': fields.IntegerField(),
|
||||
'bar': fields.ObjectField('MyObj'),
|
||||
}
|
||||
@@ -672,13 +661,13 @@ class _TestObject(object):
|
||||
obj = MyObj(created_at=dt, updated_at=dt, deleted_at=None,
|
||||
deleted=False)
|
||||
expected = {
|
||||
'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.6',
|
||||
'nova_object.changes': [
|
||||
'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.6',
|
||||
'versioned_object.changes': [
|
||||
'deleted', 'created_at', 'deleted_at', 'updated_at',
|
||||
],
|
||||
'nova_object.data': {
|
||||
'versioned_object.data': {
|
||||
'created_at': timeutils.isotime(dt),
|
||||
'updated_at': timeutils.isotime(dt),
|
||||
'deleted_at': None,
|
||||
@@ -718,7 +707,7 @@ class _TestObject(object):
|
||||
self.assertRaises(AttributeError, obj.get, 'nothing', 3)
|
||||
|
||||
def test_object_inheritance(self):
|
||||
base_fields = base.NovaPersistentObject.fields.keys()
|
||||
base_fields = base.VersionedPersistentObject.fields.keys()
|
||||
myobj_fields = (['foo', 'bar', 'missing',
|
||||
'readonly', 'rel_object', 'rel_objects'] +
|
||||
base_fields)
|
||||
@@ -764,7 +753,7 @@ class _TestObject(object):
|
||||
self.assertEqual({}, obj.obj_get_changes())
|
||||
|
||||
def test_obj_fields(self):
|
||||
class TestObj(base.NovaObject):
|
||||
class TestObj(base.VersionedObject):
|
||||
fields = {'foo': fields.Field(fields.Integer())}
|
||||
obj_extra_fields = ['bar']
|
||||
|
||||
@@ -800,7 +789,7 @@ class _TestObject(object):
|
||||
obj.obj_relationships = {
|
||||
'rel_object': [('1.5', '1.1'), ('1.7', '1.2')],
|
||||
}
|
||||
primitive = obj.obj_to_primitive()['nova_object.data']
|
||||
primitive = obj.obj_to_primitive()['versioned_object.data']
|
||||
with mock.patch.object(subobj, 'obj_make_compatible') as mock_compat:
|
||||
obj._obj_make_obj_compatible(copy.copy(primitive), '1.8',
|
||||
'rel_object')
|
||||
@@ -810,25 +799,25 @@ class _TestObject(object):
|
||||
obj._obj_make_obj_compatible(copy.copy(primitive),
|
||||
'1.7', 'rel_object')
|
||||
mock_compat.assert_called_once_with(
|
||||
primitive['rel_object']['nova_object.data'], '1.2')
|
||||
self.assertEqual('1.2',
|
||||
primitive['rel_object']['nova_object.version'])
|
||||
primitive['rel_object']['versioned_object.data'], '1.2')
|
||||
self.assertEqual(
|
||||
'1.2', primitive['rel_object']['versioned_object.version'])
|
||||
|
||||
with mock.patch.object(subobj, 'obj_make_compatible') as mock_compat:
|
||||
obj._obj_make_obj_compatible(copy.copy(primitive),
|
||||
'1.6', 'rel_object')
|
||||
mock_compat.assert_called_once_with(
|
||||
primitive['rel_object']['nova_object.data'], '1.1')
|
||||
self.assertEqual('1.1',
|
||||
primitive['rel_object']['nova_object.version'])
|
||||
primitive['rel_object']['versioned_object.data'], '1.1')
|
||||
self.assertEqual(
|
||||
'1.1', primitive['rel_object']['versioned_object.version'])
|
||||
|
||||
with mock.patch.object(subobj, 'obj_make_compatible') as mock_compat:
|
||||
obj._obj_make_obj_compatible(copy.copy(primitive), '1.5',
|
||||
'rel_object')
|
||||
mock_compat.assert_called_once_with(
|
||||
primitive['rel_object']['nova_object.data'], '1.1')
|
||||
self.assertEqual('1.1',
|
||||
primitive['rel_object']['nova_object.version'])
|
||||
primitive['rel_object']['versioned_object.data'], '1.1')
|
||||
self.assertEqual(
|
||||
'1.1', primitive['rel_object']['versioned_object.version'])
|
||||
|
||||
with mock.patch.object(subobj, 'obj_make_compatible') as mock_compat:
|
||||
_prim = copy.copy(primitive)
|
||||
@@ -924,14 +913,14 @@ class TestRemoteObject(_RemoteTest, _TestObject):
|
||||
class TestObjectListBase(test.TestCase):
|
||||
def test_list_like_operations(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class MyElement(base.NovaObject):
|
||||
class MyElement(base.VersionedObject):
|
||||
fields = {'foo': fields.IntegerField()}
|
||||
|
||||
def __init__(self, foo):
|
||||
super(MyElement, self).__init__()
|
||||
self.foo = foo
|
||||
|
||||
class Foo(base.ObjectListBase, base.NovaObject):
|
||||
class Foo(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('MyElement')}
|
||||
|
||||
objlist = Foo(context='foo',
|
||||
@@ -950,11 +939,11 @@ class TestObjectListBase(test.TestCase):
|
||||
|
||||
def test_serialization(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Foo(base.ObjectListBase, base.NovaObject):
|
||||
class Foo(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('Bar')}
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Bar(base.NovaObject):
|
||||
class Bar(base.VersionedObject):
|
||||
fields = {'foo': fields.Field(fields.String())}
|
||||
|
||||
obj = Foo(objects=[])
|
||||
@@ -962,7 +951,7 @@ class TestObjectListBase(test.TestCase):
|
||||
bar = Bar(foo=i)
|
||||
obj.objects.append(bar)
|
||||
|
||||
obj2 = base.NovaObject.obj_from_primitive(obj.obj_to_primitive())
|
||||
obj2 = base.VersionedObject.obj_from_primitive(obj.obj_to_primitive())
|
||||
self.assertFalse(obj is obj2)
|
||||
self.assertEqual([x.foo for x in obj],
|
||||
[y.foo for y in obj2])
|
||||
@@ -995,11 +984,11 @@ class TestObjectListBase(test.TestCase):
|
||||
|
||||
def test_list_changes(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Foo(base.ObjectListBase, base.NovaObject):
|
||||
class Foo(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('Bar')}
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Bar(base.NovaObject):
|
||||
class Bar(base.VersionedObject):
|
||||
fields = {'foo': fields.StringField()}
|
||||
|
||||
obj = Foo(objects=[])
|
||||
@@ -1014,10 +1003,10 @@ class TestObjectListBase(test.TestCase):
|
||||
self.assertEqual(set(), obj.obj_what_changed())
|
||||
|
||||
def test_initialize_objects(self):
|
||||
class Foo(base.ObjectListBase, base.NovaObject):
|
||||
class Foo(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('Bar')}
|
||||
|
||||
class Bar(base.NovaObject):
|
||||
class Bar(base.VersionedObject):
|
||||
fields = {'foo': fields.StringField()}
|
||||
|
||||
obj = Foo()
|
||||
@@ -1026,11 +1015,11 @@ class TestObjectListBase(test.TestCase):
|
||||
|
||||
def test_obj_repr(self):
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Foo(base.ObjectListBase, base.NovaObject):
|
||||
class Foo(base.ObjectListBase, base.VersionedObject):
|
||||
fields = {'objects': fields.ListOfObjectsField('Bar')}
|
||||
|
||||
@base.VersionedObjectRegistry.register
|
||||
class Bar(base.NovaObject):
|
||||
class Bar(base.VersionedObject):
|
||||
fields = {'uuid': fields.StringField()}
|
||||
|
||||
obj = Foo(objects=[Bar(uuid='fake-uuid')])
|
||||
@@ -1039,22 +1028,22 @@ class TestObjectListBase(test.TestCase):
|
||||
|
||||
class TestObjectSerializer(_BaseTestCase):
|
||||
def test_serialize_entity_primitive(self):
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
for thing in (1, 'foo', [1, 2], {'foo': 'bar'}):
|
||||
self.assertEqual(thing, ser.serialize_entity(None, thing))
|
||||
|
||||
def test_deserialize_entity_primitive(self):
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
for thing in (1, 'foo', [1, 2], {'foo': 'bar'}):
|
||||
self.assertEqual(thing, ser.deserialize_entity(None, thing))
|
||||
|
||||
def test_serialize_set_to_list(self):
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
self.assertEqual([1, 2], ser.serialize_entity(None, set([1, 2])))
|
||||
|
||||
def _test_deserialize_entity_newer(self, obj_version, backported_to,
|
||||
my_version='1.6'):
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
ser._conductor = mock.Mock()
|
||||
ser._conductor.object_backport.return_value = 'backported'
|
||||
|
||||
@@ -1087,13 +1076,13 @@ class TestObjectSerializer(_BaseTestCase):
|
||||
self._test_deserialize_entity_newer('1.7', '1.6.1', '1.6.1')
|
||||
|
||||
def test_deserialize_dot_z_with_extra_stuff(self):
|
||||
primitive = {'nova_object.name': 'MyObj',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.version': '1.6.1',
|
||||
'nova_object.data': {
|
||||
primitive = {'versioned_object.name': 'MyObj',
|
||||
'versioned_object.namespace': 'versionedobjects',
|
||||
'versioned_object.version': '1.6.1',
|
||||
'versioned_object.data': {
|
||||
'foo': 1,
|
||||
'unexpected_thing': 'foobar'}}
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
obj = ser.deserialize_entity(self.context, primitive)
|
||||
self.assertEqual(1, obj.foo)
|
||||
self.assertFalse(hasattr(obj, 'unexpected_thing'))
|
||||
@@ -1105,23 +1094,23 @@ class TestObjectSerializer(_BaseTestCase):
|
||||
self.assertEqual('1.6', obj.VERSION)
|
||||
|
||||
def test_object_serialization(self):
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
obj = MyObj()
|
||||
primitive = ser.serialize_entity(self.context, obj)
|
||||
self.assertIn('nova_object.name', primitive)
|
||||
self.assertIn('versioned_object.name', primitive)
|
||||
obj2 = ser.deserialize_entity(self.context, primitive)
|
||||
self.assertIsInstance(obj2, MyObj)
|
||||
self.assertEqual(self.context, obj2._context)
|
||||
|
||||
def test_object_serialization_iterables(self):
|
||||
ser = base.NovaObjectSerializer()
|
||||
ser = base.VersionedObjectSerializer()
|
||||
obj = MyObj()
|
||||
for iterable in (list, tuple, set):
|
||||
thing = iterable([obj])
|
||||
primitive = ser.serialize_entity(self.context, thing)
|
||||
self.assertEqual(1, len(primitive))
|
||||
for item in primitive:
|
||||
self.assertNotIsInstance(item, base.NovaObject)
|
||||
self.assertNotIsInstance(item, base.VersionedObject)
|
||||
thing2 = ser.deserialize_entity(self.context, primitive)
|
||||
self.assertEqual(1, len(thing2))
|
||||
for item in thing2:
|
||||
@@ -1131,7 +1120,7 @@ class TestObjectSerializer(_BaseTestCase):
|
||||
primitive = ser.serialize_entity(self.context, thing)
|
||||
self.assertEqual(1, len(primitive))
|
||||
for item in primitive.itervalues():
|
||||
self.assertNotIsInstance(item, base.NovaObject)
|
||||
self.assertNotIsInstance(item, base.VersionedObject)
|
||||
thing2 = ser.deserialize_entity(self.context, primitive)
|
||||
self.assertEqual(1, len(thing2))
|
||||
for item in thing2.itervalues():
|
||||
@@ -1142,7 +1131,7 @@ class TestObjectSerializer(_BaseTestCase):
|
||||
primitive = ser.serialize_entity(self.context, thing)
|
||||
self.assertEqual(thing, primitive)
|
||||
thing2 = ser.deserialize_entity(self.context, thing)
|
||||
self.assertIsInstance(thing2['foo'], base.NovaObject)
|
||||
self.assertIsInstance(thing2['foo'], base.VersionedObject)
|
||||
|
||||
|
||||
# NOTE(danms): The hashes in this list should only be changed if
|
||||
|
||||
2
oslo_versionedobjects/tests/test_utils.py
Normal file → Executable file
2
oslo_versionedobjects/tests/test_utils.py
Normal file → Executable file
@@ -26,7 +26,7 @@ class VersionTestCase(test.NoDBTestCase):
|
||||
self.assertEqual(utils.convert_version_to_int('6.2.0'), 6002000)
|
||||
self.assertEqual(utils.convert_version_to_int((6, 4, 3)), 6004003)
|
||||
self.assertEqual(utils.convert_version_to_int((5, )), 5)
|
||||
self.assertRaises(exception.NovaException,
|
||||
self.assertRaises(exception.VersionedObjectsException,
|
||||
utils.convert_version_to_int, '5a.6b')
|
||||
|
||||
def test_convert_version_to_string(self):
|
||||
|
||||
@@ -35,7 +35,7 @@ def convert_version_to_int(version):
|
||||
return reduce(lambda x, y: (x * 1000) + y, version)
|
||||
except Exception:
|
||||
msg = _("Hypervisor version %s is invalid.") % version
|
||||
raise exception.NovaException(msg)
|
||||
raise exception.VersionedObjectsException(msg)
|
||||
|
||||
|
||||
def convert_version_to_str(version_int):
|
||||
|
||||
Reference in New Issue
Block a user