]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add backref relationships to ConsistencyGroup obj
authorMichał Dulko <michal.dulko@intel.com>
Thu, 22 Oct 2015 16:25:22 +0000 (18:25 +0200)
committerMichał Dulko <michal.dulko@intel.com>
Tue, 29 Dec 2015 15:09:40 +0000 (16:09 +0100)
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

cinder/objects/__init__.py
cinder/objects/consistencygroup.py
cinder/tests/unit/fake_consistencygroup.py
cinder/tests/unit/objects/test_consistencygroup.py
cinder/tests/unit/objects/test_objects.py

index f8c2ba4897cbd6844a5f8f485e2c16233804ffe2..10367843ae1f813c10edf16f1f104350fe11085a 100644 (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')
index a252c7f880e64ad526e4b2a8d3f06a5d26b09fcc..1c16fbc6e2f23efc782955954e4357dce4dfa5b6 100644 (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()
 
index 042321e0a839d3152340919d6863d4cfd28a36ce..280959c308bea5e0fe10ad0185f9a88b800bd91d 100644 (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:
index 9c66bb9cfafd8bb816d7ffaa4f550c8121dc1c2f..d4a5e1ffa123c94cf71fc48ea403ba51ffa7d704 100644 (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,
index 1348cb633d62930d5d273dfa98a21b503f5158d2..bf58eaf68f0d9d92b8447ed846580f24655945f4 100644 (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',