From 23cfc6efab58b239b37c6bdd16852239810dbbac Mon Sep 17 00:00:00 2001 From: Simon Dodsley Date: Tue, 14 May 2019 18:01:44 -0400 Subject: [PATCH] Pure Storage FlashArray iSCSI driver target CIDR support Add new configuration parameter to allow user to specify the CIDR of iSCSI targets on a FlashArray that can be connected to. This allows a FlashArray to have targets in multiple VLANs and Cinder not try to connect to inaccesible targets which can cause serious timeouts when connecting Cinder volumes to hosts. Default setting will be 0.0.0.0/0 which allow connection to any live iSCSI target. Change-Id: Ic813445cb5d55edb68ca8e756b9350ca7e8a1270 --- cinder/tests/unit/volume/drivers/test_pure.py | 2 ++ cinder/volume/drivers/pure.py | 30 +++++++++++++++++-- .../pure-iscsi-cidr-cbc1afb3850a9217.yaml | 7 +++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/pure-iscsi-cidr-cbc1afb3850a9217.yaml diff --git a/cinder/tests/unit/volume/drivers/test_pure.py b/cinder/tests/unit/volume/drivers/test_pure.py index 06d0cc818a2..c8abb04bbd5 100644 --- a/cinder/tests/unit/volume/drivers/test_pure.py +++ b/cinder/tests/unit/volume/drivers/test_pure.py @@ -76,6 +76,7 @@ ISCSI_PORT_NAMES = ["ct0.eth2", "ct0.eth3", "ct1.eth2", "ct1.eth3"] FC_PORT_NAMES = ["ct0.fc2", "ct0.fc3", "ct1.fc2", "ct1.fc3"] ISCSI_IPS = ["10.0.0." + str(i + 1) for i in range(len(ISCSI_PORT_NAMES))] AC_ISCSI_IPS = ["10.1.1." + str(i + 1) for i in range(len(ISCSI_PORT_NAMES))] +ISCSI_CIDR = "0.0.0.0/0" FC_WWNS = ["21000024ff59fe9" + str(i + 1) for i in range(len(FC_PORT_NAMES))] AC_FC_WWNS = [ "21000024ff59fab" + str(i + 1) for i in range(len(FC_PORT_NAMES))] @@ -489,6 +490,7 @@ class PureDriverTestCase(test.TestCase): self.mock_config.pure_eradicate_on_delete = False self.mock_config.driver_ssl_cert_verify = False self.mock_config.driver_ssl_cert_path = None + self.mock_config.pure_iscsi_cidr = ISCSI_CIDR self.array = mock.Mock() self.array.get.return_value = GET_ARRAY_PRIMARY self.array.array_name = GET_ARRAY_PRIMARY["array_name"] diff --git a/cinder/volume/drivers/pure.py b/cinder/volume/drivers/pure.py index aa06ef043fa..3941d70649f 100644 --- a/cinder/volume/drivers/pure.py +++ b/cinder/volume/drivers/pure.py @@ -19,6 +19,7 @@ This driver requires Purity version 4.0.0 or later. """ import functools +import ipaddress import math import platform import re @@ -83,6 +84,10 @@ PURE_OPTS = [ cfg.StrOpt("pure_replication_pod_name", default="cinder-pod", help="Pure Pod name to use for sync replication " "(will be created if it does not exist)."), + cfg.StrOpt("pure_iscsi_cidr", default="0.0.0.0/0", + help="CIDR of FlashArray iSCSI targets hosts are allowed to " + "connect to. Default will allow connection to any " + "IP address."), cfg.BoolOpt("pure_eradicate_on_delete", default=False, help="When enabled, all Pure volumes, snapshots, and " @@ -2323,7 +2328,7 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver): the underlying storage connectivity with the FlashArray. """ - VERSION = "8.0.0" + VERSION = "9.0.0" def __init__(self, *args, **kwargs): execute = kwargs.pop("execute", utils.execute) @@ -2391,6 +2396,7 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver): target_luns = [] target_iqns = [] target_portals = [] + valid_portals = [] # Aggregate all targets together, we may end up with different LUNs # for different target iqn/portal sets (ie. it could be a unique LUN @@ -2402,11 +2408,29 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver): target_iqns.append(port["iqn"]) target_portals.append(port["portal"]) + # Check to ensure all returned portal IP addresses + # are in iSCSI target CIDR + if not isinstance(self.configuration.pure_iscsi_cidr, six.text_type): + cidr = self.configuration.pure_iscsi_cidr.decode('utf8') + else: + cidr = self.configuration.pure_iscsi_cidr + check_cidr = ipaddress.IPv4Network(cidr) + for target_portal in target_portals: + if not isinstance(target_portal.split(":")[0], six.text_type): + portal = (target_portal.split(":")[0]).decode('utf8') + else: + portal = target_portal.split(":")[0] + check_ip = ipaddress.IPv4Address(portal) + if check_ip in check_cidr: + valid_portals.append(target_portal) + LOG.info("iSCSI target portals that match CIDR range: '%s'", + valid_portals) + # If we have multiple ports always report them. - if target_luns and target_iqns and target_portals: + if target_luns and target_iqns and valid_portals: props["data"]["target_luns"] = target_luns props["data"]["target_iqns"] = target_iqns - props["data"]["target_portals"] = target_portals + props["data"]["target_portals"] = valid_portals return props diff --git a/releasenotes/notes/pure-iscsi-cidr-cbc1afb3850a9217.yaml b/releasenotes/notes/pure-iscsi-cidr-cbc1afb3850a9217.yaml new file mode 100644 index 00000000000..e784d9dd1a2 --- /dev/null +++ b/releasenotes/notes/pure-iscsi-cidr-cbc1afb3850a9217.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Pure Storage FlashArray driver has added configuration option + ``pure_iscsi_cidr`` for setting a network CIDR for iSCSI target + connection. The default value will allow connections to all + iSCSI targets.