From 2c5f154171c5c62c63fc239a46b448ded0a0041f Mon Sep 17 00:00:00 2001 From: nikeshm Date: Sat, 22 Aug 2015 02:09:51 +0530 Subject: [PATCH] Add https options and minor code changes Adds https options x_verify_certificate and x_verify_certificate_path in DotHill and rebranded drivers. Minor cosmetic changes like replacing 'realstor' with 'virtual' and 'wbi' with 'api'. Adding default value for 'x_backend_type' and 'x_api_protocol' options. Minor code optimization for finding array iSCSI addresses. Here 'x' stands for dothill or hpmsa or lenovo. DocImpact Change-Id: I7a5924bbd56053aee6d652842b48e913c54ae7dd Closes-Bug: #1486160 Co-Authored-By: Lakshman Co-Authored-By: Chris Maio --- cinder/tests/unit/test_dothill.py | 23 ++++++----- .../volume/drivers/dothill/dothill_client.py | 27 ++++++------ .../volume/drivers/dothill/dothill_common.py | 41 ++++++++++++------- cinder/volume/drivers/dothill/dothill_fc.py | 2 +- .../volume/drivers/dothill/dothill_iscsi.py | 2 +- cinder/volume/drivers/lenovo/lenovo_client.py | 5 ++- cinder/volume/drivers/lenovo/lenovo_common.py | 31 ++++++++++---- cinder/volume/drivers/san/hp/hpmsa_client.py | 4 +- cinder/volume/drivers/san/hp/hpmsa_common.py | 32 +++++++++++---- 9 files changed, 105 insertions(+), 62 deletions(-) diff --git a/cinder/tests/unit/test_dothill.py b/cinder/tests/unit/test_dothill.py index 6b9365bb1..6b55fa0af 100644 --- a/cinder/tests/unit/test_dothill.py +++ b/cinder/tests/unit/test_dothill.py @@ -51,7 +51,7 @@ response_stats_linear = ''' 3863830528 3863830528 ''' -response_stats_realstor = ''' +response_stats_virtual = ''' 3863830528 3863830528 ''' @@ -87,7 +87,7 @@ response_ports = ''' ''' response_ports_linear = response_ports % {'ip': 'primary-ip-address'} -response_ports_realstor = response_ports % {'ip': 'ip-address'} +response_ports_virtual = response_ports % {'ip': 'ip-address'} invalid_xml = '''''' @@ -146,8 +146,9 @@ class TestDotHillClient(test.TestCase): self.passwd = '!manage' self.ip = '10.0.0.1' self.protocol = 'http' + self.ssl_verify = False self.client = dothill.DotHillClient(self.ip, self.login, self.passwd, - self.protocol) + self.protocol, self.ssl_verify) @mock.patch('requests.get') def test_login(self, mock_requests_get): @@ -219,13 +220,13 @@ class TestDotHillClient(test.TestCase): stats = {'free_capacity_gb': 1979, 'total_capacity_gb': 1979} linear = etree.XML(response_stats_linear) - realstor = etree.XML(response_stats_realstor) - mock_request.side_effect = [linear, realstor] + virtual = etree.XML(response_stats_virtual) + mock_request.side_effect = [linear, virtual] self.assertEqual(stats, self.client.backend_stats('OpenStack', 'linear')) - self.assertEqual(stats, self.client.backend_stats('OpenStack', - 'realstor')) + self.assertEqual(stats, self.client.backend_stats('A', + 'virtual')) @mock.patch.object(dothill.DotHillClient, '_request') def test_get_lun(self, mock_request): @@ -266,10 +267,10 @@ class TestDotHillClient(test.TestCase): def test_get_iscsi_portals(self, mock_request): portals = {'10.0.0.12': 'Up', '10.0.0.11': 'Up'} mock_request.side_effect = [etree.XML(response_ports_linear), - etree.XML(response_ports_realstor)] - ret = self.client.get_active_iscsi_target_portals('linear') + etree.XML(response_ports_virtual)] + ret = self.client.get_active_iscsi_target_portals() self.assertEqual(portals, ret) - ret = self.client.get_active_iscsi_target_portals('realstor') + ret = self.client.get_active_iscsi_target_portals() self.assertEqual(portals, ret) @@ -279,7 +280,7 @@ class FakeConfiguration1(object): san_ip = '10.0.0.1' san_login = 'manage' san_password = '!manage' - dothill_wbi_protocol = 'http' + dothill_api_protocol = 'http' def safe_get(self, key): return 'fakevalue' diff --git a/cinder/volume/drivers/dothill/dothill_client.py b/cinder/volume/drivers/dothill/dothill_client.py index 5cc864805..c1da83132 100644 --- a/cinder/volume/drivers/dothill/dothill_client.py +++ b/cinder/volume/drivers/dothill/dothill_client.py @@ -30,11 +30,12 @@ LOG = logging.getLogger(__name__) class DotHillClient(object): - def __init__(self, host, login, password, protocol): + def __init__(self, host, login, password, protocol, ssl_verify): self._login = login self._password = password self._base_url = "%s://%s/api" % (protocol, host) self._session_key = None + self.ssl_verify = ssl_verify def _get_auth_token(self, xml): """Parse an XML authentication reply to extract the session key.""" @@ -53,7 +54,7 @@ class DotHillClient(object): url = self._base_url + "/login/" + digest try: - xml = requests.get(url) + xml = requests.get(url, verify=self.ssl_verify) except requests.exceptions.RequestException: raise exception.DotHillConnectionError @@ -96,7 +97,7 @@ class DotHillClient(object): url = self._build_request_url(path, *args, **kargs) headers = {'dataType': 'api', 'sessionKey': self._session_key} try: - xml = requests.get(url, headers=headers) + xml = requests.get(url, headers=headers, verify=self.ssl_verify) tree = etree.XML(xml.text.encode('utf8')) except Exception: raise exception.DotHillConnectionError @@ -109,7 +110,7 @@ class DotHillClient(object): def logout(self): url = self._base_url + '/exit' try: - requests.get(url) + requests.get(url, verify=self.ssl_verify) return True except Exception: return False @@ -275,10 +276,10 @@ class DotHillClient(object): return host_status def _safe_hostname(self, hostname): - """DotHill hostname restrictions. + """Modify an initiator name to match firmware requirements. - A host name cannot include " , \ in linear and " , < > \ in realstor - and can have a max of 15 bytes in linear and 32 bytes in realstor. + Initiator name cannot include certain characters and cannot exceed + 15 bytes in 'T' firmware (32 bytes in 'G' firmware). """ for ch in [',', '"', '\\', '<', '>']: if ch in hostname: @@ -288,16 +289,14 @@ class DotHillClient(object): index = 15 return hostname[:index] - def get_active_iscsi_target_portals(self, backend_type): + def get_active_iscsi_target_portals(self): # This function returns {'ip': status,} portals = {} - prop = "" + prop = 'ip-address' tree = self._request("/show/ports") - if backend_type == "linear": - prop = "primary-ip-address" - else: - prop = "ip-address" - + for el in tree.xpath("//PROPERTY[@name='primary-ip-address']"): + prop = 'primary-ip-address' + break iscsi_ips = [ip.text for ip in tree.xpath( "//PROPERTY[@name='%s']" % prop)] if not iscsi_ips: diff --git a/cinder/volume/drivers/dothill/dothill_common.py b/cinder/volume/drivers/dothill/dothill_common.py index 21dc9f16c..2c395137d 100644 --- a/cinder/volume/drivers/dothill/dothill_common.py +++ b/cinder/volume/drivers/dothill/dothill_common.py @@ -32,20 +32,28 @@ LOG = logging.getLogger(__name__) common_opt = [ cfg.StrOpt('dothill_backend_name', - default='OpenStack', - help="VDisk or Pool name to use for volume creation."), + default='A', + help="Pool or Vdisk name to use for volume creation."), cfg.StrOpt('dothill_backend_type', - choices=['linear', 'realstor'], - help="linear (for VDisk) or realstor (for Pool)."), - cfg.StrOpt('dothill_wbi_protocol', + choices=['linear', 'virtual'], + default='virtual', + help="linear (for Vdisk) or virtual (for Pool)."), + cfg.StrOpt('dothill_api_protocol', choices=['http', 'https'], - help="DotHill web interface protocol."), + default='https', + help="DotHill API interface protocol."), + cfg.BoolOpt('dothill_verify_certificate', + default=False, + help="Whether to verify DotHill array SSL certificate."), + cfg.StrOpt('dothill_verify_certificate_path', + default=None, + help="DotHill array SSL certificate path."), ] iscsi_opt = [ cfg.ListOpt('dothill_iscsi_ips', default=[], - help="List of comma separated target iSCSI IP addresses."), + help="List of comma-separated target iSCSI IP addresses."), ] CONF = cfg.CONF @@ -63,10 +71,16 @@ class DotHillCommon(object): self.vendor_name = "DotHill" self.backend_name = self.config.dothill_backend_name self.backend_type = self.config.dothill_backend_type + self.api_protocol = self.config.dothill_api_protocol + ssl_verify = False + if (self.api_protocol == 'https' and + self.config.dothill_verify_certificate): + ssl_verify = self.config.dothill_verify_certificate_path or True self.client = dothill.DotHillClient(self.config.san_ip, self.config.san_login, self.config.san_password, - self.config.dothill_wbi_protocol) + self.api_protocol, + ssl_verify) def get_version(self): return self.VERSION @@ -75,7 +89,7 @@ class DotHillCommon(object): self.client_login() self._validate_backend() if (self.backend_type == "linear" or - (self.backend_type == "realstor" and + (self.backend_type == "virtual" and self.backend_name not in ['A', 'B'])): self._get_owner_info(self.backend_name) self._get_serial_number() @@ -194,7 +208,7 @@ class DotHillCommon(object): raise exception.VolumeAttached(volume_id=volume['id']) def create_cloned_volume(self, volume, src_vref): - if self.backend_type == "realstor" and self.backend_name in ["A", "B"]: + if self.backend_type == "virtual" and self.backend_name in ["A", "B"]: msg = _("Create volume from volume(clone) does not have support " "for virtual pool A and B.") LOG.error(msg) @@ -223,7 +237,7 @@ class DotHillCommon(object): self.client_logout() def create_volume_from_snapshot(self, volume, snapshot): - if self.backend_type == "realstor" and self.backend_name in ["A", "B"]: + if self.backend_type == "virtual" and self.backend_name in ["A", "B"]: msg = _('Create volume from snapshot does not have support ' 'for virtual pool A and B.') LOG.error(msg) @@ -290,7 +304,7 @@ class DotHillCommon(object): self.backend_type) pool.update(backend_stats) if (self.backend_type == "linear" or - (self.backend_type == "realstor" and + (self.backend_type == "virtual" and self.backend_name not in ['A', 'B'])): pool['location_info'] = ('%s:%s:%s:%s' % (src_type, @@ -362,8 +376,7 @@ class DotHillCommon(object): def get_active_iscsi_target_portals(self): try: - return self.client.get_active_iscsi_target_portals( - self.backend_type) + return self.client.get_active_iscsi_target_portals() except exception.DotHillRequestError as ex: LOG.exception(_LE("Error getting active ISCSI target portals.")) raise exception.Invalid(ex) diff --git a/cinder/volume/drivers/dothill/dothill_fc.py b/cinder/volume/drivers/dothill/dothill_fc.py index 443cfc5a2..9bbebe40d 100644 --- a/cinder/volume/drivers/dothill/dothill_fc.py +++ b/cinder/volume/drivers/dothill/dothill_fc.py @@ -33,7 +33,7 @@ class DotHillFCDriver(cinder.volume.driver.FibreChannelDriver): cinder/volume/drivers/san/hp" 1.0 - Version developed for DotHill arrays with the following modifications: - - added support for v3 API(realstor feature) + - added support for v3 API(virtual pool feature) - added support for retype volume - added support for manage/unmanage volume - added initiator target mapping in FC zoning diff --git a/cinder/volume/drivers/dothill/dothill_iscsi.py b/cinder/volume/drivers/dothill/dothill_iscsi.py index 84f5933c3..e6ddc1dac 100644 --- a/cinder/volume/drivers/dothill/dothill_iscsi.py +++ b/cinder/volume/drivers/dothill/dothill_iscsi.py @@ -39,7 +39,7 @@ class DotHillISCSIDriver(cinder.volume.driver.ISCSIDriver): modifications: - added iSCSI support - added CHAP support in iSCSI - - added support for v3 API(realstor feature) + - added support for v3 API(virtual pool feature) - added support for retype volume - added support for manage/unmanage volume - added https support diff --git a/cinder/volume/drivers/lenovo/lenovo_client.py b/cinder/volume/drivers/lenovo/lenovo_client.py index 1518f53dd..07e807cdb 100644 --- a/cinder/volume/drivers/lenovo/lenovo_client.py +++ b/cinder/volume/drivers/lenovo/lenovo_client.py @@ -19,5 +19,6 @@ from cinder.volume.drivers.dothill import dothill_client class LenovoClient(dothill_client.DotHillClient): - def __init__(self, host, login, password, protocol): - super(LenovoClient, self).__init__(host, login, password, protocol) + def __init__(self, host, login, password, protocol, ssl_verify): + super(LenovoClient, self).__init__(host, login, password, protocol, + ssl_verify) diff --git a/cinder/volume/drivers/lenovo/lenovo_common.py b/cinder/volume/drivers/lenovo/lenovo_common.py index 9b3878376..95cb91e9b 100644 --- a/cinder/volume/drivers/lenovo/lenovo_common.py +++ b/cinder/volume/drivers/lenovo/lenovo_common.py @@ -21,20 +21,28 @@ from cinder.volume.drivers.lenovo import lenovo_client common_opt = [ cfg.StrOpt('lenovo_backend_name', - default='OpenStack', - help="VDisk or Pool name to use for volume creation."), + default='A', + help="Pool or Vdisk name to use for volume creation."), cfg.StrOpt('lenovo_backend_type', - choices=['linear', 'realstor'], - help="linear (for VDisk) or realstor (for Pool)."), - cfg.StrOpt('lenovo_wbi_protocol', + choices=['linear', 'virtual'], + default='virtual', + help="linear (for VDisk) or virtual (for Pool)."), + cfg.StrOpt('lenovo_api_protocol', choices=['http', 'https'], - help="Lenovo web interface protocol."), + default='https', + help="Lenovo api interface protocol."), + cfg.BoolOpt('lenovo_verify_certificate', + default=False, + help="Whether to verify Lenovo array SSL certificate."), + cfg.StrOpt('lenovo_verify_certificate_path', + default=None, + help="Lenovo array SSL certificate path.") ] iscsi_opt = [ cfg.ListOpt('lenovo_iscsi_ips', default=[], - help="List of comma separated target iSCSI IP addresses."), + help="List of comma-separated target iSCSI IP addresses."), ] CONF = cfg.CONF @@ -50,8 +58,13 @@ class LenovoCommon(dothill_common.DotHillCommon): self.vendor_name = "Lenovo" self.backend_name = self.config.lenovo_backend_name self.backend_type = self.config.lenovo_backend_type - self.wbi_protocol = self.config.lenovo_wbi_protocol + self.api_protocol = self.config.lenovo_api_protocol + ssl_verify = False + if (self.api_protocol == 'https' and + self.config.lenovo_verify_certificate): + ssl_verify = self.config.lenovo_verify_certificate_path or True self.client = lenovo_client.LenovoClient(self.config.san_ip, self.config.san_login, self.config.san_password, - self.wbi_protocol) + self.api_protocol, + ssl_verify) diff --git a/cinder/volume/drivers/san/hp/hpmsa_client.py b/cinder/volume/drivers/san/hp/hpmsa_client.py index 43185525b..bec7bfd44 100644 --- a/cinder/volume/drivers/san/hp/hpmsa_client.py +++ b/cinder/volume/drivers/san/hp/hpmsa_client.py @@ -19,6 +19,6 @@ from cinder.volume.drivers.dothill import dothill_client class HPMSAClient(dothill_client.DotHillClient): - def __init__(self, host, login, password, protocol): + def __init__(self, host, login, password, protocol, ssl_verify): super(HPMSAClient, self).__init__(host, login, password, - protocol) + protocol, ssl_verify) diff --git a/cinder/volume/drivers/san/hp/hpmsa_common.py b/cinder/volume/drivers/san/hp/hpmsa_common.py index 051ae4b76..8c16bc33c 100644 --- a/cinder/volume/drivers/san/hp/hpmsa_common.py +++ b/cinder/volume/drivers/san/hp/hpmsa_common.py @@ -21,20 +21,29 @@ from cinder.volume.drivers.san.hp import hpmsa_client common_opt = [ cfg.StrOpt('hpmsa_backend_name', - default='OpenStack', - help="VDisk or Pool name to use for volume creation."), + default='A', + help="Pool or Vdisk name to use for volume creation."), cfg.StrOpt('hpmsa_backend_type', - choices=['linear', 'realstor'], - help="linear (for VDisk) or realstor (for Pool)."), - cfg.StrOpt('hpmsa_wbi_protocol', + choices=['linear', 'virtual'], + default='virtual', + help="linear (for Vdisk) or virtual (for Pool)."), + cfg.StrOpt('hpmsa_api_protocol', choices=['http', 'https'], - help="HPMSA web interface protocol."), + default='https', + help="HPMSA API interface protocol."), + cfg.BoolOpt('hpmsa_verify_certificate', + default=False, + help="Whether to verify HPMSA array SSL certificate."), + cfg.StrOpt('hpmsa_verify_certificate_path', + default=None, + help="HPMSA array SSL certificate path."), + ] iscsi_opt = [ cfg.ListOpt('hpmsa_iscsi_ips', default=[], - help="List of comma separated target iSCSI IP addresses."), + help="List of comma-separated target iSCSI IP addresses."), ] CONF = cfg.CONF @@ -50,7 +59,14 @@ class HPMSACommon(dothill_common.DotHillCommon): self.vendor_name = "HPMSA" self.backend_name = self.config.hpmsa_backend_name self.backend_type = self.config.hpmsa_backend_type + self.api_protocol = self.config.hpmsa_api_protocol + ssl_verify = False + if (self.api_protocol == 'https' and + self.config.hpmsa_verify_certificate): + ssl_verify = self.config.hpmsa_verify_certificate_path or True + self.client = hpmsa_client.HPMSAClient(self.config.san_ip, self.config.san_login, self.config.san_password, - self.config.hpmsa_wbi_protocol) + self.api_protocol, + ssl_verify) -- 2.45.2