¿Cómo iniciar y apagar automáticamente las máquinas VirtualBox?

52

Necesito ejecutar un sistema de software destinado a ser instalado como un dispositivo en una máquina dedicada. Para ahorrar energía, planeo ejecutar el sistema en una VM VirtualBox.

El host es una caja Linux estándar con un sistema SysV-Init, el huésped es un Linux muy modificado y preferiría no tener que modificarlo más. VirtualBox se usa en la versión OSE.

Ya he descubierto cómo iniciar la VM cuando se inicia el host ( Editar: esto se hace, como Nikhil menciona a continuación, a través del comando VBoxManager startvm), pero ¿cómo puedo apagar la VM con gracia? Cualquier script que se ejecute en el host deberá esperar hasta que el invitado se haya apagado por completo.

¿Alguien puede sugerir cómo, por ejemplo, un archivo de servicio que hace esto tendría que verse?

jstarek
fuente
¿podría dar el script de inicio para iniciar la máquina virtual durante el arranque
Principiante

Respuestas:

34

¿Has probado acpipowerbuttondesde este conjunto de comandos?

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

Edite después de leer los comentarios:

Puede usar acpidu otras utilidades acpi para que sea elegante. Además, ¿puede proporcionar más información sobre cómo apaga la máquina en este momento?

Plain shutdownno esperaría por trabajos sin terminar, un retraso de tiempo puede ser demasiado largo.

Supongo que no estás usando un administrador de ventanas, así que prueba esta herramienta.

Acabo de ver a este demonio . Tu podrias encontrar esto útil.

Mavromatis Lozay
fuente
¡Gracias por su respuesta y bienvenido a unix.stackexchange.com! Sin embargo, me temo que su respuesta tampoco resuelve mi problema: acpipowerbutton simula presionar el botón de encendido en una máquina real, pero después de emitir este comando en el host, la VM, nuevamente, tardaría un tiempo en apagarse.
jstarek
44
Seguro. Por lo tanto, debe escribir un bucle que verifique si la VM todavía se está ejecutando. ACPI es exactamente el mismo método que utilizo en mis scripts para esto. vboxmanage list runningvmshasta que tu VM se haya ido.
Nils
OK, aunque creo que me conformaré con un contenedor de administración en la práctica, ¡+50 para ti por señalar el initscript!
jstarek
16

En lugar de codificar esto usted mismo, considere usar Vagrant , que está diseñado para crear instancias y controlar instancias de virtualbox. La documentación es excelente y le sugiero que la revise en lugar de intentar rodar la suya.

En resumidas cuentas, crea un archivo de control simple y luego lo ejecuta vagrant uppara iniciar tantas instancias de VirtualBox como desee. Puede usar vagrant sshpara iniciar sesión en los hosts y vagrant haltapagar el host (sin terminar). vagrant destroyeliminará las instancias.

Admite el aprovisionamiento con Puppet, Ansible o Chef y le permite controlar la mayoría de las configuraciones de configuración de VBox expuestas.

Aaron Brown
fuente
2
Soy fanático de los vagabundos, pero en este caso, ¿para qué lo querrías? El OP está ejecutando un dispositivo, no está construyendo su propio sistema, por lo que el aprovisionamiento pierde el punto por completo. ¿Y por qué ir y hacer una 'caja' personalizada del dispositivo, solo para usar vagabundo, cuando básicamente estarías pasando por el proceso de construir el sistema con virtualbox para hacer eso?
mc0e
10

Tengo una aplicación similar a la suya, con una diferencia: necesito reiniciar el sistema y recuperarme de la instantánea.

Lo que le interesa es el modo sin cabeza .

Tengo algunos de estos servicios, así que uso el siguiente 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

¿Cómo puedo apagar la máquina virtual con gracia?

SI desea apagar la máquina virtual con gracia, tiene dos opciones, dependiendo de su aplicación:

  • Emule el "botón de apagado" o el "botón de suspensión" y prepare la VM para reaccionar (para cerrar con gracia)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Guardar el estado de la VM para restaurar luego
    • VBoxManage controlvm <uuid>|<VMname> savestate

CONSEJOS: Puede que te resulte útil:

  • VBoxManage list vms - lista de vms disponibles
  • rdesktop IP-ADDR:3389o rdesktop-vrdp IP-ADDR:3389- cuando desea una GUI (incluso remotamente ) cuando ejecuta en modo sin cabeza:VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - Comience con GUI para la depuración local

