#!/usr/bin/env bash
# Boot the Cirros qcow2 under KVM with QMP and a monitor socket exposed.
#
# This is the v0 VM launcher for phase 2: validate that the orchestrator
# and host /proc collector work against a real qemu-system process. No
# host-only bridge yet, no exploit driver, no payload — just boot and
# idle. We add the bridge and exploit machinery in later phases.
#
# Run dir is exported so the orchestrator can read the qemu pid:
#   $RUN_DIR/qemu.pid
#   $RUN_DIR/qmp.sock
#   $RUN_DIR/monitor.sock

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
IMAGE="${IMAGE:-$REPO_ROOT/vm/images/alpine-baseline.qcow2}"
CIDATA="${CIDATA:-$REPO_ROOT/vm/images/cidata.iso}"
# SLOT lets the fleet runner spin up N concurrent VMs without socket /
# port collisions. Default RUN_DIR + ssh hostfwd port keep single-VM
# usage unchanged.
SLOT="${SLOT:-0}"
RUN_DIR="${RUN_DIR:-/tmp/cis490-vm-$SLOT}"
SSH_PORT="${SSH_PORT:-$((2222 + SLOT))}"
# When BRIDGE is set, attach a tap to the host-only bridge instead of
# using SLIRP usermode networking. The tap must already exist and be a
# member of the bridge — see vm/setup_bridge.sh + (operator) ip tuntap.
BRIDGE="${BRIDGE:-}"
TAP="${TAP:-cis490tap$SLOT}"

mkdir -p "$RUN_DIR"
QMP_SOCK="$RUN_DIR/qmp.sock"
MON_SOCK="$RUN_DIR/monitor.sock"
PID_FILE="$RUN_DIR/qemu.pid"

if [[ ! -f "$IMAGE" ]]; then
    echo "no image at $IMAGE" >&2
    exit 1
fi
if [[ ! -f "$CIDATA" ]]; then
    echo "no cidata at $CIDATA — build it with: uv run python tools/build_cidata.py $CIDATA" >&2
    exit 1
fi

AGENT_SOCK="$RUN_DIR/agent.sock"

# snapshot=on routes guest writes through a temporary overlay so the qcow2
# on disk is never mutated — every boot starts from the same bytes.
#
# Second virtio-serial port (cis490.guest.agent) carries telemetry
# from the in-guest agent. Surfaces inside the guest at
# /dev/virtio-ports/cis490.guest.agent and on the host at $AGENT_SOCK.
exec qemu-system-x86_64 \
    -name cis490-vm \
    -machine q35,accel=kvm \
    -cpu host \
    -smp 1,sockets=1,cores=1,threads=1 \
    -m 256 \
    -drive file="$IMAGE",format=qcow2,if=virtio,snapshot=on \
    -drive file="$CIDATA",format=raw,if=virtio,readonly=on \
    $(if [[ -n "$BRIDGE" ]]; then \
        echo -n "-netdev tap,id=n0,ifname=$TAP,script=no,downscript=no "; \
      else \
        echo -n "-netdev user,id=n0,hostfwd=tcp:127.0.0.1:$SSH_PORT-:22 "; \
      fi) \
    -device virtio-net-pci,netdev=n0 \
    -device virtio-serial-pci,id=cis490vs0 \
    -chardev socket,id=cis490agent,path="$AGENT_SOCK",server=on,wait=off \
    -device virtserialport,chardev=cis490agent,name=cis490.guest.agent \
    -nographic \
    -serial unix:"$RUN_DIR/serial.sock",server=on,wait=off \
    -monitor unix:"$MON_SOCK",server=on,wait=off \
    -qmp unix:"$QMP_SOCK",server=on,wait=off \
    -pidfile "$PID_FILE" \
    -display none
