From 58556d2a16802444a325b7700eb11f8bf3f89b37 Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Wed, 15 Apr 2015 15:33:59 -0400 Subject: [PATCH] Fixed issue with mismatched config in VMAX driver When the source and target volumes have different meta device configurations, clone volume will fail. This patch fixed the problem. Closes-Bug: #1442376 Change-Id: If2f2c085596b0045d7af6762bddeb4cd59158a57 --- cinder/tests/unit/test_emc_vmax.py | 47 +++++++++++++++++++- cinder/volume/drivers/emc/emc_vmax_common.py | 38 +++++++++------- cinder/volume/drivers/emc/emc_vmax_fc.py | 3 +- cinder/volume/drivers/emc/emc_vmax_iscsi.py | 3 +- 4 files changed, 72 insertions(+), 19 deletions(-) diff --git a/cinder/tests/unit/test_emc_vmax.py b/cinder/tests/unit/test_emc_vmax.py index d335053b544..e7d0c6d48ed 100644 --- a/cinder/tests/unit/test_emc_vmax.py +++ b/cinder/tests/unit/test_emc_vmax.py @@ -393,7 +393,7 @@ class EMCVMAXCommonData(object): 'project_id': 'project', 'id': '2', 'provider_location': - six.text_type(provider_location), + six.text_type(provider_location), 'display_description': 'snapshot source volume'} test_CG = {'name': 'myCG1', @@ -2661,6 +2661,51 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase): self.driver.delete_cgsnapshot( self.data.test_ctxt, self.data.test_CG_snapshot) + # Bug https://bugs.launchpad.net/cinder/+bug/1442376 + @mock.patch.object( + emc_vmax_common.EMCVMAXCommon, + '_get_pool_and_storage_system', + return_value=(None, EMCVMAXCommonData.storage_system)) + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'get_meta_members_capacity_in_bit', + return_value=[1234567, 7654321]) + @mock.patch.object( + emc_vmax_utils.EMCVMAXUtils, + 'get_volume_meta_head', + return_value=[EMCVMAXCommonData.test_volume]) + @mock.patch.object( + FakeDB, + 'volume_get', + return_value=EMCVMAXCommonData.test_source_volume) + @mock.patch.object( + volume_types, + 'get_volume_type_extra_specs', + return_value={'volume_backend_name': 'ISCSINoFAST'}) + def test_create_clone_with_different_meta_sizes( + self, mock_volume_type, mock_volume, + mock_meta, mock_size, mock_pool): + self.data.test_volume['volume_name'] = "vmax-1234567" + common = self.driver.common + volumeDict = {'classname': u'Symm_StorageVolume', + 'keybindings': EMCVMAXCommonData.keybindings} + volume = {'size': 0L} + common.provision.create_volume_from_pool = ( + mock.Mock(return_value=(volumeDict, volume['size']))) + common.provision.get_volume_dict_from_job = ( + mock.Mock(return_value=volumeDict)) + + common._create_composite_volume = ( + mock.Mock(return_value=(0L, + volumeDict, + EMCVMAXCommonData.storage_system))) + + self.driver.create_cloned_volume(self.data.test_volume, + EMCVMAXCommonData.test_source_volume) + extraSpecs = self.driver.common._initial_setup(self.data.test_volume) + common._create_composite_volume.assert_called_with( + volume, "TargetBaseVol", 1234567, extraSpecs, 1) + def _cleanup(self): if self.config_file_path: bExists = os.path.exists(self.config_file_path) diff --git a/cinder/volume/drivers/emc/emc_vmax_common.py b/cinder/volume/drivers/emc/emc_vmax_common.py index 6cc4e34cccd..dd17b26457c 100644 --- a/cinder/volume/drivers/emc/emc_vmax_common.py +++ b/cinder/volume/drivers/emc/emc_vmax_common.py @@ -2671,41 +2671,47 @@ class EMCVMAXCommon(object): return memberInstanceNames def _create_composite_volume( - self, volume, volumeName, volumeSize, extraSpecs): + self, volume, volumeName, volumeSize, extraSpecs, + memberCount=None): """Create a composite volume (V2). :param volume: the volume object :param volumeName: the name of the volume :param volumeSize: the size of the volume :param extraSpecs: extra specifications + :param memberCount: the number of meta members in a composite volume :returns: int -- return code :returns: dict -- volumeDict :returns: string -- storageSystemName :raises: VolumeBackendAPIException """ - memberCount, errorDesc = self.utils.determine_member_count( - volume['size'], extraSpecs[MEMBERCOUNT], - extraSpecs[COMPOSITETYPE]) - if errorDesc is not None: - exceptionMessage = (_("The striped meta count of %(memberCount)s " - "is too small for volume: %(volumeName)s " - "with size %(volumeSize)s.") - % {'memberCount': memberCount, - 'volumeName': volumeName, - 'volumeSize': volume['size']}) - LOG.error(exceptionMessage) - raise exception.VolumeBackendAPIException(data=exceptionMessage) + if not memberCount: + memberCount, errorDesc = self.utils.determine_member_count( + volume['size'], extraSpecs[MEMBERCOUNT], + extraSpecs[COMPOSITETYPE]) + if errorDesc is not None: + exceptionMessage = (_("The striped meta count of " + "%(memberCount)s is too small for " + "volume: %(volumeName)s, " + "with size %(volumeSize)s.") + % {'memberCount': memberCount, + 'volumeName': volumeName, + 'volumeSize': volume['size']}) + LOG.error(exceptionMessage) + raise exception.VolumeBackendAPIException( + data=exceptionMessage) poolInstanceName, storageSystemName = ( self._get_pool_and_storage_system(extraSpecs)) LOG.debug("Create Volume: %(volume)s Pool: %(pool)s " "Storage System: %(storageSystem)s " - "Size: %(size)lu.", + "Size: %(size)lu MemberCount: %(memberCount)s.", {'volume': volumeName, 'pool': poolInstanceName, 'storageSystem': storageSystemName, - 'size': volumeSize}) + 'size': volumeSize, + 'memberCount': memberCount}) elementCompositionService = ( self.utils.find_element_composition_service(self.conn, @@ -3483,7 +3489,7 @@ class EMCVMAXCommon(object): _rc, baseVolumeDict, storageSystemName = ( self._create_composite_volume( volume, baseVolumeName, volumeSizeInbits, - extraSpecs)) + extraSpecs, 1)) baseTargetVolumeInstance = self.utils.find_volume_instance( self.conn, baseVolumeDict, baseVolumeName) LOG.debug("Base target volume %(targetVol)s created. " diff --git a/cinder/volume/drivers/emc/emc_vmax_fc.py b/cinder/volume/drivers/emc/emc_vmax_fc.py index d02aafc4b70..c56e5875253 100644 --- a/cinder/volume/drivers/emc/emc_vmax_fc.py +++ b/cinder/volume/drivers/emc/emc_vmax_fc.py @@ -34,9 +34,10 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver): performance enhancement. 2.0.0 - Add driver requirement functions 2.1.0 - Add consistency group functions + 2.1.1 - Fixed issue with mismatched config (bug #1442376) """ - VERSION = "2.1.0" + VERSION = "2.1.1" def __init__(self, *args, **kwargs): diff --git a/cinder/volume/drivers/emc/emc_vmax_iscsi.py b/cinder/volume/drivers/emc/emc_vmax_iscsi.py index eda1de19e8f..f2d49a7c65e 100644 --- a/cinder/volume/drivers/emc/emc_vmax_iscsi.py +++ b/cinder/volume/drivers/emc/emc_vmax_iscsi.py @@ -42,9 +42,10 @@ class EMCVMAXISCSIDriver(driver.ISCSIDriver): performance enhancement. 2.0.0 - Add driver requirement functions 2.1.0 - Add consistency group functions + 2.1.1 - Fixed issue with mismatched config (bug #1442376) """ - VERSION = "2.1.0" + VERSION = "2.1.1" def __init__(self, *args, **kwargs):