Comment démarrer et éteindre automatiquement les machines VirtualBox?


52

Je dois exécuter un système logiciel destiné à être installé en tant qu'appliance sur une machine dédiée. Afin d'économiser de l'énergie, j'ai l'intention d'exécuter le système sur une machine virtuelle VirtualBox.

L'hôte est une machine Linux standard avec un système SysV-Init, l'invité est un Linux fortement modifié et je préférerais ne pas avoir à le modifier davantage. VirtualBox est utilisé dans la version OSE.

J'ai déjà compris comment démarrer la machine virtuelle lorsque l'hôte démarre ( Edit: ceci est fait, comme indiqué par Nikhil ci-dessous, via la commande VBoxManager startvm), mais comment puis-je arrêter la machine virtuelle en douceur? Tout script exécuté sur l'hôte doit attendre que l'invité soit complètement arrêté.

Quelqu'un peut-il suggérer à quoi, par exemple, un fichier de service faisant cela devrait ressembler?


pourriez-vous donner le script de démarrage pour démarrer la machine virtuelle lors du démarrage
Débutant le

Réponses:


34

Avez-vous essayé acpipowerbuttonde cet ensemble de commandes?

VBoxManage controlvm        <uuid>|<name>
                            pause|resume|reset|poweroff|savestate|
                            acpipowerbutton|acpisleepbutton|

Modifier après avoir lu les commentaires:

Vous pouvez utiliser acpidou d'autres utilitaires acpi pour le rendre gracieux. Aussi, pouvez-vous fournir plus d'informations sur la façon dont vous arrêtez la machine en ce moment?

Plaine shutdownn'attendrait pas les travaux non terminés, un délai peut être trop long.

Je suppose que vous n'utilisez pas de gestionnaire de fenêtres, alors essayez cet outil.

Je viens de voir ce démon . Vous pourriez le trouver utile.


Merci pour votre réponse et bienvenue sur unix.stackexchange.com! Cependant, je crains que votre réponse ne réponde pas non plus à mon problème: acpipowerbutton simule d'appuyer sur le bouton d'alimentation d'une machine réelle, mais après avoir exécuté cette commande sur l'hôte, la VM mettrait encore un peu de temps à s'éteindre.
Jstarek

4
Sûr. Vous devez donc écrire une boucle qui vérifie si la machine virtuelle est toujours en cours d'exécution. ACPI est exactement la même méthode que j'utilise dans mes scripts pour cela. vboxmanage list runningvmsjusqu'à ce que votre VM est parti.
Nils

OK, alors que je pense que je vais me contenter d'un wrapper de gestion dans la pratique, +50 à vous pour avoir indiqué l'initscript!
Jstarek

16

Plutôt que de coder cela vous-même, pensez à utiliser Vagrant , qui est conçu pour instancier et contrôler les instances de virtualbox. La documentation est excellente et je suggère que vous vérifiiez plutôt que d'essayer de rouler vous-même.

En résumé, vous créez un fichier de contrôle simple, puis exécutez-le vagrant uppour démarrer autant d'instances de VirtualBox que vous le souhaitez. Vous pouvez utiliser vagrant sshpour vous connecter aux hôtes et vagrant haltpour éteindre l’hôte (sans terminer). vagrant destroyse débarrasser des instances.

Il prend en charge l’approvisionnement avec puppet, Ansible ou Chef et vous permet de contrôler la plupart des paramètres de configuration de la VBox exposés.


2
Je suis un fan de vagrant, mais dans ce cas, pourquoi voudriez-vous cela? L'OP exécute une appliance et ne construit pas son propre système. Le provisionnement passe donc à côté de l'essentiel. Et pourquoi créer une «boîte» personnalisée à partir de l'appliance, juste pour utiliser vagabond, alors que vous allez en fait créer le système avec virtualbox pour le faire?
mc0e

10

J'ai une application similaire à la vôtre, à une différence près: je dois redémarrer le système et récupérer les instantanés.

