#!/usr/bin/env bash # Boot a THROWAWAY copy-on-write overlay of the golden image, run commands over # the serial console, then discard the overlay. The golden image is never # mutated, so every boot starts from the exact same snapshot. # # Usage: boot-overlay.sh [command ...] # With no command, runs a nina smoke test (help / hello / status). # Tunables via env: MEM_MB (2048), SMP (2), BOOT_TIMEOUT (600) set -euo pipefail GOLDEN="${1:?usage: boot-overlay.sh [command...]}" shift || true MEM_MB="${MEM_MB:-2048}" SMP="${SMP:-2}" BOOT_TIMEOUT="${BOOT_TIMEOUT:-600}" [ -f "$GOLDEN" ] || { echo "missing golden: $GOLDEN" >&2; exit 1; } if [ "$#" -gt 0 ]; then CMD="$*"; else CMD='/root/nina help; echo ---; /root/nina hello; echo ---; /root/nina --version 2>/dev/null || true' fi work="$(mktemp -d)" trap 'rm -rf "$work"' EXIT overlay="$work/overlay.qcow2" qemu-img create -f qcow2 -b "$(cd "$(dirname "$GOLDEN")" && pwd)/$(basename "$GOLDEN")" -F qcow2 "$overlay" >/dev/null echo "throwaway overlay: $overlay (backing: $GOLDEN)" expect -c ' set timeout [lindex $argv 3] set overlay [lindex $argv 0] set mem [lindex $argv 1] set smp [lindex $argv 2] set cmd [lindex $argv 4] spawn qemu-system-x86_64 \ -machine q35 -accel tcg -cpu max -smp $smp -m $mem \ -drive file=$overlay,if=virtio,format=qcow2 \ -netdev user,id=n0 -device virtio-net-pci,netdev=n0 \ -nographic expect { timeout { puts "\n!! no login on serial"; exit 2 } -re {\[root@test-primary[^\]]*\]#} {} -re {login:} { send "root\r"; exp_continue } } send "\r" expect -re {\[root@test-primary[^\]]*\]#} send "echo NINA_SMOKE_BEGIN\r" expect "NINA_SMOKE_BEGIN" send "$cmd\r" send "echo NINA_SMOKE_END_RC=\$?\r" expect { timeout { puts "\n!! command timed out"; exit 3 } -re {NINA_SMOKE_END_RC=[0-9]+} {} } send "poweroff\r" set timeout 120 expect eof ' "$overlay" "$MEM_MB" "$SMP" "$BOOT_TIMEOUT" "$CMD" echo "=== overlay discarded; golden image unchanged ==="