]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Clone cg support in VNX driver
authorTina <tina.tang@emc.com>
Fri, 14 Aug 2015 03:10:53 +0000 (23:10 -0400)
committerTina <tina.tang@emc.com>
Wed, 7 Oct 2015 11:59:59 +0000 (11:59 +0000)
This change added the clone consistency group support
in VNX driver.

DocImpact
Implements: blueprint vnx-clone-cg
Change-Id: I7eb69be2e6ffe47a92bca5818c952addd1b45217

cinder/tests/unit/test_emc_vnxdirect.py
cinder/volume/drivers/emc/emc_cli_fc.py
cinder/volume/drivers/emc/emc_cli_iscsi.py
cinder/volume/drivers/emc/emc_vnx_cli.py

index e560a65e5242680c833d82a03f80a9b647ed1da6..e1fcdd5e43655fd3df477abf6adc905b5737f61d 100644 (file)
@@ -22,6 +22,7 @@ import six
 from cinder import context
 from cinder import exception
 from cinder import test
+from cinder.tests.unit import fake_consistencygroup
 from cinder.tests.unit import fake_snapshot
 from cinder.tests.unit import fake_volume
 from cinder.tests.unit import utils
@@ -3879,9 +3880,9 @@ Time Remaining:  0 second(s)
     def test_create_consistencygroup_from_cgsnapshot(self):
         output_migrate_verify = ('The specified source LUN '
                                  'is not currently migrating.', 23)
-        new_cg = self.testData.test_cg.copy()
-        new_cg.update(
-            {'id': 'new_cg_id'})
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        new_cg.id = 'new_cg_id'
         vol1_in_new_cg = self.testData.test_volume_cg.copy()
         vol1_in_new_cg.update(
             {'name': 'vol1_in_cg',
@@ -3897,18 +3898,24 @@ Time Remaining:  0 second(s)
         src_cgsnap = self.testData.test_cgsnapshot
         snap1_in_src_cgsnap = self.testData.test_member_cgsnapshot.copy()
         snap1_in_src_cgsnap.update(
-            {'volume': self.testData.test_volume,
-             'volume_name': 'src_vol1'})
+            {'volume': fake_volume.fake_volume_obj(
+             None, **self.testData.test_volume),
+             'expected_attrs': ['volume']})
+        snap1_in_src_cgsnap = fake_snapshot.fake_snapshot_obj(
+            None, **snap1_in_src_cgsnap)
         snap2_in_src_cgsnap = self.testData.test_member_cgsnapshot.copy()
         snap2_in_src_cgsnap.update(
-            {'volume': self.testData.test_volume2,
-             'volume_name': 'src_vol2'})
+            {'volume': fake_volume.fake_volume_obj(
+             None, **self.testData.test_volume2),
+             'expected_attrs': ['volume']})
+        snap2_in_src_cgsnap = fake_snapshot.fake_snapshot_obj(
+            None, **snap2_in_src_cgsnap)
         copied_snap_name = 'temp_snapshot_for_%s' % new_cg['id']
         td = self.testData
         commands = [td.SNAP_COPY_CMD(src_cgsnap['id'], copied_snap_name),
                     td.ALLOW_READWRITE_ON_SNAP_CMD(copied_snap_name),
                     td.SNAP_MP_CREATE_CMD(vol1_in_new_cg['name'],
-                                          snap1_in_src_cgsnap['volume_name']),
+                                          snap1_in_src_cgsnap.volume_name),
                     td.SNAP_ATTACH_CMD(vol1_in_new_cg['name'],
                                        copied_snap_name),
                     td.LUN_CREATION_CMD(vol1_in_new_cg['name'] + '_dest',
@@ -3919,7 +3926,7 @@ Time Remaining:  0 second(s)
                     td.MIGRATION_CMD(6231, 1),
 
                     td.SNAP_MP_CREATE_CMD(vol2_in_new_cg['name'],
-                                          snap2_in_src_cgsnap['volume_name']),
+                                          snap2_in_src_cgsnap.volume_name),
                     td.SNAP_ATTACH_CMD(vol2_in_new_cg['name'],
                                        copied_snap_name),
                     td.LUN_CREATION_CMD(vol2_in_new_cg['name'] + '_dest',
@@ -3963,7 +3970,7 @@ Time Remaining:  0 second(s)
             mock.call(*td.SNAP_COPY_CMD(src_cgsnap['id'], copied_snap_name)),
             mock.call(*td.ALLOW_READWRITE_ON_SNAP_CMD(copied_snap_name)),
             mock.call(*td.SNAP_MP_CREATE_CMD(vol1_in_new_cg['name'],
-                      snap1_in_src_cgsnap['volume_name']),
+                      snap1_in_src_cgsnap.volume_name),
                       poll=False),
             mock.call(*td.LUN_PROPERTY_ALL_CMD(vol1_in_new_cg['name']),
                       poll=True),
