File init.xendomains of Package xen.481

#!/bin/bash
#
# xendomains	Starts and stops Xen VMs
#
# chkconfig: 35 99 00
# description: Starts and stops Xen VMs
#
### BEGIN INIT INFO
# Provides:          xendomains
# Required-Start:    $syslog $remote_fs xenstored xenconsoled
# Should-Start:      xend iscsi o2cb ocfs2
# Required-Stop:     $syslog $remote_fs xenstored xenconsoled
# Should-Stop:       xend iscsi
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: Starts and stops Xen VMs
# Description:       Starts and stops Xen VMs automatically when the
#                    host starts and stops.
### END INIT INFO

. /etc/rc.status
rc_reset

RETCODE_FILE=/tmp/xendomains.rc.$$
xm_cmd=echo

# See docs/misc/distro_mapping.txt
if [ -d /var/lock/subsys ]; then
	LOCKFILE=/var/lock/subsys/xendomains
else
	LOCKFILE=/var/lock/xendomains
fi

if [ -d /etc/sysconfig ]; then
	XENDOM_CONFIG=/etc/sysconfig/xendomains
else
	XENDOM_CONFIG=/etc/default/xendomains
fi

test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
	if [ "$1" = "stop" ]; then exit 0;
	else exit 6; fi; }

. "$XENDOM_CONFIG"

shopt -s dotglob nullglob

smart_term=1
if [ -z "$esc" ]; then
	smart_term=0
	rc_timer_on()
	{
		(trap "exit 0" TERM; sleep $1) & _rc_timer_pid=$!
	}
	rc_timer_off()
	{
		if [ -n "$_rc_timer_pid" ]; then
			kill -TERM $_rc_timer_pid > /dev/null 2>&1
		fi
		unset _rc_timer_pid
	}
fi

xendomains_abort()
{
	echo -n "xendomains "
	rc_failed $1
	rc_status -v
	rc_exit
}

check()
{
	XEND=`pidof -x /usr/sbin/xend`
	if [ -z "$XEND" ]; then
		xm_cmd="xl -f"
		XEND="xl"
	else
		xm_cmd="xm"
	fi
	if [ "$1" = status ]; then
		if [ ! -e /proc/xen/capabilities ] || [ ! -r "$XENDOM_CONFIG" ] || [ -z "$XEND" ]; then
			xendomains_abort 3
		fi
	else
		if [ `id -u` != 0 ]; then
			xendomains_abort 4
		fi
		if [ ! -e /proc/xen/capabilities ] || [ -z "$XEND" ] ||
		     ! grep control_d /proc/xen/capabilities >/dev/null 2>&1; then
			if [ "$1" = stop ] ||
			   [ "$1" = restart ]; then
				xendomains_abort 0
			else
				xendomains_abort 6
			fi
		fi
		if [ ! -r "$XENDOM_CONFIG" ]; then
			xendomains_abort 6
		fi
	fi
}

dir_contains_something()
{
        [ -d "$1" ] || return 1
	local dirfiles=( "$1"/* )
	[ ${#dirfiles[@]} != 0 ]
}

get_name_from_cfg()
{
	if grep -q "^name" "$1";then
		NM=`grep '^name[	 ]*=' "$1" | sed -e 's/^name[	 ]*=[	 ]*['\''"]\([^'\''"]*\)['\''"].*$/\1/'`
	elif grep -q "(name " "$1";then
		NM=`grep '(name ' "$1" | sed -e 's/^ *//' | cut -d " " -f 2 | sed -e 's/)//'`
	fi
}

