#!/bin/bash
#
# xendomains            Start / stop domains automatically when domain 0 boots / shuts down.
#
# chkconfig:            345 99 00
# description:          Start / stop Xen domains.
#

. /etc/rc.d/init.d/functions

if ! [ -e /proc/xen/privcmd ]; then
	exit 0
fi

TOOLSTACK=$(/usr/libexec/xen/bin/xen-toolstack toolstack 2>/dev/null)
if [ $? -ne 0 ]; then
	echo "No usable Xen toolstack selected"
	exit 0
fi
if [ "$(basename "$TOOLSTACK")" != xl ] && [ "$(basename "$TOOLSTACK")" != xm ]; then
	exit 0
fi

if ! /usr/libexec/xen/bin/xen-toolstack list >/dev/null 2>&1 ; then
	exit 0;
fi

[ -r /etc/sysconfig/xendomains ] && . /etc/sysconfig/xendomains

shopt -s nullglob

check_config_name()
{
	/usr/libexec/xen/bin/xen-toolstack create --quiet --dryrun --defconfig "$1" | sed -n 's/^.*(name \(.*\))$/\1/p;s/^.*"name": "\(.*\)",$/\1/p'
}

check_running()
{
	/usr/libexec/xen/bin/xen-toolstack domid "$1" >/dev/null 2>&1
	return $?
}

timeout_coproc()
{
	local TIMEOUT=$1
	shift

	coproc "$@" >/dev/null 2>&1

	local COPROC_OUT
	exec {COPROC_OUT}<&"${COPROC[0]}"
	local PID="$COPROC_PID"

	for no in $(seq 0 $TIMEOUT); do
		if [ -z "$COPROC_PID" ]; then break; fi
		sleep 1
	done

	kill -INT "$COPROC_PID" >/dev/null 2>&1
	wait $PID
	local rc=$?
	if [ $rc -eq 0 ]; then
		ok
	else
		fail
	fi

	[ $rc -gt 0 ] && cat <&$COPROC_OUT
	exec <&$COPROC_OUT-
}

timeout_domain()
{
	name="$1"
	TIMEOUT="$2"
	for no in $(seq 0 $TIMEOUT); do
		if ! check_running "$name"; then return 0; fi
		sleep 1
	done
	return 1
}

do_start_restore()
{
	[ -n "$XENDOMAINS_SAVE" ] || return
	[ -d "$XENDOMAINS_SAVE" ] || return
	[ -n "$XENDOMAINS_RESTORE" ] || return

	for file in $XENDOMAINS_SAVE/*; do
		if [ -f $file ] ; then
			name="${file##*/}"
			show "Restoring Xen domain $name (from $file)"
			busy

			out=$(/usr/libexec/xen/bin/xen-toolstack restore "$file" >/dev/null 2>&1)
			case "$?" in
				0)
					rm "$file"
					domains[$name]='started'
					ok
					;;
				*)
					domains[$name]='failed'
					fail
					echo "$out"
					;;
			esac
		fi
	done
}

do_start_auto()
{
	[ -n "$XENDOMAINS_AUTO" ] || return
	[ -d "$XENDOMAINS_AUTO" ] || return

	for file in $XENDOMAINS_AUTO/*; do
		name="$(check_config_name $file)"

		if [ "${domains[$name]}" = started ]; then
			:
		elif check_running "$name"; then
			echo "Xen domain $name already running"
		else
			show "Starting Xen domain $name (from $file)"
			busy

			if [ "${domains[$name]}" = failed ]; then
				fail
			else
				out=$(/usr/libexec/xen/bin/xen-toolstack create --quiet --defconfig "$file" >/dev/null 2>&1)
				case "$?" in
					0)
						ok
						;;
					*)
						fail
						echo "$out"
						;;
				esac
			fi
		fi
	done
}

do_start() 
{
	declare -A domains

	if [ -f /var/lock/subsys/xendomains ]; then 
		msg_already_running "xendomains"
		return
	fi

	do_start_restore
	do_start_auto

	touch /var/lock/subsys/xendomains
}

do_stop_migrate()
{
	[ -n "$XENDOMAINS_MIGRATE" ] || return

	while read id name rest; do
		show "Migrating Xen domain $name ($id)"
		busy
		(timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" /usr/libexec/xen/bin/xen-toolstack migrate $id $XENDOMAINS_MIGRATE)
	done < <(/usr/libexec/xen/bin/xen-init-list)
}

do_stop_save()
{
	[ -n "$XENDOMAINS_SAVE" ] || return
	[ -d "$XENDOMAINS_SAVE" ] || mkdir -m 0700 -p "$XENDOMAINS_SAVE"

	while read id name rest; do
		show "Saving Xen domain $name ($id)"
		busy
		(timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" /usr/libexec/xen/bin/xen-toolstack save $id $XENDOMAINS_SAVE/$name)
	done < <(/usr/libexec/xen/bin/xen-init-list)
}

do_stop_shutdown()
{
	while read id name rest; do
		show "Shutting down Xen domain $name ($id)"
		busy
		/usr/libexec/xen/bin/xen-toolstack shutdown $id >/dev/null 2>&1
		if [ $? -eq 0 ]; then
			ok
		else
			fail
		fi
	done < <(/usr/libexec/xen/bin/xen-init-list)
	while read id name rest; do
		show "Waiting for Xen domain $name ($id) to shut down"
		busy
		timeout_domain "$name" "$XENDOMAINS_STOP_MAXWAIT"
		if [ $? -eq 0 ]; then
			ok
		else
			fail
		fi
	done < <(/usr/libexec/xen/bin/xen-init-list)
}

do_stop()
{
	if [ ! -f /var/lock/subsys/xendomains ]; then 
		msg_not_running "xendomains"
		return
	fi

	do_stop_migrate
	do_stop_save
	do_stop_shutdown

	rm -f /var/lock/subsys/xendomains
}

case "$1" in
	start)
		do_start
		;;
	stop)
		do_stop
		;;
	restart)
		do_stop
		do_start
		;;
	reload|force-reload)
		do_stop
		do_start
		;;
	status)
		if [ -f /var/lock/subsys/xendomains ]; then
			/usr/libexec/xen/bin/xen-toolstack list -v
		fi
		;;
	*)
		echo "Usage: $0 {start|stop|status|restart|reload|force-reload}"
		exit 3
		;;
esac

exit 0
