--- xendomains.org	2008-04-27 22:37:02.000000000 +0900
+++ xendomains	2008-05-05 07:47:27.000000000 +0900
@@ -14,6 +14,10 @@
 # Applications HOWTO" by Avi Alkalay
 # <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
 #
+# Revised by T.Nonogaki, Stray Penguin
+# <http://www.asahi-net.or.jp/~aa4t-nngk/>
+# Rev.0.1.2
+#
 ### BEGIN INIT INFO
 # Provides:          xendomains
 # Required-Start:    $syslog $remote_fs xend
@@ -66,8 +70,10 @@
 	    #echo -n "  [${_SMSG[${_RC_RV}]}] "
 	    if test ${_RC_RV} = 0; then
 		success "  [${_SMSG[${_RC_RV}]}] "
+		echo
 	    else
 		failure "  [${_SMSG[${_RC_RV}]}] "
+		echo
 	    fi
 	}
     elif test -e /lib/lsb/init-functions; then
@@ -128,7 +134,7 @@
     }
 fi
 
-if ! which usleep >&/dev/null
+if ! which usleep &>/dev/null
 then
   usleep()
   {
@@ -159,8 +165,8 @@
 # read name from xen config file
 rdname()
 {
-    NM=$(xm create --quiet --dryrun --defconfig "$1" |
-         sed -n 's/^.*(name \(.*\))$/\1/p')
+    NM=$(env LANG=C virsh dominfo ${1##*/} 2>/dev/null |
+         awk '/^Name:[[:space:]]+/ { print $2; exit; }')
 }
 
 rdnames()
@@ -182,10 +188,21 @@
 
 parseln()
 {
-    name=`echo "$1" | cut -c0-17`
+    local numf
+    name=`echo "$@" | cut -c0-17`
     name=${name%% *}
-    rest=`echo "$1" | cut -c18- `
-    read id mem cpu vcpu state tm < <(echo "$rest")
+    rest=`echo "$@" | cut -c18-`
+    numf=`echo $rest | wc -w`
+    if [ $numf -eq 5 ]; then
+        read id mem vcpu state tm < <(echo "$rest")
+    elif [ $numf -eq 4 ]; then
+        read mem vcpu state tm < <(echo "$rest")
+        id=""
+    else
+        read mem vcpu tm < <(echo "$rest")
+        id=""
+        state=""
+    fi
 }
 
 is_running()
@@ -194,20 +211,41 @@
     RC=1
     while read LN; do
 	parseln "$LN"
-	if test $id = 0; then continue; fi
+	if [ "$id" = "0" -o -z "$id" ]; then continue; fi
 	case $name in 
-	    ($NM)
+	     $NM)
 		RC=0
+		break
 		;;
 	esac
-    done < <(xm list | grep -v '^Name')
+    done < <(xm list | grep -Ev 'Name[[:space:]]+ID')
+    return $RC
+}
+
+is_running_by_virsh()
+{
+    rdname $1
+    RC=1
+    while read LN; do
+	read id name state < <(echo "$LN")
+	if [ "$id" = "0" -o "$state" = "shut off" ]; then continue; fi
+	case $name in 
+	     $NM)
+		RC=0
+		break
+		;;
+	esac
+    done < <(env LANG=C virsh list --all 2>/dev/null |
+	grep -E '^ +' | grep -Ev '^ *Id +Name')
     return $RC
 }
 
 start() 
 {
-    if [ -f $LOCKFILE ]; then 
+    local RETVAL
+    if [ -f $LOCKFILE ]; then
 	echo -n "xendomains already running (lockfile exists)"
+	rc_failed
 	return; 
     fi
 
@@ -215,28 +253,29 @@
     if [ "$XENDOMAINS_RESTORE" = "true" ] &&
        contains_something "$XENDOMAINS_SAVE"
     then
-        mkdir -p $(dirname "$LOCKFILE")
-	touch $LOCKFILE
-	echo -n "Restoring Xen domains:"
+        [ -d $(dirname "$LOCKFILE") ] || 
+           mkdir -p $(dirname "$LOCKFILE")
+	echo -n "Restoring Xen domains: "
 	saved_domains=`ls $XENDOMAINS_SAVE`
 	for dom in $XENDOMAINS_SAVE/*; do
-	    echo -n " ${dom##*/}"
-	    xm restore $dom
-	    if [ $? -ne 0 ]; then
-		rc_failed $?
+	    echo -n "${dom##*/} "
+	    xm restore $dom &>/dev/null
+	    RETVAL=$?
+	    if [ $RETVAL -ne 0 ]; then
+		rc_failed $RETVAL
 		echo -n '!'
 	    else
