/libexec.xendomains
# · Bash · 564 lines · 520 code · 44 blank · 0 comment · 0 complexity · 079680ce151f0b036716119ba87fafaa MD5 · raw file
- #!/bin/bash
- #
- # /etc/init.d/xendomains
- # Start / stop domains automatically when domain 0 boots / shuts down.
- #
- # chkconfig: 345 99 00
- # description: Start / stop Xen domains.
- #
- # This script offers fairly basic functionality. It should work on Redhat
- # but also on LSB-compliant SuSE releases and on Debian with the LSB package
- # installed. (LSB is the Linux Standard Base)
- #
- # Based on the example in the "Designing High Quality Integrated Linux
- # Applications HOWTO" by Avi Alkalay
- # <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
- #
- ### BEGIN INIT INFO
- # Provides: xendomains
- # Required-Start: $syslog $remote_fs xenstored xenconsoled
- # Should-Start: xend
- # Required-Stop: $syslog $remote_fs xenstored xenconsoled
- # Should-Stop: xend
- # Default-Start: 2 3 4 5
- # Default-Stop: 0 1 6
- # Short-Description: Start/stop secondary xen domains
- # Description: Start / stop domains automatically when domain 0
- # boots / shuts down.
- ### END INIT INFO
- CMD=xl
- $CMD list &> /dev/null
- if test $? -ne 0
- then
- CMD=xm
- fi
- $CMD list &> /dev/null
- if test $? -ne 0
- then
- exit 0;
- fi
- # Correct exit code would probably be 5, but it's enough
- # if xend complains if we're not running as privileged domain
- if ! [ -e /proc/xen/privcmd ]; then
- exit 0
- fi
- # 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
- # Use the SUSE rc_ init script functions;
- # emulate them on LSB, RH and other systems
- if test -e /etc/rc.status; then
- # SUSE rc script library
- . /etc/rc.status
- else
- _cmd=$1
- declare -a _SMSG
- if test "${_cmd}" = "status"; then
- _SMSG=(running dead dead unused unknown)
- _RC_UNUSED=3
- else
- _SMSG=(done failed failed missed failed skipped unused failed failed)
- _RC_UNUSED=6
- fi
- if test -e /lib/lsb/init-functions; then
- # LSB
- . /lib/lsb/init-functions
- if alias log_success_msg >/dev/null 2>/dev/null; then
- echo_rc()
- {
- echo " [${_SMSG[${_RC_RV}]}] "
- }
- else
- echo_rc()
- {
- if test ${_RC_RV} = 0; then
- log_success_msg " [${_SMSG[${_RC_RV}]}] "
- else
- log_failure_msg " [${_SMSG[${_RC_RV}]}] "
- fi
- }
- fi
- else
- # emulate it
- echo_rc()
- {
- echo " [${_SMSG[${_RC_RV}]}] "
- }
- fi
- rc_reset() { _RC_RV=0; }
- rc_failed()
- {
- if test -z "$1"; then
- _RC_RV=1;
- elif test "$1" != "0"; then
- _RC_RV=$1;
- fi
- return ${_RC_RV}
- }
- rc_check()
- {
- return rc_failed $?
- }
- rc_status()
- {
- rc_failed $?
- if test "$1" = "-r"; then _RC_RV=0; shift; fi
- if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
- if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
- if test "$1" = "-v"; then echo_rc; shift; fi
- if test "$1" = "-r"; then _RC_RV=0; shift; fi
- return ${_RC_RV}
- }
- rc_exit() { exit ${_RC_RV}; }
- rc_active()
- {
- if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
- if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
- return 1
- }
- fi
- if ! which usleep >&/dev/null
- then
- usleep()
- {
- if [ -n "$1" ]
- then
- sleep $(( $1 / 1000000 ))
- fi
- }
- fi
- # Reset status of this service
- rc_reset
- ##
- # Returns 0 (success) if the given parameter names a directory, and that
- # directory is not empty.
- #
- contains_something()
- {
- if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
- then
- return 0
- else
- return 1
- fi
- }
- # read name from xen config file
- rdname()
- {
- NM=$($CMD create --quiet --dryrun --defconfig "$1" |
- sed -n 's/^.*(name \(.*\))$/\1/p')
- }
- rdnames()
- {
- NAMES=
- if ! contains_something "$XENDOMAINS_AUTO"
- then
- return
- fi
- for dom in $XENDOMAINS_AUTO/*; do
- rdname $dom
- if test -z $NAMES; then
- NAMES=$NM;
- else
- NAMES="$NAMES|$NM"
- fi
- done
- }
- parseln()
- {
- if [[ "$1" =~ '(domain' ]]; then
- name=;id=
- else if [[ "$1" =~ '(name' ]]; then
- name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
- else if [[ "$1" =~ '(domid' ]]; then
- id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
- fi; fi; fi
- [ -n "$name" -a -n "$id" ] && return 0 || return 1
- }
- is_running()
- {
- rdname $1
- RC=1
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- case $name in
- ($NM)
- RC=0
- ;;
- esac
- done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
- return $RC
- }
- start()
- {
- if [ -f $LOCKFILE ]; then
- echo -e "xendomains already running (lockfile exists)"
- return;
- fi
- saved_domains=" "
- if [ "$XENDOMAINS_RESTORE" = "true" ] &&
- contains_something "$XENDOMAINS_SAVE"
- then
- mkdir -p $(dirname "$LOCKFILE")
- touch $LOCKFILE
- echo -n "Restoring Xen domains:"
- saved_domains=`ls $XENDOMAINS_SAVE`
- for dom in $XENDOMAINS_SAVE/*; do
- if [ -f $dom ] ; then
- HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
- if [ $HEADER = "LinuxGuestRecord" ]; then
- echo -n " ${dom##*/}"
- XMR=`$CMD restore $dom 2>&1 1>/dev/null`
- #$CMD restore $dom
- if [ $? -ne 0 ]; then
- echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR"
- rc_failed $?
- echo -e '!'
- else
- # mv $dom ${dom%/*}/.${dom##*/}
- rm $dom
- fi
- fi
- fi
- done
- echo -e
- 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
- # Create all domains with config files in XENDOMAINS_AUTO.
- # TODO: We should record which domain name belongs
- # so we have the option to selectively shut down / migrate later
- # 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.
- 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 "(skip)"
- else
- XMC=`$CMD create --quiet --defconfig $dom`
- if [ $? -ne 0 ]; then
- echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n"
- rc_failed $?
- echo -e '!'
- else
- usleep $XENDOMAINS_CREATE_USLEEP
- fi
- fi
- done
- fi
- }
- all_zombies()
- {
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- if test "$state" != "-b---d" -a "$state" != "-----d"; then
- return 1;
- fi
- done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
- return 0
- }
- # Wait for max $XENDOMAINS_STOP_MAXWAIT for $CMD $1 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). Third parameter, if any, suppresses
- # output of dots per working state (formatting issues)
- watchdog_xencmd()
- {
- if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
- exit
- fi
- usleep 20000
- for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
- # exit if $CMD save/migrate/shutdown is finished
- PSAX=`ps axlw | grep "$CMD $1" | grep -v grep`
- if test -z "$PSAX"; then exit; fi
- if ! test -n "$3"; then echo -n '.'; fi
- sleep 1
- # go to kill immediately if there's only zombies left
- if all_zombies && test -n "$2"; then break; fi
- done
- sleep 1
- read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
- # kill $CMD $1
- kill $PSPID >/dev/null 2>&1
-
- echo -e .
- }
- stop()
- {
- exec 3>&2 2> /dev/null
-
- # Collect list of domains to shut down
- if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
- rdnames
- fi
- echo -n "Shutting down Xen domains:"
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- echo -n " $name"
- if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
- eval "
- case \"\$name\" in
- ($NAMES)
- # nothing
- ;;
- (*)
- echo -e '(skip)'
- continue
- ;;
- esac
- "
- fi
- # XENDOMAINS_SYSRQ chould be something like just "s"
- # or "s e i u" or even "s e s i u o"
- # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
- if test -n "$XENDOMAINS_SYSRQ"; then
- for sysrq in $XENDOMAINS_SYSRQ; do
- echo -n "(SR-$sysrq)"
- XMR=`$CMD sysrq $id $sysrq 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n"
- rc_failed $?
- echo -n '!'
- fi
- # usleep just ignores empty arg
- usleep $XENDOMAINS_USLEEP
- done
- fi
- if test "$state" = "-b---d" -o "$state" = "-----d"; then
- echo -n "(zomb)"
- continue
- fi
- if test -n "$XENDOMAINS_MIGRATE"; then
- echo -n "(migr)"
- watchdog_xencmd migrate &
- WDOG_PID=$!
- XMR=`$CMD migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while migrating domain:\n$XMR\n"
- rc_failed $?
- echo -e '!'
- kill $WDOG_PID >/dev/null 2>&1
- else
- kill $WDOG_PID >/dev/null 2>&1
-
- echo -e .
- usleep 1000
- continue
- fi
- fi
- if test -n "$XENDOMAINS_SAVE"; then
- echo -n "(save)"
- watchdog_xencmd save &
- WDOG_PID=$!
- mkdir -p "$XENDOMAINS_SAVE"
- XMR=`$CMD save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while saving domain:\n$XMR\n"
- rc_failed $?
- echo -e '!'
- kill $WDOG_PID >/dev/null 2>&1
- else
- kill $WDOG_PID >/dev/null 2>&1
- echo -e .
- usleep 1000
- continue
- fi
- fi
- if test -n "$XENDOMAINS_SHUTDOWN"; then
- # XENDOMAINS_SHUTDOWN should be "--halt --wait"
- echo -n "(shut)"
- watchdog_xencmd shutdown &
- WDOG_PID=$!
- XMR=`$CMD shutdown $id $XENDOMAINS_SHUTDOWN 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while shutting down domain:\n$XMR\n"
- rc_failed $?
- echo -e '!'
- fi
- kill $WDOG_PID >/dev/null 2>&1
- fi
- done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
- # 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_xencmd shutdown 1 false &
- WDOG_PID=$!
- XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null`
- if test $? -ne 0; then
- echo -e "\nAn error occurred while shutting down all domains: $XMR\n"
- rc_failed $?
- echo -e '!'
- fi
- kill $WDOG_PID >/dev/null 2>&1
- fi
- # Unconditionally delete lock file
- rm -f $LOCKFILE
-
- exec 2>&3
- }
- check_domain_up()
- {
- name=;id=
- while read LN; do
- parseln "$LN" || continue
- if test $id = 0; then continue; fi
- case $name in
- ($1)
- return 0
- ;;
- esac
- done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
- return 1
- }
- check_all_auto_domains_up()
- {
- if ! contains_something "$XENDOMAINS_AUTO"
- then
- return 0
- fi
- missing=
- for nm in $XENDOMAINS_AUTO/*; do
- rdname $nm
- found=0
- if check_domain_up "$NM"; then
- echo -n " $name"
- else
- missing="$missing $NM"
- fi
- done
- if test -n "$missing"; then
- echo -n " MISS AUTO:$missing"
- return 1
- fi
- return 0
- }
- check_all_saved_domains_up()
- {
- if ! contains_something "$XENDOMAINS_SAVE"
- then
- return 0
- fi
- missing=`/bin/ls $XENDOMAINS_SAVE`
- echo -n " MISS SAVED: " $missing
- return 1
- }
- # 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.
- # Commented out to avoid confusion!
- restart()
- {
- stop
- start
- }
- reload()
- {
- restart
- }
- case "$1" in
- start)
- start
- rc_status
- if test -f $LOCKFILE; then rc_status -v; fi
- ;;
- stop)
- stop
- rc_status -v
- ;;
- restart)
- restart
- ;;
- reload)
- reload
- ;;
- status)
- echo -n "Checking for xendomains:"
- if test ! -f $LOCKFILE; then
- rc_failed 3
- else
- check_all_auto_domains_up
- rc_status
- check_all_saved_domains_up
- rc_status
- fi
- rc_status -v
- ;;
- *)
- echo "Usage: $0 {start|stop|restart|reload|status}"
- rc_failed 3
- rc_status -v
- ;;
- esac
- rc_exit