diff --git a/os_brick/initiator/connector.py b/os_brick/initiator/connector.py index d005b30..0545efc 100644 --- a/os_brick/initiator/connector.py +++ b/os_brick/initiator/connector.py @@ -224,23 +224,27 @@ class ISCSIConnector(InitiatorConnector): super(ISCSIConnector, self).set_execute(execute) self._linuxscsi.set_execute(execute) - def _iterate_multiple_targets(self, connection_properties, ips_iqns_luns): - for ip, iqn, lun in ips_iqns_luns: + def _iterate_all_targets(self, connection_properties): + for ip, iqn, lun in self._get_all_targets(connection_properties): props = copy.deepcopy(connection_properties) props['target_portal'] = ip props['target_iqn'] = iqn props['target_lun'] = lun + for key in ('target_portals', 'target_iqns', 'target_luns'): + props.pop(key, None) yield props - def _alternative_targets(self, connection_properties): - return zip(connection_properties.get('target_alternative_portals', []), - connection_properties.get('target_alternative_iqns', []), - connection_properties.get('target_alternative_luns', [])) + def _get_all_targets(self, connection_properties): + if all([key in connection_properties for key in ('target_portals', + 'target_iqns', + 'target_luns')]): + return zip(connection_properties['target_portals'], + connection_properties['target_iqns'], + connection_properties['target_luns']) - def _multipath_targets(self, connection_properties): - return zip(connection_properties.get('target_portals', []), - connection_properties.get('target_iqns', []), - connection_properties.get('target_luns', [])) + return [(connection_properties['target_portal'], + connection_properties['target_iqn'], + connection_properties.get('target_lun', 0))] def _discover_iscsi_portals(self, connection_properties): if all([key in connection_properties for key in ('target_portals', @@ -286,13 +290,10 @@ class ISCSIConnector(InitiatorConnector): host_devices = self._get_device_path(connection_properties) else: target_props = connection_properties - if not self._connect_to_iscsi_portal(target_props): - for props in self._iterate_multiple_targets( - connection_properties, - self._alternative_targets(connection_properties)): - if self._connect_to_iscsi_portal(props): - target_props = props - break + for props in self._iterate_all_targets(connection_properties): + if self._connect_to_iscsi_portal(props): + target_props = props + break else: LOG.warn(_LW( 'Failed to login to any of the iSCSI targets.')) @@ -381,14 +382,7 @@ class ISCSIConnector(InitiatorConnector): # When multiple portals/iqns/luns are specified, we need to remove # unused devices created by logging into other LUNs' session. - ips_iqns_luns = self._multipath_targets(connection_properties) - if not ips_iqns_luns: - ips_iqns_luns = ([[connection_properties['target_portal'], - connection_properties['target_iqn'], - connection_properties.get('target_lun', 0)]] + - self._alternative_targets(connection_properties)) - for props in self._iterate_multiple_targets(connection_properties, - ips_iqns_luns): + for props in self._iterate_all_targets(connection_properties): self._disconnect_volume_iscsi(props) def _disconnect_volume_iscsi(self, connection_properties): @@ -412,16 +406,8 @@ class ISCSIConnector(InitiatorConnector): self._disconnect_from_iscsi_portal(connection_properties) def _get_device_path(self, connection_properties): - multipath_targets = self._multipath_targets(connection_properties) - if multipath_targets: - return ["/dev/disk/by-path/ip-%s-iscsi-%s-lun-%s" % x for x in - multipath_targets] - - path = ("/dev/disk/by-path/ip-%(portal)s-iscsi-%(iqn)s-lun-%(lun)s" % - {'portal': connection_properties['target_portal'], - 'iqn': connection_properties['target_iqn'], - 'lun': connection_properties.get('target_lun', 0)}) - return [path] + return ["/dev/disk/by-path/ip-%s-iscsi-%s-lun-%s" % x for x in + self._get_all_targets(connection_properties)] def get_initiator(self): """Secure helper to read file as root.""" diff --git a/os_brick/tests/initiator/test_connector.py b/os_brick/tests/initiator/test_connector.py index 1987084..01c80d3 100644 --- a/os_brick/tests/initiator/test_connector.py +++ b/os_brick/tests/initiator/test_connector.py @@ -278,11 +278,13 @@ class ISCSIConnectorTestCase(ConnectorTestCase): @testtools.skipUnless(os.path.exists('/dev/disk/by-path'), 'Test requires /dev/disk/by-path') def test_connect_volume_with_alternative_targets(self): + location = '10.0.2.15:3260' location2 = '10.0.3.15:3260' + iqn = 'iqn.2010-10.org.openstack:volume-00000001' iqn2 = 'iqn.2010-10.org.openstack:volume-00000001-2' - extra_props = {'target_alternative_portals': [location2], - 'target_alternative_iqns': [iqn2], - 'target_alternative_luns': [2]} + extra_props = {'target_portals': [location, location2], + 'target_iqns': [iqn, iqn2], + 'target_luns': [1, 2]} additional_commands = [('blockdev --flushbufs /dev/sdb'), ('tee -a /sys/block/sdb/device/delete'), ('iscsiadm -m node -T %s -p %s --op update' @@ -307,9 +309,9 @@ class ISCSIConnectorTestCase(ConnectorTestCase): iqn2 = 'iqn.2010-10.org.openstack:%s-2' % name vol = {'id': 1, 'name': name} connection_info = self.iscsi_connection(vol, location, iqn) - connection_info['data']['target_alternative_portals'] = [location2] - connection_info['data']['target_alternative_iqns'] = [iqn2] - connection_info['data']['target_alternative_luns'] = [2] + connection_info['data']['target_portals'] = [location, location2] + connection_info['data']['target_iqns'] = [iqn, iqn2] + connection_info['data']['target_luns'] = [1, 2] dev_str2 = '/dev/disk/by-path/ip-%s-iscsi-%s-lun-2' % (location2, iqn2) def fake_run_iscsiadm(iscsi_properties, iscsi_command, **kwargs): @@ -324,6 +326,8 @@ class ISCSIConnectorTestCase(ConnectorTestCase): self.assertEqual('block', device['type']) self.assertEqual(dev_str2, device['path']) props = connection_info['data'].copy() + for key in ('target_portals', 'target_iqns', 'target_luns'): + props.pop(key, None) props['target_portal'] = location2 props['target_iqn'] = iqn2 props['target_lun'] = 2 @@ -333,6 +337,8 @@ class ISCSIConnectorTestCase(ConnectorTestCase): mock_iscsiadm.reset_mock() self.connector.disconnect_volume(connection_info['data'], device) props = connection_info['data'].copy() + for key in ('target_portals', 'target_iqns', 'target_luns'): + props.pop(key, None) mock_iscsiadm.assert_any_call(props, ('--logout',), check_exit_code=[0, 21, 255]) props['target_portal'] = location2