+		touch $LOCKFILE
 		# mv $dom ${dom%/*}/.${dom##*/}
 		rm $dom
 	    fi
+	echo -n ". "
 	done
-	echo .
+	HAVE_SAVE=1
     fi
 
     if contains_something "$XENDOMAINS_AUTO"
     then
-	touch $LOCKFILE
-	echo -n "Starting auto Xen domains:"
 	# We expect config scripts for auto starting domains to be in
 	# XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
 
@@ -246,80 +285,137 @@
 	# If a domain statefile from $XENDOMAINS_SAVE matches a domain name
 	# in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't 
 	# restore correctly it requires administrative attention.
+	[ $HAVE_SAVE -eq 1 ] && echo
+	echo -n "Starting auto Xen domains: "
 	for dom in $XENDOMAINS_AUTO/*; do
-	    echo -n " ${dom##*/}"
 	    shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
-	    echo $saved_domains | grep -w $shortdom > /dev/null
-	    if [ $? -eq 0 ] || is_running $dom; then
+	    echo -n " $shortdom"
+	    echo $saved_domains | grep -w $shortdom >/dev/null
+	    if [ $? -eq 0 ]; then
+		echo -n "(skip)"
+	    elif is_running $shortdom && is_running_by_virsh $shortdom; then
 		echo -n "(skip)"
 	    else
+		echo -n " "
 		xm create --quiet --defconfig $dom
-		if [ $? -ne 0 ]; then
-		    rc_failed $?
+		RETVAL=$?
+		if [ $RETVAL -ne 0 ]; then
+		    rc_failed $RETVAL
 		    echo -n '!'
 		else
+		    touch $LOCKFILE
 		    usleep $XENDOMAINS_CREATE_USLEEP
 		fi
+		HAVE_AUTO=1
 	    fi
+	    echo -n ". "
 	done
+	[ $HAVE_AUTO -eq 1 ] || echo
     fi	
 }
 
+# Return TRUE if it seems only zombie domains (not in shutdown process)
+# are left, FALSE if no domains left or found any shutting-down healthily.
 all_zombies()
 {
     while read LN; do
 	parseln "$LN"
-	if test $id = 0; then continue; fi
+	if [ "$id" = "0" -o -z "$id" ]; then continue; fi
 	if test "$state" != "-b---d" -a "$state" != "-----d"; then
-	    return 1;
+	    return 1
 	fi
-    done < <(xm list | grep -v '^Name')
+    done < <(xm list | grep -Ev 'Name[[:space:]]+ID')
     return 0
 }
 
-# Wait for max $XENDOMAINS_STOP_MAXWAIT for xm $1 to finish;
+# Return TRUE if it seems only zombie domains (not in shutdown process)
+# left, FALSE if no domains left or found any shutting-down healthily.
+# FIXME: State obtained via virsh is not so strict as xm.
+# Are these check conditions correct?
+all_zombies_by_virsh()
+{
+    local all=0
+    local zomb=0
+    while read LN; do
+	read id name state < <(echo "$LN")
+	if [ "$id" = "0" -o "$state" = "shut off" ]; then continue; fi
+	: $((all++))
+	if test "$state" = "no state"; then
+	    : $((zomb++))
+	fi
+    done < <(env LANG=C virsh list --all 2>/dev/null |
+	grep -E '^ +' | grep -Ev '^ *Id +Name')
+    [ $all -eq 0 ] && return 1
+    [ $all -eq $zomb ] && return 0
+    return 1
+}
+
+# Call syntax: watchdog_xm -c $act {-d $dom|-f}
+# Wait for max $XENDOMAINS_STOP_MAXWAIT for `xm $dom $id' to finish;
 # if it has not exited by that time kill it, so the init script will
