]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Create initiator id if not exist in VMAX driver
authorXing Yang <xing.yang@emc.com>
Sat, 4 Apr 2015 22:25:48 +0000 (18:25 -0400)
committerXing Yang <xing.yang@emc.com>
Mon, 6 Apr 2015 20:37:55 +0000 (16:37 -0400)
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

cinder/tests/test_emc_vmax.py
cinder/volume/drivers/emc/emc_vmax_common.py
cinder/volume/drivers/emc/emc_vmax_fc.py
cinder/volume/drivers/emc/emc_vmax_masking.py
cinder/volume/drivers/emc/emc_vmax_utils.py

index 11b86a6389a1a19c3718019a61586c0c910587e0..d335053b5443810ee1a6ee9a8c5643d57603f939 100644 (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],
index a2d818fb1efddc4c11681a32b8507f070cfbcc9b..6cc4e34cccd7af42bde1fc8ec36cd2b1f7b9d5f8 100644 (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,
index f52b2e7916bbf16698d1e563d09d377268e071be..d02aafc4b7075ef0be5a8195dcbafcef95015a6c 100644 (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(
index 64f218e93244081c3992b409d8f1590dd03e6844..eb32e9df2358dac1f8a9cc1bbf4710e22adc5afc 100644 (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,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
index 481f2f32e585901b7559118fb83d7510c09a12aa..8636a69b48b09fefef339b8e6c8026b7bca5f833 100644 (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