]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Fixed attach volume for EMC SMI-S iSCSI driver
authorXing Yang <xing.yang@emc.com>
Thu, 21 Mar 2013 04:36:03 +0000 (00:36 -0400)
committerXing Yang <xing.yang@emc.com>
Fri, 22 Mar 2013 03:35:45 +0000 (23:35 -0400)
This problem was encountered during Grizzly RC1 testing.  The driver
didn't find the correct target IQN.  As a result, Nova couldn't find
the matching path in /dev/disk/by-path and therefore detached the volume.

Change-Id: I8bcf6d9896b9d445f6376ecc3a5695be46507663
Fixes: bug #1157912
cinder/tests/test_emc.py
cinder/volume/drivers/emc/emc_smis_common.py
cinder/volume/drivers/emc/emc_smis_iscsi.py

index e1098c9dfa74fb66e8993d003116eedb2e8dbb0b..c12070629edddfa86636707d947f6a9fb6554fa1 100644 (file)
@@ -221,6 +221,8 @@ class FakeEcomConnection():
             result = self._enum_unitnames()
         elif name == 'EMC_LunMaskingSCSIProtocolController':
             result = self._enum_lunmaskctrls()
+        elif name == 'EMC_StorageProcessorSystem':
+            result = self._enum_processors()
         else:
             result = self._default_enum()
         return result
@@ -259,6 +261,8 @@ class FakeEcomConnection():
         result = None
         if resultClass == 'EMC_StorageHardwareID':
             result = self._assoc_hdwid()
+        elif resultClass == 'EMC_iSCSIProtocolEndpoint':
+            result = self._assoc_endpoint()
         else:
             result = self._default_assoc(objectpath)
         return result
@@ -313,6 +317,14 @@ class FakeEcomConnection():
         assocs.append(assoc)
         return assocs
 
+    def _assoc_endpoint(self):
+        assocs = []
+        assoc = {}
+        assoc['Name'] = 'iqn.1992-04.com.emc:cx.apm00123907237.a8,t,0x0001'
+        assoc['SystemName'] = storage_system + '+SP_A+8'
+        assocs.append(assoc)
+        return assocs
+
     def _default_assoc(self, objectpath):
         return objectpath
 
@@ -567,6 +579,14 @@ class FakeEcomConnection():
         ctrls.append(ctrl)
         return ctrls
 
+    def _enum_processors(self):
+        ctrls = []
+        ctrl = {}
+        ctrl['CreationClassName'] = 'Clar_StorageProcessorSystem'
+        ctrl['Name'] = storage_system + '+SP_A'
+        ctrls.append(ctrl)
+        return ctrls
+
     def _default_enum(self):
         names = []
         name = {}
@@ -587,8 +607,8 @@ class EMCSMISISCSIDriverTestCase(test.TestCase):
         configuration.cinder_emc_config_file = self.config_file_path
         configuration.append_config_values(mox.IgnoreArg())
 
-        self.stubs.Set(EMCSMISISCSIDriver, '_get_iscsi_properties',
-                       self.fake_get_iscsi_properties)
+        self.stubs.Set(EMCSMISISCSIDriver, '_do_iscsi_discovery',
+                       self.fake_do_iscsi_discovery)
         self.stubs.Set(EMCSMISCommon, '_get_ecom_connection',
                        self.fake_ecom_connection)
         driver = EMCSMISISCSIDriver(configuration=configuration)
@@ -633,23 +653,13 @@ class EMCSMISISCSIDriverTestCase(test.TestCase):
         conn = FakeEcomConnection()
         return conn
 
-    def fake_get_iscsi_properties(self, volume):
-        LOG.info('Fake _get_iscsi_properties.')
-        properties = {}
-        properties['target_discovered'] = True
-        properties['target_portal'] = '10.10.10.10'
-        properties['target_iqn'] = 'iqn.1993-08.org.debian:01:a1b2c3d4e5f6'
-        device_number = '000008'
-        properties['target_lun'] = device_number
-        properties['volume_id'] = volume['id']
-        auth = volume['provider_auth']
-        if auth:
-            (auth_method, auth_username, auth_secret) = auth.split()
-            properties['auth_method'] = auth_method
-            properties['auth_username'] = auth_username
-            properties['auth_password'] = auth_secret
-        LOG.info(_("Fake ISCSI properties: %s") % (properties))
-        return properties
+    def fake_do_iscsi_discovery(self, volume):
+        output = []
+        item = '10.0.0.3:3260,1 iqn.1992-04.com.emc:cx.apm00123907237.a8'
+        item2 = '10.0.0.4:3260,2 iqn.1992-04.com.emc:cx.apm00123907237.b8'
+        output.append(item)
+        output.append(item2)
+        return output
 
     def test_get_volume_stats(self):
         self.driver.get_volume_stats(True)
@@ -674,8 +684,7 @@ class EMCSMISISCSIDriverTestCase(test.TestCase):
         self.driver.create_volume(test_volume)
         export = self.driver.create_export(None, test_volume)
         test_volume['provider_location'] = export['provider_location']
