summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-01-26 09:02:12 +0000
committerGerrit Code Review <review@openstack.org>2015-01-26 09:02:12 +0000
commit793198f6d8a6fc082ecc2aac876148b7bcb3d9c1 (patch)
tree79a4b789826cc2bcd79b2d83142310ea1078a67f
parentcefdf1465353abe0d32c56961820343e439efdb1 (diff)
parent4c1f28a0f467d749ebf406f970b3cea4888ff1b0 (diff)
downloadnova-793198f6d8a6fc082ecc2aac876148b7bcb3d9c1.tar.gz
Merge "Fix connecting unnecessary iSCSI sessions issue" into stable/juno
-rw-r--r--nova/tests/virt/libvirt/test_volume.py40
-rw-r--r--nova/virt/libvirt/volume.py25
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()