From 82427ff40fb4e6122dba05c8af16e76d5759d2d5 Mon Sep 17 00:00:00 2001 From: Ivan Pchelintsev Date: Tue, 16 Feb 2021 13:29:24 +0300 Subject: [PATCH] Add ports filtering support to Dell EMC XtremIO driver If there are some iSCSI or FC targets (ESXi for example) that are not connected to the OpenStack host, attach volume operation waits until timeout. The XtremIO Cinder driver needs a new option to support ports filtering. Change-Id: I2a521118598de336148a56c1d5352107ece80721 Closes-Bug: #1915800 (cherry picked from commit e175d64cac735e8845165d0e8b48c4a8f2402ea1) (cherry picked from commit a357ca2755d613ba31556d2f42c120b4cafdc2be) (cherry picked from commit d9c029c174ab872c19f3fe2da504d87015ff60a5) --- .../volume/drivers/dell_emc/test_xtremio.py | 50 ++++++++++++- cinder/volume/drivers/dell_emc/xtremio.py | 70 +++++++++++++++---- .../drivers/dell-emc-xtremio-driver.rst | 11 +++ ...emio-ports-filtering-e68f90d47f17a7d9.yaml | 5 ++ 4 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 releasenotes/notes/bug-1900979-xtremio-ports-filtering-e68f90d47f17a7d9.yaml diff --git a/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py b/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py index 5461f94f18a..2a3502c0682 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py @@ -62,6 +62,14 @@ xms_init = {'xms': {1: {'version': '4.2.0', "name": "10.205.68.5/16", "index": 1, }, + '10.205.68.6/16': + {"port-address": + "iqn.2008-05.com.xtremio:002e67939c34", + "ip-port": 3260, + "ip-addr": "10.205.68.6/16", + "name": "10.205.68.6/16", + "index": 1, + }, }, 'targets': {'X1-SC2-target1': {'index': 1, "name": "X1-SC2-fc1", "port-address": @@ -347,7 +355,8 @@ class BaseXtremIODriverTestCase(test.TestCase): driver_ssl_cert_path='/test/path/root_ca.crt', xtremio_array_busy_retry_count=5, xtremio_array_busy_retry_interval=5, - xtremio_clean_unused_ig=False) + xtremio_clean_unused_ig=False, + xtremio_ports=[]) def safe_get(key): return getattr(self.config, key) @@ -650,10 +659,26 @@ class XtremIODriverISCSITestCase(BaseXtremIODriverTestCase): portals = xms_data['iscsi-portals'].copy() xms_data['iscsi-portals'].clear() lunmap = {'lun': 4} - self.assertRaises(exception.VolumeDriverException, + self.assertRaises(exception.VolumeBackendAPIException, self.driver._get_iscsi_properties, lunmap) xms_data['iscsi-portals'] = portals + def test_no_allowed_portals(self, req): + req.side_effect = xms_request + lunmap = {'lun': 4} + self.driver.allowed_ports = ['1.2.3.4'] + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_iscsi_properties, lunmap) + + def test_filtered_portals(self, req): + req.side_effect = xms_request + lunmap = {'lun': 4} + self.driver.allowed_ports = ['10.205.68.6'] + connection_properties = self.driver._get_iscsi_properties(lunmap) + self.assertEqual(1, len(connection_properties['target_portals'])) + self.assertIn('10.205.68.6:3260', + connection_properties['target_portals']) + def test_initialize_connection(self, req): req.side_effect = xms_request self.driver.create_volume(self.data.test_volume) @@ -1365,6 +1390,27 @@ class XtremIODriverFCTestCase(BaseXtremIODriverTestCase): configuration=self.config) # ##### Connection FC##### + def test_no_targets_configured(self, req): + req.side_effect = xms_request + targets = xms_data['targets'].copy() + xms_data['targets'].clear() + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.get_targets) + xms_data['targets'] = targets + + def test_no_allowed_targets(self, req): + req.side_effect = xms_request + self.driver.allowed_ports = ['58:cc:f0:98:49:22:07:02'] + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.get_targets) + + def test_filtered_targets(self, req): + req.side_effect = xms_request + self.driver.allowed_ports = ['21:00:00:24:ff:57:b2:36'] + targets = self.driver.get_targets() + self.assertEqual(1, len(targets)) + self.assertIn('21000024ff57b236', targets) + def test_initialize_connection(self, req): req.side_effect = xms_request diff --git a/cinder/volume/drivers/dell_emc/xtremio.py b/cinder/volume/drivers/dell_emc/xtremio.py index 82818d02a98..c57241ba053 100644 --- a/cinder/volume/drivers/dell_emc/xtremio.py +++ b/cinder/volume/drivers/dell_emc/xtremio.py @@ -31,6 +31,7 @@ supported XtremIO version 2.4 and up 1.0.9 - performance improvements, support force detach, support for X2 1.0.10 - option to clean unused IGs 1.0.11 - add support for multiattach + 1.0.12 - add support for ports filtering """ import json @@ -83,7 +84,13 @@ XTREMIO_OPTS = [ 'the IG be, we default to False (not deleting IGs ' 'without connected volumes); setting this parameter ' 'to True will remove any IG after terminating its ' - 'connection to the last volume.')] + 'connection to the last volume.'), + cfg.ListOpt('xtremio_ports', + default=[], + help='Allowed ports. Comma separated list of XtremIO ' + 'iSCSI IPs or FC WWNs (ex. 58:cc:f0:98:49:22:07:02) ' + 'to be used. If option is not set all ports are allowed.') +] CONF.register_opts(XTREMIO_OPTS, group=configuration.SHARED_CONF_GROUP) @@ -421,7 +428,7 @@ class XtremIOClient42(XtremIOClient4): class XtremIOVolumeDriver(san.SanDriver): """Executes commands relating to Volumes.""" - VERSION = '1.0.11' + VERSION = '1.0.12' # ThirdPartySystems wiki CI_WIKI_NAME = "EMC_XIO_CI" @@ -445,6 +452,10 @@ class XtremIOVolumeDriver(san.SanDriver): self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig') or False) self._stats = {} + self.allowed_ports = [ + port.strip().lower() for port in + self.configuration.safe_get('xtremio_ports') + ] self.client = XtremIOClient3(self.configuration, self.cluster_id) @staticmethod @@ -1060,6 +1071,19 @@ class XtremIOVolumeDriver(san.SanDriver): raise (exception.VolumeBackendAPIException (data=_("Failed to create IG, %s") % name)) + def _port_is_allowed(self, port): + """Check if port is in allowed ports list. + + If allowed ports are empty then all ports are allowed. + + :param port: iSCSI IP/FC WWN to check + :return: is port allowed + """ + + if not self.allowed_ports: + return True + return port.lower() in self.allowed_ports + @interface.volumedriver class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver): @@ -1177,26 +1201,33 @@ class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver): multiple values. The main portal information is also returned in :target_iqn, :target_portal, :target_lun for backward compatibility. """ - portals = self.client.get_iscsi_portals() - if not portals: - msg = _("XtremIO not configured correctly, no iscsi portals found") - LOG.error(msg) - raise exception.VolumeDriverException(message=msg) - portal = RANDOM.choice(portals) + iscsi_portals = self.client.get_iscsi_portals() + allowed_portals = [] + for iscsi_portal in iscsi_portals: + iscsi_portal['ip-addr'] = iscsi_portal['ip-addr'].split('/')[0] + if self._port_is_allowed(iscsi_portal['ip-addr']): + allowed_portals.append(iscsi_portal) + if not allowed_portals: + msg = _("There are no accessible iSCSI targets on the " + "system.") + raise exception.VolumeBackendAPIException(data=msg) + portal = RANDOM.choice(allowed_portals) portal_addr = ('%(ip)s:%(port)d' % - {'ip': portal['ip-addr'].split('/')[0], + {'ip': portal['ip-addr'], 'port': portal['ip-port']}) - tg_portals = ['%(ip)s:%(port)d' % {'ip': p['ip-addr'].split('/')[0], + tg_portals = ['%(ip)s:%(port)d' % {'ip': p['ip-addr'], 'port': p['ip-port']} - for p in portals] + for p in allowed_portals] properties = {'target_discovered': False, 'target_iqn': portal['port-address'], 'target_lun': lunmap['lun'], 'target_portal': portal_addr, - 'target_iqns': [p['port-address'] for p in portals], + 'target_iqns': [ + p['port-address'] for p in allowed_portals + ], 'target_portals': tg_portals, - 'target_luns': [lunmap['lun']] * len(portals)} + 'target_luns': [lunmap['lun']] * len(allowed_portals)} return properties def _get_initiator_names(self, connector): @@ -1219,8 +1250,17 @@ class XtremIOFCDriver(XtremIOVolumeDriver, if not self._targets: try: targets = self.client.get_fc_up_ports() - self._targets = [target['port-address'].replace(':', '') - for target in targets] + allowed_targets = [] + for target in targets: + if self._port_is_allowed(target['port-address']): + allowed_targets.append( + target['port-address'].replace(':', '') + ) + if not allowed_targets: + msg = _("There are no accessible Fibre Channel targets " + "on the system.") + raise exception.VolumeBackendAPIException(data=msg) + self._targets = allowed_targets except exception.NotFound: raise (exception.VolumeBackendAPIException (data=_("Failed to get targets"))) diff --git a/doc/source/configuration/block-storage/drivers/dell-emc-xtremio-driver.rst b/doc/source/configuration/block-storage/drivers/dell-emc-xtremio-driver.rst index c4e1d172ab0..7eb2896d485 100644 --- a/doc/source/configuration/block-storage/drivers/dell-emc-xtremio-driver.rst +++ b/doc/source/configuration/block-storage/drivers/dell-emc-xtremio-driver.rst @@ -232,6 +232,16 @@ The CHAP initiator authentication and discovery credentials (username and password) are generated automatically by the Block Storage driver. Therefore, there is no need to configure the initial CHAP credentials manually in XMS. +Configuring ports filtering +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The XtremIO Block Storage driver supports ports filtering to define a list +of iSCSI IP-addresses or FC WWNs which will be used to attach volumes. +If option is not set all ports are allowed. + +.. code-block:: ini + + xtremio_ports = iSCSI IPs or FC WWNs + .. _emc_extremio_configuration_example: Configuration example @@ -249,6 +259,7 @@ follows: volume_driver = cinder.volume.drivers.dell_emc.xtremio.XtremIOFibreChannelDriver san_ip = XMS_IP xtremio_cluster_name = Cluster01 + xtremio_ports = 21:00:00:24:ff:57:b2:36,21:00:00:24:ff:57:b2:55 san_login = XMS_USER san_password = XMS_PASSWD volume_backend_name = XtremIOAFA diff --git a/releasenotes/notes/bug-1900979-xtremio-ports-filtering-e68f90d47f17a7d9.yaml b/releasenotes/notes/bug-1900979-xtremio-ports-filtering-e68f90d47f17a7d9.yaml new file mode 100644 index 00000000000..1b65880843f --- /dev/null +++ b/releasenotes/notes/bug-1900979-xtremio-ports-filtering-e68f90d47f17a7d9.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + `Bug #1915800 `_: + Add support for ports filtering in XtremIO driver.