Skip to content

Commit 0e32b2d

Browse files
committed
Add DRA e2e CI test
Add an end-to-end test that validates the full DRA lifecycle: DaemonSet creation, DeviceClass management, node labeling, status reporting, and cleanup on Module deletion.
1 parent 3138a60 commit 0e32b2d

3 files changed

Lines changed: 151 additions & 0 deletions

File tree

ci/e2e-dra/dra-consumer-pod.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
apiVersion: resource.k8s.io/v1
3+
kind: ResourceClaimTemplate
4+
metadata:
5+
name: dra-test-claim
6+
spec:
7+
spec:
8+
devices:
9+
requests:
10+
- name: gpu
11+
exactly:
12+
deviceClassName: kmm-ci-test-device
13+
---
14+
apiVersion: v1
15+
kind: Pod
16+
metadata:
17+
name: dra-consumer
18+
spec:
19+
# Prefer nodes WITHOUT the DRA device. This ensures that if the pod
20+
# still lands on the labeled node, it is because DRA scheduling overrode
21+
# the node preference — not scheduler coincidence.
22+
affinity:
23+
nodeAffinity:
24+
preferredDuringSchedulingIgnoredDuringExecution:
25+
- weight: 100
26+
preference:
27+
matchExpressions:
28+
- key: task
29+
operator: NotIn
30+
values:
31+
- kmm-ci-dra
32+
containers:
33+
- name: consumer
34+
image: busybox:1.36
35+
command: ["sh", "-c", "sleep infinity"]
36+
resources:
37+
claims:
38+
- name: gpu
39+
resourceClaims:
40+
- name: gpu
41+
resourceClaimTemplateName: dra-test-claim

ci/e2e-dra/module-kmm-ci-dra.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
apiVersion: kmm.sigs.x-k8s.io/v1beta1
3+
kind: Module
4+
metadata:
5+
name: kmm-ci-dra
6+
spec:
7+
moduleLoader:
8+
container:
9+
modprobe:
10+
moduleName: kmm_ci_a
11+
modulesLoadingOrder: [kmm_ci_a, kmm_ci_b]
12+
kernelMappings:
13+
- regexp: '^.+$'
14+
containerImage: image-registry.openshift-image-registry.svc:5000/$MOD_NAMESPACE/$MOD_NAME:$KERNEL_FULL_VERSION
15+
build:
16+
secrets:
17+
- name: build-secret
18+
dockerfileConfigMap:
19+
name: kmm-kmod-dockerfile
20+
dra:
21+
driverName: gpu.example.com
22+
container:
23+
image: registry.k8s.io/dra-example-driver/dra-example-driver:v0.3.0
24+
command: ["dra-example-kubeletplugin"]
25+
env:
26+
- name: DRIVER_NAME
27+
value: gpu.example.com
28+
deviceClasses:
29+
- name: kmm-ci-test-device
30+
selector:
31+
task: kmm-ci-dra

