diff options
author | Lin Tan <lin.tan@intel.com> | 2015-08-27 11:12:28 +0800 |
---|---|---|
committer | Lin Tan <lin.tan@intel.com> | 2015-09-16 10:32:19 +0800 |
commit | 442633cd9e923ddad67fbf9c768fca65acee55db (patch) | |
tree | b62f499bdcdc89780e04d09c98084cd3331e7c7d /ironic/objects/base.py | |
parent | de6aa5833a6832be1deb9cb104ca0ba56d0e36e7 (diff) | |
download | ironic-442633cd9e923ddad67fbf9c768fca65acee55db.tar.gz |
Replace metaclass registry with explicit opt-in registry from oslo
Previously, objects are registered through metaclass, which is
complicate to understand. So oslo.versionedobjects move this to
ObjectRegistry class. Each object is registered with a decorator.
This also includes registering some test-only classes,
which use the register_if(False) scheme to do the object-building step,
but without actually inserting the class into the registry. This prevents
those test classes from ever being registered at runtime by accident
(and thus send/receive-able over RPC).
Co-Author: Dan Smith <dms@danplanet.com>
Partial-Bug: #1461239
Change-Id: Ice4d47185b888d1b33e761d7d1437bb20abb3d93
Diffstat (limited to 'ironic/objects/base.py')
-rw-r--r-- | ironic/objects/base.py | 66 |
1 files changed, 9 insertions, 57 deletions
diff --git a/ironic/objects/base.py b/ironic/objects/base.py index cdb9dfb7a..aa926894f 100644 --- a/ironic/objects/base.py +++ b/ironic/objects/base.py @@ -14,14 +14,12 @@ """Ironic common internal object model""" -import collections import copy from oslo_context import context from oslo_log import log as logging from oslo_utils import versionutils from oslo_versionedobjects import base as object_base -import six from ironic.common import exception from ironic.common.i18n import _ @@ -35,59 +33,11 @@ LOG = logging.getLogger('object') def get_attrname(name): """Return the mangled name of the attribute's underlying storage.""" - return '_%s' % name - - -def make_class_properties(cls): - # NOTE(danms/comstud): Inherit fields from super classes. - # mro() returns the current class first and returns 'object' last, so - # those can be skipped. Also be careful to not overwrite any fields - # that already exist. And make sure each cls has its own copy of - # fields and that it is not sharing the dict with a super class. - cls.fields = dict(cls.fields) - for supercls in cls.mro()[1:-1]: - if not hasattr(supercls, 'fields'): - continue - for name, field in supercls.fields.items(): - if name not in cls.fields: - cls.fields[name] = field - for name, field in cls.fields.items(): - - def getter(self, name=name): - attrname = get_attrname(name) - if not hasattr(self, attrname): - self.obj_load_attr(name) - return getattr(self, attrname) - - def setter(self, value, name=name, field=field): - self._changed_fields.add(name) - try: - field_value = field.coerce(self, name, value) - return setattr(self, get_attrname(name), field_value) - except Exception: - attr = "%s.%s" % (self.obj_name(), name) - LOG.exception(_LE('Error setting %(attr)s'), - {'attr': attr}) - raise - - setattr(cls, name, property(getter, setter)) - - -class IronicObjectMetaclass(type): - """Metaclass that allows tracking of object classes.""" - - # NOTE(danms): This is what controls whether object operations are - # remoted. If this is not None, use it to remote things over RPC. - indirection_api = None + return '_obj_' + name - def __init__(cls, names, bases, dict_): - if not hasattr(cls, '_obj_classes'): - # This will be set in the 'IronicObject' class. - cls._obj_classes = collections.defaultdict(list) - else: - # Add the subclass to IronicObject._obj_classes - make_class_properties(cls) - cls._obj_classes[cls.obj_name()].append(cls) + +class IronicObjectRegistry(object_base.VersionedObjectRegistry): + pass # These are decorators that mark an object's method as remotable. @@ -166,7 +116,6 @@ def check_object_version(server, client): dict(client=client_minor, server=server_minor)) -@six.add_metaclass(IronicObjectMetaclass) class IronicObject(object_base.VersionedObjectDictCompat): """Base class and object factory. @@ -177,6 +126,8 @@ class IronicObject(object_base.VersionedObjectDictCompat): as appropriate. """ + indirection_api = None + OBJ_SERIAL_NAMESPACE = 'ironic_object' # Version of this object (see rules above check_object_version()) VERSION = '1.0' @@ -218,14 +169,15 @@ class IronicObject(object_base.VersionedObjectDictCompat): @classmethod def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" - if objname not in cls._obj_classes: + if objname not in IronicObjectRegistry.obj_classes(): LOG.error(_LE('Unable to instantiate unregistered object type ' '%(objtype)s'), dict(objtype=objname)) raise exception.UnsupportedObjectError(objtype=objname) latest = None compatible_match = None - for objclass in cls._obj_classes[objname]: + obj_classes = IronicObjectRegistry.obj_classes() + for objclass in obj_classes[objname]: if objclass.VERSION == objver: return objclass |