diff --git a/test/conformance/tests/test_sriov_operator.go b/test/conformance/tests/test_sriov_operator.go index cf1943db42..691bed85ed 100644 --- a/test/conformance/tests/test_sriov_operator.go +++ b/test/conformance/tests/test_sriov_operator.go @@ -1368,6 +1368,138 @@ var _ = Describe("[sriov] operator", func() { Expect(stdout).To(ContainSubstring("2 packets transmitted, 2 received, 0% packet loss")) }) }) + + Context("ExcludeTopology", func() { + BeforeEach(func() { + if discovery.Enabled() { + Skip("Test unsuitable to be run in discovery mode") + } + }) + /* + apiVersion: v1 │ + data: + cnfdd5.clus2.t5g.lab.eng.bos.redhat.com: '{"resourceList":[{"resourceName":"testSriovResource","excludeTopology":true,"selectors":{"vendors":["8086"],"devices":["154c"],"rootDevices":["0000:3b:00.0"],"IsRdma":false,"NeedVhostNet":false},"SelectorObj":null}]}' + dhcp19-17-171.clus2.t5g.lab.eng.bos.redhat.com: '{"resourceList":null}' + kind: ConfigMap + metadata: + creationTimestamp: "2023-05-29T09:45:33Z" + name: device-plugin-config + namespace: openshift-sriov-network-operator + resourceVersion: "10437605" + uid: 74dd4f4c-4924-4ea0-bf21-7dd68d7fb8f7 + + */ + FIt("field is forwarded to the device plugin configuration", func() { + node := sriovInfos.Nodes[0] + sriovDeviceList, err := sriovInfos.FindSriovDevices(node) + Expect(err).ToNot(HaveOccurred()) + unusedSriovDevices, err := findUnusedSriovDevices(node, sriovDeviceList) + Expect(err).ToNot(HaveOccurred()) + + intf := unusedSriovDevices[0] + + excludeTopologyTrue := &sriovv1.SriovNetworkNodePolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-exclude-topology-true", + Namespace: operatorNamespace, + }, + + Spec: sriovv1.SriovNetworkNodePolicySpec{ + NumVfs: 10, + ResourceName: "resourceXXX", + NodeSelector: map[string]string{"kubernetes.io/hostname": node}, + NicSelector: sriovv1.SriovNetworkNicSelector{ + PfNames: []string{intf.Name + "#0-4"}, + }, + ExcludeTopology: true, + }, + } + err = clients.Create(context.Background(), excludeTopologyTrue) + Expect(err).ToNot(HaveOccurred()) + + assertDevicePluginConfigurationContains(node, + `{"resourceName":"resourceXXX","excludeTopology":true,"selectors":{"pfNames":["`+intf.Name+`#0-4"],"IsRdma":false,"NeedVhostNet":false},"SelectorObj":null}`) + + excludeTopologyFalse := &sriovv1.SriovNetworkNodePolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-exclude-topology-false", + Namespace: operatorNamespace, + }, + + Spec: sriovv1.SriovNetworkNodePolicySpec{ + NumVfs: 10, + ResourceName: "resourceYYY", + NodeSelector: map[string]string{"kubernetes.io/hostname": node}, + NicSelector: sriovv1.SriovNetworkNicSelector{ + PfNames: []string{intf.Name + "#5-9"}, + }, + ExcludeTopology: false, + }, + } + + err = clients.Create(context.Background(), excludeTopologyFalse) + Expect(err).ToNot(HaveOccurred()) + + assertDevicePluginConfigurationContains(node, + `{"resourceName":"resourceXXX","excludeTopology":true,"selectors":{"pfNames":["`+intf.Name+`#0-4"],"IsRdma":false,"NeedVhostNet":false},"SelectorObj":null}`) + assertDevicePluginConfigurationContains(node, + `{"resourceName":"resourceYYY","selectors":{"pfNames":["`+intf.Name+`#5-9"],"IsRdma":false,"NeedVhostNet":false},"SelectorObj":null}`) + }) + + It("multiple values for the same resource should not be allowed", func() { + node := sriovInfos.Nodes[0] + sriovDeviceList, err := sriovInfos.FindSriovDevices(node) + Expect(err).ToNot(HaveOccurred()) + unusedSriovDevices, err := findUnusedSriovDevices(node, sriovDeviceList) + Expect(err).ToNot(HaveOccurred()) + + intf := unusedSriovDevices[0] + + excludeTopologyTrue := &sriovv1.SriovNetworkNodePolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-exclude-topology-true", + Namespace: operatorNamespace, + }, + + Spec: sriovv1.SriovNetworkNodePolicySpec{ + NumVfs: 10, + ResourceName: "resourceXXX", + NodeSelector: map[string]string{"kubernetes.io/hostname": node}, + NicSelector: sriovv1.SriovNetworkNicSelector{ + PfNames: []string{intf.Name + "#0-4"}, + }, + ExcludeTopology: true, + }, + } + + err = clients.Create(context.Background(), excludeTopologyTrue) + Expect(err).ToNot(HaveOccurred()) + + excludeTopologyFalse := &sriovv1.SriovNetworkNodePolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-exclude-topology-false", + Namespace: operatorNamespace, + }, + + Spec: sriovv1.SriovNetworkNodePolicySpec{ + NumVfs: 10, + ResourceName: "resourceXXX", + NodeSelector: map[string]string{"kubernetes.io/hostname": node}, + NicSelector: sriovv1.SriovNetworkNicSelector{ + PfNames: []string{intf.Name + "#5-9"}, + }, + ExcludeTopology: false, + }, + } + + err = clients.Create(context.Background(), excludeTopologyFalse) + Expect(err).To(HaveOccurred()) + + Expect(err.Error()).To(ContainSubstring( + "excludeTopology[false] field conflicts with policy [test-exclude-topology-true].ExcludeTopology[true]" + + " as they target the same resource[resourceXXX]")) + }) + }) }) Context("Nic Validation", func() { @@ -2124,3 +2256,18 @@ func assertObjectIsNotFound(name string, obj runtimeclient.Object) { return err != nil && k8serrors.IsNotFound(err) }, 2*time.Minute, 10*time.Second).Should(BeTrue()) } + +func assertDevicePluginConfigurationContains(node, configuration string) { + Eventually(func(g Gomega) map[string]string { + cfg := corev1.ConfigMap{} + err := clients.Get(context.Background(), runtimeclient.ObjectKey{ + Name: "device-plugin-config", + Namespace: operatorNamespace, + }, &cfg) + g.Expect(err).ToNot(HaveOccurred()) + + return cfg.Data + }, 30*time.Second, 2*time.Second).Should( + HaveKeyWithValue(node, ContainSubstring(configuration)), + ) +}