Merge "Fix a problem with FAST support in VMAX driver"

This commit is contained in:
Jenkins 2015-05-20 00:25:48 +00:00 committed by Gerrit Code Review
commit 0acf257464
7 changed files with 283 additions and 97 deletions

View File

@ -24,6 +24,7 @@ from oslo_log import log as logging
import six
from cinder import exception
from cinder.i18n import _
from cinder.openstack.common import loopingcall
from cinder import test
from cinder.volume.drivers.emc import emc_vmax_common
@ -263,7 +264,8 @@ class EMCVMAXCommonData(object):
hardwareid_creationclass = 'EMC_StorageHardwareID'
replicationgroup_creationclass = 'CIM_ReplicationGroup'
storagepoolid = 'SYMMETRIX+000195900551+U+gold'
storagegroupname = 'OS_default_GOLD1_SG'
storagegroupname = 'OS-fakehost-gold-I-SG'
defaultstoragegroupname = 'OS_default_GOLD1_SG'
storagevolume_creationclass = 'EMC_StorageVolume'
policyrule = 'gold'
poolname = 'gold'
@ -783,12 +785,18 @@ class FakeEcomConnection(object):
def _assoc_storagegroup(self):
assocs = []
assoc = CIM_DeviceMaskingGroup()
assoc['ElementName'] = 'OS_default_GOLD1_SG'
assoc['SystemName'] = self.data.storage_system
assoc['CreationClassName'] = 'CIM_DeviceMaskingGroup'
assoc.path = assoc
assocs.append(assoc)
assoc1 = CIM_DeviceMaskingGroup()
assoc1['ElementName'] = self.data.storagegroupname
assoc1['SystemName'] = self.data.storage_system
assoc1['CreationClassName'] = 'CIM_DeviceMaskingGroup'
assoc1.path = assoc1
assocs.append(assoc1)
assoc2 = CIM_DeviceMaskingGroup()
assoc2['ElementName'] = self.data.defaultstoragegroupname
assoc2['SystemName'] = self.data.storage_system
assoc2['CreationClassName'] = 'CIM_DeviceMaskingGroup'
assoc2.path = assoc2
assocs.append(assoc2)
return assocs
def _assoc_portgroup(self):
@ -981,8 +989,17 @@ class FakeEcomConnection(object):
def _getinstance_devicemaskinggroup(self, objectpath):
targetmaskinggroup = {}
targetmaskinggroup['CreationClassName'] = 'CIM_DeviceMaskingGroup'
targetmaskinggroup['ElementName'] = 'OS_default_GOLD1_SG'
if 'CreationClassName' in objectpath:
targetmaskinggroup['CreationClassName'] = (
objectpath['CreationClassName'])
else:
targetmaskinggroup['CreationClassName'] = (
'CIM_DeviceMaskingGroup')
if 'ElementName' in objectpath:
targetmaskinggroup['ElementName'] = objectpath['ElementName']
else:
targetmaskinggroup['ElementName'] = (
self.data.storagegroupname)
return targetmaskinggroup
def _getinstance_unit(self, objectpath):
@ -1324,11 +1341,27 @@ class FakeEcomConnection(object):
def _enum_storagegroup(self):
storagegroups = []
storagegroup = {}
storagegroup['CreationClassName'] = (
storagegroup1 = {}
storagegroup1['CreationClassName'] = (
self.data.storagegroup_creationclass)
storagegroup['ElementName'] = self.data.storagegroupname
storagegroups.append(storagegroup)
storagegroup1['ElementName'] = self.data.storagegroupname
storagegroups.append(storagegroup1)
storagegroup2 = {}
storagegroup2['CreationClassName'] = (
self.data.storagegroup_creationclass)
storagegroup2['ElementName'] = self.data.defaultstoragegroupname
storagegroup2['SystemName'] = self.data.storage_system
storagegroups.append(storagegroup2)
storagegroup3 = {}
storagegroup3['CreationClassName'] = (
self.data.storagegroup_creationclass)
storagegroup3['ElementName'] = 'OS-fakehost-SRP_1-Bronze-DSS-SG'
storagegroups.append(storagegroup3)
storagegroup4 = {}
storagegroup4['CreationClassName'] = (
self.data.storagegroup_creationclass)
storagegroup4['ElementName'] = 'OS-SRP_1-Bronze-DSS-SG'
storagegroups.append(storagegroup4)
return storagegroups
def _enum_storagevolume(self):
@ -1659,6 +1692,90 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
self.driver.utils._get_hardware_type(bogus_initiator))
self.assertEqual(0, hardwaretypeid)
def test_check_if_rollback_action_for_masking_required(self):
conn = self.fake_ecom_connection()
controllerConfigService = (
self.driver.utils.find_controller_configuration_service(
conn, self.data.storage_system))
extraSpecs = {'volume_backend_name': 'GOLD_BE',
'isV3': False,
'storagetype:fastpolicy': 'GOLD1'}
vol = EMC_StorageVolume()
vol['name'] = self.data.test_volume['name']
vol['CreationClassName'] = 'Symm_StorageVolume'
vol['ElementName'] = self.data.test_volume['id']
vol['DeviceID'] = self.data.test_volume['device_id']
vol['Id'] = self.data.test_volume['id']
vol['SystemName'] = self.data.storage_system
vol['NumberOfBlocks'] = self.data.test_volume['NumberOfBlocks']
vol['BlockSize'] = self.data.test_volume['BlockSize']
# Added vol to vol.path
vol['SystemCreationClassName'] = 'Symm_StorageSystem'
vol.path = vol
vol.path.classname = vol['CreationClassName']
rollbackDict = {}
rollbackDict['isV3'] = False
rollbackDict['defaultStorageGroupInstanceName'] = (
self.data.default_storage_group)
rollbackDict['sgName'] = self.data.storagegroupname
rollbackDict['volumeName'] = 'vol1'
rollbackDict['fastPolicyName'] = 'GOLD1'
rollbackDict['volumeInstance'] = vol
rollbackDict['controllerConfigService'] = controllerConfigService
rollbackDict['extraSpecs'] = extraSpecs
# Path 1 - The volume is in another storage group that isn't the
# default storage group
expectedmessage = (_("V2 rollback - Volume in another storage "
"group besides default storage group."))
message = (
self.driver.common.masking.
_check_if_rollback_action_for_masking_required(
conn, rollbackDict))
self.assertEqual(expectedmessage, message)
# Path 2 - The volume is not in any storage group
rollbackDict['sgName'] = 'sq_not_exist'
expectedmessage = (_("V2 rollback, volume is not in any storage "
"group."))
message = (
self.driver.common.masking.
_check_if_rollback_action_for_masking_required(
conn, rollbackDict))
self.assertEqual(expectedmessage, message)
def test_migrate_cleanup(self):
conn = self.fake_ecom_connection()
extraSpecs = {'volume_backend_name': 'GOLD_BE',
'isV3': False,
'storagetype:fastpolicy': 'GOLD1'}
vol = EMC_StorageVolume()
vol['name'] = self.data.test_volume['name']
vol['CreationClassName'] = 'Symm_StorageVolume'
vol['ElementName'] = self.data.test_volume['id']
vol['DeviceID'] = self.data.test_volume['device_id']
vol['Id'] = self.data.test_volume['id']
vol['SystemName'] = self.data.storage_system
vol['NumberOfBlocks'] = self.data.test_volume['NumberOfBlocks']
vol['BlockSize'] = self.data.test_volume['BlockSize']
# Added vol to vol.path
vol['SystemCreationClassName'] = 'Symm_StorageSystem'
vol.path = vol
vol.path.classname = vol['CreationClassName']
# The volume is already belong to default storage group
return_to_default = self.driver.common._migrate_cleanup(
conn, vol, self.data.storage_system, 'GOLD1',
vol['name'], extraSpecs)
self.assertFalse(return_to_default)
# The volume does not belong to default storage group
return_to_default = self.driver.common._migrate_cleanup(
conn, vol, self.data.storage_system, 'BRONZE1',
vol['name'], extraSpecs)
self.assertTrue(return_to_default)
def test_wait_for_job_complete(self):
myjob = SE_ConcreteJob()
myjob.classname = 'SE_ConcreteJob'
@ -3839,7 +3956,7 @@ class EMCVMAXFCDriverNoFastTestCase(test.TestCase):
def test_get_port_group_parser(self):
self.create_fake_config_file_parse_port_group()
for _ in range(0, 10):
for _var in range(0, 10):
self.assertEqual(
u'OS-PORTGROUP1-PG',
self.driver.utils.parse_file_to_get_port_group_name(

View File

@ -803,42 +803,41 @@ class EMCVMAXCommon(object):
:param sourceFastPolicyName: the source FAST policy name
:param volumeName: the volume Name
:param extraSpecs: extra specifications
:returns: boolean -- True/False
"""
LOG.warning(_LW("_migrate_cleanup on : %(volumeName)s."),
{'volumeName': volumeName})
return_to_default = True
controllerConfigurationService = (
self.utils.find_controller_configuration_service(
conn, storageSystemName))
# Check to see what SG it is in.
assocStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(conn,
volumeInstance.path))
assocStorageGroupInstanceNames = (
self.utils.get_storage_groups_from_volume(conn,
volumeInstance.path))
# This is the SG it should be in.
defaultStorageGroupInstanceName = (
self.fast.get_policy_default_storage_group(
conn, controllerConfigurationService, sourceFastPolicyName))
# It is not in any storage group. Must add it to default source.
if assocStorageGroupInstanceName is None:
self.add_to_default_SG(conn, volumeInstance,
storageSystemName, sourceFastPolicyName,
volumeName, extraSpecs)
# It is in the incorrect storage group.
if (assocStorageGroupInstanceName is not None and
(assocStorageGroupInstanceName !=
defaultStorageGroupInstanceName)):
self.provision.remove_device_from_storage_group(
conn, controllerConfigurationService,
assocStorageGroupInstanceName,
volumeInstance.path, volumeName, extraSpecs)
for assocStorageGroupInstanceName in assocStorageGroupInstanceNames:
# It is in the incorrect storage group.
if (assocStorageGroupInstanceName !=
defaultStorageGroupInstanceName):
self.provision.remove_device_from_storage_group(
conn, controllerConfigurationService,
assocStorageGroupInstanceName,
volumeInstance.path, volumeName, extraSpecs)
else:
# The volume is already in the default.
return_to_default = False
if return_to_default:
self.add_to_default_SG(
conn, volumeInstance, storageSystemName, sourceFastPolicyName,
volumeName, extraSpecs)
return return_to_default
def _migrate_volume_fast_target(
self, volumeInstance, storageSystemName,
@ -1041,7 +1040,7 @@ class EMCVMAXCommon(object):
def _is_valid_for_storage_assisted_migration_v3(
self, volumeInstanceName, host, sourceArraySerialNumber,
sourcePoolName, volumeName, volumeStatus):
sourcePoolName, volumeName, volumeStatus, sgName):
"""Check if volume is suitable for storage assisted (pool) migration.
:param volumeInstanceName: the volume instance id
@ -1050,7 +1049,8 @@ class EMCVMAXCommon(object):
the original volume
:param sourcePoolName: the pool name of the original volume
:param volumeName: the name of the volume to be migrated
:param volumeStatus: the status of the volume e.g
:param volumeStatus: the status of the volume
:param sgName: storage group name
:returns: boolean -- True/False
:returns: string -- targetSlo
:returns: string -- targetWorkload
@ -1094,7 +1094,7 @@ class EMCVMAXCommon(object):
foundStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
self.conn, volumeInstanceName))
self.conn, volumeInstanceName, sgName))
if foundStorageGroupInstanceName is None:
LOG.warning(_LW(
"Volume: %(volumeName)s is not currently "
@ -1775,13 +1775,14 @@ class EMCVMAXCommon(object):
controllerConfigurationService = (
self.utils.find_controller_configuration_service(
self.conn, storageSystemName))
defaultSgName = self.fast.format_default_sg_string(fastPolicyName)
self.fast.add_volume_to_default_storage_group_for_fast_policy(
self.conn, controllerConfigurationService, volumeInstance,
volumeName, fastPolicyName, extraSpecs)
foundStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
self.conn, volumeInstance.path))
self.conn, volumeInstance.path, defaultSgName))
if foundStorageGroupInstanceName is None:
exceptionMessage = (_(
@ -2948,11 +2949,14 @@ class EMCVMAXCommon(object):
:param extraSpecs: extra specifications
:returns: boolean -- True if migration succeeded, False if error.
"""
storageGroupName = self.utils.get_v3_storage_group_name(
extraSpecs[POOL], extraSpecs[SLO], extraSpecs[WORKLOAD])
volumeInstanceName = volumeInstance.path
isValid, targetSlo, targetWorkload = (
self._is_valid_for_storage_assisted_migration_v3(
volumeInstanceName, host, extraSpecs[ARRAY],
extraSpecs[POOL], volumeName, volumeStatus))
extraSpecs[POOL], volumeName, volumeStatus,
storageGroupName))
storageSystemName = volumeInstance['SystemName']
@ -2998,10 +3002,12 @@ class EMCVMAXCommon(object):
controllerConfigService = (
self.utils.find_controller_configuration_service(
self.conn, storageSystemName))
defaultSgName = self.utils.get_v3_storage_group_name(
extraSpecs[POOL], extraSpecs[SLO], extraSpecs[WORKLOAD])
foundStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
self.conn, volumeInstance.path))
self.conn, volumeInstance.path, defaultSgName))
if foundStorageGroupInstanceName is None:
LOG.warning(_LW(
"Volume : %(volumeName)s is not currently "
@ -3017,7 +3023,7 @@ class EMCVMAXCommon(object):
# Check that it has been removed.
sgFromVolRemovedInstanceName = (
self.utils.wrap_get_storage_group_from_volume(
self.conn, volumeInstance.path))
self.conn, volumeInstance.path, defaultSgName))
if sgFromVolRemovedInstanceName is not None:
LOG.error(_LE(
"Volume : %(volumeName)s has not been "
@ -3044,7 +3050,7 @@ class EMCVMAXCommon(object):
# Check that it has been added.
sgFromVolAddedInstanceName = (
self.utils.get_storage_group_from_volume(
self.conn, volumeInstance.path))
self.conn, volumeInstance.path, storageGroupName))
if sgFromVolAddedInstanceName is None:
LOG.error(_LE(
"Volume : %(volumeName)s has not been "

View File

@ -106,7 +106,7 @@ class EMCVMAXFast(object):
:param volumeInstanceName: the volume instance name
:param volumeName: the volume name (String)
:param fastPolicyName: the fast policy name (String)
:returns: foundDefaultStorageGroupInstanceName
:returns: foundDefaultStorageGroupInstanceName, defaultSgName
"""
foundDefaultStorageGroupInstanceName = None
storageSystemInstanceName = self.utils.find_storage_system(
@ -117,9 +117,11 @@ class EMCVMAXFast(object):
"FAST is not supported on this array."))
raise
defaultSgName = self.format_default_sg_string(fastPolicyName)
assocStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(conn, volumeInstanceName))
defaultSgName = self._format_default_sg_string(fastPolicyName)
self.utils.get_storage_group_from_volume(conn, volumeInstanceName,
defaultSgName))
defaultStorageGroupInstanceName = (
self.utils.find_storage_masking_group(conn,
controllerConfigService,
@ -137,12 +139,12 @@ class EMCVMAXFast(object):
else:
LOG.warning(_LW(
"Volume: %(volumeName)s Does not belong "
"to storage storage group %(defaultSgGroupName)s."),
"to storage group %(defaultSgName)s."),
{'volumeName': volumeName,
'defaultSgGroupName': defaultSgName})
return foundDefaultStorageGroupInstanceName
'defaultSgName': defaultSgName})
return foundDefaultStorageGroupInstanceName, defaultSgName
def _format_default_sg_string(self, fastPolicyName):
def format_default_sg_string(self, fastPolicyName):
"""Format the default storage group name
:param fastPolicyName: the fast policy name
@ -171,14 +173,13 @@ class EMCVMAXFast(object):
associated with the volume
"""
failedRet = None
defaultSgName = self._format_default_sg_string(fastPolicyName)
defaultSgName = self.format_default_sg_string(fastPolicyName)
storageGroupInstanceName = self.utils.find_storage_masking_group(
conn, controllerConfigService, defaultSgName)
if storageGroupInstanceName is None:
LOG.error(_LE(
"Unable to create default storage group for "
"FAST policy : %(fastPolicyName)s."),
{'fastPolicyName': fastPolicyName})
"Unable to get default storage group %(defaultSgName)s."),
{'defaultSgName': defaultSgName})
return failedRet
self.provision.add_members_to_masking_group(
@ -187,7 +188,8 @@ class EMCVMAXFast(object):
# Check to see if the volume is in the storage group.
assocStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(conn,
volumeInstance.path))
volumeInstance.path,
defaultSgName))
return assocStorageGroupInstanceName
def _create_default_storage_group(self, conn, controllerConfigService,
@ -750,7 +752,7 @@ class EMCVMAXFast(object):
:returns: defaultStorageGroupInstanceName - the default storage group
instance name
"""
defaultSgName = self._format_default_sg_string(fastPolicyName)
defaultSgName = self.format_default_sg_string(fastPolicyName)
defaultStorageGroupInstanceName = (
self.utils.find_storage_masking_group(conn,
controllerConfigService,

View File

@ -35,7 +35,8 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver):
2.0.0 - Add driver requirement functions
2.1.0 - Add consistency group functions
2.1.1 - Fixed issue with mismatched config (bug #1442376)
2.1.3 - Clean up failed clones (bug #1440154)
2.1.2 - Clean up failed clones (bug #1440154)
2.1.3 - Fixed a problem with FAST support (bug #1435069)
"""
VERSION = "2.1.3"

View File

@ -43,7 +43,8 @@ class EMCVMAXISCSIDriver(driver.ISCSIDriver):
2.0.0 - Add driver requirement functions
2.1.0 - Add consistency group functions
2.1.1 - Fixed issue with mismatched config (bug #1442376)
2.1.3 - Clean up failed clones (bug #1440154)
2.1.2 - Clean up failed clones (bug #1440154)
2.1.3 - Fixed a problem with FAST support (bug #1435069)
"""
VERSION = "2.1.3"

View File

@ -93,7 +93,8 @@ class EMCVMAXMasking(object):
if isV3:
assocStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
conn, volumeInstance.path))
conn, volumeInstance.path,
maskingViewDict['sgGroupName']))
instance = conn.GetInstance(
assocStorageGroupInstanceName, LocalOnly=False)
assocStorageGroupName = instance['ElementName']
@ -125,14 +126,24 @@ class EMCVMAXMasking(object):
volumeName, fastPolicyName,
extraSpecs))
maskingViewInstanceName, storageGroupInstanceName, errorMessage = (
self._validate_masking_view(conn, maskingViewDict,
defaultStorageGroupInstanceName))
LOG.debug(
"The masking view in the attach operation is "
"%(maskingViewInstanceName)s.",
{'maskingViewInstanceName': maskingViewInstanceName})
# If anything has gone wrong with the masking view we rollback
try:
maskingViewInstanceName, storageGroupInstanceName, errorMessage = (
self._validate_masking_view(conn, maskingViewDict,
defaultStorageGroupInstanceName))
LOG.debug(
"The masking view in the attach operation is "
"%(maskingViewInstanceName)s. The storage group "
"in the masking view is %(storageGroupInstanceName)s.",
{'maskingViewInstanceName': maskingViewInstanceName,
'storageGroupInstanceName': storageGroupInstanceName})
except Exception as e:
LOG.exception(_LE(
"Masking View creation or retrieval was not successful "
"for masking view %(maskingViewName)s. "
"Attempting rollback."),
{'maskingViewName': maskingViewDict['maskingViewName']})
errorMessage = e
if not errorMessage:
# Only after the masking view has been validated, add the
@ -149,6 +160,7 @@ class EMCVMAXMasking(object):
rollbackDict['fastPolicyName'] = fastPolicyName
rollbackDict['isV3'] = isV3
rollbackDict['extraSpecs'] = extraSpecs
rollbackDict['sgName'] = maskingViewDict['sgGroupName']
if errorMessage:
# Rollback code if we cannot complete any of the steps above
@ -471,7 +483,7 @@ class EMCVMAXMasking(object):
msg = None
if self._is_volume_in_storage_group(
conn, storageGroupInstanceName,
volumeInstance):
volumeInstance, sgGroupName):
LOG.warning(_LW(
"Volume: %(volumeName)s is already part "
"of storage group %(sgGroupName)s."),
@ -484,7 +496,7 @@ class EMCVMAXMasking(object):
sgGroupName, maskingViewDict['extraSpecs'])
if not self._is_volume_in_storage_group(
conn, storageGroupInstanceName,
volumeInstance):
volumeInstance, sgGroupName):
# This may be used in exception hence _ instead of _LE.
msg = (_(
"Volume: %(volumeName)s was not added "
@ -533,8 +545,7 @@ class EMCVMAXMasking(object):
volumeName, fastPolicyName, extraSpecs))
if retStorageGroupInstanceName is None:
exceptionMessage = (_(
"Failed to remove volume %(volumeName)s from default SG: "
"%(volumeName)s.")
"Failed to remove volume %(volumeName)s from default SG.")
% {'volumeName': volumeName})
LOG.error(exceptionMessage)
raise exception.VolumeBackendAPIException(
@ -577,7 +588,8 @@ class EMCVMAXMasking(object):
# Required for unit tests.
emptyStorageGroupInstanceName = (
self._wrap_get_storage_group_from_volume(conn, volumeInstanceName))
self._wrap_get_storage_group_from_volume(
conn, volumeInstanceName, maskingViewDict['sgGroupName']))
if emptyStorageGroupInstanceName is not None:
exceptionMessage = (_(
@ -589,7 +601,7 @@ class EMCVMAXMasking(object):
data=exceptionMessage)
def _is_volume_in_storage_group(
self, conn, storageGroupInstanceName, volumeInstance):
self, conn, storageGroupInstanceName, volumeInstance, sgName):
"""Check if the volume is already part of the storage group.
Check if the volume is already part of the storage group,
@ -602,7 +614,7 @@ class EMCVMAXMasking(object):
"""
foundStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
conn, volumeInstance.path))
conn, volumeInstance.path, sgName))
if foundStorageGroupInstanceName is not None:
storageGroupInstance = conn.GetInstance(
@ -1195,8 +1207,10 @@ class EMCVMAXMasking(object):
:param conn: the connection to the ecom server
:param rollbackDict: the rollback dictionary
:returns: message
:raises: VolumeBackendAPIException
"""
message = None
try:
if rollbackDict['isV3']:
errorMessage = self._check_adding_volume_to_storage_group(
@ -1204,14 +1218,16 @@ class EMCVMAXMasking(object):
rollbackDict['defaultStorageGroupInstanceName'])
if errorMessage:
LOG.error(errorMessage)
message = (_("V3 rollback"))
else:
foundStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
conn, rollbackDict['volumeInstance'].path))
conn, rollbackDict['volumeInstance'].path,
rollbackDict['sgName']))
# Volume is not associated with any storage group so add
# it back to the default.
if len(foundStorageGroupInstanceName) == 0:
if not foundStorageGroupInstanceName:
LOG.warning(_LW(
"No storage group found. "
"Performing rollback on Volume: %(volumeName)s "
@ -1237,26 +1253,29 @@ class EMCVMAXMasking(object):
"admin to get the volume re-added manually."),
{'volumeName': rollbackDict['volumeName'],
'fastPolicyName': rollbackDict['fastPolicyName']})
if len(foundStorageGroupInstanceName) > 0:
message = (_("V2 rollback, volume is not in any storage "
"group."))
else:
LOG.info(_LI(
"The storage group found is "
"%(foundStorageGroupInstanceName)s."),
{'foundStorageGroupInstanceName':
foundStorageGroupInstanceName})
# Check the name, see is it the default storage group
# or another.
if (foundStorageGroupInstanceName !=
rollbackDict['defaultStorageGroupInstanceName']):
# Remove it from its current masking view and return it
# to its default masking view if fast is enabled.
self.remove_and_reset_members(
conn,
rollbackDict['controllerConfigService'],
rollbackDict['volumeInstance'],
rollbackDict['fastPolicyName'],
rollbackDict['volumeName'], rollbackDict['extraSpecs'],
False)
# Check the name, see is it the default storage group
# or another.
if (foundStorageGroupInstanceName !=
rollbackDict['defaultStorageGroupInstanceName']):
# Remove it from its current masking view and return it
# to its default masking view if fast is enabled.
self.remove_and_reset_members(
conn,
rollbackDict['controllerConfigService'],
rollbackDict['volumeInstance'],
rollbackDict['volumeName'],
rollbackDict['extraSpecs'])
message = (_("V2 rollback - Volume in another storage "
"group besides default storage group."))
except Exception:
errorMessage = (_(
"Rollback for Volume: %(volumeName)s has failed. "
@ -1267,6 +1286,7 @@ class EMCVMAXMasking(object):
'fastPolicyName': rollbackDict['fastPolicyName']})
LOG.exception(errorMessage)
raise exception.VolumeBackendAPIException(data=errorMessage)
return message
def _find_new_initiator_group(self, conn, maskingGroupDict):
"""After creating an new initiator group find it and return it.
@ -1575,7 +1595,7 @@ class EMCVMAXMasking(object):
:returns: instance name defaultStorageGroupInstanceName
"""
failedRet = None
defaultStorageGroupInstanceName = (
defaultStorageGroupInstanceName, defaultSgName = (
self.fast.get_and_verify_default_storage_group(
conn, controllerConfigService, volumeInstanceName,
volumeName, fastPolicyName))
@ -1610,7 +1630,8 @@ class EMCVMAXMasking(object):
# Required for unit tests.
emptyStorageGroupInstanceName = (
self._wrap_get_storage_group_from_volume(conn, volumeInstanceName))
self._wrap_get_storage_group_from_volume(conn, volumeInstanceName,
defaultSgName))
if emptyStorageGroupInstanceName is not None:
LOG.error(_LE(
@ -1621,18 +1642,20 @@ class EMCVMAXMasking(object):
return defaultStorageGroupInstanceName
def _wrap_get_storage_group_from_volume(self, conn, volumeInstanceName):
def _wrap_get_storage_group_from_volume(self, conn, volumeInstanceName,
defaultSgName):
"""Wrapper for get_storage_group_from_volume.
Needed for override in tests.
:param conn: the connection to the ecom server
:param volumeInstanceName: the volume instance name
:param defaultSgName: the default storage group name
:returns: emptyStorageGroupInstanceName
"""
return self.utils.get_storage_group_from_volume(
conn, volumeInstanceName)
conn, volumeInstanceName, defaultSgName)
def get_devices_from_storage_group(
self, conn, storageGroupInstanceName):

View File

@ -489,7 +489,7 @@ class EMCVMAXUtils(object):
return foundStorageSystemInstanceName
def get_storage_group_from_volume(self, conn, volumeInstanceName):
def get_storage_group_from_volume(self, conn, volumeInstanceName, sgName):
"""Returns the storage group for a particular volume.
Given the volume instance name get the associated storage group if it
@ -505,14 +505,50 @@ class EMCVMAXUtils(object):
volumeInstanceName,
ResultClass='CIM_DeviceMaskingGroup')
if len(storageGroupInstanceNames) > 0:
foundStorageGroupInstanceName = storageGroupInstanceNames[0]
if len(storageGroupInstanceNames) > 1:
LOG.info(_LI(
"The volume belongs to more than one storage group. "
"Returning storage group %(sgName)s."),
{'sgName': sgName})
for storageGroupInstanceName in storageGroupInstanceNames:
instance = self.get_existing_instance(
conn, storageGroupInstanceName)
if instance and sgName == instance['ElementName']:
foundStorageGroupInstanceName = storageGroupInstanceName
break
return foundStorageGroupInstanceName
def wrap_get_storage_group_from_volume(self, conn, volumeInstanceName):
def get_storage_groups_from_volume(self, conn, volumeInstanceName):
"""Returns all the storage group for a particular volume.
Given the volume instance name get all the associated storage groups.
:param conn: connection to the ecom server
:param volumeInstanceName: the volume instance name
:returns: foundStorageGroupInstanceName
"""
storageGroupInstanceNames = conn.AssociatorNames(
volumeInstanceName,
ResultClass='CIM_DeviceMaskingGroup')
if storageGroupInstanceNames:
LOG.debug("There are %(len)d storage groups associated "
"with volume %(volumeInstanceName)s.",
{'len': len(storageGroupInstanceNames),
'volumeInstanceName': volumeInstanceName})
else:
LOG.debug("There are no storage groups associated "
"with volume %(volumeInstanceName)s.",
{'volumeInstanceName': volumeInstanceName})
return storageGroupInstanceNames
def wrap_get_storage_group_from_volume(self, conn, volumeInstanceName,
sgName):
"""Unit test aid"""
return self.get_storage_group_from_volume(conn, volumeInstanceName)
return self.get_storage_group_from_volume(conn, volumeInstanceName,
sgName)
def find_storage_masking_group(self, conn, controllerConfigService,
storageGroupName):