Merge "Add ports filtering support to Dell EMC XtremIO driver" into stable/train
This commit is contained in:
commit
4947045d5b
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ supported 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
|
||||||
|
@ -83,7 +84,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)
|
||||||
|
|
||||||
|
@ -421,7 +428,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"
|
||||||
|
@ -445,6 +452,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)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -1060,6 +1071,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):
|
||||||
|
@ -1177,26 +1201,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):
|
||||||
|
@ -1219,8 +1250,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")))
|
||||||
|
|
|
@ -232,6 +232,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
|
||||||
|
@ -249,6 +259,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
|
||||||
|
|
|
@ -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