From d2f89951039e99c7ab4aa11bea5464004265c76b Mon Sep 17 00:00:00 2001 From: Adam Spiers Date: Tue, 19 Mar 2019 00:53:02 +0000 Subject: [PATCH] Move libvirt calculation of machine type to utils.py The libvirt driver contains some code to calculate the default machine type given an architecture, by looking it up in CONF.libvirt.hw_machine_type. This code will need to be reused when introducing calls to libvirt's getDomainCapabilities() API, which requires the machine type as one of the parameters. However those calls will need to be made from nova.virt.libvirt.host.Host which has no access to the driver, so move the machine type calculation code into nova.virt.libvirt.utils so that it can be reused by both classes. Also add some unit tests, and warn when an invalid config value is used. blueprint: amd-sev-libvirt-support Change-Id: I055918ff16766c5b106d794a111ad8af8ff9ab23 --- .../unit/virt/libvirt/fake_libvirt_utils.py | 4 +++ nova/tests/unit/virt/libvirt/test_utils.py | 27 +++++++++++++++++++ nova/virt/libvirt/driver.py | 14 +++------- nova/virt/libvirt/utils.py | 15 +++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/fake_libvirt_utils.py b/nova/tests/unit/virt/libvirt/fake_libvirt_utils.py index 3e1ea8083f7b..7dbc14c2d144 100644 --- a/nova/tests/unit/virt/libvirt/fake_libvirt_utils.py +++ b/nova/tests/unit/virt/libvirt/fake_libvirt_utils.py @@ -179,6 +179,10 @@ def cpu_features_to_traits(features): return libvirt_utils.cpu_features_to_traits(features) +def get_default_machine_type(arch): + return libvirt_utils.get_default_machine_type(arch) + + def mdev_name2uuid(mdev_name): return libvirt_utils.mdev_name2uuid(mdev_name) diff --git a/nova/tests/unit/virt/libvirt/test_utils.py b/nova/tests/unit/virt/libvirt/test_utils.py index 8aeb4af2e074..674b66f0cbc1 100644 --- a/nova/tests/unit/virt/libvirt/test_utils.py +++ b/nova/tests/unit/virt/libvirt/test_utils.py @@ -32,6 +32,7 @@ from nova import objects from nova.objects import fields as obj_fields import nova.privsep.fs from nova import test +from nova.tests import fixtures as nova_fixtures from nova.tests.unit import fake_instance from nova.tests.unit.virt.libvirt import fakelibvirt from nova.virt.disk import api as disk @@ -969,3 +970,29 @@ sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime 0 0 disk_path, format = libvirt_utils.find_disk(guest) self.assertEqual('/test/disk', disk_path) self.assertEqual('ploop', format) + + def test_machine_type_mappings(self): + self.useFixture(nova_fixtures.ConfPatcher( + group="libvirt", hw_machine_type=['x86_64=q35', 'i686=legacy'])) + self.assertDictEqual({'x86_64': 'q35', 'i686': 'legacy'}, + libvirt_utils.machine_type_mappings()) + + def test_invalid_machine_type_mappings(self): + self.useFixture(nova_fixtures.ConfPatcher( + group="libvirt", hw_machine_type=['x86_64=q35', 'foo'])) + self.assertDictEqual({'x86_64': 'q35'}, + libvirt_utils.machine_type_mappings()) + + def test_get_default_machine_type(self): + self.useFixture(nova_fixtures.ConfPatcher( + group="libvirt", hw_machine_type=['x86_64=q35', 'i686=legacy'])) + self.assertEqual('q35', + libvirt_utils.get_default_machine_type('x86_64')) + + def test_get_default_machine_type_empty(self): + self.assertIsNone(libvirt_utils.get_default_machine_type('sparc')) + + def test_get_default_machine_type_missing(self): + self.useFixture(nova_fixtures.ConfPatcher( + group="libvirt", hw_machine_type=['x86_64=q35', 'i686=legacy'])) + self.assertIsNone(libvirt_utils.get_default_machine_type('sparc')) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index a23b56362427..608ac874296c 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -4227,13 +4227,6 @@ class LibvirtDriver(driver.ComputeDriver): return meta - def _machine_type_mappings(self): - mappings = {} - for mapping in CONF.libvirt.hw_machine_type: - host_arch, _, machine_type = mapping.partition('=') - mappings[host_arch] = machine_type - return mappings - def _get_machine_type(self, image_meta, caps): # The guest machine type can be set as an image metadata # property, or otherwise based on architecture-specific @@ -4257,9 +4250,10 @@ class LibvirtDriver(driver.ComputeDriver): mach_type = 's390-ccw-virtio' # If set in the config, use that as the default. - if CONF.libvirt.hw_machine_type: - mappings = self._machine_type_mappings() - mach_type = mappings.get(caps.host.cpu.arch) + mach_type = ( + libvirt_utils.get_default_machine_type(caps.host.cpu.arch) + or mach_type + ) return mach_type diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py index 59bb982caee6..10759f136a7f 100644 --- a/nova/virt/libvirt/utils.py +++ b/nova/virt/libvirt/utils.py @@ -541,6 +541,21 @@ def get_cpu_model_from_arch(arch): return mode +def machine_type_mappings(): + mappings = {} + for mapping in CONF.libvirt.hw_machine_type or {}: + host_arch, _, machine_type = mapping.partition('=') + if machine_type == '': + LOG.warning("Invalid hw_machine_type config value %s", mapping) + else: + mappings[host_arch] = machine_type + return mappings + + +def get_default_machine_type(arch): + return machine_type_mappings().get(arch) + + def mdev_name2uuid(mdev_name): """Convert an mdev name (of the form mdev_) to a uuid (of the form 8-4-4-4-12).