Merge "Refactor objects into a magic registry"

This commit is contained in:
Jenkins 2016-01-04 21:03:35 +00:00 committed by Gerrit Code Review
commit 99f0bf8d3f
5 changed files with 72 additions and 14 deletions

View File

@ -33,6 +33,7 @@ from ironic.common.i18n import _
from ironic.common.i18n import _LE
from ironic.common.i18n import _LI
from ironic.common import rpc
from ironic import objects
from ironic.objects import base as objects_base
@ -140,6 +141,7 @@ def prepare_service(argv=[]):
])
config.parse_args(argv)
log.setup(CONF, 'ironic')
objects.register_all()
def process_launcher():

View File

@ -12,18 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from ironic.objects import chassis
from ironic.objects import conductor
from ironic.objects import node
from ironic.objects import port
# NOTE(comstud): You may scratch your head as you see code that imports
# this module and then accesses attributes for objects such as Node,
# etc, yet you do not see these attributes in here. Never fear, there is
# a little bit of magic. When objects are registered, an attribute is set
# on this module automatically, pointing to the newest/latest version of
# the object.
Chassis = chassis.Chassis
Conductor = conductor.Conductor
Node = node.Node
Port = port.Port
__all__ = (Chassis,
Conductor,
Node,
Port)
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__('ironic.objects.chassis')
__import__('ironic.objects.conductor')
__import__('ironic.objects.node')
__import__('ironic.objects.port')

View File

@ -14,13 +14,27 @@
"""Ironic common internal object model"""
from oslo_utils import versionutils
from oslo_versionedobjects import base as object_base
from ironic import objects
from ironic.objects import fields as object_fields
class IronicObjectRegistry(object_base.VersionedObjectRegistry):
pass
def registration_hook(self, cls, index):
# NOTE(jroll): blatantly stolen from nova
# NOTE(danms): This is called when an object is registered,
# and is responsible for maintaining ironic.objects.$OBJECT
# as the highest-versioned implementation of a given object.
version = versionutils.convert_version_to_tuple(cls.VERSION)
if not hasattr(objects, cls.obj_name()):
setattr(objects, cls.obj_name(), cls)
else:
cur_version = versionutils.convert_version_to_tuple(
getattr(objects, cls.obj_name()).VERSION)
if version >= cur_version:
setattr(objects, cls.obj_name(), cls)
class IronicObject(object_base.VersionedObject):

View File

@ -26,4 +26,11 @@
import eventlet
from ironic import objects
eventlet.monkey_patch(os=False)
# 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
# tests that run at import time.
objects.register_all()

View File

@ -496,3 +496,37 @@ class TestObjectSerializer(test_base.TestCase):
def test_deserialize_entity_newer_version_passes_revision(self):
"Test object with unsupported (newer) version and revision"
self._test_deserialize_entity_newer('1.7', '1.6.1', my_version='1.6.1')
class TestRegistry(test_base.TestCase):
@mock.patch('ironic.objects.base.objects')
def test_hook_chooses_newer_properly(self, mock_objects):
reg = base.IronicObjectRegistry()
reg.registration_hook(MyObj, 0)
class MyNewerObj(object):
VERSION = '1.123'
@classmethod
def obj_name(cls):
return 'MyObj'
self.assertEqual(MyObj, mock_objects.MyObj)
reg.registration_hook(MyNewerObj, 0)
self.assertEqual(MyNewerObj, mock_objects.MyObj)
@mock.patch('ironic.objects.base.objects')
def test_hook_keeps_newer_properly(self, mock_objects):
reg = base.IronicObjectRegistry()
reg.registration_hook(MyObj, 0)
class MyOlderObj(object):
VERSION = '1.1'
@classmethod
def obj_name(cls):
return 'MyObj'
self.assertEqual(MyObj, mock_objects.MyObj)
reg.registration_hook(MyOlderObj, 0)
self.assertEqual(MyObj, mock_objects.MyObj)