Created
April 27, 2018 03:18
-
-
Save tai/0dcee25b044010a040f6019db1deb519 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 - Simple wrapper to run QEMU/KVM in various configurations | |
| 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 nfs:/n/sid64 | |
| # $p 9p:/n/sid64 | |
| # $p /some/image.qcow2 | |
| # $p /dev/sdx | |
| # $p raw:/some/image.dd | |
| # $p raw-virtio:/some/image.dd | |
| # $p none -drive file=/foo/hdd.dd,cache=none,format=raw,if=virtio | |
| # $p none -boot n -curses | |
| # $p /n/sid64 -drive file=/foo/hdd.qcow2,cache=none | |
| # $p /n/sid64 -bios OVMF.fd -curses | |
| # $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 | |
| # NORUN=echo $p /n/sid64 | |
| # 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" | |
| } | |
| # | |
| # Usage: | |
| # findboot [tag:]<file-or-dir> | |
| # Example: | |
| # findboot /n/sid64 | |
| # findboot /n/sid64/boot/vmlinuz-1.2.3-amd64 | |
| # findboot nfs:/n/sid64 | |
| # findboot 9p:/n/sid64 | |
| # | |
| findboot() { | |
| local arg=$1 | |
| local src=${arg#*:} | |
| local tag=$(test "$arg" = "$src" || echo ${arg%%:*}) | |
| local is_kernel_image=false | |
| # skip if given as "empty" | |
| case "$src" in | |
| -|none) return 0;; | |
| esac | |
| # clone environment on-demand | |
| test -e "$src" || makeroot ${src%%/boot/*} | |
| # CASE: src is a block device or system image (> 100MB) | |
| if [ -b "$src" -o $(stat -c %s "$src") -gt $((1024 * 1024 * 100)) ]; then | |
| is_kernel_image=false | |
| : ${tag:=raw-scsi} | |
| # CASE: src is either a kernel or initrd image | |
| elif [ -f "$src" ]; then | |
| is_kernel_image=true | |
| : ${tag:=nfs} | |
| # CASE: src is a bootable rootfs | |
| elif [ -d "$src/boot" ]; then | |
| is_kernel_image=true | |
| : ${tag:=nfs} | |
| # use latest kernel image in /boot | |
| src=$(ls -1v $src/boot/vmli* | egrep -vm1 '(old|bak)') | |
| else | |
| log "Not bootable: $src" | |
| return 1 | |
| fi | |
| local kernel initrd tty=ttyS0 | |
| if $is_kernel_image; then | |
| # get info from kernel/initrd pathname | |
| local ver=$(basename $src | cut -d- -f2-) | |
| local loc=${src%%/boot/*} | |
| initrd=$(ls -1v $loc/boot/init*${ver} | egrep -vm1 '(old|bak)') | |
| kernel=$(ls -1v $loc/boot/vmli*${ver} | egrep -vm1 '(old|bak)') | |
| # select QEMU and arch-specific options | |
| 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*) tty=ttyAMA0 | |
| : ${QEMU:=qemu-system-arm -M ${KVM_MACHINE:=versatilepb}};; | |
| *) log "Unknown arch: $kernel"; return 1;; | |
| esac | |
| fi | |
| # | |
| # generate qemu options | |
| # | |
| case "$tag" in | |
| raw) KVM_EXTRAS="-drive file=$src,cache=none,format=raw";; | |
| raw-*) KVM_EXTRAS="-drive file=$src,cache=none,format=raw,if=${tag#raw-}";; | |
| hdd-*) KVM_EXTRAS="-drive file=$src,cache=none,if=${tag#hdd-}";; | |
| hda) KVM_EXTRAS="-drive file=$src,cache=none";; | |
| sda) KVM_EXTRAS="-drive file=$src,cache=none,if=scsi";; | |
| vda) KVM_EXTRAS="-drive file=$src,cache=none,if=virtio";; | |
| nfs) | |
| KVM_INITRD=$initrd | |
| KVM_KERNEL=$kernel | |
| KVM_APPEND="ip=dhcp root=/dev/nfs rw nfsroot=${KVM_NFS:=10.0.100.10}:$loc,tcp,soft,intr,nolock console=$tty" | |
| ;; | |
| 9p) | |
| KVM_INITRD=$initrd | |
| KVM_KERNEL=$kernel | |
| KVM_APPEND="virtfsroot=9p::root9p boot=virtfs console=$tty" | |
| KVM_EXTRAS="-virtfs local,path=$loc,mount_tag=root9p,security_model=none" | |
| ;; | |
| *) | |
| log "Unknown boot type: $tag" | |
| return 1 | |
| esac | |
| return 0 | |
| } | |
| 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 | |
| findboot $arg || die "Failed to boot: $arg" | |
| # | |
| # 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} \ | |
| ${KVM_KERNEL:+-kernel $KVM_KERNEL} \ | |
| ${KVM_INITRD:+-initrd $KVM_INITRD} \ | |
| ${KVM_APPEND:+-append "$KVM_APPEND $boot_opt"} \ | |
| $KVM_EXTRAS $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