Category: Redmine

How to setup VirtualBox as a service

My redmine server runs on a virtual machine over VirtualBox. At the beginning I used to start and stop the VM manually through the graphic interface, but soon it came out that it would be certainly better to have a better solution which:

  • starts and stops the virtual machine automatically following the boot up and shutdown of the host
  • launches the virtual machine as root
  • handles eventually more than one virtual machine
  • avoid to launch the VirtualBox GUI

Linux helps us with the possibility to create a script invoked at every change of the run level and it can be done also manually. In addition we can start VirtualBox using a handy tool called VBoxHeadless that allows you to connect to the virtual machine just through a remote desktop connection and without its GUI. This makes the boot up and shutdown sequences much more faster.

Following is how I setup a virtual machine hosted by VirtualBox as a service on a linux machine running Ubuntu 10.04 LTS.

Service Command

Redmine VM will be a service called redmine-server which can be manually handled through the service command with its typical arguments: start, stop, restart, status. More precisely:

to start the VM:

$ sudo service redmine-server start

to stop the VM:

$ sudo service redmine-server stop

to restart the VM:

$ sudo service redmine-server restart

to see all the current services status:

$ service --status-all

Scripts and run levels

Linux run levels are numbered 0 through 6. Run levels stop at six for practical and historical reasons, in Ubuntu the run levels are summarizes as following:

  • 0 System Halt
  • 1 Single user
  • 2 Full multi-user mode (Default)
  • 3-5 Same as 2
  • 6 System Reboot

Concerning the invocation for each run level, we can notice that in the folder /etc there are seven sub folders named in the range rc0.drc6.d which contain the links pointing to the scripts in /etc/init.d.

So, let’s see what happens during the reboot /etc/rc6.d:

lrwxrwxrwx 1 root root 17 2011-04-21 14:27 K20hddtemp -> ../init.d/hddtemp*
lrwxrwxrwx 1 root root 33 2011-05-04 12:35 K20vboxballoonctrl-service -> ../init.d/vboxballoonctrl-service*
lrwxrwxrwx 1 root root 17 2011-01-10 16:53 K20vboxdrv -> ../init.d/vboxdrv*
lrwxrwxrwx 1 root root 25 2011-01-10 16:53 K20vboxweb-service -> ../init.d/vboxweb-service*
lrwxrwxrwx 1 root root 24 2011-07-04 10:47 K30redmine-server -> ../init.d/redmine-server*
lrwxrwxrwx 1 root root 13 2011-06-17 08:26 K50ntp -> ../init.d/ntp*
lrwxrwxrwx 1 root root 19 2011-01-10 17:17 K74bluetooth -> ../init.d/bluetooth*
lrwxrwxrwx 1 root root 29 2011-01-10 17:17 S10unattended-upgrades -> ../init.d/unattended-upgrades*
lrwxrwxrwx 1 root root 18 2011-01-10 17:17 S20sendsigs -> ../init.d/sendsigs*
lrwxrwxrwx 1 root root 17 2011-01-10 17:17 S30urandom -> ../init.d/urandom*
lrwxrwxrwx 1 root root 22 2011-01-10 17:17 S31umountnfs.sh -> ../init.d/umountnfs.sh*
lrwxrwxrwx 1 root root 20 2011-01-10 17:17 S35networking -> ../init.d/networking*
lrwxrwxrwx 1 root root 18 2011-01-10 17:17 S40umountfs -> ../init.d/umountfs*
lrwxrwxrwx 1 root root 20 2011-01-10 17:17 S60umountroot -> ../init.d/umountroot*
lrwxrwxrwx 1 root root 16 2011-01-10 17:17 S90reboot -> ../init.d/reboot*

Every link has a simple syntax which assigns own priority and which signal should be passed to the script.
For example, S35networking -> ../init.d/networking* means Start with priority 50 the script called networking. Similarly,
K74bluetooth -> ../init.d/bluetooth* means to Kill with priority 74 the script called bluetooth. The default priority is 20 while 99 is the lowest priority (started last) but you can adjust it to match your needs concerning the scripts sequence.

Returning to my case, I had to look for a free priority to bind the virtualbox script and looking after not to interfere with the vbox kernel module to which has been assigned a priority of 20.

If I open /etc/rc5.d I have:

lrwxrwxrwx 1 root root 20 2011-01-10 17:17 S20fancontrol -> ../init.d/fancontrol*
lrwxrwxrwx 1 root root 17 2011-04-21 14:27 S20hddtemp -> ../init.d/hddtemp*
lrwxrwxrwx 1 root root 20 2011-01-10 17:17 S20kerneloops -> ../init.d/kerneloops*
lrwxrwxrwx 1 root root 27 2011-01-10 17:17 S20speech-dispatcher -> ../init.d/speech-dispatcher*
lrwxrwxrwx 1 root root 33 2011-05-04 12:35 S20vboxballoonctrl-service -> ../init.d/vboxballoonctrl-service*
lrwxrwxrwx 1 root root 17 2011-01-10 16:53 S20vboxdrv -> ../init.d/vboxdrv*
lrwxrwxrwx 1 root root 25 2011-01-10 16:53 S20vboxweb-service -> ../init.d/vboxweb-service*
lrwxrwxrwx 1 root root 13 2011-06-17 08:26 S23ntp -> ../init.d/ntp*
lrwxrwxrwx 1 root root 19 2011-01-10 17:17 S25bluetooth -> ../init.d/bluetooth*
lrwxrwxrwx 1 root root 20 2011-01-10 17:17 S50pulseaudio -> ../init.d/pulseaudio*
lrwxrwxrwx 1 root root 15 2011-01-10 17:17 S50rsync -> ../init.d/rsync*
lrwxrwxrwx 1 root root 15 2011-01-10 17:17 S50saned -> ../init.d/saned*
lrwxrwxrwx 1 root root 19 2011-01-10 17:17 S70dns-clean -> ../init.d/dns-clean*
lrwxrwxrwx 1 root root 18 2011-01-10 17:17 S70pppd-dns -> ../init.d/pppd-dns*
lrwxrwxrwx 1 root root 14 2011-05-02 14:21 S75sudo -> ../init.d/sudo*
lrwxrwxrwx 1 root root 24 2011-01-10 17:17 S90binfmt-support -> ../init.d/binfmt-support*
lrwxrwxrwx 1 root root 22 2011-01-10 17:17 S99acpi-support -> ../init.d/acpi-support*
lrwxrwxrwx 1 root root 21 2011-01-10 17:17 S99grub-common -> ../init.d/grub-common*
lrwxrwxrwx 1 root root 18 2011-01-10 17:17 S99ondemand -> ../init.d/ondemand*
lrwxrwxrwx 1 root root 18 2011-01-10 17:17 S99rc.local -> ../init.d/rc.local*

I decide to assign to my script the priority 80 for the start (which has not been assigned yet) and similarly a priority of 30 for the stop.

Installing the script

Service’s scripts are located in /etc/init.d and their names represents effectively the service names. Following how I installed the script.

Create the empty script file:

$ sudo touch /etc/init.d/redmine-server

assign executable permits

$ sudo chmod +x redmine-server

edit the script

$ gedit redmine-server

This is my script:

#!/bin/sh
#==============================================================================
# Description: Script for start|stop|restart|status of VirtualBox Images
# Service Name: redmine-server
# Runlevel Start: 2 3 4 5
# Runlevel Stop: 0 1 6
# Author: Cesare Riva
# Date: 30 June 2011
# Version: 1.0.00
#==============================================================================
set -e
VBOX_MANAGE=$(which VBoxManage)
VBOX_HEADLESS=$(which VBoxHeadless)
VBOX_NAME="c5b5e0dc-17c9-4fa5-ba82-5b694e000621" UUID
#VBOX_NAME="redmine_server_vm"
VBOX_IMAGES="$VBOX_NAME" # list of the VMs, actually just one
SCRIPT_NAME=$(basename $0)
COMMAND="$1"
RET=0

# if eventually we would like to invoke a binary as a different user than root:
# sudo -H -u $USER $VBOX_MANAGE showvminfo {command}

# check if the VM is already running
is_running ()
  { $VBOX_MANAGE showvminfo "$1" | grep "^State:s*running" > /dev/null && RET=0 || RET=1
  }

# check if the VM is already powered off (not used in this script)
is_poweredoff ()
  { $VBOX_MANAGE showvminfo "$1" | grep "^State:s*powered off" > /dev/null && RET=0 || RET=1
  }

do_start ()
  { for d in $VBOX_IMAGES
    do
    echo "Starting VM $d ..."
    # check if the VM is already running
    $VBOX_MANAGE showvminfo "$d" | grep "^State:s*running" > /dev/null &&
     { echo "Attention! $d is already running ..."
       continue #go to the next element
     }

    # starting the VM and check if is failed
    $VBOX_HEADLESS --startvm "$d" &> /dev/null ||
      { echo "Failed to start '$d' ..."
        continue #go to the next element
      }
    echo "$d started!"
    done
    RET=0
  }

do_stop ()
  { for d in $VBOX_IMAGES
    do
    echo "Shutting down VM '$d' ..."
    # check if the VM is already stopped
    $VBOX_MANAGE showvminfo "$d" | grep "^State:s*running" > /dev/null ||
      { echo "Attention! $d is already in poweroff ..."
        continue
      }
    $VBOX_MANAGE controlvm "$d" poweroff > /dev/null ||
      { echo "Failed to stop $d ..."
        continue
      }
    echo "$d powered off"
    done
    RET=0
  }

# this is invoked when "$sudo service --status-all"
show_status ()
  { for d in $VBOX_IMAGES
    do
    # we investigate only if, at least, there is one vm not running,
    # otherwise leave with exit code = 0 (service is running)
    is_running $d
    if [ $RET -eq 1 ]; then
      exit 1
    fi
    done
  }

