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>
121 lines
3.2 KiB
Bash
Executable File
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
|