diff --git a/cinder/tests/unit/volume/drivers/emc/test_emc_vmax.py b/cinder/tests/unit/volume/drivers/emc/test_emc_vmax.py index a035d96f269..c132b8f9f86 100644 --- a/cinder/tests/unit/volume/drivers/emc/test_emc_vmax.py +++ b/cinder/tests/unit/volume/drivers/emc/test_emc_vmax.py @@ -6200,7 +6200,14 @@ class EMCV3DriverTestCase(test.TestCase): return_value=self.default_extraspec()) self.driver.delete_volume(self.data.test_volume_v3) - @unittest.skip("Skip until bug #1578986 is fixed") + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'get_v3_default_sg_instance_name', + return_value=(None, None, EMCVMAXCommonData.default_sg_instance_name)) + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'is_clone_licensed', + return_value=True) @mock.patch.object( emc_vmax_common.EMCVMAXCommon, '_get_pool_and_storage_system', @@ -6210,15 +6217,11 @@ class EMCV3DriverTestCase(test.TestCase): 'get_volume_type_extra_specs', return_value={'volume_backend_name': 'V3_BE'}) def test_create_snapshot_v3_success( - self, mock_type, mock_pool): + self, mock_type, mock_pool, mock_licence, mock_sg): common = self.driver.common - common.provisionv3.utils.get_v3_default_sg_instance_name = mock.Mock( - return_value=(None, None, self.data.default_sg_instance_name)) - common.utils.is_clone_licensed = ( - mock.Mock(return_value=True)) - common._initial_setup = mock.Mock( - return_value=self.default_extraspec()) - self.driver.create_snapshot(self.data.test_snapshot_v3) + with mock.patch.object(common, '_initial_setup', + return_value=self.default_extraspec()): + self.driver.create_snapshot(self.data.test_snapshot_v3) @mock.patch.object( volume_types, @@ -6230,7 +6233,18 @@ class EMCV3DriverTestCase(test.TestCase): return_value=self.default_extraspec()) self.driver.delete_snapshot(self.data.test_snapshot_v3) - @unittest.skip("Skip until bug #1578986 is fixed") + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'get_v3_default_sg_instance_name', + return_value=(None, None, EMCVMAXCommonData.default_sg_instance_name)) + @mock.patch.object( + emc_vmax_common.EMCVMAXCommon, + '_get_or_create_storage_group_v3', + return_value=EMCVMAXCommonData.default_sg_instance_name) + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'is_clone_licensed', + return_value=True) @mock.patch.object( emc_vmax_utils.EMCVMAXUtils, 'compare_size', @@ -6248,8 +6262,11 @@ class EMCV3DriverTestCase(test.TestCase): 'volume_get', return_value=EMCVMAXCommonData.test_source_volume) def test_create_cloned_volume_v3_success( - self, mock_volume_db, mock_type, mock_pool, mock_compare): - self.data.test_volume_v3['volume_name'] = "vmax-1234567" + self, mock_volume_db, mock_type, mock_pool, mock_compare, + mock_licence, mock_sg, mock_sg_name): + sourceVol = self.data.test_volume_v3.copy() + sourceVol['volume_name'] = "vmax-1234567" + sourceVol['size'] = 100 cloneVol = {} cloneVol['name'] = 'vol1' cloneVol['id'] = '10' @@ -6262,17 +6279,16 @@ class EMCV3DriverTestCase(test.TestCase): cloneVol['NumberOfBlocks'] = 100 cloneVol['BlockSize'] = self.data.block_size cloneVol['host'] = self.data.fake_host_v3 - cloneVol['size'] = 1 + cloneVol['size'] = 100 common = self.driver.common - common.utils.is_clone_licensed = ( - mock.Mock(return_value=True)) - common._initial_setup = mock.Mock( - return_value=self.default_extraspec()) - common._get_or_create_storage_group_v3 = mock.Mock( - return_value = self.data.default_sg_instance_name) - common.provisionv3.utils.get_v3_default_sg_instance_name = mock.Mock( - return_value=(None, None, self.data.default_sg_instance_name)) - self.driver.create_cloned_volume(cloneVol, self.data.test_volume_v3) + conn = FakeEcomConnection() + sourceInstance = ( + conn.EnumerateInstanceNames("EMC_StorageVolume")[0]) + with mock.patch.object(common, '_initial_setup', + return_value=self.default_extraspec()): + with mock.patch.object(common, '_find_lun', + return_value=sourceInstance): + self.driver.create_cloned_volume(cloneVol, sourceVol) @mock.patch.object( emc_vmax_common.EMCVMAXCommon, @@ -7703,7 +7719,11 @@ class EMCVMAXProvisionV3Test(test.TestCase): extraSpecs) self.assertEqual(self.data.default_sg_instance_name, newstoragegroup) - def test_create_element_replica(self): + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'get_v3_default_sg_instance_name', + return_value=(None, None, EMCVMAXCommonData.default_sg_instance_name)) + def test_create_element_replica(self, mock_sg): provisionv3 = self.driver.common.provisionv3 conn = FakeEcomConnection() repServiceInstanceName = { @@ -7718,8 +7738,6 @@ class EMCVMAXProvisionV3Test(test.TestCase): conn.EnumerateInstanceNames("EMC_StorageVolume")[0]) syncType = 7 cloneName = 'new_ss' - provisionv3.utils.get_v3_default_sg_instance_name = mock.Mock( - return_value=(None, None, self.data.default_sg_instance_name)) rc, job = provisionv3.create_element_replica( conn, repServiceInstanceName, cloneName, syncType, sourceInstance, extraSpecs) diff --git a/cinder/volume/drivers/emc/emc_vmax_common.py b/cinder/volume/drivers/emc/emc_vmax_common.py index e8dd71b6a5b..06a172db2f6 100644 --- a/cinder/volume/drivers/emc/emc_vmax_common.py +++ b/cinder/volume/drivers/emc/emc_vmax_common.py @@ -3914,6 +3914,7 @@ class EMCVMAXCommon(object): operation = self.utils.get_num(DISSOLVE_SNAPVX, '16') rsdInstance = None targetInstance = None + copyState = None if isSnapshot: rsdInstance = self.utils.set_target_element_supplier_in_rsd( self.conn, repServiceInstanceName, SNAPVX_REPLICATION_TYPE, @@ -3921,12 +3922,14 @@ class EMCVMAXCommon(object): else: targetInstance = self._create_duplicate_volume( sourceInstance, cloneName, extraSpecs) + copyState = self.utils.get_num(4, '16') try: _rc, job = ( self.provisionv3.create_element_replica( self.conn, repServiceInstanceName, cloneName, syncType, - sourceInstance, extraSpecs, targetInstance, rsdInstance)) + sourceInstance, extraSpecs, targetInstance, rsdInstance, + copyState)) except Exception: LOG.warning(_LW( "Clone failed on V3. Cleaning up the target volume. " diff --git a/cinder/volume/drivers/emc/emc_vmax_provision_v3.py b/cinder/volume/drivers/emc/emc_vmax_provision_v3.py index 9d0ec4c717f..2273b0a736f 100644 --- a/cinder/volume/drivers/emc/emc_vmax_provision_v3.py +++ b/cinder/volume/drivers/emc/emc_vmax_provision_v3.py @@ -234,7 +234,7 @@ class EMCVMAXProvisionV3(object): def create_element_replica( self, conn, repServiceInstanceName, cloneName, syncType, sourceInstance, extraSpecs, - targetInstance=None, rsdInstance=None): + targetInstance=None, rsdInstance=None, copyState=None): """Make SMI-S call to create replica for source element. :param conn: the connection to the ecom server @@ -284,7 +284,7 @@ class EMCVMAXProvisionV3(object): rc, job = self._create_element_replica_extra_params( conn, repServiceInstanceName, cloneName, syncType, sourceInstance, targetInstance, rsdInstance, - sgInstanceName) + sgInstanceName, copyState=copyState) if rc != 0: rc, errordesc = self.utils.wait_for_job_complete(conn, job, @@ -309,7 +309,8 @@ class EMCVMAXProvisionV3(object): def _create_element_replica_extra_params( self, conn, repServiceInstanceName, cloneName, syncType, - sourceInstance, targetInstance, rsdInstance, sgInstanceName): + sourceInstance, targetInstance, rsdInstance, sgInstanceName, + copyState=None): """CreateElementReplica using extra parameters. :param conn: the connection to the ecom server @@ -332,13 +333,6 @@ class EMCVMAXProvisionV3(object): SourceElement=sourceInstance.path, TargetElement=targetInstance.path, ReplicationSettingData=rsdInstance) - elif targetInstance: - rc, job = conn.InvokeMethod( - 'CreateElementReplica', repServiceInstanceName, - ElementName=cloneName, - SyncType=syncType, - SourceElement=sourceInstance.path, - TargetElement=targetInstance.path) elif rsdInstance: rc, job = conn.InvokeMethod( 'CreateElementReplica', repServiceInstanceName, @@ -347,7 +341,21 @@ class EMCVMAXProvisionV3(object): SourceElement=sourceInstance.path, ReplicationSettingData=rsdInstance, Collections=[sgInstanceName]) - + elif targetInstance and copyState: + rc, job = conn.InvokeMethod( + 'CreateElementReplica', repServiceInstanceName, + ElementName=cloneName, + SyncType=syncType, + SourceElement=sourceInstance.path, + TargetElement=targetInstance.path, + WaitForCopyState=copyState) + elif targetInstance: + rc, job = conn.InvokeMethod( + 'CreateElementReplica', repServiceInstanceName, + ElementName=cloneName, + SyncType=syncType, + SourceElement=sourceInstance.path, + TargetElement=targetInstance.path) return rc, job def break_replication_relationship(