File virtualbox-ose-vboxes of Package virtualbox-ose

#!/bin/sh
#
# chkconfig: - 91 35
# description: Starts and stops vbox autostart VMs.
# Based on
# http://www.amiryan.org/2009/11/04/virtualbox-init-d-service-autostart-scriptu
#
# By Richard Bos <rbos at opensuse dot org> - May 2010

### BEGIN INIT INFO
# Provides: vboxes
# Required-Start: $network vboxdrv $ALL
# Required-Stop: $network $named
# Default-Start: 3 5
# Default-Stop: 0 1 2 3 4 5 6
# Short-Description: Autostart Virtual Box VMs
# Description: Autostart Virtual Box VMs that are mentioned in /etc/sysconfig/vbox file
### END INIT INFO

# Shell functions sourced from /etc/rc.status:
#      rc_check         check and set local and overall rc status
#      rc_status        check and set local and overall rc status
#      rc_status -v     be verbose in local rc status and clear it afterwards
#      rc_status -v -r  ditto and clear both the local and overall rc status
#      rc_status -s     display "skipped" and exit with status 3
#      rc_status -u     display "unused" and exit with status 3
#      rc_failed        set local and overall rc status to failed
#      rc_failed <num>  set local and overall rc status to <num>
#      rc_reset         clear both the local and overall rc status
#      rc_exit          exit appropriate to overall rc status
#      rc_active        checks whether a service is activated by symlinks
. /etc/rc.status

# Reset status of this service
rc_reset

# Return values acc. to LSB for all commands but status:
# 0       - success
# 1       - generic or unspecified error
# 2       - invalid or excess argument(s)
# 3       - unimplemented feature (e.g. "reload")
# 4       - user had insufficient privileges
# 5       - program is not installed
# 6       - program is not configured
# 7       - program is not running
# 8--199  - reserved (8--99 LSB, 100--149 distrib, 150--199 appl)
#
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signaling is not supported) are
# considered a success.

VBOXMGR_BIN=/usr/lib/virtualbox/VBoxManage
if [[ ! -x $VBOXMGR_BIN ]]; then
  echo "$VBOXMGR_BIN does not exist"
  if [ "$1" = "stop" ]; then
    exit 0;
  else
    exit 6
  fi;
fi

VBOXHeadLess_BIN=/usr/lib/virtualbox/VBoxHeadless
if [[ ! -x $VBOXHeadLess_BIN ]]; then
  echo "$VBOXHeadLess_BIN does not exist"
  if [ "$1" = "start" ]; then
    exit 6;
  else
    exit 0
  fi;
fi

PRG=$(basename $0)
SERVICE="Virtualbox machines"

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

