All pastes #1973954 Raw Edit

Something

public text v1 · immutable
#1973954 ·published 2010-10-26 20:17 UTC
rendered paste body
# Version: 20100414.2

## Aims:
# - Do not configure VM in this script - except vrdp port
# - If run as root, get list of VM's to action from /etc/vbox/init.d
# - If run as a user, get list of VM's to action from $HOME/.VirtualBox/init.d

## Actions:
# - start: run VM
# - stop: save VM state
# - status: showvminfo
# - restart|force-reload: start+stop
# - poweroff: send acpi power off sequence to the guest

## Todo:
# - fix the startvm incantation to get useful exit codes. eg nice will complain if a non-root user tries to use
#   a value less than 0. sudo will complain if the user does not exist.
#   VBoxHeadless probably has many things to complain about.
# - get list of VM's from /etc/vbox/init.d
# - tidy up comments, debug echo's, etc
# - make sure all variables are properly quoted. ie "$VM_NAME" instead of
#   $VM_NAME
# - add GPL license
# - add debian update-rc.d control info: begin INIT info -> end init info
#   from /etc/rc.d/skeleton

## Wishlist:
# - teleport control
# - make a debian package or get this included in the official VirtualBox debian package

### BEGIN INIT INFO
# Provides:          vbox
# Required-Start:    $network vboxnet vboxdrv
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: VirtualBox server autostart
# Description:       Enable service provided by daemon.
### END INIT INFO

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/sbin:/usr/bin:/sbin:/bin
MANAGE_CMD=/usr/bin/VBoxManage
HEADLESS_CMD=/usr/bin/VBoxHeadless
SCRIPTNAME=/etc/init.d/virtualbox
CONFIG_DIR=/etc/vbox/vms

### hacky internal configuration should *really* come from a config file
VM_NAME="Windows XP"
VM_OWNER="vbox"
VM_VRDP="3389"
VM_NICE="-1"

echo VM_NAME: $VM_NAME VM_OWNER: $VM_OWNER VM_NICE: $VM_VRDP VM_NICE=$VM_NICE

if [ "$(id -u)" != "0" ]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

# Load the VERBOSE setting and other rcS variables
[ -f /etc/default/rcS ] && . /etc/default/rcS

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# Load network defaults. Use this if there is any extra network stuff to do first.
[ -f /etc/vbox/network ] && . /etc/vbox/network

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started

    # get state
    do_status

    case "$vm_status" in
      running)
       echo "$VM_NAME" is already running
   return 1
      ;;

      "poweroff")
   echo $VM_NAME is starting as user $VM_OWNER with priority $VM_NICE
        # Need to sleep between startvm else we get a GURU_MEDITATION(crash)
        sleep 1
   ## this command tested to start vm successfully. what a mouthful and the exit code is crud:
   nice -${VM_NICE} sudo -H -u $VM_OWNER $HEADLESS_CMD --startvm "$VM_NAME" --vrdpport $VM_VRDP > /dev/null 2>&1 &
   ##
   echo 'exit code:' $?
   # case $? in
     # 0)
          # echo started "$VM_NAME"
          # return 0
          #;;

     #  *)
          # echo failed to start "$VM_NAME"
          # return 1
          #;;
    # esac

      ;;

      saved)
   echo $VM_NAME is resuming as user $VM_OWNER with priority $VM_NICE
        # Need to sleep between startvm else we get a GURU_MEDITATION(crash)
        sleep 1
   ## this command tested to start vm successfully. what a mouthful and the exit code is crud:
   # we cannot change the vrdp port on a vm in saved state
   nice -${VM_NICE} sudo -H -u $VM_OWNER $HEADLESS_CMD --startvm "$VM_NAME" > /dev/null 2>&1 &
   ##
   echo 'exit code:' $?
        # use return handler from poweroff
   return 0
      ;;

      *)
        echo "$VM_NAME" is not in an awkward state: "$vm_status"
        return 2
      ;;

      esac

}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred

    do_status
    case "$vm_status" in
      "poweroff"|saved)
        echo "$VM_NAME" is already stopped. Exact state: "$vm_status"
        return 1
      ;;

      running)
   sudo -H -u $VM_OWNER $MANAGE_CMD controlvm "$VM_NAME" savestate || {
        echo Failed to stop "$VM_NAME".
        return 2
   }
   echo "$VM_NAME" suspended.
   return 0
      ;;

      *)
        echo $VM_NAME is in awkward state: $vm_status
        return 3
      ;;
    esac

}

do_poweroff()
{
   ### need to check if state is running
   sudo -H -u $VM_OWNER $MANAGE_CMD controlvm "$VM_NAME" acpipowerbutton
   ##### need error handler *********************
}

#
# Display "State" field from showinfo action
#
do_status()
{
#    sudo -H -u $VM_OWNER $MANAGE_CMD showvminfo "$VM_NAME"|grep "^State:\s*.*$"
#vm_status=`sudo -H -u $VM_OWNER $MANAGE_CMD showvminfo "$VM_NAME" | grep '^State' | sed 's/^State:\s*//' | sed 's/\s(since.*$//'`
vm_status=`sudo -H -u $VM_OWNER $MANAGE_CMD showvminfo "$VM_NAME" --machinereadable | grep 'VMState=' | cut -d '"' -f2`
#vm_status=$(VBoxManage showvminfo $VMNAME --machinereadable | grep 'VMState=' | cut -d '"' -f2)
}

case "$1" in
  start)
#    (#IFS=/
#    cd $CONFPATH
#    echo $CONFPATH
#    pwd
#    for conf in *.conf; do
#   echo $CONFPATH/$conf
#        . $CONFPATH/$conf
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $VM_NAME"
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
#    done;)

    ;;
  stop)
#    (#IFS=/
#    cd "$CONFPATH"
#    for conf in *.conf; do
#        . "$CONFPATH"/$conf
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $VM_NAME"
        do_stop
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2|3) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
#    done;)
    ;;
  restart|force-reload)
#    (#IFS=/
#    cd "$CONFPATH"
#    for conf in *.conf; do
#        . "$CONFPATH"/$conf
        [ "$VERBOSE" != no ] && log_daemon_msg "Restarting $VM_NAME"
        do_stop
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2|3) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
#    done;)
    ;;
  status)
#    (#IFS=/
#    cd "$CONFPATH"
#    for conf in *.conf; do
#        . "$CONFPATH"/$conf
   do_status
        echo "Status for $VM_NAME": ${vm_status}


#    done;)
    ;;
  poweroff)
     do_poweroff
     exit 3
    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|poweroff|status}" >&2
    exit 3
    ;;
esac