From d1e9ecb443dd6bd5dc6456a3f9e33c1551436364 Mon Sep 17 00:00:00 2001 From: Dmitrii Shcherbakov Date: Fri, 4 Feb 2022 13:40:00 +0300 Subject: [PATCH] Add supports_remote_managed_ports capability In order to support remote-managed ports the following is needed: * Nova compute driver needs to support this feature; * For the Libvirt compute driver, a given host needs to have the right version of Libvirt - the one which supports PCI VPD (7.9.0 https://libvirt.org/news.html#v7-9-0-2021-11-01). Therefore, this change introduces a new capability to track driver support for remote-managed ports. Change-Id: I7ea96fd85d2607e0af0f6918b0b45c58e8bec058 --- nova/pci/stats.py | 4 ++++ .../functional/test_servers_provider_tree.py | 1 + nova/tests/unit/virt/libvirt/test_driver.py | 16 ++++++++++++++++ nova/tests/unit/virt/libvirt/test_host.py | 10 ++++++++++ nova/virt/driver.py | 2 ++ nova/virt/fake.py | 1 + nova/virt/hyperv/driver.py | 1 + nova/virt/ironic/driver.py | 1 + nova/virt/libvirt/driver.py | 2 ++ nova/virt/libvirt/host.py | 17 +++++++++++++++++ nova/virt/powervm/driver.py | 1 + nova/virt/vmwareapi/driver.py | 1 + nova/virt/zvm/driver.py | 1 + 13 files changed, 58 insertions(+) diff --git a/nova/pci/stats.py b/nova/pci/stats.py index 5da56ee94d37..0ec49b5d7196 100644 --- a/nova/pci/stats.py +++ b/nova/pci/stats.py @@ -110,6 +110,10 @@ class PciDeviceStats(object): fields.PciDeviceType.SRIOV_PF, fields.PciDeviceType.VDPA): return + + # A tag is added here rather than at the client side to avoid an + # issue with having objects without this tag specified during an + # upgrade to the first version that supports handling this tag. if pool.get(PCI_REMOTE_MANAGED_TAG) is None: # NOTE: tags are compared as strings case-insensitively, see # pci_device_prop_match in nova/pci/utils.py. diff --git a/nova/tests/functional/test_servers_provider_tree.py b/nova/tests/functional/test_servers_provider_tree.py index 0eff6c6bda06..334c4f329beb 100644 --- a/nova/tests/functional/test_servers_provider_tree.py +++ b/nova/tests/functional/test_servers_provider_tree.py @@ -45,6 +45,7 @@ class ProviderTreeTests(integrated_helpers.ProviderUsageBaseTestCase): os_traits.COMPUTE_VOLUME_EXTEND, os_traits.COMPUTE_VOLUME_MULTI_ATTACH, os_traits.COMPUTE_TRUSTED_CERTS, + os_traits.COMPUTE_REMOTE_MANAGED_PORTS, ] ]) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 50cb5536ef92..755b02d5b84c 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -885,6 +885,22 @@ class LibvirtConnTestCase(test.NoDBTestCase, ) mock_supports.assert_called_once_with() + @mock.patch.object( + libvirt_driver.LibvirtDriver, '_register_instance_machine_type', + new=mock.Mock()) + @mock.patch.object( + host.Host, 'supports_remote_managed_ports', + new_callable=mock.PropertyMock) + def test_driver_capabilities_remote_managed_ports(self, mock_supports): + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + drvr.init_host("dummyhost") + self.assertTrue( + drvr.capabilities['supports_remote_managed_ports'], + "Driver capabilities for 'supports_remote_managed_ports' " + "is invalid when host should support this feature" + ) + mock_supports.assert_called_once_with() + def test_driver_raises_on_non_linux_platform(self): with utils.temporary_mutation(sys, platform='darwin'): self.assertRaises( diff --git a/nova/tests/unit/virt/libvirt/test_host.py b/nova/tests/unit/virt/libvirt/test_host.py index a33ffef7024b..3aba6b35ee8d 100644 --- a/nova/tests/unit/virt/libvirt/test_host.py +++ b/nova/tests/unit/virt/libvirt/test_host.py @@ -1816,6 +1816,16 @@ cg /cgroup/memory cg opt1,opt2 0 0 """ self.assertTrue(self.host.supports_secure_boot) + @mock.patch.object(fakelibvirt.virConnect, "getLibVersion") + def test_supports_remote_managed_ports__true(self, mock_libversion): + mock_libversion.return_value = 7009000 + self.assertTrue(self.host.supports_remote_managed_ports) + + @mock.patch.object(fakelibvirt.virConnect, "getLibVersion") + def test_supports_remote_managed_ports__false(self, mock_libversion): + mock_libversion.return_value = 7008000 + self.assertFalse(self.host.supports_remote_managed_ports) + @mock.patch.object(host.Host, 'loaders', new_callable=mock.PropertyMock) @mock.patch.object(host.Host, 'get_canonical_machine_type') def test_get_loader(self, mock_get_mtype, mock_loaders): diff --git a/nova/virt/driver.py b/nova/virt/driver.py index b20e0c6bf75c..dfe97938eb24 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -126,6 +126,7 @@ CAPABILITY_TRAITS_MAP = { "supports_secure_boot": os_traits.COMPUTE_SECURITY_UEFI_SECURE_BOOT, "supports_socket_pci_numa_affinity": os_traits.COMPUTE_SOCKET_PCI_NUMA_AFFINITY, + "supports_remote_managed_ports": os_traits.COMPUTE_REMOTE_MANAGED_PORTS, } @@ -194,6 +195,7 @@ class ComputeDriver(object): "supports_vtpm": False, "supports_secure_boot": False, "supports_socket_pci_numa_affinity": False, + "supports_remote_managed_ports": False, # Image type support flags "supports_image_type_aki": False, diff --git a/nova/virt/fake.py b/nova/virt/fake.py index e0bcda554ca5..5aab8ce30078 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -116,6 +116,7 @@ class FakeDriver(driver.ComputeDriver): "supports_trusted_certs": True, "supports_pcpus": False, "supports_accelerators": True, + "supports_remote_managed_ports": True, # Supported image types "supports_image_type_raw": True, diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py index 350e59e295c4..1291f975add2 100644 --- a/nova/virt/hyperv/driver.py +++ b/nova/virt/hyperv/driver.py @@ -103,6 +103,7 @@ class HyperVDriver(driver.ComputeDriver): "supports_pcpus": False, "supports_accelerators": False, "supports_secure_boot": True, + "supports_remote_managed_ports": False, # Supported image types "supports_image_type_vhd": True, diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index 2a4fd39fda7b..7970f185412b 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -164,6 +164,7 @@ class IronicDriver(virt_driver.ComputeDriver): "supports_trusted_certs": False, "supports_pcpus": False, "supports_accelerators": False, + "supports_remote_managed_ports": False, # Image type support flags "supports_image_type_aki": False, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index c8fd7e22ed38..4e920afe13fb 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -812,6 +812,8 @@ class LibvirtDriver(driver.ComputeDriver): # or UEFI bootloader support in this manner self.capabilities.update({ 'supports_secure_boot': self._host.supports_secure_boot, + 'supports_remote_managed_ports': + self._host.supports_remote_managed_ports }) def _register_instance_machine_type(self): diff --git a/nova/virt/libvirt/host.py b/nova/virt/libvirt/host.py index 80663ab1dc43..f37ebba473e1 100644 --- a/nova/virt/libvirt/host.py +++ b/nova/virt/libvirt/host.py @@ -1701,6 +1701,23 @@ class Host(object): LOG.debug("No AMD SEV support detected for any (arch, machine_type)") return self._supports_amd_sev + @property + def supports_remote_managed_ports(self) -> bool: + """Determine if the host supports remote managed ports. + + Returns a boolean indicating whether remote managed ports are + possible to use on this host. + + The check is based on a Libvirt version which added support for + parsing and exposing PCI VPD since a card serial number (if present in + the VPD) since the use of remote managed ports depends on this. + https://libvirt.org/news.html#v7-9-0-2021-11-01 + + The actual presence of a card serial number for a particular device + is meant to be checked elsewhere. + """ + return self.has_min_version(lv_ver=(7, 9, 0)) + @property def loaders(self) -> ty.List[dict]: """Retrieve details of loader configuration for the host. diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py index 0f94a3b75b2c..d3eb9fc7706a 100644 --- a/nova/virt/powervm/driver.py +++ b/nova/virt/powervm/driver.py @@ -82,6 +82,7 @@ class PowerVMDriver(driver.ComputeDriver): 'supports_vtpm': False, 'supports_secure_boot': False, 'supports_socket_pci_numa_affinity': False, + 'supports_remote_managed_ports': False, # Supported image types "supports_image_type_aki": False, diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index 9934627e1edf..cc80ca775efc 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -72,6 +72,7 @@ class VMwareVCDriver(driver.ComputeDriver): "supports_trusted_certs": False, "supports_pcpus": False, "supports_accelerators": False, + "supports_remote_managed_ports": False, # Image type support flags "supports_image_type_aki": False, diff --git a/nova/virt/zvm/driver.py b/nova/virt/zvm/driver.py index c3552ecc3857..a1fa721515c3 100644 --- a/nova/virt/zvm/driver.py +++ b/nova/virt/zvm/driver.py @@ -46,6 +46,7 @@ class ZVMDriver(driver.ComputeDriver): """z/VM implementation of ComputeDriver.""" capabilities = { "supports_pcpus": False, + "supports_remote_managed_ports": False, # Image type support flags "supports_image_type_aki": False,