objects: in get_object(s), filter by fields, not model attributes

This is needed for objects that have fields that have different names
comparing to corresponding attributes in the database. Updated test
cases to reflect that behaviour (pass field filters into object
get_object(s), but expect db_api functions to receive and return model
attributes).

Partially-Implements: blueprint adopt-oslo-versioned-objects-for-db
Change-Id: Ib65922eeaa9573312e3428c748ff415ef600052c
This commit is contained in:
Ihar Hrachyshka 2016-06-08 19:04:56 +02:00
parent 9e7137f7f6
commit d4012705de
4 changed files with 37 additions and 22 deletions

View File

@ -276,7 +276,10 @@ class NeutronDbObject(NeutronObject):
missing_keys=missing_keys)
with db_api.autonested_transaction(context.session):
db_obj = obj_db_api.get_object(context, cls.db_model, **kwargs)
db_obj = obj_db_api.get_object(
context, cls.db_model,
**cls.modify_fields_to_db(kwargs)
)
if db_obj:
return cls._load_object(context, db_obj)
@ -294,7 +297,9 @@ class NeutronDbObject(NeutronObject):
cls.validate_filters(**kwargs)
with db_api.autonested_transaction(context.session):
db_objs = obj_db_api.get_objects(
context, cls.db_model, _pager=_pager, **kwargs)
context, cls.db_model, _pager=_pager,
**cls.modify_fields_to_db(kwargs)
)
return [cls._load_object(context, db_obj) for db_obj in db_objs]
@classmethod
@ -371,7 +376,7 @@ class NeutronDbObject(NeutronObject):
keys = {}
for key in self.primary_keys:
keys[key] = getattr(self, key)
return self.modify_fields_to_db(keys)
return keys
def update_nonidentifying_fields(self, obj_data, reset_changes=False):
"""Updates non-identifying fields of an object.
@ -400,9 +405,11 @@ class NeutronDbObject(NeutronObject):
db_obj = obj_db_api.update_object(
self.obj_context, self.db_model,
self.modify_fields_to_db(updates),
**self._get_composite_keys())
**self.modify_fields_to_db(
self._get_composite_keys()))
self.from_db_object(db_obj)
def delete(self):
obj_db_api.delete_object(self.obj_context, self.db_model,
**self._get_composite_keys())
**self.modify_fields_to_db(
self._get_composite_keys()))

View File

@ -36,8 +36,9 @@ class AllowedAddressPair(base.NeutronDbObject):
# TODO(mhickey): get rid of it once we switch the db model to using
# custom types.
def modify_fields_to_db(self, fields):
result = super(AllowedAddressPair, self).modify_fields_to_db(fields)
@classmethod
def modify_fields_to_db(cls, fields):
result = super(AllowedAddressPair, cls).modify_fields_to_db(fields)
if 'ip_address' in result:
result['ip_address'] = str(result['ip_address'])
if 'mac_address' in result:

View File

@ -63,12 +63,13 @@ class SubnetPool(base.NeutronDbObject):
]
return fields
def modify_fields_to_db(self, fields):
result = super(SubnetPool, self).modify_fields_to_db(fields)
@classmethod
def modify_fields_to_db(cls, fields):
result = super(SubnetPool, cls).modify_fields_to_db(fields)
if 'prefixes' in result:
result['prefixes'] = [
models.SubnetPoolPrefix(cidr=str(prefix),
subnetpool_id=self.id)
subnetpool_id=result['id'])
for prefix in result['prefixes']
]
return result
@ -152,8 +153,9 @@ class SubnetPoolPrefix(base.NeutronDbObject):
# TODO(ihrachys): get rid of it once we switch the db model to using CIDR
# custom type
def modify_fields_to_db(self, fields):
result = super(SubnetPoolPrefix, self).modify_fields_to_db(fields)
@classmethod
def modify_fields_to_db(cls, fields):
result = super(SubnetPoolPrefix, cls).modify_fields_to_db(fields)
if 'cidr' in result:
result['cidr'] = str(result['cidr'])
return result

View File

@ -310,8 +310,7 @@ class _BaseObjectTestCase(object):
if field not in obj_cls.synthetic_fields:
generator = FIELD_TYPE_VALUE_GENERATOR_MAP[type(field_obj)]
fields[field] = get_value(generator, ip_version)
obj = obj_cls(None, **fields)
return obj.modify_fields_to_db(fields)
return obj_cls.modify_fields_to_db(fields)
@classmethod
def generate_object_keys(cls, obj_cls):
@ -350,7 +349,8 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
self.assertTrue(self._is_test_class(obj))
self.assertEqual(self.obj_fields[0], get_obj_db_fields(obj))
get_object_mock.assert_called_once_with(
self.context, self._test_class.db_model, **obj_keys)
self.context, self._test_class.db_model,
**self._test_class.modify_fields_to_db(obj_keys))
def test_get_object_missing_object(self):
with mock.patch.object(obj_db_api, 'get_object', return_value=None):
@ -403,8 +403,10 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
self._validate_objects(self.db_objs, objs)
mock_calls = [
mock.call(self.context, self._test_class.db_model, _pager=None,
**self.valid_field_filter)
mock.call(
self.context, self._test_class.db_model, _pager=None,
**self._test_class.modify_fields_to_db(self.valid_field_filter)
)
]
mock_calls.extend(self._get_synthetic_fields_get_objects_calls(
[self.db_obj]))
@ -519,7 +521,8 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
@mock.patch.object(obj_db_api, 'update_object')
def test_update_changes(self, update_mock):
fields_to_update = self.get_updatable_fields(self.db_obj)
fields_to_update = self.get_updatable_fields(
self._test_class.modify_fields_from_db(self.db_obj))
if not fields_to_update:
self.skipTest('No updatable fields found in test class %r' %
self._test_class)
@ -532,13 +535,15 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
obj = self._test_class(self.context, **self.obj_fields[0])
# get new values and fix keys
update_mock.return_value = self.db_objs[1].copy()
for key, value in obj._get_composite_keys().items():
fixed_keys = self._test_class.modify_fields_to_db(
obj._get_composite_keys())
for key, value in fixed_keys.items():
update_mock.return_value[key] = value
obj.update()
update_mock.assert_called_once_with(
self.context, self._test_class.db_model,
fields_to_update,
**obj._get_composite_keys())
self._test_class.modify_fields_to_db(fields_to_update),
**fixed_keys)
@mock.patch.object(base.NeutronDbObject,
'_get_changed_persistent_fields',
@ -580,7 +585,7 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
self._check_equal(obj, self.obj_fields[0])
delete_mock.assert_called_once_with(
self.context, self._test_class.db_model,
**obj._get_composite_keys())
**self._test_class.modify_fields_to_db(obj._get_composite_keys()))
@mock.patch(OBJECTS_BASE_OBJ_FROM_PRIMITIVE)
def test_clean_obj_from_primitive(self, get_prim_m):