From b5574ae74646734b680b17cc533063727f37d390 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Mon, 21 Nov 2016 12:29:56 +0200 Subject: [PATCH] Windows connectors: add device_scan_interval arg The Hyper-V Nova driver will pass os-brick the device rescan interval. This change indends to honor this for the Windows connectors. Other connectors use either a fixed rescan interval, either a exponentially growing interval. If needed, this patch can be updated so that other connectors may use this argument as well. Change-Id: I3d6b4ed2ac27269241420ca03ec7075a977e86e8 --- os_brick/initiator/windows/base.py | 5 +++++ os_brick/initiator/windows/fibre_channel.py | 3 +++ os_brick/initiator/windows/iscsi.py | 7 ++++++- os_brick/tests/windows/test_fibre_channel.py | 8 +++++++- os_brick/tests/windows/test_iscsi.py | 13 ++++++++++--- 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/os_brick/initiator/windows/base.py b/os_brick/initiator/windows/base.py index bb2fb4693..34cfcfd62 100644 --- a/os_brick/initiator/windows/base.py +++ b/os_brick/initiator/windows/base.py @@ -29,9 +29,14 @@ class BaseWindowsConnector(initiator_connector.InitiatorConnector): platform = initiator.PLATFORM_ALL os_type = initiator.OS_TYPE_WINDOWS + DEFAULT_DEVICE_SCAN_INTERVAL = 2 + def __init__(self, root_helper=None, *args, **kwargs): super(BaseWindowsConnector, self).__init__(root_helper, *args, **kwargs) + self.device_scan_interval = kwargs.pop( + 'device_scan_interval', self.DEFAULT_DEVICE_SCAN_INTERVAL) + self._diskutils = utilsfactory.get_diskutils() @staticmethod diff --git a/os_brick/initiator/windows/fibre_channel.py b/os_brick/initiator/windows/fibre_channel.py index d87fed309..10ef2d213 100644 --- a/os_brick/initiator/windows/fibre_channel.py +++ b/os_brick/initiator/windows/fibre_channel.py @@ -14,6 +14,7 @@ # under the License. import collections +import time from os_win import utilsfactory from oslo_log import log as logging @@ -95,6 +96,8 @@ class WindowsFCConnector(win_conn_base.BaseWindowsConnector): if disk_paths: break + time.sleep(self.device_scan_interval) + self._check_device_paths(disk_paths) return list(disk_paths) diff --git a/os_brick/initiator/windows/iscsi.py b/os_brick/initiator/windows/iscsi.py index f23241793..83b32915a 100644 --- a/os_brick/initiator/windows/iscsi.py +++ b/os_brick/initiator/windows/iscsi.py @@ -101,7 +101,12 @@ class WindowsISCSIConnector(win_conn_base.BaseWindowsConnector, auth_password=connection_properties.get('auth_password'), mpio_enabled=self.use_multipath, initiator_name=initiator_name, - rescan_attempts=self.device_scan_attempts) + ensure_lun_available=False) + self._iscsi_utils.ensure_lun_available( + target_iqn=target_iqn, + target_lun=target_lun, + rescan_attempts=self.device_scan_attempts, + retry_interval=self.device_scan_interval) if not volume_connected: (device_number, diff --git a/os_brick/tests/windows/test_fibre_channel.py b/os_brick/tests/windows/test_fibre_channel.py index 0d370ba86..f8ae3e606 100644 --- a/os_brick/tests/windows/test_fibre_channel.py +++ b/os_brick/tests/windows/test_fibre_channel.py @@ -25,7 +25,8 @@ from os_brick.tests.windows import test_base class WindowsFCConnectorTestCase(test_base.WindowsConnectorTestBase): def setUp(self): super(WindowsFCConnectorTestCase, self).setUp() - self._connector = fc.WindowsFCConnector() + self._connector = fc.WindowsFCConnector( + device_scan_interval=mock.sentinel.rescan_interval) self._diskutils = self._connector._diskutils self._fc_utils = self._connector._fc_utils @@ -92,10 +93,12 @@ class WindowsFCConnectorTestCase(test_base.WindowsConnectorTestBase): dict(device_name=mock.sentinel.disk_path)], 'expected_paths': [mock.sentinel.disk_path]}) @ddt.unpack + @mock.patch('time.sleep') @mock.patch.object(fc.WindowsFCConnector, '_get_fc_volume_mappings') @mock.patch.object(fc.WindowsFCConnector, '_check_device_paths') def test_get_volume_paths(self, mock_check_device_paths, mock_get_fc_mappings, + mock_sleep, volume_mappings, expected_paths): mock_get_fc_mappings.return_value = volume_mappings @@ -113,6 +116,9 @@ class WindowsFCConnectorTestCase(test_base.WindowsConnectorTestBase): [mock.call(mock.sentinel.conn_props)] * expected_try_count) mock_check_device_paths.assert_called_once_with( set(vol_paths)) + mock_sleep.assert_has_calls( + [mock.call(mock.sentinel.rescan_interval)] * + (expected_try_count - 1)) @mock.patch.object(fc.WindowsFCConnector, '_get_fc_hba_mappings') def test_get_fc_volume_mappings(self, mock_get_fc_hba_mappings): diff --git a/os_brick/tests/windows/test_iscsi.py b/os_brick/tests/windows/test_iscsi.py index 03bc278e2..42d6ca28b 100644 --- a/os_brick/tests/windows/test_iscsi.py +++ b/os_brick/tests/windows/test_iscsi.py @@ -31,7 +31,8 @@ class WindowsISCSIConnectorTestCase(test_base.WindowsConnectorTestBase): self._diskutils = mock.Mock() self._iscsi_utils = mock.Mock() - self._connector = iscsi.WindowsISCSIConnector() + self._connector = iscsi.WindowsISCSIConnector( + device_scan_interval=mock.sentinel.rescan_interval) self._connector._diskutils = self._diskutils self._connector._iscsi_utils = self._iscsi_utils @@ -128,9 +129,15 @@ class WindowsISCSIConnectorTestCase(test_base.WindowsConnectorTestBase): auth_password=mock.sentinel.auth_password, mpio_enabled=use_multipath, initiator_name=mock.sentinel.initiator_name, - rescan_attempts=( - self._connector.device_scan_attempts))] * + ensure_lun_available=False)] * expected_login_attempts) + self._iscsi_utils.ensure_lun_available.assert_has_calls( + [mock.call(target_iqn=mock.sentinel.target_iqn, + target_lun=mock.sentinel.target_lun, + rescan_attempts=( + self._connector.device_scan_attempts), + retry_interval=mock.sentinel.rescan_interval)] * + (expected_login_attempts - 1)) self._iscsi_utils.get_device_number_and_path.assert_called_once_with( mock.sentinel.target_iqn, mock.sentinel.target_lun)