VirtualBox init-Script: vboxctl

Hey,

vor einiger Zeit bin ich von vmware zu VirtualBox gewechselt. Um die virtuellen Maschinen auf meinem Server verwalten zu können, habe ich folgendes init-Script geschrieben. Ziel war es eine zuverlässige Lösung zu schaffen, welche virtuelle Maschinen automatisiert starten, stoppen und rudimentär auf einen FTP sichern kann. Wichtig ist, dass die Maschinen über den Start-Stop-Daemon verwaltet und dass ausgeführte Befehle auf ihren Erfolg geprüft werden.

Wer das Skript vboxctl nutzen möchte kann das gerne tun. ;-) Garantie übernehme ich natürlich keine, Bug-Reports dafür aber gerne.

#! /bin/sh
### BEGIN INIT INFO
# Provides:          vboxctl
# Required-Start:    $remote_fs $syslog $network vboxdrv
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start/Stop/Backup for VirtualBox VMs
# Description:       This script is designed as an ease of use VirtualBox
#                    handler. Beside start and stop it gives you the ability to
#                    backup VMs. Therefor the build in OVF export
#                    function is used.
### END INIT INFO
 
# Author: Philipp Micheel <floss@phm.me>
#
#   VBoxCtl provides ease of use start, stop and backup functionality for
#   VirtualBox virtual machines.
#
#   Copyright (C) 2010 Philipp Micheel
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
# Changelog:
#   10.07.2010  Implemented backup functionality
#   13.07.2010  Revamped to be more generic
#   31.07.2010  Implemented start/stop functionality (for use as init script)
#   07.08.2010  Make it atleast fully work
#               Changed from clonehd to OVF export
#   21.08.2010  Some minor fixes/changes
#   15.11.2010  typo and wrong backup date format, old backups weren't always purged
#
# TODO:
#   - enhance backup (check on success, rotation etc.)
#   - make the script more silent or at least treat verbose=no
#   - kill VM (via pidfile)
#
# ATTENTION:
#   There is no support for snapshots! I never had a check on them. It probably
#   works since it's based on the OVF export.
#
# Installation:
#   copy to /etc/init.d
#   update-rc.d vboxctl defaults 80
#
 
### BEGIN CONFIG (Can be overwritten in /etc/default/vboxctl)
 
USER="user1"
# Machines to control (seperated by spaces)
VMS="vm1 vm2"
 
# Additional start parameters can be added here
GUESTSTARTUPPARAMS="--vrdp off"
# Shutdown method (Make sure your guests support acpi or change to savestate.)
GUESTSHUTDOWN="acpipowerbutton"
#GUESTSHUTDOWN="savestate"
 
## Backup
# Where to store the backups:
BACKUPDIR="/var/backup"
# Compression makes no sense anymore; OVF export is used (vmdk is already
# compressed) anyways --bzip or --use-compress-program=lbzip2 will do the job
TARPARAMS=""
TARSUFFIX=".tar"
# FTP upload (leave FTPHOST empty to disable)
FTPHOST=""
FTPUSER=""
FTPPASS=""
 
### END CONFIG
 
# No need to edit anything below this line
 
PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME="vboxctl"
DAEMON="/usr/bin/VBoxHeadless"
DAEMON_ARGS="--startvm"
CONTROL="/usr/bin/VBoxManage"
PIDDIR="/var/run/VBoxHeadless/$USER"
SCRIPTNAME="/etc/init.d/$NAME"
SUCMD="su -- $USER -c"
DATE=`date +%Y%m%d%H%M`
 
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Exit if VirtualBox is not installed
[ -x "$DAEMON" ] && [ -x "$CONTROL"  ] || exit 1
 
. /lib/init/vars.sh
. /lib/lsb/init-functions
 
#
# Function that starts all the VMs
#
do_start()
{
    #Make sure PIDDIR exists
    mkdir -p --mode=0771 "$PIDDIR" && chgrp vboxusers "$PIDDIR"
 
    #Start the given machines
    for VM in $@ ; do
        PIDFILE="$PIDDIR/$VM.pid"
        log_daemon_msg "Starting virtual machine" "$VM"
        #Machine already running?
        if [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` -eq 1 ]
        then
            log_warning_msg "Virtual machine $VM is already running"
        else
            #Make sure no old pidfile is present
            rm -f "$PIDFILE"
            #Let's go..
            start-stop-daemon --start --quiet --background --make-pidfile \
            --pidfile $PIDFILE --chuid $USER:vboxusers --startas $DAEMON -- \
            $DAEMON_ARGS $VM $GUESTSTARTUPPARAMS && sleep 10
        fi
        #The machine should be running now!
        [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` -eq 1 ] \
        && log_end_msg 0 || log_end_msg 1
    done
}
 
