Fix iSCSI volume attachment over RDMA transport
Recent changes assumed 'tcp:' prefix to iscsi sessions, and that broke the session status discovery for RDMA connections. in this change we add the 'iser:' transport prefix to the os-brick functions, to fix volumes attach over RDMA. Closes-bug: #1710599 Change-Id: I27b30dafcf488ebd125917e1924c828e3bdf3a99
This commit is contained in:
parent
b2cc3c99f7
commit
af2f60f9ba
|
@ -43,6 +43,7 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
|
|||
|
||||
supported_transports = ['be2iscsi', 'bnx2i', 'cxgb3i', 'default',
|
||||
'cxgb4i', 'qla4xxx', 'ocs', 'iser']
|
||||
VALID_SESSIONS_PREFIX = ('tcp:', 'iser:')
|
||||
|
||||
def __init__(self, root_helper, driver=None,
|
||||
execute=None, use_multipath=False,
|
||||
|
@ -782,7 +783,8 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
|
|||
nodes = self._get_iscsi_nodes()
|
||||
sessions = self._get_iscsi_sessions_full()
|
||||
# Use (portal, iqn) to map the session value
|
||||
sessions_map = {(s[2], s[4]): s[1] for s in sessions if s[0] == 'tcp:'}
|
||||
sessions_map = {(s[2], s[4]): s[1] for s in sessions
|
||||
if s[0] in self.VALID_SESSIONS_PREFIX}
|
||||
# device_map will keep a tuple with devices from the connection and
|
||||
# others that don't belong to this connection" (belong, others)
|
||||
device_map = collections.defaultdict(lambda: (set(), set()))
|
||||
|
@ -1020,7 +1022,8 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
|
|||
sessions = self._get_iscsi_sessions_full()
|
||||
for s in sessions:
|
||||
# Found our session, return session_id
|
||||
if 'tcp:' == s[0] and portal == s[2] and s[4] == target_iqn:
|
||||
if (s[0] in self.VALID_SESSIONS_PREFIX and
|
||||
portal == s[2] and s[4] == target_iqn):
|
||||
return s[1], manual_scan
|
||||
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from os_brick.initiator.connectors import iscsi
|
||||
from os_brick.tests.initiator import test_connector
|
||||
|
||||
|
||||
class ISERConnectorTestCase(test_connector.ConnectorTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ISERConnectorTestCase, self).setUp()
|
||||
self.connector = iscsi.ISCSIConnector(
|
||||
None, execute=self.fake_execute, use_multipath=False)
|
||||
self.connection_data = {
|
||||
'volume_id': 'volume_id',
|
||||
'target_portal': 'ip:port',
|
||||
'target_iqn': 'target_1',
|
||||
'target_lun': 1,
|
||||
'target_portals': ['ip:port'],
|
||||
'target_iqns': ['target_1'],
|
||||
'target_luns': [1]
|
||||
}
|
||||
|
||||
@mock.patch.object(iscsi.ISCSIConnector, '_get_ips_iqns_luns')
|
||||
@mock.patch('glob.glob')
|
||||
@mock.patch.object(iscsi.ISCSIConnector, '_get_iscsi_sessions_full')
|
||||
@mock.patch.object(iscsi.ISCSIConnector, '_get_iscsi_nodes')
|
||||
def test_get_connection_devices(
|
||||
self, nodes_mock, sessions_mock, glob_mock, iql_mock):
|
||||
|
||||
self.connector.use_multipath = True
|
||||
iql_mock.return_value = \
|
||||
self.connector._get_all_targets(self.connection_data)
|
||||
|
||||
# mocked iSCSI sessions
|
||||
sessions_mock.return_value = \
|
||||
[('iser:', '0', 'ip:port', '1', 'target_1')]
|
||||
|
||||
# mocked iSCSI nodes
|
||||
nodes_mock.return_value = [('ip:port', 'target_1')]
|
||||
sys_cls = '/sys/class/scsi_host/host'
|
||||
glob_mock.side_effect = [
|
||||
[sys_cls + '1/device/session/target/1:1:1:1/block/sda']
|
||||
]
|
||||
res = self.connector._get_connection_devices(self.connection_data)
|
||||
expected = {('ip:port', 'target_1'): ({'sda'}, set())}
|
||||
self.assertDictEqual(expected, res)
|
||||
iql_mock.assert_called_once_with(self.connection_data, discover=False)
|
||||
|
||||
@mock.patch.object(iscsi.ISCSIConnector, '_get_iscsi_sessions_full')
|
||||
@mock.patch.object(iscsi.ISCSIConnector, '_execute')
|
||||
def test_connect_to_iscsi_portal(self, exec_mock, sessions_mock):
|
||||
"""Connect to portal while session already established"""
|
||||
|
||||
# connected sessions
|
||||
sessions_mock.side_effect = [
|
||||
[('iser:', 'session_iser', 'ip:port', '1', 'target_1')]
|
||||
]
|
||||
exec_mock.side_effect = [('', None), ('', None), ('', None)]
|
||||
res = self.connector._connect_to_iscsi_portal(self.connection_data)
|
||||
|
||||
# session name is expected to be in the result.
|
||||
self.assertEqual(("session_iser", True), res)
|
||||
prefix = 'iscsiadm -m node -T target_1 -p ip:port'
|
||||
expected_cmds = [
|
||||
prefix,
|
||||
prefix + ' --op update -n node.session.scan -v manual'
|
||||
]
|
||||
actual_cmds = [' '.join(args[0]) for args in exec_mock.call_args_list]
|
||||
self.assertListEqual(expected_cmds, actual_cmds)
|
Loading…
Reference in New Issue