-# succeed within a finite amount of time; if $2 is nonnull, it will
-# kill the command as well as soon as no domain (except for zombies)
-# are left (used for shutdown --all).
+# succeed within a finite amount of time; if $force (-f) is nonnull,
+# it will kill the command as well as soon as no domain (except for
+# zombies) are left (used for shutdown --all).
 watchdog_xm()
 {
+    local act dom
+    local force=0
     if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
 	exit
     fi
-    usleep 20000
+    while getopts "c:d:f" opt; do
+	case $opt in
+	    c)
+		act=$OPTARG;;
+	    d)
+		dom=$OPTARG;;
+	    f)
+		force=1
+		dom=$XENDOMAINS_SHUTDOWN_ALL;;
+	esac
+    done
+    shift $(($OPTIND -1))
+    usleep 300000
     for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
 	# exit if xm save/migrate/shutdown is finished
-	PSAX=`ps axlw | grep "xm $1" | grep -v grep`
-	if test -z "$PSAX"; then exit; fi
+	PSAX=`ps axlw | grep "xm $act $dom" | grep -v grep`
+	[ -z "$PSAX" ] && exit
 	echo -n "."; sleep 1
 	# go to kill immediately if there's only zombies left
-	if all_zombies && test -n "$2"; then break; fi
+	if [ $force -eq 1 ]; then
+	    #if all_zombies || all_zombies_by_virsh; then
+	    if all_zombies; then
+		#echo "Domain $dom seems zombie"
+		break
+	    fi
+	fi
     done
     sleep 1
     read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
-    # kill xm $1
-    kill $PSPID >/dev/null 2>&1
+    # kill `xm $act $dom' process
+    kill $PSPID &>/dev/null
+    exit
 }
 
 stop()
 {
+    local RETVAL
     # Collect list of domains to shut down
     if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
 	rdnames
     fi
-    echo -n "Shutting down Xen domains:"
+    echo -n "Shutting down Xen domains: "
     while read LN; do
 	parseln "$LN"
-	if test $id = 0; then continue; fi
-	echo -n " $name"
+	if [ "$id" = "0" -o -z "$id" ]; then continue; fi
+	echo -n "$name"
 	if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
 	    case $name in
-		($NAMES)
+		$NAMES)
 		    # nothing
 		    ;;
-		(*)
-		    echo -n "(skip)"
+		*)
+		    echo "(skip). "
 		    continue
 		    ;;
 	    esac
@@ -330,9 +426,10 @@
 	if test -n "$XENDOMAINS_SYSRQ"; then
 	    for sysrq in $XENDOMAINS_SYSRQ; do
 		echo -n "(SR-$sysrq)"
-		xm sysrq $id $sysrq
-		if test $? -ne 0; then
-		    rc_failed $?
+		xm sysrq $id $sysrq &>/dev/null
+		RETVAL=$?
+		if [ $RETVAL -ne 0 ]; then
+		    rc_failed $RETVAL
 		    echo -n '!'
 		fi
 		# usleep just ignores empty arg
@@ -340,67 +437,78 @@
 	    done
 	fi
 	if test "$state" = "-b---d" -o "$state" = "-----d"; then
-	    echo -n "(zomb)"
+	    echo -n "(zomb). "
 	    continue
 	fi
 	if test -n "$XENDOMAINS_MIGRATE"; then
 	    echo -n "(migr)"
-	    watchdog_xm migrate &
+	    watchdog_xm -c migrate -d $name &
 	    WDOG_PID=$!
-	    xm migrate $id $XENDOMAINS_MIGRATE
-	    if test $? -ne 0; then
-		rc_failed $?
-		echo -n '!'
-		kill $WDOG_PID >/dev/null 2>&1
+	    xm migrate $name $XENDOMAINS_MIGRATE &>/dev/null
+	    RETVAL=$?
+	    if [ $RETVAL -ne 0 ]; then
+		rc_failed $RETVAL
+		echo -n '!. '
+		kill $WDOG_PID &>/dev/null
 	    else