@@ -3979,7 +3986,7 @@ Time Remaining:  0 second(s)
             mock.call(*td.MIGRATION_CMD(6231, 1),
                       poll=True, retry_disable=True),
             mock.call(*td.SNAP_MP_CREATE_CMD(vol2_in_new_cg['name'],
-                      snap2_in_src_cgsnap['volume_name']),
+                      snap2_in_src_cgsnap.volume_name),
                       poll=False),
             mock.call(*td.LUN_PROPERTY_ALL_CMD(vol2_in_new_cg['name']),
                       poll=True),
@@ -4001,33 +4008,56 @@ Time Remaining:  0 second(s)
             mock.call(*td.DELETE_CG_SNAPSHOT(copied_snap_name))]
         self.assertEqual(expect_cmd, fake_cli.call_args_list)
 
-    def test_create_consistencygroup_from_othersource(self):
-        new_cg = self.testData.test_cg.copy()
-        new_cg.update(
-            {'id': 'new_cg_id'})
-        vol1_in_new_cg = self.testData.test_volume_cg.copy()
-        vol1_in_new_cg.update(
-            {'name': 'vol1_in_cg',
-             'id': '111111',
-             'consistencygroup_id': 'new_cg_id',
-             'provider_location': None})
-        vol2_in_new_cg = self.testData.test_volume_cg.copy()
-        vol2_in_new_cg.update(
-            {'name': 'vol2_in_cg',
-             'id': '222222',
-             'consistencygroup_id': 'new_cg_id',
-             'provider_location': None})
+    def test_create_cg_from_src_failed_without_source(self):
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        vol1_in_new_cg = self.testData.test_volume_cg
         self.driverSetup()
         self.assertRaises(
             exception.InvalidInput,
             self.driver.create_consistencygroup_from_src,
-            new_cg, [vol1_in_new_cg, vol2_in_new_cg],
+            new_cg, [vol1_in_new_cg],
             None, None, None, None)
 
+    def test_create_cg_from_src_failed_with_multiple_sources(self):
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        vol1_in_new_cg = self.testData.test_volume_cg
+        src_cgsnap = self.testData.test_cgsnapshot
+        snap1_in_src_cgsnap = fake_snapshot.fake_snapshot_obj(
+            None, **self.testData.test_member_cgsnapshot)
+        src_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        src_cg.id = 'fake_source_cg'
+        vol1_in_src_cg = {'id': 'fake_volume',
+                          'consistencygroup_id': src_cg.id}
+        self.driverSetup()
+        self.assertRaises(
+            exception.InvalidInput,
+            self.driver.create_consistencygroup_from_src,
+            new_cg, [vol1_in_new_cg],
+            src_cgsnap, [snap1_in_src_cgsnap], src_cg, [vol1_in_src_cg])
+
+    def test_create_cg_from_src_failed_with_invalid_source(self):
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        src_cgsnap = self.testData.test_cgsnapshot
+        vol1_in_new_cg = self.testData.test_volume_cg
+
+        src_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        src_cg.id = 'fake_source_cg'
+        self.driverSetup()
+        self.assertRaises(
+            exception.InvalidInput,
+            self.driver.create_consistencygroup_from_src,
+            new_cg, [vol1_in_new_cg],
+            src_cgsnap, None, src_cg, None)
+
     def test_create_cg_from_cgsnapshot_migrate_failed(self):
