Files
kubesolo-os/test/qemu/run-vm.sh
Adolfo Delorenzo e372df578b feat: initial Phase 1 PoC scaffolding for KubeSolo OS
Complete Phase 1 implementation of KubeSolo OS — an immutable, bootable
Linux distribution built on Tiny Core Linux for running KubeSolo
single-node Kubernetes.

Build system:
- Makefile with fetch, rootfs, initramfs, iso, disk-image targets
- Dockerfile.builder for reproducible builds
- Scripts to download Tiny Core, extract rootfs, inject KubeSolo,
  pack initramfs, and create bootable ISO/disk images

Init system (10 POSIX sh stages):
- Early mount (proc/sys/dev/cgroup2), cmdline parsing, persistent
  mount with bind-mounts, kernel module loading, sysctl, DHCP
  networking, hostname, clock sync, containerd prep, KubeSolo exec

Shared libraries:
- functions.sh (device wait, IP lookup, config helpers)
- network.sh (static IP, config persistence, interface detection)
- health.sh (containerd, API server, node readiness checks)
- Emergency shell for boot failure debugging

Testing:
- QEMU boot test with serial log marker detection
- K8s readiness test with kubectl verification
- Persistence test (reboot + verify state survives)
- Workload deployment test (nginx pod)
- Local storage test (PVC + local-path provisioner)
- Network policy test
- Reusable run-vm.sh launcher

Developer tools:
- dev-vm.sh (interactive QEMU with port forwarding)
- rebuild-initramfs.sh (fast iteration)
- inject-ssh.sh (dropbear SSH for debugging)
- extract-kernel-config.sh + kernel-audit.sh

Documentation:
- Full design document with architecture research
- Boot flow documentation covering all 10 init stages
- Cloud-init examples (DHCP, static IP, Portainer Edge, air-gapped)

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

121 lines
3.2 KiB
Bash
Executable File

#!/bin/bash
# run-vm.sh — Launch QEMU VM for testing (reusable by other test scripts)
# Usage: ./test/qemu/run-vm.sh <iso-or-img> [options]
#
# Options:
# --data-disk <path> Use existing data disk (default: create temp)
# --data-size <MB> Size of temp data disk (default: 1024)
# --memory <MB> VM memory (default: 2048)
# --cpus <n> VM CPUs (default: 2)
# --serial-log <path> Write serial output to file
# --api-port <port> Forward K8s API to host port (default: 6443)
# --ssh-port <port> Forward SSH to host port (default: 2222)
# --background Run in background, print PID
# --append <args> Extra kernel append args
#
# Outputs (on stdout):
# QEMU_PID=<pid>
# DATA_DISK=<path>
# SERIAL_LOG=<path>
set -euo pipefail
IMAGE="${1:?Usage: $0 <iso-or-img> [options]}"
shift
# Defaults
DATA_DISK=""
DATA_SIZE_MB=1024
MEMORY=2048
CPUS=2
SERIAL_LOG=""
API_PORT=6443
SSH_PORT=2222
BACKGROUND=0
EXTRA_APPEND=""
CREATED_DATA_DISK=""
# Parse options
while [ $# -gt 0 ]; do
case "$1" in
--data-disk) DATA_DISK="$2"; shift 2 ;;
--data-size) DATA_SIZE_MB="$2"; shift 2 ;;
--memory) MEMORY="$2"; shift 2 ;;
--cpus) CPUS="$2"; shift 2 ;;
--serial-log) SERIAL_LOG="$2"; shift 2 ;;
--api-port) API_PORT="$2"; shift 2 ;;
--ssh-port) SSH_PORT="$2"; shift 2 ;;
--background) BACKGROUND=1; shift ;;
--append) EXTRA_APPEND="$2"; shift 2 ;;
*) echo "Unknown option: $1" >&2; exit 1 ;;
esac
done
# Create data disk if not provided
if [ -z "$DATA_DISK" ]; then
DATA_DISK=$(mktemp /tmp/kubesolo-data-XXXXXX.img)
CREATED_DATA_DISK="$DATA_DISK"
dd if=/dev/zero of="$DATA_DISK" bs=1M count="$DATA_SIZE_MB" 2>/dev/null
mkfs.ext4 -q -L KSOLODATA "$DATA_DISK" 2>/dev/null
fi
# Create serial log if not provided
if [ -z "$SERIAL_LOG" ]; then
SERIAL_LOG=$(mktemp /tmp/kubesolo-serial-XXXXXX.log)
fi
# Detect KVM availability
KVM_FLAG=""
if [ -w /dev/kvm ] 2>/dev/null; then
KVM_FLAG="-enable-kvm"
fi
# Build QEMU command
QEMU_CMD=(
qemu-system-x86_64
-m "$MEMORY"
-smp "$CPUS"
-nographic
-net nic,model=virtio
-net "user,hostfwd=tcp::${API_PORT}-:6443,hostfwd=tcp::${SSH_PORT}-:22"
-drive "file=$DATA_DISK,format=raw,if=virtio"
-serial "file:$SERIAL_LOG"
)
[ -n "$KVM_FLAG" ] && QEMU_CMD+=("$KVM_FLAG")
case "$IMAGE" in
*.iso)
QEMU_CMD+=(
-cdrom "$IMAGE"
-boot d
-append "console=ttyS0,115200n8 kubesolo.data=/dev/vda kubesolo.debug $EXTRA_APPEND"
)
;;
*.img)
QEMU_CMD+=(
-drive "file=$IMAGE,format=raw,if=virtio"
)
;;
*)
echo "ERROR: Unrecognized image format: $IMAGE" >&2
exit 1
;;
esac
# Launch
"${QEMU_CMD[@]}" &
QEMU_PID=$!
# Output metadata
echo "QEMU_PID=$QEMU_PID"
echo "DATA_DISK=$DATA_DISK"
echo "SERIAL_LOG=$SERIAL_LOG"
echo "CREATED_DATA_DISK=$CREATED_DATA_DISK"
if [ "$BACKGROUND" = "0" ]; then
# Foreground mode — wait for QEMU to exit
wait "$QEMU_PID" || true
# Clean up temp data disk
[ -n "$CREATED_DATA_DISK" ] && rm -f "$CREATED_DATA_DISK"
fi