ci/prow/e2e-dra

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env bash
2+
3+
set -euxo pipefail
4+
5+
KUBE_MAJOR=$(oc version -o json | jq -r '.serverVersion.major' | tr -d '+')
6+
KUBE_MINOR=$(oc version -o json | jq -r '.serverVersion.minor' | tr -d '+')
7+
if [ "${KUBE_MAJOR}" -eq 1 ] && [ "${KUBE_MINOR}" -lt 34 ]; then
8+
echo "SKIP: DRA requires Kubernetes >= 1.34, got ${KUBE_MAJOR}.${KUBE_MINOR}"
9+
exit 0
10+
fi
11+
12+
echo "Get a worker node..."
13+
export NODE=$(oc get nodes -l node-role.kubernetes.io/worker -o jsonpath='{.items[0].metadata.name}')
14+
15+
echo "Label the node to match the Module selector..."
16+
oc label node "${NODE}" task=kmm-ci-dra
17+
18+
oc project openshift-kmm
19+
20+
oc wait --for=condition=Available deployment/kmm-operator-controller deployment/kmm-operator-webhook
21+
22+
echo "Create a build secret"
23+
oc create secret generic build-secret --from-literal=ci-build-secret=super-secret-value
24+
25+
echo "Add a configmap that contains the kernel module build dockerfile"
26+
oc apply -f ci/kmm-kmod-dockerfile.yaml
27+
28+
echo "Add a Module with DRA spec"
29+
timeout 1m bash -c 'until oc apply -f ci/e2e-dra/module-kmm-ci-dra.yaml; do sleep 3; done'
30+
31+
echo "Check that the module gets loaded on the node"
32+
timeout 10m bash -c 'until oc debug node/${NODE} -- chroot host/ lsmod | grep kmm_ci_a; do sleep 3; done'
33+
34+
echo "Check that the DRA DaemonSet gets created"
35+
timeout 2m bash -c 'until oc get ds -l kmm.node.kubernetes.io/role=dra,kmm.node.kubernetes.io/module.name=kmm-ci-dra -o name 2>/dev/null | grep -q daemonset; do sleep 3; done'
36+
37+
echo "Check that the DRA DaemonSet pod is ready"
38+
timeout 5m bash -c 'until [ "$(oc get ds -l kmm.node.kubernetes.io/role=dra,kmm.node.kubernetes.io/module.name=kmm-ci-dra -o jsonpath="{.items[0].status.numberReady}" 2>/dev/null)" = "1" ]; do sleep 3; done'
39+
40+
echo "Check that the DeviceClass was created with correct labels"
41+
DC_MODULE_NAME=$(oc get deviceclass kmm-ci-test-device -o jsonpath='{.metadata.labels.kmm\.node\.kubernetes\.io/module\.name}')
42+
DC_MODULE_NS=$(oc get deviceclass kmm-ci-test-device -o jsonpath='{.metadata.labels.kmm\.node\.kubernetes\.io/module\.namespace}')
43+
[ "${DC_MODULE_NAME}" = "kmm-ci-dra" ]
44+
[ "${DC_MODULE_NS}" = "openshift-kmm" ]
45+
46+
echo "Check that the DRA node label was set"
47+
timeout 2m bash -c 'until oc get node ${NODE} -o jsonpath="{.metadata.labels}" | grep "kmm\.node\.kubernetes\.io/openshift-kmm\.kmm-ci-dra\.dra-ready"; do sleep 3; done'
48+
49+
echo "Check that ResourceSlices were published by the driver"
50+
timeout 2m bash -c 'until [ "$(oc get resourceslice --no-headers 2>/dev/null | grep gpu.example.com | wc -l)" -gt 0 ]; do sleep 3; done'
51+
52+
echo "Check that Module status.dra is populated"
53+
[ "$(oc get module kmm-ci-dra -o jsonpath='{.status.dra.availableNumber}')" = "1" ]
54+
55+
echo "Deploy a consumer pod requesting DRA hardware"
56+
oc apply -f ci/e2e-dra/dra-consumer-pod.yaml
57+
58+
echo "Check that the consumer pod is running on the node with the DRA driver"
59+
oc wait --for=condition=Ready pod/dra-consumer --timeout=2m
60+
[ "$(oc get pod dra-consumer -o jsonpath='{.spec.nodeName}')" = "${NODE}" ]
61+
62+
echo "Remove the consumer pod"
63+
oc delete -f ci/e2e-dra/dra-consumer-pod.yaml
64+
timeout 1m bash -c 'until ! oc get pod dra-consumer 2>/dev/null; do sleep 3; done'
65+
66+
echo "Remove the Module"
67+
oc delete -f ci/e2e-dra/module-kmm-ci-dra.yaml --wait=false
68+
69+
echo "Check that the DRA DaemonSet gets cleaned up"
70+
timeout 2m bash -c 'until [ "$(oc get ds -l kmm.node.kubernetes.io/role=dra,kmm.node.kubernetes.io/module.name=kmm-ci-dra --no-headers 2>/dev/null | wc -l)" -eq 0 ]; do sleep 3; done'
71+
72+
echo "Check that the DeviceClass gets cleaned up"
73+
timeout 1m bash -c 'until ! oc get deviceclass kmm-ci-test-device 2>/dev/null; do sleep 3; done'
74+
75+
echo "Check that the module gets unloaded from the node"
76+
timeout 1m bash -c 'until ! oc debug node/${NODE} -- chroot host/ lsmod | grep kmm_ci_a; do sleep 3; done'
77+
78+
echo "Wait for the Module to be deleted"
79+
oc wait --for delete modules.kmm.sigs.x-k8s.io/kmm-ci-dra

0 commit comments

Comments
 (0)