From 7903ee8d0ac87090f4d3c54e35e1e5f4172fe4e5 Mon Sep 17 00:00:00 2001 From: Andrea Panattoni Date: Tue, 18 Jun 2024 17:22:04 +0200 Subject: [PATCH] e2e: Verify removing partial policy works Add an end-to-end test to verify removing a partial SriovNetworkNodePolicy does not trigger any issue in the operator's deployment. Refs: - https://issues.redhat.com/browse/OCPBUGS-34934 - https://github.com/k8snetworkplumbingwg/sriov-network-operator/pull/710 Signed-off-by: Andrea Panattoni --- .../tests/test_policy_configuration.go | 39 ++++++++++++++++++- test/conformance/tests/test_sriov_operator.go | 22 +++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/test/conformance/tests/test_policy_configuration.go b/test/conformance/tests/test_policy_configuration.go index b2159d88c..0d0e440c2 100644 --- a/test/conformance/tests/test_policy_configuration.go +++ b/test/conformance/tests/test_policy_configuration.go @@ -23,7 +23,7 @@ import ( "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/pod" ) -var _ = Describe("[sriov] operator", func() { +var _ = Describe("[sriov] operator", Ordered, func() { var sriovInfos *cluster.EnabledNodes BeforeAll(func() { @@ -387,7 +387,44 @@ var _ = Describe("[sriov] operator", func() { err = clients.Create(context.Background(), secondConfig) Expect(err).To(HaveOccurred()) }) + + // https://issues.redhat.com/browse/OCPBUGS-34934 + It("Should be possible to delete a vfio-pci policy without getting a reconfiguration", func() { + vfioNode, vfioNic := sriovInfos.FindOneVfioSriovDevice() + if vfioNode == "" { + Skip("skip test as no vfio-pci capable PF was found") + } + By("Using device " + vfioNic.Name + " on node " + vfioNode) + + By("Creating a vfio-pci policy") + _, err := network.CreateSriovPolicy(clients, "test-policy-", operatorNamespace, vfioNic.Name+"#0-1", vfioNode, 5, "resvfiopci", "vfio-pci") + Expect(err).ToNot(HaveOccurred()) + + By("Creating a netdevice policy") + vfiopolicy, err := network.CreateSriovPolicy(clients, "test-policy-", operatorNamespace, vfioNic.Name+"#2-4", vfioNode, 5, "resnetdevice", "netdevice") + Expect(err).ToNot(HaveOccurred()) + + By("Checking the SriovNetworkNodeState is correctly configured") + assertNodeStateHasVFMatching(vfioNode, + Fields{"VfID": Equal(0), "Driver": Equal("vfio-pci")}) + assertNodeStateHasVFMatching(vfioNode, + Fields{"VfID": Equal(1), "Driver": Equal("vfio-pci")}) + assertNodeStateHasVFMatching(vfioNode, + Fields{"VfID": Equal(2), "Name": Not(BeEmpty())}) + + By("Deleting the vfio-pci policy") + err = clients.Delete(context.Background(), vfiopolicy) + Expect(err).ToNot(HaveOccurred()) + + By("Checking the SriovNetworkNodeState is not reconfiguring") + Consistently(func(g Gomega) { + nodeState, err := clients.SriovNetworkNodeStates(operatorNamespace).Get(context.Background(), vfioNode, metav1.GetOptions{}) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(nodeState.Status.SyncStatus).To(Equal("Succeeded")) + }, "15s", "1s").Should(Succeed()) + }) }) + Context("Main PF", func() { It("should work when vfs are used by pods", func() { if !discovery.Enabled() { diff --git a/test/conformance/tests/test_sriov_operator.go b/test/conformance/tests/test_sriov_operator.go index fb30c24cc..2b0294df2 100644 --- a/test/conformance/tests/test_sriov_operator.go +++ b/test/conformance/tests/test_sriov_operator.go @@ -2205,3 +2205,25 @@ func waitForNetAttachDef(name, namespace string) { return clients.Get(context.Background(), runtimeclient.ObjectKey{Name: name, Namespace: namespace}, netAttDef) }, (10+snoTimeoutMultiplier*110)*time.Second, 1*time.Second).ShouldNot(HaveOccurred()) } + +// assertNodeStateHasVFMatching asserts that the given node state has at least one VF matching the given fields +func assertNodeStateHasVFMatching(nodeName string, fields Fields) { + EventuallyWithOffset(1, func(g Gomega) sriovv1.InterfaceExts { + nodeState, err := clients.SriovNetworkNodeStates(operatorNamespace).Get(context.Background(), nodeName, metav1.GetOptions{}) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(nodeState.Status.SyncStatus).To(Equal("Succeeded")) + return nodeState.Status.Interfaces + }, 3*time.Minute, 1*time.Second). + Should( + ContainElement( + MatchFields( + IgnoreExtras, + Fields{ + "VFs": ContainElement( + MatchFields(IgnoreExtras, fields), + ), + }, + ), + ), + ) +}