--- 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")
;;