summaryrefslogtreecommitdiff
path: root/ironic/objects/base.py
diff options
context:
space:
mode:
authorLin Tan <lin.tan@intel.com>2015-08-27 11:12:28 +0800
committerLin Tan <lin.tan@intel.com>2015-09-16 10:32:19 +0800
commit442633cd9e923ddad67fbf9c768fca65acee55db (patch)
treeb62f499bdcdc89780e04d09c98084cd3331e7c7d /ironic/objects/base.py
parentde6aa5833a6832be1deb9cb104ca0ba56d0e36e7 (diff)
downloadironic-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.py66
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