Como instalar Virtualbox como servicio en Ubuntu server 12.04

La última versión de VirtualBox 4.2.0 establece mecanismos para levantar maquinas virtuales desde el init del sistema, pude leerse las instrucciones en:


Starting virtual machines during system boot

El caso es que a mí desde Ubuntu server 12.04 no me funciona pues el comando VBoxManage carece de las opciones de autostartdbpath por lo que he necesitado realizar el proceso a la vieja usanza; es decir crear script de init.d gestionado la máquina virtual desde la linea de comandos, lo que en la terminología técnica se puede encontrar por el termino Headless.
Las instrucciones detaladas así comom el script se pueden enctontrar en:


How to Setup VirtualBox as a Service in Linux

y también en:

Crear servicio para VirtualBox

Yo repito el script para que quede constancia:

#! /bin/sh
#
# chkconfig: 2345 90 10
### BEGIN INIT INFO
# Provides:          vbox-service-template
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: 'service-template' virtual machine
# Description:       Starts and stops a VirtualBox host as a service.
### END INIT INFO

# Author: Brendan Kidwell <brendan@glump.net>
# License: GPL 3 <http://opensource.org/licenses/GPL-3.0>
#
# Based on /etc/init.d/skeleton from Ubuntu 12.04.

#-------------------------------------------------------------------------------
#
#  CONFIGURATION
#
#  What is the name of the VM exactly as it appears in the VirtualBox control
#  panel? This is the 'name' and the 'long name' of the VM.
#
#     Does 'name' contain spaces or other special characters? If so, you must
#     make up some other value for 'name' that doesn't have spaces.
#
#  Setup:
#
#  1. Copy this file to /etc/init.d/vbox-'name'. The filename must start with
#     the prefix "vbox-". Make sure you set the 'x' bit on the file to make it
#     executable.
#
#  2. Edit 'Provides', above, to match the filename.
#
#  3. Edit 'Short-Description' to describe the function of the VM.
#
#  4. If 'long name' is different from 'name' fill it in below, otherwise leave
#     LONGNAME as an empty string.
      VM_LONG_NAME=""
#
#  5. What user owns the virtual machine?
      VM_OWNER=???
#
#  6. Which stop command? "hibernate" or "powerbutton"
      VM_STOP=hibernate
#
#  7. For the 'start-wait' command -- waiting until network is up, what is the
#     VM's hostname?
      VM_HOSTNAME=""
#
#-------------------------------------------------------------------------------

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
# Pull DESC from file header
DESC=`grep --max-count=1 "^# Short-Description:" $(readlink -f $0)|cut --delimiter=' ' --field=3-|sed 's/^ *//'`
# Pull NAME from file header
NAME=`grep --max-count=1 "^# Provides:" $(readlink -f $0)|cut --delimiter=' ' --field=3-|sed 's/^ *//'`
SCRIPTNAME=/etc/init.d/$NAME

MANAGE_CMD=VBoxManage

# Get VM_SHORT_NAME from service name
VM_SHORT_NAME=`echo $NAME|cut --delimiter='-' --field=2-`
# Actual filename of VM is VM_SHORT_NAME, or if VM_LONG_NAME is set, use that
if [ ! "$VM_LONG_NAME" ] ; then VM_LONG_NAME=$VM_SHORT_NAME ; fi

# Do not use 'sudo' if this script is actually running as VM_OWNER already
if [ `whoami` = $VM_OWNER ] ; then SUDO_CMD="" ; else SUDO_CMD="sudo -H -u $VM_OWNER" ; fi

# Set VBoxManage command for stop action
if [ $VM_STOP = powerbutton ] ; then VM_STOP_CMD=acpipowerbutton ; else VM_STOP_CMD=savestate ; fi

# If VM_HOSTNAME isn't set (for 'start-wait' command) use VM_SHORTNAME
if [ ! "$VM_HOSTNAME" ] ; then VM_HOSTNAME=$VM_SHORT_NAME; fi

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

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

