vbox-headless: init script for multiple VMs

Discussions related to using VirtualBox on Linux hosts.

vbox-headless: init script for multiple VMs

Postby nte » 25. Sep 2010, 02:56

Hello, I needed an init script to load multiple VMs on boot. Since I could not find an adequate one, here is my solution.

This is a very rough version, I basically hacked it all together in one pass. Use at your own risk -- caveat emptor.

Features
  • configure VirtualBox user
  • run all registered VMs for user or
  • specify list of VMs to run
  • stopping VMs with controlvm savestate
  • uses standard mechanisms, that means
  • ignore already running/stopped VMs
  • manage with system tools, ie. update-rc.d

/etc/init.d/vbox-headless
Code: Select all   Expand viewCollapse view
#! /bin/sh
### BEGIN INIT INFO
# Provides:          vbox-headless
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start VMs in headless mode.
# Description:       This script runs VMs for the default VirtualBox user in
#                    headless mode. Make sure all VMs are using different RDP
#                    ports.
### END INIT INFO

# Author: Nicolas Tessore <n.tessore@gmail.com>

####
# VirtualBox settings
####

# The user which owns the VMs
VBOX_USER=vbox

# The list of VMs to run. Leave empty to run all registered VMs.
VBOX_LIST=""

# VirtualBox executables
VBOX_MANAGE=/usr/bin/VBoxManage
VBOX_HEADLESS=/usr/bin/VBoxHeadless

####
# End VirtualBox settings
####

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="VirtualBox daemon"
NAME=vbox-headless
DAEMON=$VBOX_HEADLESS
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

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


vm_init_list()
{
   # get registered VMs
   LIST_VMS=`sudo -H -u $VBOX_USER $VBOX_MANAGE --nologo list vms | cut -d ' ' -f 1 | tr -d '"'`
   
   # check for list of VMs
   if [ -z "$VBOX_LIST" ]
   then
      # all registered VMs for user
      VBOX_LIST=$LIST_VMS
   else
      # check that VMs exist
      for VM in $VBOX_LIST
      do
         case $LIST_VMS in
         "$VM")
            continue
            ;;
         *)
            log_failure_msg "ERROR: VM '$VM' is not registered!"
            exit 1
            ;;
         esac
      done
   fi
}

# get uuid for vm
vm_get_uuid()
{
   vm=$1
   hwuuid=`sudo -H -u $VBOX_USER $VBOX_MANAGE --nologo showvminfo --machinereadable "$vm" | grep 'hardwareuuid='`
   echo $hwuuid | cut -d '=' -f 2 | tr -d '"'
}

# control running vm
vm_ctrl()
{
   sudo -H -u $VBOX_USER $VBOX_MANAGE --nologo controlvm $1 $2 > /dev/null 2>&1
}

#
# Function that starts the daemon/service
#
do_start()
{
   vm_init_list
   
   # Return
   #   0 if daemon has been started
   #   1 if daemon was already running
   #   2 if daemon could not be started
   RETVAL=0
   
   # Start all VMs
   for VM in $VBOX_LIST
   do
      VM_UUID=`vm_get_uuid $VM`
      VM_PIDFILE="$PIDFILE.$VM_UUID"
      VM_DAEMON="$DAEMON"
      VM_DAEMON_ARGS="$DAEMON_ARGS --startvm $VM_UUID"
      
      log_action_begin_msg "Starting VM '$VM'"
      
      # test for running VM
      USER=$VBOX_USER LOGNAME=$VBOX_USER start-stop-daemon \
         --start \
         --quiet \
         --pidfile $VM_PIDFILE \
         --startas $VM_DAEMON \
         --test \
         > /dev/null
      
      # VM already running
      if [ "$?" != 0 ]
      then
         # report VM is running
         log_warning_msg "VM '$VM' already running"
         [ "$RETVAL" = 0 ] && RETVAL=1
         continue
      fi
      
      # start VM
      USER=$VBOX_USER LOGNAME=$VBOX_USER start-stop-daemon \
         --start \
         --quiet \
         --pidfile $VM_PIDFILE \
         --make-pidfile \
         --background \
         --chuid $VBOX_USER \
         --startas $VM_DAEMON \
         -- $VM_DAEMON_ARGS
      
      log_action_end_msg "$?"
      
      # check if start failed
      if [ "$?" != 0 ]
      then
         # report error
         log_failure_msg "Error starting VM '$VM'"
         RETVAL=2
      fi
   done
   
   if [ "$RETVAL" -lt 2 ]
   then
      log_daemon_msg "VirtualBox daemon started successfully"
   else
      log_daemon_msg "VirtualBox daemon started with errors"
   fi
   
   return "$RETVAL"
}

