#!/bin/bash # ksim-vm run boot the exam host of this container. Its disk is /env/disk.qcow2, a thin copy of # the base disk made on the first start; /course is the task's /opt/course. # ksim-vm build make the base disk: boot the Ubuntu cloud image once with guest/provision.sh as # its first-boot script, and keep the result. # # /base .state/vm of the simulator: the Ubuntu cloud image and the base disks (read-only for run) # /env the host's own directory (.state/envs/): disk and console log # /keys the simulator's ssh key pair (read-only) set -euo pipefail KVM=(-enable-kvm -cpu host -machine q35 -display none -monitor none -device virtio-rng-pci) case "${1:-run}" in run) base=/base/${KSIM_BASE:?} [ -f /env/disk.qcow2 ] || qemu-img create -q -f qcow2 -F qcow2 -b "$base" /env/disk.qcow2 # what the machine needs to know about itself, handed over as a second shared directory: # its name, and the key the simulator and the desktop log in with (guest/firstboot.sh reads both) mkdir -p /run/ksim && echo "${KSIM_HOSTNAME:?}" > /run/ksim/hostname && cp /keys/id_ed25519.pub /run/ksim/authorized_keys exec qemu-system-x86_64 "${KVM[@]}" -smp "${KSIM_VM_CPUS:-2}" -m "${KSIM_VM_MB:-2048}" -serial file:/env/console.log \ -drive file=/env/disk.qcow2,if=virtio,cache=unsafe,discard=unmap \ -netdev user,id=n0,hostfwd=tcp::22-:22,hostfwd=tcp::6443-:6443 -device virtio-net-pci,netdev=n0 \ -virtfs local,path=/course,mount_tag=course,security_model=passthrough,id=course \ -virtfs local,path=/run/ksim,mount_tag=ksim,security_model=none,readonly=on,id=ksim ;; build) out=/base/${KSIM_BASE:?}; work=/base/.build.qcow2; log=/base/build.log rm -f "$work" /base/.seed.iso "$out.new"; : > "$log" qemu-img create -q -f qcow2 -F qcow2 -b /base/noble.img "$work" 20G printf 'instance-id: ksim-build\nlocal-hostname: ksim-build\n' > /tmp/meta-data cloud-localds /base/.seed.iso /build/provision.sh /tmp/meta-data # the guest powers itself off when provision.sh is through; -no-reboot turns that into QEMU exiting timeout "${KSIM_BUILD_TIMEOUT:-2400}" qemu-system-x86_64 "${KVM[@]}" -smp 4 -m 4096 -serial "file:$log" -no-reboot \ -drive file="$work",if=virtio,cache=unsafe -drive file=/base/.seed.iso,if=virtio,format=raw \ -netdev user,id=n0 -device virtio-net-pci,netdev=n0 \ -virtfs local,path=/build,mount_tag=build,security_model=none,readonly=on,id=build || true if ! grep -q KSIM-PROVISION-OK "$log"; then echo "provisioning did not finish - the end of the VM's console:" >&2; tail -n 40 "$log" >&2; rm -f "$work" /base/.seed.iso; exit 1 fi qemu-img convert -O qcow2 "$work" "$out.new" && mv "$out.new" "$out" rm -f "$work" /base/.seed.iso ;; *) echo "usage: ksim-vm run|build" >&2; exit 2 ;; esac