-        new_cg = self.testData.test_cg.copy()
-        new_cg.update(
-            {'id': 'new_cg_id'})
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        new_cg.id = 'new_cg_id'
         vol1_in_new_cg = self.testData.test_volume_cg.copy()
         vol1_in_new_cg.update(
             {'name': 'vol1_in_cg',
@@ -4043,12 +4073,18 @@ Time Remaining:  0 second(s)
         src_cgsnap = self.testData.test_cgsnapshot
         snap1_in_src_cgsnap = self.testData.test_member_cgsnapshot.copy()
         snap1_in_src_cgsnap.update(
-            {'volume': self.testData.test_volume,
-             'volume_name': 'src_vol1'})
+            {'volume': fake_volume.fake_volume_obj(
+             None, **self.testData.test_volume),
+             'expected_attrs': ['volume']})
+        snap1_in_src_cgsnap = fake_snapshot.fake_snapshot_obj(
+            None, **snap1_in_src_cgsnap)
         snap2_in_src_cgsnap = self.testData.test_member_cgsnapshot.copy()
         snap2_in_src_cgsnap.update(
-            {'volume': self.testData.test_volume2,
-             'volume_name': 'src_vol2'})
+            {'volume': fake_volume.fake_volume_obj(
+             None, **self.testData.test_volume2),
+             'expected_attrs': ['volume']})
+        snap2_in_src_cgsnap = fake_snapshot.fake_snapshot_obj(
+            None, **snap2_in_src_cgsnap)
         copied_snap_name = 'temp_snapshot_for_%s' % new_cg['id']
         td = self.testData
         commands = [td.LUN_PROPERTY_ALL_CMD(vol1_in_new_cg['name'] + '_dest'),
@@ -4086,6 +4122,154 @@ Time Remaining:  0 second(s)
             mock.call(*td.SNAP_DELETE_CMD(copied_snap_name), poll=True)]
         fake_cli.assert_has_calls(expect_cmd)
 
