2 votes

Comment systemd peut-il démarrer automatiquement et contrôler les invités VirtualBox ?

Dans mon cas particulier, avec une nouvelle installation de serveur Ubuntu 18.04 Bionic et VirtualBox-5.2.20, il semble que l'ancienne méthode de démarrage automatique des invités ne soit plus disponible. Ce n'est pas qu'elle était merveilleuse, mais elle fonctionnait. Il ne semble pas y avoir de méthode propre pour résoudre ce problème - comment systemd et VirtualBox peuvent-ils fonctionner ? ensemble pour un démarrage, un contrôle et un arrêt intelligents ?

6voto

dusty Points 142

Semblable à votre solution, mais un peu plus simple :

  1. Ejecutar systemctl edit vbox@.service --full --force et collez le contenu suivant, en remplaçant Utilisateur et Groupe par votre nom d'utilisateur.

    [Unit] Description=Virtual Box Guest %I After=network.target vboxdrv.service Before=runlevel2.target shutdown.target

    [Service] User=USERNAME Group=GROUPNAME Type=forking Restart=no TimeoutSec=5min IgnoreSIGPIPE=no KillMode=process GuessMainPID=no RemainAfterExit=yes

    ExecStart=/usr/bin/VBoxManage startvm %i --type headless ExecStop=/usr/bin/VBoxManage controlvm %i acpipowerbutton

    [Install] WantedBy=multi-user.target

  2. Recharger systemd : systemctl daemon-reload

  3. Obtenir une liste de vos machines virtuelles VBoxManage list vms :

    $ VBoxManage list vms "Ubuntu" {1ba32309-d4c4-420a-a9c8-a38177f00bc4} "Windows" {573df054-0e33-4389-896a-1234f10e25ad}

  4. Utilisez le nom obtenu à l'étape 3 pour gérer la VM via systemd. Par exemple, pour gérer la VM "Ubuntu", vous devez exécuter :

    sudo systemctl start vbox@Ubuntu # Start the VM sudo systemctl enable vbox@Ubuntu # Start the VM on boot

1voto

ubuntu ox93g Points 11

Eh bien... je crois que j'ai trouvé une réponse.

Voici ma solution. Elle n'est certainement pas parfaite - et une partie de la raison pour laquelle je la partage est d'inviter à l'améliorer. Cependant, elle permet le démarrage automatique, la surveillance et l'arrêt via systemd. Et je penser cela va au moins dans la bonne direction pour ces deux produits.

Une mise en garde s'impose : le texte ci-dessous suppose une certaine familiarité avec systemd et VirtualBox. Il faut également que les fonctions d'arrêt ACPI soient activées sur les invités. Cela peut être intégré à Windows, et aussi simple que d'installer la fonction d'arrêt ACPI sur les invités. acpid sous Linux, mais je n'en suis pas sûr. De plus, certains invités (Windows version xxxx) peuvent avoir besoin d'être modifiés pour s'assurer que les arrêts ACPI se produisent immédiatement. https://ethertubes.com/unattended-acpi-shutdown-of-Windows-server/

Tout d'abord, il faut bien sûr créer une unité systemd. Je profite de la disponibilité de modèles .

Exécution systemctl edit --full vbox@.service fournit un éditeur dans lequel nous nous plaçons : [Unité]. Description=VirtualBox %I Serveur virtuel After=network.target vboxdrv.service

[Service]
Type=forking
Restart=no
TimeoutSec=5min
KillMode=process
RuntimeDirectory=vbox
RuntimeDirectoryPreserve=yes
PIDFile=/run/vbox/%I.pid

Environment='RUNDIR=/run'
Environment='PIDDIR=/vbox'
Environment='VM=%I'
ExecStart=/etc/init.d/vbox-systemd start
ExecStop=/etc/init.d/vbox-systemd stop

[Install]
WantedBy=multi-user.target

Ce qui précède constitue une base :

- Allows for up to 5 minutes for startup/shutdown per guest
- The pid files will be stored as /run/vbox/<guest>.pid
- And the guests will be started as part of the normal boot process

Cette valeur peut être ajustée selon les besoins, mais en dehors des valeurs par défaut pour l'ensemble du serveur, ne la modifiez pas. Les invités individuels seront adaptés plus tard. Maintenant, il faut fournir l'aide script. Je viens de passer une longue période de temps à me battre avec les subtilités de BASH, un manque de sommeil, et un manque sévère d'expérience active avec BASH. Ce qui suit fonctionne, il y a un mélange de styles, et j'aimerais vraiment savoir pourquoi ma tentative d'utiliser des fonctions BASH simples a échoué si lamentablement. Mais je suis prêt à aller me coucher, alors même si ce n'est pas mon meilleur travail... ça marche !

#! /bin/bash
# /etc/init.d/vbox-systemd: Helper script to startup & shutdown VirtualBox
# headless machines via systemd
#
# written by Daniel L. Miller <dmiller@amfes.com>

