#!/bin/bash
### BEGIN INIT INFO
# Provides:          xendomains
# Required-Start:    $syslog $remote_fs xen
# Required-Stop:     $syslog $remote_fs xen
# Should-Start:      drbd iscsi openvswitch-switch
# Should-Stop:       drbd iscsi openvswitch-switch
# X-Start-Before:    corosync heartbeat
# X-Stop-After:      corosync heartbeat
# 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

. /lib/init/vars.sh
. /lib/lsb/init-functions

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

xen list &> /dev/null
if test $? -ne 0
then
	exit 0;
fi

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

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

shopt -s nullglob

check_config_name()
{
  xen create --quiet --dryrun --defconfig "$1" | sed -n 's/^.*(name \(.*\))$/\1/p'
}

check_running()
{
  xen domid "$1" > /dev/null 2>&1
  return $?
}

timeout_coproc()
{
  local TIMEOUT=$1
  shift

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

  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
    log_action_cont_msg
  done

  kill -INT "$COPROC_PID" >/dev/null 2>&1
  wait $PID
  local rc=$?
  log_action_end_msg $rc

  [ $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
    log_action_cont_msg
  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##*/}"
      log_action_begin_msg "Restoring Xen domain $name (from $file)"

      out=$(xen restore "$file" 2>&1 1>/dev/null)
      case "$?" in
        0) 
          rm "$file"
          domains[$name]='started'
          log_action_end_msg 0
          ;;
        *) 
          domains[$name]='failed'
          log_action_end_msg 1
          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
      log_action_msg "Xen domain $name already running"
    else
      log_action_begin_msg "Starting Xen domain $name (from $file)"

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

do_start() 
{
  declare -A domains

  do_start_restore
  do_start_auto
}

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

  while read id name rest; do
    log_action_begin_msg "Migrating Xen domain $name ($id)"
    (timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" xen migrate $id $XENDOMAINS_MIGRATE)
  done < <(/usr/lib/xen-common/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
    log_action_begin_msg "Saving Xen domain $name ($id)"
    (timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" xen save $id $XENDOMAINS_SAVE/$name)
  done < <(/usr/lib/xen-common/bin/xen-init-list)
}

do_stop_shutdown()
{
  while read id name rest; do
    log_action_begin_msg "Shutting down Xen domain $name ($id)"
    xen shutdown $id 2>&1 1>/dev/null
    log_action_end_msg $?
  done < <(/usr/lib/xen-common/bin/xen-init-list)
  while read id name rest; do
    log_action_begin_msg "Waiting for Xen domain $name ($id) to shut down"
    timeout_domain "$name" "$XENDOMAINS_STOP_MAXWAIT"
    log_action_end_msg $?
  done < <(/usr/lib/xen-common/bin/xen-init-list)
}

do_stop()
{
  do_stop_migrate
  do_stop_save
  do_stop_shutdown
}

case "$1" in
  start)
    do_start
    ;;

  stop)
    do_stop
    ;;

  restart)
    do_stop
    do_start
    ;;

  reload|force-reload)
    do_stop
    do_start
    ;;

  *)
    echo "Usage: $0 {start|stop|restart|reload|force-reload}"
    exit 3
    ;;
esac

exit 0
