- more sophisticated
authorheiko
Tue, 28 Oct 2008 10:42:10 +0000
changeset 4 1ab9431a52bc
parent 3 d8aba2189a27
child 5 b4e073b1250e
- more sophisticated - still open: ugly messages from job control
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 @@
 # +--<vmN>
 
 
-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 </dev/null & )
+        && ( silently exec $VNCVIEWER :$id </dev/null & )
 
         ;;
     stop)   
         {
         echo "stopping (powerdown) $vm"
-        a=$tmp/a; b=$tmp/b; mkfifo $a $b
-        ( $NC localhost $port 0<>$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")
         ;;