You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
machine_setup/router/launch_unifi.bash

151 lines
3.7 KiB
Bash

#!/usr/local/bin/bash
#
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
: ${CD:=""}
: ${VNC_ENABLE:="NO"}
: ${VNC_LISTEN:="127.0.0.1:5900"}
: ${PID_FILE:="/var/run/unifi.pid"}
############## Setup #########################
function cleanup {
for vm in "${vms[@]}"; do
log "Destroying bhyve vm $vm"
bhyvectl "--vm=$vm" --destroy
log "Destroyed bhyve vm $vm"
done
}
vms=()
for sig in EXIT INT QUIT HUP TERM; do
trap "set +e; sleep 10; cleanup" "$sig"
done
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
start_vm
}
function start_vm {
local name="unifi"
# -H release the CPU when guest issues HLT instruction. Otherwise 100% of core will be consumed.
# -s 3,ahci-cd,/vm/.iso/archlinux-2023.04.01-x86_64.iso \
# -s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080,wait \
# -s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080 \
# TODO: Look into using nmdm instead of stdio for serial console
if [ -n "$CD" ]; then
additional_args+=("-s" "5,ahci-cd,$CD")
fi
if [ "$VNC_ENABLE" = "YES" ]; then
additional_args+=("-s" "29,fbuf,tcp=$VNC_LISTEN,w=1920,h=1080")
fi
local bridge_name="bridge_vm"
wait_for_bridge "$bridge_name"
local mac_address
mac_address=$(calculate_mac_address "$name")
local bridge_link_name
bridge_link_name=$(detect_available_link "${bridge_name}")
additional_args+=("-s" "2:0,virtio-net,netgraph,path=${bridge_name}:,peerhook=${bridge_link_name},mac=${mac_address}")
vms+=("$name")
while true; do
set -x
set +e
bhyve \
-D \
-c 1 \
-m 3G \
-H \
-o 'rtc.use_localtime=false' \
-s 0,hostbridge \
-s "4,nvme,/dev/zvol/zroot/vm/unifi/disk0" \
-s 30,xhci,tablet \
-s 31,lpc -l com1,stdio \
-l "bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd,/vm/unifi/BHYVE_UEFI_VARS.fd" \
"${additional_args[@]}" \
"$name"
# local bhyvepid=$!
# echo "$bhyvepid" > "$PID_FILE"
# wait $bhyvepid
local exit_code=$?
set +x
set -e
if [ $exit_code -eq 0 ]; then
echo "Rebooting."
sleep 5
elif [ $exit_code -eq 1 ]; then
echo "Powered off."
break
elif [ $exit_code -eq 2 ]; then
echo "Halted."
break
elif [ $exit_code -eq 3 ]; then
echo "Triple fault."
break
elif [ $exit_code -eq 4 ]; then
echo "Exited due to an error."
break
fi
done
}
function ng_exists {
ngctl status "${1}" >/dev/null 2>&1
}
function wait_for_bridge {
local bridge_name="$1"
while ! ng_exists "${bridge_name}:"; do
echo "${bridge_name} does not yet exist, sleeping."
sleep 10
done
}
function detect_available_link {
local bridge_name="$1"
local linknum=1
while true; do
local link_name="link${linknum}"
if ! ng_exists "${bridge_name}:${link_name}"; then
echo "$link_name"
return
fi
linknum=$((linknum + 1))
if [ "$linknum" -gt 90 ]; then
(>&2 echo "No available links on bridge $bridge_name")
exit 1
fi
done
}
function calculate_mac_address {
local name="$1"
local source
source=$(md5 -r -s "$name" | awk '{print $1}')
echo "06:${source:0:2}:${source:2:2}:${source:4:2}:${source:6:2}:${source:8:2}"
}
main "${@}"