From cef2880afea3c754a48f0286f42abd98ce9c2772 Mon Sep 17 00:00:00 2001 From: Michael Price Date: Mon, 8 Aug 2016 12:13:28 -0500 Subject: [PATCH] Fix iSCSI discovery with ISER transport The iSCSI discovery is not working with the ISER transport type. By default, iscsiadm will use the tcp transport type. This patch changes the iscsiadm invocation to provide the '-I' option with a value of iser where ISER is in use, and a value of default otherwise. Closes-Bug: #1594892 Change-Id: I1f0e01c4c2e928022080cfc0475fb5190066df23 --- os_brick/initiator/connectors/iscsi.py | 16 +++++- .../tests/initiator/connectors/test_iscsi.py | 51 +++++++++++++++++-- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/os_brick/initiator/connectors/iscsi.py b/os_brick/initiator/connectors/iscsi.py index 4245c3b1e..1e54268b2 100644 --- a/os_brick/initiator/connectors/iscsi.py +++ b/os_brick/initiator/connectors/iscsi.py @@ -291,9 +291,12 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): connection_properties['target_iqns']) out = None + iscsi_transport = ('iser' if self._get_transport() == 'iser' + else 'default') if connection_properties.get('discovery_auth_method'): try: - self._run_iscsiadm_update_discoverydb(connection_properties) + self._run_iscsiadm_update_discoverydb(connection_properties, + iscsi_transport) except putils.ProcessExecutionError as exception: # iscsiadm returns 6 for "db record not found" if exception.exit_code == 6: @@ -302,6 +305,7 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): ['-m', 'discoverydb', '-t', 'sendtargets', '-p', connection_properties['target_portal'], + '-I', iscsi_transport, '--op', 'new'], check_exit_code=[0, 255]) self._run_iscsiadm_update_discoverydb( @@ -316,6 +320,7 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): out = self._run_iscsiadm_bare( ['-m', 'discoverydb', '-t', 'sendtargets', + '-I', iscsi_transport, '-p', connection_properties['target_portal'], '--discover'], check_exit_code=[0, 255])[0] or "" @@ -323,16 +328,19 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): out = self._run_iscsiadm_bare( ['-m', 'discovery', '-t', 'sendtargets', + '-I', iscsi_transport, '-p', connection_properties['target_portal']], check_exit_code=[0, 255])[0] or "" return self._get_target_portals_from_iscsiadm_output(out) - def _run_iscsiadm_update_discoverydb(self, connection_properties): + def _run_iscsiadm_update_discoverydb(self, connection_properties, + iscsi_transport='default'): return self._execute( 'iscsiadm', '-m', 'discoverydb', '-t', 'sendtargets', + '-I', iscsi_transport, '-p', connection_properties['target_portal'], '--op', 'update', '-n', "discovery.sendtargets.auth.authmethod", @@ -383,6 +391,7 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): device_info = {'type': 'block'} + # At this point the host_devices may be an empty list host_devices, target_props = self._get_potential_volume_paths( connection_properties) @@ -402,6 +411,9 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): # The rescan isn't documented as being necessary(?), but it helps if self.use_multipath: self._rescan_iscsi() + # We need to refresh the paths as the devices may be empty + host_devices, target_props = ( + self._get_potential_volume_paths(connection_properties)) else: if (tries): host_devices = self._get_device_path(target_props) diff --git a/os_brick/tests/initiator/connectors/test_iscsi.py b/os_brick/tests/initiator/connectors/test_iscsi.py index 94e3c5cb3..8f09d7151 100644 --- a/os_brick/tests/initiator/connectors/test_iscsi.py +++ b/os_brick/tests/initiator/connectors/test_iscsi.py @@ -437,6 +437,49 @@ class ISCSIConnectorTestCase(test_connector.ConnectorTestCase): 'scsi_wwn': test_connector.FAKE_SCSI_WWN} self.assertEqual(expected_result, result) + def test_discover_iscsi_portals(self): + location = '10.0.2.15:3260' + name = 'volume-00000001' + iqn = 'iqn.2010-10.org.openstack:%s' % name + vol = {'id': 1, 'name': name} + auth_method = 'CHAP' + auth_username = 'fake_chap_username' + auth_password = 'fake_chap_password' + discovery_auth_method = 'CHAP' + discovery_auth_username = 'fake_chap_username' + discovery_auth_password = 'fake_chap_password' + connection_properties = self.iscsi_connection_chap( + vol, location, iqn, auth_method, auth_username, auth_password, + discovery_auth_method, discovery_auth_username, + discovery_auth_password) + self.connector_with_multipath = iscsi.ISCSIConnector( + None, execute=self.fake_execute, use_multipath=True) + + for transport in ['default', 'iser', 'badTransport']: + interface = 'iser' if transport == 'iser' else 'default' + self.mock_object(self.connector_with_multipath, '_get_transport', + mock.Mock(return_value=interface)) + + self.connector_with_multipath._discover_iscsi_portals( + connection_properties['data']) + + expected_cmds = [ + 'iscsiadm -m discoverydb -t sendtargets -I %(iface)s ' + '-p %(location)s --op update ' + '-n discovery.sendtargets.auth.authmethod -v %(auth_method)s ' + '-n discovery.sendtargets.auth.username -v %(username)s ' + '-n discovery.sendtargets.auth.password -v %(password)s' % + {'iface': interface, 'location': location, + 'auth_method': discovery_auth_method, + 'username': discovery_auth_username, + 'password': discovery_auth_password}, + 'iscsiadm -m discoverydb -t sendtargets -I %(iface)s' + ' -p %(location)s --discover' % {'iface': interface, + 'location': location}] + self.assertEqual(expected_cmds, self.cmds) + # Reset to run with a different transport type + self.cmds = list() + @mock.patch.object(iscsi.ISCSIConnector, '_run_iscsiadm_update_discoverydb') @mock.patch.object(os.path, 'exists', return_value=True) @@ -473,10 +516,10 @@ class ISCSIConnectorTestCase(test_connector.ConnectorTestCase): update_discoverydb.assert_called_with(connection_properties['data']) expected_cmds = [ - 'iscsiadm -m discoverydb -t sendtargets -p %s --op new' % - location, - 'iscsiadm -m discoverydb -t sendtargets -p %s --discover' % - location] + 'iscsiadm -m discoverydb -t sendtargets -p %s -I default' + ' --op new' % location, + 'iscsiadm -m discoverydb -t sendtargets -I default -p %s' + ' --discover' % location] self.assertEqual(expected_cmds, self.cmds) self.assertRaises(exception.TargetPortalNotFound,