#!/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)" export BO_OVERLAY="$overlay" BO_MEM="$MEM_MB" BO_SMP="$SMP" \ BO_TIMEOUT="$BOOT_TIMEOUT" BO_CMD="$CMD" expect -c ' set timeout $env(BO_TIMEOUT) set overlay $env(BO_OVERLAY) set mem $env(BO_MEM) set smp $env(BO_SMP) set cmd $env(BO_CMD) 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 autologin on serial"; exit 2 } "automatic login" {} } sleep 6 send "echo NINA_SMOKE_BEGIN\r" expect { timeout { puts "\n!! shell not ready"; exit 3 } "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 ' echo "=== overlay discarded; golden image unchanged ==="