Ce qui vous intéresse, c'est le mode sans tête .

J'ai quelques-uns de ces services alors j'utilise le script suivant:

VBox_StopRestoreStart.sh

#!/bin/bash
if [ -z "$1" ]; then
        echo "Usage: $0 VMNAME_or_UUID"
        exit 1
fi
set -x
VBoxManage controlvm  "$1" poweroff  #enforce turnoff
VBoxManage snapshot   "$1" restorecurrent   #retore state
VBoxManage showvminfo "$1" | grep State   #display state to ensure
VBoxHeadless -s       "$1"  #run in headless mode in background

Comment puis-je fermer la machine virtuelle?

SI vous souhaitez éteindre la machine virtuelle avec élégance, vous avez deux options, selon votre application:

  • Émulez le "bouton d'arrêt" ou le "bouton de veille" et préparez la machine virtuelle à réagir dessus (pour se fermer normalement)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Enregistrer l'état de la machine virtuelle pour pouvoir ensuite être restauré
    • VBoxManage controlvm <uuid>|<VMname> savestate

CONSEILS: Vous pourriez trouver utile:

  • VBoxManage list vms - liste des vms disponibles
  • rdesktop IP-ADDR:3389ou rdesktop-vrdp IP-ADDR:3389- lorsque vous souhaitez une interface graphique (même à distance ) lorsque vous utilisez le mode sans tête:VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - commencez par l'interface graphique pour le débogage local

Chapitre du manuel de VirtualBox lié: Chapitre 7. Machines virtuelles distantes - Étape par étape: créer une machine virtuelle sur un serveur sans tête

PS Si vous êtes intéressé par les solutions complètes déjà mises en œuvre, OpenStack semble un choix intéressant.


10

Consultation de la documentation de gestion de VM VirtualBox à l' adresse http://www.virtualbox.org/manual/ch08.html

Pour lister les VM, utilisez la commande VBoxManage list vms

Pour démarrer la VM, utilisez la commande VBoxManage startvm

http://www.virtualbox.org/manual/ch08.html#vboxmanage-controlvm

Pour contrôler la VM, utilisez VBoxManage controlvm

La controlvmsous-commande vous permet de modifier l'état d'une machine virtuelle en cours d'exécution. Les éléments suivants peuvent être spécifiés:

VBoxManage controlvm <vm> pausemet temporairement une machine virtuelle en attente, sans changer définitivement son état. La fenêtre de la machine virtuelle sera peinte en gris pour indiquer que la machine virtuelle est actuellement en pause. (Cela équivaut à sélectionner l'élément "Pause" dans le menu "Machine" de l'interface graphique.)

Utilisez VBoxManage controlvm <vm> resumepour annuler une commande de pause précédente. (Cela revient à sélectionner l’option "Reprendre" dans le menu "Machine" de l’interface graphique.)

VBoxManage controlvm <vm> reseta le même effet sur une machine virtuelle que d'appuyer sur le bouton "Réinitialiser" d'un ordinateur réel: un redémarrage à froid de la machine virtuelle, qui redémarre et redémarre immédiatement le système d'exploitation invité. L'état de la machine virtuelle n'est pas enregistré au préalable et des données peuvent être perdues. (Cela équivaut à sélectionner l'élément "Réinitialiser" dans le menu "Machine" de l'interface graphique.)

VBoxManage controlvm <vm> poweroffa le même effet sur une machine virtuelle que de tirer le câble d’alimentation sur un ordinateur réel. Là encore, l'état de la machine virtuelle n'est pas enregistré au préalable et des données peuvent être perdues. (Cela équivaut à sélectionner l'élément "Fermer" dans le menu "Machine" de l'interface graphique ou à appuyer sur le bouton de fermeture de la fenêtre, puis à sélectionner "Eteindre la machine" dans la boîte de dialogue.)

Après cela, l'état de la VM sera "Eteint".


Notez que sur certains systèmes, c'est le vboxmanagecas (tous en minuscules).
Arcege

