objects: fixed base to_dict implementation
The implementation was using wrong approach to detect field type, and it never triggered the actual code. Adopting the base class implementation for QoS policy object revealed the problem. Now, we fix the base class to_dict implementation for synthetic fields, and are able to adopt it for the policy object. Note that the bug in the base class was never exposed in production because no objects are currently relying on it. Change-Id: I3b8727fd3837b51cc1a778dc73d8a1e06f2de5a9 Partial-Bug: #1541928
This commit is contained in:
parent
8bccf9c2a5
commit
d503c830fb
|
@ -78,15 +78,20 @@ class NeutronObject(obj_base.VersionedObject,
|
|||
super(NeutronObject, self).__init__(context, **kwargs)
|
||||
self.obj_set_defaults()
|
||||
|
||||
def _synthetic_fields_items(self):
|
||||
for field in self.synthetic_fields:
|
||||
if field in self:
|
||||
yield field, getattr(self, field)
|
||||
|
||||
def to_dict(self):
|
||||
dict_ = dict(self.items())
|
||||
for field in self.synthetic_fields:
|
||||
if field in dict_:
|
||||
if isinstance(dict_[field], obj_fields.ListOfObjectsField):
|
||||
dict_[field] = [obj.to_dict() for obj in dict_[field]]
|
||||
elif isinstance(dict_[field], obj_fields.ObjectField):
|
||||
dict_[field] = (
|
||||
dict_[field].to_dict() if dict_[field] else None)
|
||||
for field_name, value in self._synthetic_fields_items():
|
||||
field = self.fields[field_name]
|
||||
if isinstance(field, obj_fields.ListOfObjectsField):
|
||||
dict_[field_name] = [obj.to_dict() for obj in value]
|
||||
elif isinstance(field, obj_fields.ObjectField):
|
||||
dict_[field_name] = (
|
||||
dict_[field_name].to_dict() if value else None)
|
||||
return dict_
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -61,12 +61,6 @@ class QosPolicy(base.NeutronDbObject):
|
|||
binding_models = {'network': network_binding_model,
|
||||
'port': port_binding_model}
|
||||
|
||||
def to_dict(self):
|
||||
dict_ = super(QosPolicy, self).to_dict()
|
||||
if 'rules' in dict_:
|
||||
dict_['rules'] = [rule.to_dict() for rule in dict_['rules']]
|
||||
return dict_
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
if attrname != 'rules':
|
||||
raise exceptions.ObjectActionError(
|
||||
|
|
|
@ -488,6 +488,39 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
|
|||
|
||||
self.assertRaises(base.NeutronObjectUpdateForbidden, obj.update)
|
||||
|
||||
def test_to_dict_synthetic_fields(self):
|
||||
cls_ = self._test_class
|
||||
object_fields = [
|
||||
field
|
||||
for field in cls_.synthetic_fields
|
||||
if cls_.is_object_field(field)
|
||||
]
|
||||
if not object_fields:
|
||||
self.skipTest(
|
||||
'No object fields found in test class %r' % cls_)
|
||||
|
||||
for field in object_fields:
|
||||
obj = cls_(self.context, **self.db_obj)
|
||||
objclasses = obj_base.VersionedObjectRegistry.obj_classes(
|
||||
).get(cls_.fields[field].objname)
|
||||
if not objclasses:
|
||||
# NOTE(ihrachys): this test does not handle fields of types
|
||||
# that are not registered (for example, QosRule)
|
||||
continue
|
||||
objclass = objclasses[0]
|
||||
child = objclass(
|
||||
self.context, **self.get_random_fields(obj_cls=objclass)
|
||||
)
|
||||
child_dict = child.to_dict()
|
||||
if isinstance(cls_.fields[field], obj_fields.ListOfObjectsField):
|
||||
setattr(obj, field, [child])
|
||||
dict_ = obj.to_dict()
|
||||
self.assertEqual([child_dict], dict_[field])
|
||||
else:
|
||||
setattr(obj, field, child)
|
||||
dict_ = obj.to_dict()
|
||||
self.assertEqual(child_dict, dict_[field])
|
||||
|
||||
|
||||
class BaseDbObjectNonStandardPrimaryKeyTestCase(BaseObjectIfaceTestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue