#!/usr/bin/env bash set -Euo pipefail # ----------------------------------------------------------------------------- # This script sets up and launches (or stops) a QEMU virtual machine with OVMF. # # Usage: # ./run-vm.sh [install] # starts (and backgrounds) the VM; use "install" to attach the ISO # ./run-vm.sh stop # kills the running QEMU VM (reads PID from .vm/qemu.pid) # ----------------------------------------------------------------------------- # Paths to OVMF firmware (pflash) OVMF_CODE="/run/libvirt/nix-ovmf/OVMF_CODE.fd" OVMF_VARS_DEFAULT="/run/libvirt/nix-ovmf/OVMF_VARS.fd" # Determine where this script lives and compute related paths SCRIPT_DIR=$(dirname "$(readlink -f "$0")") TARGET_DIR=$(readlink -f "$SCRIPT_DIR/../.vm") OVMF_VARS_PATH="$TARGET_DIR/OVMF_VARS-myvm.fd" IMG_PATH="$TARGET_DIR/disk.img" ISO_DIR=$(readlink -f "$SCRIPT_DIR/../iso/result/iso") PID_FILE="$TARGET_DIR/qemu.pid" # If first argument is "stop", then kill the running VM and exit: if [ "${1-}" = "stop" ]; then if [ -f "$PID_FILE" ]; then VM_PID=$(<"$PID_FILE") if kill -0 "$VM_PID" 2>/dev/null; then echo "Killing QEMU (PID $VM_PID)..." kill "$VM_PID" # Optionally wait for it to die: wait "$VM_PID" 2>/dev/null || true echo "✅ VM stopped." rm -f "$PID_FILE" exit 0 else echo "⚠️ No running QEMU process with PID $VM_PID. Removing stale PID file." rm -f "$PID_FILE" exit 1 fi else echo "⚠️ No PID file found at $PID_FILE. Is the VM running?" exit 1 fi fi echo echo "============================================================" echo " QEMU VM Setup and Launch Script" echo "============================================================" echo # ----------------------------------------------------------------------------- # 1. Locate the ISO file # ----------------------------------------------------------------------------- echo "[1/6] Locating ISO file in: $ISO_DIR" ISO_FILE=$(ls "$ISO_DIR"/*.iso 2>/dev/null | head -n 1 || true) if [ -z "$ISO_FILE" ]; then echo " ❌ Error: No ISO found in $ISO_DIR" echo " Please verify the directory and try again." exit 1 else echo " ✅ Found ISO: $ISO_FILE" fi echo # ----------------------------------------------------------------------------- # 2. Ensure target VM directory exists # ----------------------------------------------------------------------------- echo "[2/6] Checking VM target directory: $TARGET_DIR" if [ ! -d "$TARGET_DIR" ]; then echo " 📁 Directory does not exist; creating: $TARGET_DIR" mkdir -p "$TARGET_DIR" echo " ✅ Directory created." else echo " ✅ Directory already exists." fi echo # ----------------------------------------------------------------------------- # 3. Prepare OVMF variables file (OVMF_VARS-myvm.fd) # ----------------------------------------------------------------------------- echo "[3/6] Preparing OVMF variables file" if [ ! -f "$OVMF_VARS_PATH" ]; then echo " Copying default vars to: $OVMF_VARS_PATH" cp "$OVMF_VARS_DEFAULT" "$OVMF_VARS_PATH" chmod 600 "$OVMF_VARS_PATH" echo " ✅ OVMF_VARS-myvm.fd created and permissions set." else echo " ✅ OVMF_VARS-myvm.fd already exists." fi echo # ----------------------------------------------------------------------------- # 4. Create QCOW2 disk image if missing # ----------------------------------------------------------------------------- echo "[4/6] Ensuring QCOW2 disk image exists at: $IMG_PATH" if [ ! -f "$IMG_PATH" ]; then echo " 💾 Creating a new 64G QCOW2 image..." qemu-img create -f qcow2 "$IMG_PATH" "64G" echo " ✅ Disk image created: $IMG_PATH (64G)" else echo " ✅ Disk image already exists." fi echo # ----------------------------------------------------------------------------- # 5. Parse arguments (install mode or normal boot) # ----------------------------------------------------------------------------- INSTALL_MODE=0 if [ "${1-}" = "install" ]; then INSTALL_MODE=1 fi if [ "$INSTALL_MODE" -eq 1 ]; then echo "[5/6] Install mode enabled: CD-ROM will be attached" CDROM_OPTS="-drive file=\"$ISO_FILE\",format=raw,if=none,media=cdrom,id=cd1,readonly=on \ -device ahci,id=ahci0 -device ide-cd,bus=ahci0.0,drive=cd1,bootindex=1" else echo "[5/6] Normal boot mode: No CD-ROM attached" CDROM_OPTS="" fi echo # ----------------------------------------------------------------------------- # 6. Launch QEMU (in the background) # ----------------------------------------------------------------------------- echo "[6/6] Launching QEMU VM now (in background)..." echo "------------------------------------------------------------" echo " • Machine: q35, KVM acceleration" echo " • Memory: 4096 MB" echo " • CPU: host" echo " • OVMF_CODE (readonly): $OVMF_CODE" echo " • OVMF_VARS: $OVMF_VARS_PATH" echo " • Disk image: $IMG_PATH" if [ "$INSTALL_MODE" -eq 1 ]; then echo " • CD-ROM (ISO): $ISO_FILE" fi echo " • Networking: user-mode with hostfwd ssh (host:2222 → guest:22)" echo " • Connect to VM via: ssh -p 2222 root@localhost" echo " • VGA: virtio" echo "------------------------------------------------------------" echo # Construct network options NET_OPTS="-netdev user,id=net0,hostfwd=tcp::2222-:22 -device e1000,netdev=net0" # Run QEMU in the background and store its PID eval qemu-system-x86_64 \ -machine type=q35,accel=kvm \ -m 4096 \ -cpu host \ \ -drive if=pflash,format=raw,readonly=on,file="$OVMF_CODE" \ \ -drive if=pflash,format=raw,file="$OVMF_VARS_PATH" \ \ -drive file="$IMG_PATH",format=qcow2 \ \ $CDROM_OPTS \ \ $NET_OPTS \ -vga virtio \ & VM_PID=$! echo "$VM_PID" > "$PID_FILE" echo "✅ QEMU started with PID $VM_PID. PID file: $PID_FILE" echo echo "To stop the VM at any time, run:" echo " $0 stop" echo exit 0