La virtualisation est aujourd’hui assez largement répandue. Des solutions assez fiables existent. Sur Mac on connait notamment Parallels Desktop et VMWare Fusion. Côté libre, VirtualBox est aussi une référence, même si il est moins à la pointe, et il rempli pleinement la fonction pour des besoins plus ponctuels.
Pour certaines utilisations on a parfois besoin (ou envie) que sa machine virtuelle
- démarre en même temps que l’ordinateur,
- et idéalement, en tâche de fond comme service “headless”, de sorte que même si l’on n’a pas de session utilisateur ouverte, la machine virtuelle soit active.
C’est notamment utile si on souhaite utiliser VirtualBox pour virtualiser un OS serveur.
J’ai trouvé plusieurs méthodes sur le web. La plus courante consiste à utiliser la commande “/usr/bin/VBoxHeadless” pour lancer votre machine virtuelle, dans un launchdameon. Le problème c’est que cette commande ne gère pas la fermeture de votre machine virtuelle en réagissant au SIGTERM. Du coup, si vous redémarrez votre ordinateur, la machine virtuelle ne sera pas correctement fermée, provoquant crash et autre corruptions de fichiers. Evidemment on peut manuellement fermer le système virtuel avant d’éteindre l’ordinateur … mais pour une configuration qui demande le moins d’intervention d’un utilisateur, ce n’est pas top !
Pour compléter, j’ai cherché à activé phpVirtualBox, histoire d’avoir un accès via un navigateur à mes machines virtuelles.
Pour ce premier billet je vous propose de décomposer la méthode utilisée pour lancer une machine virtuelle en tâche de fond sur Mac.
Etape 1 : Préparer votre machine virtuelle
- Téléchargez et installez la dernière version de VirtualBox correspondant à votre système :
https://www.virtualbox.org/wiki/Downloads. - Téléchargez et installez la version de VirtualBox Extension Pack correspondant à votre système :
https://www.virtualbox.org/wiki/Downloads. - Installer l’OS que vous souhaitez comme machine virtuelle sous VirtualBox.
- Faites tous les tests nécessaires pour avoir une configuration stable et pleinement fonctionnelle.
- Installez un outil permettant de prendre le contrôle de votre machine virtuelle à distance et sans écran (par exemple Team Viewer, SparkAngel ou plus simplement RealVNC) et testez la prise de contrôle.
- Eteignez votre machine virtuelle.
Etape 2 : Préparer le Mac que vous allez utiliser pour héberger votre machine virtuelle en mode headless
- Téléchargez et installez la dernière version de VirtualBox correspondant à votre système :
https://www.virtualbox.org/wiki/Downloads. - Téléchargez et installez la version de VirtualBox Extension Pack correspondant à votre système :
https://www.virtualbox.org/wiki/Downloads. - Déplacez sur ce Mac le dossier contenant votre machine virtuelle (dossier contenant un fichier .vbox + le disque virtuel que vous avez créé pour cette machine, par défaut au format .vdi).
- Double-cliquez sur le fichier .vbox de votre machine virtuelle. Cette manipulation va ajouter à VirtualBox votre machine virtuelle. Si vous déplacez ensuite le dossier contenant votre machine virtuelle, pensez à la supprimer de VirtualBox, puis la relancer en ouvrant le fichier .vbox pour recréer les bonnes liaisons.
- Notez de côté le nom de votre machine virtuelle, car vous en aurez ensuite besoin.
- Faites un test en lançant depuis votre application VirtualBox votre machine virtuelle, puis éteignez-là et fermez VirtualBox.
Etape 3 : créer un script de démarrage et d’extinction des machines virtuelles qui récupère SIGTERM
Comme je l’ai dit plus haut, le lancement en mode headless d’une machine virtuelle via une ligne de commande ne pose pas de problème. Il suffit de faire un
/usr/bin/VBoxHeadless -s NAMEVM
en remplaçant ‘NAMEVM’ par le nom de votre machine virtuelle. Normalement, cela lance le démarrage de votre machine virtuelle, et vous devriez pouvoir y accéder à distance (puis la fermer correctement).
Une fois ce test effectué, nous allons à proprement parler mettre en place le script de démarrage suivant :
#!/bin/bash # Expects VM name to be passed as parameter trap shutdown SIGTERM function displayhelp() { echo echo Usage: echo echo -e $0 vmname\|'\x22'vmname \(long name\)'\x22' echo -e'\t'Starts VM named '\x22'vmname'\x22' \(use quotes to enclose names with spaces\) echo echo -e $0 -o\|--off vmname\|'\x22'vmname \(long name\)'\x22' echo -e '\t'Powers off VM named '\x22'vmname'\x22' \(use quotes to enclose names with spaces\) echo } function shutdown() { echo `date` "Received SIGTERM, powering off VBox: $VM" /usr/bin/VBoxManage controlvm $VM savestate # poweroff is bad # savestate is soft but works # acpipowerbutton doesn't always work echo `date` "Powered off VBox: $VM" echo exit 0 } function startup() { echo `date`'' "Starting VBox: $VM" # /usr/bin/VBoxHeadless --startvm $VM & ## Etrangement non fonctionnel sur mon mac /usr/bin/VBoxHeadless -s $VM & echo `date` Running VBox: $VM echo wait $! echo `date` Daemon exited: $0 $1 $2 } echo echo `date` Daemon launched: $0 $1 $2 case $2 in -o|--off) VM=$2; shutdown $VM;; esac case $1 in -o|--off) VM=$2; shutdown $VM;; -h|--help) displayhelp;; *) VM=$1; echo VM: $VM; startup $VM;; esac
Enregistrez ce script là où vous le souhaitez (chez moi /VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh). Si vous le souhaitez vous pouvez le faire via un éditeur de texte ou via le Terminal avec nano :
nano /VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh
Pour rendre ce script exécutable, il faut évidemment ajuster les droits CHMOD :
sudo chmod g+x /VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh
Vous n’avez besoin que d’un seul script pour l’ensemble de vos machines virtuelles. Pour l’utiliser, comme /usr/bin/VBoxHeadless, il faut appeler le script en mettant en paramètre le nom de votre machine virtuelle, exemple :
/VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh WindowsXP
Vous pouvez évidemment faire un test d’accès à votre machine virtuelle, et l’éteindre correctement !
4. Mettre en place l’entrée launchdaemon pour un lancement en tâche de fond au démarrage de l’ordinateur
Pour que votre machine virtuelle démarre en tâche de fond, sans nécessité qu’une session soit ouverte sur le Mac hôte, nous allons créer une entrée launchdaemon. Vous pouvez le faire avec Lingon ou manuellement :
- Créer le fichier .plist nécessaire, dans /Library/LaunchDaemons. Pour moi ce sera me.yvangodard.serveur.virtualbox.windowsxp.plist. Pour créer ce fichier vous pouvez utiliser votre éditeur favori ou le faire via le Terminal avec un petit :
nano /Library/LaunchDaemons/me.yvangodard.serveur.virtualbox.windowsxp.plist
Entrer ensuite le contenu du fichier,
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>me.yvangodard.reseauenscene.virtualbox.windowsxp</string> <key>ProgramArguments</key> <array> <string>/bin/sh</string> <string>/VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh</string> <string>WindowsXP</string> </array> <key>RunAtLoad</key> <true/> <key>StandardErrorPath</key> <string>/VirtualBox-VMs/WindowsXP/Logs/VBoxVM-error.log</string> <key>StandardOutPath</key> <string>/VirtualBox-VMs/WindowsXP/Logs/VBoxVM.log</string> <key>TimeOut</key> <integer>600</integer> <key>UserName</key> <string>localadmin</string> </dict> </plist>
Pensez à personnaliser la commande “/VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh” en fonction de l’emplacement et du nom que vous avez choisi pour ce script à l’étape précédente.
Remplacez aussi “WindowsXP” par le nom de votre machine virtuelle.
Il faut aussi, à la fin du fichier .plist penser à entrer le nom de l’utilisateur qui a les droits pour lancer la machine virtuelle (ici “localadmin”).
Pour être cohérents, il faut aussi une concordance entre le nom de votre fichier plist (ici me.yvangodard.reseauenscene.virtualbox.windowsxp.plist) et l’entrée “Label” du fichier (ici c’est donc me.yvangodard.reseauenscene.virtualbox.windowsxp).
Enfin, les emplacements des journaux (log) sont aussi à adapter selon votre configuration. - Charger manuellement ce fichier plist à l’aide de la commande launchctl (il sera ensuite chargé à chaque démarrage de l’ordinateur).
sudo launchctl load /Library/LaunchDaemons/me.yvangodard.reseauenscene.virtualbox.windowsxp.plist
5. Résoudre les petits problèmes …
Pour des raisons que je n’ai pas complètement identifiées encore, le chargement de la commande :
/VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh WindowsXP
via le LaunchDaemon (cf. étape 4) ne fonctionnait pas à chaque démarrage de la machine.
Au final, j’ai créé un autre script contenant
#!/bin/sh sleep 90 /VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh WindowsXP exit 0
Enregistrez ce script là où vous le souhaitez (chez moi /VirtualBox-VMs/AUTORUN_VBOX/VMStartWindowsXP.sh). Si vous le souhaitez vous pouvez le faire via un éditeur de texte ou via le Terminal avec nano :
nano /VirtualBox-VMs/AUTORUN_VBOX/VMStartWindowsXP.sh
Pour rendre ce script exécutable, il faut évidemment ajuster les droits CHMOD :
sudo chmod g+x /VirtualBox-VMs/AUTORUN_VBOX/VMStartWindowsXP.sh
Dans ce script j’ai déporté l’appel de la commande “/VirtualBox-VMs/AUTORUN_VBOX/daemonVM.sh WindowsXP” mais j’ai ajouté une temporisation en amont (ici 90 secondes) qui a réglé mes problèmes de crash aléatoires.
Au final j’ai donc du modifier mon LaunchDaemon. Il faut d’abort éteindre la machine virtuelle, en prenant le contrôle à distance, puis unloader le LaunchDaemon
sudo launchctl unload /Library/LaunchDaemons/me.yvangodard.reseauenscene.virtualbox.windowsxp.plist
modifier le fichier “me.yvangodard.reseauenscene.virtualbox.windowsxp.plist” ainsi :
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>me.yvangodard.reseauenscene.virtualbox.windowsxp</string> <key>ProgramArguments</key> <array> <string>/bin/sh</string> <string>/VirtualBox-VMs/AUTORUN_VBOX/VMStartWindowsXP.sh</string> </array> <key>RunAtLoad</key> <true/> <key>StandardErrorPath</key> <string>/VirtualBox-VMs/WindowsXP/Logs/VBoxVM-error.log</string> <key>StandardOutPath</key> <string>/VirtualBox-VMs/WindowsXP/Logs/VBoxVM.log</string> <key>TimeOut</key> <integer>600</integer> <key>UserName</key> <string>localadmin</string> </dict> </plist>
Puis il faut recharger le Daemon :
sudo launchctl load /Library/LaunchDaemons/me.yvangodard.reseauenscene.virtualbox.windowsxp.plist
Et pour finir quelques ressources sur lesquelles je me suis appuyé :
http://alblue.bandlem.com/2009/09/running-headless-vms-under-mac-os-x.html
http://grahamgilbert.com/blog/2012/04/21/headless-virtualbox/