From: Xing Yang Date: Thu, 21 Mar 2013 04:36:03 +0000 (-0400) Subject: Fixed attach volume for EMC SMI-S iSCSI driver X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=18bf0b386b2f26f524ebb6ab540941f64cad4642;p=openstack-build%2Fcinder-build.git Fixed attach volume for EMC SMI-S iSCSI driver 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 --- diff --git a/cinder/tests/test_emc.py b/cinder/tests/test_emc.py index e1098c9df..c12070629 100644 --- a/cinder/tests/test_emc.py +++ b/cinder/tests/test_emc.py @@ -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) diff --git a/cinder/volume/drivers/emc/emc_smis_common.py b/cinder/volume/drivers/emc/emc_smis_common.py index 60c4c3452..31f094bfe 100644 --- a/cinder/volume/drivers/emc/emc_smis_common.py +++ b/cinder/volume/drivers/emc/emc_smis_common.py @@ -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 = { diff --git a/cinder/volume/drivers/emc/emc_smis_iscsi.py b/cinder/volume/drivers/emc/emc_smis_iscsi.py index 3046e041d..d9c58a29a 100644 --- a/cinder/volume/drivers/emc/emc_smis_iscsi.py +++ b/cinder/volume/drivers/emc/emc_smis_iscsi.py @@ -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