#!/bin/bash
set -e

# main available options:
#   QEMU_CPU=n    (cores)
#   QEMU_RAM=nnn  (megabytes)
#   QEMU_HDA      (filename)
#   QEMU_HDA_SIZE (bytes, suffixes like "G" allowed)
#   QEMU_CDROM    (filename)
#   QEMU_BOOT     (-boot)
#   QEMU_PORTS="xxx[ xxx ...]" (space separated port numbers)
#   QEMU_NET_USER_EXTRA="net=192.168.76.0/24,dhcpstart=192.168.76.9" (extra raw args for "-net user,...")
#   QEMU_NO_SSH=1 (suppress automatic port 22 forwarding)
#   QEMU_NO_SERIAL=1 (suppress automatic "-serial stdio")
#   QEMU_NO_VNC=1 (suppress automatic "-vnc ':0'")

hostArch="$(uname -m)"
qemuArch="${QEMU_ARCH:-$hostArch}"
qemu="${QEMU_BIN:-qemu-system-$qemuArch}"
qemuArgs=()

qemuPorts=()
if [ -z "${QEMU_NO_SSH:-}" ]; then
	qemuPorts+=( 22 )
fi
qemuPorts+=( ${QEMU_PORTS:-} )

if [ -e /dev/kvm ] && sh -c 'echo -n > /dev/kvm' &> /dev/null; then
	# https://github.com/tianon/docker-qemu/issues/4
	qemuArgs+=( -enable-kvm )
elif [ "$hostArch" = "$qemuArch" ]; then
	echo >&2
	echo >&2 'warning: /dev/kvm not found'
	echo >&2 '  PERFORMANCE WILL SUFFER'
	echo >&2 '  (hint: docker run --device /dev/kvm ...)'
	echo >&2
	sleep 3
fi

qemuArgs+=( -smp "${QEMU_CPU:-1}" )
qemuArgs+=( -m "${QEMU_RAM:-512}" )

if [ -n "${QEMU_HDA:-}" ]; then
	if [ ! -f "$QEMU_HDA" -o ! -s "$QEMU_HDA" ]; then
		(
			set -x
			qemu-img create -f qcow2 -o preallocation=off "$QEMU_HDA" "${QEMU_HDA_SIZE:-8G}"
		)
	fi

	# http://wiki.qemu.org/download/qemu-doc.html#Invocation
	qemuScsiDevice='virtio-scsi-pci'
	case "$qemuArch" in
		arm | riscv64) qemuScsiDevice='virtio-scsi-device' ;;
	esac

	#qemuArgs+=( -hda "$QEMU_HDA" )
	#qemuArgs+=( -drive file="$QEMU_HDA",index=0,media=disk,discard=unmap )
	qemuArgs+=(
		-drive file="$QEMU_HDA",index=0,media=disk,discard=unmap,detect-zeroes=unmap,if=none,id=hda
		-device "$qemuScsiDevice"
		-device scsi-hd,drive=hda
	)
fi

if [ -n "${QEMU_CDROM:-}" ]; then
	qemuArgs+=( -cdrom "$QEMU_CDROM" )
fi

if [ -n "${QEMU_BOOT:-}" ]; then
	qemuArgs+=( -boot "$QEMU_BOOT" )
fi

netArg='user'
netArg+=",hostname=$(hostname)"
if [ -n "${QEMU_NET_USER_EXTRA:-}" ]; then
	netArg+=",$QEMU_NET_USER_EXTRA"
fi
for port in "${qemuPorts[@]}"; do
	netArg+=",hostfwd=tcp::$port-:$port"
	netArg+=",hostfwd=udp::$port-:$port"
done

qemuNetDevice='virtio-net-pci'
case "$qemuArch" in
	arm | riscv64) qemuNetDevice='virtio-net-device' ;;
esac

qemuArgs+=(
	-netdev "$netArg,id=net"
	-device "$qemuNetDevice,netdev=net"
)

if [ -z "${QEMU_NO_SERIAL:-}" ]; then
	qemuArgs+=(
		-serial stdio
	)
fi

if [ -z "${QEMU_NO_VNC:-}" ]; then
	qemuArgs+=(
		-vnc ':0'
	)
fi

qemuArgs+=( "$@" )

set -x
exec "$qemu" "${qemuArgs[@]}"