ref:main
#!/usr/bin/env bash
# Start a private dbus-daemon and a QEMU guest that exports its display and audio on it.
#
# Usage: run_vm.sh <work-dir> <disk-image> [extra qemu args...]
#
# Environment:
# QEMU QEMU binary (default: qemu-system-x86_64 from PATH)
# VM_NAME VM name (default: e2e-guest)
# VM_ACCEL "kvm" or "tcg" (default: kvm when /dev/kvm is usable, else tcg)
# VM_START_WAIT seconds to wait for org.qemu on the bus (default: 30)
#
# Writes into <work-dir>:
# bus.sock the private bus socket; bus address is unix:path=<work-dir>/bus.sock
# dbus.pid dbus-daemon pid
# qemu.pid QEMU pid
# qmp.sock QMP socket
# qemu.log QEMU stdout/stderr
# dbus.log dbus-daemon stdout/stderr
set -euo pipefail
work="${1:?usage: run_vm.sh <work-dir> <disk-image> [qemu args...]}"
image="${2:?usage: run_vm.sh <work-dir> <disk-image> [qemu args...]}"
shift 2
qemu="${QEMU:-qemu-system-x86_64}"
name="${VM_NAME:-e2e-guest}"
wait_s="${VM_START_WAIT:-30}"
if [[ -z "${VM_ACCEL:-}" ]]; then
if [[ -r /dev/kvm && -w /dev/kvm ]]; then
VM_ACCEL=kvm
else
VM_ACCEL=tcg
fi
fi
mkdir -p "${work}"
bus_socket="${work}/bus.sock"
bus_address="unix:path=${bus_socket}"
rm -f "${bus_socket}" "${work}/qmp.sock"
dbus-daemon --session --nofork --nopidfile --address="${bus_address}" > "${work}/dbus.log" 2>&1 &
echo $! > "${work}/dbus.pid"
for _ in $(seq 1 100); do
[[ -S "${bus_socket}" ]] && break
sleep 0.05
done
if [[ ! -S "${bus_socket}" ]]; then
echo "dbus-daemon didn't create ${bus_socket}" >&2
exit 1
fi
"${qemu}" \
-name "${name}" \
-accel "${VM_ACCEL}" \
-m 128 \
-nodefaults \
-device virtio-vga \
-display dbus,addr="${bus_address}" \
-audiodev dbus,id=snd0 \
-device intel-hda -device hda-output,audiodev=snd0 \
-device virtio-tablet-pci \
-device virtio-keyboard-pci \
-drive file="${image}",format=raw,if=ide,snapshot=on \
-qmp unix:"${work}/qmp.sock",server=on,wait=off \
"$@" > "${work}/qemu.log" 2>&1 &
echo $! > "${work}/qemu.pid"
for _ in $(seq 1 $((wait_s * 10))); do
if ! kill -0 "$(cat "${work}/qemu.pid")" 2>/dev/null; then
echo "QEMU exited early; see ${work}/qemu.log" >&2
cat "${work}/qemu.log" >&2
exit 1
fi
if gdbus call --address "${bus_address}" --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus \
--method org.freedesktop.DBus.NameHasOwner org.qemu 2>/dev/null | grep -q true; then
echo "${bus_address}"
exit 0
fi
sleep 0.1
done
echo "QEMU didn't own org.qemu within ${wait_s}s" >&2
exit 1