#!/usr/bin/env bash # # Mechanics check for the microvm runtime on a bare-metal node. # # Syncs the Go tree to the node, overlays freshly built binaries plus the # Cloud Hypervisor tooling onto the runtime image that is already cached # there (no CRIU/gVisor/QEMU rebuild), and runs the `microvm`-tagged # integration tests inside that image with the same privileges the agent # grants a worker. No gateway, agent, or SDK involved. # # hack/microvm-smoke.sh # sync, build, rootfs, test # hack/microvm-smoke.sh test Boot # rerun only tests matching Boot # hack/microvm-smoke.sh shell # privileged shell in the dev image # # Environment: # MICROVM_HOST ssh target (required) # MICROVM_SSH_KEY ssh identity (required) # MICROVM_REMOTE_DIR remote checkout (~/beta9-microvm) # MICROVM_RUNTIME_IMAGE cached runtime image (public.ecr.aws/n4e0e1y0/beta9-worker:0.1.764) # MICROVM_IMAGE_TAG dev image tag (localhost:5000/beta9-worker:microvm-dev) # MICROVM_TEST_TIMEOUT go test timeout (45m) set -Eeuo pipefail beta9_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" host="${MICROVM_HOST:?set MICROVM_HOST to the ssh target of the node}" ssh_key="${MICROVM_SSH_KEY:?set MICROVM_SSH_KEY to the ssh identity file}" remote_dir="${MICROVM_REMOTE_DIR:-\$HOME/beta9-microvm}" runtime_image="${MICROVM_RUNTIME_IMAGE:-public.ecr.aws/n4e0e1y0/beta9-worker:0.1.764}" image_tag="${MICROVM_IMAGE_TAG:-localhost:5000/beta9-worker:microvm-dev}" # Rootfs tarballs the harness boots. alpine covers boot/exit/network, dind # covers Docker-in-VM, python covers the import-loop timing baseline. rootfs_images=( "alpine=docker.io/library/alpine:3.20" "dind=docker.io/library/docker:27-dind" "python=docker.io/library/python:3.12-slim" ) log() { printf 'microvm-smoke: %s\n' "$*" >&2; } fail() { log "$*"; exit 1; } remote() { ssh -i "$ssh_key" -o BatchMode=yes -o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new "$host" "$@" } # The agent's docker run flags for a worker (pkg/agent/worker_container.go), # minus the worker-specific volumes and env; plus the rootfs tarballs and a # host-backed work dir (overlay upper/work dirs and scratch disks cannot live # on the container's own overlayfs root, exactly as the worker's /tmp is a # host bind). docker_run_flags() { cat </dev/null || echo dev) \ --load -t $image_tag --progress=plain" 2>&1 | tail -n 40 } cmd_rootfs() { log "exporting rootfs tarballs on $host" local script="set -euo pipefail; mkdir -p $remote_dir/rootfs; cd $remote_dir/rootfs;" local entry name image for entry in "${rootfs_images[@]}"; do name="${entry%%=*}" image="${entry#*=}" script+=" if [ ! -s $name.tar ]; then" script+=" sudo docker pull -q $image >/dev/null;" script+=" cid=\$(sudo docker create $image true);" script+=" sudo docker export \$cid > $name.tar.tmp && mv $name.tar.tmp $name.tar;" script+=" sudo docker rm \$cid >/dev/null;" script+=" echo exported $name.tar;" script+=" fi;" done remote "$script" } cmd_test() { local run_filter="${1:-}" local filter_args="" if [ -n "$run_filter" ]; then filter_args="-test.run '$run_filter'" fi log "running microvm integration tests in $image_tag on $host" remote "sudo docker run --rm $(docker_run_flags) $image_tag \ /usr/local/bin/microvm.test -test.v -test.timeout ${MICROVM_TEST_TIMEOUT:-45m} $filter_args" } cmd_shell() { remote -t "sudo docker run --rm -it $(docker_run_flags) $image_tag bash" } cmd_preflight() { log "preflight on $host" remote 'set -e; ls -l /dev/kvm /dev/vhost-vsock /dev/net/tun; lsmod | grep -E "^kvm|^vhost"; echo "cgroup=$(stat -fc %T /sys/fs/cgroup)"; sudo docker image inspect '"$runtime_image"' --format "runtime image: {{.Id}} {{.Size}}"' } main() { local cmd="${1:-all}" shift || true case "$cmd" in all) cmd_preflight cmd_sync cmd_build cmd_rootfs cmd_test "${1:-}" ;; preflight) cmd_preflight ;; sync) cmd_sync ;; build) cmd_sync; cmd_build ;; rootfs) cmd_rootfs ;; test) cmd_test "${1:-}" ;; shell) cmd_shell ;; *) fail "unknown command $cmd (all|preflight|sync|build|rootfs|test [regex]|shell)" ;; esac } main "$@"