From 3fd24ba528314b45fe5f91110638ada7bf7fcb96 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Mon, 4 Jan 2016 20:11:08 +0000 Subject: [PATCH] libvirt: force config related migration flags The Nova libvirt driver relies on libvirt deleting the configuration from the source host at the end of the migration, otherwise the VM remains on the source host in a "shut off" state ... except in the case of block migration, where the cleanup code path does actually delete the VM's libvirt config. If the Nova code assume's that VIR_MIGRATE_UNDEFINE_SOURCE is set, there's really no sense in allowing users to configure without it. Similarly, the driver explicitly saves the VM configuration on the destination host, so it makes no sense to allow users to configure the VIR_MIGRATE_PERSIST_DEST flag. Change-Id: Ibeb35590fd83f2190c9c9cb16128e9e2628b38cd Signed-off-by: Mark McLoughlin --- nova/tests/unit/virt/libvirt/fakelibvirt.py | 1 + nova/tests/unit/virt/libvirt/test_driver.py | 31 +++++++++++++++++++ nova/virt/libvirt/driver.py | 14 +++++++++ ...ation-flags-mangling-a2407a31ddf17427.yaml | 4 ++- 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/nova/tests/unit/virt/libvirt/fakelibvirt.py b/nova/tests/unit/virt/libvirt/fakelibvirt.py index 085064b892df..b47dfc2fbca3 100644 --- a/nova/tests/unit/virt/libvirt/fakelibvirt.py +++ b/nova/tests/unit/virt/libvirt/fakelibvirt.py @@ -91,6 +91,7 @@ VIR_CRED_EXTERNAL = 9 VIR_MIGRATE_LIVE = 1 VIR_MIGRATE_PEER2PEER = 2 VIR_MIGRATE_TUNNELLED = 4 +VIR_MIGRATE_PERSIST_DEST = 8 VIR_MIGRATE_UNDEFINE_SOURCE = 16 VIR_MIGRATE_NON_SHARED_INC = 128 diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index d7f91ac42e40..1d390ce137f8 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -991,6 +991,37 @@ class LibvirtConnTestCase(test.NoDBTestCase): msg = mock_log.warning.call_args_list[1] self.assertIn('Removing the VIR_MIGRATE_PEER2PEER flag', msg[0][0]) + @mock.patch('nova.virt.libvirt.driver.LOG') + def test_parse_migration_flags_config_mgmt(self, mock_log): + self._do_test_parse_migration_flags( + lm_config=('VIR_MIGRATE_PERSIST_DEST, ' + 'VIR_MIGRATE_PEER2PEER, ' + 'VIR_MIGRATE_LIVE, ' + 'VIR_MIGRATE_TUNNELLED'), + bm_config=('VIR_MIGRATE_PERSIST_DEST, ' + 'VIR_MIGRATE_PEER2PEER, ' + 'VIR_MIGRATE_LIVE, ' + 'VIR_MIGRATE_TUNNELLED, ' + 'VIR_MIGRATE_NON_SHARED_INC'), + lm_expected=(libvirt_driver.libvirt.VIR_MIGRATE_UNDEFINE_SOURCE | + libvirt_driver.libvirt.VIR_MIGRATE_PEER2PEER | + libvirt_driver.libvirt.VIR_MIGRATE_LIVE | + libvirt_driver.libvirt.VIR_MIGRATE_TUNNELLED), + bm_expected=(libvirt_driver.libvirt.VIR_MIGRATE_UNDEFINE_SOURCE | + libvirt_driver.libvirt.VIR_MIGRATE_PEER2PEER | + libvirt_driver.libvirt.VIR_MIGRATE_LIVE | + libvirt_driver.libvirt.VIR_MIGRATE_TUNNELLED | + libvirt_driver.libvirt.VIR_MIGRATE_NON_SHARED_INC)) + + msg = mock_log.warning.call_args_list[0] + self.assertIn('Adding the VIR_MIGRATE_UNDEFINE_SOURCE flag', msg[0][0]) + msg = mock_log.warning.call_args_list[1] + self.assertIn('Removing the VIR_MIGRATE_PERSIST_DEST flag', msg[0][0]) + msg = mock_log.warning.call_args_list[2] + self.assertIn('Adding the VIR_MIGRATE_UNDEFINE_SOURCE flag', msg[0][0]) + msg = mock_log.warning.call_args_list[3] + self.assertIn('Removing the VIR_MIGRATE_PERSIST_DEST flag', msg[0][0]) + @mock.patch('nova.utils.get_image_from_system_metadata') @mock.patch.object(host.Host, 'has_min_version', return_value=True) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 7edb8d56402d..70dfc019047b 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -659,6 +659,20 @@ class LibvirtDriver(driver.ComputeDriver): 'virt_type': CONF.libvirt.virt_type}) migration_flags |= libvirt.VIR_MIGRATE_PEER2PEER + if (migration_flags & libvirt.VIR_MIGRATE_UNDEFINE_SOURCE) == 0: + LOG.warning(_LW('Adding the VIR_MIGRATE_UNDEFINE_SOURCE flag to ' + '%(config_name)s because, without it, migrated ' + 'VMs will remain defined on the source host'), + {'config_name': config_name}) + migration_flags |= libvirt.VIR_MIGRATE_UNDEFINE_SOURCE + + if (migration_flags & libvirt.VIR_MIGRATE_PERSIST_DEST) != 0: + LOG.warning(_LW('Removing the VIR_MIGRATE_PERSIST_DEST flag from ' + '%(config_name)s as Nova ensures the VM is ' + 'persisted on the destination host'), + {'config_name': config_name}) + migration_flags &= ~libvirt.VIR_MIGRATE_PERSIST_DEST + return migration_flags def _check_block_migration_flags(self, live_migration_flags, diff --git a/releasenotes/notes/libvirt-live-migration-flags-mangling-a2407a31ddf17427.yaml b/releasenotes/notes/libvirt-live-migration-flags-mangling-a2407a31ddf17427.yaml index 979994bbf376..fd2d6f7c6713 100644 --- a/releasenotes/notes/libvirt-live-migration-flags-mangling-a2407a31ddf17427.yaml +++ b/releasenotes/notes/libvirt-live-migration-flags-mangling-a2407a31ddf17427.yaml @@ -6,5 +6,7 @@ upgrade: contain VIR_MIGRATE_SHARED_INC but block_migration_flag must contain it. Both options must contain the VIR_MIGRATE_PEER2PEER, except when using the 'xen' virt - type this flag is not supported. + type this flag is not supported. Both flags must contain + the VIR_MIGRATE_UNDEFINE_SOURCE flag and not contain the + VIR_MIGRATE_PERSIST_DEST flag.