From 33fa92b6cb1dfeb88a4188c0e4e4ce51be1f7a4b Mon Sep 17 00:00:00 2001 From: Sivasathurappan Radhakrishnan Date: Fri, 10 Mar 2017 22:16:42 +0000 Subject: [PATCH] Allow live migrate paused instance when post copy is enabled Live migration of paused instance fails when VIR_MIGRATE_POSTCOPY flag is set. In this patch, the flag is unset to permit live migration of paused instance. Change-Id: Ib5cbc948cb953e35a22bcbb859976f0afddcb662 Closes-Bug: #1671011 --- nova/tests/unit/virt/libvirt/test_driver.py | 33 +++++++++++++++++++-- nova/virt/libvirt/driver.py | 11 +++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 12165a14672c..b21257c5f521 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -694,6 +694,7 @@ def _create_test_instance(): 'numa_topology': None, 'config_drive': None, 'vm_mode': None, + 'vm_state': None, 'kernel_id': None, 'ramdisk_id': None, 'os_type': 'linux', @@ -12318,7 +12319,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_updated_guest_xml, mock_migrateToURI3): self.compute = manager.ComputeManager() - instance_ref = self.test_instance + instance_ref = objects.Instance(**self.test_instance) target_connection = '127.0.0.2' target_xml = self.device_xml_tmpl.format( @@ -12487,7 +12488,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_migrateToURI3, mock_min_version): self.compute = manager.ComputeManager() - instance_ref = self.test_instance + instance_ref = objects.Instance(**self.test_instance) target_connection = '127.0.0.2' target_xml = self.device_xml_tmpl.format( @@ -13102,6 +13103,33 @@ class LibvirtConnTestCase(test.NoDBTestCase, drvr._live_migration_uri(target_connection), params=params, flags=expected_flags) + @mock.patch.object(host.Host, 'has_min_version', return_value=True) + @mock.patch.object(fakelibvirt.virDomain, "migrateToURI3") + @mock.patch('nova.virt.libvirt.migration.get_updated_guest_xml', + return_value='') + def test_live_migration_paused_instance_postcopy(self, mock_new_xml, + mock_migrateToURI3, + mock_min_version): + disk_paths = [] + params = {'bandwidth': CONF.libvirt.live_migration_bandwidth} + migrate_data = objects.LibvirtLiveMigrateData(block_migration=False, + serial_listen_addr=False) + dom = fakelibvirt.virDomain + guest = libvirt_guest.Guest(dom) + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + drvr._parse_migration_flags() + instance = objects.Instance(**self.test_instance) + instance.vm_state = vm_states.PAUSED + + drvr._live_migration_operation(self.context, instance, 'dest', + True, migrate_data, guest, + disk_paths) + + # Verify VIR_MIGRATE_POSTCOPY flag was not set + self.assertEqual(drvr._live_migration_flags, 27) + mock_migrateToURI3.assert_called_once_with( + drvr._live_migration_uri('dest'), params=params, flags=27) + @mock.patch.object(host.Host, 'has_min_version', return_value=True) @mock.patch.object(fakelibvirt.virDomain, "migrateToURI3") @mock.patch('nova.virt.libvirt.migration.get_updated_guest_xml', @@ -13111,7 +13139,6 @@ class LibvirtConnTestCase(test.NoDBTestCase, self, mock_old_xml, mock_new_xml, mock_migrateToURI3, mock_min_version): self.flags(live_migration_with_native_tls=True, group='libvirt') - target_connection = None disk_paths = ['vda', 'vdb'] diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 2be2ebc9ac6b..bce5f2df7360 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -10211,6 +10211,17 @@ class LibvirtDriver(driver.ComputeDriver): else: migration_flags = self._live_migration_flags + # Note(siva_krishnan): live migrating paused instance fails + # when VIR_MIGRATE_POSTCOPY flag is set. It is unset here + # to permit live migration of paused instance. + if ( + instance.vm_state == vm_states.PAUSED and + self._is_post_copy_enabled(migration_flags) + ): + LOG.debug('Post-copy flag unset because instance is paused.', + instance=instance) + migration_flags ^= libvirt.VIR_MIGRATE_POSTCOPY + if not migrate_data.serial_listen_addr: # In this context we want to ensure that serial console is # disabled on source node. This is because nova couldn't