]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Sort snapshots in create CG from CG snapshot
authorXing Yang <xing.yang@emc.com>
Wed, 11 Mar 2015 04:42:16 +0000 (00:42 -0400)
committerXing Yang <xing.yang@emc.com>
Wed, 11 Mar 2015 17:09:10 +0000 (13:09 -0400)
This problem was discovered while testing create CG from CG snapshot.
In create_consistencygroup_from_src() in manager.py, it calls the driver
method create_consistencygroup_from_src() and passes in parameters
including source snapshots and target volumes. The problem is that the
snapshots list is not sorted to be in the same order as their corresponding
volumes. So they may be in the wrong order.

In this patch, the source snapshots were sorted before being passed to
the driver.

Change-Id: I988ce2836f2d553391deeee6e68738356877109b
Closes-Bug: #1430628

cinder/tests/test_volume.py
cinder/volume/manager.py

index 3837900187ac4a1d9f7c83ea38855188a0c41193..42e66bb52e7ca6aca7a0c9b9d1b8a77358f47907 100644 (file)
@@ -3834,6 +3834,51 @@ class VolumeTestCase(BaseVolumeTestCase):
         self.volume.delete_cgsnapshot(self.context, cgsnapshot_id)
         self.volume.delete_consistencygroup(self.context, group_id)
 
+    def test_sort_snapshots(self):
+        vol1 = {'id': '1', 'name': 'volume 1',
+                'snapshot_id': '1',
+                'consistencygroup_id': '1'}
+        vol2 = {'id': '2', 'name': 'volume 2',
+                'snapshot_id': '2',
+                'consistencygroup_id': '1'}
+        vol3 = {'id': '3', 'name': 'volume 3',
+                'snapshot_id': '3',
+                'consistencygroup_id': '1'}
+        snp1 = {'id': '1', 'name': 'snap 1',
+                'cgsnapshot_id': '1'}
+        snp2 = {'id': '2', 'name': 'snap 2',
+                'cgsnapshot_id': '1'}
+        snp3 = {'id': '3', 'name': 'snap 3',
+                'cgsnapshot_id': '1'}
+        volumes = []
+        snapshots = []
+        volumes.append(vol1)
+        volumes.append(vol2)
+        volumes.append(vol3)
+        snapshots.append(snp2)
+        snapshots.append(snp3)
+        snapshots.append(snp1)
+        i = 0
+        for vol in volumes:
+            snap = snapshots[i]
+            i += 1
+            self.assertNotEqual(vol['snapshot_id'], snap['id'])
+        sorted_snaps = self.volume._sort_snapshots(volumes, snapshots)
+        i = 0
+        for vol in volumes:
+            snap = sorted_snaps[i]
+            i += 1
+            self.assertEqual(vol['snapshot_id'], snap['id'])
+
+        snapshots[2]['id'] = '9999'
+        self.assertRaises(exception.SnapshotNotFound,
+                          self.volume._sort_snapshots,
+                          volumes, snapshots)
+
+        self.assertRaises(exception.InvalidInput,
+                          self.volume._sort_snapshots,
+                          volumes, [])
+
     @staticmethod
     def _create_cgsnapshot(group_id, volume_id, size='0'):
         """Create a cgsnapshot object."""
index e009f71f18147530c9e4b651c5cab8bc8acdd4d8..92cb31db0c50a14be086e221c1d275075ffad516 100644 (file)
@@ -1832,6 +1832,9 @@ class VolumeManager(manager.SchedulerDependentManager):
                                     'valid': VALID_CREATE_CG_SRC_SNAP_STATUS})
                             raise exception.InvalidConsistencyGroup(reason=msg)
 
+            # Sort source snapshots so that they are in the same order as their
+            # corresponding target volumes.
+            sorted_snapshots = self._sort_snapshots(volumes, snapshots)
             self._notify_about_consistencygroup_usage(
                 context, group_ref, "create.start")
 
@@ -1843,7 +1846,8 @@ class VolumeManager(manager.SchedulerDependentManager):
                       'snap': cgsnapshot_id})
             model_update, volumes_model_update = (
                 self.driver.create_consistencygroup_from_src(
-                    context, group_ref, volumes, cgsnapshot, snapshots))
+                    context, group_ref, volumes, cgsnapshot,
+                    sorted_snapshots))
 
             if volumes_model_update:
                 for update in volumes_model_update:
@@ -1890,6 +1894,29 @@ class VolumeManager(manager.SchedulerDependentManager):
 
         return group_ref['id']
 
+    def _sort_snapshots(self, volumes, snapshots):
+        # Sort source snapshots so that they are in the same order as their
+        # corresponding target volumes. Each source snapshot in the snapshots
+        # list should have a corresponding target volume in the volumes list.
+        if not volumes or not snapshots or len(volumes) != len(snapshots):
+            msg = _("Input volumes or snapshots are invalid.")
+            LOG.error(msg)
+            raise exception.InvalidInput(reason=msg)
+
+        sorted_snapshots = []
+        for vol in volumes:
+            found_snaps = filter(
+                lambda snap: snap['id'] == vol['snapshot_id'], snapshots)
+            if not found_snaps:
+                LOG.error(_LE("Source snapshot cannot be found for target "
+                              "volume %(volume_id)s."),
+                          {'volume_id': vol['id']})
+                raise exception.SnapshotNotFound(
+                    snapshot_id=vol['snapshot_id'])
+            sorted_snapshots.extend(found_snaps)
+
+        return sorted_snapshots
+
     def _update_volume_from_src(self, context, vol, update, group_id=None):
         try:
             snapshot_ref = self.db.snapshot_get(context,