-		kill $WDOG_PID >/dev/null 2>&1
+		#kill $WDOG_PID &>/dev/null
+		echo -n ". "
 		continue
 	    fi
 	fi
 	if test -n "$XENDOMAINS_SAVE"; then
 	    echo -n "(save)"
-	    watchdog_xm save &
+	    watchdog_xm -c save -d $name &
 	    WDOG_PID=$!
 	    mkdir -p "$XENDOMAINS_SAVE"
-	    xm save $id $XENDOMAINS_SAVE/$name
-	    if test $? -ne 0; then
-		rc_failed $?
-		echo -n '!'
-		kill $WDOG_PID >/dev/null 2>&1
+	    xm save $name ${XENDOMAINS_SAVE}/$name &>/dev/null
+	    RETVAL=$?
+	    if [ $RETVAL -ne 0 ]; then
+		rc_failed $RETVAL
+		echo -n '!. '
+		kill $WDOG_PID &>/dev/null
 	    else
-		kill $WDOG_PID >/dev/null 2>&1
+		#kill $WDOG_PID &>/dev/null
+		echo -n ". "
 		continue
 	    fi
 	fi
 	if test -n "$XENDOMAINS_SHUTDOWN"; then
 	    # XENDOMAINS_SHUTDOWN should be "--halt --wait"
 	    echo -n "(shut)"
-	    watchdog_xm shutdown &
+	    watchdog_xm -c shutdown -d $name &
 	    WDOG_PID=$!
-	    xm shutdown $id $XENDOMAINS_SHUTDOWN
-	    if test $? -ne 0; then
-		rc_failed $?
+	    xm shutdown $name $XENDOMAINS_SHUTDOWN &>/dev/null
+	    RETVAL=$?
+	    if [ $RETVAL -ne 0 ]; then
+		rc_failed $RETVAL
 		echo -n '!'
+		kill $WDOG_PID &>/dev/null
 	    fi
-	    kill $WDOG_PID >/dev/null 2>&1
+	    echo -n ". "
 	fi
-    done < <(xm list | grep -v '^Name')
+    done < <(xm list | grep -Ev 'Name[[:space:]]+ID')
 
     # NB. this shuts down ALL Xen domains (politely), not just the ones in
     # AUTODIR/*
     # This is because it's easier to do ;-) but arguably if this script is run
     # on system shutdown then it's also the right thing to do.
-    if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
-	# XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
-	echo -n " SHUTDOWN_ALL "
-	watchdog_xm shutdown 1 &
-	WDOG_PID=$!
-	xm shutdown $XENDOMAINS_SHUTDOWN_ALL
-	if test $? -ne 0; then
-	    rc_failed $?
-	    echo -n '!'
+    if test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
+	#if ! all_zombies && ! all_zombies_by_virsh; then
+	if ! all_zombies; then
+	    # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
+	    echo
+	    echo -n "SHUTDOWN_ALL "
+	    watchdog_xm -c shutdown -f &
+	    WDOG_PID=$!
+	    xm shutdown $XENDOMAINS_SHUTDOWN_ALL >/dev/null
+	    RETVAL=$?
+	    if [ $RETVAL -ne 0 ]; then
+		rc_failed $RETVAL
+		echo -n '!'
+		kill $WDOG_PID >/dev/null 2>&1
+	    fi
 	fi
-	kill $WDOG_PID >/dev/null 2>&1
     fi
 
     # Unconditionally delete lock file
@@ -411,13 +519,13 @@
 {
     while read LN; do
 	parseln "$LN"
-	if test $id = 0; then continue; fi
+	if [ "$id" = "0" -o -z "$id" ]; then continue; fi
 	case $name in 
-	    ($1)
+	    $1)
 		return 0
 		;;
 	esac
-    done < <(xm list | grep -v "^Name")
+    done < <(xm list | grep -Ev 'Name[[:space:]]+ID')
     return 1
 }
 
@@ -464,7 +572,9 @@
 restart()
 {
     stop
+    rc_status -v
     start
+    rc_status
 }
 
 reload()
@@ -472,6 +582,8 @@
     restart
 }
 
+HAVE_SAVE=0
+HAVE_AUTO=0
 
 case "$1" in
     start)
