#!/bin/sh basedir="`dirname "$0"`/.." TAPUTIL="$basedir/bin/taputil" SUDO="/usr/bin/sudo" #VM_NAME="xp.intra.ogris.net" if [ -z "$VM_NAME" ]; then script="`basename "$0"`" script=${script%%.sh} VM_NAME=${script##[0-9]} port=${script%%$VM_NAME} fi VM_VNC=${VM_VNC:-$port} VM_MEM=${VM_MEM:-2048} VM_CPU=${VM_CPU:-"host"} VM_MACHINE=${VM_MACHINE:-"pc"} VM_CPUS=${VM_CPUS:-2} VM_CDROMS=${VM_CDROMS:-1} VM_EXTRA=${VM_EXTRA:-""} VM_LAUNCH_VNC=${VM_LAUNCH_VNC:-1} VM_FILE_NAME0=${VM_FILE_NAME0:-$VM_NAME} #VM_FILE_TYPE0="virtio" #VM_FILE_CACHE0="none" #... #VM_FILE_NAME9=... #VM_FILE_TYPE9=... #VM_FILE_CACHE9=... #VM_NET_MAC0=${VM_NET_MAC0:-"52:54:00:00:0$VM_MAC:00"} #VM_NET_TAP0=${VM_NET_TAP0:-"0$VM_VNC"} VM_NET_TYPE0=${VM_NET_TYPE0:-"virtio"} #VM_NET_BRIDGE0={$VM_NET_BRIDGE0:-"00"} #... #VM_NET_MAC3=${VM_NET_MAC0:-"52:54:00:00:0$VM_MAC:03"} #VM_NET_TAP3=... #VM_NET_TYPE3=... #VM_NET_BRIDGE3=... VM_PORT=${VM_PORT:-$((VM_VNC+6666))} VM_MAC=${VM_MAC:-$VM_VNC} VM_PID=${VM_PID:-"$basedir/tmp/kvm-$VM_NAME.pid"} # for remote shutdown via net rpc: #VM_SHUT_DOMAIN="XP" #VM_SHUT_USER="administrator" #VM_SHUT_PASS="secret" #VM_SHUT_HOST="192.168.1.13" [ -z "$VM_NAME" ] && { echo "no VM_NAME" >&2; exit 1; } [ -z "$VM_VNC" ] && { echo "no VM_VNC" >&2; exit 1; } [ -x "$TAPUTIL" ] || { echo "no $TAPUTIL" >&2; exit 1; } [ -x "$SUDO" ] || { echo "no $SUDO" >&2; exit 1; } function vm_vnc() { local xpos=$((VM_VNC%2*850)) local ypos=$((VM_VNC/2*650)) nohup vncviewer :"$VM_VNC" -geometry "+$xpos+$ypos" >/dev/null 2>&1 & } function vm_nics() { local mode="$1" local nicmac local nictap local nictype local nicbridge local bridge local port local i nics="" for i in {0..3}; do eval nicmac=\$VM_NET_MAC$i eval nictap=\$VM_NET_TAP$i eval nictype=\$VM_NET_TYPE$i eval nicbridge=\$VM_NET_BRIDGE$i [ -z "$nicmac" -a -z "$nictap" -a -z "$nictype" -a -z "$nicbridge" ] && continue nicmac=${nicmac:-"52:54:00:00:0$VM_MAC:0$((i+1))"} bridge=`printf %02d $i` port=`printf %02d $VM_VNC` nictap=${nictap:-"${bridge}${port}"} nictype=${nictype:-"virtio"} nicbridge=${nicbridge:-"${bridge}"} if [ "$nictype" != "none" ]; then nics="$nics -net nic,vlan=$i,model=$nictype,macaddr=$nicmac \ -net tap,vlan=$i,ifname=tap$nictap,script=no,downscript=no" "$SUDO" "$TAPUTIL" "$mode" "$nictap" "$nicbridge" || exit 1 fi done } function vm_start() { local files local filename local filetype local filecache local i local have_cdrom local cdroms echo "Starting $VM_NAME" vm_nics "add" files="" for i in {0..9}; do eval filename=\$VM_FILE_NAME$i eval filetype=\$VM_FILE_TYPE$i eval filecache=\$VM_FILE_CACHE$i filetype=${filetype:-"virtio"} filecache=${filecache:-"none"} [ -n "$filename" -a "$filename" != "none" ] && files="$files \ -drive format=raw,cache=$filecache,file=$basedir/disks/$filename.raw,if=$filetype" done have_cdrom=-1 for i in "$@"; do [ "$i" = "-cdrom" ] && have_cdrom=0 done cdroms="" for i in {0..3}; do [ $i -lt $VM_CDROMS -a $have_cdrom -ne $i ] && cdroms="$cdroms \ -drive readonly=on,media=cdrom,if=ide,bus=1,unit=$i" done qemu-system-x86_64 --enable-kvm -k de -rtc base=utc -daemonize -m "$VM_MEM" \ -name "$VM_NAME" -cpu "$VM_CPU" -machine "$VM_MACHINE" -smp "$VM_CPUS" \ $files \ $nics \ $cdroms \ -soundhw ac97 \ -balloon virtio \ -vnc :"$VM_VNC" -monitor tcp::"$VM_PORT",server,nowait \ -pidfile "$VM_PID" \ $VM_EXTRA \ "$@" sleep 1 if [ "$VM_LAUNCH_VNC" = "1" ]; then vm_vnc fi echo >/dev/tcp/localhost/$VM_PORT } function vm_quit() { local i local p echo quit | nc localhost $VM_PORT & echo -n "waiting 30 seconds for $VM_NAME to quit" for i in {0..30}; do sleep 1 echo -n "." p=`cat "$VM_PID" 2>/dev/null` || { echo "ok"; return; } kill -0 "$p" 2>/dev/null || { echo "ok"; rm -f "$VM_PID"; return; } done echo "did neither shutdown nor quit, killing" p=`cat "$VM_PID"` || return rm -f "$VM_PID" kill "$p" } function vm_stop() { local i local p echo "Stopping $VM_NAME" [ -n "$VM_SHUT_HOST" ] && net rpc shutdown -f \ -U "$VM_SHUT_DOMAIN"'\'"$VM_SHUT_USER"'%'"$VM_SHUT_PASS" -t 2 \ -I "$VM_SHUT_HOST" echo system_powerdown | nc localhost $VM_PORT & echo -n "waiting 150 seconds for $VM_NAME to shutdown" for i in {0..180}; do sleep 1 echo -n "." p=`cat "$VM_PID" 2>/dev/null` || { echo "ok"; return; } kill -0 "$p" 2>/dev/null || { echo "ok"; rm -f "$VM_PID"; return; } done vm_quit } function vm_cmd() { exec telnet localhost $VM_PORT } case "$1" in start) shift vm_start "$@" ;; stop) vm_stop vm_nics "del" ;; quit) vm_quit vm_nics "del" ;; vnc) vm_vnc ;; cmd) vm_cmd ;; *) echo "usage: $0 [ option ... ]" >&2 exit 1 ;; esac