From dc0556443541d2825cb507a70161128aaaf0a559 Mon Sep 17 00:00:00 2001 From: Rico Lin Date: Fri, 3 Jun 2022 01:16:07 +0800 Subject: [PATCH] Add traits for viommu model * Add iommu model trait for viommu model * Add ``hw_viommu_model`` to request_filter, this will extend the transform_image_metadata prefilter to select host with the correct model. * Provide new compute ``COMPUTE_VIOMMU_MODEL_*`` capablity trait for each model it supports in driver. Implements: blueprint libvirt-viommu-device Depends-On: https://review.opendev.org/c/openstack/os-traits/+/844336 Change-Id: I2caa1a9c473a2b11c287061280b4a78edb96f859 --- nova/scheduler/request_filter.py | 1 + nova/tests/unit/virt/libvirt/test_config.py | 3 ++- nova/tests/unit/virt/libvirt/test_driver.py | 20 +++++++++++++---- nova/virt/libvirt/driver.py | 25 +++++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/nova/scheduler/request_filter.py b/nova/scheduler/request_filter.py index 2a701facb5a1..bf5c32f37201 100644 --- a/nova/scheduler/request_filter.py +++ b/nova/scheduler/request_filter.py @@ -214,6 +214,7 @@ def transform_image_metadata(ctxt, request_spec): 'hw_vif_model': 'COMPUTE_NET_VIF_MODEL', 'hw_architecture': 'HW_ARCH', 'hw_emulation_architecture': 'COMPUTE_ARCH', + 'hw_viommu_model': 'COMPUTE_VIOMMU', } trait_names = [] diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py index 6cc67fba54b0..c4c9359dd838 100644 --- a/nova/tests/unit/virt/libvirt/test_config.py +++ b/nova/tests/unit/virt/libvirt/test_config.py @@ -4156,7 +4156,8 @@ class LibvirtConfigDomainCapsDevicesTests(LibvirtConfigBaseTest): obj.parse_str(xml) # we only use the video and disk devices today. device_types = [config.LibvirtConfigDomainCapsDiskBuses, - config.LibvirtConfigDomainCapsVideoModels] + config.LibvirtConfigDomainCapsVideoModels, + ] # so we assert there are only two device types parsed self.assertEqual(2, len(obj.devices)) # we then assert that the parsed devices are of the correct type diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 1b349205ccab..bbd4a9a20fac 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -961,9 +961,10 @@ class LibvirtConnTestCase(test.NoDBTestCase, @mock.patch.object(libvirt_driver.LibvirtDriver, '_get_storage_bus_traits') @mock.patch.object(libvirt_driver.LibvirtDriver, '_get_video_model_traits') @mock.patch.object(libvirt_driver.LibvirtDriver, '_get_vif_model_traits') + @mock.patch.object(host.Host, "has_min_version") def test_static_traits( - self, mock_vif_traits, mock_video_traits, mock_storage_traits, - mock_cpu_traits, + self, mock_version, mock_vif_traits, mock_video_traits, + mock_storage_traits, mock_cpu_traits, ): """Ensure driver capabilities are correctly retrieved and cached.""" @@ -974,14 +975,21 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_video_traits.return_value = {'COMPUTE_GRAPHICS_MODEL_VGA': True} mock_vif_traits.return_value = {'COMPUTE_NET_VIF_MODEL_VIRTIO': True} + # for support COMPUTE_VIOMMU_MODEL_VIRTIO + mock_version.return_value = True + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) expected = { - 'HW_CPU_HYPERTHREADING': True, - 'COMPUTE_STORAGE_BUS_VIRTIO': True, 'COMPUTE_GRAPHICS_MODEL_VGA': True, 'COMPUTE_NET_VIF_MODEL_VIRTIO': True, 'COMPUTE_SECURITY_TPM_1_2': False, 'COMPUTE_SECURITY_TPM_2_0': False, + 'COMPUTE_STORAGE_BUS_VIRTIO': True, + 'COMPUTE_VIOMMU_MODEL_AUTO': True, + 'COMPUTE_VIOMMU_MODEL_INTEL': True, + 'COMPUTE_VIOMMU_MODEL_SMMUV3': True, + 'COMPUTE_VIOMMU_MODEL_VIRTIO': True, + 'HW_CPU_HYPERTHREADING': True } static_traits = drvr.static_traits @@ -1027,6 +1035,10 @@ class LibvirtConnTestCase(test.NoDBTestCase, 'COMPUTE_NET_VIF_MODEL_VIRTIO': True, 'COMPUTE_SECURITY_TPM_1_2': False, 'COMPUTE_SECURITY_TPM_2_0': False, + 'COMPUTE_VIOMMU_MODEL_AUTO': True, + 'COMPUTE_VIOMMU_MODEL_INTEL': True, + 'COMPUTE_VIOMMU_MODEL_SMMUV3': True, + 'COMPUTE_VIOMMU_MODEL_VIRTIO': False } static_traits = drvr.static_traits diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index cf3c4464e8b3..252d7d027bdb 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -8922,6 +8922,7 @@ class LibvirtDriver(driver.ComputeDriver): traits.update(self._get_storage_bus_traits()) traits.update(self._get_video_model_traits()) traits.update(self._get_vif_model_traits()) + traits.update(self._get_iommu_model_traits()) traits.update(self._get_tpm_traits()) _, invalid_traits = ot.check_traits(traits) @@ -12198,6 +12199,30 @@ class LibvirtDriver(driver.ComputeDriver): in supported_models for model in all_models } + def _get_iommu_model_traits(self) -> ty.Dict[str, bool]: + """Get iommu model traits based on the currently enabled virt_type. + Not all traits generated by this function may be valid and the result + should be validated. + :return: A dict of trait names mapped to boolean values. + """ + dom_caps = self._host.get_domain_capabilities() + supported_models: ty.Set[str] = {fields.VIOMMUModel.AUTO} + # our min version of qemu/libvirt supprot q35 and virt machine types. + # They also support the smmuv3 and intel iommu modeles so if the qemu + # binary is avaiable we can report the trait. + if fields.Architecture.AARCH64 in dom_caps: + supported_models.add(fields.VIOMMUModel.SMMUV3) + if fields.Architecture.X86_64 in dom_caps: + supported_models.add(fields.VIOMMUModel.INTEL) + # the virtio iommu model requires a newer libvirt then our min + # libvirt so we need to check the version explcitly. + if self._host.has_min_version(MIN_LIBVIRT_VIOMMU_VIRTIO_MODEL): + supported_models.add(fields.VIOMMUModel.VIRTIO) + return { + f'COMPUTE_VIOMMU_MODEL_{model.replace("-", "_").upper()}': model + in supported_models for model in fields.VIOMMUModel.ALL + } + def _get_storage_bus_traits(self) -> ty.Dict[str, bool]: """Get storage bus traits based on the currently enabled virt_type.