Merge "Add ports filtering support to Dell EMC XtremIO driver" into stable/ussuri
This commit is contained in:
commit
f7a8e09c10
|
@ -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
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ Supports 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
|
||||
|
@ -82,7 +83,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)
|
||||
|
||||
|
@ -420,7 +427,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"
|
||||
|
@ -444,6 +451,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)
|
||||
|
||||
@classmethod
|
||||
|
@ -1063,6 +1074,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):
|
||||
|
@ -1180,26 +1204,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):
|
||||
|
@ -1222,8 +1253,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")))
|
||||
|
|
|
@ -233,6 +233,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
|
||||
|
@ -250,6 +260,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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
`Bug #1915800 <https://bugs.launchpad.net/cinder/+bug/1915800>`_:
|
||||
Add support for ports filtering in XtremIO driver.
|
Loading…
Reference in New Issue