From 6347baf3d09036525b7f6df991ae440d558f9cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20J=C3=B3zefczyk?= Date: Thu, 23 Feb 2017 12:56:04 +0100 Subject: [PATCH] Ensure that instance directory is removed after success migration/resize Nova recreates instance directory on source host after successful migration/resize. This patch removes directory of migrated instance from source host. Change-Id: Ic683f83e428106df64be42287e2c5f3b40e73da4 Closes-Bug: #1666831 --- nova/tests/unit/virt/libvirt/test_driver.py | 23 +++++++++++++++------ nova/virt/libvirt/driver.py | 13 +++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 17cb95a4ae..0ddc4990c8 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -16271,8 +16271,9 @@ class LibvirtDriverTestCase(test.NoDBTestCase): with test.nested( mock.patch.object(os.path, 'exists'), mock.patch.object(libvirt_utils, 'get_instance_path'), - mock.patch.object(utils, 'execute')) as ( - mock_exists, mock_get_path, mock_exec): + mock.patch.object(utils, 'execute'), + mock.patch.object(shutil, 'rmtree')) as ( + mock_exists, mock_get_path, mock_exec, mock_rmtree): mock_exists.return_value = True mock_get_path.return_value = '/fake/inst' @@ -16280,6 +16281,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): mock_get_path.assert_called_once_with(ins_ref) mock_exec.assert_called_once_with('rm', '-rf', '/fake/inst_resize', delay_on_retry=True, attempts=5) + mock_rmtree.assert_not_called() def test_cleanup_resize_not_same_host(self): CONF.set_override('policy_dirs', [], group='oslo_policy') @@ -16290,16 +16292,18 @@ class LibvirtDriverTestCase(test.NoDBTestCase): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr.image_backend = mock.Mock() drvr.image_backend.by_name.return_value = drvr.image_backend + drvr.image_backend.exists.return_value = False with test.nested( mock.patch.object(os.path, 'exists'), mock.patch.object(libvirt_utils, 'get_instance_path'), mock.patch.object(utils, 'execute'), + mock.patch.object(shutil, 'rmtree'), mock.patch.object(drvr, '_undefine_domain'), mock.patch.object(drvr, 'unplug_vifs'), mock.patch.object(drvr, 'unfilter_instance') - ) as (mock_exists, mock_get_path, mock_exec, mock_undef, - mock_unplug, mock_unfilter): + ) as (mock_exists, mock_get_path, mock_exec, mock_rmtree, + mock_undef, mock_unplug, mock_unfilter): mock_exists.return_value = True mock_get_path.return_value = '/fake/inst' @@ -16307,6 +16311,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): mock_get_path.assert_called_once_with(ins_ref) mock_exec.assert_called_once_with('rm', '-rf', '/fake/inst_resize', delay_on_retry=True, attempts=5) + mock_rmtree.assert_called_once_with('/fake/inst') mock_undef.assert_called_once_with(ins_ref) mock_unplug.assert_called_once_with(ins_ref, fake_net) mock_unfilter.assert_called_once_with(ins_ref, fake_net) @@ -16322,8 +16327,10 @@ class LibvirtDriverTestCase(test.NoDBTestCase): mock.patch.object(os.path, 'exists'), mock.patch.object(libvirt_utils, 'get_instance_path'), mock.patch.object(utils, 'execute'), + mock.patch.object(shutil, 'rmtree'), mock.patch.object(drvr.image_backend, 'remove_snap')) as ( - mock_exists, mock_get_path, mock_exec, mock_remove): + mock_exists, mock_get_path, mock_exec, mock_rmtree, + mock_remove): mock_exists.return_value = True mock_get_path.return_value = '/fake/inst' @@ -16333,6 +16340,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): delay_on_retry=True, attempts=5) mock_remove.assert_called_once_with( libvirt_utils.RESIZE_SNAPSHOT_NAME, ignore_errors=True) + self.assertFalse(mock_rmtree.called) def test_cleanup_resize_snap_backend_image_does_not_exist(self): CONF.set_override('policy_dirs', [], group='oslo_policy') @@ -16346,8 +16354,10 @@ class LibvirtDriverTestCase(test.NoDBTestCase): mock.patch.object(os.path, 'exists'), mock.patch.object(libvirt_utils, 'get_instance_path'), mock.patch.object(utils, 'execute'), + mock.patch.object(shutil, 'rmtree'), mock.patch.object(drvr.image_backend, 'remove_snap')) as ( - mock_exists, mock_get_path, mock_exec, mock_remove): + mock_exists, mock_get_path, mock_exec, mock_rmtree, + mock_remove): mock_exists.return_value = True mock_get_path.return_value = '/fake/inst' @@ -16356,6 +16366,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): mock_exec.assert_called_once_with('rm', '-rf', '/fake/inst_resize', delay_on_retry=True, attempts=5) self.assertFalse(mock_remove.called) + mock_rmtree.called_once_with('/fake/inst') def test_get_instance_disk_info_exception(self): instance = self._create_instance() diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index d1660db29b..6679e5da0b 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -1110,7 +1110,8 @@ class LibvirtDriver(driver.ComputeDriver): host=CONF.host) def _cleanup_resize(self, instance, network_info): - target = libvirt_utils.get_instance_path(instance) + '_resize' + inst_base = libvirt_utils.get_instance_path(instance) + target = inst_base + '_resize' if os.path.exists(target): # Deletion can fail over NFS, so retry the deletion as required. @@ -1131,6 +1132,16 @@ class LibvirtDriver(driver.ComputeDriver): root_disk.remove_snap(libvirt_utils.RESIZE_SNAPSHOT_NAME, ignore_errors=True) + # NOTE(mjozefcz): + # self.image_backend.image for some backends recreates instance + # directory and image disk.info - remove it here if exists + if os.path.exists(inst_base) and not root_disk.exists(): + try: + shutil.rmtree(inst_base) + except OSError as e: + if e.errno != errno.ENOENT: + raise + if instance.host != CONF.host: self._undefine_domain(instance) self.unplug_vifs(instance, network_info)