From c235cb62beefd03087e7cfc7f7f55f0c7c6601c9 Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 1 Aug 2026 00:00:00 +0000 Subject: Enter vmm A QEMU/KVM virtual machine manager in one POSIX shell script. Each VM is a directory of plain files under $VMMDIR, configured by a hand-edited KEY=VALUE file that is parsed rather than sourced, so nothing in it can inject a raw QEMU argument. Control is a QMP FIFO pair inside that directory, guarded by its permissions alone; nothing binds a TCP port. The tests are TAP without a framework and boot real guests where the host allows. --- tests/argv | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 tests/argv (limited to 'tests/argv') diff --git a/tests/argv b/tests/argv new file mode 100644 index 0000000..628d621 --- /dev/null +++ b/tests/argv @@ -0,0 +1,151 @@ +# The QEMU argv, as printed by dryrun. + +"$VMM" create av1 64M >/dev/null 2>&1 +IMG=$VMMDIR/av1/disk.qcow2 + +cfg av1 </dev/null 2>&1 +out=$(VMMDIR="$COMMA_DIR" "$VMM" dryrun avc 2>&1) && got=0 || got=$? +if [ "$got" = 0 ] && printf '%s\n' "$out" | grep -q 'vms,,comma'; then + ok "a comma in VMMDIR is escaped" +else + notok "a comma in VMMDIR is escaped" "exit $got: $out" +fi + +: > "$VMMDIR/av1/config" + +# Two VMs must not share a MAC. +"$VMM" create av2 64M >/dev/null 2>&1 +m1=$("$VMM" dryrun av1 2>/dev/null | sed -n 's/.*mac=\([0-9a-f:]*\).*/\1/p') +m2=$("$VMM" dryrun av2 2>/dev/null | sed -n 's/.*mac=\([0-9a-f:]*\).*/\1/p') +if [ -n "$m1" ] && [ "$m1" != "$m2" ]; then + ok "each VM gets its own MAC" +else + notok "each VM gets its own MAC" "av1=$m1 av2=$m2" +fi + +# dryrun output must be pasteable, so every argument is single quoted. +outputs "'node-name=disk0f,driver=file,filename=$IMG" \ + "dryrun shell-quotes its argv" dryrun av1 + +# A malformed uuid must never reach QEMU or be silently regenerated. +cp "$VMMDIR/av1/uuid" "$WORK/uuid.bak" +: > "$VMMDIR/av1/uuid" +refuses 'uuid is missing or malformed' "an empty uuid is refused" dryrun av1 +refuses 'uuid is missing or malformed' "start does not repair an empty uuid" start av1 +holds "a refused start leaves the empty uuid untouched" \ + test ! -s "$VMMDIR/av1/uuid" +printf 'zzzzzzzz-1111-2222-3333-444444444444\n' > "$VMMDIR/av1/uuid" +refuses 'uuid is missing or malformed' "a non-hex uuid is refused" dryrun av1 +printf '12345678-1111-2222-3333-44444444444z\n' > "$VMMDIR/av1/uuid" +refuses 'uuid is missing or malformed' "every uuid group is validated" dryrun av1 +cp "$WORK/uuid.bak" "$VMMDIR/av1/uuid" + +# Graphics means a display and an absolute pointer. Guest agents and +# clipboard sharing are separate policy and do not belong on this argv. +cfg av1 < "$VMMDIR/av1/config" + +# dryrun launches nothing, so it must work on a host with no qemu at all. +# The README promises it as a config checker anywhere. +BIN=$WORK/dryrun-bin +mkdir -p "$BIN" +for b in uname cat sed tr grep od awk; do + ln -sf "$(command -v "$b")" "$BIN/$b" +done +holds "dryrun works with no qemu installed" \ + env PATH="$BIN" "$VMM" dryrun av1 + +# What dryrun prints is what start runs, so the printed argv must boot a +# guest vmm then recognises as that VM. The CDROM path carries a comma, +# which reaches QEMU whole only if the doubling is right. +if command -v "qemu-system-$(uname -m)" >/dev/null 2>&1; then + : > "$WORK/comma,name.iso" + "$VMM" create av3 64M >/dev/null 2>&1 + cfg av3 < "$WORK/av3.sh" + sh "$WORK/av3.sh" > "$WORK/av3.out" 2>&1 & + pasted=$! + i=0 + while [ ! -s "$VMMDIR/av3/pid" ] && [ "$i" -lt 15 ]; do + sleep 1 + i=$((i + 1)) + done + out=$("$VMM" status av3 2>&1) && got=0 || got=$? + if [ "$got" = 0 ]; then + ok "the argv dryrun prints boots a guest vmm knows" + else + notok "the argv dryrun prints boots a guest vmm knows" \ + "status exit $got: $out" "$(tail -n 5 "$WORK/av3.out")" + fi + exits 0 "and vmm stops what dryrun started" kill av3 + wait "$pasted" 2>/dev/null || : +else + skip 2 "no qemu for the host architecture" +fi -- cgit v1.2.3