Merge "Fix cold migration with qcow2 ephemeral disks"

This commit is contained in:
Jenkins
2016-11-16 21:57:08 +00:00
committed by Gerrit Code Review
3 changed files with 109 additions and 12 deletions

View File

@@ -139,7 +139,7 @@ class ImageBackendFixture(fixtures.Fixture):
# Used directly by callers. These would have been set if called
# the real constructor.
setattr(disk, 'path', path)
setattr(disk, 'is_block_dev', False)
setattr(disk, 'is_block_dev', mock.sentinel.is_block_dev)
# Used by tests. Note that image_init is a closure over image_type.
setattr(disk, 'image_type', image_type)

View File

@@ -19,6 +19,7 @@ import contextlib
import copy
import datetime
import errno
import functools
import glob
import os
import random
@@ -10546,7 +10547,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
return gotFiles, imported_files
def test_create_image_with_swap(self):
def test_create_image_with_flavor_swap(self):
def enable_swap(instance_ref):
# Turn on some swap to exercise that codepath in _create_image
instance_ref['system_metadata']['instance_type_swap'] = 500
@@ -10577,6 +10578,52 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertTrue(imported_files[0][0].endswith('/disk.config'))
self.assertEqual('disk.config', imported_files[0][1])
def test_create_image_with_swap(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance_ref = self.test_instance
instance_ref['image_ref'] = ''
instance = objects.Instance(**instance_ref)
# Also check that bdm specified swap takes precedence over flavor
# specified swap
instance.flavor.swap = 200
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
bdi = {'swap': {'swap_size': 100,
'device_name': '/dev/vdb'},
'block_device_mapping': [{'boot_index': 0}]}
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance, image_meta,
block_device_info=bdi)
backend = self.useFixture(fake_imagebackend.ImageBackendFixture())
drvr._create_image(self.context, instance, disk_info['mapping'],
block_device_info=bdi)
backend.disks['disk.swap'].cache.assert_called_once_with(
fetch_func=drvr._create_swap, context=self.context,
filename='swap_100', size=100 * units.Mi, swap_mb=100)
def test_create_image_with_legacy_swap_resizing(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance_ref = self.test_instance
instance_ref['image_ref'] = ''
instance = objects.Instance(**instance_ref)
instance.flavor.swap = 200
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
bdi = {'swap': {'swap_size': 100,
'device_name': '/dev/vdb'},
'block_device_mapping': [{'boot_index': 0}]}
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance, image_meta,
block_device_info=bdi)
backend = self.useFixture(fake_imagebackend.ImageBackendFixture())
drvr._create_image(self.context, instance, disk_info['mapping'],
block_device_info=bdi, ignore_bdi_for_swap=True)
backend.disks['disk.swap'].cache.assert_called_once_with(
fetch_func=drvr._create_swap, context=self.context,
filename='swap_200', size=200 * units.Mi, swap_mb=200)
@mock.patch.object(nova.virt.libvirt.imagebackend.Image, 'cache',
side_effect=exception.ImageNotFound(image_id='fake-id'))
def test_create_image_not_exist_no_fallback(self, mock_cache):
@@ -10620,6 +10667,37 @@ class LibvirtConnTestCase(test.NoDBTestCase):
host='fake-source-host',
receive=True)
@mock.patch('nova.virt.disk.api.get_file_extension_for_os_type')
def test_create_image_with_ephemerals(self, mock_get_ext):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance_ref = self.test_instance
instance_ref['image_ref'] = ''
instance = objects.Instance(**instance_ref)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
bdi = {'ephemerals': [{'size': 100}],
'block_device_mapping': [{'boot_index': 0}]}
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance, image_meta,
block_device_info=bdi)
mock_get_ext.return_value = mock.sentinel.file_ext
backend = self.useFixture(fake_imagebackend.ImageBackendFixture())
drvr._create_image(self.context, instance, disk_info['mapping'],
block_device_info=bdi)
backend.disks['disk.eph0'].cache.assert_called_once_with(
fetch_func=mock.ANY, context=self.context,
filename=('ephemeral_100_%s' % mock.sentinel.file_ext),
size=100 * units.Gi, ephemeral_size=100, specified_fs=None)
fetch_func = (backend.disks['disk.eph0'].cache.
mock_calls[0][2]['fetch_func'])
self.assertIsInstance(fetch_func, functools.partial)
self.assertEqual(drvr._create_ephemeral, fetch_func.func)
self.assertEqual(
dict(fs_label='ephemeral0', os_type=instance.os_type,
is_block_dev=mock.sentinel.is_block_dev),
fetch_func.keywords)
@mock.patch.object(nova.virt.libvirt.imagebackend.Image, 'cache')
def test_create_image_resize_snap_backend(self, mock_cache):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@@ -15672,6 +15750,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
self.fake_create_domain_called = False
self.fake_disk_resize_called = False
create_image_called = [False]
bdi = {'block_device_mapping': []}
def fake_to_xml(context, instance, network_info, disk_info,
image_meta=None, rescue=None,
@@ -15685,8 +15764,11 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
disk_mapping, suffix='',
disk_images=None, network_info=None,
block_device_info=None, inject_files=True,
fallback_from_host=None):
fallback_from_host=None,
ignore_bdi_for_swap=False):
self.assertTrue(ignore_bdi_for_swap)
self.assertFalse(inject_files)
self.assertEqual(bdi, block_device_info)
create_image_called[0] = True
def fake_create_domain_and_network(
@@ -15754,7 +15836,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
self.drvr.finish_migration(
context.get_admin_context(), migration, instance,
disk_info, [], image_meta,
resize_instance, None, power_on)
resize_instance, bdi, power_on)
mock_ensure_console_log.assert_called_once_with(instance)

