Files
kubesolo-os/hack/dev-vm.sh
Adolfo Delorenzo d9ac58418d
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
CI / Shellcheck (push) Has been cancelled
fix: macOS dev VM, CA certs, DNS fallback, Portainer Edge integration
- dev-vm.sh: rewrite for macOS (bsdtar ISO extraction, Homebrew mkfs.ext4
  detection, direct kernel boot, TCG acceleration, port 8080 forwarding)
- inject-kubesolo.sh: add CA certificates bundle from builder so containerd
  can verify TLS when pulling from registries (Docker Hub, etc.)
- 50-network.sh: add DNS fallback (10.0.2.3 + 8.8.8.8) when DHCP client
  doesn't populate /etc/resolv.conf
- 90-kubesolo.sh: serve kubeconfig via HTTP on port 8080 for reliable
  retrieval from host, add 127.0.0.1 and 10.0.2.15 to API server SANs
- portainer.go: add headless Service to Edge Agent manifest (required for
  agent peer discovery DNS lookup)
- 10-parse-cmdline.sh + init.sh: add kubesolo.edge_id/edge_key boot params
- 20-persistent-mount.sh: auto-format unformatted data disks on first boot
- hack/fix-portainer-service.sh: helper to patch running cluster

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 02:11:31 -06:00

151 lines
5.1 KiB
Bash
Executable File