2
Merci pour votre réponse, mais malheureusement, cela ne résout pas mon problème: je dois gracieusement fermer l'invité, à savoir délivrer un « shutdown -h maintenant » à l' intérieur du client et ont l'hôte d' attendre jusqu'à ce que le client a fermé complètement. Aucune des VBoxManage controlvmsous-commandes ne le fait.
Jstarek

Vous pouvez vous assurer qu'en revérifiant que tous les messages virtuels sont hors service dans l'hôte avant que celui-ci ne tombe en panne. Si vous avez besoin de contrôler l'hôte depuis l'invité, alors virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol mais cela ne vous donnera peut-être pas ce que vous recherchez. Vous devez écrire un script de démarrage tel que /etc/init.d/vboxvms-servicescript sur le système hôte, qui au démarrage rendra tous les vms actifs et à l’arrêt, les arrêtera tous.
Nikhil Mulley

VBoxManage controlvm savestateest une autre possibilité (du moins google me dit), il enregistre le statut des machines et l’arrête proprement, mais toujours aucun moyen de forcer l’hôte à attendre.
Baarn

5

Pour un système basé sur systemd, vous pouvez essayer ceci.

Étape 1: créer un fichier de service

[Unit]
Description=VBox Virtual Machine %i Service
Requires=systemd-modules-load.service
After=systemd-modules-load.service

[Service]
User=user
Group=vboxusers
ExecStart=/usr/bin/VBoxHeadless -s %i
ExecStop=/usr/bin/VBoxManage controlvm %i savestate

[Install]
WantedBy=multi-user.target

Étape 2: Activer le fichier de service

$ sudo systemctl enable vboxvmservice@vm_name.service

Références


1
Il est préférable d’inclure une réponse ici et de fournir éventuellement des liens vers des informations plus détaillées. Les cibles de lien disparaissent sans préavis, ce qui rend votre réponse inutile.
Anthon

Eh bien, le problème est que je ne peux pas vraiment copier tout le fichier systemd dans le lien 1 ici, ou devrais-je le faire?
Jan Rüegg

Malheureusement, "Link Rot" est un énorme problème dans ces cas-là ... Pour la postérité, je pense que les deux lignes suivantes reprennent l'idée de base de votre lien: créer un service qui permet VBoxHeadless -s %ide démarrer et VBoxManage controlvm %i savestated'arrêter la machine virtuelle.
jstarek

J'ai essayé cela dans Jessie, mais cela n'a pas fonctionné. Utilisateur et groupe créés, définissez la propriété de tous les fichiers (y compris / dev / vbox *). Mais lorsque le service démarre, il ne peut pas trouver la machine virtuelle, même si le nom est correct. Utilisera le script d'initialisation après tout.
Mivk

3

Que diriez-vous d'envoyer la commande via ssh de l'hôte à l'invité?

Je ne suis pas sûr si cela fonctionne et si vous pouvez vérifier l'état de la machine par la suite ou obtenir quelque chose comme un état de sortie, mais il devrait au moins être nettoyé.


Bien pensé, mais cela garantirait que la machine virtuelle invitée soit accessible via le réseau à partir de l'hôte, au moins via le port ssh (22).
Nikhil Mulley

Fondamentalement, cela fonctionnerait, l’appliance peut être atteinte dans l’ensemble du réseau local via son entrée DNS. Cependant, supposons que j'ai écrit un script qui ssh'd dans l'appliance chaque fois que l'hôte tombe en panne - il devrait toujours bloquer (pause) jusqu'à ce que l'invité se soit complètement arrêté. C’est précisément le sens de ma question: comment le script peut-il savoir que l’invité est en panne, de sorte qu’il puisse restituer un flux de contrôle à SysV-Init et que l’hôte puisse continuer à s’arrêter?
Jstarek