#
# Function that stops the daemon/service
#
do_stop()
{
   vm_init_list
   
   # 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
   RETVAL=0
   
   for VM in $VBOX_LIST
   do
      VM_UUID=`vm_get_uuid $VM`
      VM_PIDFILE="$PIDFILE.$VM_UUID"
      
      log_action_begin_msg "Stopping VM '$VM'"
      
      # try savestate halt
      vm_ctrl $VM savestate
      
      # stop daemon
      USER=$VBOX_USER LOGNAME=$VBOX_USER start-stop-daemon \
         --stop \
         --quiet \
         --retry=TERM/30/KILL/5 \
         --pidfile $VM_PIDFILE
      
      case "$?" in
      0)
         log_action_end_msg 0
         ;;
      1)
         log_warning_msg "VM '$VM' already stopped"
         [ "$RETVAL" = 0 ] && RETVAL=1
         ;;
      2)
         log_action_end_msg 1
         log_failure_msg "ERROR: Could not stop VM '$VM'"
         RETVAL=2
         continue
         ;;
      esac
      
      rm -f $VM_PIDFILE
   done
   
   if [ "$RETVAL" -lt 2 ]
   then
      log_daemon_msg "VirtualBox daemon stopped successfully"
   else
      log_daemon_msg "VirtualBox daemon stopped with errors"
   fi
   
   return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
   #
   # If the daemon can reload its configuration without
   # restarting (for example, when it is sent a SIGHUP),
   # then implement that here.
   #
   start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
   return 0
}

case "$1" in
  start)
   log_daemon_msg "Starting $DESC" "$NAME"
   do_start
   case "$?" in
      0|1) log_end_msg 0 ;;
      2) log_end_msg 1 ;;
   esac
   ;;
  stop)
   log_daemon_msg "Stopping $DESC" "$NAME"
   do_stop
   case "$?" in
      0|1) log_end_msg 0 ;;
      2) log_end_msg 1 ;;
   esac
   ;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  #reload|force-reload)
   #
   # If do_reload() is not implemented then leave this commented out
   # and leave 'force-reload' as an alias for 'restart'.
   #
   #log_daemon_msg "Reloading $DESC" "$NAME"
   #do_reload
   #log_end_msg $?
   #;;
  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
   ;;
  *)
   #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
   echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
   exit 3
   ;;
esac

:

nte
 
Posts: 1
Joined: 25. Sep 2010, 01:08
Primary OS: Ubuntu other
VBox Version: PUEL
Guest OSses: Windows 2000

Re: vbox-headless: init script for multiple VMs

Postby mr.deek » 3. Mar 2011, 05:47

Hello,

Did you know ...

You can start/manage/stop a VM without the pain of running vbox headless command itself?

Stick this in your startup:

vboxmanage startvm "VMNAME" --type headless

and

vboxmanage controlvm "VMNAME" poweroff

And all will be good.
mr.deek
 
Posts: 9
Joined: 22. Feb 2011, 05:03
Primary OS: Ubuntu other
VBox Version: OSE Debian
Guest OSses: ALL

Re: vbox-headless: init script for multiple VMs

Postby larrykemp » 3. Mar 2011, 19:57

What about when you need to have them gracefully shutdown when the host system is going down for reboot or getting powered off?
larrykemp
 
Posts: 4
Joined: 28. Sep 2010, 22:51
Primary OS: Linux other
VBox Version: OSE other
Guest OSses: Cent OS, Windows

Re: vbox-headless: init script for multiple VMs

Postby mooninite » 3. Mar 2011, 20:50

You should have your scripts save state instead of powering off the VMs.

service vbox-guests start
# Starts all VMs in "Saved State" state.

service vbox-guests stop
# Calls "VBoxManage controlvm $VM savestate"
mooninite
 
Posts: 16
Joined: 17. Jan 2008, 05:50
Primary OS: Fedora other
VBox Version: OSE Fedora
Guest OSses: RHEL, SuSE, SCO OpenServer, Windows XP

Re: vbox-headless: init script for multiple VMs

