Merge "Make MagnumObject a subclass of Oslo VersionedObject"
This commit is contained in:
commit
a5f56a2c1a
|
@ -15,14 +15,13 @@
|
|||
"""Magnum common internal object model"""
|
||||
|
||||
import collections
|
||||
import copy
|
||||
|
||||
from oslo_context import context as oslo_context
|
||||
from oslo_versionedobjects import base as ovoo_base
|
||||
from oslo_versionedobjects import fields as ovoo_fields
|
||||
import six
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.objects import utils as obj_utils
|
||||
from magnum.openstack.common._i18n import _
|
||||
from magnum.openstack.common._i18n import _LE
|
||||
from magnum.openstack.common import log as logging
|
||||
|
@ -32,49 +31,6 @@ from magnum.openstack.common import versionutils
|
|||
LOG = logging.getLogger('object')
|
||||
|
||||
|
||||
class NotSpecifiedSentinel(object):
|
||||
pass
|
||||
|
||||
|
||||
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, typefn in cls.fields.iteritems():
|
||||
|
||||
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, typefn=typefn):
|
||||
self._changed_fields.add(name)
|
||||
try:
|
||||
return setattr(self, get_attrname(name), typefn(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 MagnumObjectMetaclass(type):
|
||||
"""Metaclass that allows tracking of object classes."""
|
||||
|
||||
|
@ -88,8 +44,10 @@ class MagnumObjectMetaclass(type):
|
|||
cls._obj_classes = collections.defaultdict(list)
|
||||
else:
|
||||
# Add the subclass to MagnumObject._obj_classes
|
||||
make_class_properties(cls)
|
||||
ovoo_base._make_class_properties(cls)
|
||||
cls._obj_classes[cls.obj_name()].append(cls)
|
||||
# NOTE(xek): object tracking will be moved to a new registartion
|
||||
# scheme from oslo.versionedobjects, which uses decorators
|
||||
|
||||
|
||||
# These are decorators that mark an object's method as remotable.
|
||||
|
@ -136,7 +94,8 @@ def remotable(fn):
|
|||
context, self, fn.__name__, args, kwargs)
|
||||
for key, value in updates.iteritems():
|
||||
if key in self.fields:
|
||||
self[key] = self._attr_from_primitive(key, value)
|
||||
field = self.fields[key]
|
||||
self[key] = field.from_primitive(self, key, value)
|
||||
self._changed_fields = set(updates.get('obj_what_changed', []))
|
||||
return result
|
||||
else:
|
||||
|
@ -169,7 +128,7 @@ def check_object_version(server, client):
|
|||
|
||||
|
||||
@six.add_metaclass(MagnumObjectMetaclass)
|
||||
class MagnumObject(ovoo_base.VersionedObjectDictCompat):
|
||||
class MagnumObject(ovoo_base.VersionedObject):
|
||||
"""Base class and object factory.
|
||||
|
||||
This forms the base of all objects that can be remoted or instantiated
|
||||
|
@ -180,43 +139,7 @@ class MagnumObject(ovoo_base.VersionedObjectDictCompat):
|
|||
"""
|
||||
|
||||
OBJ_SERIAL_NAMESPACE = 'magnum_object'
|
||||
|
||||
# Version of this object (see rules above check_object_version())
|
||||
VERSION = '1.0'
|
||||
|
||||
# The fields present in this object as key:typefn pairs. For example:
|
||||
#
|
||||
# fields = { 'foo': int,
|
||||
# 'bar': str,
|
||||
# 'baz': lambda x: str(x).ljust(8),
|
||||
# }
|
||||
#
|
||||
# NOTE(danms): The base MagnumObject class' fields will be inherited
|
||||
# by subclasses, but that is a special case. Objects inheriting from
|
||||
# other objects will not receive this merging of fields contents.
|
||||
fields = {
|
||||
'created_at': obj_utils.datetime_or_str_or_none,
|
||||
'updated_at': obj_utils.datetime_or_str_or_none,
|
||||
}
|
||||
obj_extra_fields = []
|
||||
|
||||
_attr_created_at_from_primitive = obj_utils.dt_deserializer
|
||||
_attr_updated_at_from_primitive = obj_utils.dt_deserializer
|
||||
_attr_created_at_to_primitive = obj_utils.dt_serializer('created_at')
|
||||
_attr_updated_at_to_primitive = obj_utils.dt_serializer('updated_at')
|
||||
|
||||
def __init__(self, context, **kwargs):
|
||||
self._changed_fields = set()
|
||||
self._context = context
|
||||
self.update(kwargs)
|
||||
|
||||
@classmethod
|
||||
def obj_name(cls):
|
||||
"""Get canonical object name.
|
||||
|
||||
This object name will be used over the wire for remote hydration.
|
||||
"""
|
||||
return cls.__name__
|
||||
OBJ_PROJECT_NAMESPACE = 'magnum'
|
||||
|
||||
@classmethod
|
||||
def obj_class_from_name(cls, objname, objver):
|
||||
|
@ -249,161 +172,26 @@ class MagnumObject(ovoo_base.VersionedObjectDictCompat):
|
|||
objver=objver,
|
||||
supported=latest_ver)
|
||||
|
||||
def _attr_from_primitive(self, attribute, value):
|
||||
"""Attribute deserialization dispatcher.
|
||||
|
||||
This calls self._attr_foo_from_primitive(value) for an attribute
|
||||
foo with value, if it exists, otherwise it assumes the value
|
||||
is suitable for the attribute's setter method.
|
||||
"""
|
||||
handler = '_attr_%s_from_primitive' % attribute
|
||||
if hasattr(self, handler):
|
||||
return getattr(self, handler)(value)
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def _obj_from_primitive(cls, context, objver, primitive):
|
||||
self = cls(context)
|
||||
self.VERSION = objver
|
||||
objdata = primitive['magnum_object.data']
|
||||
changes = primitive.get('magnum_object.changes', [])
|
||||
for name in self.fields:
|
||||
if name in objdata:
|
||||
setattr(self, name,
|
||||
self._attr_from_primitive(name, objdata[name]))
|
||||
self._changed_fields = set([x for x in changes if x in self.fields])
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context=None):
|
||||
"""Simple base-case hydration.
|
||||
|
||||
This calls self._attr_from_primitive() for each item in fields.
|
||||
"""
|
||||
if primitive['magnum_object.namespace'] != 'magnum':
|
||||
# NOTE(danms): We don't do anything with this now, but it's
|
||||
# there for "the future"
|
||||
raise exception.UnsupportedObjectError(
|
||||
objtype='%s.%s' % (primitive['magnum_object.namespace'],
|
||||
primitive['magnum_object.name']))
|
||||
objname = primitive['magnum_object.name']
|
||||
objver = primitive['magnum_object.version']
|
||||
objclass = cls.obj_class_from_name(objname, objver)
|
||||
return objclass._obj_from_primitive(context, objver, primitive)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
"""Efficiently make a deep copy of this object."""
|
||||
|
||||
# NOTE(danms): A naive deepcopy would copy more than we need,
|
||||
# and since we have knowledge of the volatile bits of the
|
||||
# object, we can be smarter here. Also, nested entities within
|
||||
# some objects may be uncopyable, so we can avoid those sorts
|
||||
# of issues by copying only our field data.
|
||||
|
||||
nobj = self.__class__(self._context)
|
||||
for name in self.fields:
|
||||
if self.obj_attr_is_set(name):
|
||||
nval = copy.deepcopy(getattr(self, name), memo)
|
||||
setattr(nobj, name, nval)
|
||||
nobj._changed_fields = set(self._changed_fields)
|
||||
return nobj
|
||||
|
||||
def obj_clone(self):
|
||||
"""Create a copy."""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def _attr_to_primitive(self, attribute):
|
||||
"""Attribute serialization dispatcher.
|
||||
|
||||
This calls self._attr_foo_to_primitive() for an attribute foo,
|
||||
if it exists, otherwise it assumes the attribute itself is
|
||||
primitive-enough to be sent over the RPC wire.
|
||||
"""
|
||||
handler = '_attr_%s_to_primitive' % attribute
|
||||
if hasattr(self, handler):
|
||||
return getattr(self, handler)()
|
||||
else:
|
||||
return getattr(self, attribute)
|
||||
|
||||
def obj_to_primitive(self):
|
||||
"""Simple base-case dehydration.
|
||||
|
||||
This calls self._attr_to_primitive() for each item in fields.
|
||||
"""
|
||||
primitive = dict()
|
||||
for name in self.fields:
|
||||
if hasattr(self, get_attrname(name)):
|
||||
primitive[name] = self._attr_to_primitive(name)
|
||||
obj = {'magnum_object.name': self.obj_name(),
|
||||
'magnum_object.namespace': 'magnum',
|
||||
'magnum_object.version': self.VERSION,
|
||||
'magnum_object.data': primitive}
|
||||
if self.obj_what_changed():
|
||||
obj['magnum_object.changes'] = list(self.obj_what_changed())
|
||||
return obj
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
"""Load an additional attribute from the real object.
|
||||
|
||||
This should use self._conductor, and cache any data that might
|
||||
be useful for future load operations.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
_("Cannot load '%(attrname)s' in the base class") %
|
||||
{'attrname': attrname})
|
||||
|
||||
def save(self, context):
|
||||
"""Save the changed fields back to the store.
|
||||
|
||||
This is optional for subclasses, but is presented here in the base
|
||||
class for consistency among those that do.
|
||||
"""
|
||||
raise NotImplementedError(_("Cannot save anything in the base class"))
|
||||
|
||||
def obj_get_changes(self):
|
||||
"""Returns a dict of changed fields and their new values."""
|
||||
changes = {}
|
||||
for key in self.obj_what_changed():
|
||||
changes[key] = self[key]
|
||||
return changes
|
||||
|
||||
def obj_what_changed(self):
|
||||
"""Returns a set of fields that have been modified."""
|
||||
return self._changed_fields
|
||||
|
||||
def obj_reset_changes(self, fields=None):
|
||||
"""Reset the list of fields that have been changed.
|
||||
|
||||
Note that this is NOT "revert to previous values"
|
||||
"""
|
||||
if fields:
|
||||
self._changed_fields -= set(fields)
|
||||
else:
|
||||
self._changed_fields.clear()
|
||||
|
||||
def obj_attr_is_set(self, attrname):
|
||||
"""Test object to see if attrname is present.
|
||||
|
||||
Returns True if the named attribute has a value set, or
|
||||
False if not. Raises AttributeError if attrname is not
|
||||
a valid attribute for this object.
|
||||
"""
|
||||
if attrname not in self.obj_fields:
|
||||
raise AttributeError(
|
||||
_("%(objname)s object has no attribute '%(attrname)s'") %
|
||||
{'objname': self.obj_name(), 'attrname': attrname})
|
||||
return hasattr(self, get_attrname(attrname))
|
||||
|
||||
@property
|
||||
def obj_fields(self):
|
||||
return self.fields.keys() + self.obj_extra_fields
|
||||
|
||||
def as_dict(self):
|
||||
return dict((k, getattr(self, k))
|
||||
for k in self.fields
|
||||
if hasattr(self, k))
|
||||
|
||||
|
||||
class MagnumObjectDictCompat(ovoo_base.VersionedObjectDictCompat):
|
||||
pass
|
||||
|
||||
|
||||
class MagnumPersistentObject(object):
|
||||
"""Mixin class for Persistent objects.
|
||||
This adds the fields that we use in common for all persistent objects.
|
||||
"""
|
||||
fields = {
|
||||
'created_at': ovoo_fields.DateTimeField(nullable=True),
|
||||
'updated_at': ovoo_fields.DateTimeField(nullable=True),
|
||||
}
|
||||
|
||||
|
||||
class ObjectListBase(ovoo_base.ObjectListBase):
|
||||
# TODO(xek): These are for transition to using the oslo base object
|
||||
# and can be removed when we move to it.
|
||||
|
@ -440,8 +228,9 @@ def obj_to_primitive(obj):
|
|||
return [obj_to_primitive(x) for x in obj]
|
||||
elif isinstance(obj, MagnumObject):
|
||||
result = {}
|
||||
for key, value in obj.iteritems():
|
||||
result[key] = obj_to_primitive(value)
|
||||
for key in obj.obj_fields:
|
||||
if obj.obj_attr_is_set(key) or key in obj.obj_extra_fields:
|
||||
result[key] = obj_to_primitive(getattr(obj, key))
|
||||
return result
|
||||
else:
|
||||
return obj
|
||||
|
|
|
@ -13,11 +13,12 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.common import utils
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class Status(object):
|
||||
|
@ -32,28 +33,29 @@ class Status(object):
|
|||
DELETED = 'DELETED'
|
||||
|
||||
|
||||
class Bay(base.MagnumObject):
|
||||
class Bay(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'name': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'baymodel_id': obj_utils.str_or_none,
|
||||
'stack_id': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.UUIDField(nullable=True),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'baymodel_id': fields.StringField(nullable=True),
|
||||
'stack_id': fields.StringField(nullable=True),
|
||||
# One of CREATE_IN_PROGRESS|CREATE_FAILED|CREATED
|
||||
# UPDATE_IN_PROGRESS|UPDATE_FAILED|UPDATED
|
||||
# DELETE_IN_PROGRESS|DELETE_FAILED|DELETED
|
||||
'status': obj_utils.str_or_none,
|
||||
'api_address': obj_utils.str_or_none,
|
||||
'node_addresses': obj_utils.list_or_none,
|
||||
'node_count': obj_utils.int_or_none,
|
||||
'discovery_url': obj_utils.str_or_none,
|
||||
'status': fields.StringField(nullable=True),
|
||||
'api_address': fields.StringField(nullable=True),
|
||||
'node_addresses': fields.ListOfStringsField(nullable=True),
|
||||
'node_count': fields.IntegerField(nullable=True),
|
||||
'discovery_url': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -204,6 +206,5 @@ class Bay(base.MagnumObject):
|
|||
"""
|
||||
current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
|
||||
for field in self.fields:
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -11,21 +11,23 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class BayLock(base.MagnumObject):
|
||||
class BayLock(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'bay_uuid': obj_utils.str_or_none,
|
||||
'conductor_id': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'bay_uuid': fields.StringField(nullable=True),
|
||||
'conductor_id': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
|
|
|
@ -13,37 +13,39 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.common import utils
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class BayModel(base.MagnumObject):
|
||||
class BayModel(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'name': obj_utils.str_or_none,
|
||||
'image_id': obj_utils.str_or_none,
|
||||
'flavor_id': obj_utils.str_or_none,
|
||||
'master_flavor_id': obj_utils.str_or_none,
|
||||
'keypair_id': obj_utils.str_or_none,
|
||||
'dns_nameserver': obj_utils.str_or_none,
|
||||
'external_network_id': obj_utils.str_or_none,
|
||||
'fixed_network': obj_utils.str_or_none,
|
||||
'apiserver_port': obj_utils.int_or_none,
|
||||
'docker_volume_size': obj_utils.int_or_none,
|
||||
'ssh_authorized_key': obj_utils.str_or_none,
|
||||
'cluster_distro': obj_utils.str_or_none,
|
||||
'coe': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'image_id': fields.StringField(nullable=True),
|
||||
'flavor_id': fields.StringField(nullable=True),
|
||||
'master_flavor_id': fields.StringField(nullable=True),
|
||||
'keypair_id': fields.StringField(nullable=True),
|
||||
'dns_nameserver': fields.StringField(nullable=True),
|
||||
'external_network_id': fields.StringField(nullable=True),
|
||||
'fixed_network': fields.StringField(nullable=True),
|
||||
'apiserver_port': fields.IntegerField(nullable=True),
|
||||
'docker_volume_size': fields.IntegerField(nullable=True),
|
||||
'ssh_authorized_key': fields.StringField(nullable=True),
|
||||
'cluster_distro': fields.StringField(nullable=True),
|
||||
'coe': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -195,6 +197,5 @@ class BayModel(base.MagnumObject):
|
|||
"""
|
||||
current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
|
||||
for field in self.fields:
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -13,26 +13,28 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class Container(base.MagnumObject):
|
||||
class Container(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'name': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'image_id': obj_utils.str_or_none,
|
||||
'command': obj_utils.str_or_none,
|
||||
'bay_uuid': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.StringField(nullable=True),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'image_id': fields.StringField(nullable=True),
|
||||
'command': fields.StringField(nullable=True),
|
||||
'bay_uuid': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -170,6 +172,5 @@ class Container(base.MagnumObject):
|
|||
"""
|
||||
current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
|
||||
for field in self.fields:
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2015 Intel Corp.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
|
||||
class ListOfDictsField(fields.AutoTypedField):
|
||||
AUTO_TYPE = fields.List(fields.Dict(fields.FieldType()))
|
|
@ -13,25 +13,27 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class Node(base.MagnumObject):
|
||||
class Node(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'type': obj_utils.str_or_none,
|
||||
'image_id': obj_utils.str_or_none,
|
||||
'ironic_node_id': obj_utils.str_or_none
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'type': fields.StringField(nullable=True),
|
||||
'image_id': fields.StringField(nullable=True),
|
||||
'ironic_node_id': fields.StringField(nullable=True)
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -156,6 +158,5 @@ class Node(base.MagnumObject):
|
|||
"""
|
||||
current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
|
||||
for field in self.fields:
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -13,30 +13,32 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class Pod(base.MagnumObject):
|
||||
class Pod(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'name': obj_utils.str_or_none,
|
||||
'desc': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'bay_uuid': obj_utils.str_or_none,
|
||||
'images': obj_utils.list_or_none,
|
||||
'labels': obj_utils.dict_or_none,
|
||||
'status': obj_utils.str_or_none,
|
||||
'manifest_url': obj_utils.str_or_none,
|
||||
'manifest': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.StringField(nullable=True),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'desc': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'bay_uuid': fields.StringField(nullable=True),
|
||||
'images': fields.ListOfStringsField(nullable=True),
|
||||
'labels': fields.DictOfStringsField(nullable=True),
|
||||
'status': fields.StringField(nullable=True),
|
||||
'manifest_url': fields.StringField(nullable=True),
|
||||
'manifest': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -193,6 +195,5 @@ class Pod(base.MagnumObject):
|
|||
continue
|
||||
if field == 'manifest':
|
||||
continue
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -12,29 +12,31 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
|
||||
|
||||
class ReplicationController(base.MagnumObject):
|
||||
class ReplicationController(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'name': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'images': obj_utils.list_or_none,
|
||||
'bay_uuid': obj_utils.str_or_none,
|
||||
'labels': obj_utils.dict_or_none,
|
||||
'replicas': obj_utils.int_or_none,
|
||||
'manifest_url': obj_utils.str_or_none,
|
||||
'manifest': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.StringField(nullable=True),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'images': fields.ListOfStringsField(nullable=True),
|
||||
'bay_uuid': fields.StringField(nullable=True),
|
||||
'labels': fields.DictOfStringsField(nullable=True),
|
||||
'replicas': fields.IntegerField(nullable=True),
|
||||
'manifest_url': fields.StringField(nullable=True),
|
||||
'manifest': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -185,6 +187,5 @@ class ReplicationController(base.MagnumObject):
|
|||
continue
|
||||
if field == 'manifest':
|
||||
continue
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -13,30 +13,33 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
from magnum.objects import utils as obj_utils
|
||||
from magnum.objects import fields as magnum_fields
|
||||
|
||||
|
||||
class Service(base.MagnumObject):
|
||||
class Service(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': obj_utils.str_or_none,
|
||||
'name': obj_utils.str_or_none,
|
||||
'project_id': obj_utils.str_or_none,
|
||||
'user_id': obj_utils.str_or_none,
|
||||
'bay_uuid': obj_utils.str_or_none,
|
||||
'labels': obj_utils.dict_or_none,
|
||||
'selector': obj_utils.dict_or_none,
|
||||
'ip': obj_utils.str_or_none,
|
||||
'ports': obj_utils.list_or_none,
|
||||
'manifest_url': obj_utils.str_or_none,
|
||||
'manifest': obj_utils.str_or_none,
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.StringField(nullable=True),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
'bay_uuid': fields.StringField(nullable=True),
|
||||
'labels': fields.DictOfStringsField(nullable=True),
|
||||
'selector': fields.DictOfStringsField(nullable=True),
|
||||
'ip': fields.StringField(nullable=True),
|
||||
'ports': magnum_fields.ListOfDictsField(nullable=True),
|
||||
'manifest_url': fields.StringField(nullable=True),
|
||||
'manifest': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -195,6 +198,5 @@ class Service(base.MagnumObject):
|
|||
continue
|
||||
if field == 'manifest':
|
||||
continue
|
||||
if (hasattr(self, base.get_attrname(field)) and
|
||||
self[field] != current[field]):
|
||||
if self.obj_attr_is_set(field) and self[field] != current[field]:
|
||||
self[field] = current[field]
|
||||
|
|
|
@ -18,6 +18,7 @@ import gettext
|
|||
import iso8601
|
||||
import netaddr
|
||||
from oslo_utils import timeutils
|
||||
from oslo_versionedobjects import fields
|
||||
import six
|
||||
|
||||
from magnum.common import context as magnum_context
|
||||
|
@ -32,9 +33,9 @@ gettext.install('magnum')
|
|||
class MyObj(base.MagnumObject):
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {'foo': int,
|
||||
'bar': str,
|
||||
'missing': str,
|
||||
fields = {'foo': fields.IntegerField(),
|
||||
'bar': fields.StringField(),
|
||||
'missing': fields.StringField(),
|
||||
}
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
|
@ -87,7 +88,7 @@ class MyObj2(object):
|
|||
|
||||
|
||||
class TestSubclassedObject(MyObj):
|
||||
fields = {'new_field': str}
|
||||
fields = {'new_field': fields.StringField()}
|
||||
|
||||
|
||||
class TestMetaclass(test_base.TestCase):
|
||||
|
@ -186,10 +187,10 @@ class TestUtils(test_base.TestCase):
|
|||
|
||||
def test_obj_to_primitive_list(self):
|
||||
class MyList(base.ObjectListBase, base.MagnumObject):
|
||||
pass
|
||||
fields = {'objects': fields.ListOfStringsField()}
|
||||
mylist = MyList(self.context)
|
||||
mylist.objects = [1, 2, 3]
|
||||
self.assertEqual([1, 2, 3], base.obj_to_primitive(mylist))
|
||||
mylist.objects = ['1', '2', '3']
|
||||
self.assertEqual(['1', '2', '3'], base.obj_to_primitive(mylist))
|
||||
|
||||
def test_obj_to_primitive_dict(self):
|
||||
myobj = MyObj(self.context)
|
||||
|
@ -200,7 +201,7 @@ class TestUtils(test_base.TestCase):
|
|||
|
||||
def test_obj_to_primitive_recursive(self):
|
||||
class MyList(base.ObjectListBase, base.MagnumObject):
|
||||
pass
|
||||
fields = {'objects': fields.ListOfObjectsField('MyObj')}
|
||||
|
||||
mylist = MyList(self.context)
|
||||
mylist.objects = [MyObj(self.context), MyObj(self.context)]
|
||||
|
@ -271,7 +272,7 @@ class _TestObject(object):
|
|||
|
||||
def test_load_in_base(self):
|
||||
class Foo(base.MagnumObject):
|
||||
fields = {'foobar': int}
|
||||
fields = {'foobar': fields.IntegerField()}
|
||||
obj = Foo(self.context)
|
||||
# NOTE(danms): Can't use assertRaisesRegexp() because of py26
|
||||
raised = False
|
||||
|
@ -453,7 +454,7 @@ class _TestObject(object):
|
|||
|
||||
def test_obj_fields(self):
|
||||
class TestObj(base.MagnumObject):
|
||||
fields = {'foo': int}
|
||||
fields = {'foo': fields.IntegerField()}
|
||||
obj_extra_fields = ['bar']
|
||||
|
||||
@property
|
||||
|
|
Loading…
Reference in New Issue