diff -Nru nova-2014.1.5/debian/changelog nova-2014.1.5/debian/changelog --- nova-2014.1.5/debian/changelog 2015-10-22 08:00:29.000000000 -0700 +++ nova-2014.1.5/debian/changelog 2016-05-02 15:16:36.000000000 -0700 @@ -1,3 +1,16 @@ +nova (1:2014.1.5-0ubuntu1.5) trusty; urgency=medium + + * Fix live migration usage of the wrong connector (LP: #1475411) + - d/p/Fix-live-migrations-usage-of-the-wrong-connector-inf.patch + * Fix wrong used ProcessExecutionError exception (LP: #1308839) + - d/p/Fix-wrong-used-ProcessExecutionError-exception.patch + * Clean up iSCSI multipath devices in Post Live Migration (LP: #1357368) + - d/p/Clean-up-iSCSI-multipath-devices-in-Post-Live-Migrat.patch + * Detach iSCSI latest path for latest disk (LP: #1374999) + - d/p/Detach-iSCSI-latest-path-for-latest-disk.patch + + -- Billy Olsen Fri, 29 Apr 2016 15:35:01 -0700 + nova (1:2014.1.5-0ubuntu1.4) trusty; urgency=medium * Protect against possible rpcapi mismatch on upgrade (LP: #1506257) diff -Nru nova-2014.1.5/debian/patches/Clean-up-iSCSI-multipath-devices-in-Post-Live-Migrat.patch nova-2014.1.5/debian/patches/Clean-up-iSCSI-multipath-devices-in-Post-Live-Migrat.patch --- nova-2014.1.5/debian/patches/Clean-up-iSCSI-multipath-devices-in-Post-Live-Migrat.patch 1969-12-31 17:00:00.000000000 -0700 +++ nova-2014.1.5/debian/patches/Clean-up-iSCSI-multipath-devices-in-Post-Live-Migrat.patch 2016-04-29 15:34:40.000000000 -0700 @@ -0,0 +1,140 @@ +From 65e606faa159b4ff6124b60e9ba090833f93a48b Mon Sep 17 00:00:00 2001 +From: Jeegn Chen +Date: Fri, 15 Aug 2014 21:40:14 +0800 +Subject: [PATCH 3/4] Clean up iSCSI multipath devices in Post Live Migration + +When a volume is attached to a VM in the source compute node through +multipath, the related files in /dev/disk/by-path/ are like this + +stack@ubuntu-server12:~/devstack$ ls /dev/disk/by-path/*24 +/dev/disk/by-path/ip-192.168.3.50:3260-iscsi-iqn.1992-04.com.emc:cx. +fnm00124500890.a5-lun-24 +/dev/disk/by-path/ip-192.168.4.51:3260-iscsi-iqn.1992-04.com.emc:cx. +fnm00124500890.b4-lun-24 + +The information on its corresponding multipath device is like this +stack@ubuntu-server12:~/devstack$ sudo multipath -l 3600601602ba034 +00921130967724e411 +3600601602ba03400921130967724e411 dm-3 DGC,VRAID +size=1.0G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw +|-+- policy='round-robin 0' prio=-1 status=active +| `- 19:0:0:24 sdl 8:176 active undef running +`-+- policy='round-robin 0' prio=-1 status=enabled + `- 18:0:0:24 sdj 8:144 active undef running + +But when the VM is migrated to the destination, the related information is +like the following example since we CANNOT guarantee that all nodes are able +to access the same iSCSI portals and the same target LUN number. And the +information is used to overwrite connection_info in the DB before the post +live migration logic is executed. + +stack@ubuntu-server13:~/devstack$ ls /dev/disk/by-path/*24 +/dev/disk/by-path/ip-192.168.3.51:3260-iscsi-iqn.1992-04.com.emc:cx. +fnm00124500890.b5-lun-100 +/dev/disk/by-path/ip-192.168.4.51:3260-iscsi-iqn.1992-04.com.emc:cx. +fnm00124500890.b4-lun-100 + +stack@ubuntu-server13:~/devstack$ sudo multipath -l 3600601602ba034 +00921130967724e411 +3600601602ba03400921130967724e411 dm-3 DGC,VRAID +size=1.0G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw +|-+- policy='round-robin 0' prio=-1 status=active +| `- 19:0:0:100 sdf 8:176 active undef running +`-+- policy='round-robin 0' prio=-1 status=enabled + `- 18:0:0:100 sdg 8:144 active undef running + +As a result, if post live migration in source side uses , and + to find the devices to clean up, it may use 192.168.3.51, +iqn.1992-04.com.emc:cx.fnm00124500890.a5 and 100. +However, the correct one should be 192.168.3.50, iqn.1992-04.com.emc:cx. +fnm00124500890.a5 and 24. + +Similar philosophy in (https://bugs.launchpad.net/nova/+bug/1327497) can be +used to fix it: Leverage the unchanged multipath_id to find correct devices +to delete. + +Conflicts: + nova/tests/virt/libvirt/test_libvirt_volume.py + +NOTE(wolsen): Conflicts are due to additional tests not included in this +cherry-pick. + +Change-Id: I875293c3ade9423caa2b8afe9eca25a74606d262 +Closes-Bug: #1357368 +(cherry picked from commit aa9104ccedb3ff13cc34a498b11f5e8ff100fd99) +(cherry picked from commit 9c3ec16576e2f7c9d5aff6e4b620d708e6636568) +--- + nova/tests/virt/libvirt/test_libvirt_volume.py | 30 ++++++++++++++++++++++++++ + nova/virt/libvirt/volume.py | 8 ++++++- + 2 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/nova/tests/virt/libvirt/test_libvirt_volume.py b/nova/tests/virt/libvirt/test_libvirt_volume.py +index e068c01..187061b 100644 +--- a/nova/tests/virt/libvirt/test_libvirt_volume.py ++++ b/nova/tests/virt/libvirt/test_libvirt_volume.py +@@ -351,6 +351,36 @@ class LibvirtVolumeTestCase(test.NoDBTestCase): + ['-f', 'fake-multipath-devname'], + check_exit_code=[0, 1]) + ++ def test_libvirt_iscsi_driver_multipath_id(self): ++ libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn) ++ libvirt_driver.use_multipath = True ++ self.stubs.Set(libvirt_driver, '_run_iscsiadm_bare', ++ lambda x, check_exit_code: ('',)) ++ self.stubs.Set(libvirt_driver, '_rescan_iscsi', lambda: None) ++ self.stubs.Set(libvirt_driver, '_get_host_device', lambda x: None) ++ self.stubs.Set(libvirt_driver, '_rescan_multipath', lambda: None) ++ fake_multipath_id = 'fake_multipath_id' ++ fake_multipath_device = '/dev/mapper/%s' % fake_multipath_id ++ self.stubs.Set(libvirt_driver, '_get_multipath_device_name', ++ lambda x: fake_multipath_device) ++ ++ def fake_disconnect_volume_multipath_iscsi(iscsi_properties, ++ multipath_device): ++ if fake_multipath_device != multipath_device: ++ raise Exception('Invalid multipath_device.') ++ ++ self.stubs.Set(libvirt_driver, '_disconnect_volume_multipath_iscsi', ++ fake_disconnect_volume_multipath_iscsi) ++ with mock.patch.object(os.path, 'exists', return_value=True): ++ vol = {'id': 1, 'name': self.name} ++ connection_info = self.iscsi_connection(vol, self.location, ++ self.iqn) ++ libvirt_driver.connect_volume(connection_info, ++ self.disk_info) ++ self.assertEqual(fake_multipath_id, ++ connection_info['data']['multipath_id']) ++ libvirt_driver.disconnect_volume(connection_info, "fake") ++ + def iser_connection(self, volume, location, iqn): + return { + 'driver_volume_type': 'iser', +diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py +index 8e18b0e..a2e6b14 100644 +--- a/nova/virt/libvirt/volume.py ++++ b/nova/virt/libvirt/volume.py +@@ -350,6 +350,8 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): + + if multipath_device is not None: + host_device = multipath_device ++ connection_info['data']['multipath_id'] = \ ++ multipath_device.split('/')[-1] + + conf.source_type = "block" + conf.source_path = host_device +@@ -362,7 +364,11 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): + host_device = self._get_host_device(iscsi_properties) + multipath_device = None + if self.use_multipath: +- multipath_device = self._get_multipath_device_name(host_device) ++ if 'multipath_id' in iscsi_properties: ++ multipath_device = ('/dev/mapper/%s' % ++ iscsi_properties['multipath_id']) ++ else: ++ multipath_device = self._get_multipath_device_name(host_device) + + super(LibvirtISCSIVolumeDriver, + self).disconnect_volume(connection_info, disk_dev) +-- +1.9.1 + diff -Nru nova-2014.1.5/debian/patches/Detach-iSCSI-latest-path-for-latest-disk.patch nova-2014.1.5/debian/patches/Detach-iSCSI-latest-path-for-latest-disk.patch --- nova-2014.1.5/debian/patches/Detach-iSCSI-latest-path-for-latest-disk.patch 1969-12-31 17:00:00.000000000 -0700 +++ nova-2014.1.5/debian/patches/Detach-iSCSI-latest-path-for-latest-disk.patch 2016-04-29 15:34:47.000000000 -0700 @@ -0,0 +1,116 @@ +From 030621f36e1508af779764b34baf9915f27e0d4b Mon Sep 17 00:00:00 2001 +From: Billy Olsen +Date: Thu, 21 Apr 2016 21:00:24 +0000 +Subject: [PATCH 4/4] Detach iSCSI latest path for latest disk + +The logic responsible to disconnect iscsi volumes wasn't clearing +latest path for the latest remaining disk. With this change, +latest disk path is removed right before iscsi disk is disconnected. + +Also, the device descriptor was not removed if the iqn are different +and multipath is enabled. + +Conflicts: + nova/tests/virt/libvirt/test_libvirt_volume.py + +NOTE(wolsen): Conflicts are due to removing additional tests included +in stable/juno but not part of this cherry-pick + +Change-Id: Ib6f6cea40cc3a14a3a443b157d0decba5602bf13 +Closes-Bug: 1374999 +Closes-Bug: 1452032 + +(cherry picked from commit 768da20fab6f84a8c34a089767b87924045c905a) +(cherry picked from commit 092a88b534f133aaca5f969f69f77ac38b1878fa) +--- + nova/tests/virt/libvirt/test_libvirt_volume.py | 53 +++++++++++++++++++++++--- + nova/virt/libvirt/volume.py | 1 + + 2 files changed, 48 insertions(+), 6 deletions(-) + +diff --git a/nova/tests/virt/libvirt/test_libvirt_volume.py b/nova/tests/virt/libvirt/test_libvirt_volume.py +index 187061b..5bdf78d 100644 +--- a/nova/tests/virt/libvirt/test_libvirt_volume.py ++++ b/nova/tests/virt/libvirt/test_libvirt_volume.py +@@ -364,13 +364,10 @@ class LibvirtVolumeTestCase(test.NoDBTestCase): + self.stubs.Set(libvirt_driver, '_get_multipath_device_name', + lambda x: fake_multipath_device) + +- def fake_disconnect_volume_multipath_iscsi(iscsi_properties, +- multipath_device): +- if fake_multipath_device != multipath_device: +- raise Exception('Invalid multipath_device.') ++ fake_rm_mp_dev_desc = mock.MagicMock() + +- self.stubs.Set(libvirt_driver, '_disconnect_volume_multipath_iscsi', +- fake_disconnect_volume_multipath_iscsi) ++ self.stubs.Set(libvirt_driver, '_remove_multipath_device_descriptor', ++ fake_rm_mp_dev_desc) + with mock.patch.object(os.path, 'exists', return_value=True): + vol = {'id': 1, 'name': self.name} + connection_info = self.iscsi_connection(vol, self.location, +@@ -380,6 +377,50 @@ class LibvirtVolumeTestCase(test.NoDBTestCase): + self.assertEqual(fake_multipath_id, + connection_info['data']['multipath_id']) + libvirt_driver.disconnect_volume(connection_info, "fake") ++ fake_rm_mp_dev_desc.assert_called_with(fake_multipath_device) ++ ++ def test_disconnect_volume_multipath_iscsi_not_in_use(self): ++ libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn) ++ libvirt_driver.use_multipath = True ++ self.stubs.Set(libvirt_driver, '_run_iscsiadm_bare', ++ lambda x, check_exit_code: ('',)) ++ self.stubs.Set(libvirt_driver, '_rescan_iscsi', lambda: None) ++ self.stubs.Set(libvirt_driver, '_get_host_device', lambda x: None) ++ self.stubs.Set(libvirt_driver, '_rescan_multipath', lambda: None) ++ ++ fake_multipath_id = 'fake_multipath_id' ++ fake_multipath_device = '/dev/mapper/%s' % fake_multipath_id ++ ++ fake_remove_multipath_device_descriptor = mock.MagicMock() ++ fake_disconnect_mpath = mock.MagicMock() ++ ++ self.stubs.Set(libvirt_driver, '_get_multipath_device_name', ++ lambda x: fake_multipath_device) ++ ++ self.stubs.Set(libvirt_driver, ++ '_remove_multipath_device_descriptor', ++ fake_remove_multipath_device_descriptor) ++ ++ self.stubs.Set(libvirt_driver, ++ '_disconnect_mpath', fake_disconnect_mpath) ++ ++ self.stubs.Set(libvirt_driver, ++ '_get_target_portals_from_iscsiadm_output', ++ lambda x: [[self.location, self.iqn]]) ++ ++ with contextlib.nested( ++ mock.patch.object(os.path, 'exists', return_value=True), ++ mock.patch.object(libvirt_driver, '_connect_to_iscsi_portal') ++ ): ++ vol = {'id': 1, 'name': self.name} ++ connection_info = self.iscsi_connection(vol, self.location, ++ self.iqn) ++ libvirt_driver.connect_volume(connection_info, ++ self.disk_info) ++ libvirt_driver.disconnect_volume(connection_info, "fake") ++ ++ fake_remove_multipath_device_descriptor.assert_called_with( ++ fake_multipath_device) + + def iser_connection(self, volume, location, iqn): + return { +diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py +index a2e6b14..0a80bd3 100644 +--- a/nova/virt/libvirt/volume.py ++++ b/nova/virt/libvirt/volume.py +@@ -460,6 +460,7 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): + + if not devices: + # disconnect if no other multipath devices ++ self._remove_multipath_device_descriptor(multipath_device) + self._disconnect_mpath(iscsi_properties, ips_iqns) + return + +-- +1.9.1 + diff -Nru nova-2014.1.5/debian/patches/Fix-live-migrations-usage-of-the-wrong-connector-inf.patch nova-2014.1.5/debian/patches/Fix-live-migrations-usage-of-the-wrong-connector-inf.patch --- nova-2014.1.5/debian/patches/Fix-live-migrations-usage-of-the-wrong-connector-inf.patch 1969-12-31 17:00:00.000000000 -0700 +++ nova-2014.1.5/debian/patches/Fix-live-migrations-usage-of-the-wrong-connector-inf.patch 2016-04-29 15:34:10.000000000 -0700 @@ -0,0 +1,139 @@ +From 3ec5288e964a1eb187b016845738baeb4f03f81b Mon Sep 17 00:00:00 2001 +From: Anthony Lee +Date: Thu, 16 Jul 2015 13:02:00 -0700 +Subject: [PATCH 1/4] Fix live-migrations usage of the wrong connector + information + +During the post_live_migration step for the Nova libvirt driver +an incorrect assumption is being made about the connector +information being sent to _disconnect_volume. It is assumed that +the connection information on the source and destination is the +same but that is not always the case. The BDM, where the +connector information is being retrieved from only contains the +connection information for the destination. This will not work +when trying to disconnect volumes from the source during live +migration as the properties such as the target_lun and +initiator_target_map could be different. This ends up leaving +behind dangling LUNs and possibly removing the incorrect +volume's LUNs. + +The solution proposed here utilizes the connection_info that +can be retrieved for a host from Cinder's initialize_connection +API. This connection information contains the correct data for +the source host and allows volume LUNs to be removed properly. + +Conflicts: + nova/tests/unit/virt/libvirt/test_driver.py + +NOTE(mriedem): The conflicts are due to the tests being moved +in Kilo and 41f80226e0a1f73af76c7968617ebfda0aeb40b1 not being +in stable/juno (renamed conn var to drvr in libvirt tests). + +NOTE(wolsen): The conflicts in icehouse are due to the driver +invocation changing between icehouse and juno. + +Change-Id: I3dfb75eb58dfbc66b218bcee473af4c2ac282eb6 +Closes-Bug: #1475411 +Closes-Bug: #1288039 +Closes-Bug: #1423772 +(cherry picked from commit 587092c909e15e983f7aef31d7bc0862271a32c7) +(cherry picked from commit 9d2abbd9ab60ca873650759feaba98b4d8d35566) + +Conflicts: + nova/tests/virt/libvirt/test_libvirt.py +--- + nova/tests/virt/libvirt/test_libvirt.py | 31 +++++++++++++++++++++++++------ + nova/virt/libvirt/driver.py | 18 +++++++++++++++++- + 2 files changed, 42 insertions(+), 7 deletions(-) + +diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py +index ce9914d..096fb60 100644 +--- a/nova/tests/virt/libvirt/test_libvirt.py ++++ b/nova/tests/virt/libvirt/test_libvirt.py +@@ -4496,10 +4496,22 @@ class LibvirtConnTestCase(test.TestCase): + + def test_post_live_migration(self): + vol = {'block_device_mapping': [ +- {'connection_info': 'dummy1', 'mount_device': '/dev/sda'}, +- {'connection_info': 'dummy2', 'mount_device': '/dev/sdb'}]} ++ {'connection_info': { ++ 'data': {'multipath_id': 'dummy1'}, ++ 'serial': 'fake_serial1'}, ++ 'mount_device': '/dev/sda', ++ }, ++ {'connection_info': { ++ 'data': {}, ++ 'serial': 'fake_serial2'}, ++ 'mount_device': '/dev/sdb', }]} ++ ++ def fake_initialize_connection(context, volume_id, connector): ++ return {'data': {}} ++ + conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + ++ fake_connector = {'host': 'fake'} + inst_ref = {'id': 'foo'} + cntx = context.get_admin_context() + +@@ -4507,17 +4519,24 @@ class LibvirtConnTestCase(test.TestCase): + with contextlib.nested( + mock.patch.object(driver, 'block_device_info_get_mapping', + return_value=vol['block_device_mapping']), ++ mock.patch.object(conn, "get_volume_connector", ++ return_value=fake_connector), ++ mock.patch.object(conn._volume_api, "initialize_connection", ++ side_effect=fake_initialize_connection), + mock.patch.object(conn, 'volume_driver_method') +- ) as (block_device_info_get_mapping, volume_driver_method): ++ ) as (block_device_info_get_mapping, get_volume_connector, ++ initialize_connection, volume_driver_method): + conn.post_live_migration(cntx, inst_ref, vol) + + block_device_info_get_mapping.assert_has_calls([ + mock.call(vol)]) ++ get_volume_connector.assert_has_calls([ ++ mock.call(inst_ref)]) + volume_driver_method.assert_has_calls([ + mock.call('disconnect_volume', +- v['connection_info'], +- v['mount_device'].rpartition("/")[2]) +- for v in vol['block_device_mapping']]) ++ {'data': {'multipath_id': 'dummy1'}}, 'sda'), ++ mock.call('disconnect_volume', ++ {'data': {}}, 'sdb')]) + + def test_get_instance_disk_info_excludes_volumes(self): + # Test data +diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py +index f7fd824..95792fc 100644 +--- a/nova/virt/libvirt/driver.py ++++ b/nova/virt/libvirt/driver.py +@@ -4735,8 +4735,24 @@ class LibvirtDriver(driver.ComputeDriver): + # Disconnect from volume server + block_device_mapping = driver.block_device_info_get_mapping( + block_device_info) ++ connector = self.get_volume_connector(instance) ++ volume_api = self._volume_api + for vol in block_device_mapping: +- connection_info = vol['connection_info'] ++ # Retrieve connection info from Cinder's initialize_connection API. ++ # The info returned will be accurate for the source server. ++ volume_id = vol['connection_info']['serial'] ++ connection_info = volume_api.initialize_connection(context, ++ volume_id, ++ connector) ++ ++ # Pull out multipath_id from the bdm information. The ++ # multipath_id can be placed into the connection info ++ # because it is based off of the volume and will be the ++ # same on the source and destination hosts. ++ if 'multipath_id' in vol['connection_info']['data']: ++ multipath_id = vol['connection_info']['data']['multipath_id'] ++ connection_info['data']['multipath_id'] = multipath_id ++ + disk_dev = vol['mount_device'].rpartition("/")[2] + self.volume_driver_method('disconnect_volume', + connection_info, +-- +1.9.1 + diff -Nru nova-2014.1.5/debian/patches/Fix-wrong-used-ProcessExecutionError-exception.patch nova-2014.1.5/debian/patches/Fix-wrong-used-ProcessExecutionError-exception.patch --- nova-2014.1.5/debian/patches/Fix-wrong-used-ProcessExecutionError-exception.patch 1969-12-31 17:00:00.000000000 -0700 +++ nova-2014.1.5/debian/patches/Fix-wrong-used-ProcessExecutionError-exception.patch 2016-04-29 15:34:25.000000000 -0700 @@ -0,0 +1,114 @@ +From 3a55f1422e81a642ae914e5b47f490639def34ea Mon Sep 17 00:00:00 2001 +From: Wangpan +Date: Thu, 17 Apr 2014 13:44:55 +0800 +Subject: [PATCH 2/4] Fix wrong used ProcessExecutionError exception + +This class has been moved to nova.openstack.common.processutils, +but a wrong usage is exists in nova.virt.libvirt.volume, +correct here. + +Conflicts: + nova/tests/virt/libvirt/test_libvirt_volume.py + +NOTE(wolsen): conflicts are due to test restructuring between +stable/juno and stable/icehouse. + +Closes-bug: #1308839 +Change-Id: I76f99b63dc5097b462dcff6ff63cbbb13d7580fb +(cherry picked from commit aa9383081230b92ecc7c1b176cb3eb62a237949c) +--- + nova/tests/virt/libvirt/test_libvirt_volume.py | 42 +++++++++++++++++++++++++- + nova/virt/libvirt/volume.py | 3 +- + 2 files changed, 42 insertions(+), 3 deletions(-) + +diff --git a/nova/tests/virt/libvirt/test_libvirt_volume.py b/nova/tests/virt/libvirt/test_libvirt_volume.py +index c43b175..e068c01 100644 +--- a/nova/tests/virt/libvirt/test_libvirt_volume.py ++++ b/nova/tests/virt/libvirt/test_libvirt_volume.py +@@ -14,14 +14,15 @@ + # under the License. + + import contextlib ++import fixtures + import os + import time + +-import fixtures + import mock + from oslo.config import cfg + + from nova import exception ++from nova.openstack.common import processutils + from nova.storage import linuxscsi + from nova import test + from nova.tests.virt.libvirt import fake_libvirt_utils +@@ -311,6 +312,45 @@ class LibvirtVolumeTestCase(test.NoDBTestCase): + '/sys/block/%s/device/delete' % dev_name)] + self.assertEqual(self.executes, expected_commands) + ++ def test_libvirt_iscsi_driver_disconnect_multipath_error(self): ++ libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn) ++ devs = ['/dev/disk/by-path/ip-%s-iscsi-%s-lun-2' % (self.location, ++ self.iqn)] ++ with contextlib.nested( ++ mock.patch.object(os.path, 'exists', return_value=True), ++ mock.patch.object(self.fake_conn, 'get_all_block_devices', ++ return_value=devs), ++ mock.patch.object(libvirt_driver, '_rescan_multipath'), ++ mock.patch.object(libvirt_driver, '_run_multipath'), ++ mock.patch.object(libvirt_driver, '_get_multipath_device_name', ++ return_value='/dev/mapper/fake-multipath-devname'), ++ mock.patch.object(libvirt_driver, ++ '_get_target_portals_from_iscsiadm_output', ++ return_value=[('fake-ip', 'fake-portal')]), ++ mock.patch.object(libvirt_driver, '_get_multipath_iqn', ++ return_value='fake-portal'), ++ ) as (mock_exists, mock_devices, mock_rescan_multipath, ++ mock_run_multipath, mock_device_name, mock_get_portals, ++ mock_get_iqn): ++ mock_run_multipath.side_effect = processutils.ProcessExecutionError ++ name = 'volume-00000001' ++ vol = {'id': 1, 'name': self.name} ++ connection_info = self.iscsi_connection(vol, self.location, ++ self.iqn) ++ conf = libvirt_driver.connect_volume(connection_info, ++ self.disk_info) ++ tree = conf.format_dom() ++ dev_name = 'ip-%s-iscsi-%s-lun-1' % (self.location, self.iqn) ++ dev_str = '/dev/disk/by-path/%s' % dev_name ++ self.assertEqual('block', tree.get('type')) ++ self.assertEqual(dev_str, tree.find('./source').get('dev')) ++ ++ libvirt_driver.use_multipath = True ++ libvirt_driver.disconnect_volume(connection_info, "vde") ++ mock_run_multipath.assert_called_once_with( ++ ['-f', 'fake-multipath-devname'], ++ check_exit_code=[0, 1]) ++ + def iser_connection(self, volume, location, iqn): + return { + 'driver_volume_type': 'iser', +diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py +index c7ee66f..8e18b0e 100644 +--- a/nova/virt/libvirt/volume.py ++++ b/nova/virt/libvirt/volume.py +@@ -399,7 +399,7 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): + try: + self._run_multipath(['-f', disk_descriptor], + check_exit_code=[0, 1]) +- except exception.ProcessExecutionError as exc: ++ except processutils.ProcessExecutionError as exc: + # Because not all cinder drivers need to remove the dev mapper, + # here just logs a warning to avoid affecting those drivers in + # exceptional cases. +@@ -474,7 +474,6 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): + if not in_use: + # disconnect if no other multipath devices with same iqn + self._disconnect_mpath(iscsi_properties, ips_iqns) +- return + elif multipath_device not in devices: + # delete the devices associated w/ the unused multipath + self._delete_mpath(iscsi_properties, multipath_device, ips_iqns) +-- +1.9.1 + diff -Nru nova-2014.1.5/debian/patches/series nova-2014.1.5/debian/patches/series --- nova-2014.1.5/debian/patches/series 2015-10-22 08:00:27.000000000 -0700 +++ nova-2014.1.5/debian/patches/series 2016-04-29 15:34:47.000000000 -0700 @@ -8,3 +8,7 @@ clean-shutdown.patch fix-creating-bdm-for-failed-volume-attachment.patch protect-against-upgrade-rpc-ver-mismatch.patch +Fix-live-migrations-usage-of-the-wrong-connector-inf.patch +Fix-wrong-used-ProcessExecutionError-exception.patch +Clean-up-iSCSI-multipath-devices-in-Post-Live-Migrat.patch +Detach-iSCSI-latest-path-for-latest-disk.patch