+    def test_create_consistencygroup_from_cg(self):
+        output_migrate_verify = ('The specified source LUN '
+                                 'is not currently migrating.', 23)
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        new_cg.id = 'new_cg_id'
+        vol1_in_new_cg = self.testData.test_volume_cg.copy()
+        vol1_in_new_cg.update(
+            {'name': 'vol1_in_cg',
+             'id': '111111',
+             'consistencygroup_id': 'new_cg_id',
+             'provider_location': None})
+        vol2_in_new_cg = self.testData.test_volume_cg.copy()
+        vol2_in_new_cg.update(
+            {'name': 'vol2_in_cg',
+             'id': '222222',
+             'consistencygroup_id': 'new_cg_id',
+             'provider_location': None})
+        src_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        src_cg.id = 'src_cg_id'
+        vol1_in_src_cg = self.testData.test_volume_cg.copy()
+        vol1_in_src_cg.update(
+            {'name': 'vol1_in_src_cg',
+             'id': '111110000',
+             'consistencygroup_id': 'src_cg_id',
+             'provider_location': None})
+        vol2_in_src_cg = self.testData.test_volume_cg.copy()
+        vol2_in_src_cg.update(
+            {'name': 'vol2_in_src_cg',
+             'id': '222220000',
+             'consistencygroup_id': 'src_cg_id',
+             'provider_location': None})
+        temp_snap_name = 'temp_snapshot_for_%s' % new_cg['id']
+        td = self.testData
+        commands = [td.CREATE_CG_SNAPSHOT(src_cg['id'], temp_snap_name),
+                    td.SNAP_MP_CREATE_CMD(vol1_in_new_cg['name'],
+                                          vol1_in_src_cg['name']),
+                    td.SNAP_ATTACH_CMD(vol1_in_new_cg['name'],
+                                       temp_snap_name),
+                    td.LUN_CREATION_CMD(vol1_in_new_cg['name'] + '_dest',
+                                        vol1_in_new_cg['size'],
+                                        'unit_test_pool', 'thin', None),
+                    td.LUN_PROPERTY_ALL_CMD(vol1_in_new_cg['name'] + '_dest'),
+                    td.LUN_PROPERTY_ALL_CMD(vol1_in_new_cg['name']),
+                    td.MIGRATION_CMD(6231, 1),
+
+                    td.SNAP_MP_CREATE_CMD(vol2_in_new_cg['name'],
+                                          vol2_in_src_cg['name']),
+                    td.SNAP_ATTACH_CMD(vol2_in_new_cg['name'],
+                                       temp_snap_name),
+                    td.LUN_CREATION_CMD(vol2_in_new_cg['name'] + '_dest',
+                                        vol2_in_new_cg['size'],
+                                        'unit_test_pool', 'thin', None),
+                    td.LUN_PROPERTY_ALL_CMD(vol2_in_new_cg['name'] + '_dest'),
+                    td.LUN_PROPERTY_ALL_CMD(vol2_in_new_cg['name']),
+                    td.MIGRATION_CMD(6232, 2),
+
+                    td.MIGRATION_VERIFY_CMD(6231),
+                    td.MIGRATION_VERIFY_CMD(6232),
+                    td.CREATE_CONSISTENCYGROUP_CMD(new_cg['id'], [6231, 6232]),
+                    td.DELETE_CG_SNAPSHOT(temp_snap_name)
+                    ]
+        results = [SUCCEED, SUCCEED, SUCCEED, SUCCEED,
+                   td.LUN_PROPERTY(vol1_in_new_cg['name'] + '_dest',
+                                   lunid=1),
+                   td.LUN_PROPERTY(vol1_in_new_cg['name'], lunid=6231),
+                   SUCCEED, SUCCEED, SUCCEED, SUCCEED,
+                   td.LUN_PROPERTY(vol2_in_new_cg['name'] + '_dest',
+                                   lunid=2),
+                   td.LUN_PROPERTY(vol2_in_new_cg['name'], lunid=6232),
+                   SUCCEED, output_migrate_verify, output_migrate_verify,
+                   SUCCEED, SUCCEED]
+
+        fake_cli = self.driverSetup(commands, results)
+
+        cg_model_update, volumes_model_update = (
+            self.driver.create_consistencygroup_from_src(
+                None, new_cg, [vol1_in_new_cg, vol2_in_new_cg],
+                cgsnapshot=None, snapshots=None,
+                source_cg=src_cg, source_vols=[vol1_in_src_cg,
+                                               vol2_in_src_cg]))
+        self.assertEqual(2, len(volumes_model_update))
+        self.assertTrue('id^%s' % 6231 in
+                        volumes_model_update[0]['provider_location'])
+        self.assertTrue('id^%s' % 6232 in
+                        volumes_model_update[1]['provider_location'])
+
+        delete_temp_snap_cmd = [
+            mock.call(*td.DELETE_CG_SNAPSHOT(temp_snap_name))]
+        fake_cli.assert_has_calls(delete_temp_snap_cmd)
+
+    @mock.patch.object(emc_vnx_cli, 'LOG')
+    @mock.patch.object(emc_vnx_cli.CommandLineHelper,
+                       'delete_cgsnapshot')
+    def test_delete_temp_cgsnapshot_failed_will_not_raise_exception(
+            self, mock_delete_cgsnapshot, mock_logger):
+        temp_snap_name = 'fake_temp'
+        self.driverSetup()
+        mock_delete_cgsnapshot.side_effect = exception.EMCVnxCLICmdError(
+            cmd='fake_cmd', rc=200, out='fake_output')
+        self.driver.cli._delete_temp_cgsnap(temp_snap_name)
+        mock_delete_cgsnapshot.assert_called_once_with(temp_snap_name)
+        self.assertTrue(mock_logger.warning.called)
+
+    @mock.patch.object(emc_vnx_cli.CreateSMPTask, 'execute',
+                       mock.Mock(side_effect=exception.EMCVnxCLICmdError(
+                           cmd='fake_cmd', rc=20, out='fake_output')))
+    @mock.patch.object(emc_vnx_cli.CreateSMPTask, 'revert',
+                       mock.Mock())
+    def test_create_consistencygroup_from_cg_roll_back(self):
+        new_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        new_cg.id = 'new_cg_id'
+        vol1_in_new_cg = self.testData.test_volume_cg.copy()
+        vol1_in_new_cg.update(
+            {'name': 'vol1_in_cg',
+             'id': '111111',
+             'consistencygroup_id': 'new_cg_id',
+             'provider_location': None})
+        src_cg = fake_consistencygroup.fake_consistencyobject_obj(
+            None, **self.testData.test_cg)
+        src_cg.id = 'src_cg_id'
+        vol1_in_src_cg = self.testData.test_volume_cg.copy()
+        vol1_in_src_cg.update(
+            {'name': 'vol1_in_src_cg',
+             'id': '111110000',
+             'consistencygroup_id': 'src_cg_id',
+             'provider_location': None})
+        temp_snap_name = 'temp_snapshot_for_%s' % new_cg['id']
+        td = self.testData
+        commands = [td.CREATE_CG_SNAPSHOT(src_cg['id'], temp_snap_name),
+                    td.DELETE_CG_SNAPSHOT(temp_snap_name)]
+        results = [SUCCEED, SUCCEED]
+
+        fake_cli = self.driverSetup(commands, results)
+
+        self.assertRaises(
+            exception.EMCVnxCLICmdError,
+            self.driver.create_consistencygroup_from_src,
+            None, new_cg, [vol1_in_new_cg],
+            cgsnapshot=None, snapshots=None,
+            source_cg=src_cg, source_vols=[vol1_in_src_cg])
+
+        rollback_cmd = [
+            mock.call(*td.DELETE_CG_SNAPSHOT(temp_snap_name))]
+        fake_cli.assert_has_calls(rollback_cmd)
+
     def test_deregister_initiator(self):
         fake_cli = self.driverSetup()
         self.driver.cli.destroy_empty_sg = True
