From 9272096ab832d2364a0dbb3ddcb7ff5676873db4 Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Fri, 16 Aug 2024 18:29:34 +0200 Subject: [PATCH 1/5] tests: provide README Provide tests/README.md for usage instructions, when trying to reproduce the GitHub tests inside a local VM. --- tests/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/README.md diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..2417bb5 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,23 @@ +# Tests + +The `tests` directory provides scripts and configuration files which are used within [grml-debootstrap's GitHub actions](https://github.com/grml/grml-debootstrap/actions). + +> [!CAUTION] +> executing the scripts is potentially dangerous and may destroy the host system and/or any data. Run the tests only on throw-away systems and at your own risk. + +The scripts are **not** designed to be executed manually, though it's possible to run them inside a local Debian throw-away VM. + +> [!NOTE] +> make sure to have at least 8GB disk space and 2GB memory available on your VM. + +Execute the following steps to build a Debian VM image (`qemu.img`) and run the tests against it: + +``` +sudo apt install git docker.io +git clone https://github.com/grml/grml-debootstrap +cd grml-debootstrap +sudo ./tests/docker-build-deb.sh --autobuild 01 +sudo ./tests/build-vm-and-test.sh setup +sudo ./tests/build-vm-and-test.sh run +sudo ./tests/build-vm-and-test.sh test +``` From bffadf3ac9bfd722f6177e8dbf0ccd11fb9333fd Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Sat, 17 Aug 2024 21:20:45 +0200 Subject: [PATCH 2/5] tests/build-vm-and-test.sh: install curl Our tests/build-vm-and-test.sh script relies on presence of curl command, so ensure it's available. --- tests/build-vm-and-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/build-vm-and-test.sh b/tests/build-vm-and-test.sh index 53076ac..1fb604d 100755 --- a/tests/build-vm-and-test.sh +++ b/tests/build-vm-and-test.sh @@ -32,9 +32,9 @@ if [ ! -d ./tests ]; then fi if [ "$1" == "setup" ]; then - [ -x ./tests/goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)/tests" sh sudo apt-get update - sudo apt-get -qq -y install qemu-system-x86 kpartx python3-pexpect python3-serial + sudo apt-get -qq -y install curl qemu-system-x86 kpartx python3-pexpect python3-serial + [ -x ./tests/goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)/tests" sh # TODO: docker.io exit 0 fi From 95bd689a525c8681f514cc869bcff254227db3d0 Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Sat, 17 Aug 2024 21:21:13 +0200 Subject: [PATCH 3/5] tests/serial-console-connection: use python3 in shebang We need to replace `/usr/bin/env python` with `/usr/bin/env python3` as /usr/bin/python is provided only by the python-is-python3 or python-is-python2 packages through a symlink (meant for third-party or legacy scripts, see https://wiki.debian.org/Python), though those might not be present e.g. when running in a local Debian bookworm VM. --- tests/serial-console-connection | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serial-console-connection b/tests/serial-console-connection index b44299a..14a9c2e 100755 --- a/tests/serial-console-connection +++ b/tests/serial-console-connection @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import argparse import serial import sys From 844419c1962f2548cde63cb483d40f2a5e5e8d47 Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Sat, 17 Aug 2024 21:21:24 +0200 Subject: [PATCH 4/5] tests/serial-console-connection: update default hostname For bookworm. --- tests/serial-console-connection | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serial-console-connection b/tests/serial-console-connection index 14a9c2e..40660f6 100755 --- a/tests/serial-console-connection +++ b/tests/serial-console-connection @@ -15,7 +15,7 @@ parser.add_argument( help="serial console device to connect " + "to (e.g. /dev/pts/X)", ) parser.add_argument( - "--hostname", default="buster", help="hostname of the system for login process" + "--hostname", default="bookworm", help="hostname of the system for login process" ) parser.add_argument("--user", default="root", help="user name to use for login") parser.add_argument("--password", default="grml", help="password for login") From 13e2a3931b661c41117c9ed535fe399fafcf1c6f Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Sat, 17 Aug 2024 14:14:08 +0200 Subject: [PATCH 5/5] tests: Try to capture screenshot via VNC if serial-console-connection fails While debugging the failing GitHub Actions (see #278), we noticed that it might serve useful to have a screenshot of the booted system available. We can capture such a screenshot via vncsnapshot. NOTE: we move the files inside `results` only if the directory as such exists in $PWD, otherwise we'd fail the build when being executed as `tests/build-vm-and-test.sh test` from inside the grml-debootstrap.git. This happens when manually reproducing the GH tests, though then `build-vm-and-test.sh` is supposed to be executed from the parent directory of the `tests` directory (being the grml-debootstrap.git checkout). --- .github/workflows/test-build.yml | 1 + tests/build-vm-and-test.sh | 2 ++ tests/serial-console-connection | 25 +++++++++++++++++++++++++ tests/test-vm.sh | 13 +++++++++++-- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 03d7994..b1a0e2f 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -99,6 +99,7 @@ jobs: - name: Archive VM test results uses: actions/upload-artifact@v4 + if: always() with: name: vm-results-${{matrix.host_release}}-${{matrix.release}}-${{matrix.debootstrap}} if-no-files-found: error diff --git a/tests/build-vm-and-test.sh b/tests/build-vm-and-test.sh index 1fb604d..c88c6c5 100755 --- a/tests/build-vm-and-test.sh +++ b/tests/build-vm-and-test.sh @@ -34,6 +34,8 @@ fi if [ "$1" == "setup" ]; then sudo apt-get update sudo apt-get -qq -y install curl qemu-system-x86 kpartx python3-pexpect python3-serial + # vncsnapshot might not be available, though we don't want to abort execution then + sudo apt-get -qq -y install vncsnapshot || true [ -x ./tests/goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)/tests" sh # TODO: docker.io exit 0 diff --git a/tests/serial-console-connection b/tests/serial-console-connection index 40660f6..30e6bb8 100755 --- a/tests/serial-console-connection +++ b/tests/serial-console-connection @@ -1,6 +1,9 @@ #!/usr/bin/env python3 import argparse import serial +import os +import shutil +import subprocess import sys import time from pexpect import fdpexpect @@ -25,6 +28,11 @@ parser.add_argument( type=int, help="Maximum time for finding the login prompt, in seconds", ) +parser.add_argument( + "--screenshot", + default="screenshot.jpg", + help="file name for screenshot captured via VNC on error", +) parser.add_argument( "--tries", default="12", @@ -74,6 +82,21 @@ def login(ser, hostname, user, password, timeout=5): child.expect("%s@%s" % (user, hostname), timeout=timeout) +def capture_vnc_screenshot(screenshot_file): + if not shutil.which("vncsnapshot"): + print("WARN: vncsnapshot not available, skipping vnc snapshot capturing.") + return + + print("Trying to capture screenshot via vncsnapshot to", screenshot_file) + + proc = subprocess.Popen(["vncsnapshot", "localhost", screenshot_file]) + proc.wait() + if proc.returncode != 0: + print("WARN: failed to capture vnc snapshot :(") + else: + print("Screenshot file '%s' available" % os.path.abspath(screenshot_file)) + + def main(): args = parser.parse_args() hostname = args.hostname @@ -81,6 +104,7 @@ def main(): port = args.port user = args.user commands = args.command + screenshot_file = args.screenshot ser = serial.Serial(port, 115200) ser.flushInput() @@ -116,6 +140,7 @@ def main(): # after poweroff, the serial device will probably vanish. do not attempt reading from it anymore. if not success: + capture_vnc_screenshot(screenshot_file) sys.exit(1) diff --git a/tests/test-vm.sh b/tests/test-vm.sh index 85e46c5..969709d 100755 --- a/tests/test-vm.sh +++ b/tests/test-vm.sh @@ -114,12 +114,14 @@ if [ "$success" = "0" ] ; then exit 1 fi +RC=0 "$TEST_PWD"/tests/serial-console-connection \ --tries 180 \ + --screenshot "$TEST_PWD/tests/screenshot.jpg" \ --port "$serial_port" \ --hostname "$VM_HOSTNAME" \ --poweroff \ - "mount -t 9p -o trans=virtio,version=9p2000.L,rw $MOUNT_TAG /mnt && cd /mnt && ./testrunner" + "mount -t 9p -o trans=virtio,version=9p2000.L,rw $MOUNT_TAG /mnt && cd /mnt && ./testrunner" || RC=$? if [ ! -d results ] || [ ! -f ./results/goss.tap ] || [ ! -f ./results/goss.exitcode ]; then echo "Running tests inside VM failed for unknown reason" >&2 @@ -133,7 +135,14 @@ fi echo "Finished serial console connection [timeout=${timeout}]." -mv results/* "$TESTS_RESULTSDIR/" +# in case of errors we might have captured a screenshot via VNC +if [ -r "${TEST_PWD}"/tests/screenshot.jpg ] ; then + cp "${TEST_PWD}"/tests/screenshot.jpg "${TESTS_RESULTSDIR}" +fi + +if [ -d results ] ; then + mv results/* "$TESTS_RESULTSDIR/" +fi bailout $RC