From 00365789fe1500070dbf524f8b158f04cb613a6a Mon Sep 17 00:00:00 2001 From: Patryk Matuszak Date: Mon, 30 Jun 2025 13:23:30 +0200 Subject: [PATCH 1/3] Generic Device Plugin - Sanity Smoke Test --- .../fake-serial-communication.py | 60 ++++++++++ test/assets/generic-device-plugin/job.yaml | 31 +++++ ...hel96-bootc-source-optionals.containerfile | 11 ++ .../optional/generic-device-plugin.robot | 111 ++++++++++++++++++ test/suites/optional/strings.py | 29 +++++ 5 files changed, 242 insertions(+) create mode 100755 test/assets/generic-device-plugin/fake-serial-communication.py create mode 100644 test/assets/generic-device-plugin/job.yaml create mode 100644 test/suites/optional/generic-device-plugin.robot create mode 100644 test/suites/optional/strings.py diff --git a/test/assets/generic-device-plugin/fake-serial-communication.py b/test/assets/generic-device-plugin/fake-serial-communication.py new file mode 100755 index 0000000000..93f0179ce9 --- /dev/null +++ b/test/assets/generic-device-plugin/fake-serial-communication.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +""" +This script simulates a simple serial communication between a host and a pod. +It supports two modes of operation: 'host' and 'pod': + - Host listens for a message and responds. + - Pod sends a message and waits for a response. +Both sides are verifying the messages they send and receive. +""" + +import serial +import sys + +DEVICE_POD = "/dev/ttyPipeB0" +DEVICE_HOST = "/dev/ttyPipeA0" + +MSG_1 = b"HELLO\n" +MSG_2 = b"THERE\n" + + +def send_msg(ser, msg): + print(f"Sending message: {msg}") + ser.write(msg) + + +def recv_msg(ser, expected_msg): + print(f"Listening for a message. Expecting: {expected_msg}") + line = ser.readline() + print(f"Received message: {line}") + if expected_msg != line: + print("Received message does not match expected one") + sys.exit(1) + + +def host(): + s = serial.Serial(DEVICE_HOST, timeout=60) + recv_msg(s, MSG_1) + send_msg(s, MSG_2) + print("Test successful") + + +def pod(): + s = serial.Serial(DEVICE_POD, timeout=10) + send_msg(s, MSG_1) + recv_msg(s, MSG_2) + print("Test successful") + + +if len(sys.argv) == 1: + print("Not enough args") + sys.exit(1) + +mode = sys.argv[1] +if mode == "host": + host() +elif mode == "pod": + pod() +else: + print(f"Invalid arg: {mode}. Accepted args: host | pod") + sys.exit(1) diff --git a/test/assets/generic-device-plugin/job.yaml b/test/assets/generic-device-plugin/job.yaml new file mode 100644 index 0000000000..c101ecb0ab --- /dev/null +++ b/test/assets/generic-device-plugin/job.yaml @@ -0,0 +1,31 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: gdp-test +spec: + template: + spec: + restartPolicy: Never + containers: + - name: gdp-test + image: quay.io/fedora/python-311 + command: ["/bin/bash"] + args: ["/script/entrypoint.sh", "pod"] + resources: + limits: + device.microshift.io/fakeserial: 1 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + runAsNonRoot: true + seccompProfile: + type: "RuntimeDefault" + volumeMounts: + - name: script-volume + mountPath: /script/ + volumes: + - name: script-volume + configMap: + name: gdp-script + defaultMode: 0755 diff --git a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile index 701aa4791d..15fdbedff9 100644 --- a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile +++ b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile @@ -26,3 +26,14 @@ RUN dnf repoinfo --enabled && \ rm -vf /etc/yum.repos.d/microshift-*.repo && \ rm -rvf $USHIFT_RPM_REPO_PATH && \ dnf clean all + +# Prepare system for testing Generic Device Plugin. +# hadolint ignore=DL3003 +RUN KERNEL_VER=$(rpm -q --qf "%{VERSION}-%{RELEASE}" kernel); \ + KERNEL_VER_ARCH="${KERNEL_VER}.$(uname -i)"; \ + dnf install -y git make "kernel-devel-${KERNEL_VER}" python3-pyserial && \ + dnf clean all && \ + git clone https://github.com/pmtk/serialsim.git /tmp/serialsim && \ + cd /tmp/serialsim && \ + make KERNEL="${KERNEL_VER_ARCH}" all install && \ + rm -rf /tmp/serialsim diff --git a/test/suites/optional/generic-device-plugin.robot b/test/suites/optional/generic-device-plugin.robot new file mode 100644 index 0000000000..ca8b2a5d71 --- /dev/null +++ b/test/suites/optional/generic-device-plugin.robot @@ -0,0 +1,111 @@ +*** Settings *** +Documentation Generic Device Plugin + +Resource ../../resources/microshift-config.resource +Resource ../../resources/microshift-process.resource +Variables strings.py +Library strings.py + +Suite Setup Setup Suite With Namespace +Suite Teardown Teardown Suite With Namespace + + +*** Variables *** +${NAMESPACE} ${EMPTY} + + +*** Test Cases *** +Sanity Test + [Documentation] Performs a simple test of Generic Device Plugin + [Setup] Run Keywords + ... Enable And Configure GDP + ... Enable Serialsim + ... Copy Script To Host + + Wait Until Device Is Allocatable + + Command Should Work crictl pull quay.io/fedora/python-311 + Start Script On Host + Create Test Job + + Wait For Job Completion And Check Logs + + [Teardown] Run Keywords + ... Stop Script On Host + ... Disable GDP + + +*** Keywords *** +Enable And Configure GDP + [Documentation] Enables GDP and adds fake device path in MicroShift configuration + Drop In MicroShift Config ${GDP_CONFIG_DROPIN} 10-gdp + Restart MicroShift + +Disable GDP + [Documentation] Removes GDP configuration drop-in + Remove Drop In MicroShift Config 10-gdp + Restart MicroShift + +Enable Serialsim + [Documentation] Enables the serialsim kernel module. + ... serialsim creates echo and pipe devices. + Command Should Work modprobe serialsim + +Copy Script To Host + [Documentation] Starts fake serial communication script to the host + Put File + ... ./assets/generic-device-plugin/fake-serial-communication.py + ... /tmp/fake-serial-communication.py + +Start Script On Host + [Documentation] Starts fake serial communication script on the host in the background + ${cmd}= Catenate + ... systemd-run -u gdp-test-comm + ... python /tmp/fake-serial-communication.py host + Command Should Work ${cmd} + +Stop Script On Host + [Documentation] Attempts to stop the fake serial communication script on the host. + ... If it was successful, the unit is deleted automatically. + Command Execution journalctl -u gdp-test-comm.service + Command Execution systemctl stop gdp-test-comm + Command Execution systemctl reset-failed gdp-test-comm + +Create Test Job + [Documentation] Creates Job that spawns test Pod running to completion. + ${script}= OperatingSystem.Get File ./assets/generic-device-plugin/fake-serial-communication.py + ${configmap}= Append To Preamble ${script} + Log ${configmap} + ${path}= Create Random Temp File ${configmap} + Oc Create -f ${path} -n ${NAMESPACE} + Oc Create -f ./assets/generic-device-plugin/job.yaml -n ${NAMESPACE} + +Wait Until Device Is Allocatable + [Documentation] Waits until device device.microshift.io/fakeserial is allocatable + ${node}= Run With Kubeconfig oc get node -o=name + ${node_name}= Remove String ${node} node/ + + Wait Until Keyword Succeeds 60s 5s + ... Device Should Be Allocatable ${node_name} + +Device Should Be Allocatable + [Documentation] Checks if device device.microshift.io/fakeserial is allocatable + [Arguments] ${node_name} + ${device_amount}= Oc Get JsonPath + ... node + ... ${EMPTY} + ... ${node_name} + ... .status.allocatable.device\\.microshift\\.io/fakeserial + Should Be Equal As Integers ${device_amount} 1 + +Wait For Job Completion And Check Logs + [Documentation] Waits for Job completion and checks Pod logs looking for 'Test successful' message + + Oc Wait -n ${NAMESPACE} job/gdp-test --for=condition=complete --timeout=120s + ${pod}= Oc Get JsonPath + ... pod + ... ${NAMESPACE} + ... --selector=batch.kubernetes.io/job-name=gdp-test + ... .items[*].metadata.name + ${logs}= Oc Logs ${pod} ${NAMESPACE} + Should Contain ${logs} Test successful diff --git a/test/suites/optional/strings.py b/test/suites/optional/strings.py new file mode 100644 index 0000000000..ec53258bcc --- /dev/null +++ b/test/suites/optional/strings.py @@ -0,0 +1,29 @@ +GDP_CONFIG_DROPIN = ''' +genericDevicePlugin: + status: Enabled + devices: + - name: fakeserial + groups: + - paths: + - path: /dev/ttyPipeB0 +''' + +CONFIGMAP_PREAMBLE = ''' +apiVersion: v1 +kind: ConfigMap +metadata: + name: gdp-script +data: + entrypoint.sh: | + #!/usr/bin/env bash + pip install pyserial + /script/fake-serial-communication.py pod + + fake-serial-communication.py: | +''' + + +def append_to_preamble(content: str) -> str: + # Add 4 spaces before each line + content = " " + content.replace("\n", "\n ") + return CONFIGMAP_PREAMBLE + content From 00479fd90a5cd4b5869bb9769ebca1613ffad833 Mon Sep 17 00:00:00 2001 From: Patryk Matuszak Date: Mon, 7 Jul 2025 10:15:43 +0200 Subject: [PATCH 2/3] Change the image to ubi9 --- .../generic-device-plugin/fake-serial-communication.py | 2 +- test/assets/generic-device-plugin/job.yaml | 2 +- test/suites/optional/generic-device-plugin.robot | 2 +- test/suites/optional/strings.py | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/assets/generic-device-plugin/fake-serial-communication.py b/test/assets/generic-device-plugin/fake-serial-communication.py index 93f0179ce9..f256b6349e 100755 --- a/test/assets/generic-device-plugin/fake-serial-communication.py +++ b/test/assets/generic-device-plugin/fake-serial-communication.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ This script simulates a simple serial communication between a host and a pod. diff --git a/test/assets/generic-device-plugin/job.yaml b/test/assets/generic-device-plugin/job.yaml index c101ecb0ab..8daeffac46 100644 --- a/test/assets/generic-device-plugin/job.yaml +++ b/test/assets/generic-device-plugin/job.yaml @@ -8,7 +8,7 @@ spec: restartPolicy: Never containers: - name: gdp-test - image: quay.io/fedora/python-311 + image: registry.access.redhat.com/ubi9/ubi:9.6 command: ["/bin/bash"] args: ["/script/entrypoint.sh", "pod"] resources: diff --git a/test/suites/optional/generic-device-plugin.robot b/test/suites/optional/generic-device-plugin.robot index ca8b2a5d71..9c8f21b905 100644 --- a/test/suites/optional/generic-device-plugin.robot +++ b/test/suites/optional/generic-device-plugin.robot @@ -24,7 +24,7 @@ Sanity Test Wait Until Device Is Allocatable - Command Should Work crictl pull quay.io/fedora/python-311 + Command Should Work crictl pull registry.access.redhat.com/ubi9/ubi:9.6 Start Script On Host Create Test Job diff --git a/test/suites/optional/strings.py b/test/suites/optional/strings.py index ec53258bcc..34e9f6e984 100644 --- a/test/suites/optional/strings.py +++ b/test/suites/optional/strings.py @@ -16,8 +16,10 @@ data: entrypoint.sh: | #!/usr/bin/env bash - pip install pyserial - /script/fake-serial-communication.py pod + # Fake user homedir for installing pip and pyserial. + HOME=/tmp python3 -m ensurepip --upgrade + HOME=/tmp python3 -m pip install pyserial + HOME=/tmp /script/fake-serial-communication.py pod fake-serial-communication.py: | ''' From 228222f478b7d427d0ff5d6671d5592ec73e1176 Mon Sep 17 00:00:00 2001 From: Patryk Matuszak Date: Mon, 7 Jul 2025 11:12:15 +0200 Subject: [PATCH 3/3] uname -i -> -m --- .../group2/rhel96-bootc-source-optionals.containerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile index 15fdbedff9..9abea74afc 100644 --- a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile +++ b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-optionals.containerfile @@ -30,7 +30,7 @@ RUN dnf repoinfo --enabled && \ # Prepare system for testing Generic Device Plugin. # hadolint ignore=DL3003 RUN KERNEL_VER=$(rpm -q --qf "%{VERSION}-%{RELEASE}" kernel); \ - KERNEL_VER_ARCH="${KERNEL_VER}.$(uname -i)"; \ + KERNEL_VER_ARCH="${KERNEL_VER}.$(uname -m)"; \ dnf install -y git make "kernel-devel-${KERNEL_VER}" python3-pyserial && \ dnf clean all && \ git clone https://github.com/pmtk/serialsim.git /tmp/serialsim && \