index d235c7db4976831e32a119adac5f0d9a5f7cb5cd..95118dc5369086e2dabfdf847d419bd996fc85c3 100644 (file)
@@ -58,6 +58,7 @@ class EMCCLIFCDriver(driver.FibreChannelDriver):
                 White list target ports support
                 Snap copy support
                 Support efficient non-disruptive backup
+        7.0.0 - Clone consistency group support
     """
 
     def __init__(self, *args, **kwargs):
@@ -267,7 +268,9 @@ class EMCCLIFCDriver(driver.FibreChannelDriver):
                                                          group,
                                                          volumes,
                                                          cgsnapshot,
-                                                         snapshots)
+                                                         snapshots,
+                                                         source_cg,
+                                                         source_vols)
 
     def update_migrated_volume(self, context, volume, new_volume,
                                original_volume_status=None):
index 236a59031891f6bf99a28f93076cc1b8e7e7c75a..7fa8e1c71b7b078c0b950ec2839a72bffeb2b410 100644 (file)
@@ -56,6 +56,7 @@ class EMCCLIISCSIDriver(driver.ISCSIDriver):
                 White list target ports support
                 Snap copy support
                 Support efficient non-disruptive backup
+        7.0.0 - Clone consistency group support
     """
 
     def __init__(self, *args, **kwargs):
@@ -246,7 +247,9 @@ class EMCCLIISCSIDriver(driver.ISCSIDriver):
                                                          group,
                                                          volumes,
                                                          cgsnapshot,
-                                                         snapshots)
+                                                         snapshots,
+                                                         source_cg,
+                                                         source_vols)
 
     def update_migrated_volume(self, context, volume, new_volume,
                                original_volume_status=None):
index dbcc281bcda344a7d6f3eceef61c3a45a84d577d..18d7e0f45d1233ac13c87ce10eda4944bf7ba6a8 100644 (file)
@@ -759,10 +759,8 @@ class CommandLineHelper(object):
             LOG.info(_LI('Consistency group %s was deleted '
                          'successfully.'), cg_name)
 
-    def create_cgsnapshot(self, cgsnapshot):
+    def create_cgsnapshot(self, cg_name, snap_name):
         """Create a cgsnapshot (snap group)."""