running_auto_names()
{
	unset AUTONAMES[@]
	if ! dir_contains_something "$XENDOMAINS_AUTO"; then
		return
	fi
	for dom in "$XENDOMAINS_AUTO"/*; do
		get_name_from_cfg "$dom"
		AUTONAMES+=("$NM")
	done
}

parseln()
{
	name=${1:0:$((${#1}-36))}
	name=${name%% *}
	rest="${1: -36}"
	id=${rest:0:4}
	id=`echo $id`
	mem=${rest:4:6}
	mem=`echo $mem`
	vcpu=${rest:10:6}
	vcpu=`echo $vcpu`
	state=${rest:16:11}
	state=`echo $state`
	tm=${rest:27}
	tm=`echo $tm`
}

xm_list()
{
	TERM=vt100 ${xm_cmd} list | grep -v '^Name *ID'
}

is_cfg_running()
{
	get_name_from_cfg "$1"
	while read LN; do
		parseln "$LN"
		[ "$id" = 0 ] && continue
		if [ "$name" = "$NM" ]; then
			[ -z "$state" ] && return 1
			return 0
		fi
	done < <(xm_list)
	return 1
}

start()
{
	if [ -f "$LOCKFILE" ]; then
		echo -n "xendomains already running (lockfile exists)"
		rc_reset
		rc_status -v
		return 0
	fi

	local printed=0

	if [ "$XENDOMAINS_RESTORE" = "true" ] &&
	   dir_contains_something "$XENDOMAINS_SAVE"; then
		mkdir -p $(dirname "$LOCKFILE")
		touch "$LOCKFILE"
		echo "Restoring saved Xen domains"
		printed=1
		for dom in "$XENDOMAINS_SAVE"/*; do
			echo -n "	${dom##*/}: "
			${xm_cmd} restore "$dom" >/dev/null 2>&1
			if [ $? -ne 0 ]; then
				rc_failed
			else
				rc_reset
				rm -f "$dom"
			fi
			rc_status -v
		done
	fi

	if dir_contains_something "$XENDOMAINS_AUTO"; then
		touch "$LOCKFILE"
		echo "Starting auto Xen domains"
		printed=1
		for dom in "$XENDOMAINS_AUTO"/*; do
			echo -n "	${dom##*/}: "
			if is_cfg_running "$dom"; then
				rc_status -s
			else
				if grep -q "^name" "$dom";then
					${xm_cmd} create --quiet --defconfig "$dom"
				elif grep -q "(name .*" "$dom";then
					${xm_cmd} create --quiet --config "$dom"
				fi
				if [ $? -ne 0 ]; then
				    rc_failed
				else
				    usleep $XENDOMAINS_CREATE_USLEEP
				    rc_reset
				fi
				rc_status -v
			fi
		done
	fi

	if [ $printed -eq 0 ]; then
		echo -n "Starting xendomains"
		rc_failed 6  # not configured
		rc_status -v
	fi
}

is_zombie_state()
{
	[ "$1" = "-b---d" ] || [ "$1" = "-----d" ]
}

any_non_zombies()
{
	while read LN; do
		parseln "$LN"
		[ "$id" = 0 ] && continue
		[ -z "$state" ] && continue
		is_zombie_state "$state" || return 0
	done < <(xm_list)
	return 1
}

migrate_with_watchdog()
{
	(${xm_cmd} migrate "$@" ; echo $? > "$RETCODE_FILE") >/dev/null 2>&1 &
	watchdog_xm $!
}

save_with_watchdog()
{
	(${xm_cmd} save "$@" ; echo $? > "$RETCODE_FILE") >/dev/null 2>&1 &
	watchdog_xm $!
}

shutdown_with_watchdog()
{
	(${xm_cmd} shutdown -w "$@" ; echo $? > "$RETCODE_FILE") >/dev/null 2>&1 &
	watchdog_xm $!
}

get_return_code()
{
	local RC=127
	[ -r "$RETCODE_FILE" ] && RC=`head -c10 "$RETCODE_FILE"`
	rm -f "$RETCODE_FILE"
	return $RC
}

#  $1:  The PID to wait on.
watchdog_xm()
{
	local col=$((COLUMNS-11))
	if [ -z "$XENDOMAINS_STOP_MAXWAIT" ] || [ "$XENDOMAINS_STOP_MAXWAIT" = "0" ]; then
		wait $1 >/dev/null 2>&1
		get_return_code
		return
	fi

	rc_timer_on $XENDOMAINS_STOP_MAXWAIT $col
	while true; do
		# Prefer "jobs" over "ps":  faster and no false positives
		pid=`jobs -l | grep " $1 Running"`
		if [ -z "$pid" ]; then
			break
		fi
		pid=`jobs -l | grep " $_rc_timer_pid Running"`
		if [ -z "$pid" ]; then
			disown $1  # To avoid the "Terminated..." message
			kill $1 >/dev/null 2>&1
		fi
		sleep 1
	done
	rc_timer_off
	if [ $smart_term -ne 0 ]; then
		echo -en "\015${esc}[${col}C      "
	fi
	get_return_code
}

