clawdie-iso/scripts/bhyve-test.sh
Sam & Claude 60c35361a0 Make ISO builds cleaner by default (Sam & Codex)
---

Build: FAIL | Tests: FAIL — not run (deferred)
2026-06-04 20:04:22 +02:00

166 lines
4.2 KiB
Bash
Executable file

#!/bin/sh
# Setup and boot Clawdie-ISO in bhyve VM
# Usage: bhyve-test.sh [ISO_PATH] [--name VM_NAME]
#
# Network isolation: each VM gets its own tap interface on a dedicated
# bhyve0 bridge (10.99.0.0/24), separate from warden0 (jail bridge).
# The script creates bhyve0. PF is not modified by this test harness.
set -eu
VM_NAME="${BHYVE_VM_NAME:-clawdie-test}"
VM_DIR="/var/bhyve/$VM_NAME"
DISK_SIZE="25G"
MEM="2G"
CPUS="2"
ISO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
ISO_OUTPUT_DIR="${ISO_DIR}/tmp/output"
# bhyve network — isolated from warden0 (jail bridge)
BHYVE_BRIDGE="bhyve0"
BHYVE_BRIDGE_IP="10.99.0.1"
BHYVE_NET="10.99.0.0/24"
# Guardrail: bhyve inside a VM is unstable without nested VT-x.
if command -v sysctl >/dev/null 2>&1; then
VM_GUEST="$(sysctl -n kern.vm_guest 2>/dev/null || true)"
if [ -n "$VM_GUEST" ] && [ "$VM_GUEST" != "none" ]; then
echo "ERROR: bhyve test requires bare metal or nested VT-x enabled."
echo "Detected virtualized host: $VM_GUEST"
exit 1
fi
fi
# Parse args
ISO=""
while [ $# -gt 0 ]; do
case "$1" in
--name) VM_NAME="$2"; VM_DIR="/var/bhyve/$VM_NAME"; shift 2 ;;
*) ISO="$1"; shift ;;
esac
done
# Auto-detect newest baremetal image if no ISO given
if [ -z "$ISO" ]; then
if [ -d "$ISO_OUTPUT_DIR" ]; then
ISO="$(ls -t "${ISO_OUTPUT_DIR}"/clawdie-iso-baremetal-*.img 2>/dev/null | head -1)"
fi
if [ -z "$ISO" ]; then
ISO="$(ls -t "${ISO_DIR}"/clawdie-iso-baremetal-*.img 2>/dev/null | head -1)"
fi
fi
if [ -z "$ISO" ] || [ ! -f "$ISO" ]; then
echo "ERROR: No ISO found. Pass path as argument or place a"
echo " clawdie-iso-baremetal-*.img in ${ISO_OUTPUT_DIR}/"
exit 1
fi
ISO="$(realpath "$ISO")"
echo "=== Clawdie-ISO bhyve Test Setup ==="
echo ""
# Cleanup old VM if exists
if bhyvectl --vm="$VM_NAME" --get-stats >/dev/null 2>&1; then
echo "Destroying old VM: $VM_NAME"
bhyvectl --vm="$VM_NAME" --destroy 2>/dev/null || true
fi
# Create VM directory
mkdir -p "$VM_DIR"
cd "$VM_DIR"
# Create disk image (sparse — only uses what's written)
if [ ! -f disk.img ]; then
echo "Creating ${DISK_SIZE} virtual disk (sparse)..."
truncate -s "$DISK_SIZE" disk.img
else
echo "Reusing existing disk.img"
fi
# ── Network: dedicated bhyve bridge ────────────────────────────────────────
# Cleanup tap on exit
cleanup() {
if [ -n "${TAP:-}" ]; then
ifconfig "$BHYVE_BRIDGE" deletem "$TAP" 2>/dev/null || true
ifconfig "$TAP" destroy 2>/dev/null || true
fi
}
trap cleanup EXIT
# Create bhyve0 bridge if it doesn't exist
if ! ifconfig "$BHYVE_BRIDGE" >/dev/null 2>&1; then
echo "Creating ${BHYVE_BRIDGE} bridge at ${BHYVE_BRIDGE_IP}/24..."
ifconfig bridge create name "$BHYVE_BRIDGE" >/dev/null
ifconfig "$BHYVE_BRIDGE" inet "$BHYVE_BRIDGE_IP" netmask 255.255.255.0
ifconfig "$BHYVE_BRIDGE" up
else
echo "Bridge ${BHYVE_BRIDGE} already exists"
fi
# Pick a tap interface that isn't already in use
TAP_ID=0
while ifconfig "tap${TAP_ID}" >/dev/null 2>&1; do
TAP_ID=$((TAP_ID + 1))
done
TAP="tap${TAP_ID}"
echo "Creating ${TAP} interface..."
ifconfig "$TAP" create up
echo "Adding ${TAP} to ${BHYVE_BRIDGE} bridge..."
ifconfig "$BHYVE_BRIDGE" addm "$TAP"
# Locate UEFI bootrom
BOOTROM="/usr/local/share/uefi-firmware/BHYVE_UEFI.fd"
if [ ! -f "$BOOTROM" ]; then
BOOTROM="/usr/local/share/edk2-bhyve/BHYVE_UEFI.fd"
fi
if [ ! -f "$BOOTROM" ]; then
echo "ERROR: UEFI bootrom not found"
exit 1
fi
# Boot parameters
echo ""
echo "Starting VM boot sequence..."
echo " VM Name: $VM_NAME"
echo " Disk: $VM_DIR/disk.img ($DISK_SIZE)"
echo " ISO: $ISO"
echo " Memory: $MEM"
echo " CPUs: $CPUS"
echo " Network: ${TAP} -> ${BHYVE_BRIDGE} (${BHYVE_NET})"
echo ""
echo " Guest should use:"
echo " IP: 10.99.0.2/24"
echo " Gateway: ${BHYVE_BRIDGE_IP}"
echo " DNS: 1.1.1.1"
echo ""
echo "Booting... (30 min timeout)"
echo ""
# Boot VM from ISO
timeout 1800 bhyve \
-A -H -P \
-m "$MEM" \
-c "$CPUS" \
-s 0:0,hostbridge \
-s 1:0,ahci-hd,disk.img \
-s 2:0,ahci-cd,"$ISO" \
-s 3:0,virtio-net,"$TAP" \
-l bootrom,"$BOOTROM" \
-l com1,stdio \
"$VM_NAME"
exit_code=$?
# Cleanup tap on exit
echo ""
echo "Boot sequence complete. Cleaning up ${TAP}..."
cleanup
echo "Done."
exit "$exit_code"