#!/bin/sh
set -eu

instance_id=${1:?instance ID is required}
nonce=${2:?registration nonce is required}

case "$instance_id" in
    ????????-????-????-????-????????????) ;;
    *) echo "invalid instance ID" >&2; exit 64 ;;
esac
case "$nonce" in
    *[!A-Za-z0-9_-]*|'') echo "invalid nonce" >&2; exit 64 ;;
esac

state_root=${RUNNER_STATE_ROOT:-/var/lib/microvm-runner}
base_image=${RUNNER_BASE_IMAGE:-$state_root/images/runner-base.qcow2}
firmware=${RUNNER_FIRMWARE:-$state_root/firmware/CLOUDHV.fd}
bridge=${RUNNER_BRIDGE:-mvrbr0}
cloud_hypervisor=${CLOUD_HYPERVISOR:-/usr/local/bin/cloud-hypervisor}
vm_timeout=${RUNNER_VM_TIMEOUT:-3h}
cpus=${RUNNER_VM_CPUS:-4}
memory=${RUNNER_VM_MEMORY:-3G}
gitea_instance=${GITEA_INSTANCE:-https://git.ddupan.top}
runner_label=${RUNNER_LABEL:-kind-microvm}
token_url=${RUNNER_TOKEN_URL:-http://172.30.0.1:8787}

vm_dir="$state_root/instances/$instance_id"
tap="mvr${instance_id%%-*}"
overlay="$vm_dir/root.qcow2"
seed="$vm_dir/seed.img"
serial="$vm_dir/serial.log"

cleanup() {
    ip link delete "$tap" 2>/dev/null || true
    rm -rf -- "$vm_dir"
}
trap cleanup EXIT INT TERM

test -r "$base_image"
test -r "$firmware"
install -d -m 0700 "$state_root/instances" "$vm_dir"
qemu-img create -q -f qcow2 -F qcow2 -b "$base_image" "$overlay"

cat >"$vm_dir/meta-data" <<EOF
instance-id: $instance_id
local-hostname: gitea-runner-${instance_id%%-*}
EOF
cat >"$vm_dir/user-data" <<EOF
#cloud-config
runcmd:
  - [ /usr/local/libexec/gitea-microvm-guest-runner, "$token_url/token/$nonce", "$gitea_instance", "gitea-${instance_id%%-*}", "$runner_label" ]
EOF
cloud-localds "$seed" "$vm_dir/user-data" "$vm_dir/meta-data"

digest=$(printf '%s' "$instance_id" | sha256sum | cut -c1-10)
mac=$(printf '02:%s:%s:%s:%s:%s' \
    "$(printf '%s' "$digest" | cut -c1-2)" \
    "$(printf '%s' "$digest" | cut -c3-4)" \
    "$(printf '%s' "$digest" | cut -c5-6)" \
    "$(printf '%s' "$digest" | cut -c7-8)" \
    "$(printf '%s' "$digest" | cut -c9-10)")
ip tuntap add dev "$tap" mode tap
ip link set "$tap" master "$bridge"
ip link set "$tap" up

timeout --signal=TERM --kill-after=30s "$vm_timeout" "$cloud_hypervisor" \
    --firmware "$firmware" \
    --cpus "boot=$cpus" \
    --memory "size=$memory" \
    --disk "path=$overlay" \
    --disk "path=$seed,readonly=on" \
    --net "tap=$tap,mac=$mac" \
    --serial "file=$serial" \
    --console off
