forked from kubevirt/kubevirt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathusb.go
129 lines (110 loc) · 4.39 KB
/
usb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package usb
import (
"context"
"fmt"
"strings"
expect "github.com/google/goexpect"
. "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"
pkgUtil "kubevirt.io/kubevirt/pkg/util"
virtconfig "kubevirt.io/kubevirt/pkg/virt-config"
"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
"kubevirt.io/kubevirt/tests"
"kubevirt.io/kubevirt/tests/console"
"kubevirt.io/kubevirt/tests/decorators"
"kubevirt.io/kubevirt/tests/framework/kubevirt"
"kubevirt.io/kubevirt/tests/libvmifact"
"kubevirt.io/kubevirt/tests/libwait"
"kubevirt.io/kubevirt/tests/util"
)
const (
failedDeleteVMI = "Failed to delete VMI"
cmdNumberUSBs = "dmesg | grep -c idVendor=46f4"
)
var _ = Describe("[Serial][sig-compute][USB] host USB Passthrough", Serial, decorators.SigCompute, decorators.USB, func() {
var virtClient kubecli.KubevirtClient
var config v1.KubeVirtConfiguration
var vmi *v1.VirtualMachineInstance
BeforeEach(func() {
virtClient = kubevirt.Client()
kv := util.GetCurrentKv(virtClient)
config = kv.Spec.Configuration
nodeName := tests.NodeNameWithHandler()
Expect(nodeName).ToNot(BeEmpty())
// Emulated USB devices only on c9s providers. Remove this when sig-compute 1.26 is the
// oldest sig-compute with test with.
// See: https://github.com/kubevirt/project-infra/pull/2922
stdout, err := tests.ExecuteCommandInVirtHandlerPod(nodeName, []string{"dmesg"})
Expect(err).ToNot(HaveOccurred())
if strings.Count(stdout, "idVendor=46f4") == 0 {
Skip("No emulated USB devices present for functional test.")
}
vmi = libvmifact.NewCirros()
})
AfterEach(func() {
// 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)
})
Context("with usb storage", func() {
DescribeTable("with emulated USB devices", func(deviceNames []string) {
const 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,
})
}
var err error
vmi.Spec.Domain.Devices.HostDevices = hostDevs
vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(context.Background(), vmi, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())
vmi = libwait.WaitForSuccessfulVMIStart(vmi)
Expect(console.LoginToCirros(vmi)).To(Succeed())
By("Making sure the usb is present inside the VMI")
Expect(console.SafeExpectBatch(vmi, []expect.Batcher{
&expect.BSnd{S: fmt.Sprintf("%s\n", cmdNumberUSBs)},
&expect.BExp{R: console.RetValue(fmt.Sprintf("%d", len(deviceNames)))},
}, 15)).To(Succeed(), "Device not found")
By("Verifying ownership is properly set in the host")
domainXml, err := tests.GetRunningVMIDomainSpec(vmi)
Expect(err).ToNot(HaveOccurred())
for _, hostDevice := range domainXml.Devices.HostDevices {
if hostDevice.Type != api.HostDeviceUSB {
continue
}
addr := hostDevice.Source.Address
path := fmt.Sprintf("%sdev/bus/usb/00%s/00%s", pkgUtil.HostRootMount, addr.Bus, addr.Device)
cmd := []string{"stat", "--printf", `"%u %g"`, path}
stdout, err := tests.ExecuteCommandInVirtHandlerPod(vmi.Status.NodeName, cmd)
Expect(err).ToNot(HaveOccurred())
Expect(stdout).Should(Equal(`"107 107"`))
}
},
Entry("Should successfully passthrough 1 emulated USB device", []string{"slow-storage"}),
Entry("Should successfully passthrough 2 emulated USB devices", []string{"fast-storage", "low-storage"}),
)
})
})