From 5657fe4de5ad9f7c7ef51d140d5174ffc8d73e0f Mon Sep 17 00:00:00 2001 From: Amit Oren Date: Wed, 21 Mar 2018 17:46:41 +0200 Subject: [PATCH] INFINIDAT: set REST API client parameters Communicating with the INFINIDAT InfiniBox backend is done using a REST API through a client implemented by the infinisdk package. This change sets the number of retries in case of an erroneous API call and sets the User-Agent string for the client. Change-Id: I7e94ab69e460e56ef59e33e206e9377024b213d9 --- .../unit/volume/drivers/test_infinidat.py | 33 ++++++++++++++++++- cinder/volume/drivers/infinidat.py | 19 +++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/cinder/tests/unit/volume/drivers/test_infinidat.py b/cinder/tests/unit/volume/drivers/test_infinidat.py index 9331b6f5f3f..ef7302255df 100644 --- a/cinder/tests/unit/volume/drivers/test_infinidat.py +++ b/cinder/tests/unit/volume/drivers/test_infinidat.py @@ -14,6 +14,7 @@ # under the License. """Unit tests for INFINIDAT InfiniBox volume driver.""" +import functools import mock from oslo_utils import units @@ -41,11 +42,24 @@ test_connector = dict(wwpns=[TEST_WWN_1], initiator=TEST_IQN) +def skip_driver_setup(func): + @functools.wraps(func) + def f(*args, **kwargs): + return func(*args, **kwargs) + f.__skip_driver_setup = True + return f + + class FakeInfinisdkException(Exception): pass class InfiniboxDriverTestCaseBase(test.TestCase): + def _test_skips_driver_setup(self): + test_method_name = self.id().split('.')[-1] + test_method = getattr(self, test_method_name) + return getattr(test_method, '__skip_driver_setup', False) + def setUp(self): super(InfiniboxDriverTestCaseBase, self).setUp() @@ -82,7 +96,9 @@ class InfiniboxDriverTestCaseBase(test.TestCase): capacity.GiB = units.Gi infinisdk.core.exceptions.InfiniSDKException = FakeInfinisdkException infinisdk.InfiniBox.return_value = self._system - self.driver.do_setup(None) + + if not self._test_skips_driver_setup(): + self.driver.do_setup(None) def _infinibox_mock(self): result = mock.Mock() @@ -121,6 +137,21 @@ class InfiniboxDriverTestCaseBase(test.TestCase): class InfiniboxDriverTestCase(InfiniboxDriverTestCaseBase): + @skip_driver_setup + def test__setup_and_get_system_object(self): + # This test should skip the driver setup, as it generates more calls to + # the add_auto_retry, set_source_identifier and login methods: + auth = (self.configuration.san_login, + self.configuration.san_password) + + self.driver._setup_and_get_system_object( + self.configuration.san_ip, auth) + + self._system.api.add_auto_retry.assert_called_once() + self._system.api.set_source_identifier.assert_called_once_with( + infinidat._INFINIDAT_CINDER_IDENTIFIER) + self._system.login.assert_called_once() + def test_initialize_connection(self): self._system.hosts.safe_get.return_value = None result = self.driver.initialize_connection(test_volume, test_connector) diff --git a/cinder/volume/drivers/infinidat.py b/cinder/volume/drivers/infinidat.py index 1926b8909b7..61c5e857869 100644 --- a/cinder/volume/drivers/infinidat.py +++ b/cinder/volume/drivers/infinidat.py @@ -61,6 +61,11 @@ BACKEND_QOS_CONSUMERS = frozenset(['back-end', 'both']) QOS_MAX_IOPS = 'maxIOPS' QOS_MAX_BWS = 'maxBWS' +# Max retries for the REST API client in case of a failure: +_API_MAX_RETRIES = 5 +_INFINIDAT_CINDER_IDENTIFIER = ( + "cinder/%s" % version.version_info.release_string()) + infinidat_opts = [ cfg.StrOpt('infinidat_pool_name', help='Name of the pool from which volumes are allocated'), @@ -127,6 +132,16 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver): self.configuration.append_config_values(infinidat_opts) self._lookup_service = fczm_utils.create_lookup_service() + def _setup_and_get_system_object(self, management_address, auth): + system = infinisdk.InfiniBox(management_address, auth=auth) + system.api.add_auto_retry( + lambda e: isinstance( + e, infinisdk.core.exceptions.APITransportFailure) and + "Interrupted system call" in e.error_desc, _API_MAX_RETRIES) + system.api.set_source_identifier(_INFINIDAT_CINDER_IDENTIFIER) + system.login() + return system + def do_setup(self, context): """Driver initialization""" if infinisdk is None: @@ -136,8 +151,8 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver): auth = (self.configuration.san_login, self.configuration.san_password) self.management_address = self.configuration.san_ip - self._system = infinisdk.InfiniBox(self.management_address, auth=auth) - self._system.login() + self._system = ( + self._setup_and_get_system_object(self.management_address, auth)) backend_name = self.configuration.safe_get('volume_backend_name') self._backend_name = backend_name or self.__class__.__name__ self._volume_stats = None