Create initiator id if not exist in VMAX driver

This problem was discovered in a customer's environment. If the
initiator id (hardware id SMI-S instance) does not exist on the
array, the attach volume operation will fail. In this patch,
the initiator id will be created if it doesn't exist.

Change-Id: I868118528d831a9f49081a6393e64eb7a414b36f
Closes-Bug: #1440427
This commit is contained in:
Xing Yang 2015-04-04 18:25:48 -04:00
parent 07f716c2cd
commit d36ac8277d
5 changed files with 101 additions and 13 deletions

View File

@ -240,7 +240,7 @@ class EMCVMAXCommonData(object):
initiatorgroup_name = \
'OS-fakehost-IG'
initiatorgroup_creationclass = 'SE_InitiatorMaskingGroup'
iscsi_initiator = 'iqn.1993-08.org.debian'
storageextent_creationclass = 'CIM_StorageExtent'
initiator1 = 'iqn.1993-08.org.debian: 01: 1a2b3c4d5f6g'
stconf_service_creationclass = 'Symm_StorageConfigurationService'
@ -462,7 +462,7 @@ class FakeEcomConnection(object):
Type=None, EMCSRP=None, EMCSLO=None, EMCWorkload=None,
EMCCollections=None, InitiatorMaskingGroup=None,
DeviceMaskingGroup=None, TargetMaskingGroup=None,
ProtocolController=None):
ProtocolController=None, StorageID=None, IDType=None):
rc = 0L
myjob = SE_ConcreteJob()
@ -510,6 +510,12 @@ class FakeEcomConnection(object):
rsd = SE_ReplicationSettingData()
rsd['DefaultInstance'] = SE_ReplicationSettingData()
return rc, rsd
if MethodName == 'CreateStorageHardwareID':
ret = {}
rc = 0L
ret['HardwareID'] = self.data.iscsi_initiator
return rc, ret
job = {'Job': myjob}
return rc, job
@ -1611,6 +1617,20 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
def fake_is_v3(self, conn, serialNumber):
return False
def test_create_hardware_ids(self):
conn = self.fake_ecom_connection()
connector = {
'ip': '10.0.0.2',
'initiator': self.data.iscsi_initiator,
'host': 'fakehost'}
initiatorNames = (
self.driver.common.masking._find_initiator_names(conn, connector))
storageHardwareIDInstanceNames = (
self.driver.common.masking._create_hardware_ids(
conn, initiatorNames, self.data.storage_system))
self.assertEqual(storageHardwareIDInstanceNames[0],
self.data.iscsi_initiator)
def test_format_system_name(self):
v2array = ['SYMMETRIX', '000195900551', 'U', 'gold']
systemnameV2 = self.driver.utils._format_system_name(v2array[0],

View File

@ -3480,7 +3480,7 @@ class EMCVMAXCommon(object):
baseVolumeName = "TargetBaseVol"
volume = {'size': int(self.utils.convert_bits_to_gbs(
volumeSizeInbits))}
rc, baseVolumeDict, storageSystemName = (
_rc, baseVolumeDict, storageSystemName = (
self._create_composite_volume(
volume, baseVolumeName, volumeSizeInbits,
extraSpecs))
@ -3518,7 +3518,7 @@ class EMCVMAXCommon(object):
self.conn, storageSystemName))
compositeType = self.utils.get_composite_type(
extraSpecs[COMPOSITETYPE])
rc, modifiedVolumeDict = (
_rc, modifiedVolumeDict = (
self._modify_and_get_composite_volume_instance(
self.conn,
elementCompositionService,

View File

@ -184,7 +184,8 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver):
:returns: dict -- the target_wwns and initiator_target_map if the
zone is to be removed, otherwise empty
"""
data = {}
data = {'driver_volume_type': 'fibre_channel',
'data': {}}
loc = volume['provider_location']
name = eval(loc)
storage_system = name['keybindings']['SystemName']
@ -193,8 +194,6 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver):
mvInstanceName = self.common.get_masking_view_by_volume(
volume, connector)
data = {'driver_volume_type': 'fibre_channel',
'data': {}}
if mvInstanceName is not None:
portGroupInstanceName = (
self.common.get_port_group_from_masking_view(

View File

@ -776,7 +776,6 @@ class EMCVMAXMasking(object):
:param storageSystemName: the storage system name (String)
:returns: foundInitiatorGroupInstanceName
"""
failedRet = None
initiatorNames = self._find_initiator_names(conn, connector)
LOG.debug("The initiator name(s) are: %(initiatorNames)s.",
{'initiatorNames': initiatorNames})
@ -793,12 +792,20 @@ class EMCVMAXMasking(object):
self._get_storage_hardware_id_instance_names(
conn, initiatorNames, storageSystemName))
if not storageHardwareIDInstanceNames:
LOG.error(_LE(
LOG.info(_LI(
"Initiator Name(s) %(initiatorNames)s are not on array "
"%(storageSystemName)s."),
{'initiatorNames': initiatorNames,
'storageSystemName': storageSystemName})
return failedRet
storageHardwareIDInstanceNames = (
self._create_hardware_ids(conn, initiatorNames,
storageSystemName))
if not storageHardwareIDInstanceNames:
msg = (_("Failed to create hardware id(s) on "
"%(storageSystemName)s.")
% {'storageSystemName': storageSystemName})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
foundInitiatorGroupInstanceName = self._create_initiator_Group(
conn, controllerConfigService, igGroupName,
@ -1343,11 +1350,19 @@ class EMCVMAXMasking(object):
self._get_storage_hardware_id_instance_names(
conn, initiatorNames, storageSystemName))
if not storageHardwareIDInstanceNames:
LOG.error(_LE(
LOG.info(_LI(
"Initiator Name(s) %(initiatorNames)s are not on "
"array %(storageSystemName)s."),
"array %(storageSystemName)s. "),
{'initiatorNames': initiatorNames,
'storageSystemName': storageSystemName})
storageHardwareIDInstanceNames = (
self._create_hardware_ids(conn, initiatorNames,
storageSystemName))
if not storageHardwareIDInstanceNames:
LOG.error(_LE(
"Failed to create hardware id(s) on "
"%(storageSystemName)s."),
{'storageSystemName': storageSystemName})
return False
foundInitiatorGroupFromConnector = (
@ -2247,3 +2262,28 @@ class EMCVMAXMasking(object):
LOG.error(exceptionMessage)
raise exception.VolumeBackendAPIException(
data=exceptionMessage)
def _create_hardware_ids(
self, conn, initiatorNames, storageSystemName):
"""Create hardwareIds for initiator(s).
:param conn: the connection to the ecom server
:param initiatorNames: the list of initiator names
:param storageSystemName: the storage system name
:returns: list -- foundHardwareIDsInstanceNames
"""
foundHardwareIDsInstanceNames = []
hardwareIdManagementService = (
self.utils.find_storage_hardwareid_service(
conn, storageSystemName))
for initiatorName in initiatorNames:
hardwareIdInstanceName = (
self.utils.create_storage_hardwareId_instance_name(
conn, hardwareIdManagementService, initiatorName))
LOG.debug(
"Created hardwareId Instance: %(hardwareIdInstanceName)s.",
{'hardwareIdInstanceName': hardwareIdInstanceName})
foundHardwareIDsInstanceNames.append(hardwareIdInstanceName)
return foundHardwareIDsInstanceNames

View File

@ -1891,3 +1891,32 @@ class EMCVMAXUtils(object):
LOG.debug("Clone is licensed and enabled.")
return True
return False
def create_storage_hardwareId_instance_name(
self, conn, hardwareIdManagementService, initiator):
"""Create storage hardware ID instance name based on the given wwpn.
:param conn: connection to the ecom server
:param hardwareIdManagementService: the hardware ID management service
:param initiator: initiator(IQN or WWPN) to create the hardware ID
instance
:returns: hardwareIdList
"""
hardwareIdList = None
hardwareIdType = 2
rc, ret = conn.InvokeMethod(
'CreateStorageHardwareID',
hardwareIdManagementService,
StorageID=initiator,
IDType=self.get_num(hardwareIdType, '16'))
if 'HardwareID' in ret:
LOG.debug("Created hardware ID instance for initiator:"
"%(initiator)s rc=%(rc)d, ret=%(ret)s",
{'initiator': initiator, 'rc': rc, 'ret': ret})
hardwareIdList = ret['HardwareID']
else:
LOG.warn(_LW("CreateStorageHardwareID failed. initiator: "
"%(initiator)s, rc=%(rc)d, ret=%(ret)s."),
{'initiator': initiator, 'rc': rc, 'ret': ret})
return hardwareIdList