Wednesday, June 1, 2011

VirtualBox Daemon

This is a quick post about running VirtualBox guest images as daemons from a headless Ubuntu server host. Most of this can be found in Brendan Kidwell's post located at...

http://www.glump.net/howto/virtualbox_as_a_service

...so I am mostly re-posting it here for myself and others in case his post is ever removed.

First, take a look at the VirtualBox service manager script that is installed with VBox. It is located at /etc/default/virtualbox. This script is run when the computer is shutdown, so it is a good place to tell the computer what to do about an any running virtualbox guest VMs. I modified or added the following lines so it would look for guest images running at my user and save their state, as apposed to just shutting them down.

SHUTDOWN_USERS="user1 user2" # space-delimited list of users who might have runnings vms
SHUTDOWN=savestate # if any are found, suspend them to disk. Could be shutoff too


Next, you need to create a new service manager script to run when the computer starts up. This is a standard startup script in most distributions of linux and usually placed in the /etc/init.d/ directory. You can use the script from the bottom of this post to startup one VirtualBox guest VM, so name it with the guest name and copy it like so...
sudo cp virtualbox-machinename /etc/init.d/virtualbox-machinename

#! /bin/sh
### BEGIN INIT INFO
# Provides:          virtualbox-!!SHORTNAME
# Required-Start:    $local_fs $remote_fs vboxdrv vboxnet
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: !!LONGNAME virtual machine
# Description:       !!LONGNAME virtual machine hosted by VirtualBox
### END INIT INFO
 
# Author: Brendan Kidwell 
#
# Based on /etc/init.d/skeleton from Ubuntu 8.04. Updated for Ubuntu 9.10.
# If you are using Ubuntu <9.10, you might need to change "Default-Stop"
# above to "S 0 1 6".
 
# Do NOT "set -e"
 
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/sbin:/usr/bin:/sbin:/bin
DESC="!!LONGNAME virtual machine"
NAME=virtualbox-!!SHORTNAME
SCRIPTNAME=/etc/init.d/$NAME
 
MANAGE_CMD=VBoxManage
VM_OWNER=!!USERNAME
VM_NAME="!!LONGNAME" #This has to be the name exactly as it appears in your VirtualBox GUI control panel.
 
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
 
# 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
 
#
# 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
 
 sudo -H -u $VM_OWNER $MANAGE_CMD showvminfo "$VM_NAME"|grep "^State:\s*running" >/dev/null && {
     echo "$VM_NAME" is already running.
     return 1
 }
 
 sudo -H -u $VM_OWNER $MANAGE_CMD startvm "$VM_NAME" -type vrdp >/dev/null || {
     echo Failed to start "$VM_NAME".
     return 2
 }
 
 echo "$VM_NAME" started or resumed.
 return 0
}
 
#
# 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
 
 sudo -H -u $VM_OWNER $MANAGE_CMD showvminfo "$VM_NAME"|grep "^State:\s*running" >/dev/null || {
     echo "$VM_NAME" is already stopped.
     return 1
 }
 
 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
}
 
#
# Display "State" field from showinfo action
#
do_status()
{
 sudo -H -u $VM_OWNER $MANAGE_CMD showvminfo "$VM_NAME"|grep "^State:\s*.*$"
}
 
case "$1" in
  start)
 [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
 do_start
 case "$?" in
  0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
 esac
 ;;
  stop)
 [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
 do_stop
 case "$?" in
  0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
 esac
 ;;
  restart|force-reload)
 #
 # If the "reload" option is implemented then remove the
 # 'force-reload' alias
 #
 log_daemon_msg "Restarting $DESC" "$NAME"
 do_stop
 case "$?" in
   0|1)
  do_start
  case "$?" in
   0) log_end_msg 0 ;;
   1) log_end_msg 1 ;; # Old process is still running
   *) log_end_msg 1 ;; # Failed to start
  esac
  ;;
   *)
    # Failed to stop
  log_end_msg 1
  ;;
 esac
 ;;
  status)
 do_status
 ;;
  *)
 #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
 exit 3
 ;;
esac

Then set the permissions so it can be executable and leave the owner set to root

sudo chmod 755 virtualbox-machinename


Now you can test it with...

./etc/init.d/virtualbox-machinename status # Is the VM running?
./etc/init.d/virtualbox-machinename start  # Start the VM
./etc/inid.d/virtualbox-machinename stop   # Stop the VM


Run the command top to see if a VBoxHeadless process is running. Now we need to install the script with the host computer. Use the update-rc.d command to install the script. I like to add another argument (99) to this to make sure that the script is made to run late in the bootup process. That way there is not a problem if this process relies on some other service that has not been run yet.

sudo update-rc.d -f virtualbox-machinename defaults 99


You are done! You can repeat this process for any other virtual machines you would like to run on this host computer.

Links:
https://help.ubuntu.com/community/UbuntuBootupHowto
http://www.glump.net/howto/virtualbox_as_a_service
http://www.liberiangeek.net/2010/05/how-to-start-stop-services-in-ubuntu-lucid-automatically/
http://www.virtualbox.org/manual/ch08.html
http://www.howtoforge.com/vboxheadless-running-virtual-machines-with-virtualbox-4.0-on-a-headless-ubuntu-11.04-server

1 comment:

  1. Thanks for the script. Really helped me out!

    ReplyDelete

Note: Only a member of this blog may post a comment.