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
This commit is contained in:
Xing Yang 2015-04-15 15:33:59 -04:00
parent c8b413696a
commit 58556d2a16
4 changed files with 72 additions and 19 deletions

View File

@ -393,7 +393,7 @@ class EMCVMAXCommonData(object):
'project_id': 'project_id':
'project', 'id': '2', 'project', 'id': '2',
'provider_location': 'provider_location':
six.text_type(provider_location), six.text_type(provider_location),
'display_description': 'snapshot source volume'} 'display_description': 'snapshot source volume'}
test_CG = {'name': 'myCG1', test_CG = {'name': 'myCG1',
@ -2661,6 +2661,51 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
self.driver.delete_cgsnapshot( self.driver.delete_cgsnapshot(
self.data.test_ctxt, self.data.test_CG_snapshot) 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): def _cleanup(self):
if self.config_file_path: if self.config_file_path:
bExists = os.path.exists(self.config_file_path) bExists = os.path.exists(self.config_file_path)

View File

@ -2671,41 +2671,47 @@ class EMCVMAXCommon(object):
return memberInstanceNames return memberInstanceNames
def _create_composite_volume( def _create_composite_volume(
self, volume, volumeName, volumeSize, extraSpecs): self, volume, volumeName, volumeSize, extraSpecs,
memberCount=None):
"""Create a composite volume (V2). """Create a composite volume (V2).
:param volume: the volume object :param volume: the volume object
:param volumeName: the name of the volume :param volumeName: the name of the volume
:param volumeSize: the size of the volume :param volumeSize: the size of the volume
:param extraSpecs: extra specifications :param extraSpecs: extra specifications
:param memberCount: the number of meta members in a composite volume
:returns: int -- return code :returns: int -- return code
:returns: dict -- volumeDict :returns: dict -- volumeDict
:returns: string -- storageSystemName :returns: string -- storageSystemName
:raises: VolumeBackendAPIException :raises: VolumeBackendAPIException
""" """
memberCount, errorDesc = self.utils.determine_member_count( if not memberCount:
volume['size'], extraSpecs[MEMBERCOUNT], memberCount, errorDesc = self.utils.determine_member_count(
extraSpecs[COMPOSITETYPE]) volume['size'], extraSpecs[MEMBERCOUNT],
if errorDesc is not None: extraSpecs[COMPOSITETYPE])
exceptionMessage = (_("The striped meta count of %(memberCount)s " if errorDesc is not None:
"is too small for volume: %(volumeName)s " exceptionMessage = (_("The striped meta count of "
"with size %(volumeSize)s.") "%(memberCount)s is too small for "
% {'memberCount': memberCount, "volume: %(volumeName)s, "
'volumeName': volumeName, "with size %(volumeSize)s.")
'volumeSize': volume['size']}) % {'memberCount': memberCount,
LOG.error(exceptionMessage) 'volumeName': volumeName,
raise exception.VolumeBackendAPIException(data=exceptionMessage) 'volumeSize': volume['size']})
LOG.error(exceptionMessage)
raise exception.VolumeBackendAPIException(
data=exceptionMessage)
poolInstanceName, storageSystemName = ( poolInstanceName, storageSystemName = (
self._get_pool_and_storage_system(extraSpecs)) self._get_pool_and_storage_system(extraSpecs))
LOG.debug("Create Volume: %(volume)s Pool: %(pool)s " LOG.debug("Create Volume: %(volume)s Pool: %(pool)s "
"Storage System: %(storageSystem)s " "Storage System: %(storageSystem)s "
"Size: %(size)lu.", "Size: %(size)lu MemberCount: %(memberCount)s.",
{'volume': volumeName, {'volume': volumeName,
'pool': poolInstanceName, 'pool': poolInstanceName,
'storageSystem': storageSystemName, 'storageSystem': storageSystemName,
'size': volumeSize}) 'size': volumeSize,
'memberCount': memberCount})
elementCompositionService = ( elementCompositionService = (
self.utils.find_element_composition_service(self.conn, self.utils.find_element_composition_service(self.conn,
@ -3483,7 +3489,7 @@ class EMCVMAXCommon(object):
_rc, baseVolumeDict, storageSystemName = ( _rc, baseVolumeDict, storageSystemName = (
self._create_composite_volume( self._create_composite_volume(
volume, baseVolumeName, volumeSizeInbits, volume, baseVolumeName, volumeSizeInbits,
extraSpecs)) extraSpecs, 1))
baseTargetVolumeInstance = self.utils.find_volume_instance( baseTargetVolumeInstance = self.utils.find_volume_instance(
self.conn, baseVolumeDict, baseVolumeName) self.conn, baseVolumeDict, baseVolumeName)
LOG.debug("Base target volume %(targetVol)s created. " LOG.debug("Base target volume %(targetVol)s created. "

View File

@ -34,9 +34,10 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver):
performance enhancement. performance enhancement.
2.0.0 - Add driver requirement functions 2.0.0 - Add driver requirement functions
2.1.0 - Add consistency group 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): def __init__(self, *args, **kwargs):

View File

@ -42,9 +42,10 @@ class EMCVMAXISCSIDriver(driver.ISCSIDriver):
performance enhancement. performance enhancement.
2.0.0 - Add driver requirement functions 2.0.0 - Add driver requirement functions
2.1.0 - Add consistency group 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): def __init__(self, *args, **kwargs):