#!/bin/bash

ACPI=
RAM="256"
IMAGE=
SHARED=
PERSIST="yes"
VNC=
NET="yes"
CDROM=
CDBOOT="yes"

KVM="qemu-kvm"

function usage {
    cat >&2 <<EOF
Usage: $0 [options] <image-file>

Options:
    -m,--memory,--ram <megabytes> : Amount of memory in megabytes to allocate to 
          the virtual machine.
    --no-acpi, --windows  : Do not enable ACPI support in the VM (Needed for 
          MS-Windows to work).
    --share <directory>   : Share this local directory through a virtual 
          harddrive (Useful for allowing a virtualized MS-Windows system to read
          host's local files).
    --protect             : Protect the image from being changed by the virtual 
          machine. All writes by the VM will be done to temporary files and will
          be reverted when the virtual machine closes.
    --vnc [display]       : Don't start the virtual machine console, instead 
          direct the console to a VNC server. If the display is not specified, 
          it will use VNC display 1. (use 'vncviewer :1' to connect to the VM
          running on VNC display 1).
    --no-net              : Disable virtual networking in the VM
    --cdrom [device]      : Attach a real cdrom device to the VM, and boot the 
          virtual machine from it:
            * If no parameters are given, then the first cdrom device on the 
              computer is attached to the virtual machine.
            * If given a number or a name of a cdrom device (such as scd1, cdrw, 
              etc') then that cdrom device is attached.
    --cd-image <file>     : Attach an ISO image of a CD or DVD to the VM as a
            virtual cdrom, and use it to boot the virtual machine. This overrides
            the --cdrom option above.
    --no-boot             : When attaching a virtual cdrom, don't boot from it.
    --help                : This message.
    
EOF
    exit 5
}

original_args="$*"

while [ -n "$*" ]; do
    case "$1" in
        --help)
	    usage
        ;;
	--windows)
	    ACPI="-no-acpi"
	;;
	--no-acpi)
	    ACPI="-no-acpi"
	;;
	-m)
	    shift
	    RAM="$1"
	;;
	--memory)
	    shift
	    RAM="$1"
	;;
	--ram)
	    shift
	    RAM="$1"
	;;
	--cdrom)
	    CDROM="$2"
	    if [ -z "$CDROM" -o "${CDROM:0:1}" == "-" ]; then # easy
		CDROM="-cdrom /dev/scd0"
	    elif [ "$CDROM" == "$(echo $CDROM | sed s/[^0-9]//)" ]; then # number
		CDROM="-cdrom /dev/scd${CDROM}"
	    elif [ -f "/dev/${CDROM}" ]; then # device name
		CDROM="-cdrom /dev/${CDROM}"
	    elif [ -f "${CDROM}" ]; then # either its a full path to a cdrom device, or its a cd image
		# I don't care either way
		CDROM="-cdrom '$CDROM'"
	    else # error
		"Error: '$CDROM' is not a valid cdrom device!" >&2
		usage
	    fi
	;;
	--cd-image)
	    shift
	    CDROM="$1"
	    if ! [ -f "$CDROM" ]; then
		echo "Error: '$CDROM' not found!" >&2
		usage
	    fi
	    CDROM="-cdrom '$CDROM'"
	;;
	--no-boot)
	    CDBOOT=	    
	;;
	--share)
	    shift
	    SHARED="$1"
	    if ! [ -d "$SHARED" ]; then
		echo "Error: '$SHARED' is not a directory!" >&2
		usage
	    fi
	    SHARED="-hdb 'vvfat:$SHARED'"
	;;
	--protect)
	    PERSIST=
	;;
	--vnc)
	    if [ -z "$2" ]; then
		vnc_display=":1"
	    else
		shift
		vnc_display="$1"
	    fi
	    echo "Using VNC display '$vnc_display' for KVM console. Please use your vncviewer to access the console"
	    VNC="-vnc $vnc_display"
	;;
	--no-net)
	    NET=
	;;
	*)
	    IMAGE="$1"
	;;
    esac
    shift
done

# make sure I run as root. not nice, but I need to load modules and start network interfaces, so sucks.
if [ "$(id -u)" != "0" ]; then
    sudo $0 $original_args
    exit $?
fi

[ -z "$IMAGE" ] && { echo "Error: missing virtual disk image to load!"; usage; }

if [ -n "$CDROM" -a -n "$CDBOOT" ]; then
    CDROM="$CDROM -boot d"
fi

# make sure TUN is loaded for networking to work
/sbin/modprobe tun 2>/dev/null || { echo "Can't load network module, make sure you have permissions to load kernel modules." >&2; exit 1; }

IFNAME=
if [ -n "$NET" ]; then
    # Figure out what network interface I want to use and lock it
    ifnum=$(ls /var/lock/kvm-tap* 2>/dev/null | wc -l)
    IFNAME="tap${ifnum}"
    echo "Locking /var/lock/kvm-${IFNAME}"
    touch /var/lock/kvm-${IFNAME}
    kvm_network="-net nic -net tap,ifname=${IFNAME},script=/usr/local/bin/kvm-network-setup"
    
    # allow IP forwarding so that the network script can enable NAT
    if [ "$(cat /proc/sys/net/ipv4/ip_forward)" == "0" ]; then
	/sbin/sysctl -w net.ipv4.ip_forward=1
    fi
fi

$KVM $ACPI -m "$RAM" -hda "$IMAGE" $CDROM $SHARED \
    $( [ -z "$PERSIST" ] && echo "-snapshot" ) $VNC $kvm_network

rm -f /var/lock/kvm-${IFNAME}
