Come avviare e arrestare automaticamente le macchine VirtualBox?


52

Devo eseguire un sistema software che deve essere installato come dispositivo su una macchina dedicata. Per risparmiare energia, intendo invece eseguire il sistema su una VM VirtualBox.

L'host è un box Linux standard con un sistema SysV-Init, l'ospite è un Linux fortemente modificato e preferirei non doverlo modificare ulteriormente. VirtualBox è utilizzato nella versione OSE.

Ho già capito come avviare la VM all'avvio dell'host ( Modifica: questo è fatto, come Nikhil menzionato di seguito, tramite il comando VBoxManager startvm), ma come posso spegnere la VM con grazia? Qualsiasi script in esecuzione sull'host dovrebbe attendere fino a quando l'ospite si è completamente spento.

Qualcuno può suggerire come, ad esempio, dovrebbe apparire un file di servizio in questo modo?


potresti dare lo script di avvio per avviare la macchina virtuale durante l'avvio
Principiante

Risposte:


34

Hai provato acpipowerbuttonda questo set di comandi?

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

Modifica dopo aver letto i commenti:

È possibile utilizzare acpido altri programmi di utilità acpi per renderlo grazioso. Inoltre, è possibile fornire ulteriori informazioni su come arrestare la macchina in questo momento?

Plain shutdownnon aspetterebbe lavori incompiuti, un ritardo potrebbe essere troppo lungo.

Suppongo che non stai usando un gestore di finestre, quindi prova questo strumento.

Ho appena visto questo demone . Potresti trovarlo utile.


Grazie per la tua risposta e benvenuto su unix.stackexchange.com! Tuttavia, temo che anche la tua risposta non risolva il mio problema: acpipowerbutton simula la pressione del pulsante di accensione su una macchina reale, ma dopo aver emesso questo comando sull'host, la VM impiegherebbe di nuovo un po 'di tempo a spegnersi.
Jstarek,

4
Sicuro. Quindi devi scrivere un ciclo che controlli se la VM è ancora in esecuzione. ACPI è esattamente lo stesso metodo che uso nei miei script per questo. vboxmanage list runningvmsfino a quando la tua VM non sarà sparita.
Nils,

OK, mentre penso che mi accontenterò di un wrapper di gestione in pratica, +50 a te per indicare l'indice!
Jstarek,

16

Piuttosto che codificarlo tu stesso, considera l'utilizzo di Vagrant , che è stato creato per creare un'istanza e controllare le istanze di virtualbox. La documentazione è eccellente e ti suggerisco di provarlo invece di provare a farne uno tuo.

Il lungo e breve è che si crea un semplice file di controllo e quindi si esegue vagrant upper avviare tutte le istanze di VirtualBox che si desidera. È possibile utilizzare vagrant sshper accedere agli host e vagrant haltper arrestare l'host (senza terminare). vagrant destroysi libererà delle istanze.

Supporta il provisioning con Puppet, Ansible o Chef e ti consente di controllare la maggior parte delle impostazioni di configurazione del VBox esposte.


2
Sono un fan del vagabondo, ma in questo caso, cosa mai lo vorresti? L'OP sta eseguendo un'appliance, non sta costruendo il proprio sistema, quindi il provisioning non rispecchia completamente il punto. E perché andare a creare una 'scatola' personalizzata dall'appliance, solo per usare il vagabondo, quando in pratica dovresti passare attraverso il processo di costruzione del sistema con virtualbox per farlo?
MC0e,

10

Ho un'applicazione simile alla tua, con una differenza: ho bisogno di riavviare il sistema e ripristinare da un'istantanea.

Quello che ti interessa è la modalità senza testa .

Ho alcuni di questi servizi quindi uso il seguente script:

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

come posso spegnere con grazia la VM?

Se si desidera disattivare la VM con grazia, sono disponibili due opzioni, a seconda dell'applicazione:

  • Emula "pulsante di spegnimento" o "pulsante di sospensione" e prepara la VM a reagire (per chiudere con grazia)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Salva stato VM per ripristinarlo in seguito
    • VBoxManage controlvm <uuid>|<VMname> savestate

CONSIGLI: Potresti trovare utile:

  • VBoxManage list vms - elenco dei vms disponibili
  • rdesktop IP-ADDR:3389oppure rdesktop-vrdp IP-ADDR:3389- quando desideri una GUI (anche da remoto ) quando corri in modalità senza testa:VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - inizia con la GUI per il debug locale