start() {

  N=1
  for VBOX in $VBOX_AUTOSTART; do

    if grep -q \; <<< "$VBOX"; then
      VBOX_NAME[$N]=$(cut -d\; -f1 <<< "$VBOX")
      VBOX_USER[$N]=$(cut -d\; -f2 <<< "$VBOX")
    else
      VBOX_NAME[$N]="$VBOX"
      VBOX_USER[$N]=""
    fi
    N=$(($N+1)) 
  done

  VBOXES=${#VBOX_NAME[*]}

  if [ $VBOXES -eq 0 ]; then
    # The virtual machines have to be configured in /etc/sysconfig/vbox
    echo -n "Starting $SERVICE: no virtual machines configured"
    rc_status -u
  else

    N=1
    echo -n "Starting $SERVICE: "
    while [[ $N -le $VBOXES ]]; do
      if [[ $N -lt $VBOXES ]]; then
        echo -n "${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]}), "
      else
        echo "${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]})"
      fi
      N=$(($N+1)) 
    done

    N=1
    while [[ $N -le $VBOXES ]]; do

      if [[ -n "${VBOX_USER[$N]}" ]]; then

        if grep --quiet --word-regexp ${VBOX_USER[$N]} /etc/passwd; then

          # The tag "Name:" occurs in multiple sections.  Require at least 7 blanks
          # with an additional flexible amount of spaces.  At the moment of writing
          # 13 spaces are needed.
          VBOX_RUNNING=$(su ${VBOX_USER[$N]} -c "VBoxManage list --long runningvms"  |
            sed -n 's/^Name:[[:blank:]]\{7\} *//p' | grep -w "${VBOX_NAME[$N]}")

          if [[ -z "$VBOX_RUNNING" ]]; then

            VBOX_PRESENT=$(su ${VBOX_USER[$N]} -c "$VBOXMGR_BIN list --long vms" |
              sed -n 's/^Name:[[:blank:]]\{7\} *//p' | grep -w "${VBOX_NAME[$N]}")

            if [[ -n "$VBOX_PRESENT" ]]; then

              # VBoxManage startvm does not result in a VM with working networking
              # su ${VBOX_USER[$N]} -c "$VBOXMGR_BIN -q startvm "${VBOX_NAME[$N]}" -type headless" > /tmp/$PRG.$$ 2>&1
              # Start virtualbox in Headless mode
              su ${VBOX_USER[$N]} -c "$VBOXHeadLess_BIN --startvm "${VBOX_NAME[$N]}"" > /tmp/$PRG.$$ 2>&1 &
              RETVAL=$?

              if [[ $RETVAL == 0 ]]; then
                echo -n " Starting virtual machine: ${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]})"
                rc_status -v -r
              else
                echo -n " Starting virtual machine: ${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]}) failed with the following output: "
                rc_failed; rc_status -v -r
                # Give the VBOXHeadLess_BIN some time to write the output file
                sleep 2
                cat /tmp/$PRG.$$
              fi

              rm /tmp/$PRG.$$

            else
              echo -n " Virtual machine: ${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]}) does not exist"
              rc_status -s -r
            fi

          else
            echo -n " Virtual machine: ${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]}) is already running"
            rc_status -v -r
          fi

        else
          echo -n " Virtual machine: ${VBOX_NAME[$N]}, VBOX_USER: ${VBOX_USER[$N]} does not exist"
          rc_status -s -r
        fi

      else
        echo -n " Virtual machine: ${VBOX_NAME[$N]}: VBOX_USER not configured"
        rc_status -s -r
      fi

      N=$(($N+1))
    done
  fi
}

stop() {

  for VBOX in $VBOX_AUTOSTART; do

    if grep -q \; <<< "$VBOX"; then
      VBOX_USER=$(cut -d\; -f2 <<< "$VBOX")

      # Only add the user to the list, if not present yet
      if ! grep -qw "$VBOX_USER" <<< "$VBOX_USERS"; then
        VBOX_USERS="$VBOX_USERS $VBOX_USER"
      fi
    fi
  done

  N=1
  for VBOX_USER in $VBOX_USERS; do
    VBOX_RUNNING=$(su $VBOX_USER -c "$VBOXMGR_BIN list --long runningvms" |
      sed -n 's/^Name:[[:blank:]]\{7\} *//p')
    for VBOX in $VBOX_RUNNING; do
      VBOX_NAME[$N]="$VBOX"
      VBOX_USER[$N]="$VBOX_USER"
      N=$(($N+1)) 
    done
  done

  VBOXES=${#VBOX_NAME[*]}

  if [[ $VBOXES -eq 0 ]]; then
    echo -n "Shutting down $SERVICE: no virtual machines running."
    rc_status -s -r
  else

    echo -n "Shutting down $SERVICE: "
    N=1
    while [[ $N -le $VBOXES ]]; do
      if [[ $N -lt $VBOXES ]]; then
        echo -n "${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]}), "
      else
        echo "${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]})"
      fi
      N=$(($N+1)) 
    done

    N=1
    while [[ $N -le $VBOXES ]]; do

      echo -n " ${VBOX_NAME[$N]}: "
      su ${VBOX_USER[$N]} -c "$VBOXMGR_BIN -q controlvm "${VBOX_NAME[$N]}" savestate"
      RETVAL=$?

      echo -n " Shutting down virtual machine: ${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]})"
      if [[ $RETVAL == $? ]]; then
        rc_status -v -r
      else
        rc_failed; rc_status -v -r
      fi
      N=$(($N+1)) 
    done
  fi
}

status() {

  for VBOX in $VBOX_AUTOSTART; do

    if grep -q \; <<< "$VBOX"; then
      VBOX_USER=$(cut -d\; -f2 <<< "$VBOX")

      # Only add the user to the list, if not present yet
      if ! grep -qw "$VBOX_USER" <<< "$VBOX_USERS"; then
        VBOX_USERS="$VBOX_USERS $VBOX_USER"
      fi
    fi
  done

  N=1
  for VBOX_USER in $VBOX_USERS; do
    # The tag "Name:" occurs in multiple sections.  Require at least 7 blanks
    # with an additional flexible amount of spaces.  At the moment of writing
    # 13 spaces are needed.
    VBOX_RUNNING=$(su $VBOX_USER -c "$VBOXMGR_BIN list --long runningvms" |
      sed -n 's/^Name:[[:blank:]]\{7\} *//p')
    for VBOX in $VBOX_RUNNING; do
      VBOX_NAME[$N]="$VBOX"
      VBOX_USER[$N]="$VBOX_USER"
      N=$(($N+1)) 
    done
  done

  VBOXES=${#VBOX_NAME[*]}

  if [[ $VBOXES -eq 0 ]]; then
    echo -n "$SERVICE: no virtual machines running."
    rc_status -s -r
  else
    N=1
    while [[ $N -le $VBOXES ]]; do
      # The long sed line changes the output from:
      #    running (since 2010-04-25T14:51:57.373000000)
      # to:
      #    running (since 2010-04-25 14:51:57)
      #
      STATE=$(su ${VBOX_USER[$N]} -c "$VBOXMGR_BIN showvminfo "${VBOX_NAME[$N]}"" |
        sed -n 's/State: *//p' |
        sed 's/\([0-9][0-9]\)\.[0-9]\{9\}/\1/;s/\([0-9][0-9]\)T\([0-9][0-9]\)/\1 \2/')
      printf " %-56s %s" "${VBOX_NAME[$N]} (user: ${VBOX_USER[$N]}):" "$STATE"
      rc_status -v
      N=$(($N+1))
    done
  fi
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart|force-reload)
        stop
        start
        ;;
  status)
        status
        ;;
  *)
        echo "Usage: $PRG {start|stop|restart|force-reload|status}" >&2
        exit 3
        ;;
esac