From 07e4a90cfea56a9513d476769190d488e33ac8b0 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 25 Apr 2016 19:48:29 +0100 Subject: [PATCH] libvirt: add explicit check for min required QEMU version Previously Nova only checked the minimum required libvirt version. It should also be checking for a minimum required QEMU version. This picks QEMU version 1.5.3, since that is the oldest QEMU version that exists in the distros that include the minimum libvirt version 1.2.1. No decision is made about a "next" QEMU version at this time. Change-Id: Ie9413338a2422cc876f48c5c477eb3cd0ffb13ec --- nova/tests/unit/virt/libvirt/fakelibvirt.py | 4 +- nova/tests/unit/virt/libvirt/test_driver.py | 59 ++++++++++++++++++- nova/virt/libvirt/driver.py | 16 +++++ .../min-required-qemu-c987a8a5c6c4fee0.yaml | 4 ++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/min-required-qemu-c987a8a5c6c4fee0.yaml diff --git a/nova/tests/unit/virt/libvirt/fakelibvirt.py b/nova/tests/unit/virt/libvirt/fakelibvirt.py index 502179129b81..8761e69c1716 100644 --- a/nova/tests/unit/virt/libvirt/fakelibvirt.py +++ b/nova/tests/unit/virt/libvirt/fakelibvirt.py @@ -152,6 +152,8 @@ VIR_SECRET_USAGE_TYPE_ISCSI = 3 # Libvirt version to match MIN_LIBVIRT_VERSION in driver.py FAKE_LIBVIRT_VERSION = 1002001 +# Libvirt version to match MIN_QEMU_VERSION in driver.py +FAKE_QEMU_VERSION = 1005003 class HostInfo(object): @@ -799,7 +801,7 @@ class DomainSnapshot(object): class Connection(object): def __init__(self, uri=None, readonly=False, version=FAKE_LIBVIRT_VERSION, - hv_version=1001000, host_info=None): + hv_version=FAKE_QEMU_VERSION, host_info=None): if not uri or uri == '': if allow_default_uri_connection: uri = 'qemu:///session' diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index b57924ecd815..e3835759cd1e 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -767,6 +767,34 @@ class LibvirtConnTestCase(test.NoDBTestCase): break self.assertTrue(version_arg_found) + @mock.patch.object(fakelibvirt.Connection, 'getVersion', + return_value=versionutils.convert_version_to_int( + libvirt_driver.NEXT_MIN_QEMU_VERSION) - 1) + @mock.patch.object(libvirt_driver.LOG, 'warning') + def test_next_min_qemu_version_deprecation_warning(self, mock_warning, + mock_get_libversion): + # Skip test if there's no currently planned new min version + if (versionutils.convert_version_to_int( + libvirt_driver.NEXT_MIN_QEMU_VERSION) == + versionutils.convert_version_to_int( + libvirt_driver.MIN_QEMU_VERSION)): + self.skipTest("NEXT_MIN_QEMU_VERSION == MIN_QEMU_VERSION") + + # Test that a warning is logged if the libvirt version is less than + # the next required minimum version. + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + drvr.init_host("dummyhost") + # assert that the next min version is in a warning message + expected_arg = {'version': versionutils.convert_version_to_str( + versionutils.convert_version_to_int( + libvirt_driver.NEXT_MIN_QEMU_VERSION))} + version_arg_found = False + for call in mock_warning.call_args_list: + if call[0][1] == expected_arg: + version_arg_found = True + break + self.assertTrue(version_arg_found) + @mock.patch.object(fakelibvirt.Connection, 'getLibVersion', return_value=versionutils.convert_version_to_int( libvirt_driver.NEXT_MIN_LIBVIRT_VERSION)) @@ -795,6 +823,34 @@ class LibvirtConnTestCase(test.NoDBTestCase): break self.assertFalse(version_arg_found) + @mock.patch.object(fakelibvirt.Connection, 'getVersion', + return_value=versionutils.convert_version_to_int( + libvirt_driver.NEXT_MIN_QEMU_VERSION)) + @mock.patch.object(libvirt_driver.LOG, 'warning') + def test_next_min_qemu_version_ok(self, mock_warning, mock_get_libversion): + # Skip test if there's no currently planned new min version + + if (versionutils.convert_version_to_int( + libvirt_driver.NEXT_MIN_QEMU_VERSION) == + versionutils.convert_version_to_int( + libvirt_driver.MIN_QEMU_VERSION)): + self.skipTest("NEXT_MIN_QEMU_VERSION == MIN_QEMU_VERSION") + + # Test that a warning is not logged if the libvirt version is greater + # than or equal to NEXT_MIN_QEMU_VERSION. + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + drvr.init_host("dummyhost") + # assert that the next min version is in a warning message + expected_arg = {'version': versionutils.convert_version_to_str( + versionutils.convert_version_to_int( + libvirt_driver.NEXT_MIN_QEMU_VERSION))} + version_arg_found = False + for call in mock_warning.call_args_list: + if call[0][1] == expected_arg: + version_arg_found = True + break + self.assertFalse(version_arg_found) + @mock.patch.object(fakelibvirt.Connection, 'getLibVersion', return_value=versionutils.convert_version_to_int( libvirt_driver.MIN_LIBVIRT_OTHER_ARCH.get( @@ -13737,7 +13793,8 @@ class HostStateTestCase(test.NoDBTestCase): self.assertEqual(stats["memory_mb_used"], 88) self.assertEqual(stats["local_gb_used"], 20) self.assertEqual(stats["hypervisor_type"], 'QEMU') - self.assertEqual(stats["hypervisor_version"], 1001000) + self.assertEqual(stats["hypervisor_version"], + fakelibvirt.FAKE_QEMU_VERSION) self.assertEqual(stats["hypervisor_hostname"], 'compute1') cpu_info = jsonutils.loads(stats["cpu_info"]) self.assertEqual(cpu_info, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 4165598d2301..8eafd9b19863 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -395,12 +395,14 @@ patch_tpool_proxy() # for all architectures/hypervisors, as this value rises to # meet them. MIN_LIBVIRT_VERSION = (1, 2, 1) +MIN_QEMU_VERSION = (1, 5, 3) # 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 = (1, 2, 1) +NEXT_MIN_QEMU_VERSION = (1, 5, 3) # When the above version matches/exceeds this version # delete it & corresponding code using it @@ -663,6 +665,12 @@ class LibvirtDriver(driver.ComputeDriver): _('Nova requires libvirt version %s or greater.') % self._version_to_string(MIN_LIBVIRT_VERSION)) + if (CONF.libvirt.virt_type in ("qemu", "kvm") and + not self._host.has_min_version(hv_ver=MIN_QEMU_VERSION)): + raise exception.NovaException( + _('Nova requires QEMU version %s or greater.') % + self._version_to_string(MIN_QEMU_VERSION)) + if (CONF.libvirt.virt_type == 'parallels' and not self._host.has_min_version(MIN_LIBVIRT_PARALLELS_VERSION)): raise exception.NovaException( @@ -679,6 +687,14 @@ class LibvirtDriver(driver.ComputeDriver): 'in the next release.'), {'version': self._version_to_string( NEXT_MIN_LIBVIRT_VERSION)}) + if (CONF.libvirt.virt_type in ("qemu", "kvm") and + not self._host.has_min_version(NEXT_MIN_QEMU_VERSION)): + LOG.warning(_LW('Running Nova with a QEMU version less than ' + '%(version)s is deprecated. The required minimum ' + 'version of QEMU will be raised to %(version)s ' + 'in the next release.'), + {'version': self._version_to_string( + NEXT_MIN_QEMU_VERSION)}) kvm_arch = arch.from_host() if (CONF.libvirt.virt_type in ('kvm', 'qemu') and diff --git a/releasenotes/notes/min-required-qemu-c987a8a5c6c4fee0.yaml b/releasenotes/notes/min-required-qemu-c987a8a5c6c4fee0.yaml new file mode 100644 index 000000000000..91b21170e17b --- /dev/null +++ b/releasenotes/notes/min-required-qemu-c987a8a5c6c4fee0.yaml @@ -0,0 +1,4 @@ +--- +upgrade: + - The minimum required QEMU version is now checked and + has been set to 1.5.3