Capítulo relacionado del manual de VirtualBox: Capítulo 7. Máquinas virtuales remotas: paso a paso: crear una máquina virtual en un servidor sin cabeza

PD: si está interesado en soluciones completas ya implementadas, OpenStack parece una opción interesante.

Grzegorz Wierzowiecki
fuente
10

Consulte la documentación de administración de VM VirtualBox en http://www.virtualbox.org/manual/ch08.html

Para enumerar las máquinas virtuales, use el comando VBoxManage list vms

Para iniciar la VM, use el comando VBoxManage startvm

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

Para controlar VM, use VBoxManage controlvm

El controlvmsubcomando le permite cambiar el estado de una máquina virtual que se está ejecutando actualmente. Se puede especificar lo siguiente:

VBoxManage controlvm <vm> pausetemporalmente pone una máquina virtual en espera, sin cambiar su estado para siempre. La ventana de VM se pintará en gris para indicar que la VM está actualmente en pausa. (Esto es equivalente a seleccionar el elemento "Pausa" en el menú "Máquina" de la GUI).

Use VBoxManage controlvm <vm> resumepara deshacer un comando de pausa anterior. (Esto es equivalente a seleccionar el elemento "Reanudar" en el menú "Máquina" de la GUI).

VBoxManage controlvm <vm> resettiene el mismo efecto en una máquina virtual que presionar el botón "Restablecer" en una computadora real: un reinicio en frío de la máquina virtual, que reiniciará y reiniciará el sistema operativo invitado nuevamente de inmediato. El estado de la VM no se guarda de antemano y se pueden perder datos. (Esto es equivalente a seleccionar el elemento "Restablecer" en el menú "Máquina" de la GUI).

VBoxManage controlvm <vm> powerofftiene el mismo efecto en una máquina virtual que tirar del cable de alimentación en una computadora real. Nuevamente, el estado de la VM no se guarda de antemano, y los datos pueden perderse. (Esto es equivalente a seleccionar el elemento "Cerrar" en el menú "Máquina" de la GUI o presionar el botón de cerrar de la ventana, y luego seleccionar "Apagar la máquina" en el cuadro de diálogo).

Después de esto, el estado de la VM estará "Apagado".

Nikhil Mulley
fuente
Tenga en cuenta que en algunos sistemas, lo es vboxmanage(todo en minúsculas).
Arcege
2
Gracias por su respuesta, pero desafortunadamente, esto no soluciona mi problema: necesito cerrar el invitado con gracia , es decir, emitir un "apagado -h ahora" dentro del invitado y hacer que el anfitrión espere hasta que el invitado se haya cerrado por completo. Ninguno de los VBoxManage controlvmsubcomandos hace eso.
jstarek
Puede asegurarse de que al volver a comprobar todos los vms están inactivos en el host antes de que este se apague. Si necesita controlar el host desde dentro del invitado, entonces virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol, pero esto puede no darle lo que está buscando. Debe escribir una secuencia de comandos de inicio como la /etc/init.d/vboxvms-servicesecuencia de comandos en el sistema host, que al inicio hará que todos los vms se activen y que al detenerse, todos los vms se apaguen.
Nikhil Mulley
VBoxManage controlvm savestatees otra posibilidad (al menos google me dice), guarda el estado de las máquinas y lo apaga limpiamente, pero aún no hay forma de obligar al host a esperar.
Baarn el
5

Para un sistema basado en systemd, puede probar esto.

Paso # 1: crea un archivo de servicio

