Merge "Fix silent iSCSI login failures"

This commit is contained in:
Jenkins 2015-10-17 17:38:53 +00:00 committed by Gerrit Code Review
commit 90c285704f
3 changed files with 62 additions and 2 deletions

View File

@ -108,3 +108,7 @@ class ProtocolNotSupported(BrickException):
class TargetPortalNotFound(BrickException):
message = _("Unable to find target portal %(target_portal)s.")
class FailedISCSITargetPortalLogin(BrickException):
message = _("Unable to login to iSCSI Target Portal")

View File

@ -446,6 +446,7 @@ class ISCSIConnector(InitiatorConnector):
device_info = {'type': 'block'}
connected_to_portal = False
if self.use_multipath:
# Multipath installed, discovering other targets if available
try:
@ -474,7 +475,8 @@ class ISCSIConnector(InitiatorConnector):
props = copy.deepcopy(connection_properties)
props['target_portal'] = ip
props['target_iqn'] = iqn
self._connect_to_iscsi_portal(props)
if self._connect_to_iscsi_portal(props):
connected_to_portal = True
self._rescan_iscsi()
host_devices = self._get_device_path(connection_properties)
@ -483,13 +485,19 @@ class ISCSIConnector(InitiatorConnector):
for props in self._iterate_all_targets(connection_properties):
if self._connect_to_iscsi_portal(props):
target_props = props
connected_to_portal = True
host_devices = self._get_device_path(target_props)
break
else:
LOG.warning(_LW(
'Failed to connect to iSCSI portal %(portal)s.'),
{'portal': props['target_portal']})
host_devices = self._get_device_path(target_props)
# make sure we've logged into an iSCSI portal
if not connected_to_portal:
msg = _("Could not login to any iSCSI portal.")
LOG.error(msg)
raise exception.FailedISCSITargetPortalLogin(message=msg)
# The /dev/disk/by-path/... node is not always present immediately
# TODO(justinsb): This retry-with-delay is a pattern, move to utils?

View File

@ -706,6 +706,54 @@ class ISCSIConnectorTestCase(ConnectorTestCase):
self.assertEqual(expected_result, result)
self.assertEqual(expected_calls, mock_connect.call_args_list)
@mock.patch.object(os.path, 'exists', return_value=True)
@mock.patch.object(connector.ISCSIConnector,
'_get_target_portals_from_iscsiadm_output')
@mock.patch.object(connector.ISCSIConnector, '_connect_to_iscsi_portal')
@mock.patch.object(host_driver.HostDriver, 'get_all_block_devices')
@mock.patch.object(connector.ISCSIConnector, '_get_iscsi_devices')
@mock.patch.object(connector.ISCSIConnector, '_rescan_multipath')
@mock.patch.object(connector.ISCSIConnector, '_run_multipath')
@mock.patch.object(connector.ISCSIConnector, '_get_multipath_device_name')
def test_connect_volume_multipath_failed_iscsi_login(
self, mock_device_name, mock_run_multipath,
mock_rescan_multipath, mock_iscsi_devices, mock_devices,
mock_connect, mock_portals, mock_exists):
location1 = '10.0.2.15:3260'
location2 = '10.0.3.15:3260'
name1 = 'volume-00000001-1'
name2 = 'volume-00000001-2'
iqn1 = 'iqn.2010-10.org.openstack:%s' % name1
iqn2 = 'iqn.2010-10.org.openstack:%s' % name2
fake_multipath_dev = '/dev/mapper/fake-multipath-dev'
vol = {'id': 1, 'name': name1}
connection_properties = self.iscsi_connection(vol, location1, iqn1)
devs = ['/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location1, iqn1),
'/dev/disk/by-path/ip-%s-iscsi-%s-lun-2' % (location2, iqn2)]
mock_devices.return_value = devs
mock_iscsi_devices.return_value = devs
mock_device_name.return_value = fake_multipath_dev
mock_portals.return_value = [[location1, iqn1], [location2, iqn1],
[location2, iqn2]]
mock_connect.return_value = False
self.assertRaises(exception.FailedISCSITargetPortalLogin,
self.connector_with_multipath.connect_volume,
connection_properties['data'])
@mock.patch.object(connector.ISCSIConnector, '_connect_to_iscsi_portal')
def test_connect_volume_failed_iscsi_login(self, mock_connect):
location1 = '10.0.2.15:3260'
name1 = 'volume-00000001-1'
iqn1 = 'iqn.2010-10.org.openstack:%s' % name1
vol = {'id': 1, 'name': name1}
connection_properties = self.iscsi_connection(vol, location1, iqn1)
mock_connect.return_value = False
self.assertRaises(exception.FailedISCSITargetPortalLogin,
self.connector.connect_volume,
connection_properties['data'])
@mock.patch.object(time, 'sleep')
@mock.patch.object(os.path, 'exists', return_value=False)
def test_connect_volume_with_not_found_device(self, exists_mock,