diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-01-26 09:02:12 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-01-26 09:02:12 +0000 |
commit | 793198f6d8a6fc082ecc2aac876148b7bcb3d9c1 (patch) | |
tree | 79a4b789826cc2bcd79b2d83142310ea1078a67f | |
parent | cefdf1465353abe0d32c56961820343e439efdb1 (diff) | |
parent | 4c1f28a0f467d749ebf406f970b3cea4888ff1b0 (diff) | |
download | nova-793198f6d8a6fc082ecc2aac876148b7bcb3d9c1.tar.gz |
Merge "Fix connecting unnecessary iSCSI sessions issue" into stable/juno
-rw-r--r-- | nova/tests/virt/libvirt/test_volume.py | 40 | ||||
-rw-r--r-- | nova/virt/libvirt/volume.py | 25 |
2 files changed, 62 insertions, 3 deletions
diff --git a/nova/tests/virt/libvirt/test_volume.py b/nova/tests/virt/libvirt/test_volume.py index 0158cd5243..e1ec2c4772 100644 --- a/nova/tests/virt/libvirt/test_volume.py +++ b/nova/tests/virt/libvirt/test_volume.py @@ -636,6 +636,46 @@ Setting up iSCSI targets: unused expected_multipath_cmd = ('multipath', '-f', 'foo') self.assertIn(expected_multipath_cmd, self.executes) + def test_libvirt_kvm_volume_with_multipath_connecting(self): + libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn) + ip_iqns = [[self.location, self.iqn], + ['10.0.2.16:3260', self.iqn], + [self.location, + 'iqn.2010-10.org.openstack:volume-00000002']] + + with contextlib.nested( + mock.patch.object(os.path, 'exists', return_value=True), + mock.patch.object(libvirt_driver, '_run_iscsiadm_bare'), + mock.patch.object(libvirt_driver, + '_get_target_portals_from_iscsiadm_output', + return_value=ip_iqns), + mock.patch.object(libvirt_driver, '_connect_to_iscsi_portal'), + mock.patch.object(libvirt_driver, '_rescan_iscsi'), + mock.patch.object(libvirt_driver, '_get_host_device', + return_value='fake-device'), + mock.patch.object(libvirt_driver, '_rescan_multipath'), + mock.patch.object(libvirt_driver, '_get_multipath_device_name', + return_value='/dev/mapper/fake-mpath-devname') + ) as (mock_exists, mock_run_iscsiadm_bare, mock_get_portals, + mock_connect_iscsi, mock_rescan_iscsi, mock_host_device, + mock_rescan_multipath, mock_device_name): + vol = {'id': 1, 'name': self.name} + connection_info = self.iscsi_connection(vol, self.location, + self.iqn) + libvirt_driver.use_multipath = True + libvirt_driver.connect_volume(connection_info, self.disk_info) + + # Verify that the supplied iqn is used when it shares the same + # iqn between multiple portals. + connection_info = self.iscsi_connection(vol, self.location, + self.iqn) + props1 = connection_info['data'].copy() + props2 = connection_info['data'].copy() + props2['target_portal'] = '10.0.2.16:3260' + expected_calls = [mock.call(props1), mock.call(props2), + mock.call(props1)] + self.assertEqual(expected_calls, mock_connect_iscsi.call_args_list) + def test_libvirt_kvm_volume_with_multipath_still_in_use(self): name = 'volume-00000001' location = '10.0.2.15:3260' diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index 6ba543d0b3..d1d2c6ef52 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -285,10 +285,29 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): check_exit_code=[0, 255])[0] \ or "" - for ip, iqn in self._get_target_portals_from_iscsiadm_output(out): + # There are two types of iSCSI multipath devices. One which shares + # the same iqn between multiple portals, and the other which use + # different iqns on different portals. Try to identify the type by + # checking the iscsiadm output if the iqn is used by multiple + # portals. If it is, it's the former, so use the supplied iqn. + # Otherwise, it's the latter, so try the ip,iqn combinations to + # find the targets which constitutes the multipath device. + ips_iqns = self._get_target_portals_from_iscsiadm_output(out) + same_portal = False + all_portals = set() + match_portals = set() + for ip, iqn in ips_iqns: + all_portals.add(ip) + if iqn == iscsi_properties['target_iqn']: + match_portals.add(ip) + if len(all_portals) == len(match_portals): + same_portal = True + + for ip, iqn in ips_iqns: props = iscsi_properties.copy() - props['target_portal'] = ip - props['target_iqn'] = iqn + props['target_portal'] = ip.split(",")[0] + if not same_portal: + props['target_iqn'] = iqn self._connect_to_iscsi_portal(props) self._rescan_iscsi() |