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:
parent
c8b413696a
commit
58556d2a16
|
@ -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)
|
||||||
|
|
|
@ -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. "
|
||||||
|
|
|
@ -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):
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue