Skip to content

Commit b65ec7b

Browse files
qinqonclaude
andcommitted
kola: add KubeVirt platform support
Add KubeVirt as a new kola platform for running tests on VMs managed by KubeVirt/OpenShift Virtualization. This includes: - KubeVirt API client for creating/managing VMs via container disks - SSH access via WebSocket-based port forwarding - Cloud-init support for both ConfigDrive and NoCloud transports - Metadata tests for afterburn integration (configdrive + nocloud) - CI workflow with Kind cluster, KubeVirt, and kola test execution - Vendor dependencies for kubevirt.io/api v1.8.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b23d8cf commit b65ec7b

1,496 files changed

Lines changed: 690862 additions & 14 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/kubevirt.yaml

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
name: KubeVirt
3+
4+
on:
5+
pull_request:
6+
branches: [main]
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
kubevirt:
14+
name: KubeVirt
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Check out repository
18+
uses: actions/checkout@v4
19+
20+
- name: Enable KVM access
21+
run: |
22+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
23+
| sudo tee /etc/udev/rules.d/99-kvm.rules
24+
sudo udevadm control --reload-rules
25+
sudo udevadm trigger --name-match=kvm
26+
27+
- name: Build KubeVirt image
28+
run: |
29+
set -euxo pipefail
30+
31+
builddir=$(mktemp -d)
32+
echo "BUILDDIR=${builddir}" >> "$GITHUB_ENV"
33+
34+
cosa() {
35+
env | sort > /tmp/cosa-env
36+
podman run --rm \
37+
--security-opt=label=disable --privileged \
38+
--uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap=1001:1001:64536 \
39+
-v="${builddir}:/srv/" --device=/dev/kvm --device=/dev/fuse \
40+
--tmpfs=/tmp -v=/var/tmp:/var/tmp \
41+
--env-file=/tmp/cosa-env \
42+
${COREOS_ASSEMBLER_CONTAINER} "$@"
43+
rc=$?; return $rc
44+
}
45+
46+
export COREOS_ASSEMBLER_CONTAINER="${COREOS_ASSEMBLER_CONTAINER:-quay.io/coreos-assembler/coreos-assembler:latest}"
47+
48+
cosa init https://github.com/coreos/fedora-coreos-config
49+
cosa fetch
50+
cosa build
51+
cosa buildextend-kubevirt
52+
53+
- name: Create Kind cluster
54+
run: |
55+
cat <<EOF | kind create cluster --wait 120s --config=-
56+
kind: Cluster
57+
apiVersion: kind.x-k8s.io/v1alpha4
58+
nodes:
59+
- role: control-plane
60+
extraMounts:
61+
- hostPath: /dev/kvm
62+
containerPath: /dev/kvm
63+
EOF
64+
65+
- name: Install KubeVirt
66+
run: |
67+
set -euxo pipefail
68+
69+
KUBEVIRT_VERSION=v1.8.0
70+
KUBEVIRT_RELEASE_URL="https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}"
71+
72+
# Bump inotify limits on Kind nodes
73+
for node in $(kubectl get node --no-headers -o custom-columns=":metadata.name"); do
74+
docker exec -t "${node}" bash -c "echo 'fs.inotify.max_user_watches=1048576' >> /etc/sysctl.conf"
75+
docker exec -t "${node}" bash -c "echo 'fs.inotify.max_user_instances=512' >> /etc/sysctl.conf"
76+
docker exec -i "${node}" bash -c "sysctl -p /etc/sysctl.conf"
77+
done
78+
79+
# Deploy KubeVirt operator and CR
80+
kubectl apply -f "${KUBEVIRT_RELEASE_URL}/kubevirt-operator.yaml"
81+
kubectl apply -f "${KUBEVIRT_RELEASE_URL}/kubevirt-cr.yaml"
82+
83+
# Wait for KubeVirt to be ready
84+
if ! kubectl wait -n kubevirt kv kubevirt --for=condition=Available --timeout=15m; then
85+
kubectl get pod -n kubevirt || true
86+
kubectl describe pod -n kubevirt || true
87+
for p in $(kubectl get pod -n kubevirt -o name | sed "s#pod/##"); do
88+
kubectl logs -p --all-containers=true -n kubevirt "$p" || true
89+
kubectl logs --all-containers=true -n kubevirt "$p" || true
90+
done
91+
exit 1
92+
fi
93+
94+
- name: Load image into Kind
95+
run: |
96+
set -euxo pipefail
97+
ociarchive=$(find "${BUILDDIR}/builds/" -name '*-kubevirt.*.ociarchive' | head -1)
98+
skopeo copy "oci-archive:${ociarchive}" "docker-archive:/tmp/fcos-kubevirt.tar:localhost/fcos-kubevirt:latest"
99+
kind load image-archive /tmp/fcos-kubevirt.tar
100+
101+
- name: Set up Go
102+
uses: actions/setup-go@v5
103+
with:
104+
go-version-file: go.mod
105+
106+
- name: Build kola
107+
run: go build -o bin/kola ./mantle/cmd/kola
108+
109+
- name: Verify KubeVirt readiness
110+
run: |
111+
set -euxo pipefail
112+
# Check KVM device is available in Kind node
113+
docker exec kind-control-plane ls -la /dev/kvm
114+
# Check KubeVirt device plugin allocated kvm
115+
kubectl get node -o jsonpath='{.items[0].status.allocatable}' | jq .
116+
# Check virt components are running
117+
kubectl get pods -n kubevirt
118+
119+
- name: Run kola tests
120+
run: |
121+
set -euxo pipefail
122+
./bin/kola run -p kubevirt \
123+
--kubevirt-image localhost/fcos-kubevirt:latest \
124+
--output-dir "${BUILDDIR}/tmp/kola" \
125+
-v \
126+
'fcos.metadata.kubevirt.configdrive'
127+
128+
- name: Debug on failure
129+
if: failure()
130+
run: |
131+
set +e
132+
echo "=== VMs ==="
133+
kubectl get vm,vmi -A
134+
echo "=== VM details ==="
135+
kubectl describe vmi -A
136+
echo "=== Pods ==="
137+
kubectl get pods -A
138+
echo "=== virt-launcher logs ==="
139+
for p in $(kubectl get pod -l kubevirt.io=virt-launcher -o name 2>/dev/null); do
140+
echo "--- $p ---"
141+
kubectl logs "$p" --all-containers=true 2>/dev/null | tail -50
142+
done
143+
144+
- name: Upload KubeVirt artifact
145+
if: always()
146+
uses: actions/upload-artifact@v4
147+
with:
148+
name: fcos-kubevirt-image
149+
path: builds/latest/**/fedora-coreos-*-kubevirt.*.ociarchive
150+
if-no-files-found: warn

go.mod

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ require (
3838
github.com/google/uuid v1.6.0
3939
github.com/gophercloud/gophercloud v1.14.1
4040
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56
41+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
4142
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
4243
github.com/kylelemons/godebug v1.1.0
4344
github.com/pborman/uuid v1.2.1
@@ -56,6 +57,11 @@ require (
5657
google.golang.org/api v0.274.0
5758
gopkg.in/yaml.v2 v2.4.0
5859
gopkg.in/yaml.v3 v3.0.1
60+
k8s.io/api v0.35.3
61+
k8s.io/apimachinery v0.35.3
62+
k8s.io/client-go v0.35.3
63+
kubevirt.io/api v1.8.0
64+
sigs.k8s.io/controller-runtime v0.23.3
5965
)
6066

6167
require (
@@ -85,18 +91,25 @@ require (
8591
github.com/coreos/go-json v0.0.0-20231102161613-e49c8866685a // indirect
8692
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
8793
github.com/digitalocean/go-libvirt v0.0.0-20250317183548-13bf9b43b50b // indirect
94+
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
95+
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
8896
github.com/felixge/httpsnoop v1.0.4 // indirect
97+
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
8998
github.com/gabriel-vasile/mimetype v1.4.11 // indirect
9099
github.com/go-logr/logr v1.4.3 // indirect
91100
github.com/go-logr/stdr v1.2.2 // indirect
92101
github.com/go-openapi/errors v0.22.4 // indirect
102+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
103+
github.com/go-openapi/jsonreference v0.21.0 // indirect
93104
github.com/go-openapi/strfmt v0.25.0 // indirect
105+
github.com/go-openapi/swag v0.23.0 // indirect
94106
github.com/go-playground/locales v0.14.1 // indirect
95107
github.com/go-playground/universal-translator v0.18.1 // indirect
96108
github.com/go-playground/validator/v10 v10.28.0 // indirect
97109
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
98110
github.com/godbus/dbus/v5 v5.1.0 // indirect
99111
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
112+
github.com/google/gnostic-models v0.7.0 // indirect
100113
github.com/google/go-querystring v1.1.0 // indirect
101114
github.com/google/s2a-go v0.1.9 // indirect
102115
github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
@@ -106,18 +119,23 @@ require (
106119
github.com/hashicorp/go-uuid v1.0.3 // indirect
107120
github.com/inconshreveable/mousetrap v1.1.0 // indirect
108121
github.com/jmespath/go-jmespath v0.4.0 // indirect
122+
github.com/josharian/intern v1.0.0 // indirect
109123
github.com/json-iterator/go v1.1.12 // indirect
110124
github.com/leodido/go-urn v1.4.0 // indirect
125+
github.com/mailru/easyjson v0.7.7 // indirect
111126
github.com/mitchellh/go-homedir v1.1.0 // indirect
112127
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
113-
github.com/modern-go/reflect2 v1.0.2 // indirect
128+
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
129+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
114130
github.com/oklog/ulid v1.3.1 // indirect
115131
github.com/opencontainers/go-digest v1.0.0 // indirect
132+
github.com/openshift/custom-resource-status v1.1.2 // indirect
116133
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
117134
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
118135
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
119136
github.com/spf13/pflag v1.0.10 // indirect
120137
github.com/stretchr/testify v1.11.1 // indirect
138+
github.com/x448/float16 v0.8.4 // indirect
121139
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
122140
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
123141
go.mongodb.org/mongo-driver v1.17.6 // indirect
@@ -127,14 +145,25 @@ require (
127145
go.opentelemetry.io/otel/metric v1.42.0 // indirect
128146
go.opentelemetry.io/otel/trace v1.42.0 // indirect
129147
go.yaml.in/yaml/v2 v2.4.3 // indirect
148+
go.yaml.in/yaml/v3 v3.0.4 // indirect
130149
golang.org/x/net v0.52.0 // indirect
131150
golang.org/x/sys v0.42.0 // indirect
132151
golang.org/x/text v0.35.0 // indirect
133152
golang.org/x/time v0.15.0 // indirect
134153
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 // indirect
135154
google.golang.org/grpc v1.79.3 // indirect
136155
google.golang.org/protobuf v1.36.11 // indirect
156+
gopkg.in/inf.v0 v0.9.1 // indirect
137157
gopkg.in/ini.v1 v1.67.0 // indirect
158+
k8s.io/apiextensions-apiserver v0.35.0 // indirect
159+
k8s.io/klog/v2 v2.130.1 // indirect
160+
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
161+
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
162+
kubevirt.io/containerized-data-importer-api v1.64.0 // indirect
163+
kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4 // indirect
164+
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
165+
sigs.k8s.io/randfill v1.0.0 // indirect
166+
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect
138167
sigs.k8s.io/yaml v1.6.0 // indirect
139168
)
140169

0 commit comments

Comments
 (0)