-        cg_name = cgsnapshot['consistencygroup_id']
-        snap_name = cgsnapshot['id']
         create_cg_snap_cmd = ('-np', 'snap', '-create',
                               '-res', cg_name,
                               '-resType', 'CG',
@@ -1750,7 +1748,7 @@ class CommandLineHelper(object):
 class EMCVnxCliBase(object):
     """This class defines the functions to use the native CLI functionality."""
 
-    VERSION = '06.00.00'
+    VERSION = '07.00.00'
     stats = {'driver_version': VERSION,
              'storage_protocol': None,
              'vendor_name': 'EMC',
@@ -2749,7 +2747,8 @@ class EMCVnxCliBase(object):
                  {'group_name': cgsnapshot['consistencygroup_id']})
 
         try:
-            self._client.create_cgsnapshot(cgsnapshot)
+            self._client.create_cgsnapshot(cgsnapshot['consistencygroup_id'],
+                                           cgsnapshot['id'])
             for snapshot in snapshots:
                 snapshot['status'] = 'available'
         except Exception:
@@ -3437,17 +3436,49 @@ class EMCVnxCliBase(object):
         pass
 
     def create_consistencygroup_from_src(self, context, group, volumes,
-                                         cgsnapshot=None, snapshots=None):
+                                         cgsnapshot=None, snapshots=None,
+                                         source_cg=None, source_vols=None):
         """Creates a consistency group from cgsnapshot."""
+        if cgsnapshot and snapshots and not source_cg:
+            return self._create_consisgroup_from_cgsnapshot(
+                group, volumes, cgsnapshot, snapshots)
+        elif source_cg and source_vols and not cgsnapshot:
+            return self._clone_consisgroup(
+                group, volumes, source_cg, source_vols)
+        else:
+            msg = _("create_consistencygroup_from_src supports a "
+                    "cgsnapshot source or a consistency group source. "
+                    "Multiple sources cannot be used.")
+            raise exception.InvalidInput(reason=msg)
 
-        if not cgsnapshot or not snapshots:
-            msg = _("create_consistencygroup_from_src only supports a "
-                    "cgsnapshot source, other sources cannot be used.")
-            raise exception.InvalidInput(msg)
+    def _clone_consisgroup(self, group, volumes, source_cg, source_vols):
+        temp_cgsnapshot_name = 'temp_snapshot_for_{}'.format(group.id)
+        store_spec = {
+            'group': group,
+            'snapshot': {'id': temp_cgsnapshot_name,
+                         'consistencygroup_id': source_cg.id},
+            'snap_name': temp_cgsnapshot_name,
+            'source_lun_id': None,
+            'client': self._client
+        }
+        flow_name = 'clone_consisgroup'
+        snap_build_tasks = [CreateSnapshotTask()]
 
-        flow_name = 'create_consistencygroup_from_cgsnapshot'
-        work_flow = linear_flow.Flow(flow_name)
-        copied_snapshot_name = 'temp_snapshot_for_%s' % group['id']
+        volume_model_updates = self._create_cg_from_cgsnap_use_workflow(
+            flow_name, snap_build_tasks, store_spec,
+            volumes, source_vols)
+
+        self._delete_temp_cgsnap(temp_cgsnapshot_name)
+
+        LOG.info(_LI('Consistency group %(cg)s is created successfully.'),
+                 {'cg': group.id})
+
+        return None, volume_model_updates
+
+    def _create_consisgroup_from_cgsnapshot(self, group, volumes,
+                                            cgsnapshot, snapshots):
+        flow_name = 'create_consisgroup_from_cgsnapshot'
+        copied_snapshot_name = 'temp_snapshot_for_%s' % group.id
         store_spec = {
             'group': group,
             'src_snap_name': cgsnapshot['id'],
@@ -3455,29 +3486,55 @@ class EMCVnxCliBase(object):
             'client': self._client
         }
 
-        work_flow.add(CopySnapshotTask(),
-                      AllowReadWriteOnSnapshotTask())
+        snap_build_tasks = [CopySnapshotTask(),
+                            AllowReadWriteOnSnapshotTask()]
+
+        src_vols = map(lambda snap: snap.volume, snapshots)
+
+        volume_model_updates = self._create_cg_from_cgsnap_use_workflow(
+            flow_name, snap_build_tasks, store_spec, volumes, src_vols)
+
+        self._delete_temp_cgsnap(copied_snapshot_name)
+
+        LOG.info(_LI('Consistency group %(cg)s is created successfully.'),
+                 {'cg': group.id})
+
+        return None, volume_model_updates
+
+    def _delete_temp_cgsnap(self, snap):
+        try:
+            self._client.delete_cgsnapshot(snap)
+        except exception.EMCVnxCLICmdError as ex:
+            LOG.warning(_LW('Delete the temporary cgsnapshot %(name)s failed. '
+                            'This temporary cgsnapshot can be deleted '
+                            'manually. '
+                            'Message: %(msg)s'),
+                        {'name': snap,
+                         'msg': ex.kwargs['out']})
 
