Make Object FieldType take an object name instead of a class

The object infrastructure has a concept of an object name, which
is what we use to determine if something implements a particular
thing, and it is how we look up object classes when we
deserialize them. Since many objects will eventually reference
each other, we should be using their names to determine
compatibility, not their classes.

Related to blueprint structured-object-fields

Change-Id: I2edb8b8475662ad25e9f3319ce5e44317a2d0547
This commit is contained in:
Dan Smith
2013-10-14 15:47:03 -07:00
parent 37e143c4eb
commit 106efc7a35
15 changed files with 69 additions and 22 deletions

View File

@@ -149,6 +149,10 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
# Version 1.1: Added key argument to get_by_host() # Version 1.1: Added key argument to get_by_host()
VERSION = '1.1' VERSION = '1.1'
fields = {
'objects': fields.ListOfObjectsField('Aggregate'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_all(cls, context): def get_all(cls, context):
db_aggregates = db.aggregate_get_all(context) db_aggregates = db.aggregate_get_all(context)

View File

@@ -410,7 +410,7 @@ class ObjectListBase(object):
serialization of the list of objects automatically. serialization of the list of objects automatically.
""" """
fields = { fields = {
'objects': fields.ListOfObjectsField(NovaObject), 'objects': fields.ListOfObjectsField('NovaObject'),
} }
def __iter__(self): def __iter__(self):

View File

@@ -90,6 +90,10 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
class ComputeNodeList(base.ObjectListBase, base.NovaObject): class ComputeNodeList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('ComputeNode'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_all(cls, context): def get_all(cls, context):
db_computes = db.compute_node_get_all(context) db_computes = db.compute_node_get_all(context)

View File

@@ -324,14 +324,19 @@ class Dict(CompoundFieldType):
class Object(FieldType): class Object(FieldType):
def __init__(self, objtype, **kwargs): def __init__(self, obj_name, **kwargs):
self._objtype = objtype self._obj_name = obj_name
super(Object, self).__init__(**kwargs) super(Object, self).__init__(**kwargs)
def coerce(self, obj, attr, value): def coerce(self, obj, attr, value):
if not isinstance(value, self._objtype): try:
obj_name = value.obj_name()
except AttributeError:
obj_name = ""
if obj_name != self._obj_name:
raise ValueError(_('An object of type %s is required here') % raise ValueError(_('An object of type %s is required here') %
self._objtype.obj_name()) self._obj_name)
return value return value
def to_primitive(self, obj, attr, value): def to_primitive(self, obj, attr, value):
@@ -343,7 +348,7 @@ class Object(FieldType):
return obj_base.NovaObject.obj_from_primitive(value, obj._context) return obj_base.NovaObject.obj_from_primitive(value, obj._context)
def describe(self): def describe(self):
return "Object<%s>" % self._objtype.obj_name() return "Object<%s>" % self._obj_name
class NetworkModel(FieldType): class NetworkModel(FieldType):

View File

@@ -144,19 +144,16 @@ class Instance(base.NovaPersistentObject, base.NovaObject):
'metadata': fields.DictOfStringsField(), 'metadata': fields.DictOfStringsField(),
'system_metadata': fields.DictOfNullableStringsField(), 'system_metadata': fields.DictOfNullableStringsField(),
'info_cache': fields.ObjectField( 'info_cache': fields.ObjectField('InstanceInfoCache',
instance_info_cache.InstanceInfoCache, nullable=True), nullable=True),
'security_groups': fields.ObjectField( 'security_groups': fields.ObjectField('SecurityGroupList'),
security_group.SecurityGroupList),
'fault': fields.ObjectField(instance_fault.InstanceFault, 'fault': fields.ObjectField('InstanceFault', nullable=True),
nullable=True),
'cleaned': fields.BooleanField(default=False), 'cleaned': fields.BooleanField(default=False),
'pci_devices': fields.ObjectField(pci_device.PciDeviceList, 'pci_devices': fields.ObjectField('PciDeviceList', nullable=True),
nullable=True),
} }
obj_extra_fields = ['name'] obj_extra_fields = ['name']
@@ -490,6 +487,10 @@ def _make_instance_list(context, inst_list, db_inst_list, expected_attrs):
class InstanceList(base.ObjectListBase, base.NovaObject): class InstanceList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('Instance'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_filters(cls, context, filters, def get_by_filters(cls, context, filters,
sort_key='created_at', sort_dir='desc', limit=None, sort_key='created_at', sort_dir='desc', limit=None,

View File

@@ -77,6 +77,10 @@ class InstanceAction(base.NovaPersistentObject, base.NovaObject):
class InstanceActionList(base.ObjectListBase, base.NovaObject): class InstanceActionList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('InstanceAction'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_instance_uuid(cls, context, instance_uuid): def get_by_instance_uuid(cls, context, instance_uuid):
db_actions = db.actions_get(context, instance_uuid) db_actions = db.actions_get(context, instance_uuid)
@@ -150,6 +154,10 @@ class InstanceActionEvent(base.NovaPersistentObject, base.NovaObject):
class InstanceActionEventList(base.ObjectListBase, base.NovaObject): class InstanceActionEventList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('InstanceActionEvent'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_action(cls, context, action_id): def get_by_action(cls, context, action_id):
db_events = db.action_events_get(context, action_id) db_events = db.action_events_get(context, action_id)

View File

@@ -58,6 +58,10 @@ def _make_fault_list(faultlist, db_faultlist):
class InstanceFaultList(base.ObjectListBase, base.NovaObject): class InstanceFaultList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('InstanceFault'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_instance_uuids(cls, context, instance_uuids): def get_by_instance_uuids(cls, context, instance_uuids):
db_faults = db.instance_fault_get_by_instance_uuids(context, db_faults = db.instance_fault_get_by_instance_uuids(context,

View File

@@ -123,6 +123,9 @@ def _make_instance_group_list(context, inst_list, db_list):
class InstanceGroupList(base.ObjectListBase, base.NovaObject): class InstanceGroupList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('InstanceGroup'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_project_id(cls, context, project_id): def get_by_project_id(cls, context, project_id):

View File

@@ -59,6 +59,10 @@ class KeyPair(base.NovaPersistentObject, base.NovaObject):
class KeyPairList(base.ObjectListBase, base.NovaObject): class KeyPairList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('KeyPair'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_user(cls, context, user_id): def get_by_user(cls, context, user_id):
db_keypairs = db.key_pair_get_all_by_user(context, user_id) db_keypairs = db.key_pair_get_all_by_user(context, user_id)

View File

@@ -86,6 +86,10 @@ def _make_list(context, list_obj, item_cls, db_list):
class MigrationList(base.ObjectListBase, base.NovaObject): class MigrationList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('Migration'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_unconfirmed_by_dest_compute(cls, context, confirm_window, def get_unconfirmed_by_dest_compute(cls, context, confirm_window,
dest_compute): dest_compute):

View File

@@ -251,6 +251,10 @@ def _make_pci_list(context, pci_list, db_list):
class PciDeviceList(base.ObjectListBase, base.NovaObject): class PciDeviceList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('PciDevice'),
}
def __init__(self): def __init__(self):
super(PciDeviceList, self).__init__() super(PciDeviceList, self).__init__()
self.objects = [] self.objects = []

View File

@@ -82,6 +82,10 @@ def _make_secgroup_list(context, secgroup_list, db_secgroup_list):
class SecurityGroupList(base.ObjectListBase, base.NovaObject): class SecurityGroupList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('SecurityGroup'),
}
def __init__(self): def __init__(self):
super(SecurityGroupList, self).__init__() super(SecurityGroupList, self).__init__()
self.objects = [] self.objects = []

View File

@@ -40,7 +40,7 @@ class Service(base.NovaPersistentObject, base.NovaObject):
'disabled': fields.BooleanField(), 'disabled': fields.BooleanField(),
'disabled_reason': fields.StringField(nullable=True), 'disabled_reason': fields.StringField(nullable=True),
'availability_zone': fields.StringField(nullable=True), 'availability_zone': fields.StringField(nullable=True),
'compute_node': fields.ObjectField(compute_node.ComputeNode), 'compute_node': fields.ObjectField('ComputeNode'),
} }
@staticmethod @staticmethod
@@ -124,6 +124,10 @@ class Service(base.NovaPersistentObject, base.NovaObject):
class ServiceList(base.ObjectListBase, base.NovaObject): class ServiceList(base.ObjectListBase, base.NovaObject):
fields = {
'objects': fields.ListOfObjectsField('Service'),
}
@base.remotable_classmethod @base.remotable_classmethod
def get_by_topic(cls, context, topic): def get_by_topic(cls, context, topic):
db_services = db.service_get_all_by_topic(context, topic) db_services = db.service_get_all_by_topic(context, topic)

View File

@@ -195,7 +195,7 @@ class TestObject(TestField):
test_inst = TestableObject() test_inst = TestableObject()
super(TestObject, self).setUp() super(TestObject, self).setUp()
self.field = fields.Field(fields.Object(TestableObject)) self.field = fields.Field(fields.Object('TestableObject'))
self.coerce_good_values = [(test_inst, test_inst)] self.coerce_good_values = [(test_inst, test_inst)]
self.coerce_bad_values = [OtherTestableObject(), 1, 'foo'] self.coerce_bad_values = [OtherTestableObject(), 1, 'foo']
self.to_primitive_values = [(test_inst, test_inst.obj_to_primitive())] self.to_primitive_values = [(test_inst, test_inst.obj_to_primitive())]

View File

@@ -240,8 +240,7 @@ class TestUtils(test.TestCase):
self.foo = foo self.foo = foo
class MyList(base.ObjectListBase, base.NovaObject): class MyList(base.ObjectListBase, base.NovaObject):
fields = {'objects': fields.Field(fields.List( fields = {'objects': fields.ListOfObjectsField('MyObjElement')}
fields.Field(fields.Object(MyObjElement))))}
mylist = MyList() mylist = MyList()
mylist.objects = [MyObjElement(1), MyObjElement(2), MyObjElement(3)] mylist.objects = [MyObjElement(1), MyObjElement(2), MyObjElement(3)]
@@ -257,7 +256,7 @@ class TestUtils(test.TestCase):
def test_obj_to_primitive_recursive(self): def test_obj_to_primitive_recursive(self):
class MyList(base.ObjectListBase, base.NovaObject): class MyList(base.ObjectListBase, base.NovaObject):
pass fields = {'objects': fields.ListOfObjectsField('MyObj')}
mylist = MyList() mylist = MyList()
mylist.objects = [MyObj(), MyObj()] mylist.objects = [MyObj(), MyObj()]
@@ -686,8 +685,7 @@ class TestObjectListBase(test.TestCase):
self.foo = foo self.foo = foo
class Foo(base.ObjectListBase, base.NovaObject): class Foo(base.ObjectListBase, base.NovaObject):
fields = {'objects': fields.Field(fields.List( fields = {'objects': fields.ListOfObjectsField('MyElement')}
fields.Field(fields.Object(MyElement))))}
objlist = Foo() objlist = Foo()
objlist._context = 'foo' objlist._context = 'foo'
@@ -703,7 +701,7 @@ class TestObjectListBase(test.TestCase):
def test_serialization(self): def test_serialization(self):
class Foo(base.ObjectListBase, base.NovaObject): class Foo(base.ObjectListBase, base.NovaObject):
pass fields = {'objects': fields.ListOfObjectsField('Bar')}
class Bar(base.NovaObject): class Bar(base.NovaObject):
fields = {'foo': fields.Field(fields.String())} fields = {'foo': fields.Field(fields.String())}