Capitolo del manuale di VirtualBox correlato: Capitolo 7. Macchine virtuali remote - Procedura dettagliata: creazione di una macchina virtuale su un server senza testa

PS Se sei interessato a soluzioni già implementate con funzionalità complete, OpenStack sembra una scelta interessante.


10

Guardando la documentazione di gestione della VM VirtualBox su http://www.virtualbox.org/manual/ch08.html

Per elencare le macchine virtuali, utilizzare il comando VBoxManage list vms

Per avviare la VM, utilizzare il comando VBoxManage startvm

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

Per controllare la VM, utilizzare VBoxManage controlvm

Il controlvmsottocomando consente di modificare lo stato di una macchina virtuale attualmente in esecuzione. È possibile specificare quanto segue:

VBoxManage controlvm <vm> pausemette temporaneamente in attesa una macchina virtuale, senza cambiarne definitivamente lo stato. La finestra della VM sarà dipinta in grigio per indicare che la VM è attualmente in pausa. (Ciò equivale a selezionare la voce "Pausa" nel menu "Macchina" della GUI.)

Utilizzare VBoxManage controlvm <vm> resumeper annullare un comando di pausa precedente. (Ciò equivale a selezionare la voce "Riprendi" nel menu "Macchina" della GUI.)

VBoxManage controlvm <vm> resetha lo stesso effetto su una macchina virtuale che premere il pulsante "Ripristina" su un computer reale: un riavvio a freddo della macchina virtuale, che riavvierà e riavvierà immediatamente il sistema operativo guest. Lo stato della VM non viene salvato in anticipo e i dati potrebbero andare persi. (Ciò equivale a selezionare la voce "Ripristina" nel menu "Macchina" della GUI.)

VBoxManage controlvm <vm> poweroffha lo stesso effetto su una macchina virtuale come tirare il cavo di alimentazione su un computer reale. Ancora una volta, lo stato della VM non viene salvato in anticipo e i dati potrebbero andare persi. (Ciò equivale a selezionare la voce "Chiudi" nel menu "Macchina" della GUI o premere il pulsante di chiusura della finestra, quindi selezionare "Spegni la macchina" nella finestra di dialogo.)

Successivamente, lo stato della VM sarà "Spento".


Nota che su alcuni sistemi, lo è vboxmanage(tutto in minuscolo).
Arcege,

2
Grazie per la tua risposta, ma sfortunatamente, questo non risolve il mio problema: devo chiudere con garbo l'ospite, ovvero emettere un "shutdown -h now" all'interno dell'ospite e far attendere l'ospite fino a quando l'ospite non si è completamente spento. Nessuno dei VBoxManage controlvmsottocomandi lo fa.
jstarek,

Puoi assicurarti che ricontrollando tutti i vms siano inattivi nell'host prima che l'host si disattivi. Se devi controllare l'host dall'interno del guest, allora virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol, ma questo potrebbe non darti quello che stai cercando. Dovresti scrivere uno script di avvio come /etc/init.d/vboxvms-servicescript sul sistema host, che all'avvio farà sì che tutti i vms accendano e allo stop, faranno scendere tutti i vms.
Nikhil Mulley

VBoxManage controlvm savestateè un'altra possibilità (almeno google mi dice), salva lo stato delle macchine e lo spegne in modo pulito, ma ancora nessun modo per costringere l'host ad aspettare.
Baarn,

5

Per un sistema basato su systemd, puoi provare questo.

Passaggio 1: creare un file di servizio

