diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 4062d96604a4..78b793f51088 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -13374,9 +13374,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, @mock.patch.object(fakelibvirt.Connection, "_mark_running") @mock.patch.object(libvirt_driver.LibvirtDriver, "_live_migration_copy_disk_paths") - def test_live_migration_main(self, mock_copy_disk_path, mock_running, - mock_guest, mock_monitor, mock_thread, - mock_conn): + @mock.patch.object(libvirt_driver.LibvirtDriver, "live_migration_abort") + def _test_live_migration_main(self, mock_abort, mock_copy_disk_path, + mock_running, mock_guest, mock_monitor, + mock_thread, mock_conn, + mon_side_effect=None): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) instance = objects.Instance(**self.test_instance) @@ -13389,6 +13391,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_copy_disk_path.return_value = disks_to_copy mock_guest.return_value = guest + mock_monitor.side_effect = mon_side_effect def fake_post(): pass @@ -13396,9 +13399,15 @@ class LibvirtConnTestCase(test.NoDBTestCase, def fake_recover(): pass - drvr._live_migration(self.context, instance, "fakehost", - fake_post, fake_recover, True, - migrate_data) + if mon_side_effect: + self.assertRaises(mon_side_effect, drvr._live_migration, + self.context, instance, "fakehost", fake_post, + fake_recover, True, migrate_data) + mock_abort.assert_called_once_with(instance) + else: + drvr._live_migration(self.context, instance, "fakehost", fake_post, + fake_recover, True, migrate_data) + mock_copy_disk_path.assert_called_once_with(self.context, instance, guest) @@ -13415,6 +13424,12 @@ class LibvirtConnTestCase(test.NoDBTestCase, fake_post, fake_recover, True, migrate_data, AnyEventletEvent(), disks_to_copy[0]) + def test_live_migration_main(self): + self._test_live_migration_main() + + def test_live_migration_main_monitoring_failed(self): + self._test_live_migration_main(mon_side_effect=Exception) + @mock.patch('os.path.exists', return_value=False) @mock.patch('nova.virt.libvirt.utils.create_image') @mock.patch.object(libvirt_driver.LibvirtDriver, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 65f4e44f2731..d14bf3d19a67 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -9962,6 +9962,18 @@ class LibvirtDriver(driver.ComputeDriver): except Exception as ex: LOG.warning("Error monitoring migration: %(ex)s", {"ex": ex}, instance=instance, exc_info=True) + # NOTE(aarents): Ensure job is aborted if still running before + # raising the exception so this would avoid the migration to be + # done and the libvirt guest to be resumed on the target while + # the instance record would still related to the source host. + try: + # If migration is running in post-copy mode and guest + # already running on dest host, libvirt will refuse to + # cancel migration job. + self.live_migration_abort(instance) + except libvirt.libvirtError: + LOG.warning("Error occured when trying to abort live ", + "migration job, ignoring it.", instance=instance) raise finally: LOG.debug("Live migration monitoring is all done",