Created
April 27, 2018 00:34
-
-
Save tai/8dd6742467a5d1ae943c679359fa69ac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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