Skip to content

Instantly share code, notes, and snippets.

@tai
Created April 27, 2018 00:34
Show Gist options
  • Select an option

  • Save tai/8dd6742467a5d1ae943c679359fa69ac to your computer and use it in GitHub Desktop.

Select an option

Save tai/8dd6742467a5d1ae943c679359fa69ac to your computer and use it in GitHub Desktop.
#!/bin/sh
set -e
usage() {
local p=$(basename $0)
cat <<EOF >&2
$p - Run QEMU/KVM
Usage: $p <rootfs-or-image> <qemu-options...> -- <boot-options...>
Example:
# $p /n/sid64
# $p /n/sid64-snap00
# $p /n/sid64/boot/vmlinuz-4.14.0-3-amd64
# $p /n/sid64/boot/initrd.img-4.14.0-3-amd64
# $p /some/image.qcow2
# $p /n/sid64 -curses -bios OVMF.fd
# $p /n/sid64 -device vfio-pci,host=00:1a.0
# $p /n/sid64 -device vfio-pci,host=00:1a.0,x-vga=on -vga none
# $p /n/sid64 -usb -device usb-host,hostbus=2,hostaddr=3
# $p none -drive file=/some/image.raw,format=raw
# $p /n/sid64 -drive file=/dev/sdx,format=raw,if=virtio,cache=none
# NORUN=echo $p /n/sid64
# KVM_HDD=hda $p /n/sid64 -drive file=/disk.dd,format=raw,cache=none
# KVM_MEM=64G $p /n/sid64 -smp cpus=32
# KVM_IF0=br0 $p /n/sid64 -gdb tcp::1234 -- vsyscall=emulate
# KVM_IF1=br1 $p /n/sid64 -s -- crashkernel=128M
EOF
exit 1
}
log() { echo "$@" >&2; }
die() { log "$@"; exit 1; }
makeroot() {
local want=$1
local bn=$(basename $want)
local dn=$(dirname $want)
# either just use given path, or clone from skelton
while [ -n "$bn" ]; do
local skel="$dn/$bn"
if [ -d "$skel" ]; then
if [ "$skel" != "$want" ]; then
sudo btrfs sub snap "$skel" "$want" > /dev/null
fi
return
fi
bn=$(echo $bn | sed 's/.$//')
done
log "Failed to prepare: $want"
}
findboot() {
local arg=$1
local img
case "$arg" in
-|none) echo exitok=1; return;;
esac
# clone environment on-demand
test -e "$arg" || makeroot ${arg%%/boot/*}
# check if arg is a block device or system image (> 100MB)
if [ -b "$arg" -o $(stat -c %s "$arg") -gt $((1024 * 1024 * 100)) ]; then
echo boot_type=drive
echo KVM_HDD=hda
echo drive=$arg
echo exitok=1
return
fi
# check if arg is either a kernel or initrd image
if [ -f "$arg" ]; then
img="$arg"
elif [ -d "$arg/boot" ]; then
img=$(ls -1 -v $arg/boot/vmli* | egrep -v '(old|bak)' | head -1)
else
log "Not bootable: $arg"
return
fi
local ver=$(basename $img | cut -d- -f2-)
local loc=${img%%/boot/*}
# return whatever found
echo boot_type=nfs
echo nfsdir=$loc
echo initrd=$(find $loc/boot/init*${ver} 2> /dev/null | egrep -v '(old|bak)' | sort -V | head -1)
echo kernel=$(find $loc/boot/vmli*${ver} 2> /dev/null | egrep -v '(old|bak)' | sort -V | head -1)
echo exitok=1
}
run() {
local arg=$1; shift
# just pass-through other args
local qemu_opt="$(echo $@ | awk -F-- '{ print $1 }')"
local boot_opt="$(echo $@ | awk -F-- '{ print $2 }')"
# setup boot configuration
local boot_type
local drive KVM_HDD
local nfsdir kernel initrd
local $(findboot $arg)
test -n "$exitok" || die "Failed to boot: $arg"
# select boot source
if [ -n "$kernel" ]; then
# select arch
local tty=ttyS0
case "$kernel" in
*aarch64*) : ${QEMU:=qemu-system-aarch64};;
*mipsel*) : ${QEMU:=qemu-system-mipsel};;
*x86_64*) : ${QEMU:=qemu-system-x86_64 --enable-kvm};;
*amd64*) : ${QEMU:=qemu-system-x86_64 --enable-kvm};;
*i386*) : ${QEMU:=qemu-system-i386 --enable-kvm};;
*mips*) : ${QEMU:=qemu-system-mips};;
*arm*) : ${QEMU:=qemu-system-arm}; tty=ttyAMA0;;
*) die "Unknown arch: $kernel"
esac
if [ -n "$KVM_HDD" ]; then
case "$KVM_HDD" in
vda) append="ip=dhcp root=/dev/vda1 rw panic=30 console=$tty";;
sda) append="ip=dhcp root=/dev/sda1 rw panic=30 console=$tty";;
hda) append="ip=dhcp root=/dev/hda1 rw panic=30 console=$tty";;
*) append="ip=dhcp root=$KVM_HDD rw panic=30 console=$tty";;
esac
elif [ -n "$nfsdir" ]; then
append="ip=dhcp root=/dev/nfs rw nfsroot=${KVM_NFS:=10.0.100.10}:$nfsdir,tcp,soft,intr,nolock panic=30 console=$tty"
fi
fi
#
# NOTE:
# - snapshot saves to $TMPDIR
#
$NORUN sudo TMPDIR=${TMPDIR:=/var/tmp} ${QEMU:=kvm} \
-nographic -m ${KVM_MEM:=256M} \
-k ja -echr 0x14 \
-net nic,model=virtio,macaddr=$(macgen-qemu 0 $PPID) \
-net bridge,br=${KVM_IF0:=vz-fg} \
-net nic,model=virtio,macaddr=$(macgen-qemu 1 $PPID) \
-net bridge,br=${KVM_IF1:=vz-bg} \
${drive:+-drive file=$drive,if=virtio,cache=none} \
${kernel:+-kernel $kernel} \
${initrd:+-initrd $initrd} \
${append:+-append "$append $boot_opt"} \
$qemu_opt
}
test $# -gt 0 || usage
run "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment