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:
parent
07f716c2cd
commit
d36ac8277d
@ -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],
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user