1
Votre commentaire suppose que tout fonctionnera correctement sur le système hôte et non sur le système invité. Que se passe-t-il si le câble d'alimentation est branché sur le système hôte? C'est une discussion différente. Votre système hôte SysV-init attendra que le script de service arrête les machines virtuelles tant qu'il comprend la logique permettant d'extraire correctement les machines virtuelles invitées (arrêt de l'exécutif sur un hôte distant ou simplement mise hors tension via l'interface vbox) et puis renvoyer l’état de succès ou d’échec à la console ou à init.
Nikhil Mulley

1
En ce qui concerne: comment le script sait quand l'invité est en panne, essayez de vérifier si la machine virtuelle est activée ou non à partir de l'interface de VboxManager et si l'invité est ssh'able. En outre, mettez en place une surveillance sur le système hôte afin de déterminer si la machine virtuelle est disponible auprès de Vboxmanager et de son serveur ssh'able en temps voulu.
Nikhil Mulley

1

Ma solution: dans cet interpréteur de scripts, 'root' est l'invocateur et 'l'utilisateur' est le propriétaire de 'thevm'

Je sais que les vms ont pris fin lorsque la sortie de la commande VBoxManage list runningvmsrenvoie une chaîne vide.

...
start(){
    su -c "VBoxHeadless --startvm thevm" -s /bin/bash theuser &
    # maybe another vbox command
}

stop(){
    su -c "VBoxManage controlvm thevm acpipowerbutton" -s /bin/bash theuser
    # maybe another vbox command
    while [ "`su -c 'VBoxManage list runningvms' -s /bin/bash theuser`" != "" ]
    do
        echo waiting for VMs to shutdown
        sleep 3
    done
}
...

1

Pour démarrer vm:

VBoxManage startvm VMNAME --type headless

Pour arrêter vm:

VBoxManage controlvm VMNAME savestate

Répertoriez tous les vm en cours d'exécution:

VBoxManage list runningvms

0

Peut-être que cela aidera dans le cadre de la solution.

VBoxManage list runningvms | tr -s '\" {' '%{' | cut -d '%' -f3  | while read uuid; do
   VBoxManage controlvm $uuid savestate; 
done

0

Pourquoi ne vous connectez-vous pas à votre invité et arrêtez-vous à partir de là?

À moins que vous n'ayez une bonne raison de ne pas installer sshd et d'accéder à la machine virtuelle via la VBox, j'opterais pour un script qui ne fait que générer un script ssh shutdown -h now. Pour être honnête, je créerais un script pour chaque machine qui l'arrêterait correctement et effectuerait quelques vérifications.

Emballez simplement un script /etc/init.d/shutdown_vm qui appelle l’autre depuis l’hôte, l’appel sera bloqué jusqu’à ce qu’il soit prêt. Ce processus (tel que décrit) ajoute une dépendance linux sur l'invité mais supprime la dépendance VBox sur l'hôte.

Pour aller droit au but: vous n'avez pas besoin d'accéder à la VBox pour éteindre une machine, si vous avez un moyen d'y accéder (c.-à-d. Ssh), le système d'exploitation aura toujours un moyen de le faire (l'allumer, c'est différent, bien sûr).


Deux raisons: premièrement, comme indiqué dans la question initiale, je ne souhaitais pas modifier l'OS invité fortement modifié si cela n'était pas vraiment nécessaire. Deuxièmement, et plus important encore, cela visait à fournir un moyen propre d’arrêter automatiquement toutes les machines virtuelles en cours d’exécution si l’hôte était arrêté.
Jstarek

@jstarek Mais vous n'avez pas besoin de modifier votre système d'exploitation invité si vous ne le souhaitez pas (vous avez une possibilité de connexion ou 99,99% du temps, ou est-ce une exception). Et c’est exactement l’idée, si l’hôte tombe en panne, le script approprié sera appelé lors du changement d’exécution, et cela se connectera à l’invité et le fermera de "dedans", comme le fait vagabond de toute façon ... avant de commencer "brute" force "c'est ..."
estani
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.