#
# Function that stops the VMs
#
do_stop()
{
    for VM in $@ ; do
        PIDFILE="$PIDDIR/$VM.pid"
        log_daemon_msg "Stopping virtual machine" "$VM"
 
        #Check if the machine is running
        if [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` -eq 1 ]
        then
            #Perform a clean guest shutdown and wait for it (max 90sec)
            $SUCMD "$CONTROL -q controlvm $VM $GUESTSHUTDOWN" > /dev/null 2>&1
            TIMER=0
            while [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` \
            -eq 1 ] && [ $TIMER -lt 90 ] ; do
                sleep 3
                TIMER=$((TIMER+3))
            done
            #Force to shutdown
            if [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` -eq 1 ]
            then
                log_warning_msg "Virtual machine $VM is forced to shutdown"
                $SUCMD "$CONTROL -q controlvm $VM poweroff" > /dev/null 2>&1
                sleep 5
            fi
            #Get evil
            if [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` -eq 1 ]
            then
                log_warning_msg "Virtual machine $VM is going to be killed"
                start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE \
                && sleep 5 \
                || log_failure_msg "Virtual machine $VM could not be stopped"
            fi
        else
            log_warning_msg "Virtual machine $VM is not running"
        fi
 
        #Machine should be off now!
        [ `$SUCMD "$CONTROL -q list runningvms |grep -Fci '$VM'"` -eq 0 ] \
        && log_end_msg 0 && rm -f $PIDFILE || log_end_msg 1
    done
}
 
do_status()
{
    for VM in $@ ; do
        STATE=`$SUCMD "VBoxManage -q showvminfo ${VM} --machinereadable" |grep VMState= | cut -d "=" -f2 | tr -d "\""`
        log_success_msg "Virtual machine $VM is $STATE"
    done
}
 
#
# Function that backups all VMs
#
do_backup() {
 
    for VM in $@ ; do
        log_daemon_msg "Backing up virtual machine" "$VM"
        TARGETDIR="$BACKUPDIR/$DATE-$VM"
        TARGET="$TARGETDIR/$VM.ovf"
        FILE="$TARGETDIR$TARSUFFIX"
        mkdir -p --mode=0770 "$TARGETDIR" \
        && chgrp vboxusers "$BACKUPDIR" \
        && chgrp vboxusers "$TARGETDIR"
        cd $BACKUPDIR
 
        do_stop "$VM"
        #Export via VBoxManage
        if [ `$SUCMD "VBoxManage -q export $VM --output $TARGET" |grep -Fci 'Successfully exported'` -eq 1 ]
        then
            #Start the machine to minimize downtime
            do_start "$VM"
 
            tar --create --remove-files --file="$FILE" $TARPARAMS \
                `basename $TARGETDIR`
 
            # Backups are for root only
            chown root:root $FILE && chmod 600 $FILE
 
            #Simple Rotation
            DELFILES="`date --date \"-5 days\" +%Y%m%d`*$VM$TARSUFFIX"
            rm -f "$BACKUPDIR/$DELFILES"
 
            # Check if FTP should be used
            if [ ! -z "$FTPHOST" ]; then
/usr/bin/ftp -inv $FTPHOST << ENDFTP > /dev/null
user $FTPUSER $FTPPASS
lcd $BACKUPDIR
put `basename $FILE`
mdelete $DELFILES
bye
ENDFTP
            fi
 
            log_end_msg 0
        else
            log_failure_msg "Virtual machine $VM export failed"
            log_end_msg 1
            do_start "$VM"
        fi
    done
}
 
TASK="$1"
#check if the VMs are specified as parameter
[ $# -gt 1 ] && shift && VMS="$@"
 
case "$TASK" in
  start)
    do_start "$VMS" ;;
  stop)
    do_stop "$VMS" ;;
  status)
    do_status "$VMS" ;;
  restart|force-reload)
    do_stop "$VMS"
    do_start "$VMS"
    ;;
  backup)
    do_backup "$VMS" ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload|backup} [vm1] [vm2] [..]" >&2
    exit 3
    ;;
esac
 
:

Lg Philipp

Kommentar schreiben

3 Kommentare.

  1. VirtualBox init-Script: vboxctl | phm.me - pingback on 10. November 2010 um 17:53
  2. Do you people have a facebook fan page? I looked for one on twitter but could not discover one, I would really like to become a fan!

    • Hi,

      thanks for your interest but there is no facebook/twitter page so far. You can subscribe the rss feed to stay up-to-date. :)

      Greetings Philipp

Kommentar schreiben


Hinweis - Du kannst dies benutzenHTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Time limit is exhausted. Please reload CAPTCHA.

Trackbacks und Pingbacks: