allow live migration in case of a booted from volume instance

A BadRequest error always occurr in case of
a non shared storage environment
even if the instance is booted from volume.
We should allow user to execute live migration
in case of a booted from volume instance.

Closes-Bug: #1469006
Change-Id: I7989128d5bfa027c8f566c9d66956b1c4d328db5
This commit is contained in:
Hiroyuki Eguchi 2015-08-05 21:32:08 +09:00
parent 91f8cc9c15
commit 177e9ff722
2 changed files with 52 additions and 4 deletions

View File

@ -5373,8 +5373,10 @@ class LibvirtConnTestCase(test.NoDBTestCase):
def _mock_can_live_migrate_source(self, block_migration=False,
is_shared_block_storage=False,
is_shared_instance_path=False,
is_booted_from_volume=False,
disk_available_mb=1024,
block_device_info=None):
block_device_info=None,
block_device_text=None):
instance = objects.Instance(**self.test_instance)
dest_check_data = {'filename': 'file',
'image_type': 'default',
@ -5389,6 +5391,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.mox.StubOutWithMock(drvr, '_check_shared_storage_test_file')
drvr._check_shared_storage_test_file('file').AndReturn(
is_shared_instance_path)
self.mox.StubOutWithMock(drvr, "get_instance_disk_info")
drvr.get_instance_disk_info(instance,
block_device_info=block_device_info).\
AndReturn(block_device_text)
self.mox.StubOutWithMock(drvr, '_is_booted_from_volume')
drvr._is_booted_from_volume(instance, block_device_text).AndReturn(
is_booted_from_volume)
return (instance, dest_check_data, drvr)
@ -5463,7 +5472,6 @@ class LibvirtConnTestCase(test.NoDBTestCase):
block_migration=True,
disk_available_mb=0)
self.mox.StubOutWithMock(drvr, "get_instance_disk_info")
drvr.get_instance_disk_info(instance,
block_device_info=None).AndReturn(
'[{"virt_disk_size":2}]')
@ -5473,6 +5481,23 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr.check_can_live_migrate_source,
self.context, instance, dest_check_data)
def test_check_can_live_migrate_source_booted_from_volume(self):
instance, dest_check_data, drvr = self._mock_can_live_migrate_source(
is_booted_from_volume=True,
block_device_text='[]')
self.mox.ReplayAll()
drvr.check_can_live_migrate_source(self.context, instance,
dest_check_data)
def test_check_can_live_migrate_source_booted_from_volume_with_swap(self):
instance, dest_check_data, drvr = self._mock_can_live_migrate_source(
is_booted_from_volume=True,
block_device_text='[{"path":"disk.swap"}]')
self.mox.ReplayAll()
self.assertRaises(exception.InvalidSharedStorage,
drvr.check_can_live_migrate_source,
self.context, instance, dest_check_data)
def _is_shared_block_storage_test_create_mocks(self, disks):
# Test data
instance_xml = ("<domain type='kvm'><name>instance-0000000a</name>"

View File

@ -2630,6 +2630,20 @@ class LibvirtDriver(driver.ComputeDriver):
return ((not bool(instance.get('image_ref')))
or 'disk' not in disk_mapping)
@staticmethod
def _has_local_disk(instance, disk_mapping):
"""Determines whether the VM has a local disk
Determines whether the disk mapping indicates that the VM
has a local disk (e.g. ephemeral, swap disk and config-drive).
"""
if disk_mapping:
if ('disk.local' in disk_mapping or
'disk.swap' in disk_mapping or
'disk.config' in disk_mapping):
return True
return False
def _inject_data(self, instance, network_info, admin_pass, files, suffix):
"""Injects data in a disk image
@ -5034,6 +5048,12 @@ class LibvirtDriver(driver.ComputeDriver):
self._is_shared_block_storage(instance, dest_check_data,
block_device_info)})
disk_info_text = self.get_instance_disk_info(
instance, block_device_info=block_device_info)
booted_from_volume = self._is_booted_from_volume(instance,
disk_info_text)
has_local_disk = self._has_local_disk(instance, disk_info_text)
if dest_check_data['block_migration']:
if (dest_check_data['is_shared_block_storage'] or
dest_check_data['is_shared_instance_path']):
@ -5046,9 +5066,12 @@ class LibvirtDriver(driver.ComputeDriver):
block_device_info)
elif not (dest_check_data['is_shared_block_storage'] or
dest_check_data['is_shared_instance_path']):
dest_check_data['is_shared_instance_path'] or
(booted_from_volume and not has_local_disk)):
reason = _("Live migration can not be used "
"without shared storage.")
"without shared storage except "
"a booted from volume VM which "
"does not have a local disk.")
raise exception.InvalidSharedStorage(reason=reason, path=source)
# NOTE(mikal): include the instance directory name here because it