show_usage ()
  { echo
    echo "Usage: $ sudo service $SCRIPT_NAME {start|stop|restart|status}"
    echo
    RET=1
  }

binary_check ()
  { # exit if the package is not installed
    [ -x "$VBOX_MANAGE" ] ||
      { echo
        echo "VirtualBox package is not installed!"
        echo
        exit 1
      }
  }

#==============================================================================
#                           SCRIPT STARTS FROM HERE
#==============================================================================

binary_check

case $COMMAND in
  start)
    do_start
    ;;
  stop)
    do_stop
    ;;
  restart)
    do_stop
    do_start
    ;;
  status)
    show_status
    ;;
  *)
    show_usage
esac

exit $RET

Because I was playing with different VMs with similar names, I preferred to invoke in the script the VM using the UUID. To know the appropriate:

$ sudo vboxmanage list vms
"Redmine Server Official" {c5b5e0dc-17c9-4fa5-ba82-5b694e000621}
"Redmine Server Testing" {608aea51-7aa2-4514-ae1e-9451597fa99c}

The UUID c5b5e0dc-17c9-4fa5-ba82-5b694e000621 is, in fact, the one referred in the script.
To continue, update the script to the desired runlevels and choosen priorities

$ update-rc.d redmine-server start 80 2 3 4 5 . stop 30 0 1 6 .

now in /etc/rc6.d I have

...
lrwxrwxrwx 1 root root 24 2011-07-04 10:47 S80redmine-server -> ../init.d/redmine-server*
...

and in /etc/rc6.d

...
lrwxrwxrwx 1 root root 24 2011-07-04 10:47 K30redmine-server -> ../init.d/redmine-server*
...

If eventually I might need  to reverse the changes:

$ update-rc.d -f redmine-server remove

in addition remember the remove the script manually from /etc/init.d

You can test the script with a simple

$ sudo service redmine-server start

See what is actually running

$ top
Tasks: 195 total,   2 running, 190 sleeping,   3 stopped,   0 zombie
Cpu(s):  0.5%us,  1.3%sy,  0.0%ni, 98.0%id,  0.2%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   3722212k total,  2775556k used,   946656k free,    13684k buffers
Swap:  1952764k total,    14168k used,  1938596k free,  1382576k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1592 root      20   0 1186m 845m 832m S    3 23.3  83:52.28 VBoxHeadless
 1135 root      20   0  180m  33m  14m S    1  0.9  25:22.41 Xorg
 3836 cesare    20   0  262m 6840 3404 S    1  0.2  24:12.35 netspeed_applet
 3721 cesare    20   0  380m 7564 3080 S    0  0.2   0:20.68 gnome-settings-
 3748 cesare    20   0  277m  12m 8048 S    0  0.4   5:48.02 vino-server
19019 cesare    20   0 19416 1384  968 R    0  0.0   0:00.02 top
    1 root      20   0 23880 1328  720 S    0  0.0   0:01.05 init

or alternatively

$ ps aux | grep virtualbox
root     12276  2.4  8.5 971184 319108 ?       Sl   Jul21  22:18 /usr/lib/virtualbox/VBoxHeadless --startvm c5b5e0dc-17c9-4fa5-ba82-5b694e000621
cesare   13818  0.0  0.0   8952   876 pts/0    S+   08:27   0:00 grep --color=auto virtualbox

Just to summarize, control it manually

To start the VM

$ sudo service redmine-server start
Starting VM c5b5e0dc-17c9-4fa5-ba82-5b694e000621 ...
c5b5e0dc-17c9-4fa5-ba82-5b694e000621 started!
cesare@test-server:~$ Oracle VM VirtualBox Headless Interface 4.0.12
(C) 2008-2011 Oracle Corporation
All rights reserved.

VRDE server is listening on port 3389.

To stop the VM

$ sudo service redmine-server stop
Shutting down VM 'c5b5e0dc-17c9-4fa5-ba82-5b694e000621'
...0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
c5b5e0dc-17c9-4fa5-ba82-5b694e000621 powered off

To restart the VM

$ sudo service restart
Shutting down VM 'c5b5e0dc-17c9-4fa5-ba82-5b694e000621' ...
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
c5b5e0dc-17c9-4fa5-ba82-5b694e000621 powered off
Starting VM c5b5e0dc-17c9-4fa5-ba82-5b694e000621 ...
c5b5e0dc-17c9-4fa5-ba82-5b694e000621 started!
cesare@test-server:~$ Oracle VM VirtualBox Headless Interface 4.0.12
(C) 2008-2011 Oracle Corporation
All rights reserved.

VRDE server is listening on port 3389.

To check its status and all services

$ sudo service --status-all
...
[ + ]  redmine-server
...

Remember that everytime you to update VirtualBox, stop the service before proceeding with apt-get update, otherwise you will get an error.

WordPress Themes