stop()
{
	echo "Shutting down Xen domains"
	if [ "$XENDOMAINS_AUTO_ONLY" = "true" ]; then
		running_auto_names
	fi
	local printed=0
	while read LN; do
		parseln "$LN"
		[ "$id" = 0 ] && continue
		[ -z "$state" ] && continue
		printed=1
		if [ "$XENDOMAINS_AUTO_ONLY" = "true" ]; then
			is_auto_domain=0
			for n in "${AUTONAMES[@]}"; do
				if [ "$name" = "$n" ]; then
					is_auto_domain=1
					break
				fi
			done
			if [ $is_auto_domain -eq 0 ]; then
				echo -n "	$name: "
				rc_status -s
				continue
			fi
		fi
		if [ -n "$XENDOMAINS_SYSRQ" ]; then
			for sysrq in $XENDOMAINS_SYSRQ; do
				echo -n "	$name: "
				echo -n "sending sysrq '$sysrq'... "
				${xm_cmd} sysrq $id $sysrq
				if [ $? -ne 0 ]; then
					rc_failed
				else
					rc_reset
				fi
				rc_status -v
				# usleep just ignores empty arg
				usleep $XENDOMAINS_USLEEP
			done
		fi
		if is_zombie_state "$state"; then
			echo -n "	$name: "
			echo -n "destroying zombie... "
			${xm_cmd} destroy $id
			rc_reset
			rc_status -v
			continue
		fi
		if [ -n "$XENDOMAINS_MIGRATE" ]; then
			echo -n "	$name: "
			echo -n "migrating... "
			migrate_with_watchdog $id "$XENDOMAINS_MIGRATE"
			if [ $? -ne 0 ]; then
				rc_failed
				rc_status -v
			else
				rc_reset
				rc_status -v
				continue
			fi
		fi
		if [ -n "$XENDOMAINS_SAVE" ]; then
			echo -n "	$name: "
			echo -n "saving... "
			save_with_watchdog $id "$XENDOMAINS_SAVE/$name"
			if [ $? -ne 0 ]; then
				rm -f "$XENDOMAINS_SAVE/$name"
				rc_failed
				rc_status -v
			else
				rc_reset
				rc_status -v
				continue
			fi
		fi
		if [ -n "$XENDOMAINS_SHUTDOWN" ]; then
			echo -n "	$name: "
			echo -n "shutting down... "
			shutdown_with_watchdog $id $XENDOMAINS_SHUTDOWN
			if [ $? -ne 0 ]; then
				rc_failed
			else
				rc_reset
			fi
			rc_status -v
		fi
	done < <(xm_list)

	if [ -n "$XENDOMAINS_SHUTDOWN_ALL" ] && any_non_zombies ; then
		echo -n "	others: shutting down... "
		shutdown_with_watchdog $XENDOMAINS_SHUTDOWN_ALL
		if [ $? -ne 0 ]; then
			rc_failed
		else
			rc_reset
		fi
		rc_status -v
	fi

	if [ $printed -eq 0 ]; then
		echo -e "${rc_done_up}"
	fi

	# Unconditionally delete lock file
	rm -f "$LOCKFILE"
}

check_domain_up()
{
	while read LN; do
		parseln "$LN"
		[ "$id" = 0 ] && continue
		if [ "$name" = "$1" ]; then
			[ -z "$state" ] && return 1
			return 0
		fi
	done < <(xm_list)
	return 1
}

check_all_domains_up()
{
	any_auto=0
	any_save=0
	dir_contains_something "$XENDOMAINS_AUTO" && any_auto=1
	dir_contains_something "$XENDOMAINS_SAVE" && any_save=1
	if [ $any_auto -eq 0 ] && [ $any_save -eq 0 ]; then
		rc_reset
		rc_status -v
		return
	fi
	echo
	if [ $any_auto -ne 0 ]; then
		for nm in "$XENDOMAINS_AUTO"/*; do
			get_name_from_cfg "$nm"
			echo -n "	$nm: "
			if check_domain_up "$NM"; then
				rc_reset
			else
				rc_failed 2
			fi
			rc_status -v
		done
	fi
	if [ $any_save -ne 0 ]; then
		for nm in "$XENDOMAINS_SAVE"/*; do
			echo -n "	$nm: "
			rc_failed 3
			rc_status -v
		done
	fi
}

# This does NOT necessarily restart all running domains: instead it
# stops all running domains and then boots all the domains specified in
# AUTODIR.  If other domains have been started manually then they will
# not get restarted.
restart()
{
	"$0" stop
	start
}

case "$1" in
 start)
	check $1
	start
	;;

 stop)
	check $1
	stop
	;;

 restart|reload)
	check $1
	restart
	;;

 try-restart)
	check $1
	"$0" status
	if [ $? = 0 ]; then
		"$0" restart
	else
		rc_reset
		rc_status -v
	fi
	;;

 status)
	check $1
	echo -n "Checking status of Xen domains"
	if [ ! -f "$LOCKFILE" ]; then
		rc_failed 3
		rc_status -v
	else
		check_all_domains_up
	fi
	;;

 *)
	echo "Usage: $0 {start|stop|restart|try-restart|reload|status}"
	rc_failed 2
	;;
esac

rc_exit
openSUSE Build Service is sponsored by