View File

@@ -2984,7 +2984,8 @@ class LibvirtDriver(driver.ComputeDriver):
disk_images=None, network_info=None,
block_device_info=None, files=None,
admin_pass=None, inject_files=True,
fallback_from_host=None):
fallback_from_host=None,
ignore_bdi_for_swap=False):
booted_from_volume = self._is_booted_from_volume(
instance, disk_mapping)
@@ -3076,13 +3077,26 @@ class LibvirtDriver(driver.ComputeDriver):
mapping = disk_mapping['disk.swap']
swap_mb = 0
swap = driver.block_device_info_get_swap(block_device_info)
if driver.swap_is_usable(swap):
swap_mb = swap['swap_size']
elif (inst_type['swap'] > 0 and
not block_device.volume_in_mapping(
mapping['dev'], block_device_info)):
if ignore_bdi_for_swap:
# This is a workaround to support legacy swap resizing,
# which does not touch swap size specified in bdm,
# but works with flavor specified size only.
# In this case we follow the legacy logic and ignore block
# device info completely.
# NOTE(ft): This workaround must be removed when a correct
# implementation of resize operation changing sizes in bdms is
# developed. Also at that stage we probably may get rid of
# the direct usage of flavor swap size here,
# leaving the work with bdm only.
swap_mb = inst_type['swap']
else:
swap = driver.block_device_info_get_swap(block_device_info)
if driver.swap_is_usable(swap):
swap_mb = swap['swap_size']
elif (inst_type['swap'] > 0 and
not block_device.volume_in_mapping(
mapping['dev'], block_device_info)):
swap_mb = inst_type['swap']
if swap_mb > 0:
size = swap_mb * units.Mi
@@ -7277,7 +7291,8 @@ class LibvirtDriver(driver.ComputeDriver):
# backing file.
self._create_image(context, instance, block_disk_info['mapping'],
network_info=network_info,
block_device_info=None, inject_files=False,
block_device_info=block_device_info,
inject_files=False, ignore_bdi_for_swap=True,
fallback_from_host=migration.source_compute)
# Required by Quobyte CI