Avoid unhandled exceptions during connecting to iSCSI portals

Currently we don't properly catch some possible exceptions during
connectiing to iSCSI portals, like failures in "iscsiadm -m session".
Because of this _connect_vol threads can abort unexpectedly in some
failure patterns, and this abort causes hung in subsequent steps
waiting for results from _connct_vol threads.

This change ensures that any exceptions during connecting to iSCSI
portals are handled in the _connect_vol method corectly, to avoid
unexpected abort without updating thread results.

Conflicts:
        os_brick/tests/initiator/connectors/test_iscsi.py

Closes-Bug: #1915678
Change-Id: I0278c502806b99f8ec65cb146e3852e43031e9b8
(cherry picked from commit 4478433550)
(cherry picked from commit 57c8f4334c)
(cherry picked from commit c336cb76b3)
This commit is contained in:
Takashi Kajinami 2021-02-15 10:58:13 +09:00
parent 30244b175c
commit d09c385c24
3 changed files with 34 additions and 10 deletions

View File

@ -630,18 +630,23 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
""" """
device = hctl = None device = hctl = None
portal = props['target_portal'] portal = props['target_portal']
session, manual_scan = self._connect_to_iscsi_portal(props) try:
do_scans = rescans > 0 or manual_scan session, manual_scan = self._connect_to_iscsi_portal(props)
# Scan is sent on connect by iscsid, but we must do it manually on except Exception:
# manual scan mode. This scan cannot count towards total rescans. LOG.exception('Exception connecting to %s', portal)
if manual_scan: session = None
num_rescans = -1
seconds_next_scan = 0
else:
num_rescans = 0
seconds_next_scan = 4
if session: if session:
do_scans = rescans > 0 or manual_scan
# Scan is sent on connect by iscsid, but we must do it manually on
# manual scan mode. This scan cannot count towards total rescans.
if manual_scan:
num_rescans = -1
seconds_next_scan = 0
else:
num_rescans = 0
seconds_next_scan = 4
data['num_logins'] += 1 data['num_logins'] += 1
LOG.debug('Connected to %s', portal) LOG.debug('Connected to %s', portal)
while do_scans: while do_scans:

View File

@ -1533,6 +1533,18 @@ Setting up iSCSI targets: unused
expected.update(failed_logins=1, stopped_threads=1) expected.update(failed_logins=1, stopped_threads=1)
self.assertDictEqual(expected, data) self.assertDictEqual(expected, data)
@mock.patch.object(iscsi.ISCSIConnector, '_connect_to_iscsi_portal')
def test_connect_vol_with_connection_failure(self, connect_mock):
data = self._get_connect_vol_data()
connect_mock.side_effect = Exception()
self.connector._connect_vol(3, self.CON_PROPS, data)
expected = self._get_connect_vol_data()
expected.update(failed_logins=1, stopped_threads=1)
self.assertDictEqual(expected, data)
@mock.patch('time.sleep', mock.Mock()) @mock.patch('time.sleep', mock.Mock())
@mock.patch.object(linuxscsi.LinuxSCSI, 'scan_iscsi') @mock.patch.object(linuxscsi.LinuxSCSI, 'scan_iscsi')
@mock.patch.object(linuxscsi.LinuxSCSI, 'device_name_by_hctl', @mock.patch.object(linuxscsi.LinuxSCSI, 'device_name_by_hctl',

View File

@ -0,0 +1,7 @@
---
fixes:
- |
`Bug #1915678 <https://bugs.launchpad.net/cinder/+bug/1915678>`_: Fix
unhandled exception during iscsi volume attachment with multipath enabled
that resulted in the cinder-volume service becoming stuck and requiring
a restart.