# HG changeset patch # User heiko # Date 1225190530 0 # Node ID 1ab9431a52bcae75481d3a65a8bf890e7e874f72 # Parent d8aba2189a2784b28401d4f811c96704f43ceed7 - more sophisticated - still open: ugly messages from job control diff -r d8aba2189a27 -r 1ab9431a52bc kvmctl --- a/kvmctl Sat Oct 25 22:20:50 2008 +0000 +++ b/kvmctl Tue Oct 28 10:42:10 2008 +0000 @@ -4,6 +4,8 @@ # status: in development # 2008 Heiko Schlittermann +# Should be written in Perl! + # Structure of virtual machine directories # $BASE (see below, hard coded into this script) # | @@ -23,8 +25,8 @@ # +-- -action="${1?}"; shift -vm="$1" ; shift +action="${1?}"; shift # mandatory +vm="$1" ; shift # optional # no user service able parts below @@ -45,8 +47,9 @@ die() { echo $ME: "$@" >&2; exit 1; } warn() { echo $ME: "$@" >&2; } -silent() { "$@" &>/dev/null; } +silently() { "$@" &>/dev/null; } +debug() { echo "DEBUG: $@" >&2; } unique_ids() { local dups=$(cat $BASE/*/conf/id 2>/dev/null | sort -n | uniq -c \ @@ -54,6 +57,7 @@ test "$dups" || return 0 ERR="$dups" && return 1 } + convert_dirs() { for dir in $BASE/*; do test -d $dir/kvm || test -d $dir/conf || continue @@ -64,6 +68,32 @@ done } +monitor() { + local port=$1; shift + local command="$1"; shift + + # check, if the monitor is available, kill if somebody + # else is using it + local client=$(netstat -tn | egrep ":$port[[:space:]]+EST" | tr -s ' ' | cut -f4 -d' ') + test "${client%:*}" = 127.0.0.1 && fuser -k ${client#*:}/tcp + + local pid0 pid1 + ( + local a=$tmp/a.fifo; mkfifo $a + trap "rm -v $a" EXIT + exec 10<>$a + $NC localhost $port <&10 | { + read || exit # banner + while read -d' '; do test "$REPLY" = "(qemu)" && break; done + echo "$command" >&10 + while read -d' '; do test "$REPLY" = "(qemu)" && break; done + } + ) & pid0=$! + ( sleep $TIMEOUT; kill $pid0 ) & pid1=$! + wait $pid0 + silently kill $pid0 $pid1 +} + ### MAIN # sanity @@ -109,7 +139,7 @@ echo "$options" > $var/running_options test -f $var/frozen && options="$options $(cat $var/frozen)" - if silent fuser $var/pid; then + if silently fuser $var/pid; then echo "running, pid: $pid, display :$id, monitor tcp:127.0.0.1:$port" else ( cd $BASE/$vm && $KVM $options -daemonize ) @@ -119,52 +149,42 @@ fi test "$DISPLAY" && test "$VNCVIEWER" && test -t \ - && ( silent exec $VNCVIEWER :$id $a 1<>$b ) & pid0=$! - read <$b # we should not send anything before we got the first line - echo -e 'system_powerdown\n' >$a - ( cat <$b & sleep $TIMEOUT; silent kill $! $pid0 ) & pid1=$! - wait $pid0 - kill $pid1 2>/dev/null - silent fuser $var/pid && $0 quit $vm + monitor $port "system_powerdown" + silently fuser $var/pid && $0 quit $vm } & ;; quit) { echo "quit $vm" - a=$tmp/a; b=$tmp/b; mkfifo $a $b - ( $NC localhost $port 0<>$a 1<>$b ) & pid0=$! - read <$b - echo -e 'quit\n' >$a - ( cat <$b & sleep $TIMEOUT; silent kill $! $0 ) & pid1=$! - wait $pid0 - kill $pid1 2>/dev/null - silent fuser $var/pid && $0 kill $vm + monitor $port "quit" + silently fuser $var/pid && $0 kill $vm } & ;; kill) echo "killing $vm" kill $pid ;; - freeze) echo "freezing $vm" - fuser -k $port/tcp - echo -e "savevm HIBERNATE\nquit" | $NC localhost $port & - echo "-loadvm HIBERNATE" >$var/frozen + freeze) + { + echo "freezing $vm" + monitor $port "savevm HIBERNATED" + monitor $port "quit" + echo "-loadvm HIBERNATED" >$var/frozen + } & ;; - #status) echo "status $vm: " qemu) echo "DO *NOT* USE \"quit\", use ^C for exiting!" $NC localhost $port ;; list) - echo "$vm:" $(silent fuser $var/pid \ + echo "$vm:" $(silently fuser $var/pid \ && echo "running (pid: $pid)" \ || echo "not running") ;;