Stop relying on ad hoc rootfs handling by adding image promotion, managed work-seed fingerprint metadata, and lazy self-healing for older managed images after the first create. Rebuild guest images with baked SSH access, a guest NIC bootstrap, and default opencode services, and add the staged Void kernel/initramfs/modules workflow so void-exp uses a matching Void boot stack. Replace the opaque blocking vm.create RPC with a begin/status flow that prints live stages in the CLI while still waiting for vsock health and opencode on guest port 4096. Validate with GOCACHE=/tmp/banger-gocache go test ./... and live void-exp create/delete smoke runs.
132 lines
2.3 KiB
Bash
132 lines
2.3 KiB
Bash
#!/bin/sh
|
|
set -eu
|
|
|
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
|
|
if ! command -v ip >/dev/null 2>&1; then
|
|
exit 0
|
|
fi
|
|
|
|
cmdline="$(cat /proc/cmdline 2>/dev/null || true)"
|
|
ip_arg=""
|
|
for arg in $cmdline; do
|
|
case "$arg" in
|
|
ip=*)
|
|
ip_arg="${arg#ip=}"
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$ip_arg" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
field() {
|
|
printf '%s' "$ip_arg" | cut -d: -f"$1"
|
|
}
|
|
|
|
mask_to_prefix() {
|
|
case "$1" in
|
|
[0-9]|[1-2][0-9]|3[0-2])
|
|
printf '%s\n' "$1"
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
prefix=0
|
|
old_ifs=$IFS
|
|
IFS=.
|
|
set -- $1
|
|
IFS=$old_ifs
|
|
if [ "$#" -ne 4 ]; then
|
|
return 1
|
|
fi
|
|
|
|
for octet in "$@"; do
|
|
case "$octet" in
|
|
255) prefix=$((prefix + 8)) ;;
|
|
254) prefix=$((prefix + 7)) ;;
|
|
252) prefix=$((prefix + 6)) ;;
|
|
248) prefix=$((prefix + 5)) ;;
|
|
240) prefix=$((prefix + 4)) ;;
|
|
224) prefix=$((prefix + 3)) ;;
|
|
192) prefix=$((prefix + 2)) ;;
|
|
128) prefix=$((prefix + 1)) ;;
|
|
0) ;;
|
|
*) return 1 ;;
|
|
esac
|
|
done
|
|
|
|
printf '%s\n' "$prefix"
|
|
}
|
|
|
|
find_iface() {
|
|
hint="$1"
|
|
if [ -n "$hint" ] && [ -d "/sys/class/net/$hint" ]; then
|
|
printf '%s\n' "$hint"
|
|
return 0
|
|
fi
|
|
|
|
for path in /sys/class/net/*; do
|
|
[ -e "$path" ] || continue
|
|
iface="${path##*/}"
|
|
if [ "$iface" = "lo" ]; then
|
|
continue
|
|
fi
|
|
printf '%s\n' "$iface"
|
|
return 0
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
guest_ip="$(field 1)"
|
|
gateway_ip="$(field 3)"
|
|
netmask="$(field 4)"
|
|
iface_hint="$(field 6)"
|
|
dns1="$(field 8)"
|
|
dns2="$(field 9)"
|
|
|
|
if [ -z "$guest_ip" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
iface=""
|
|
attempt=0
|
|
while [ "$attempt" -lt 50 ]; do
|
|
iface="$(find_iface "$iface_hint" || true)"
|
|
if [ -n "$iface" ]; then
|
|
break
|
|
fi
|
|
attempt=$((attempt + 1))
|
|
sleep 0.2
|
|
done
|
|
|
|
if [ -z "$iface" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
prefix="$(mask_to_prefix "$netmask" || printf '24\n')"
|
|
|
|
ip link set "$iface" up
|
|
ip addr replace "$guest_ip/$prefix" dev "$iface"
|
|
|
|
if [ -n "$gateway_ip" ]; then
|
|
ip route replace default via "$gateway_ip" dev "$iface"
|
|
fi
|
|
|
|
if [ -n "$dns1" ] || [ -n "$dns2" ]; then
|
|
tmp_resolv="/tmp/.banger-resolv.conf.$$"
|
|
: > "$tmp_resolv"
|
|
if [ -n "$dns1" ]; then
|
|
printf 'nameserver %s\n' "$dns1" >> "$tmp_resolv"
|
|
fi
|
|
if [ -n "$dns2" ]; then
|
|
printf 'nameserver %s\n' "$dns2" >> "$tmp_resolv"
|
|
fi
|
|
if [ -s "$tmp_resolv" ]; then
|
|
cat "$tmp_resolv" > /etc/resolv.conf
|
|
fi
|
|
rm -f "$tmp_resolv"
|
|
fi
|