[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

Passaggio 2: abilitare il file di servizio

$ sudo systemctl enable vboxvmservice@vm_name.service

Riferimenti


1
Si preferisce includere qui una risposta e facoltativamente fornire collegamenti a informazioni più dettagliate. I target dei collegamenti scompaiono senza preavviso, rendendo inutile la risposta.
Anthon,

Bene, il problema è che non posso davvero copiare l'intero file systemd nel link 1 qui, o dovrei farlo?
Jan Rüegg,

Bene, sfortunatamente "link rot" è un grosso problema in quei casi ... Penso che, per i posteri, le seguenti due righe catturano l'idea di base dietro il tuo Link: sta creando un servizio che usa VBoxHeadless -s %iper avviare e VBoxManage controlvm %i savestatefermare la VM.
jstarek,

Ho provato questo in Debian Jessie, ma non ha funzionato. Creato utente e gruppo, imposta la proprietà di tutti i file (incluso / dev / vbox *). Ma quando il servizio viene avviato, non riesce a trovare la macchina virtuale, anche se il nome è corretto. Dopotutto userà il normale script init.
mivk,

3

Che ne dici di inviare il comando via ssh dall'host al guest?

Non sono sicuro che funzioni e se in seguito è possibile controllare lo stato della macchina o ottenere qualcosa come uno stato di uscita, ma dovrebbe essere pulito almeno.


Buona idea, ma ciò garantirebbe che la VM guest sia raggiungibile via rete dall'host, almeno attraverso la porta ssh (22).
Nikhil Mulley

Fondamentalmente, questo funzionerebbe, l'appliance può essere raggiunta in tutta la LAN tramite la sua voce DNS. Tuttavia, supponiamo di aver scritto uno script che è stato inserito nell'appliance ogni volta che l'host si arresta: dovrebbe comunque bloccare (mettere in pausa) fino a quando l'ospite non si è completamente spento. Questo è esattamente il punto della mia domanda: come può lo script sapere quando l'ospite è inattivo, in modo che possa restituire il flusso di controllo a SysV-Init e l'host può continuare a chiudere?
jstarek,

1
Il tuo commento presuppone che tutto funzioni senza problemi sul sistema host e non sul sistema guest. Cosa succede se il cavo di alimentazione è inserito nel sistema host? È una discussione diversa. Il tuo SysV-init sul sistema host attenderà che lo script di servizio arresti le macchine virtuali fino a quando lo script di servizio capisce la logica per spegnere correttamente le macchine virtuali guest (esegui l'arresto sull'host remoto o spegni semplicemente tramite l'interfaccia vbox) e quindi yield restituisce lo stato di esito positivo o negativo a console o init.
Nikhil Mulley,

1
Per quanto riguarda: come lo script sa quando l'ospite è inattivo, prova un semplice controllo se vm è acceso o spento dall'interfaccia di VboxManager e se l'ospite è ssh'able. Inoltre, metti un po 'di monitoraggio sul sistema host che eseguirà se la VM è disponibile da Vboxmanager e il suo servizio in modo tempestivo.
Nikhil Mulley,

1

La mia soluzione: in questo shellscript 'root' è l'invocatore e 'theuser' è il proprietario di 'thevm'

So che i vms sono terminati quando l'output del comando VBoxManage list runningvmsrestituisce una stringa vuota.

...
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

Per avviare vm:

VBoxManage startvm VMNAME --type headless

Per interrompere vm:

VBoxManage controlvm VMNAME savestate

Elenca tutti i vm in esecuzione:

VBoxManage list runningvms

0

Forse questo aiuterà come parte della soluzione.

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

0

Perché non accedi al tuo ospite e lo spegni da lì?

A meno che tu non abbia una buona ragione per non installare sshd e accedere alla VM davvero tramite VBox, sceglierei uno script che emette semplicemente un ssh shutdown -h now. Ad essere sincero, creerei uno script per ogni macchina che lo spenga correttamente ed eseguirà alcuni controlli mentre ci sono.

Basta impacchettare uno script /etc/init.d/shutdown_vm che chiama l'altro dall'host, la chiamata si bloccherà fino a quando non sarà pronta. Questo processo (come descritto) aggiunge una dipendenza linux sul guest ma rimuove la dipendenza VBox sull'host.

Andando al sodo: non è necessario accedere a VBox per spegnere una macchina, se si dispone di alcuni mezzi per accedervi (ad esempio ssh), il sistema operativo avrà sempre dei mezzi per farlo (accenderlo, ovviamente è diverso)


Due motivi: in primo luogo, come indicato nella domanda originale, non volevo alterare il sistema operativo guest fortemente modificato se non fosse realmente necessario. In secondo luogo, e ancora più importante, questo era destinato a fornire un modo pulito per arrestare automaticamente tutte le macchine virtuali in esecuzione se l'host fosse spento.
jstarek,

@jstarek Ma non è necessario modificare il sistema operativo guest se non si desidera (il 99,99% delle volte è possibile accedere o è un'eccezione). Ed è esattamente questa l'idea, se l'host scende, lo script corretto verrà chiamato quando si cambia runtime e questo si limita all'ospite e lo spegne da "dentro", che è comunque ciò che fa il vagabondo ... prima di andare "bruto" forza "cioè ...
estani,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.