#!/bin/bash
# dev-vm.sh — Launch a QEMU VM for development and testing
# Usage: ./hack/dev-vm.sh [path-to-iso-or-img] [--shell] [--debug]
#
# Works on both Linux (with KVM) and macOS (TCG emulation).
# On macOS/Apple Silicon, x86_64 guests run under TCG (~5-15x slower than KVM).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
VERSION="$(cat "$PROJECT_ROOT/VERSION")"
ROOTFS_DIR="${ROOTFS_DIR:-$PROJECT_ROOT/build/rootfs-work}"
DEFAULT_ISO="$PROJECT_ROOT/output/kubesolo-os-${VERSION}.iso"
DEFAULT_IMG="$PROJECT_ROOT/output/kubesolo-os-${VERSION}.img"
IMAGE=""
EXTRA_APPEND=""
# Parse all arguments — flags and optional image path
for arg in "$@"; do
case "$arg" in
--shell) EXTRA_APPEND="$EXTRA_APPEND kubesolo.shell" ;;
--debug) EXTRA_APPEND="$EXTRA_APPEND kubesolo.debug" ;;
--edge-id=*) EXTRA_APPEND="$EXTRA_APPEND kubesolo.edge_id=${arg#--edge-id=}" ;;
--edge-key=*) EXTRA_APPEND="$EXTRA_APPEND kubesolo.edge_key=${arg#--edge-key=}" ;;
*) IMAGE="$arg" ;;
esac
done
# Auto-detect image
if [ -z "$IMAGE" ]; then
if [ -f "$DEFAULT_ISO" ]; then
IMAGE="$DEFAULT_ISO"
elif [ -f "$DEFAULT_IMG" ]; then
IMAGE="$DEFAULT_IMG"
else
echo "ERROR: No image found. Run 'make iso' or 'make disk-image' first."
echo " Or specify path: $0 <path-to-iso-or-img>"
exit 1
fi
fi
echo "==> Launching QEMU with: $IMAGE"
echo " Press Ctrl+A, X to exit"
echo ""
DATA_APPEND=""
DATA_DISK=""
# Find mkfs.ext4 (Homebrew on macOS installs to a non-PATH location)
MKFS_EXT4=""
if command -v mkfs.ext4 >/dev/null 2>&1; then
MKFS_EXT4="mkfs.ext4"
elif [ -x "/opt/homebrew/opt/e2fsprogs/sbin/mkfs.ext4" ]; then
MKFS_EXT4="/opt/homebrew/opt/e2fsprogs/sbin/mkfs.ext4"
elif [ -x "/usr/local/opt/e2fsprogs/sbin/mkfs.ext4" ]; then
MKFS_EXT4="/usr/local/opt/e2fsprogs/sbin/mkfs.ext4"
fi
# Create and attach a formatted data disk for persistent K8s state.
if [ -n "$MKFS_EXT4" ]; then
DATA_DISK="$(mktemp /tmp/kubesolo-data-XXXXXX).img"
dd if=/dev/zero of="$DATA_DISK" bs=1M count=2048 2>/dev/null
"$MKFS_EXT4" -q -L KSOLODATA "$DATA_DISK" 2>/dev/null
DATA_APPEND="kubesolo.data=/dev/vda"
echo " Data disk: 2 GB ext4 (persistent)"
else
echo "ERROR: mkfs.ext4 not found. Install e2fsprogs:"
echo " brew install e2fsprogs"
exit 1
fi
EXTRACT_DIR=""
cleanup() {
[ -n "$DATA_DISK" ] && rm -f "$DATA_DISK" "${DATA_DISK%.img}"
[ -n "$EXTRACT_DIR" ] && rm -rf "$EXTRACT_DIR"
}
trap cleanup EXIT
# Build QEMU command
QEMU_ARGS=(-m 2048 -smp 2 -nographic -cpu max)
QEMU_ARGS+=(-net nic,model=virtio)
QEMU_ARGS+=(-net user,hostfwd=tcp::6443-:6443,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:8080)
if [ -n "$DATA_DISK" ]; then
QEMU_ARGS+=(-drive "file=$DATA_DISK,format=raw,if=virtio")
fi
# Enable KVM on Linux, fall back to TCG everywhere else
if [ -w /dev/kvm ] 2>/dev/null; then
QEMU_ARGS+=(-accel kvm)
echo " KVM acceleration: enabled"
else
QEMU_ARGS+=(-accel tcg)
echo " TCG emulation (no KVM — expect slower boot)"
fi
case "$IMAGE" in
*.iso)
# -append only works with -kernel, not -cdrom.
# Extract kernel + initramfs and use direct kernel boot.
VMLINUZ=""
INITRAMFS=""
# Prefer build artifacts if present (no extraction needed)
if [ -f "$ROOTFS_DIR/vmlinuz" ] && [ -f "$ROOTFS_DIR/kubesolo-os.gz" ]; then
VMLINUZ="$ROOTFS_DIR/vmlinuz"
INITRAMFS="$ROOTFS_DIR/kubesolo-os.gz"
echo " Using kernel/initramfs from build directory"
else
# Extract from ISO using bsdtar (works on macOS + Linux, no mount needed)
EXTRACT_DIR="$(mktemp -d /tmp/kubesolo-extract-XXXXXX)"
echo " Extracting kernel/initramfs from ISO..."
bsdtar -xf "$IMAGE" -C "$EXTRACT_DIR" boot/vmlinuz boot/kubesolo-os.gz 2>/dev/null || {
echo "ERROR: Failed to extract kernel/initramfs from ISO."
echo " Ensure bsdtar is available (ships with macOS, install libarchive on Linux)."
echo " Or run 'make rootfs initramfs' to produce build artifacts."
exit 1
}
VMLINUZ="$EXTRACT_DIR/boot/vmlinuz"
INITRAMFS="$EXTRACT_DIR/boot/kubesolo-os.gz"
if [ ! -f "$VMLINUZ" ] || [ ! -f "$INITRAMFS" ]; then
echo "ERROR: ISO does not contain expected boot/vmlinuz and boot/kubesolo-os.gz"
echo " ISO contents:"
bsdtar -tf "$IMAGE" 2>/dev/null || true
exit 1
fi
echo " Extracted kernel/initramfs from ISO"
fi
qemu-system-x86_64 \
"${QEMU_ARGS[@]}" \
-kernel "$VMLINUZ" \
-initrd "$INITRAMFS" \
-append "console=ttyS0,115200n8 $DATA_APPEND $EXTRA_APPEND"
;;
*.img)
qemu-system-x86_64 \
"${QEMU_ARGS[@]}" \
-drive "file=$IMAGE,format=raw,if=virtio"
;;
*)
echo "ERROR: Unrecognized image format: $IMAGE"
exit 1
;;
esac