[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

Paso # 2: habilite el archivo de servicio

$ sudo systemctl enable vboxvmservice@vm_name.service

Referencias

Jan Rüegg
fuente
1
Se prefiere incluir una respuesta aquí y, opcionalmente, proporcionar enlaces a información más detallada. Los objetivos de enlace desaparecen sin previo aviso, por lo que su respuesta no tiene valor.
Anthon
Bueno, el problema es que realmente no puedo copiar todo el archivo systemd en el enlace 1 aquí, ¿o debería hacer esto?
Jan Rüegg
Bueno, desafortunadamente "link rot" es un gran problema en esos casos ... Creo que, para la posteridad, las siguientes dos líneas captan la idea básica detrás de su Link: está creando un servicio que usa VBoxHeadless -s %ipara iniciar y VBoxManage controlvm %i savestatedetener la VM.
jstarek 05 de
Probé esto en Debian Jessie, pero no funcionó. Usuario y grupo creados, establezca la propiedad de todos los archivos (incluidos / dev / vbox *). Pero cuando se inicia el servicio, no puede encontrar la VM, aunque el nombre sea correcto. Utilizará el script de inicio normal después de todo.
mivk
3

¿Qué tal enviar el comando vía ssh desde el host al invitado?

No estoy seguro de si funciona y si puede verificar el estado de la máquina después u obtener algo como un estado de salida, pero al menos debería estar limpio.

Baarn
fuente
Bien pensado, pero esto garantizaría que se pueda acceder a la VM invitada a través de la red desde el host, al menos al puerto ssh (22).
Nikhil Mulley
Básicamente, esto funcionaría, se puede acceder al dispositivo en toda la LAN a través de su entrada DNS. Sin embargo, supongamos que escribí una secuencia de comandos que ssh'd en el dispositivo cada vez que el host se cae; todavía tendría que bloquear (pausar) hasta que el invitado se haya apagado por completo. Este es precisamente el punto de mi pregunta: ¿cómo puede saber el script cuando el invitado está inactivo, de modo que pueda devolver el flujo de control a SysV-Init y el host pueda continuar cerrándose?
jstarek
1
Su comentario asume que todo funcionará sin problemas en el sistema host y no en el sistema invitado. ¿Qué sucede si el cable de alimentación está enchufado en el sistema host? Es una discusión diferente. Su SysV-init en el sistema host esperará a que la secuencia de comandos de servicio detenga las máquinas virtuales siempre que la secuencia de comandos de servicio comprenda la lógica para apagar las máquinas virtuales invitadas de manera correcta (apagado ejecutivo en el host remoto o simplemente apagarse a través de la interfaz vbox) y luego, devuelva el estado de éxito o error a la consola o init.
Nikhil Mulley
1
En cuanto a: cómo el script sabe cuando el invitado está inactivo, intente verificar si el vm está activado o desactivado desde la interfaz de VboxManager y si el invitado es ssh'able. Además, ponga un poco de supervisión en el sistema host que realizará si la máquina virtual está disponible desde Vboxmanager y si ssh'able oportunamente.
Nikhil Mulley
1

Mi solución: en este shellscript, 'root' es el invocador, y 'theuser' es el propietario de 'thevm'

Sé que los vms han terminado cuando la salida del comando VBoxManage list runningvmsdevuelve una cadena vacía.

...
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
}
...
Jorge Sanchez
fuente
1

Para iniciar vm:

VBoxManage startvm VMNAME --type headless

Para detener vm:

VBoxManage controlvm VMNAME savestate

Enumere todos los vm en ejecución:

VBoxManage list runningvms
RIT
fuente
0

Quizás esto ayude como parte de la solución.

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

¿Por qué no inicias sesión en tu invitado y cierras desde allí?

A menos que tenga una buena razón para no instalar sshd y acceder a la VM realmente a través de VBox, elegiría un script que solo emita un ssh shutdown -h now. Para ser honesto, crearía un script para cada máquina que lo apaga correctamente y realizo algunos chequeos mientras lo hago.

Simplemente empaque un script /etc/init.d/shutdown_vm que llame al otro desde el host, la llamada se bloqueará hasta que esté lista. Este proceso (como se describe) agrega una dependencia de Linux en el invitado pero elimina la dependencia de VBox en el host.

Ir al grano: no necesita acceder a VBox para apagar una máquina, si tiene algún medio para acceder a él (es decir, ssh), entonces el sistema operativo siempre tendrá algún medio para eso (encenderlo, por supuesto, es diferente)

estani
fuente
Dos razones: Primero, como se indicó en la pregunta original, no quería alterar el sistema operativo invitado muy modificado si no fuera realmente necesario. En segundo lugar, y lo que es más importante, esto tenía la intención de proporcionar una forma limpia de apagar automáticamente todas las máquinas virtuales en ejecución si el host se apagaba.
jstarek
@jstarek Pero no tiene que modificar su sistema operativo invitado si no lo desea (el 99,99% de las veces tiene algún medio para iniciar sesión, o es una excepción). Y esa es exactamente la idea, si el host se cae, se llamará al script apropiado cuando se cambie el tiempo de ejecución y esto solo registra al invitado y lo apaga desde "adentro", que es lo que el vagabundo hace de todos modos ... antes de volverse "bruto" fuerza "es decir ...
estani