+    def _create_cg_from_cgsnap_use_workflow(self, flow_name, snap_build_tasks,
+                                            store_spec, volumes, source_vols):
+        work_flow = linear_flow.Flow(flow_name)
+        work_flow.add(*snap_build_tasks)
         # Add tasks for each volumes in the consistency group
         lun_id_key_template = 'new_lun_id_%s'
         lun_data_key_template = 'vol_%s'
         volume_model_updates = []
 
-        for i, (volume, snap) in enumerate(zip(volumes, snapshots)):
+        for i, (volume, src_volume) in enumerate(zip(volumes, source_vols)):
             specs = self.get_volumetype_extraspecs(volume)
-            provisioning, tiering, snapcopy = (
+            provisioning, tiering, snap_copy = (
                 self._get_and_validate_extra_specs(specs))
-            pool_name = self. get_target_storagepool(volume, snap['volume'])
+            pool_name = self.get_target_storagepool(volume, src_volume)
             sub_store_spec = {
                 'volume': volume,
-                'source_vol_name': snap['volume_name'],
+                'source_vol_name': src_volume['name'],
                 'pool_name': pool_name,
                 'dest_vol_name': volume['name'] + '_dest',
                 'volume_size': volume['size'],
                 'provisioning': provisioning,
                 'tiering': tiering,
                 'ignore_pool_full_threshold': self.ignore_pool_full_threshold,
-                'snapcopy': snapcopy
             }
             work_flow.add(
                 CreateSMPTask(name="CreateSMPTask%s" % i,
@@ -3508,26 +3565,11 @@ class EMCVnxCliBase(object):
         flow_engine = taskflow.engines.load(work_flow, store=store_spec)
         flow_engine.run()
 
-        # Delete copied snapshot
-        try:
-            self._client.delete_cgsnapshot(copied_snapshot_name)
-        except exception.EMCVnxCLICmdError as ex:
-            LOG.warning(_LW('Delete the temporary cgsnapshot %(name)s failed. '
-                            'This temporary cgsnapshot can be deleted '
-                            'manually. Consistency group %(cg)s is created '
-                            'successfully from cgsnapshot %(cgsnapshot)s. '
-                            'Message: %(msg)s'),
-                        {'name': copied_snapshot_name,
-                         'cg': group['id'],
-                         'cgsnapshot': cgsnapshot['id'],
-                         'msg': ex.kwargs['out']})
-
         for i, update in enumerate(volume_model_updates):
             new_lun_id = flow_engine.storage.fetch(lun_id_key_template % i)
             update['provider_location'] = (
                 self._build_provider_location(new_lun_id))
-
-        return None, volume_model_updates
+        return volume_model_updates
 
     def get_target_storagepool(self, volume, source_volume=None):
         pool = vol_utils.extract_host(volume['host'], 'pool')
@@ -3633,7 +3675,7 @@ class AttachSnapTask(task.Task):
 
     Reversion strategy: Detach the SMP.
     """
-    def execute(self, client, volume, snapcopy, snap_name,
+    def execute(self, client, volume, snap_name,
                 *args, **kwargs):
         LOG.debug('AttachSnapTask.execute')
         client.attach_mount_point(volume['name'], snap_name)
@@ -3733,7 +3775,8 @@ class CreateSnapshotTask(task.Task):
         LOG.debug('CreateSnapshotTask.execute')
         # Create temp Snapshot
         if snapshot['consistencygroup_id']:
-            client.create_cgsnapshot(snapshot)
+            client.create_cgsnapshot(snapshot['consistencygroup_id'],
+                                     snapshot['id'])
         else:
             snapshot_name = snapshot['name']
             volume_name = snapshot['volume_name']