Merge "Dell EMC SC: ISCSI initialize_connection fixes."

This commit is contained in:
Zuul 2018-03-20 15:45:11 +00:00 committed by Gerrit Code Review
commit 63aa5a9a7f
4 changed files with 93 additions and 19 deletions

View File

@ -3641,7 +3641,50 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): 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_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_domains.called)
@ -3666,10 +3709,12 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): mock_init):
scserver = {'instanceId': '64702.30'}
# Test case where there are no ScMapping(s) # Test case where there are no ScMapping(s)
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_iscsi_properties, self.scapi.find_iscsi_properties,
self.VOLUME) self.VOLUME,
scserver)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
@mock.patch.object(storagecenter_api.SCApi, @mock.patch.object(storagecenter_api.SCApi,
@ -3696,10 +3741,11 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): mock_init):
scserver = {'instanceId': '64702.30'}
# Test case where there are no ScFaultDomain(s) # Test case where there are no ScFaultDomain(s)
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_iscsi_properties, self.scapi.find_iscsi_properties,
self.VOLUME) self.VOLUME, scserver)
self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_domains.called)
@ -3726,10 +3772,11 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): mock_init):
scserver = {'instanceId': '64702.30'}
# Test case where there are no ScFaultDomain(s) # Test case where there are no ScFaultDomain(s)
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_iscsi_properties, self.scapi.find_iscsi_properties,
self.VOLUME) self.VOLUME, scserver)
self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
@ -3759,8 +3806,9 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): mock_init):
scserver = {'instanceId': '64702.30'}
# Test case where Read Only mappings are found # 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_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_domains.called)
@ -3804,7 +3852,8 @@ class DellSCSanAPITestCase(test.TestCase):
mock_find_ctrl_port.side_effect = [ mock_find_ctrl_port.side_effect = [
{'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'},
{'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] {'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_mappings.called)
self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_domains.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
@ -3854,7 +3903,8 @@ class DellSCSanAPITestCase(test.TestCase):
# Test case where there are multiple portals and # Test case where there are multiple portals and
mock_find_ctrl_port.return_value = { mock_find_ctrl_port.return_value = {
'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'} '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_mappings.called)
self.assertTrue(mock_find_domains.called) self.assertTrue(mock_find_domains.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
@ -3898,7 +3948,8 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): 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_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
@ -3940,9 +3991,10 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): mock_init):
scserver = {'instanceId': '64702.30'}
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_iscsi_properties, self.scapi.find_iscsi_properties,
self.VOLUME) self.VOLUME, scserver)
self.assertTrue(mock_is_virtualport_mode.called) self.assertTrue(mock_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
@ -3973,8 +4025,9 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection, mock_close_connection,
mock_open_connection, mock_open_connection,
mock_init): mock_init):
scserver = {'instanceId': '64702.30'}
# Test case where Read Only mappings are found # 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_is_virtualport_mode.called)
self.assertTrue(mock_find_mappings.called) self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
@ -4018,8 +4071,9 @@ class DellSCSanAPITestCase(test.TestCase):
mock_find_ctrl_port.side_effect = [ mock_find_ctrl_port.side_effect = [
{'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'},
{'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}]
scserver = {'instanceId': '64702.30'}
# Test case where there are multiple portals # 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_mappings.called)
self.assertTrue(mock_find_ctrl_port.called) self.assertTrue(mock_find_ctrl_port.called)
self.assertTrue(mock_find_active_controller.called) self.assertTrue(mock_find_active_controller.called)

View File

@ -1776,12 +1776,13 @@ class SCApi(object):
'Error finding configuration: %s', cportid) 'Error finding configuration: %s', cportid)
return controllerport 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. """Finds target information for a given Dell scvolume object mapping.
The data coming back is both the preferred path and all the paths. The data coming back is both the preferred path and all the paths.
:param scvolume: The dell sc volume object. :param scvolume: The dell sc volume object.
:param scserver: The dell sc server object.
:returns: iSCSI property dictionary. :returns: iSCSI property dictionary.
:raises VolumeBackendAPIException: :raises VolumeBackendAPIException:
""" """
@ -1813,9 +1814,12 @@ class SCApi(object):
# Make sure this isn't a duplicate. # Make sure this isn't a duplicate.
newportal = address + ':' + six.text_type(port) newportal = address + ':' + six.text_type(port)
for idx, portal in enumerate(portals): 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' 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 return
# It isn't in the list so process it. # It isn't in the list so process it.
portals.append(newportal) portals.append(newportal)
@ -1849,10 +1853,17 @@ class SCApi(object):
isvpmode = self._is_virtualport_mode(ssn) isvpmode = self._is_virtualport_mode(ssn)
# Trundle through our mappings. # Trundle through our mappings.
for mapping in mappings: for mapping in mappings:
# Don't return remote sc links.
msrv = mapping.get('server') msrv = mapping.get('server')
if msrv and msrv.get('objectType') == 'ScRemoteStorageCenter': if msrv:
continue # 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. # The lun, ro mode and status are in the mapping.
LOG.debug('find_iscsi_properties: mapping: %s', mapping) LOG.debug('find_iscsi_properties: mapping: %s', mapping)

View File

@ -141,7 +141,8 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver,
# 3. OS brick is calling us in single path mode so # 3. OS brick is calling us in single path mode so
# we want to return Target_Portal and # we want to return Target_Portal and
# Target_Portals as alternates. # 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 # If this is a live volume we need to map up our
# secondary volume. Note that if we have failed # secondary volume. Note that if we have failed
@ -204,7 +205,8 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver,
secondaryvol = api.get_volume( secondaryvol = api.get_volume(
sclivevolume['secondaryVolume']['instanceId']) sclivevolume['secondaryVolume']['instanceId'])
if secondaryvol: if secondaryvol:
return api.find_iscsi_properties(secondaryvol) return api.find_iscsi_properties(secondaryvol,
secondary)
# Dummy return on failure. # Dummy return on failure.
data = {'target_discovered': False, data = {'target_discovered': False,
'target_iqn': None, 'target_iqn': None,

View File

@ -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.