From 1d6ad6ef179f465289c95b5f45ac79b0f03e0866 Mon Sep 17 00:00:00 2001 From: Tom Swanson Date: Mon, 26 Feb 2018 13:50:22 -0600 Subject: [PATCH] Dell EMC SC: Added timeout options for SC driver Added dell_api_async_rest_timeout and dell_api_sync_rest_timeout to allow setting of async and sync timeouts for the Dell EMC SC REST API. The user should generally not set these. They should be set only when instructed by support. Fixed a couple of comments. Updated documentation. Change-Id: Id8fd27d83e2f97070f67523c9c2d8c59f66e6caa --- .../volume/drivers/dell_emc/sc/test_scapi.py | 43 ++++++++++++++- .../drivers/dell_emc/sc/storagecenter_api.py | 38 +++++++++---- .../dell_emc/sc/storagecenter_common.py | 6 +++ .../drivers/dell_emc/sc/storagecenter_fc.py | 5 +- .../dell_emc/sc/storagecenter_iscsi.py | 5 +- .../drivers/dell-storagecenter-driver.rst | 54 +++++++++++++------ ...-emc-sc-api-timeouts-ce8d166e1847ea94.yaml | 11 ++++ 7 files changed, 130 insertions(+), 32 deletions(-) create mode 100644 releasenotes/notes/dell-emc-sc-api-timeouts-ce8d166e1847ea94.yaml diff --git a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py index c00a6f1389d..c7e1457f442 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py @@ -14,6 +14,7 @@ import ddt import eventlet +import json import mock import requests from requests import models @@ -1683,6 +1684,8 @@ class DellSCSanAPITestCase(test.TestCase): self.configuration.target_port = 3260 self._context = context.get_admin_context() self.apiversion = '2.0' + self.asynctimeout = 15 + self.synctimeout = 30 # Set up the SCApi self.scapi = storagecenter_api.SCApi( @@ -1691,6 +1694,8 @@ class DellSCSanAPITestCase(test.TestCase): self.configuration.san_login, self.configuration.san_password, self.configuration.dell_sc_verify_cert, + self.asynctimeout, + self.synctimeout, self.apiversion) # Set up the scapi configuration vars @@ -8635,6 +8640,8 @@ class DellSCSanAPIConnectionTestCase(test.TestCase): self.configuration.target_ip_address = '192.168.1.1' self.configuration.target_port = 3260 self._context = context.get_admin_context() + self.asynctimeout = 15 + self.synctimeout = 30 self.apiversion = '2.0' # Set up the SCApi @@ -8644,6 +8651,8 @@ class DellSCSanAPIConnectionTestCase(test.TestCase): self.configuration.san_login, self.configuration.san_password, self.configuration.dell_sc_verify_cert, + self.asynctimeout, + self.synctimeout, self.apiversion) # Set up the scapi configuration vars @@ -8772,10 +8781,12 @@ class DellHttpClientTestCase(test.TestCase): self.user = 'johnnyuser' self.password = 'password' self.verify = False + self.asynctimeout = 15 + self.synctimeout = 30 self.apiversion = '3.1' self.httpclient = storagecenter_api.HttpClient( - self.host, self.port, self.user, self.password, - self.verify, self.apiversion) + self.host, self.port, self.user, self.password, self.verify, + self.asynctimeout, self.synctimeout, self.apiversion) def test_get_async_url(self): url = self.httpclient._get_async_url(self.ASYNCTASK) @@ -8904,8 +8915,36 @@ class DellHttpClientTestCase(test.TestCase): expected_headers = self.httpclient.header.copy() mock_get.assert_called_once_with('https://localhost:3033/api/rest/url', headers=expected_headers, + timeout=30, verify=False) + @mock.patch.object(requests.Session, 'post', return_value=RESPONSE_200) + @mock.patch.object(storagecenter_api.HttpClient, '_rest_ret') + def test_post(self, mock_rest_ret, mock_post): + payload = {'payload': 'payload'} + self.httpclient.post('url', payload, True) + expected_headers = self.httpclient.header.copy() + expected_headers['async'] = 'True' + mock_post.assert_called_once_with( + 'https://localhost:3033/api/rest/url', + data=json.dumps(payload, ensure_ascii=False).encode('utf-8'), + headers=expected_headers, + timeout=15, + verify=False) + + @mock.patch.object(requests.Session, 'post', return_value=RESPONSE_200) + @mock.patch.object(storagecenter_api.HttpClient, '_rest_ret') + def test_post_sync(self, mock_rest_ret, mock_post): + payload = {'payload': 'payload'} + self.httpclient.post('url', payload, False) + expected_headers = self.httpclient.header.copy() + mock_post.assert_called_once_with( + 'https://localhost:3033/api/rest/url', + data=json.dumps(payload, ensure_ascii=False).encode('utf-8'), + headers=expected_headers, + timeout=30, + verify=False) + class DellStorageCenterApiHelperTestCase(test.TestCase): diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py index 547757df2ca..5f16f882b25 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py @@ -79,7 +79,8 @@ class HttpClient(object): Helper for making the REST calls. """ - def __init__(self, host, port, user, password, verify, apiversion): + def __init__(self, host, port, user, password, + verify, asynctimeout, synctimeout, apiversion): """HttpClient handles the REST requests. :param host: IP address of the Dell Data Collector. @@ -88,6 +89,8 @@ class HttpClient(object): :param password: Password. :param verify: Boolean indicating whether certificate verification should be turned on or not. + :param asynctimeout: async REST call time out. + :param synctimeout: sync REST call time out. :param apiversion: Dell API version. """ self.baseUrl = 'https://%s:%s/' % (host, port) @@ -100,6 +103,8 @@ class HttpClient(object): self.header['Accept'] = 'application/json' self.header['x-dell-api-version'] = apiversion self.verify = verify + self.asynctimeout = asynctimeout + self.synctimeout = synctimeout # Verify is a configurable option. So if this is false do not # spam the c-vol log. @@ -230,7 +235,8 @@ class HttpClient(object): LOG.debug('get: %(url)s', {'url': url}) rest_response = self.session.get(self.__formatUrl(url), headers=self.header, - verify=self.verify) + verify=self.verify, + timeout=self.synctimeout) if (rest_response and rest_response.status_code == ( http_client.BAD_REQUEST)) and ( @@ -248,7 +254,9 @@ class HttpClient(object): data=json.dumps(payload, ensure_ascii=False).encode('utf-8'), headers=self._get_header(async_call), - verify=self.verify), async_call) + verify=self.verify, timeout=( + self.asynctimeout if async_call else self.synctimeout)), + async_call) @utils.retry(exceptions=(requests.ConnectionError,)) def put(self, url, payload, async_call=False): @@ -260,14 +268,18 @@ class HttpClient(object): data=json.dumps(payload, ensure_ascii=False).encode('utf-8'), headers=self._get_header(async_call), - verify=self.verify), async_call) + verify=self.verify, timeout=( + self.asynctimeout if async_call else self.synctimeout)), + async_call) @utils.retry(exceptions=(requests.ConnectionError,)) def delete(self, url, payload=None, async_call=False): LOG.debug('delete: %(url)s data: %(payload)s', {'url': url, 'payload': payload}) named = {'headers': self._get_header(async_call), - 'verify': self.verify} + 'verify': self.verify, + 'timeout': ( + self.asynctimeout if async_call else self.synctimeout)} if payload: named['data'] = json.dumps( payload, ensure_ascii=False).encode('utf-8') @@ -336,6 +348,8 @@ class SCApiHelper(object): self.san_login, self.san_password, self.config.dell_sc_verify_cert, + self.config.dell_api_async_rest_timeout, + self.config.dell_api_sync_rest_timeout, self.apiversion) # This instance is for a single backend. That backend has a # few items of information we should save rather than passing them @@ -368,7 +382,7 @@ class SCApiHelper(object): connection = None LOG.info('open_connection to %(ssn)s at %(ip)s', {'ssn': self.primaryssn, - 'ip': self.config.san_ip}) + 'ip': self.san_ip}) if self.primaryssn: try: """Open connection to REST API.""" @@ -420,12 +434,14 @@ class SCApi(object): 3.6.0 - Server type support. 3.7.0 - Support for Data Reduction, Group QOS and Volume QOS. 4.0.0 - Driver moved to dell_emc. + 4.1.0 - Timeouts added to rest calls. """ - APIDRIVERVERSION = '4.0.0' + APIDRIVERVERSION = '4.1.0' - def __init__(self, host, port, user, password, verify, apiversion): + def __init__(self, host, port, user, password, verify, + asynctimeout, synctimeout, apiversion): """This creates a connection to Dell SC or EM. :param host: IP address of the REST interface.. @@ -434,6 +450,8 @@ class SCApi(object): :param password: Password. :param verify: Boolean indicating whether certificate verification should be turned on or not. + :param asynctimeout: async REST call time out. + :param synctimeout: sync REST call time out. :param apiversion: Version used on login. """ self.notes = 'Created by Dell EMC Cinder Driver' @@ -454,8 +472,8 @@ class SCApi(object): # Nothing other than Replication should care if we are direct connect # or not. self.is_direct_connect = False - self.client = HttpClient(host, port, user, password, - verify, apiversion) + self.client = HttpClient(host, port, user, password, verify, + asynctimeout, synctimeout, apiversion) def __enter__(self): return self diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py index 36e53feb0e1..91a1ace692f 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py @@ -58,6 +58,12 @@ common_opts = [ cfg.PortOpt('secondary_sc_api_port', default=3033, help='Secondary Dell API port'), + cfg.IntOpt('dell_api_async_rest_timeout', + default=15, + help='Dell SC API async call default timeout in seconds.'), + cfg.IntOpt('dell_api_sync_rest_timeout', + default=30, + help='Dell SC API sync call default timeout in seconds.'), cfg.MultiOpt('excluded_domain_ip', item_type=types.IPAddress(), default=None, diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py index c1bca2bf9e2..8dbfe3df2e9 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py @@ -34,7 +34,7 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, """Implements commands for Dell Storage Center FC management. To enable the driver add the following line to the cinder configuration: - volume_driver=cinder.volume.drivers.dell_emc.sc.dell_storagecenter_fc.\ + volume_driver=cinder.volume.drivers.dell_emc.sc.storagecenter_fc.\ SCFCDriver Version history: @@ -62,10 +62,11 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, 3.6.0 - Server type support. 3.7.0 - Support for Data Reduction, Group QOS and Volume QOS. 4.0.0 - Driver moved to dell_emc. + 4.1.0 - Timeouts added to rest calls. """ - VERSION = '4.0.0' + VERSION = '4.1.0' CI_WIKI_NAME = "Dell_EMC_SC_Series_CI" diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py index d6d9f0363e6..05eac61e014 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py @@ -34,7 +34,7 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver, To enable the driver add the following line to the cinder configuration: volume_driver=cinder.volume.drivers.dell_emc.sc.\ - dell_storagecenter_iscsi.SCISCSIDriver + storagecenter_iscsi.SCISCSIDriver Version history: @@ -62,10 +62,11 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver, 3.6.0 - Server type support. 3.7.0 - Support for Data Reduction, Group QOS and Volume QOS. 4.0.0 - Driver moved to dell_emc. + 4.1.0 - Timeouts added to rest calls. """ - VERSION = '4.0.0' + VERSION = '4.1.0' CI_WIKI_NAME = "Dell_EMC_SC_Series_CI" def __init__(self, *args, **kwargs): diff --git a/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst b/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst index 4f5073f7ddd..fa98a38542e 100644 --- a/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst +++ b/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst @@ -2,19 +2,19 @@ Dell EMC SC Series Fibre Channel and iSCSI drivers ================================================== -The Dell Storage Center volume driver interacts with configured Storage +The Dell EMC Storage Center volume driver interacts with configured Storage Center arrays. -The Dell Storage Center driver manages Storage Center arrays through -the Dell Storage Manager (DSM). DSM connection settings and Storage +The Dell EMC Storage Center driver manages Storage Center arrays through +the Dell EMC Storage Manager (DSM). DSM connection settings and Storage Center options are defined in the ``cinder.conf`` file. -Prerequisite: Dell Storage Manager 2015 R1 or later must be used. +Prerequisite: Dell EMC Storage Manager 2015 R1 or later must be used. Supported operations ~~~~~~~~~~~~~~~~~~~~ -The Dell Storage Center volume driver provides the following Cinder +The Dell EMC Storage Center volume driver provides the following Cinder volume operations: - Create, delete, attach (map), and detach (unmap) volumes. @@ -33,7 +33,7 @@ volume operations: Extra spec options ~~~~~~~~~~~~~~~~~~ -Volume type extra specs can be used to enable a variety of Dell Storage +Volume type extra specs can be used to enable a variety of Dell EMC Storage Center options. Selecting Storage Profiles, Replay Profiles, enabling replication, replication options including Live Volume and Active Replay replication. @@ -170,7 +170,7 @@ Use the following instructions to update the configuration file for iSCSI: # Name to give this storage back-end volume_backend_name = delliscsi # The iSCSI driver to load - volume_driver = cinder.volume.drivers.dell.dell_storagecenter_iscsi.DellStorageCenterISCSIDriver + volume_driver = cinder.volume.drivers.dell_emc.sc.storagecenter_iscsi.SCISCSIDriver # IP address of DSM san_ip = 172.23.8.101 # DSM user name @@ -204,7 +204,8 @@ channel: # Name to give this storage back-end volume_backend_name = dellfc # The FC driver to load - volume_driver = cinder.volume.drivers.dell.dell_storagecenter_fc.DellStorageCenterFCDriver + volume_driver = cinder.volume.drivers.dell_emc.sc.storagecenter_fc.SCFCDriver + # IP address of the DSM san_ip = 172.23.8.101 # DSM user name @@ -298,10 +299,10 @@ Simply specify default as the backend_id. $ cinder failover-host cinder@delliscsi --backend_id default -Non trivial heavy lifting is done by this command. It attempts to recover best -it can but if things have diverged to far it can only do so much. It is also a -one time only command so do not reboot or restart the service in the middle of -it. +Non trivial heavy lifting is done by this command. It attempts to recover as +best it can but if things have diverged too far it can only do so much. It is +also a one time only command so do not reboot or restart the service in the +middle of it. Failover and failback are significant operations under OpenStack Cinder. Be sure to consult with support before attempting. @@ -310,11 +311,11 @@ Server type configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ This option allows one to set a default Server OS type to use when creating -a server definition on the Dell Storage Center. +a server definition on the Dell EMC Storage Center. -When attaching a volume to a node the Dell Storage Center driver creates a +When attaching a volume to a node the Dell EMC Storage Center driver creates a server definition on the storage array. This defition includes a Server OS -type. The type used by the Dell Storage Center cinder driver is +type. The type used by the Dell EMC Storage Center cinder driver is "Red Hat Linux 6.x". This is a modern operating system definition that supports all the features of an OpenStack node. @@ -352,10 +353,31 @@ Add the following to the back-end specification to exclude the domains at excluded_domain_ip=172.20.25.15 excluded_domain_ip=172.20.26.15 +Setting Dell EMC SC REST API timeouts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The user can specify timeouts for Dell EMC SC REST API calls. + +To set the timeout for ASYNC REST API calls in seconds. + +.. code-block:: ini + + [dell] + dell_api_async_rest_timeout=15 + +To set the timeout for SYNC REST API calls in seconds. + +.. code-block:: ini + + [dell] + dell_api_sync_rest_timeout=30 + +Generally these should not be set without guidance from Dell EMC support. + Driver options ~~~~~~~~~~~~~~ The following table contains the configuration options specific to the -Dell Storage Center volume driver. +Dell EMC Storage Center volume driver. .. include:: ../../tables/cinder-dellsc.inc diff --git a/releasenotes/notes/dell-emc-sc-api-timeouts-ce8d166e1847ea94.yaml b/releasenotes/notes/dell-emc-sc-api-timeouts-ce8d166e1847ea94.yaml new file mode 100644 index 00000000000..abb0be6eb7b --- /dev/null +++ b/releasenotes/notes/dell-emc-sc-api-timeouts-ce8d166e1847ea94.yaml @@ -0,0 +1,11 @@ +--- +features: + - Added dell_api_async_rest_timeout option to the + Dell EMC SC driver. This is the timeout used for + asynchronous REST calls to the Dell EMC SC REST + API. Default is 15 seconds. + - Added dell_api_sync_rest_timeout option to the + Dell EMC SC driver. This is the timeout used for + synchronous REST calls to the Dell EMC SC REST + API. Default is 30 seconds. +