From c28494fd27962622b3bb2fde2fc51e9cf3f9e5ce Mon Sep 17 00:00:00 2001 From: Pavlo Shchelokovskyy Date: Mon, 19 Jun 2023 19:32:46 +0300 Subject: [PATCH] Use configuration for single enabled mdev type Even when having specified a single mdev type, operator still might want to expose only one of available mdev-capable PCI devices to users, or use a custom resource class for it. NOTE(sbauza): That patch isn't changing the current behaviour (you can see the tests) but it just removes a weird limitation (that I wrote, sorry folks !) Co-Authored-By: Sylvain Bauza Change-Id: I9f42410e407902b2f562adaa506f14cbc69898d4 --- nova/tests/unit/virt/libvirt/test_driver.py | 35 +++++++++++++++++++-- nova/virt/libvirt/driver.py | 19 ++++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index fe3906134b04..3877e5ee5d86 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -26374,11 +26374,11 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): self.flags(enabled_mdev_types=['nvidia-11'], group='devices') self.assertEqual(['nvidia-11'], drvr._get_supported_vgpu_types()) # Given we only support one vGPU type, we don't have any map for PCI - # devices or mdev classes *yet* + # devices or mdev classes *yet* if we don't have a vgpu type section. self.assertEqual({}, drvr.pgpu_type_mapping) self.assertEqual({}, drvr.mdev_class_mapping) # Remember, we only support the VGPU resource class if we only have - # one needed vGPU type. + # one needed vGPU type without a specific vgpu type section. self.assertEqual({orc.VGPU}, drvr.mdev_classes) # Since the operator wanted to only support one type, it's fine to not # provide config groups @@ -26461,6 +26461,25 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): # be the second time that register_dynamic_opts() will be called. rdo.assert_has_calls([mock.call(CONF), mock.call(CONF)]) + @mock.patch.object(libvirt_driver.LOG, 'warning') + def test_get_supported_vgpu_types_with_a_single_type(self, mock_warning): + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + # Just add a single type... + self.flags(enabled_mdev_types=['nvidia-11'], group='devices') + # we need to call the below again to ensure the updated + # 'device_addresses' value is read and the new groups created + nova.conf.devices.register_dynamic_opts(CONF) + # ... But then use the type group for telling which pGPU to use. + self.flags(device_addresses=['0000:84:00.0'], group='mdev_nvidia-11') + self.flags(mdev_class='CUSTOM_NOTVGPU', group='mdev_nvidia-11') + + self.assertEqual(['nvidia-11'], drvr._get_supported_vgpu_types()) + self.assertEqual({'0000:84:00.0': 'nvidia-11'}, drvr.pgpu_type_mapping) + self.assertEqual({'0000:84:00.0': 'CUSTOM_NOTVGPU'}, + drvr.mdev_class_mapping) + self.assertEqual({'CUSTOM_NOTVGPU'}, drvr.mdev_classes) + mock_warning.assert_not_called() + def test_get_vgpu_type_per_pgpu(self): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) device = 'pci_0000_84_00_0' @@ -26471,7 +26490,17 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) self.assertEqual('nvidia-11', drvr._get_vgpu_type_per_pgpu(device)) - # Now, make sure we provide the right vGPU type for the device + # But this also works if we add a specific type group + self.flags(enabled_mdev_types=['nvidia-11'], group='devices') + nova.conf.devices.register_dynamic_opts(CONF) + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + # we default to directly provide the type for all devices... + self.assertEqual('nvidia-11', drvr._get_vgpu_type_per_pgpu(device)) + # ... even the ones we haven't provided yet by device_addresses + self.assertEqual('nvidia-11', + drvr._get_vgpu_type_per_pgpu('pci_0000_85_00_0')) + + # Now, use two types instead of one. self.flags(enabled_mdev_types=['nvidia-11', 'nvidia-12'], group='devices') # we need to call the below again to ensure the updated diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 31e7743282de..78dbd6cdeaf1 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -7930,8 +7930,7 @@ class LibvirtDriver(driver.ComputeDriver): # Make sure we register all the types as the compute service could # be calling this method before init_host() - if len(CONF.devices.enabled_mdev_types) > 1: - nova.conf.devices.register_dynamic_opts(CONF) + nova.conf.devices.register_dynamic_opts(CONF) for vgpu_type in CONF.devices.enabled_mdev_types: group = getattr(CONF, 'mdev_%s' % vgpu_type, None) @@ -7955,9 +7954,11 @@ class LibvirtDriver(driver.ComputeDriver): # support only the first type. self.pgpu_type_mapping.clear() self.mdev_class_mapping.clear() - # Given we only have one type, we default to only support the - # VGPU resource class. - self.mdev_classes = {orc.VGPU} + first_group = getattr(CONF, 'mdev_%s' % first_type, None) + if first_group is None: + self.mdev_classes = {orc.VGPU} + else: + self.mdev_classes = {first_group.mdev_class} return [first_type] mdev_class = group.mdev_class for device_address in group.device_addresses: @@ -8011,9 +8012,11 @@ class LibvirtDriver(driver.ComputeDriver): return if len(self.supported_vgpu_types) == 1: - # The operator wanted to only support one single type so we can - # blindly return it for every single pGPU - return self.supported_vgpu_types[0] + first_type = self.supported_vgpu_types[0] + group = getattr(CONF, 'mdev_%s' % first_type, None) + if group is None or not group.device_addresses: + return first_type + device_address = self._get_pci_id_from_libvirt_name(device_address) if not device_address: return