-        test_volume['EMCCurrentOwningStorageProcessor'] = \
-            'iqn.1993-08.org.debian:01:a1b2c3d4e5f6'
+        test_volume['EMCCurrentOwningStorageProcessor'] = 'SP_A'
         connector = {'initiator': initiator1}
         connection_info = self.driver.initialize_connection(test_volume,
                                                             connector)
index 60c4c3452a95cebaea7c4630edae54aecf759dd7..31f094bfe07baca380659eccda2132a6aebb7c95 100644 (file)
@@ -1071,7 +1071,7 @@ class EMCSMISCommon():
             poolname = instanceid[endp + 1:]
 
         idarray = instanceid.split('+')
-        if len > 2:
+        if len(idarray) > 2:
             systemname = idarray[0] + '+' + idarray[1]
 
         LOG.debug(_("Pool name: %(poolname)s  System name: %(systemname)s.")
@@ -1437,6 +1437,58 @@ class EMCSMISCommon():
 
         return foundMaskingGroup
 
+    # Find a StorageProcessorSystem given sp and storage system
+    def _find_storage_processor_system(self, owningsp, storage_system):
+        foundSystem = None
+        systems = self.conn.EnumerateInstanceNames(
+            'EMC_StorageProcessorSystem')
+        for system in systems:
+            # Clar_StorageProcessorSystem.CreationClassName=
+            # "Clar_StorageProcessorSystem",Name="CLARiiON+APM00123907237+SP_A"
+            idarray = system['Name'].split('+')
+            if len(idarray) > 2:
+                storsystemname = idarray[0] + '+' + idarray[1]
+                sp = idarray[2]
+
+            if (storage_system == storsystemname and
+                owningsp == sp):
+                foundSystem = system
+                LOG.debug(_("Found Storage Processor System: %s")
+                          % (str(system)))
+                break
+
+        return foundSystem
+
+    # Find EMC_iSCSIProtocolEndpoint for the specified sp
+    def _find_iscsi_protocol_endpoints(self, owningsp, storage_system):
+        foundEndpoints = []
+
+        processor = self._find_storage_processor_system(
+            owningsp,
+            storage_system)
+
+        associators = self.conn.Associators(
+            processor,
+            resultClass='EMC_iSCSIProtocolEndpoint')
+        for assoc in associators:
+            # Name = iqn.1992-04.com.emc:cx.apm00123907237.a8,t,0x0001
+            # SystemName = CLARiiON+APM00123907237+SP_A+8
+            arr = assoc['SystemName'].split('+')
+            if len(arr) > 2:
+                processor_name = arr[0] + '+' + arr[1] + '+' + arr[2]
+                if processor_name == processor['Name']:
+                    arr2 = assoc['Name'].split(',')
+                    if len(arr2) > 1:
+                        foundEndpoints.append(arr2[0])
+
+        LOG.debug(_("iSCSIProtocolEndpoint for storage system "
+                  "%(storage_system)s and SP %(sp)s is  "
+                  "%(endpoint)s.")
+                  % {'storage_system': storage_system,
+                     'sp': owningsp,
+                     'endpoint': str(foundEndpoints)})
+        return foundEndpoints
+
     def _getnum(self, num, datatype):
         try:
             result = {
index 3046e041d44ed714bade7b4d509ef89ee49cd304..d9c58a29a515d1a21dbdfbab7276a4d469dd1b8c 100644 (file)
@@ -169,16 +169,42 @@ class EMCSMISISCSIDriver(driver.ISCSIDriver):
             raise exception.VolumeBackendAPIException(data=exception_message)
 
         device_number = device_info['hostlunid']
+        storage_system = device_info['storagesystem']
 
+        # sp is "SP_A" or "SP_B"
         sp = device_info['owningsp']
+        endpoints = []
+        if sp:
+            # endpointss example:
+            # [iqn.1992-04.com.emc:cx.apm00123907237.a8,
+            # iqn.1992-04.com.emc:cx.apm00123907237.a9]
+            endpoints = self.common._find_iscsi_protocol_endpoints(
+                sp, storage_system)
+
+        foundEndpoint = False
         for loc in location:
             results = loc.split(" ")
             properties['target_portal'] = results[0].split(",")[0]
             properties['target_iqn'] = results[1]
             # owning sp is None for VMAX
-            # for VNX, find the owning sp in target_iqn
-            if not sp or -1 != properties['target_iqn'].find(sp):
+            # for VNX, find the target_iqn that matches the endpoint
+            # target_iqn example: iqn.1992-04.com.emc:cx.apm00123907237.a8
+            # or iqn.1992-04.com.emc:cx.apm00123907237.b8
+            if not sp:
                 break
+            for endpoint in endpoints:
+                if properties['target_iqn'] == endpoint:
+                    LOG.debug(_("Found iSCSI endpoint: %s") % endpoint)
+                    foundEndpoint = True
+                    break
+            if foundEndpoint:
+                break
+
+        if sp and not foundEndpoint:
+            LOG.warn(_("ISCSI endpoint not found for SP %(sp)s on "
+                     "storage system %(storage)s.")
+                     % {'sp': sp,
+                        'storage': storage_system})
 
         properties['target_lun'] = device_number