# This should not be called directly (though possible with the
# proper environment variables set). This is used by the
# vbox@.service template to start & stop virtual machines - 
# with supervision.

# Environment variables to be defined for us by systemd unit
# RUNDIR=/run
# PIDDIR=/vbox
# VM=<vmname>

# This was setup to use environment variables - maybe support cmd line as well.
if [ ! -z "$2" ]; then
    VM=$2
fi

# So...I suppose might as well set sane defaults
if [ -z "$RUNDIR" ]; then
    RUNDIR='/run'
fi
if [ -z "$PIDDIR" ]; then
    PIDDIR='/vbox'
fi

#
# Overprotective but trying to be good...
# These utilities should be fairly standard...
#
VB=/usr/bin/VBoxManage
GREP=/bin/grep
CUT=/usr/bin/cut
TR=/usr/bin/tr
SLEEP=/bin/sleep
WAITEXIT=300

# Make sure the utilities are available
test -x $VB || exit 3
test -x $GREP || exit 3
test -x $CUT || exit 3
test -x $TR || exit 3

# Verify the pid folder tree is defined and usable
test -d "${RUNDIR:?run directory top-level must be set}" || exit 3
test -d "$RUNDIR${PIDDIR:?pid directory must be set}" || mkdir -p "$RUNDIR$PIDDIR"
# This test is a little different - this validates the name but we don't
# care if the file exists or not. At least the moment.
test -f "$RUNDIR$PIDDIR/${VM:?Virtual Machine name must be set}.pid"

PIDFILE=$RUNDIR$PIDDIR/$VM.pid

vmactive=$($VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"')

case "${1:-''}" in
  'start')
    # Start the machine
    $VB startvm $VM --type headless
    # Give it at least a change to get started...
    $SLEEP 2
    # Now perform first trick and save pid
    vmactive=`$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"'`
    if [ "x$vmactive" == "x$VM" ]; then
        vmpid=$($VB showvminfo $VM --log 0 | $GREP -m 1 'Process ID' | $CUT -d ':' -f4 | $TR -d ' ')
        echo $vmpid > $PIDFILE
    else
        exit 1;
    fi
    ;;
  'stop')
    waited=0
    while [ "$waited" -lt $WAITEXIT ]; do
        # Test first so VB doesn't object to shutting off a non-running VM
        vmactive=`$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"'`
        if [ "x$vmactive" != "x$VM" ]; then
            echo "Proper ACPI Shutdown of $VM - or it wasn't running!"
            break
        fi
        # Try to turn it off - repeatedly
        $VB controlvm $VM acpipowerbutton
        # Give it a chance to take.
        $SLEEP 5
        waited=$((waited+5))
    done

    # Time to clean up - force terminate if necessary and delete the pid file
    [ "$waited" -ge $WAITEXIT ] && [ -f $PIDFILE ] && kill -s 9 $PIDFILE
    [ -f $PIDFILE ] && rm $PIDFILE
    ;;
  'status')
    vmactive=`$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"'`
    if [ "x$vmactive" == "x$VM" ]; then
        vmpid=$($VB showvminfo $VM --log 0 | $GREP -m 1 'Process ID' | $CUT -d ':' -f4 | $TR -d ' ')
        echo "$VM is running as PID $vmpid"
    else
        echo "$VM is not running"
    fi
    ;;
  *)
    echo "Usage: vbox-systemd [start|stop|status]" >&2
    exit 3;
    ;;
esac

Ainsi... il ne reste plus qu'à démarrer une machine virtuelle : systemctl start vbox@<your-guest-name> . Plus excitant - systemctl status vbox@<your-guest-name> fournira l'état systemd de la VM ! Et vous pouvez même faire un systemctl stop vbox@<your-guest-name> pour l'éteindre.

Pour activer le démarrage automatique, il suffit de lancer systemctl enable vbox@<your-guest-name> .

Maintenant, si vous avez besoin d'un contrôle supplémentaire, par exemple en spécifiant le paramètre commande dans lequel les invités démarrent, utilisez l'astuce systemctl edit vbox@<your-guest-name> . Remarquez que cette fois-ci, nous n'utilisons pas l'option --full argument - cela crée un dossier prioritaire uniquement pour cet invité sans dupliquer l'unité de base. Cet invité a peut-être besoin de services SQL de la part de l'hôte :

[Unit]
After=mysql.service
Wants=mysql.service

Maintenant, cet invité ne sera pas démarré tant que le serveur mysql ne sera pas en place. Ou si cet invité fournit des services critiques, vous pouvez ajouter :

[Services]
Restart=yes

Rappelez-vous - il suffit d'entrer les arguments systemd que vous avez besoin d'ajouter ou d'écraser - le reste vient du modèle.

J'espère que cela aidera quelqu'un d'autre - et si d'autres peuvent apporter leur contribution, qu'ils le fassent !

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X