summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXing Yang <xing.yang@emc.com>2015-04-04 18:25:48 -0400
committerXing Yang <xing.yang@emc.com>2015-04-06 16:37:55 -0400
commitd36ac8277dfe26e18ec7fdd6ebb782fd83df38d5 (patch)
tree481ec666bcf1b09b890f0dd1bf19fd37589defde
parent07f716c2cdbdf1d04843096b6fb7d03651521f3f (diff)
downloadcinder-d36ac8277dfe26e18ec7fdd6ebb782fd83df38d5.tar.gz
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
-rw-r--r--cinder/tests/test_emc_vmax.py24
-rw-r--r--cinder/volume/drivers/emc/emc_vmax_common.py4
-rw-r--r--cinder/volume/drivers/emc/emc_vmax_fc.py5
-rw-r--r--cinder/volume/drivers/emc/emc_vmax_masking.py52
-rw-r--r--cinder/volume/drivers/emc/emc_vmax_utils.py29
5 files changed, 101 insertions, 13 deletions
diff --git a/cinder/tests/test_emc_vmax.py b/cinder/tests/test_emc_vmax.py
index 11b86a638..d335053b5 100644
--- a/cinder/tests/test_emc_vmax.py
+++ b/cinder/tests/test_emc_vmax.py
@@ -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],
diff --git a/cinder/volume/drivers/emc/emc_vmax_common.py b/cinder/volume/drivers/emc/emc_vmax_common.py
index a2d818fb1..6cc4e34cc 100644
--- a/cinder/volume/drivers/emc/emc_vmax_common.py
+++ b/cinder/volume/drivers/emc/emc_vmax_common.py
@@ -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,
diff --git a/cinder/volume/drivers/emc/emc_vmax_fc.py b/cinder/volume/drivers/emc/emc_vmax_fc.py
index f52b2e791..d02aafc4b 100644
--- a/cinder/volume/drivers/emc/emc_vmax_fc.py
+++ b/cinder/volume/drivers/emc/emc_vmax_fc.py
@@ -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(
diff --git a/cinder/volume/drivers/emc/emc_vmax_masking.py b/cinder/volume/drivers/emc/emc_vmax_masking.py
index 64f218e93..eb32e9df2 100644
--- a/cinder/volume/drivers/emc/emc_vmax_masking.py
+++ b/cinder/volume/drivers/emc/emc_vmax_masking.py
@@ -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,12 +1350,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."),
+ "array %(storageSystemName)s. "),
{'initiatorNames': initiatorNames,
'storageSystemName': storageSystemName})
- return False
+ 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 = (
self._create_initiator_Group(
@@ -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
diff --git a/cinder/volume/drivers/emc/emc_vmax_utils.py b/cinder/volume/drivers/emc/emc_vmax_utils.py
index 481f2f32e..8636a69b4 100644
--- a/cinder/volume/drivers/emc/emc_vmax_utils.py
+++ b/cinder/volume/drivers/emc/emc_vmax_utils.py
@@ -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