diff --git a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py index c7e1457f442..524dff3fcad 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py @@ -3641,7 +3641,50 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): - res = self.scapi.find_iscsi_properties(self.VOLUME) + scserver = {'instanceId': '64702.30'} + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) + self.assertTrue(mock_is_virtualport_mode.called) + self.assertTrue(mock_find_mappings.called) + self.assertTrue(mock_find_domains.called) + self.assertTrue(mock_find_ctrl_port.called) + self.assertTrue(mock_find_active_controller.called) + expected = {'target_discovered': False, + 'target_iqn': + u'iqn.2002-03.com.compellent:5000d31000fcbe43', + 'target_iqns': + [u'iqn.2002-03.com.compellent:5000d31000fcbe43'], + 'target_lun': 1, + 'target_luns': [1], + 'target_portal': u'192.168.0.21:3260', + 'target_portals': [u'192.168.0.21:3260']} + self.assertEqual(expected, res, 'Wrong Target Info') + + @mock.patch.object(storagecenter_api.SCApi, + '_find_active_controller', + return_value='64702.5764839588723736131.91') + @mock.patch.object(storagecenter_api.SCApi, + '_find_controller_port', + return_value=ISCSI_CTRLR_PORT) + @mock.patch.object(storagecenter_api.SCApi, + '_find_domains', + return_value=ISCSI_FLT_DOMAINS) + @mock.patch.object(storagecenter_api.SCApi, + '_find_mappings', + return_value=MAPPINGS) + @mock.patch.object(storagecenter_api.SCApi, + '_is_virtualport_mode', + return_value=True) + def test_find_iscsi_properties_multiple_servers_mapped( + self, mock_is_virtualport_mode, mock_find_mappings, + mock_find_domains, mock_find_ctrl_port, + mock_find_active_controller, mock_close_connection, + mock_open_connection, mock_init): + mappings = [{'instanceId': '64702.970.64702', + 'server': {'instanceId': '64702.47'}, + 'volume': {'instanceId': '64702.92'}}] + mappings.append(self.MAPPINGS[0].copy()) + scserver = {'instanceId': '64702.30'} + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_domains.called) @@ -3666,10 +3709,12 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): + scserver = {'instanceId': '64702.30'} # Test case where there are no ScMapping(s) self.assertRaises(exception.VolumeBackendAPIException, self.scapi.find_iscsi_properties, - self.VOLUME) + self.VOLUME, + scserver) self.assertTrue(mock_find_mappings.called) @mock.patch.object(storagecenter_api.SCApi, @@ -3696,10 +3741,11 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): + scserver = {'instanceId': '64702.30'} # Test case where there are no ScFaultDomain(s) self.assertRaises(exception.VolumeBackendAPIException, self.scapi.find_iscsi_properties, - self.VOLUME) + self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_domains.called) @@ -3726,10 +3772,11 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): + scserver = {'instanceId': '64702.30'} # Test case where there are no ScFaultDomain(s) self.assertRaises(exception.VolumeBackendAPIException, self.scapi.find_iscsi_properties, - self.VOLUME) + self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_ctrl_port.called) @@ -3759,8 +3806,9 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): + scserver = {'instanceId': '64702.30'} # Test case where Read Only mappings are found - res = self.scapi.find_iscsi_properties(self.VOLUME) + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_domains.called) @@ -3804,7 +3852,8 @@ class DellSCSanAPITestCase(test.TestCase): mock_find_ctrl_port.side_effect = [ {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] - res = self.scapi.find_iscsi_properties(self.VOLUME) + scserver = {'instanceId': '64702.30'} + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_ctrl_port.called) @@ -3854,7 +3903,8 @@ class DellSCSanAPITestCase(test.TestCase): # Test case where there are multiple portals and mock_find_ctrl_port.return_value = { 'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'} - res = self.scapi.find_iscsi_properties(self.VOLUME) + scserver = {'instanceId': '64702.30'} + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_ctrl_port.called) @@ -3898,7 +3948,8 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): - res = self.scapi.find_iscsi_properties(self.VOLUME) + scserver = {'instanceId': '64702.30'} + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_ctrl_port.called) @@ -3940,9 +3991,10 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): + scserver = {'instanceId': '64702.30'} self.assertRaises(exception.VolumeBackendAPIException, self.scapi.find_iscsi_properties, - self.VOLUME) + self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_ctrl_port.called) @@ -3973,8 +4025,9 @@ class DellSCSanAPITestCase(test.TestCase): mock_close_connection, mock_open_connection, mock_init): + scserver = {'instanceId': '64702.30'} # Test case where Read Only mappings are found - res = self.scapi.find_iscsi_properties(self.VOLUME) + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_ctrl_port.called) @@ -4018,8 +4071,9 @@ class DellSCSanAPITestCase(test.TestCase): mock_find_ctrl_port.side_effect = [ {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] + scserver = {'instanceId': '64702.30'} # Test case where there are multiple portals - res = self.scapi.find_iscsi_properties(self.VOLUME) + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_active_controller.called) diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py index 5f16f882b25..3b16309c478 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py @@ -1776,12 +1776,13 @@ class SCApi(object): 'Error finding configuration: %s', cportid) return controllerport - def find_iscsi_properties(self, scvolume): + def find_iscsi_properties(self, scvolume, scserver): """Finds target information for a given Dell scvolume object mapping. The data coming back is both the preferred path and all the paths. :param scvolume: The dell sc volume object. + :param scserver: The dell sc server object. :returns: iSCSI property dictionary. :raises VolumeBackendAPIException: """ @@ -1813,9 +1814,12 @@ class SCApi(object): # Make sure this isn't a duplicate. newportal = address + ':' + six.text_type(port) for idx, portal in enumerate(portals): - if portal == newportal and iqns[idx] == iqn: + if (portal == newportal + and iqns[idx] == iqn + and luns[idx] == lun): LOG.debug('Skipping duplicate portal %(ptrl)s and' - 'iqn %(iqn)s.', {'ptrl': portal, 'iqn': iqn}) + ' iqn %(iqn)s and lun %(lun)s.', + {'ptrl': portal, 'iqn': iqn, 'lun': lun}) return # It isn't in the list so process it. portals.append(newportal) @@ -1849,10 +1853,17 @@ class SCApi(object): isvpmode = self._is_virtualport_mode(ssn) # Trundle through our mappings. for mapping in mappings: - # Don't return remote sc links. msrv = mapping.get('server') - if msrv and msrv.get('objectType') == 'ScRemoteStorageCenter': - continue + if msrv: + # Don't return remote sc links. + if msrv.get('objectType') == 'ScRemoteStorageCenter': + continue + # Don't return information for other servers. But + # do log it. + if self._get_id(msrv) != self._get_id(scserver): + LOG.debug('find_iscsi_properties: Multiple servers' + ' attached to volume.') + continue # The lun, ro mode and status are in the mapping. LOG.debug('find_iscsi_properties: mapping: %s', mapping) diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py index 05eac61e014..04f62c98ff7 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py @@ -141,7 +141,8 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver, # 3. OS brick is calling us in single path mode so # we want to return Target_Portal and # Target_Portals as alternates. - iscsiprops = api.find_iscsi_properties(scvolume) + iscsiprops = api.find_iscsi_properties(scvolume, + scserver) # If this is a live volume we need to map up our # secondary volume. Note that if we have failed @@ -204,7 +205,8 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver, secondaryvol = api.get_volume( sclivevolume['secondaryVolume']['instanceId']) if secondaryvol: - return api.find_iscsi_properties(secondaryvol) + return api.find_iscsi_properties(secondaryvol, + secondary) # Dummy return on failure. data = {'target_discovered': False, 'target_iqn': None, diff --git a/releasenotes/notes/dell-emc-sc-bugfix-1756914-ffca3133273040f6.yaml b/releasenotes/notes/dell-emc-sc-bugfix-1756914-ffca3133273040f6.yaml new file mode 100644 index 00000000000..624346d7ff4 --- /dev/null +++ b/releasenotes/notes/dell-emc-sc-bugfix-1756914-ffca3133273040f6.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - Dell EMC SC driver correctly returns initialize_connection + data when more than one IQN is attached to a volume. This + fixes some random Nova Live Migration failures where the + connection information being returned was for an IQN other + than the one for which it was being requested.