166 lines
4.2 KiB
Bash
Executable file
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"
|