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
This commit is contained in:
Tom Swanson 2018-02-26 13:50:22 -06:00
parent 015b105399
commit 1d6ad6ef17
7 changed files with 130 additions and 32 deletions

View File

@ -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,6 +8915,34 @@ 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)

View File

@ -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

View File

@ -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,

View File

@ -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"

View File

@ -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):

View File

@ -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

View File

@ -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.