Check instance on dest once during block migration
During live block migrations both pre_live_migration and pre_block_migration check for the presence of the instance on the destination and create the instance dir if it doesn't exist. As a result the call to pre_block_migration always fails as pre_live_migration has already created the instance dir on the destination. As it turns out the pre_block_migration call is completely unnecessary. The libvirt driver is the only driver that uses the call and the work it does can easily be done in the existing pre_live_migration call. In order to streamline things we completely remove the pre_block_migration call from all drivers. Additionally we update the function definition for pre_live_migration to pass needed disk info down to the virt drivers. Fixes bug: #1193359 Change-Id: Id9dfe482db3471d6a1b9b6c7d59a5ddc48775d7f
This commit is contained in:
parent
9e2d4ac460
commit
659ec75eaf
@ -3681,6 +3681,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
|||||||
instance,
|
instance,
|
||||||
block_device_info,
|
block_device_info,
|
||||||
self._legacy_nw_info(network_info),
|
self._legacy_nw_info(network_info),
|
||||||
|
disk,
|
||||||
migrate_data)
|
migrate_data)
|
||||||
|
|
||||||
# NOTE(tr3buchet): setup networks on destination host
|
# NOTE(tr3buchet): setup networks on destination host
|
||||||
@ -3696,10 +3697,6 @@ class ComputeManager(manager.SchedulerDependentManager):
|
|||||||
self.driver.ensure_filtering_rules_for_instance(instance,
|
self.driver.ensure_filtering_rules_for_instance(instance,
|
||||||
self._legacy_nw_info(network_info))
|
self._legacy_nw_info(network_info))
|
||||||
|
|
||||||
# Preparation for block migration
|
|
||||||
if block_migration:
|
|
||||||
self.driver.pre_block_migration(context, instance, disk)
|
|
||||||
|
|
||||||
self._notify_about_instance_usage(
|
self._notify_about_instance_usage(
|
||||||
context, instance, "live_migration.pre.end",
|
context, instance, "live_migration.pre.end",
|
||||||
network_info=network_info)
|
network_info=network_info)
|
||||||
|
@ -3901,6 +3901,7 @@ class ComputeTestCase(BaseTestCase):
|
|||||||
self.compute.driver.pre_live_migration(mox.IsA(c), mox.IsA(instance),
|
self.compute.driver.pre_live_migration(mox.IsA(c), mox.IsA(instance),
|
||||||
{'block_device_mapping': []},
|
{'block_device_mapping': []},
|
||||||
mox.IgnoreArg(),
|
mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg(),
|
||||||
mox.IgnoreArg())
|
mox.IgnoreArg())
|
||||||
self.mox.StubOutWithMock(self.compute.driver,
|
self.mox.StubOutWithMock(self.compute.driver,
|
||||||
'ensure_filtering_rules_for_instance')
|
'ensure_filtering_rules_for_instance')
|
||||||
|
@ -684,7 +684,7 @@ class HyperVAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
self._mox.ReplayAll()
|
self._mox.ReplayAll()
|
||||||
self._conn.pre_live_migration(self._context, instance,
|
self._conn.pre_live_migration(self._context, instance,
|
||||||
block_device_info, network_info)
|
block_device_info, None, network_info)
|
||||||
self._mox.VerifyAll()
|
self._mox.VerifyAll()
|
||||||
|
|
||||||
if cow:
|
if cow:
|
||||||
|
@ -19,7 +19,6 @@ import copy
|
|||||||
import errno
|
import errno
|
||||||
import eventlet
|
import eventlet
|
||||||
import fixtures
|
import fixtures
|
||||||
import json
|
|
||||||
import mox
|
import mox
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -2528,6 +2527,11 @@ class LibvirtConnTestCase(test.TestCase):
|
|||||||
def fixed_ips(self):
|
def fixed_ips(self):
|
||||||
return ["test_ip_addr"]
|
return ["test_ip_addr"]
|
||||||
|
|
||||||
|
def fake_none(*args, **kwargs):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.stubs.Set(conn, '_create_images_and_backing', fake_none)
|
||||||
|
|
||||||
inst_ref = {'id': 'foo'}
|
inst_ref = {'id': 'foo'}
|
||||||
c = context.get_admin_context()
|
c = context.get_admin_context()
|
||||||
nw_info = FakeNetworkInfo()
|
nw_info = FakeNetworkInfo()
|
||||||
@ -2550,7 +2554,7 @@ class LibvirtConnTestCase(test.TestCase):
|
|||||||
conn.plug_vifs(mox.IsA(inst_ref), nw_info)
|
conn.plug_vifs(mox.IsA(inst_ref), nw_info)
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
result = conn.pre_live_migration(c, inst_ref, vol, nw_info)
|
result = conn.pre_live_migration(c, inst_ref, vol, nw_info, None)
|
||||||
self.assertEqual(result, None)
|
self.assertEqual(result, None)
|
||||||
|
|
||||||
def test_pre_live_migration_vol_backed_works_correctly_mocked(self):
|
def test_pre_live_migration_vol_backed_works_correctly_mocked(self):
|
||||||
@ -2562,6 +2566,11 @@ class LibvirtConnTestCase(test.TestCase):
|
|||||||
{'connection_info': 'dummy', 'mount_device': '/dev/sdb'}]}
|
{'connection_info': 'dummy', 'mount_device': '/dev/sdb'}]}
|
||||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||||
|
|
||||||
|
def fake_none(*args, **kwargs):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.stubs.Set(conn, '_create_images_and_backing', fake_none)
|
||||||
|
|
||||||
class FakeNetworkInfo():
|
class FakeNetworkInfo():
|
||||||
def fixed_ips(self):
|
def fixed_ips(self):
|
||||||
return ["test_ip_addr"]
|
return ["test_ip_addr"]
|
||||||
@ -2587,50 +2596,13 @@ class LibvirtConnTestCase(test.TestCase):
|
|||||||
'block_migration': False,
|
'block_migration': False,
|
||||||
'instance_relative_path': inst_ref['name']
|
'instance_relative_path': inst_ref['name']
|
||||||
}
|
}
|
||||||
ret = conn.pre_live_migration(c, inst_ref, vol, nw_info,
|
ret = conn.pre_live_migration(c, inst_ref, vol, nw_info, None,
|
||||||
migrate_data)
|
migrate_data)
|
||||||
self.assertEqual(ret, None)
|
self.assertEqual(ret, None)
|
||||||
self.assertTrue(os.path.exists('%s/%s/' % (tmpdir,
|
self.assertTrue(os.path.exists('%s/%s/' % (tmpdir,
|
||||||
inst_ref['name'])))
|
inst_ref['name'])))
|
||||||
db.instance_destroy(self.context, inst_ref['uuid'])
|
db.instance_destroy(self.context, inst_ref['uuid'])
|
||||||
|
|
||||||
def test_pre_block_migration_works_correctly(self):
|
|
||||||
# Replace instances_path since this testcase creates tmpfile
|
|
||||||
with utils.tempdir() as tmpdir:
|
|
||||||
self.flags(instances_path=tmpdir)
|
|
||||||
|
|
||||||
# Test data
|
|
||||||
instance_ref = db.instance_create(self.context, self.test_instance)
|
|
||||||
dummy_info = [{'path': '%s/disk' % tmpdir,
|
|
||||||
'disk_size': 10737418240,
|
|
||||||
'type': 'raw',
|
|
||||||
'backing_file': ''},
|
|
||||||
{'backing_file': 'otherdisk_1234567',
|
|
||||||
'path': '%s/otherdisk' % tmpdir,
|
|
||||||
'virt_disk_size': 10737418240}]
|
|
||||||
dummyjson = json.dumps(dummy_info)
|
|
||||||
|
|
||||||
# qemu-img should be mockd since test environment might not have
|
|
||||||
# large disk space.
|
|
||||||
self.mox.StubOutWithMock(imagebackend.Image, 'cache')
|
|
||||||
imagebackend.Image.cache(context=mox.IgnoreArg(),
|
|
||||||
fetch_func=mox.IgnoreArg(),
|
|
||||||
filename='otherdisk_1234567',
|
|
||||||
image_id=self.test_instance['image_ref'],
|
|
||||||
project_id='fake',
|
|
||||||
size=10737418240L,
|
|
||||||
user_id=None).AndReturn(None)
|
|
||||||
self.mox.ReplayAll()
|
|
||||||
|
|
||||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
|
||||||
conn.pre_block_migration(self.context, instance_ref,
|
|
||||||
dummyjson)
|
|
||||||
|
|
||||||
self.assertTrue(os.path.exists('%s/%s/' %
|
|
||||||
(tmpdir, instance_ref['uuid'])))
|
|
||||||
|
|
||||||
db.instance_destroy(self.context, instance_ref['uuid'])
|
|
||||||
|
|
||||||
def test_get_instance_disk_info_works_correctly(self):
|
def test_get_instance_disk_info_works_correctly(self):
|
||||||
# Test data
|
# Test data
|
||||||
instance_ref = db.instance_create(self.context, self.test_instance)
|
instance_ref = db.instance_create(self.context, self.test_instance)
|
||||||
|
@ -3092,7 +3092,7 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase):
|
|||||||
# ensure method is present
|
# ensure method is present
|
||||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
|
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
|
||||||
self.conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
|
self.conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
|
||||||
self.conn.pre_live_migration(None, None, None, None)
|
self.conn.pre_live_migration(None, None, None, None, None)
|
||||||
|
|
||||||
def test_post_live_migration_at_destination(self):
|
def test_post_live_migration_at_destination(self):
|
||||||
# ensure method is present
|
# ensure method is present
|
||||||
|
@ -474,29 +474,19 @@ class ComputeDriver(object):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def pre_live_migration(self, ctxt, instance_ref,
|
def pre_live_migration(self, ctxt, instance_ref, block_device_info,
|
||||||
block_device_info, network_info,
|
network_info, disk_info, migrate_data=None):
|
||||||
migrate_data=None):
|
|
||||||
"""Prepare an instance for live migration
|
"""Prepare an instance for live migration
|
||||||
|
|
||||||
:param ctxt: security context
|
:param ctxt: security context
|
||||||
:param instance_ref: instance object that will be migrated
|
:param instance_ref: instance object that will be migrated
|
||||||
:param block_device_info: instance block device information
|
:param block_device_info: instance block device information
|
||||||
:param network_info: instance network information
|
:param network_info: instance network information
|
||||||
|
:param disk_info: instance disk information
|
||||||
:param migrate_data: implementation specific data dict.
|
:param migrate_data: implementation specific data dict.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def pre_block_migration(self, ctxt, instance_ref, disk_info):
|
|
||||||
"""Prepare a block device for migration
|
|
||||||
|
|
||||||
:param ctxt: security context
|
|
||||||
:param instance_ref: instance object that will have its disk migrated
|
|
||||||
:param disk_info: information about disk to be migrated (as returned
|
|
||||||
from get_instance_disk_info())
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def live_migration(self, ctxt, instance_ref, dest,
|
def live_migration(self, ctxt, instance_ref, dest,
|
||||||
post_method, recover_method, block_migration=False,
|
post_method, recover_method, block_migration=False,
|
||||||
migrate_data=None):
|
migrate_data=None):
|
||||||
|
@ -382,7 +382,7 @@ class FakeDriver(driver.ComputeDriver):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def pre_live_migration(self, context, instance_ref, block_device_info,
|
def pre_live_migration(self, context, instance_ref, block_device_info,
|
||||||
network_info, migrate_data=None):
|
network_info, disk, migrate_data=None):
|
||||||
return
|
return
|
||||||
|
|
||||||
def unfilter_instance(self, instance_ref, network_info):
|
def unfilter_instance(self, instance_ref, network_info):
|
||||||
|
@ -115,7 +115,7 @@ class HyperVDriver(driver.ComputeDriver):
|
|||||||
block_migration, migrate_data)
|
block_migration, migrate_data)
|
||||||
|
|
||||||
def pre_live_migration(self, context, instance, block_device_info,
|
def pre_live_migration(self, context, instance, block_device_info,
|
||||||
network_info, migrate_data=None):
|
network_info, disk, migrate_data=None):
|
||||||
self._livemigrationops.pre_live_migration(context, instance,
|
self._livemigrationops.pre_live_migration(context, instance,
|
||||||
block_device_info,
|
block_device_info,
|
||||||
network_info)
|
network_info)
|
||||||
|
@ -1438,7 +1438,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
# NOTE (rmk): Re-populate any missing backing files.
|
# NOTE (rmk): Re-populate any missing backing files.
|
||||||
disk_info_json = self.get_instance_disk_info(instance['name'], xml,
|
disk_info_json = self.get_instance_disk_info(instance['name'], xml,
|
||||||
block_device_info)
|
block_device_info)
|
||||||
self._create_images_and_backing(context, instance, disk_info_json)
|
instance_dir = libvirt_utils.get_instance_path(instance)
|
||||||
|
self._create_images_and_backing(context, instance, instance_dir,
|
||||||
|
disk_info_json)
|
||||||
|
|
||||||
# Initialize all the necessary networking, block devices and
|
# Initialize all the necessary networking, block devices and
|
||||||
# start the instance.
|
# start the instance.
|
||||||
@ -3395,7 +3397,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
instance['project_id'])
|
instance['project_id'])
|
||||||
|
|
||||||
def pre_live_migration(self, context, instance, block_device_info,
|
def pre_live_migration(self, context, instance, block_device_info,
|
||||||
network_info, migrate_data=None):
|
network_info, disk_info, migrate_data=None):
|
||||||
"""Preparation live migration."""
|
"""Preparation live migration."""
|
||||||
# Steps for volume backed instance live migration w/o shared storage.
|
# Steps for volume backed instance live migration w/o shared storage.
|
||||||
is_shared_storage = True
|
is_shared_storage = True
|
||||||
@ -3422,6 +3424,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
raise exception.DestinationDiskExists(path=instance_dir)
|
raise exception.DestinationDiskExists(path=instance_dir)
|
||||||
os.mkdir(instance_dir)
|
os.mkdir(instance_dir)
|
||||||
|
|
||||||
|
# Ensure images and backing files are present.
|
||||||
|
self._create_images_and_backing(context, instance, instance_dir,
|
||||||
|
disk_info)
|
||||||
|
|
||||||
if is_volume_backed and not (is_block_migration or is_shared_storage):
|
if is_volume_backed and not (is_block_migration or is_shared_storage):
|
||||||
# Touch the console.log file, required by libvirt.
|
# Touch the console.log file, required by libvirt.
|
||||||
console_file = self._get_console_log_path(instance)
|
console_file = self._get_console_log_path(instance)
|
||||||
@ -3467,28 +3473,21 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
instance=instance)
|
instance=instance)
|
||||||
greenthread.sleep(1)
|
greenthread.sleep(1)
|
||||||
|
|
||||||
def pre_block_migration(self, context, instance, disk_info_json):
|
def _create_images_and_backing(self, context, instance, instance_dir,
|
||||||
"""Preparation for block migration."""
|
disk_info_json):
|
||||||
# NOTE (rmk): When preparing for a block migration, the instance dir
|
|
||||||
# should not exist on the destination hypervisor.
|
|
||||||
instance_dir = libvirt_utils.get_instance_path(instance)
|
|
||||||
if os.path.exists(instance_dir):
|
|
||||||
raise exception.DestinationDiskExists(path=instance_dir)
|
|
||||||
os.mkdir(instance_dir)
|
|
||||||
self._create_images_and_backing(context, instance, disk_info_json)
|
|
||||||
|
|
||||||
def _create_images_and_backing(self, context, instance, disk_info_json):
|
|
||||||
"""
|
"""
|
||||||
:params context: security context
|
:params context: security context
|
||||||
:params instance:
|
:params instance:
|
||||||
nova.db.sqlalchemy.models.Instance object
|
nova.db.sqlalchemy.models.Instance object
|
||||||
instance object that is migrated.
|
instance object that is migrated.
|
||||||
|
:params instance_dir:
|
||||||
|
instance path to use, calculated externally to handle block
|
||||||
|
migrating an instance with an old style instance path
|
||||||
:params disk_info_json:
|
:params disk_info_json:
|
||||||
json strings specified in get_instance_disk_info
|
json strings specified in get_instance_disk_info
|
||||||
|
|
||||||
"""
|
"""
|
||||||
disk_info = jsonutils.loads(disk_info_json)
|
disk_info = jsonutils.loads(disk_info_json)
|
||||||
instance_dir = libvirt_utils.get_instance_path(instance)
|
|
||||||
|
|
||||||
for info in disk_info:
|
for info in disk_info:
|
||||||
base = os.path.basename(info['path'])
|
base = os.path.basename(info['path'])
|
||||||
|
@ -465,13 +465,6 @@ class XenAPIDriver(driver.ComputeDriver):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def pre_block_migration(self, ctxt, instance_ref, disk_info_json):
|
|
||||||
"""Used by libvirt for live migration. We rely on xenapi
|
|
||||||
checks to do this for us. May be used in the future to
|
|
||||||
populate the vdi/vif maps.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def live_migration(self, ctxt, instance_ref, dest,
|
def live_migration(self, ctxt, instance_ref, dest,
|
||||||
post_method, recover_method, block_migration=False,
|
post_method, recover_method, block_migration=False,
|
||||||
migrate_data=None):
|
migrate_data=None):
|
||||||
@ -495,7 +488,7 @@ class XenAPIDriver(driver.ComputeDriver):
|
|||||||
recover_method, block_migration, migrate_data)
|
recover_method, block_migration, migrate_data)
|
||||||
|
|
||||||
def pre_live_migration(self, context, instance_ref, block_device_info,
|
def pre_live_migration(self, context, instance_ref, block_device_info,
|
||||||
network_info, migrate_data=None):
|
network_info, data, migrate_data=None):
|
||||||
"""Preparation live migration.
|
"""Preparation live migration.
|
||||||
|
|
||||||
:params block_device_info:
|
:params block_device_info:
|
||||||
|
Loading…
Reference in New Issue
Block a user