get_vm_state()
{
    # possible SHORT_STATE values: running, paused, aborted, powered off

    VMINFO=$($SUDO_CMD $MANAGE_CMD showvminfo "$VM_LONG_NAME" 2>/dev/null)
    if [ $? = 0 ] ; then
        # No error retriving state string
        LONG_STATE=$(echo "$VMINFO"|grep --max-count=1 "^State:"|cut --delimiter=' ' \
            --fields=2-|sed 's/^ *//')
        SHORT_STATE=$(echo $LONG_STATE|cut --delimiter="(" --fields=1|sed 's/ *$//')
        # Fix for syntax highlighting in KomodoEdit for previous line
        [ 0 = 1 ] && NOOP=$(echo ")")
    else
        # VM must be missing
        LONG_STATE=missing
        SHORT_STATE=missing
    fi
}

do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started

    get_vm_state

    if [ "$SHORT_STATE" = "missing" ] ; then
        echo Could not access VM \"$VM_LONG_NAME\".
        return 2
    fi

    if [ "$SHORT_STATE" = "running" ] ; then
        echo VM \"$VM_LONG_NAME\" is already running.
        return 1
    fi

    $SUDO_CMD $MANAGE_CMD startvm "$VM_LONG_NAME" -type vrdp || {
        echo Failed to start VM \"$VM_LONG_NAME\".
        return 2
    }

    # No status report; VBoxManage said if it worked.
    return 0
}

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

    get_vm_state

    if [ "$SHORT_STATE" = "missing" ] ; then
        echo Could not access VM \"$VM_LONG_NAME\".
        return 3
    fi

    if [ ! "$SHORT_STATE" = "running" ] ; then
        echo VM \"$VM_LONG_NAME\" is already stopped.
        return 1
    fi

    $SUDO_CMD $MANAGE_CMD controlvm "$VM_LONG_NAME" $VM_STOP_CMD || {
        echo Failed to hibernate VM \"$VM_LONG_NAME\".
        return 2
    }

    echo Waiting for \"$VM_LONG_NAME\" to complete shutdown...
    while [ "$SHORT_STATE" = "running" ] ; do
        sleep 1
        get_vm_state
    done

    echo The VM \"$VM_LONG_NAME\" has been stopped \($VM_STOP\).
    return 0
}

do_status()
{
    get_vm_state
    if [ "$SHORT_STATE" = "missing" ] ; then
        echo Could not access VM \"$VM_LONG_NAME\".
        return 2
    fi
    echo Status of VM \"$VM_LONG_NAME\": $LONG_STATE

    if [ "$SHORT_STATE" = "running" ] ; then return 1 ; else return 0 ; fi
}

do_reload() {
    VM_STOP=powerbutton
    VM_STOP_CMD=acpipowerbutton
    do_stop && do_start
}

do_wait_for_online() {
    echo Waiting for \"$VM_LONG_NAME\" to come up on the network...
    while [ ! "$result" = "0" ] ; do
        sleep 1
        ping -c 1 $VM_HOSTNAME >/dev/null 2>/dev/null
        result=$?
    done
    echo Ready.
}

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
    ;;
  start-wait)
    do_start && do_wait_for_online
    ;;
  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
    ;;
  status)
    do_status && exit 0 || exit $?
    ;;
  restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    [ "$VERBOSE" != no ] && log_daemon_msg "Restarting $DESC" "$NAME"
    VM_STOP=powerbutton
    VM_STOP_CMD=acpipowerbutton
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            1) [ "$VERBOSE" != no ] && log_end_msg 1 ;; # Old process is still running
            *) [ "$VERBOSE" != no ] && log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        [ "$VERBOSE" != no ] && log_end_msg 1
        ;;
    esac
    ;;
  restart-wait)
    VM_STOP=poweroff
    VM_STOP_CMD=acpipowerbutton
    do_stop
    do_start && do_wait_for_online
    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|start-wait|stop|status|restart|restart-wait|force-reload}" >&2
    exit 3
    ;;
esac
:

Antes que nada se debe editar\crear el archivo /etc/default/virtualbox en donde se define los usuarios que tienen derechos a suspender la máquina virtual

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

Una vez realizado el procedimiento anterior la forma de seguir es la habitual para establecer servicios:

vim /etc/init.c/vbox-NAME

se copia el script anterior.
Atención en nombrar el script con el nombre del a maquina virtual a ejecutar; buen detalle pues permite tener ordenados los script para ejecutar mas de una maquina a la vez.
Se otorgan permisos de ejecución al script

$ sudo chmod 755 /etc/init.d/vbox-NAME

Se actualizan los directorios de arranque

sudo update-rc.d vbox-NAME defaults 90
Tagged with:
Posted in Programación