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
This commit is contained in:
Michael Price 2016-08-08 12:13:28 -05:00
parent 45184cb9b0
commit cef2880afe
2 changed files with 61 additions and 6 deletions

View File

@ -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)

View File

@ -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,