From 95f34962cb82d03a86e9a653fb249976e57331ea Mon Sep 17 00:00:00 2001 From: Tina Date: Thu, 13 Aug 2015 23:10:53 -0400 Subject: [PATCH] Clone cg support in VNX driver 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 | 254 ++++++++++++++++++--- cinder/volume/drivers/emc/emc_cli_fc.py | 5 +- cinder/volume/drivers/emc/emc_cli_iscsi.py | 5 +- cinder/volume/drivers/emc/emc_vnx_cli.py | 119 +++++++--- 4 files changed, 308 insertions(+), 75 deletions(-) diff --git a/cinder/tests/unit/test_emc_vnxdirect.py b/cinder/tests/unit/test_emc_vnxdirect.py index e560a65e5..e1fcdd5e4 100644 --- a/cinder/tests/unit/test_emc_vnxdirect.py +++ b/cinder/tests/unit/test_emc_vnxdirect.py @@ -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 diff --git a/cinder/volume/drivers/emc/emc_cli_fc.py b/cinder/volume/drivers/emc/emc_cli_fc.py index d235c7db4..95118dc53 100644 --- a/cinder/volume/drivers/emc/emc_cli_fc.py +++ b/cinder/volume/drivers/emc/emc_cli_fc.py @@ -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): diff --git a/cinder/volume/drivers/emc/emc_cli_iscsi.py b/cinder/volume/drivers/emc/emc_cli_iscsi.py index 236a59031..7fa8e1c71 100644 --- a/cinder/volume/drivers/emc/emc_cli_iscsi.py +++ b/cinder/volume/drivers/emc/emc_cli_iscsi.py @@ -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): diff --git a/cinder/volume/drivers/emc/emc_vnx_cli.py b/cinder/volume/drivers/emc/emc_vnx_cli.py index dbcc281bc..18d7e0f45 100644 --- a/cinder/volume/drivers/emc/emc_vnx_cli.py +++ b/cinder/volume/drivers/emc/emc_vnx_cli.py @@ -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'] -- 2.45.2