Postby ofirk » 10. Jul 2011, 16:53

Sorry to bump this topic now, but I have searched the web for days trying to find a working init script for Ubuntu 10.10 (probably will work for 11.04 too), and couldn't find.

I bumped into this post but the script attached to this post didn't work. To keep the (very) long story short, I found a working init script which auto starts a Virtualbox VM at start (boot) and saves its states at shutdown (or reboot).
It can be found at http://www.glump.net/howto/virtualbox_as_a_service, however, since the link refers to an external website, which could be down regardless of this post, I am posting the main parts of that URL here.

Create the init.d Script
Now that you've got your virtual machine setup and configured and tested, you're ready to create and configure scripts in ”/etc/init.d/” to start and suspend the guest on demand.

First, if you look at ”/etc/init.d/vboxdrv”, the service manager script for the VirtualBox kernel driver, you'll see that it looks for a couple of options to tell it what to do with running virtual machines when vboxdrv stops. Create or edit the config file:
Code: Select all   Expand viewCollapse view
sudo touch /etc/default/virtualbox
sudo nano /etc/default/virtualbox


/etc/default/virtualbox:
Code: Select all   Expand viewCollapse view
SHUTDOWN_USERS="user1 user2" # space-delimited list of users who might have runnings vms
SHUTDOWN=savestate # if any are found, suspend them to disk


Now, the above settings only cover the system shutdown process, not startup. VirtualBox itself doesn't provide any mechanism for starting virtual machines automatically. To do that, create a new service manager script of your own.

Items that you need to fill in for yourself marked with ”!!”. In all the example files and commands below, find those items and fill them in with strings that make sense for your personal setup.
Code: Select all   Expand viewCollapse view
sudo touch /etc/init.d/virtualbox-!!SHORTNAME #substitute your machine name here
sudo chmod +x /etc/init.d/virtualbox-!!SHORTNAME
sudo nano /etc/init.d/virtualbox-!!SHORTNAME


/etc/init.d/virtualbox-!!SHORTNAME:
Code: Select all   Expand viewCollapse view
#! /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 <brendan@glump.net>
#
# 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

Thanks to Trevor White who emailed me and suggested I add the -H option to the sudo commands when I said this script wasn't working correctly during boot time.

Test the init.d Script
Test the script's status, start, and start commands:
Code: Select all   Expand viewCollapse view
/etc/init.d/virtualbox-!!SHORTNAME status # Is the VM running?
/etc/init.d/virtualbox-!!SHORTNAME start  # Start the VM
rdesktop localhost                        # Connect to the VM
/etc/inid.d/virtualbox-!!SHORTNAME stop   # Stop the VM


Install the init.d Script
Use the update-rc.d command to install the script.
Code: Select all   Expand viewCollapse view
sudo update-rc.d virtualbox-!!SHORTNAME defaults

Now whenever you enter normal multiuser run mode (at boot time, for example) your VM will start, and when you exit multiuser mode (during shutdown, for example), your VM will be suspended to disk if it was running.

ofirk
 
Posts: 1
Joined: 10. Jul 2011, 16:44
Primary OS: Ubuntu other
VBox Version: PUEL
Guest OSses: XP,Ubuntu

Re: vbox-headless: init script for multiple VMs

Postby ikus060 » 10. Jul 2011, 17:59

To have Virtual machines startup and shutdown with an init script, I use vboxtool. It provide an init script easily configurable to startup vms in headless mode with vrde enabled.

Here the link : http://vboxtool.sourceforge.net/
ikus060
 
Posts: 2
Joined: 10. Jul 2011, 17:56
Primary OS: Ubuntu other
VBox Version: OSE Debian
Guest OSses: Linux, Windows

Re: vbox-headless: init script for multiple VMs

Postby zmerch » 11. Jul 2011, 19:27

I had a need to restart virtual servers gracefully, and this is what I came up with:

Code: Select all   Expand viewCollapse view
vboxserver@avotus-core:~$ cat /etc/init.d/virtuals
#!/bin/sh -e
### BEGIN INIT INFO
# Provides:          virtualservers
# Required-Start:    networking
# Default-Start:     S
# Default-Stop:      0 6
### END INIT INFO
PATH="$PATH:/usr/X11R6/bin/:/usr/lib/virtualbox/"
# The Username:Group that will run VirtualBox
export USER="vboxuser"
#${RUNAS}
# The name that the Virtual Servers will have.
NAME1="Server1"
NAME2="SQLServer"
IP1="10.10.10.5"
IP2="10.10.10.6"
ADMIN="Administrator\%WindersAdminPasswd"

