From f6515754b514c74d1f239a8a98f05c2563eca059 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 29 Jun 2023 09:34:44 +0200 Subject: [PATCH] hostdev: usb: Add functional testing The test takes inspiration on PCI's tests/vmi_hostdev_test.go Since the introduction of emulated USB devices [0], this can be tested locally with: > export KUBEVIRT_PROVIDER=k8s-1.26-centos9 > export KUBEVIRTCI_TAG=latest > export KUBEVIRT_PROVIDER_EXTRA_ARGS="--usb 20M --usb 40M" > make cluster-up [0] https://github.com/kubevirt/kubevirtci/pull/996 Signed-off-by: Luboslav Pivarc Signed-off-by: Victor Toso --- tests/decorators/decorators.go | 1 + tests/tests_suite_test.go | 1 + tests/usb/usb.go | 105 +++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 tests/usb/usb.go diff --git a/tests/decorators/decorators.go b/tests/decorators/decorators.go index 1f70c4231df4..a4e728cb7deb 100644 --- a/tests/decorators/decorators.go +++ b/tests/decorators/decorators.go @@ -36,6 +36,7 @@ var ( TscFrequencies = []interface{}{Label("TscFrequencies")} PasstGate = []interface{}{Label("PasstGate")} VMX = []interface{}{Label("VMX")} + USB = []interface{}{Label("USB")} Upgrade = []interface{}{Label("Upgrade")} CustomSELinux = []interface{}{Label("CustomSELinux")} Istio = []interface{}{Label("Istio")} diff --git a/tests/tests_suite_test.go b/tests/tests_suite_test.go index d7c679d63c18..251f16b61ae9 100644 --- a/tests/tests_suite_test.go +++ b/tests/tests_suite_test.go @@ -52,6 +52,7 @@ import ( _ "kubevirt.io/kubevirt/tests/realtime" _ "kubevirt.io/kubevirt/tests/scale" _ "kubevirt.io/kubevirt/tests/storage" + _ "kubevirt.io/kubevirt/tests/usb" _ "kubevirt.io/kubevirt/tests/virtctl" _ "kubevirt.io/kubevirt/tests/virtiofs" ) diff --git a/tests/usb/usb.go b/tests/usb/usb.go new file mode 100644 index 000000000000..250bc69a71ee --- /dev/null +++ b/tests/usb/usb.go @@ -0,0 +1,105 @@ +package usb + +import ( + "context" + "fmt" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v1 "kubevirt.io/api/core/v1" + "kubevirt.io/client-go/kubecli" + + virtconfig "kubevirt.io/kubevirt/pkg/virt-config" + "kubevirt.io/kubevirt/tests" + "kubevirt.io/kubevirt/tests/console" + "kubevirt.io/kubevirt/tests/decorators" + "kubevirt.io/kubevirt/tests/framework/kubevirt" + "kubevirt.io/kubevirt/tests/libwait" + "kubevirt.io/kubevirt/tests/util" +) + +const ( + failedDeleteVMI = "Failed to delete VMI" +) + +var _ = FDescribe("[Serial][sig-compute][USB] host USB Passthrough", Serial, decorators.SigCompute, decorators.USB, func() { + var ( + virtClient kubecli.KubevirtClient + config v1.KubeVirtConfiguration + ) + + BeforeEach(func() { + virtClient = kubevirt.Client() + kv := util.GetCurrentKv(virtClient) + config = kv.Spec.Configuration + }) + + AfterEach(func() { + kv := util.GetCurrentKv(virtClient) + // Reinitialized the DeveloperConfiguration to avoid to influence the next test + config = kv.Spec.Configuration + config.DeveloperConfiguration = &v1.DeveloperConfiguration{} + config.PermittedHostDevices = &v1.PermittedHostDevices{} + tests.UpdateKubeVirtConfigValueAndWait(config) + }) + + Context("with usb storage", func() { + DescribeTable("with emulated USB devices", func(deviceNames []string) { + resourceName := "kubevirt.io/usb-storage" + + By("Adding the emulated USB device to the permitted host devices") + config.DeveloperConfiguration = &v1.DeveloperConfiguration{ + FeatureGates: []string{virtconfig.HostDevicesGate}, + } + config.PermittedHostDevices = &v1.PermittedHostDevices{ + USB: []v1.USBHostDevice{ + { + ResourceName: resourceName, + Selectors: []v1.USBSelector{ + { + Vendor: "46f4", + Product: "0001", + }}, + }}, + } + tests.UpdateKubeVirtConfigValueAndWait(config) + + By("Creating a Fedora VMI with the usb host device") + hostDevs := []v1.HostDevice{} + for i, name := range deviceNames { + hostDevs = append(hostDevs, v1.HostDevice{ + Name: fmt.Sprintf("usb-%d-%s", i, name), + DeviceName: resourceName, + }) + } + + randomVMI := tests.NewRandomFedoraVMIWithGuestAgent() + randomVMI.Spec.Domain.Devices.HostDevices = hostDevs + vmi, err := virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(context.Background(), randomVMI) + Expect(err).ToNot(HaveOccurred()) + libwait.WaitForSuccessfulVMIStart(vmi) + Expect(console.LoginToFedora(vmi)).To(Succeed()) + + By("Making sure the usb is present inside the VMI") + /* + for _, id := range deviceIDs { + Expect(console.SafeExpectBatch(vmi, []expect.Batcher{ + &expect.BSnd{S: "grep -c " + strings.Replace(id, ":", "", 1) + " /proc/bus/pci/devices\n"}, + &expect.BExp{R: console.RetValue("1")}, + }, 15)).To(Succeed(), "Device not found") + } + */ + + // Make sure to delete the VMI before ending the test otherwise a device could still be taken + err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Delete(context.Background(), vmi.ObjectMeta.Name, &metav1.DeleteOptions{}) + Expect(err).ToNot(HaveOccurred(), failedDeleteVMI) + libwait.WaitForVirtualMachineToDisappearWithTimeout(vmi, 180) + }, + Entry("Should successfully passthrough 1 emulated USB device", []string{"slow-storage"}), + Entry("Should successfully passthrough 2 emulated USB devices", []string{"fast-storage", "low-storage"}), + ) + }) +})