scripts/kvm.sh
#!/usr/bin/env bash
# tunnr-etcd main + twin under KVM: install each ISO to a blank disk, then boot the disks.
# eth0 = user net (host forwards 2379), eth1 = a private L2 between the two VMs (socket mcast).
set -euo pipefail
ROOT=$(cd "$(dirname "$0")/.." && pwd)
W=${W:-$ROOT/.kvm}; ISO=${ISO:-$ROOT/.iso-out}
CODE=/usr/share/OVMF/OVMF_CODE_4M.fd; VARS=/usr/share/OVMF/OVMF_VARS_4M.fd
mkdir -p "$W"
mac() { [ "$1" = main ] && echo "$2:01" || echo "$2:02"; }
port() { [ "$1" = main ] && echo 23790 || echo 23791; }
qemu() { # role cdrom? log
local r=$1 cd=$2 log=$3
local args=(-machine q35,accel=kvm -cpu host -smp ${SMP:-2} -m ${MEM:-512} -display none -no-user-config
-drive if=pflash,format=raw,readonly=on,file=$CODE -drive if=pflash,format=raw,file=$W/$r.vars
-drive if=none,id=d0,format=raw,file=$W/$r.disk -device virtio-blk-pci,drive=d0,bootindex=1
-netdev user,id=n0,hostfwd=tcp:127.0.0.1:$(port $r)-:2379 -device virtio-net-pci,netdev=n0,mac=$(mac $r 52:54:00:aa:00)
-netdev socket,id=n1,mcast=230.0.77.1:47701 -device virtio-net-pci,netdev=n1,mac=$(mac $r 52:54:00:bb:00)
-serial file:$log -pidfile $W/$r.pid -monitor unix:$W/$r.mon,server,nowait)
if [ "$cd" = cd ]; then args+=(-drive if=none,id=c0,media=cdrom,file=$ISO/tunnr-etcd-$r.iso -device ide-cd,drive=c0,bootindex=0 -no-reboot); fi
nice -n 10 qemu-system-x86_64 "${args[@]}"
}
case ${1:-} in
install) r=$2; rm -f $W/$r.disk; truncate -s 4G $W/$r.disk; cp $VARS $W/$r.vars
timeout 900 bash -c "$(declare -f qemu mac port); W=$W ISO=$ISO CODE=$CODE; qemu $r cd $W/$r-install.log" || true
grep -a -c "INSTALL-OK" $W/$r-install.log ;;
boot) r=$2; n=${3:-1}; qemu $r disk $W/$r-boot$n.log >$W/$r-qemu$n.out 2>&1 </dev/null & echo $! > $W/$r.qpid ;;
stop) r=$2; kill "$(cat $W/$r.pid)" 2>/dev/null || true ;;
powerdown) r=$2; python3 -c "import socket,sys,time; s=socket.socket(socket.AF_UNIX); s.connect(sys.argv[1]); time.sleep(0.3); s.recv(4096); s.sendall(b\"system_powerdown\\n\"); time.sleep(0.5)" $W/$r.mon ;;
*) echo "usage: kvm.sh install|boot|stop main|twin [n]"; exit 2 ;;
esac