diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
old mode 100644
new mode 100755
index a4454333afc2..db1a692801f1
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -8275,6 +8275,61 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr._live_migration_uri('dest'),
params=params, flags=0)
+ @mock.patch.object(fakelibvirt.virDomain, "migrateToURI3")
+ @mock.patch.object(host.Host, 'has_min_version', return_value=True)
+ @mock.patch('nova.virt.libvirt.guest.Guest.get_xml_desc',
+ return_value='')
+ def _test_live_migration_block_migration_flags(self,
+ device_names, expected_flags,
+ mock_old_xml, mock_min_version, mock_migrateToURI3):
+ migrate_data = objects.LibvirtLiveMigrateData(
+ graphics_listen_addr_vnc='0.0.0.0',
+ graphics_listen_addr_spice='0.0.0.0',
+ serial_listen_addr='127.0.0.1',
+ target_connect_addr=None,
+ bdms=[],
+ block_migration=True)
+
+ 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)
+ drvr._live_migration_operation(self.context, instance, 'dest',
+ True, migrate_data, guest,
+ device_names)
+
+ params = {
+ 'migrate_disks': device_names,
+ 'bandwidth': CONF.libvirt.live_migration_bandwidth,
+ 'destination_xml': b'',
+ }
+ mock_migrateToURI3.assert_called_once_with(
+ drvr._live_migration_uri('dest'), params=params,
+ flags=expected_flags)
+
+ def test_live_migration_block_migration_with_devices(self):
+ device_names = ['vda']
+ expected_flags = (fakelibvirt.VIR_MIGRATE_NON_SHARED_INC |
+ fakelibvirt.VIR_MIGRATE_UNDEFINE_SOURCE |
+ fakelibvirt.VIR_MIGRATE_PERSIST_DEST |
+ fakelibvirt.VIR_MIGRATE_PEER2PEER |
+ fakelibvirt.VIR_MIGRATE_LIVE)
+
+ self._test_live_migration_block_migration_flags(device_names,
+ expected_flags)
+
+ def test_live_migration_block_migration_all_filtered(self):
+ device_names = []
+ expected_flags = (fakelibvirt.VIR_MIGRATE_UNDEFINE_SOURCE |
+ fakelibvirt.VIR_MIGRATE_PERSIST_DEST |
+ fakelibvirt.VIR_MIGRATE_PEER2PEER |
+ fakelibvirt.VIR_MIGRATE_LIVE)
+
+ self._test_live_migration_block_migration_flags(device_names,
+ 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',
@@ -8307,9 +8362,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance = objects.Instance(**self.test_instance)
drvr._live_migration_operation(self.context, instance, 'dest',
True, migrate_data, guest, disk_paths)
+ expected_flags = (fakelibvirt.VIR_MIGRATE_UNDEFINE_SOURCE |
+ fakelibvirt.VIR_MIGRATE_PERSIST_DEST |
+ fakelibvirt.VIR_MIGRATE_TUNNELLED |
+ fakelibvirt.VIR_MIGRATE_PEER2PEER |
+ fakelibvirt.VIR_MIGRATE_LIVE)
mock_migrateToURI3.assert_called_once_with(
drvr._live_migration_uri('dest'),
- params=params, flags=159)
+ params=params, flags=expected_flags)
def test_live_migration_raises_exception(self):
# Confirms recover method is called when exceptions are raised.
diff --git a/nova/virt/libvirt/guest.py b/nova/virt/libvirt/guest.py
old mode 100644
new mode 100755
index ee74d90ec708..457d73bdf135
--- a/nova/virt/libvirt/guest.py
+++ b/nova/virt/libvirt/guest.py
@@ -641,6 +641,18 @@ class Guest(object):
destination, flags=flags, bandwidth=bandwidth)
else:
if params:
+ # Due to a quirk in the libvirt python bindings,
+ # VIR_MIGRATE_NON_SHARED_INC with an empty migrate_disks is
+ # interpreted as "block migrate all writable disks" rather than
+ # "don't block migrate any disks". This includes attached
+ # volumes, which will potentially corrupt data on those
+ # volumes. Consequently we need to explicitly unset
+ # VIR_MIGRATE_NON_SHARED_INC if there are no disks to be block
+ # migrated.
+ if (flags & libvirt.VIR_MIGRATE_NON_SHARED_INC != 0 and
+ not params.get('migrate_disks')):
+ flags &= ~libvirt.VIR_MIGRATE_NON_SHARED_INC
+
# In migrateToURI3 these parameters are extracted from the
# `params` dict
if migrate_uri: