Add backref relationships to ConsistencyGroup obj

ConsistencyGroup object was missing relationships that were defined on
the SQLAlchemy model as backrefs. This includes volumes and cgsnapshots
fields. This commit adds fields representing these relationships.

Change-Id: Ia74997ddfed1e472874b6892c2fcaa208b7a9a3c
Partial-Bug: 1509012
This commit is contained in:
Michał Dulko
2015-10-22 18:25:22 +02:00
parent 49507b61cb
commit b3f3747654
5 changed files with 126 additions and 4 deletions

View File

@@ -25,8 +25,8 @@ def register_all():
# function in order for it to be registered by services that may
# need to receive it via RPC.
__import__('cinder.objects.backup')
__import__('cinder.objects.consistencygroup')
__import__('cinder.objects.cgsnapshot')
__import__('cinder.objects.consistencygroup')
__import__('cinder.objects.service')
__import__('cinder.objects.snapshot')
__import__('cinder.objects.volume')

View File

@@ -19,11 +19,15 @@ from cinder import objects
from cinder.objects import base
from oslo_versionedobjects import fields
OPTIONAL_FIELDS = ['cgsnapshots', 'volumes']
@base.CinderObjectRegistry.register
class ConsistencyGroup(base.CinderPersistentObject, base.CinderObject,
base.CinderObjectDictCompat):
VERSION = '1.0'
# Version 1.0: Initial version
# Version 1.1: Added cgsnapshots and volumes relationships
VERSION = '1.1'
fields = {
'id': fields.UUIDField(),
@@ -37,14 +41,35 @@ class ConsistencyGroup(base.CinderPersistentObject, base.CinderObject,
'status': fields.StringField(nullable=True),
'cgsnapshot_id': fields.UUIDField(nullable=True),
'source_cgid': fields.UUIDField(nullable=True),
'cgsnapshots': fields.ObjectField('CGSnapshotList', nullable=True),
'volumes': fields.ObjectField('VolumeList', nullable=True),
}
@staticmethod
def _from_db_object(context, consistencygroup, db_consistencygroup):
def _from_db_object(context, consistencygroup, db_consistencygroup,
expected_attrs=None):
if expected_attrs is None:
expected_attrs = []
for name, field in consistencygroup.fields.items():
if name in OPTIONAL_FIELDS:
continue
value = db_consistencygroup.get(name)
setattr(consistencygroup, name, value)
if 'cgsnapshots' in expected_attrs:
cgsnapshots = base.obj_make_list(
context, objects.CGSnapshotsList(context),
objects.CGSnapshot,
db_consistencygroup['cgsnapshots'])
consistencygroup.cgsnapshots = cgsnapshots
if 'volumes' in expected_attrs:
volumes = base.obj_make_list(
context, objects.VolumeList(context),
objects.Volume,
db_consistencygroup['volumes'])
consistencygroup.cgsnapshots = volumes
consistencygroup._context = context
consistencygroup.obj_reset_changes()
return consistencygroup
@@ -55,14 +80,49 @@ class ConsistencyGroup(base.CinderPersistentObject, base.CinderObject,
raise exception.ObjectActionError(action='create',
reason=_('already_created'))
updates = self.cinder_obj_get_changes()
if 'cgsnapshots' in updates:
raise exception.ObjectActionError(action='create',
reason=_('cgsnapshots assigned'))
if 'volumes' in updates:
raise exception.ObjectActionError(action='create',
reason=_('volumes assigned'))
db_consistencygroups = db.consistencygroup_create(self._context,
updates)
self._from_db_object(self._context, self, db_consistencygroups)
def obj_load_attr(self, attrname):
if attrname not in OPTIONAL_FIELDS:
raise exception.ObjectActionError(
action='obj_load_attr',
reason=_('attribute %s not lazy-loadable') % attrname)
if not self._context:
raise exception.OrphanedObjectError(method='obj_load_attr',
objtype=self.obj_name())
if attrname == 'cgsnapshots':
self.cgsnapshots = objects.CGSnapshotList.get_all_by_group(
self._context, self.id)
if attrname == 'volumes':
self.volumes = objects.VolumeList.get_all_by_group(self._context,
self.id)
self.obj_reset_changes(fields=[attrname])
@base.remotable
def save(self):
updates = self.cinder_obj_get_changes()
if updates:
if 'cgsnapshots' in updates:
raise exception.ObjectActionError(
action='save', reason=_('cgsnapshots changed'))
if 'volumes' in updates:
raise exception.ObjectActionError(
action='save', reason=_('volumes changed'))
db.consistencygroup_update(self._context, self.id, updates)
self.obj_reset_changes()

View File

@@ -23,6 +23,7 @@ def fake_db_consistencygroup(**updates):
'user_id': '2',
'project_id': '3',
'host': 'FakeHost',
'volumes': [],
}
for name, field in objects.ConsistencyGroup.fields.items():
if name in db_values:

View File

@@ -32,6 +32,16 @@ fake_consistencygroup = {
'source_cgid': None,
}
fake_cgsnapshot = {
'id': '1',
'user_id': 'fake_user_id',
'project_id': 'fake_project_id',
'name': 'fake_name',
'description': 'fake_description',
'status': 'creating',
'consistencygroup_id': 'fake_id',
}
class TestConsistencyGroup(test_objects.BaseObjectsTestCase):
@@ -74,6 +84,57 @@ class TestConsistencyGroup(test_objects.BaseObjectsTestCase):
consistencygroup.id,
{'status': 'active'})
def test_save_with_cgsnapshots(self):
consistencygroup = objects.ConsistencyGroup._from_db_object(
self.context, objects.ConsistencyGroup(), fake_consistencygroup)
cgsnapshots_objs = [objects.CGSnapshot(context=self.context, id=i)
for i in [3, 4, 5]]
cgsnapshots = objects.CGSnapshotList(objects=cgsnapshots_objs)
consistencygroup.name = 'foobar'
consistencygroup.cgsnapshots = cgsnapshots
self.assertEqual({'name': 'foobar',
'cgsnapshots': cgsnapshots},
consistencygroup.obj_get_changes())
self.assertRaises(exception.ObjectActionError, consistencygroup.save)
def test_save_with_volumes(self):
consistencygroup = objects.ConsistencyGroup._from_db_object(
self.context, objects.ConsistencyGroup(), fake_consistencygroup)
volumes_objs = [objects.Volume(context=self.context, id=i)
for i in [3, 4, 5]]
volumes = objects.VolumeList(objects=volumes_objs)
consistencygroup.name = 'foobar'
consistencygroup.volumes = volumes
self.assertEqual({'name': 'foobar',
'volumes': volumes},
consistencygroup.obj_get_changes())
self.assertRaises(exception.ObjectActionError, consistencygroup.save)
@mock.patch('cinder.objects.cgsnapshot.CGSnapshotList.get_all_by_group')
@mock.patch('cinder.objects.volume.VolumeList.get_all_by_group')
def test_obj_load_attr(self, mock_vol_get_all_by_group,
mock_cgsnap_get_all_by_group):
consistencygroup = objects.ConsistencyGroup._from_db_object(
self.context, objects.ConsistencyGroup(), fake_consistencygroup)
# Test cgsnapshots lazy-loaded field
cgsnapshots_objs = [objects.CGSnapshot(context=self.context, id=i)
for i in [3, 4, 5]]
cgsnapshots = objects.CGSnapshotList(context=self.context,
objects=cgsnapshots_objs)
mock_cgsnap_get_all_by_group.return_value = cgsnapshots
self.assertEqual(cgsnapshots, consistencygroup.cgsnapshots)
mock_cgsnap_get_all_by_group.assert_called_once_with(
self.context, consistencygroup.id)
# Test volumes lazy-loaded field
volume_objs = [objects.Volume(context=self.context, id=i)
for i in [3, 4, 5]]
volumes = objects.VolumeList(context=self.context, objects=volume_objs)
mock_vol_get_all_by_group.return_value = volumes
self.assertEqual(volumes, consistencygroup.volumes)
mock_vol_get_all_by_group.assert_called_once_with(self.context,
consistencygroup.id)
@mock.patch('cinder.db.consistencygroup_destroy')
def test_destroy(self, consistencygroup_destroy):
consistencygroup = objects.ConsistencyGroup(context=self.context,

View File

@@ -26,7 +26,7 @@ object_data = {
'BackupList': '1.0-24591dabe26d920ce0756fe64cd5f3aa',
'CGSnapshot': '1.0-190da2a2aa9457edc771d888f7d225c4',
'CGSnapshotList': '1.0-e8c3f4078cd0ee23487b34d173eec776',
'ConsistencyGroup': '1.0-b9bad093daee0b259edddb3993c60c31',
'ConsistencyGroup': '1.1-8d8b867a67c1bd6e9f840bcf5e375dbb',
'ConsistencyGroupList': '1.0-09d0aad5491e762ecfdf66bef02ceb8d',
'Service': '1.0-64baeb4911dbab1153064dd1c87edb9f',
'ServiceList': '1.0-d242d3384b68e5a5a534e090ff1d5161',