. /lib/lsb/init-functions
case "$1" in
start)
echo "Starting Server 1"
su ${USER} -c "/usr/bin/VBoxHeadless -s ${NAME1} > /dev/null &"
sleep 1
echo "Starting Server 2"
su ${USER} -c "/usr/bin/VBoxHeadless -s ${NAME2} > /dev/null &"
;;
stop)
echo "Stopping Servers -- waiting at least 20 seconds to make sure they've closed down."
su ${USER} -c "/usr/bin/net rpc SHUTDOWN -C Shutdown_Script -f -t 1 -I ${IP1} -U ${ADMIN}"
su ${USER} -c "/usr/bin/net rpc SHUTDOWN -C Shutdown_Script -f -t 1 -I ${IP2} -U ${ADMIN}"
sleep 20
;;
restart)
$0 stop
$0 start
;;
esac
exit 0


Yes, this is a very unsecure script as it has the Windows servers administrator password in plaintext, but I'm the only individual that has direct access to the host. Also, you have to install the Samba client (IIRC) to get the /usr/bin/net utility to send the correct shutdown signals to the windows guests.

Hope this helps,
Roger "Merch" Merchberger
zmerch
 
Posts: 4
Joined: 11. Jul 2011, 18:23
Primary OS: Ubuntu other
VBox Version: OSE Debian
Guest OSses: Win Server 2003

Re: vbox-headless: init script for multiple VMs

Postby AssureTek » 16. Aug 2011, 09:59

ofirk wrote:<Snip>
Install the init.d Script
Use the update-rc.d command to install the script.
Code: Select all   Expand viewCollapse view
sudo update-rc.d virtualbox-!!SHORTNAME defaults

Now whenever you enter normal multiuser run mode (at boot time, for example) your VM will start, and when you exit multiuser mode (during shutdown, for example), your VM will be suspended to disk if it was running.
<snip>
[/quote]

I am using Ubuntu 11.04. When I used defaults for update-rc.d it makes the link S20 which is the same time as virtualbox-ose.
The problem was that my virtualbox is named virtualbox-Elastix. Which comes before. So the script was trying to start without the kernel modules being loaded.
I used update-rc.d virtualbox-Elastix defaults 98 02
That way it is started last on boot and stopped first on shutdown.

I should also not that I had to change the script from -type vrdp to -type headless.

This might be because I am using the OSE and installed extensions manually though.
AssureTek
 
Posts: 1
Joined: 16. Aug 2011, 09:48
Primary OS: Ubuntu other
VBox Version: OSE other
Guest OSses: Ubuntu WinXP

Re: vbox-headless: init script for multiple VMs

Postby levk » 16. Aug 2011, 20:11

Edit /etc/default/virtualbox-ose to specify powerdown event for guests on host shutdown. "poweroff" is hard power off, graceful shutdown is "acpibutton". You have to make sure the guest will actually power down on the event, most Windows will just ask you if you're really sure about that and wait there.

If you're having problems with your scripts starting your guests before the module is loaded, manually load the module; on Ubuntu you can put it in /etc/modules.

Last time I looked around for the autostarting tools, saw vboxtool, saw how it wasn't touched in 2 years and decided against it. These scripts are probably awesome and all, but what's wrong cron? It's literally one line of code in the crontab:

Code: Select all   Expand viewCollapse view
@reboot for vm in $(grep -v "^#" /home/vbox/.autostart); do vboxmanage startvm $vm --type headless; done;


And the autostart file can even have comments in it:

Code: Select all   Expand viewCollapse view
# List guests to start on boot, VM names or UUIDs work. No spaces in names.

# Empty lines and lines starting with '#' are ignored
# THERE ARE NO END OF LINE COMMENTS

# My awesome guest
guest1

# My second awesome guest
guest2
levk
 
Posts: 33
Joined: 13. Apr 2011, 22:35
Primary OS: Ubuntu other
VBox Version: PUEL
Guest OSses: XP, Gentoo, Ubuntu*, CentOS, Scientific Linux


Return to VirtualBox on Linux Hosts

Who is online

Users browsing this forum: No registered users and 3 guests