Merge "Add ports filtering support to Dell EMC XtremIO driver" into stable/victoria

This commit is contained in:
Zuul 2021-03-20 01:54:25 +00:00 committed by Gerrit Code Review
commit 7cedb079ff
4 changed files with 119 additions and 17 deletions

View File

@ -62,6 +62,14 @@ xms_init = {'xms': {1: {'version': '4.2.0',
"name": "10.205.68.5/16", "name": "10.205.68.5/16",
"index": 1, "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", 'targets': {'X1-SC2-target1': {'index': 1, "name": "X1-SC2-fc1",
"port-address": "port-address":
@ -347,7 +355,8 @@ class BaseXtremIODriverTestCase(test.TestCase):
driver_ssl_cert_path='/test/path/root_ca.crt', driver_ssl_cert_path='/test/path/root_ca.crt',
xtremio_array_busy_retry_count=5, xtremio_array_busy_retry_count=5,
xtremio_array_busy_retry_interval=5, xtremio_array_busy_retry_interval=5,
xtremio_clean_unused_ig=False) xtremio_clean_unused_ig=False,
xtremio_ports=[])
def safe_get(key): def safe_get(key):
return getattr(self.config, key) return getattr(self.config, key)
@ -650,10 +659,26 @@ class XtremIODriverISCSITestCase(BaseXtremIODriverTestCase):
portals = xms_data['iscsi-portals'].copy() portals = xms_data['iscsi-portals'].copy()
xms_data['iscsi-portals'].clear() xms_data['iscsi-portals'].clear()
lunmap = {'lun': 4} lunmap = {'lun': 4}
self.assertRaises(exception.VolumeDriverException, self.assertRaises(exception.VolumeBackendAPIException,
self.driver._get_iscsi_properties, lunmap) self.driver._get_iscsi_properties, lunmap)
xms_data['iscsi-portals'] = portals 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): def test_initialize_connection(self, req):
req.side_effect = xms_request req.side_effect = xms_request
self.driver.create_volume(self.data.test_volume) self.driver.create_volume(self.data.test_volume)
@ -1365,6 +1390,27 @@ class XtremIODriverFCTestCase(BaseXtremIODriverTestCase):
configuration=self.config) configuration=self.config)
# ##### Connection FC##### # ##### 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): def test_initialize_connection(self, req):
req.side_effect = xms_request req.side_effect = xms_request

View File

@ -31,6 +31,7 @@ Supports XtremIO version 2.4 and up.
1.0.9 - performance improvements, support force detach, support for X2 1.0.9 - performance improvements, support force detach, support for X2
1.0.10 - option to clean unused IGs 1.0.10 - option to clean unused IGs
1.0.11 - add support for multiattach 1.0.11 - add support for multiattach
1.0.12 - add support for ports filtering
""" """
import json import json
@ -82,7 +83,13 @@ XTREMIO_OPTS = [
'the IG be, we default to False (not deleting IGs ' 'the IG be, we default to False (not deleting IGs '
'without connected volumes); setting this parameter ' 'without connected volumes); setting this parameter '
'to True will remove any IG after terminating its ' '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) CONF.register_opts(XTREMIO_OPTS, group=configuration.SHARED_CONF_GROUP)
@ -420,7 +427,7 @@ class XtremIOClient42(XtremIOClient4):
class XtremIOVolumeDriver(san.SanDriver): class XtremIOVolumeDriver(san.SanDriver):
"""Executes commands relating to Volumes.""" """Executes commands relating to Volumes."""
VERSION = '1.0.11' VERSION = '1.0.12'
# ThirdPartySystems wiki # ThirdPartySystems wiki
CI_WIKI_NAME = "EMC_XIO_CI" CI_WIKI_NAME = "EMC_XIO_CI"
@ -444,6 +451,10 @@ class XtremIOVolumeDriver(san.SanDriver):
self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig') self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig')
or False) or False)
self._stats = {} 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) self.client = XtremIOClient3(self.configuration, self.cluster_id)
@classmethod @classmethod
@ -1054,6 +1065,19 @@ class XtremIOVolumeDriver(san.SanDriver):
raise (exception.VolumeBackendAPIException raise (exception.VolumeBackendAPIException
(data=_("Failed to create IG, %s") % name)) (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 @interface.volumedriver
class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver): class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver):
@ -1171,26 +1195,33 @@ class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver):
multiple values. The main portal information is also returned in multiple values. The main portal information is also returned in
:target_iqn, :target_portal, :target_lun for backward compatibility. :target_iqn, :target_portal, :target_lun for backward compatibility.
""" """
portals = self.client.get_iscsi_portals() iscsi_portals = self.client.get_iscsi_portals()
if not portals: allowed_portals = []
msg = _("XtremIO not configured correctly, no iscsi portals found") for iscsi_portal in iscsi_portals:
LOG.error(msg) iscsi_portal['ip-addr'] = iscsi_portal['ip-addr'].split('/')[0]
raise exception.VolumeDriverException(message=msg) if self._port_is_allowed(iscsi_portal['ip-addr']):
portal = RANDOM.choice(portals) 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' % portal_addr = ('%(ip)s:%(port)d' %
{'ip': portal['ip-addr'].split('/')[0], {'ip': portal['ip-addr'],
'port': portal['ip-port']}) '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']} 'port': p['ip-port']}
for p in portals] for p in allowed_portals]
properties = {'target_discovered': False, properties = {'target_discovered': False,
'target_iqn': portal['port-address'], 'target_iqn': portal['port-address'],
'target_lun': lunmap['lun'], 'target_lun': lunmap['lun'],
'target_portal': portal_addr, '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_portals': tg_portals,
'target_luns': [lunmap['lun']] * len(portals)} 'target_luns': [lunmap['lun']] * len(allowed_portals)}
return properties return properties
def _get_initiator_names(self, connector): def _get_initiator_names(self, connector):
@ -1213,8 +1244,17 @@ class XtremIOFCDriver(XtremIOVolumeDriver,
if not self._targets: if not self._targets:
try: try:
targets = self.client.get_fc_up_ports() targets = self.client.get_fc_up_ports()
self._targets = [target['port-address'].replace(':', '') allowed_targets = []
for target in 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: except exception.NotFound:
raise (exception.VolumeBackendAPIException raise (exception.VolumeBackendAPIException
(data=_("Failed to get targets"))) (data=_("Failed to get targets")))

View File

@ -233,6 +233,16 @@ The CHAP initiator authentication and discovery credentials (username and
password) are generated automatically by the Block Storage driver. Therefore, password) are generated automatically by the Block Storage driver. Therefore,
there is no need to configure the initial CHAP credentials manually in XMS. 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: .. _emc_extremio_configuration_example:
Configuration example Configuration example
@ -250,6 +260,7 @@ follows:
volume_driver = cinder.volume.drivers.dell_emc.xtremio.XtremIOFibreChannelDriver volume_driver = cinder.volume.drivers.dell_emc.xtremio.XtremIOFibreChannelDriver
san_ip = XMS_IP san_ip = XMS_IP
xtremio_cluster_name = Cluster01 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_login = XMS_USER
san_password = XMS_PASSWD san_password = XMS_PASSWD
volume_backend_name = XtremIOAFA volume_backend_name = XtremIOAFA

View File

@ -0,0 +1,5 @@
---
fixes:
- |
`Bug #1915800 <https://bugs.launchpad.net/cinder/+bug/1915800>`_:
Add support for ports filtering in XtremIO driver.