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. Closes-Bug: 1398999 Change-Id: Ibcd423976bb9fea46e3e1cb23cc8e5cd944d8fc2
This commit is contained in:
parent
9b27095a00
commit
d667b6a63e
|
@ -440,7 +440,7 @@ class FakeNodeDevice(object):
|
|||
return self.xml
|
||||
|
||||
|
||||
class LibvirtConnTestCase(test.NoDBTestCase):
|
||||
class LibvirtConnTestCase(test.TestCase):
|
||||
|
||||
REQUIRES_LOCKING = True
|
||||
|
||||
|
@ -6881,7 +6881,9 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
drvr.plug_vifs(mox.IsA(instance), nw_info)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
result = drvr.pre_live_migration(c, instance, vol, nw_info, None)
|
||||
result = drvr.pre_live_migration(
|
||||
c, instance, vol, nw_info, None,
|
||||
migrate_data={"block_migration": False})
|
||||
|
||||
target_ret = {
|
||||
'graphics_listen_addrs': {'spice': '127.0.0.1', 'vnc': '127.0.0.1'},
|
||||
|
@ -7080,6 +7082,32 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
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 = objects.Instance(**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 = objects.Instance(**self.test_instance)
|
||||
|
|
|
@ -5442,6 +5442,18 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
CONF.libvirt.virt_type, image_meta, 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,
|
||||
|
|
Loading…
Reference in New Issue