libvirt: Fail when live block migrating instance with volumes

This raises an exception when attempting to live block migrate (nova
live-migration --block-migrate) an instance with attached volumes.
libvirt copies these volumes from themselves to themselves. At a
minimum, this is horribly slow and de-sparses a sparse volume; at
worst, this could cause massive data corruption.

(cherry picked from commit d667b6a63e)

Closes-Bug: 1398999
Change-Id: Ibcd423976bb9fea46e3e1cb23cc8e5cd944d8fc2
This commit is contained in:
Chris St. Pierre 2014-12-03 16:16:34 -06:00 committed by Claudiu Belu
parent 81ce2601ba
commit 98834ab9f7
2 changed files with 41 additions and 1 deletions

View File

@ -5993,7 +5993,9 @@ class LibvirtConnTestCase(test.TestCase):
conn.plug_vifs(mox.IsA(inst_ref), nw_info)
self.mox.ReplayAll()
result = conn.pre_live_migration(c, inst_ref, vol, nw_info, None)
result = conn.pre_live_migration(
c, inst_ref, vol, nw_info, None,
migrate_data={"block_migration": False})
target_res = {'graphics_listen_addrs': {'spice': '127.0.0.1',
'vnc': '127.0.0.1'}}
@ -6189,6 +6191,32 @@ class LibvirtConnTestCase(test.TestCase):
self.assertTrue(create_image_mock.called)
self.assertIsInstance(res, dict)
def test_pre_live_migration_block_migrate_fails(self):
bdms = [{
'connection_info': {
'serial': '12345',
u'data': {
'device_path':
u'/dev/disk/by-path/ip-1.2.3.4:3260-iqn.abc.12345.t-lun-X'
}
},
'mount_device': '/dev/sda'}]
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = db.instance_create(self.context, self.test_instance)
with contextlib.nested(
mock.patch.object(drvr, '_create_images_and_backing'),
mock.patch.object(drvr, 'ensure_filtering_rules_for_instance'),
mock.patch.object(drvr, 'plug_vifs'),
mock.patch.object(drvr, '_connect_volume'),
mock.patch.object(driver, 'block_device_info_get_mapping',
return_value=bdms)):
self.assertRaises(exception.MigrationError,
drvr.pre_live_migration,
self.context, instance, block_device_info=None,
network_info=[], disk_info={}, migrate_data={})
def test_get_instance_disk_info_works_correctly(self):
# Test data
instance_ref = db.instance_create(self.context, self.test_instance)

View File

@ -5577,6 +5577,18 @@ class LibvirtDriver(driver.ComputeDriver):
CONF.libvirt.virt_type, vol)
self._connect_volume(connection_info, disk_info)
if is_block_migration and len(block_device_mapping):
# NOTE(stpierre): if this instance has mapped volumes,
# we can't do a block migration, since that will
# result in volumes being copied from themselves to
# themselves, which is a recipe for disaster.
LOG.error(
_LE('Cannot block migrate instance %s with mapped volumes') %
instance.uuid)
raise exception.MigrationError(
_('Cannot block migrate instance %s with mapped volumes') %
instance.uuid)
# We call plug_vifs before the compute manager calls
# ensure_filtering_rules_for_instance, to ensure bridge is set up
# Retry operation is necessary because continuously request comes,