Files

175 lines
5.8 KiB
Bash
Executable File

#!/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