From 8a997d88ae2b3c1a925ecd107c50fc3122e05029 Mon Sep 17 00:00:00 2001 From: rajinir Date: Wed, 13 May 2020 16:48:32 -0500 Subject: [PATCH] Dell EMC Sc: Add support for whitelisting fault domains Added an ``included_domain_ips`` option to the Dell EMC SC driver. This option takes a comma separated list of target IP addresses listed under the fault domains to whitelisted. This option only applies to the ISCSI driver. Change-Id: I41448202ba1874b90b6865e63eb2c597bf6fda36 --- .../volume/drivers/dell_emc/sc/test_fc.py | 1 + .../volume/drivers/dell_emc/sc/test_sc.py | 1 + .../volume/drivers/dell_emc/sc/test_scapi.py | 266 ++++++++++++++++++ .../drivers/dell_emc/sc/storagecenter_api.py | 18 +- .../dell_emc/sc/storagecenter_common.py | 5 + .../drivers/dell_emc/sc/storagecenter_fc.py | 3 +- .../dell_emc/sc/storagecenter_iscsi.py | 3 +- .../drivers/dell-storagecenter-driver.rst | 32 ++- ...d_domain_ips_ListOpt-61bacddee199ce83.yaml | 6 + 9 files changed, 329 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/SC-included_domain_ips_ListOpt-61bacddee199ce83.yaml diff --git a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_fc.py b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_fc.py index 8d97c53bf50..f60f1f80acd 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_fc.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_fc.py @@ -146,6 +146,7 @@ class DellSCSanFCDriverTestCase(test.TestCase): self.configuration.dell_sc_api_port = 3033 self.configuration.excluded_domain_ip = None self.configuration.excluded_domain_ips = [] + self.configuration.included_domain_ips = [] self._context = context.get_admin_context() self.driver = storagecenter_fc.SCFCDriver( diff --git a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_sc.py b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_sc.py index 8c1b2bfbf42..39543fd17e6 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_sc.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_sc.py @@ -229,6 +229,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase): self.configuration.target_port = 3260 self.configuration.excluded_domain_ip = None self.configuration.excluded_domain_ips = [] + self.configuration.included_domain_ips = [] self._context = context.get_admin_context() self.driver = storagecenter_iscsi.SCISCSIDriver( diff --git a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py index cf7b7d8f43c..b85329eccc4 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/sc/test_scapi.py @@ -1194,6 +1194,70 @@ class DellSCSanAPITestCase(test.TestCase): u'bidirectionalChapSecret': u'', u'keepAliveTimeout': u'SECONDS_30'}] + ISCSI_FLT_DOMAINS_MULTI_PORTALS_IPV6 = \ + [{u'headerDigestEnabled': False, + u'classOfServicePriority': 0, + u'wellKnownIpAddress': u'0:0:0:0:0:ffff:c0a8:15', + u'scSerialNumber': 64702, + u'iscsiName': + u'iqn.2002-03.com.compellent:5000d31000fcbe42', + u'portNumber': 3260, + u'subnetMask': u'255.255.255.0', + u'gateway': u'192.168.0.1', + u'objectType': u'ScIscsiFaultDomain', + u'chapEnabled': False, + u'instanceId': u'64702.6.5.3', + u'childStatus': u'Up', + u'defaultTimeToRetain': u'SECONDS_20', + u'dataDigestEnabled': False, + u'instanceName': u'iSCSI 10G 2', + u'statusMessage': u'', + u'status': u'Up', + u'transportType': u'Iscsi', + u'vlanId': 0, + u'windowSize': u'131072.0 Bytes', + u'defaultTimeToWait': u'SECONDS_2', + u'scsiCommandTimeout': u'MINUTES_1', + u'deleteAllowed': False, + u'name': u'iSCSI 10G 2', + u'immediateDataWriteEnabled': False, + u'scName': u'Storage Center 64702', + u'notes': u'', + u'mtu': u'MTU_1500', + u'bidirectionalChapSecret': u'', + u'keepAliveTimeout': u'SECONDS_30'}, + {u'headerDigestEnabled': False, + u'classOfServicePriority': 0, + u'wellKnownIpAddress': u'0:0:0:0:0:ffff:c0a8:19', + u'scSerialNumber': 64702, + u'iscsiName': + u'iqn.2002-03.com.compellent:5000d31000fcbe42', + u'portNumber': 3260, + u'subnetMask': u'255.255.255.0', + u'gateway': u'192.168.0.1', + u'objectType': u'ScIscsiFaultDomain', + u'chapEnabled': False, + u'instanceId': u'64702.6.5.3', + u'childStatus': u'Up', + u'defaultTimeToRetain': u'SECONDS_20', + u'dataDigestEnabled': False, + u'instanceName': u'iSCSI 10G 2', + u'statusMessage': u'', + u'status': u'Up', + u'transportType': u'Iscsi', + u'vlanId': 0, + u'windowSize': u'131072.0 Bytes', + u'defaultTimeToWait': u'SECONDS_2', + u'scsiCommandTimeout': u'MINUTES_1', + u'deleteAllowed': False, + u'name': u'iSCSI 10G 2', + u'immediateDataWriteEnabled': False, + u'scName': u'Storage Center 64702', + u'notes': u'', + u'mtu': u'MTU_1500', + u'bidirectionalChapSecret': u'', + u'keepAliveTimeout': u'SECONDS_30'}] + ISCSI_FLT_DOMAIN = {u'headerDigestEnabled': False, u'classOfServicePriority': 0, u'wellKnownIpAddress': u'192.168.0.21', @@ -3924,6 +3988,208 @@ class DellSCSanAPITestCase(test.TestCase): u'192.168.0.21:3260']} self.assertEqual(expected, res, 'Wrong Target Info') + @mock.patch.object(storagecenter_api.SCApi, + '_find_active_controller', + return_value='64702.64702') + @mock.patch.object(storagecenter_api.SCApi, + '_find_controller_port') + @mock.patch.object(storagecenter_api.SCApi, + '_find_domains', + return_value=ISCSI_FLT_DOMAINS_MULTI_PORTALS) + @mock.patch.object(storagecenter_api.SCApi, + '_find_mappings', + return_value=MAPPINGS_MULTI_PORTAL) + @mock.patch.object(storagecenter_api.SCApi, + '_is_virtualport_mode', + return_value=True) + def test_find_iscsi_properties_excluded(self, + mock_is_virtualport_mode, + mock_find_mappings, + mock_find_domains, + mock_find_ctrl_port, + mock_find_active_controller, + mock_close_connection, + mock_open_connection, + mock_init): + # Test case where ips are blacklisted using excluded_domain_ips + mock_find_ctrl_port.side_effect = [ + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] + scserver = {'instanceId': '64702.30'} + self.scapi.excluded_domain_ips = ['192.168.0.21'] + self.scapi.included_domain_ips = [] + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) + self.assertTrue(mock_find_mappings.called) + self.assertTrue(mock_find_domains.called) + self.assertTrue(mock_find_ctrl_port.called) + self.assertTrue(mock_find_active_controller.called) + self.assertTrue(mock_is_virtualport_mode.called) + expected = {'target_discovered': False, + 'target_iqn': + u'iqn.2002-03.com.compellent:5000d31000fcbe44', + 'target_iqns': + [u'iqn.2002-03.com.compellent:5000d31000fcbe44', + u'iqn.2002-03.com.compellent:5000d31000fcbe43'], + 'target_lun': 1, + 'target_luns': [1, 1], + 'target_portal': u'192.168.0.25:3260', + 'target_portals': [u'192.168.0.25:3260', + u'192.168.0.25:3260']} + self.assertEqual(expected, res, 'Wrong Target Info') + + @mock.patch.object(storagecenter_api.SCApi, + '_find_active_controller', + return_value='64702.64702') + @mock.patch.object(storagecenter_api.SCApi, + '_find_controller_port') + @mock.patch.object(storagecenter_api.SCApi, + '_find_domains', + return_value=ISCSI_FLT_DOMAINS_MULTI_PORTALS) + @mock.patch.object(storagecenter_api.SCApi, + '_find_mappings', + return_value=MAPPINGS_MULTI_PORTAL) + @mock.patch.object(storagecenter_api.SCApi, + '_is_virtualport_mode', + return_value=True) + def test_find_iscsi_properties_included(self, + mock_is_virtualport_mode, + mock_find_mappings, + mock_find_domains, + mock_find_ctrl_port, + mock_find_active_controller, + mock_close_connection, + mock_open_connection, + mock_init): + # Test case where of included_domain_ips aka whitelisting + mock_find_ctrl_port.side_effect = [ + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] + scserver = {'instanceId': '64702.30'} + self.scapi.excluded_domain_ips = [] + self.scapi.included_domain_ips = ['192.168.0.25'] + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) + self.assertTrue(mock_find_mappings.called) + self.assertTrue(mock_find_domains.called) + self.assertTrue(mock_find_ctrl_port.called) + self.assertTrue(mock_find_active_controller.called) + self.assertTrue(mock_is_virtualport_mode.called) + expected = {'target_discovered': False, + 'target_iqn': + u'iqn.2002-03.com.compellent:5000d31000fcbe44', + 'target_iqns': + [u'iqn.2002-03.com.compellent:5000d31000fcbe44', + u'iqn.2002-03.com.compellent:5000d31000fcbe43'], + 'target_lun': 1, + 'target_luns': [1, 1], + 'target_portal': u'192.168.0.25:3260', + 'target_portals': [u'192.168.0.25:3260', + u'192.168.0.25:3260']} + self.assertEqual(expected, res, 'Wrong Target Info') + + @mock.patch.object(storagecenter_api.SCApi, + '_find_active_controller', + return_value='64702.64702') + @mock.patch.object(storagecenter_api.SCApi, + '_find_controller_port') + @mock.patch.object(storagecenter_api.SCApi, + '_find_domains', + return_value=ISCSI_FLT_DOMAINS_MULTI_PORTALS_IPV6) + @mock.patch.object(storagecenter_api.SCApi, + '_find_mappings', + return_value=MAPPINGS_MULTI_PORTAL) + @mock.patch.object(storagecenter_api.SCApi, + '_is_virtualport_mode', + return_value=True) + def test_find_iscsi_properties_included1(self, + mock_is_virtualport_mode, + mock_find_mappings, + mock_find_domains, + mock_find_ctrl_port, + mock_find_active_controller, + mock_close_connection, + mock_open_connection, + mock_init): + # Test case included_domain_ips aka whitelisting + # For ipv6 addresses + mock_find_ctrl_port.side_effect = [ + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] + scserver = {'instanceId': '64702.30'} + self.scapi.excluded_domain_ips = [] + self.scapi.included_domain_ips = ['0:0:0:0:0:ffff:c0a8:19'] + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) + self.assertTrue(mock_find_mappings.called) + self.assertTrue(mock_find_domains.called) + self.assertTrue(mock_find_ctrl_port.called) + self.assertTrue(mock_find_active_controller.called) + self.assertTrue(mock_is_virtualport_mode.called) + expected = {'target_discovered': False, + 'target_iqn': + u'iqn.2002-03.com.compellent:5000d31000fcbe44', + 'target_iqns': + [u'iqn.2002-03.com.compellent:5000d31000fcbe44', + u'iqn.2002-03.com.compellent:5000d31000fcbe43'], + 'target_lun': 1, + 'target_luns': [1, 1], + 'target_portal': u'0:0:0:0:0:ffff:c0a8:19:3260', + 'target_portals': [u'0:0:0:0:0:ffff:c0a8:19:3260', + u'0:0:0:0:0:ffff:c0a8:19:3260']} + self.assertEqual(expected, res, 'Wrong Target Info') + + @mock.patch.object(storagecenter_api.SCApi, + '_find_active_controller', + return_value='64702.64702') + @mock.patch.object(storagecenter_api.SCApi, + '_find_controller_port') + @mock.patch.object(storagecenter_api.SCApi, + '_find_domains', + return_value=ISCSI_FLT_DOMAINS_MULTI_PORTALS) + @mock.patch.object(storagecenter_api.SCApi, + '_find_mappings', + return_value=MAPPINGS_MULTI_PORTAL) + @mock.patch.object(storagecenter_api.SCApi, + '_is_virtualport_mode', + return_value=True) + def test_find_iscsi_properties_include2(self, + mock_is_virtualport_mode, + mock_find_mappings, + mock_find_domains, + mock_find_ctrl_port, + mock_find_active_controller, + mock_close_connection, + mock_open_connection, + mock_init): + # Test case where included_domain_ips(whitelisting) takes precendence + # over excluded_domain_ips ( blacklisting) + mock_find_ctrl_port.side_effect = [ + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe43'}, + {'iscsiName': 'iqn.2002-03.com.compellent:5000d31000fcbe44'}] + scserver = {'instanceId': '64702.30'} + self.scapi.excluded_domain_ips = ['192.168.0.21'] + self.scapi.included_domain_ips = ['192.168.0.25', '192.168.0.21'] + res = self.scapi.find_iscsi_properties(self.VOLUME, scserver) + self.assertTrue(mock_find_mappings.called) + self.assertTrue(mock_find_domains.called) + self.assertTrue(mock_find_ctrl_port.called) + self.assertTrue(mock_find_active_controller.called) + self.assertTrue(mock_is_virtualport_mode.called) + expected = {'target_discovered': False, + 'target_iqn': + u'iqn.2002-03.com.compellent:5000d31000fcbe44', + 'target_iqns': + [u'iqn.2002-03.com.compellent:5000d31000fcbe44', + u'iqn.2002-03.com.compellent:5000d31000fcbe43', + u'iqn.2002-03.com.compellent:5000d31000fcbe43', + u'iqn.2002-03.com.compellent:5000d31000fcbe44'], + 'target_lun': 1, + 'target_luns': [1, 1, 1, 1], + 'target_portal': u'192.168.0.25:3260', + 'target_portals': [u'192.168.0.25:3260', + u'192.168.0.21:3260', + u'192.168.0.25:3260', + u'192.168.0.21:3260']} + self.assertEqual(expected, res, 'Wrong Target Info') + @mock.patch.object(storagecenter_api.SCApi, '_find_active_controller', return_value='64702.5764839588723736131.91') diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py index 4d1e5f6c574..19bdcb2f380 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_api.py @@ -360,6 +360,7 @@ class SCApiHelper(object): connection.vfname = self.config.dell_sc_volume_folder connection.sfname = self.config.dell_sc_server_folder connection.excluded_domain_ips = self.config.excluded_domain_ips + connection.included_domain_ips = self.config.included_domain_ips if self.config.excluded_domain_ip: LOG.info("Using excluded_domain_ip for " "excluding domain IPs is deprecated in the " @@ -447,10 +448,11 @@ class SCApi(object): 4.0.0 - Driver moved to dell_emc. 4.1.0 - Timeouts added to rest calls. 4.1.1 - excluded_domain_ips support. + 4.1.2 - included_domain_ips support. """ - APIDRIVERVERSION = '4.1.1' + APIDRIVERVERSION = '4.1.2' def __init__(self, host, port, user, password, verify, asynctimeout, synctimeout, apiversion): @@ -476,6 +478,7 @@ class SCApi(object): self.vfname = 'openstack' self.sfname = 'openstack' self.excluded_domain_ips = [] + self.included_domain_ips = [] self.legacypayloadfilters = False self.consisgroups = True self.protocol = 'Iscsi' @@ -1829,7 +1832,18 @@ class SCApi(object): controller or not. :return: Nothing """ - if self.excluded_domain_ips.count(address) == 0: + process_it = False + + # Check the white list + # If the white list is empty, check the black list + if (not self.included_domain_ips): + # Check the black list + if self.excluded_domain_ips.count(address) == 0: + process_it = True + elif (self.included_domain_ips.count(address) > 0): + process_it = True + + if process_it: # Make sure this isn't a duplicate. newportal = address + ':' + six.text_type(port) for idx, portal in enumerate(portals): diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py index 1045d4afb36..565a2b1a995 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_common.py @@ -77,6 +77,11 @@ common_opts = [ default=[], help='Comma separated Fault Domain IPs to be excluded ' 'from iSCSI returns.'), + cfg.ListOpt('included_domain_ips', + item_type=types.IPAddress(), + default=[], + help='Comma separated Fault Domain IPs to be included ' + 'from iSCSI returns.'), cfg.StrOpt('dell_server_os', default='Red Hat Linux 6.x', help='Server OS type to use when creating a new server on the ' diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py index 1e120ae105d..9331e2fa5d1 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py @@ -65,10 +65,11 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, 4.0.0 - Driver moved to dell_emc. 4.1.0 - Timeouts added to rest calls. 4.1.1 - excluded_domain_ips support. + 4.1.2 - included_domain_ips IP support. """ - VERSION = '4.1.1' + VERSION = '4.1.2' CI_WIKI_NAME = "Dell_EMC_SC_Series_CI" diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py index a7d7c91e132..eba27dfecea 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_iscsi.py @@ -65,10 +65,11 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver, 4.0.0 - Driver moved to dell_emc. 4.1.0 - Timeouts added to rest calls. 4.1.1 - excluded_domain_ips support. + 4.1.2 - included_domain_ips IP support. """ - VERSION = '4.1.1' + VERSION = '4.1.2' CI_WIKI_NAME = "Dell_EMC_SC_Series_CI" def __init__(self, *args, **kwargs): diff --git a/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst b/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst index 0d805eefa35..9d4c3a70656 100644 --- a/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst +++ b/doc/source/configuration/block-storage/drivers/dell-storagecenter-driver.rst @@ -359,16 +359,44 @@ only applies to the ISCSI driver. Add the excluded_domain_ips option into the backend config for several fault domains to be excluded. This option takes a comma separated list of Target -IPv4 Addresses listed under the fault domain. Older versions of DSM (EM) may +IP addresses listed under the fault domain. Older versions of DSM (EM) may list this as the Well Known IP Address. +Note that the ``included_domain_ips`` takes precedance over +``excluded_domain_ips``. When ``included_domain_ips`` is not an empty list, +the option ``excluded_domain_ips`` is ignored. + Add the following to the back-end specification to exclude the domains at 172.20.25.15 and 172.20.26.15. .. code-block:: ini [dell] - excluded_domain_ips=172.20.25.15, 172.20.26.15 + excluded_domain_ips=172.20.25.15, 172.20.26.15, 0:0:0:0:0:ffff:c0a8:15 + +Including domains +~~~~~~~~~~~~~~~~~~ + +This option includes or will whitelist a list of Storage Center ISCSI fault +domains from the ISCSI properties returned by the initialize_connection call. +This only applies to the ISCSI driver. + +Add the ``included_domain_ips`` option into the backend config for several +default domains to be included or whitelisted. This option takes a comma +separated list of Target IP addresses listed under the fault domain. Older +versions of DSM (EM) may list this as the Well Known IP Address. + +Note that the ``included_domain_ips`` takes precedance over +``excluded_domain_ips``. When ``included_domain_ips`` is not an empty list, +the option ``excluded_domain_ips`` is ignored. + +Add the following to the back-end specification to include or whitelist the +domains at 172.20.25.15 and 172.20.26.15. + +.. code-block:: ini + + [dell] + included_domain_ips=172.20.25.15, 172.20.26.15, 0:0:0:0:0:ffff:c0a8:15 diff --git a/releasenotes/notes/SC-included_domain_ips_ListOpt-61bacddee199ce83.yaml b/releasenotes/notes/SC-included_domain_ips_ListOpt-61bacddee199ce83.yaml new file mode 100644 index 00000000000..44fa4fa9d0a --- /dev/null +++ b/releasenotes/notes/SC-included_domain_ips_ListOpt-61bacddee199ce83.yaml @@ -0,0 +1,6 @@ +--- +features: + - Added an ``included_domain_ips`` option to the Dell EMC SC driver. This + option takes a comma separated list of target IP addresses listed under + the fault domains to whitelisted. This option only applies to the ISCSI + driver.