Merge "libvirt: Bump MIN_{LIBVIRT,QEMU}_VERSION and NEXT_MIN_{LIBVIRT,QEMU}_VERSION"
This commit is contained in:
@@ -19,7 +19,6 @@ from castellan.common.objects import passphrase
|
||||
from castellan.key_manager import key_manager
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
from oslo_utils import versionutils
|
||||
|
||||
import nova.conf
|
||||
from nova import context as nova_context
|
||||
@@ -28,7 +27,6 @@ from nova import exception
|
||||
from nova import objects
|
||||
from nova.tests.functional.api import client
|
||||
from nova.tests.functional.libvirt import base
|
||||
from nova.virt.libvirt import driver
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
@@ -137,10 +135,7 @@ class VTPMServersTest(base.ServersTestBase):
|
||||
|
||||
# TODO(stephenfin): This should be moved to the base class
|
||||
def start_compute(self, hostname='compute1'):
|
||||
libvirt_version = versionutils.convert_version_to_int(
|
||||
driver.MIN_LIBVIRT_VTPM)
|
||||
fake_connection = self._get_connection(
|
||||
libvirt_version=libvirt_version, hostname=hostname)
|
||||
fake_connection = self._get_connection(hostname=hostname)
|
||||
|
||||
# This is fun. Firstly we need to do a global'ish mock so we can
|
||||
# actually start the service.
|
||||
|
||||
@@ -61,6 +61,10 @@ VIR_DOMAIN_XML_INACTIVE = 2
|
||||
VIR_DOMAIN_XML_UPDATE_CPU = 4
|
||||
VIR_DOMAIN_XML_MIGRATABLE = 8
|
||||
|
||||
VIR_DOMAIN_BLOCK_COPY_SHALLOW = 1
|
||||
VIR_DOMAIN_BLOCK_COPY_REUSE_EXT = 2
|
||||
VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB = 4
|
||||
|
||||
VIR_DOMAIN_BLOCK_REBASE_SHALLOW = 1
|
||||
VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT = 2
|
||||
VIR_DOMAIN_BLOCK_REBASE_COPY = 8
|
||||
@@ -1347,6 +1351,9 @@ class Domain(object):
|
||||
error_domain=VIR_FROM_QEMU)
|
||||
return 0
|
||||
|
||||
def blockCopy(self, disk, base, flags=0):
|
||||
return 0
|
||||
|
||||
def blockCommit(self, disk, base, top, flags):
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1625,18 +1625,16 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
)
|
||||
mock_getgrnam.assert_called_with('admins')
|
||||
|
||||
@mock.patch.object(host.Host, 'has_min_version')
|
||||
@mock.patch('shutil.which')
|
||||
@mock.patch('pwd.getpwnam')
|
||||
@mock.patch('grp.getgrnam')
|
||||
def test__check_vtpm_support(
|
||||
self, mock_getgrnam, mock_getpwnam, mock_which, mock_version,
|
||||
self, mock_getgrnam, mock_getpwnam, mock_which
|
||||
):
|
||||
"""Test checking for vTPM support when everything is configured
|
||||
correctly.
|
||||
"""
|
||||
self.flags(swtpm_enabled=True, virt_type='kvm', group='libvirt')
|
||||
mock_version.return_value = True
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
drvr.init_host('dummyhost')
|
||||
@@ -1644,7 +1642,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
mock_which.assert_has_calls(
|
||||
[mock.call('swtpm_setup'), mock.call().__bool__()],
|
||||
)
|
||||
mock_version.assert_called_with(lv_ver=(5, 6, 0))
|
||||
|
||||
@mock.patch.object(libvirt_driver.LOG, 'warning')
|
||||
def test_check_cpu_set_configuration__no_configuration(self, mock_log):
|
||||
@@ -10811,26 +10808,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
ret = conn._compare_cpu(None, None, instance)
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_compare_cpu_virt_platform_s390x(self):
|
||||
_fake_s390xcpu_info = {
|
||||
"arch": "s390x",
|
||||
"model": "test_model",
|
||||
"vendor": "test_vendor",
|
||||
"topology": {
|
||||
"sockets": 1,
|
||||
"cores": 8,
|
||||
"threads": 16
|
||||
},
|
||||
"features": ["feature1", "feature2"]
|
||||
}
|
||||
|
||||
instance = objects.Instance(**self.test_instance)
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
ret = conn._compare_cpu(None,
|
||||
jsonutils.dumps(_fake_s390xcpu_info),
|
||||
instance)
|
||||
self.assertIsNone(ret)
|
||||
|
||||
@mock.patch.object(host.Host, 'compare_cpu')
|
||||
@mock.patch.object(nova.virt.libvirt, 'config')
|
||||
def test_compare_cpu_invalid_cpuinfo_raises(self, mock_vconfig,
|
||||
@@ -19432,11 +19409,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
self.assertRaises(NotImplementedError, drvr.swap_volume, self.context,
|
||||
{}, {}, None, None, None)
|
||||
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
@mock.patch('nova.virt.libvirt.host.Host.write_instance_config')
|
||||
def test_swap_volume_copy(self, mock_write_instance_config,
|
||||
mock_libvirt_ver, mock_qemu_ver):
|
||||
def test_swap_volume_copy(self, mock_write_instance_config):
|
||||
"""Assert the happy path of calling virDomainBlockCopy to swap"""
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI())
|
||||
|
||||
@@ -19448,10 +19422,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
target_dev=mock.sentinel.target_dev,
|
||||
source_path=None)
|
||||
|
||||
mock_libvirt_ver.return_value = versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_BLOCKDEV)
|
||||
mock_qemu_ver.return_value = versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_BLOCKDEV)
|
||||
mock_dev.is_job_complete.return_value = True
|
||||
mock_guest.get_block_device.return_value = mock_dev
|
||||
mock_guest.get_xml_desc.side_effect = [
|
||||
@@ -19480,11 +19450,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
mock_write_instance_config.assert_called_once_with(
|
||||
mock.sentinel.new_xml_desc)
|
||||
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
@mock.patch('nova.virt.libvirt.host.Host.write_instance_config')
|
||||
def test_swap_volume_copy_failure(self, mock_write_instance_config,
|
||||
mock_libvirt_ver, mock_qemu_ver):
|
||||
def test_swap_volume_copy_failure(self, mock_write_instance_config):
|
||||
"""Assert that exception.VolumeRebaseFailed is raised on failure"""
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI())
|
||||
|
||||
@@ -19496,10 +19463,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
target_dev=mock.sentinel.target_dev,
|
||||
source_path=None)
|
||||
|
||||
mock_libvirt_ver.return_value = versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_BLOCKDEV)
|
||||
mock_qemu_ver.return_value = versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_BLOCKDEV)
|
||||
mock_dev.copy.side_effect = test.TestingException()
|
||||
mock_guest.get_block_device.return_value = mock_dev
|
||||
mock_guest.get_xml_desc.side_effect = [
|
||||
@@ -19520,105 +19483,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
mock_write_instance_config.assert_called_once_with(
|
||||
mock.sentinel.original_xml_desc)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.guest.BlockDevice.is_job_complete',
|
||||
return_value=True)
|
||||
def _test_swap_volume_rebase(self, mock_is_job_complete, source_type,
|
||||
resize=False, fail=False):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI())
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
hw_firmware_type = image_meta.properties.get(
|
||||
'hw_firmware_type')
|
||||
|
||||
mock_dom = mock.MagicMock()
|
||||
guest = libvirt_guest.Guest(mock_dom)
|
||||
|
||||
with mock.patch.object(drvr._conn, 'defineXML',
|
||||
create=True) as mock_define:
|
||||
srcfile = "/first/path"
|
||||
dstfile = "/second/path"
|
||||
orig_xml = str(mock.sentinel.orig_xml)
|
||||
new_xml = str(mock.sentinel.new_xml)
|
||||
|
||||
mock_dom.XMLDesc.return_value = orig_xml
|
||||
mock_dom.isPersistent.return_value = True
|
||||
|
||||
def fake_rebase_success(*args, **kwargs):
|
||||
# Make sure the XML is set after the rebase so we know
|
||||
# get_xml_desc was called after the update.
|
||||
mock_dom.XMLDesc.return_value = new_xml
|
||||
|
||||
if not fail:
|
||||
mock_dom.blockRebase.side_effect = fake_rebase_success
|
||||
# If the swap succeeds, make sure we use the new XML to
|
||||
# redefine the domain.
|
||||
expected_xml = new_xml
|
||||
else:
|
||||
if resize:
|
||||
mock_dom.blockResize.side_effect = test.TestingException()
|
||||
expected_exception = test.TestingException
|
||||
else:
|
||||
mock_dom.blockRebase.side_effect = test.TestingException()
|
||||
expected_exception = exception.VolumeRebaseFailed
|
||||
# If the swap fails, make sure we use the original domain XML
|
||||
# to redefine the domain.
|
||||
expected_xml = orig_xml
|
||||
|
||||
# Run the swap volume code.
|
||||
mock_conf = mock.MagicMock(source_type=source_type,
|
||||
source_path=dstfile)
|
||||
if not fail:
|
||||
drvr._swap_volume(guest, srcfile, mock_conf, 1,
|
||||
hw_firmware_type)
|
||||
else:
|
||||
self.assertRaises(expected_exception, drvr._swap_volume, guest,
|
||||
srcfile, mock_conf, 1, hw_firmware_type)
|
||||
|
||||
# Verify we read the original persistent config.
|
||||
expected_call_count = 1
|
||||
expected_calls = [mock.call(
|
||||
flags=(fakelibvirt.VIR_DOMAIN_XML_INACTIVE |
|
||||
fakelibvirt.VIR_DOMAIN_XML_SECURE))]
|
||||
if not fail:
|
||||
# Verify we read the updated live config.
|
||||
expected_call_count = 2
|
||||
expected_calls.append(
|
||||
mock.call(flags=fakelibvirt.VIR_DOMAIN_XML_SECURE))
|
||||
self.assertEqual(expected_call_count, mock_dom.XMLDesc.call_count)
|
||||
mock_dom.XMLDesc.assert_has_calls(expected_calls)
|
||||
|
||||
# Verify we called with the correct flags.
|
||||
expected_flags = (fakelibvirt.VIR_DOMAIN_BLOCK_REBASE_COPY |
|
||||
fakelibvirt.VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)
|
||||
if source_type == 'block':
|
||||
expected_flags = (expected_flags |
|
||||
fakelibvirt.VIR_DOMAIN_BLOCK_REBASE_COPY_DEV)
|
||||
mock_dom.blockRebase.assert_called_once_with(srcfile, dstfile, 0,
|
||||
flags=expected_flags)
|
||||
|
||||
# Verify we defined the expected XML.
|
||||
mock_define.assert_called_once_with(expected_xml)
|
||||
|
||||
# Verify we called resize with the correct args.
|
||||
if resize:
|
||||
mock_dom.blockResize.assert_called_once_with(
|
||||
srcfile, 1 * units.Gi, flags=1)
|
||||
|
||||
def test_swap_volume_rebase_file(self):
|
||||
self._test_swap_volume_rebase('file')
|
||||
|
||||
def test_swap_volume_rebase_block(self):
|
||||
"""If the swapped volume is type="block", make sure that we give
|
||||
libvirt the correct VIR_DOMAIN_BLOCK_REBASE_COPY_DEV flag to ensure the
|
||||
correct type="block" XML is generated (bug 1691195)
|
||||
"""
|
||||
self._test_swap_volume_rebase('block')
|
||||
|
||||
def test_swap_volume_rebase_fail(self):
|
||||
self._test_swap_volume_rebase('block', fail=True)
|
||||
|
||||
def test_swap_volume_rebase_resize_fail(self):
|
||||
self._test_swap_volume_rebase('file', resize=True, fail=True)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._disconnect_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._swap_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_volume_config')
|
||||
@@ -19669,99 +19533,17 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
old_connection_info,
|
||||
instance)
|
||||
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._disconnect_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._swap_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_volume_config')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._connect_volume')
|
||||
@mock.patch('nova.virt.libvirt.host.Host.get_guest')
|
||||
def test_swap_volume_without_device_path_blocked(self, get_guest,
|
||||
connect_volume, get_volume_config, swap_volume, disconnect_volume):
|
||||
"""Assert that NotImplementedError is raised when swap_volume is called
|
||||
without a source_path prior to MIN_LIBVIRT_BLOCKDEV.
|
||||
"""
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI())
|
||||
instance = objects.Instance(**self.test_instance)
|
||||
old_connection_info = {'driver_volume_type': 'rbd',
|
||||
'serial': 'old-volume-id',
|
||||
'data': {'access_mode': 'rw'}}
|
||||
new_connection_info = {'driver_volume_type': 'rbd',
|
||||
'serial': 'new-volume-id',
|
||||
'data': {'access_mode': 'rw'}}
|
||||
|
||||
mock_guest = mock.MagicMock()
|
||||
mock_guest.get_disk.return_value = True
|
||||
get_guest.return_value = mock_guest
|
||||
get_volume_config.return_value = mock.MagicMock(source_path=None)
|
||||
|
||||
self.assertRaises(NotImplementedError, conn.swap_volume, self.context,
|
||||
old_connection_info, new_connection_info, instance,
|
||||
'/dev/vdb', 1)
|
||||
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._disconnect_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._swap_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_volume_config')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._connect_volume')
|
||||
@mock.patch('nova.virt.libvirt.host.Host.get_guest')
|
||||
def test_swap_volume_blockdev_without_device_path(self, get_guest,
|
||||
connect_volume, get_volume_config, swap_volume, disconnect_volume,
|
||||
lib_version, qemu_version):
|
||||
"""Assert that swap_volume correctly calls down to _swap_volume when
|
||||
source_path isn't provided after MIN_LIBVIRT_BLOCKDEV.
|
||||
"""
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI())
|
||||
lib_version.return_value = versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_BLOCKDEV)
|
||||
qemu_version.return_value = versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_BLOCKDEV)
|
||||
instance = objects.Instance(**self.test_instance)
|
||||
old_connection_info = {'driver_volume_type': 'rbd',
|
||||
'serial': 'old-volume-id',
|
||||
'data': {'access_mode': 'rw'}}
|
||||
new_connection_info = {'driver_volume_type': 'rbd',
|
||||
'serial': 'new-volume-id',
|
||||
'data': {'access_mode': 'rw'}}
|
||||
mock_dom = mock.MagicMock()
|
||||
guest = libvirt_guest.Guest(mock_dom)
|
||||
mock_dom.XMLDesc.return_value = """<domain>
|
||||
<devices>
|
||||
<disk type='file'>
|
||||
<source file='/fake-old-volume'/>
|
||||
<target dev='vdb' bus='virtio'/>
|
||||
</disk>
|
||||
</devices>
|
||||
</domain>
|
||||
"""
|
||||
mock_dom.name.return_value = 'inst'
|
||||
mock_dom.UUIDString.return_value = 'uuid'
|
||||
get_guest.return_value = guest
|
||||
conf = mock.MagicMock(source_path='/fake-new-volume')
|
||||
get_volume_config.return_value = conf
|
||||
|
||||
conn.swap_volume(self.context, old_connection_info,
|
||||
new_connection_info, instance, '/dev/vdb', 1)
|
||||
|
||||
get_guest.assert_called_once_with(instance)
|
||||
connect_volume.assert_called_once_with(self.context,
|
||||
new_connection_info, instance)
|
||||
|
||||
swap_volume.assert_called_once_with(guest, 'vdb', conf, 1, None)
|
||||
disconnect_volume.assert_called_once_with(self.context,
|
||||
old_connection_info,
|
||||
instance)
|
||||
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_encryption')
|
||||
@mock.patch('nova.virt.libvirt.guest.BlockDevice.rebase')
|
||||
@mock.patch('nova.virt.libvirt.guest.BlockDevice.copy')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._disconnect_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._connect_volume')
|
||||
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_volume_config')
|
||||
@mock.patch('nova.virt.libvirt.guest.Guest.get_disk')
|
||||
@mock.patch('nova.virt.libvirt.host.Host.get_guest')
|
||||
@mock.patch('nova.virt.libvirt.host.Host.write_instance_config')
|
||||
def test_swap_volume_disconnect_new_volume_on_rebase_error(self,
|
||||
def test_swap_volume_disconnect_new_volume_on_copy_error(self,
|
||||
write_config, get_guest, get_disk, get_volume_config,
|
||||
connect_volume, disconnect_volume, rebase, get_volume_encryption):
|
||||
connect_volume, disconnect_volume, copy, get_volume_encryption):
|
||||
"""Assert that disconnect_volume is called for the new volume if an
|
||||
error is encountered while rebasing
|
||||
"""
|
||||
@@ -19772,7 +19554,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
get_volume_encryption.return_value = {}
|
||||
exc = fakelibvirt.make_libvirtError(fakelibvirt.libvirtError,
|
||||
'internal error', error_code=fakelibvirt.VIR_ERR_INTERNAL_ERROR)
|
||||
rebase.side_effect = exc
|
||||
copy.side_effect = exc
|
||||
|
||||
self.assertRaises(exception.VolumeRebaseFailed, conn.swap_volume,
|
||||
self.context, mock.sentinel.old_connection_info,
|
||||
|
||||
@@ -101,7 +101,6 @@ import nova.privsep.utils
|
||||
from nova.storage import rbd_utils
|
||||
from nova import utils
|
||||
from nova import version
|
||||
from nova.virt import arch
|
||||
from nova.virt import block_device as driver_block_device
|
||||
from nova.virt import configdrive
|
||||
from nova.virt.disk import api as disk_api
|
||||
@@ -222,15 +221,15 @@ patch_tpool_proxy()
|
||||
# versions. Over time, this will become a common min version
|
||||
# for all architectures/hypervisors, as this value rises to
|
||||
# meet them.
|
||||
MIN_LIBVIRT_VERSION = (5, 0, 0)
|
||||
MIN_QEMU_VERSION = (4, 0, 0)
|
||||
MIN_LIBVIRT_VERSION = (6, 0, 0)
|
||||
MIN_QEMU_VERSION = (4, 2, 0)
|
||||
# TODO(berrange): Re-evaluate this at start of each release cycle
|
||||
# to decide if we want to plan a future min version bump.
|
||||
# MIN_LIBVIRT_VERSION can be updated to match this after
|
||||
# NEXT_MIN_LIBVIRT_VERSION has been at a higher value for
|
||||
# one cycle
|
||||
NEXT_MIN_LIBVIRT_VERSION = (6, 0, 0)
|
||||
NEXT_MIN_QEMU_VERSION = (4, 2, 0)
|
||||
NEXT_MIN_LIBVIRT_VERSION = (7, 0, 0)
|
||||
NEXT_MIN_QEMU_VERSION = (5, 2, 0)
|
||||
|
||||
# Virtuozzo driver support
|
||||
MIN_VIRTUOZZO_VERSION = (7, 0, 0)
|
||||
@@ -249,15 +248,6 @@ VGPU_RESOURCE_SEMAPHORE = 'vgpu_resources'
|
||||
|
||||
LIBVIRT_PERF_EVENT_PREFIX = 'VIR_PERF_PARAM_'
|
||||
|
||||
# -blockdev support (replacing -drive)
|
||||
MIN_LIBVIRT_BLOCKDEV = (6, 0, 0)
|
||||
MIN_QEMU_BLOCKDEV = (4, 2, 0)
|
||||
|
||||
# Virtual TPM (vTPM) support
|
||||
MIN_LIBVIRT_VTPM = (5, 6, 0)
|
||||
|
||||
MIN_LIBVIRT_S390X_CPU_COMPARE = (5, 9, 0)
|
||||
|
||||
|
||||
class LibvirtDriver(driver.ComputeDriver):
|
||||
def __init__(self, virtapi, read_only=False):
|
||||
@@ -728,14 +718,6 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
"'kvm'; found '%s'.")
|
||||
raise exception.InvalidConfiguration(msg % CONF.libvirt.virt_type)
|
||||
|
||||
if not self._host.has_min_version(lv_ver=MIN_LIBVIRT_VTPM):
|
||||
msg = _(
|
||||
'vTPM support requires Libvirt version %(libvirt)s or '
|
||||
'greater.')
|
||||
raise exception.InvalidConfiguration(msg % {
|
||||
'libvirt': libvirt_utils.version_to_string(MIN_LIBVIRT_VTPM),
|
||||
})
|
||||
|
||||
# These executables need to be installed for libvirt to make use of
|
||||
# emulated TPM.
|
||||
# NOTE(stephenfin): This checks using the PATH of the user running
|
||||
@@ -1918,23 +1900,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
guest.delete_configuration(support_uefi)
|
||||
|
||||
try:
|
||||
# NOTE(lyarwood): Use virDomainBlockCopy from libvirt >= 6.0.0
|
||||
# and QEMU >= 4.2.0 with -blockdev domains allowing QEMU to
|
||||
# copy to remote disks.
|
||||
if self._host.has_min_version(lv_ver=MIN_LIBVIRT_BLOCKDEV,
|
||||
hv_ver=MIN_QEMU_BLOCKDEV):
|
||||
dev.copy(conf.to_xml(), reuse_ext=True)
|
||||
else:
|
||||
# TODO(lyarwood): Remove the following use of
|
||||
# virDomainBlockRebase once MIN_LIBVIRT_VERSION hits >=
|
||||
# 6.0.0 and MIN_QEMU_VERSION hits >= 4.2.0.
|
||||
# Start copy with VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT flag to
|
||||
# allow writing to existing external volume file. Use
|
||||
# VIR_DOMAIN_BLOCK_REBASE_COPY_DEV if it's a block device
|
||||
# to make sure XML is generated correctly (bug 1691195)
|
||||
copy_dev = conf.source_type == 'block'
|
||||
dev.rebase(conf.source_path, copy=True, reuse_ext=True,
|
||||
copy_dev=copy_dev)
|
||||
dev.copy(conf.to_xml(), reuse_ext=True)
|
||||
|
||||
while not dev.is_job_complete():
|
||||
time.sleep(0.5)
|
||||
|
||||
@@ -1994,14 +1961,6 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
# eventually do this for us.
|
||||
self._connect_volume(context, new_connection_info, instance)
|
||||
conf = self._get_volume_config(new_connection_info, disk_info)
|
||||
if (not conf.source_path and not
|
||||
self._host.has_min_version(lv_ver=MIN_LIBVIRT_BLOCKDEV,
|
||||
hv_ver=MIN_QEMU_BLOCKDEV)):
|
||||
self._disconnect_volume(context, new_connection_info, instance)
|
||||
raise NotImplementedError(_("Swap only supports host devices and "
|
||||
"files with Libvirt < 6.0.0 or QEMU "
|
||||
"< 4.2.0"))
|
||||
|
||||
hw_firmware_type = instance.image_meta.properties.get(
|
||||
'hw_firmware_type')
|
||||
|
||||
@@ -8828,18 +8787,6 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
else:
|
||||
cpu = self._vcpu_model_to_cpu_config(guest_cpu)
|
||||
|
||||
# s390x doesn't support cpu model in host info, so compare
|
||||
# cpu info will raise an error anyway, thus have to avoid check
|
||||
# see bug 1854126 for more info
|
||||
if (
|
||||
cpu.arch in (arch.S390X, arch.S390) and
|
||||
not self._host.has_min_version(MIN_LIBVIRT_S390X_CPU_COMPARE)
|
||||
):
|
||||
LOG.debug("on s390x platform, the min libvirt version "
|
||||
"support cpu model compare is %s",
|
||||
MIN_LIBVIRT_S390X_CPU_COMPARE)
|
||||
return
|
||||
|
||||
u = ("http://libvirt.org/html/libvirt-libvirt-host.html#"
|
||||
"virCPUCompareResult")
|
||||
m = _("CPU doesn't have compatibility.\n\n%(ret)s\n\nRefer to %(u)s")
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The minimum required version of libvirt used by the `nova-compute` service
|
||||
is now 6.0.0. The next minimum required version to be used in a future
|
||||
release is 7.0.0.
|
||||
|
||||
The minimum required version of QEMU used by the `nova-compute` service is
|
||||
now 4.2.0. The next minimum required version to be used in a future release
|
||||
is 5.2.0.
|
||||
|
||||
Failing to meet these minimum versions when using the libvirt compute
|
||||
driver will result in the `nova-compute` service not starting.
|
||||
Reference in New Issue
Block a user