Como iniciar e desligar automaticamente máquinas VirtualBox?

52

Preciso executar um sistema de software destinado a ser instalado como um dispositivo em uma máquina dedicada. Para economizar energia, planejo executar o sistema em uma VM do VirtualBox.

O host é uma caixa padrão do Linux com um sistema SysV-Init, o convidado é um Linux fortemente modificado e eu preferiria não precisar alterá-lo ainda mais. O VirtualBox é usado na versão OSE.

Eu já descobri como iniciar a VM quando o host é inicializado ( Editar: isso é feito, como Nikhil mencionou abaixo, por meio do comando VBoxManager startvm), mas como posso desligar a VM normalmente? Qualquer script em execução no host precisaria aguardar até que o hóspede seja totalmente desligado.

Alguém pode sugerir como, por exemplo, um arquivo de serviço fazendo isso teria que procurar?

jstarek
fonte
você poderia dar o script de inicialização para iniciar a máquina virtual enquanto reinicia
Beginner

Respostas:

34

Você já tentou acpipowerbuttondeste conjunto de comandos?

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

Edite depois de ler os comentários:

Você pode usar acpidou outros utilitários da acpi para torná-lo elegante. Além disso, você pode fornecer mais informações sobre como desligar a máquina no momento?

A Plain shutdownnão esperaria por trabalhos inacabados; um atraso de tempo pode ser muito longo.

Eu suponho que você não está usando um gerenciador de janelas, então tente esta ferramenta.

Acabei de ver este daemon . Você pode achar util.

Mavromatis Lozay
fonte
Obrigado pela sua resposta e bem-vindo ao unix.stackexchange.com! No entanto, receio que sua resposta também não resolva o meu problema: o botão acpipower simula pressionar o botão liga / desliga em uma máquina real, mas depois de emitir este comando no host, a VM, novamente, levará algum tempo para desligar.
jstarek
4
Certo. Portanto, você deve escrever um loop que verifique se a VM ainda está em execução. ACPI é exatamente o mesmo método que eu uso em meus scripts para isso. vboxmanage list runningvmsaté a sua VM acabar.
Nils
OK, enquanto eu acho que vou me contentar com um wrapper de gerenciamento na prática, +50 para você por apontar para o initscript!
Jstarek
16

Em vez de codificar isso você mesmo, considere usar o Vagrant , criado para instanciar e controlar instâncias de caixas virtuais. A documentação é excelente e sugiro que você a verifique em vez de tentar criar sua própria.

O longo e curto disso é que você cria um arquivo de controle simples e executa vagrant uppara iniciar quantas instâncias do VirtualBox desejar. Você pode usar vagrant sshpara fazer login nos hosts e vagrant haltdesligar o host (sem terminar). vagrant destroyvai se livrar das instâncias.

Ele suporta provisionamento com fantoche, Ansible ou Chef e permite controlar a maioria das definições de configuração expostas do VBox.

Aaron Brown
fonte
2
Sou fã de vagabundos, mas, neste caso, para que diabos você gostaria? O OP está executando um dispositivo, não construindo seu próprio sistema, portanto, o provisionamento perde totalmente o objetivo. E por que criar uma 'caixa' personalizada do dispositivo, apenas para usar vagrant, quando você basicamente está passando pelo processo de construção do sistema com o VirtualBox para fazer isso?
Mc0e
10

Tenho aplicativo semelhante ao seu, com uma diferença: preciso reiniciar o sistema e me recuperar do instantâneo.

O que você está interessado é o modo sem cabeça .

Eu tenho alguns desses serviços, então eu uso o seguinte 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

como posso desligar normalmente a VM?

Se você deseja desativar a VM normalmente, você tem duas opções, dependendo do seu aplicativo:

  • Emule o "botão de desligamento" ou "botão de suspensão" e prepare a VM para reagir a ela (para fechar normalmente)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Salve o estado da VM para restaurar posteriormente
    • VBoxManage controlvm <uuid>|<VMname> savestate

Dicas: Você pode achar útil:

  • VBoxManage list vms - lista de vms disponíveis
  • rdesktop IP-ADDR:3389ou rdesktop-vrdp IP-ADDR:3389- quando você deseja uma GUI (mesmo remotamente ) quando executa no modo sem cabeça:VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - comece com GUI para depuração local

Capítulo do manual relacionado ao VirtualBox: Capítulo 7. Máquinas virtuais remotas - Passo a passo: criando uma máquina virtual em um servidor sem cabeça

PS Se você estiver interessado em soluções já implementadas com todos os recursos, o OpenStack parece uma opção interessante.

Grzegorz Wierzowiecki
fonte
10

Consultando a documentação de gerenciamento da VM do VirtualBox em http://www.virtualbox.org/manual/ch08.html

Para listar as VMs, use o comando VBoxManage list vms

Para iniciar a VM, use o comando VBoxManage startvm

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

Para controlar a VM, use VBoxManage controlvm

O controlvmsubcomando permite alterar o estado de uma máquina virtual em execução no momento. O seguinte pode ser especificado:

VBoxManage controlvm <vm> pausetemporariamente coloca uma máquina virtual em espera, sem alterar seu estado para sempre. A janela da VM será pintada em cinza para indicar que a VM está em pausa no momento. (Isso é equivalente a selecionar o item "Pausar" no menu "Máquina" da GUI.)

Use VBoxManage controlvm <vm> resumepara desfazer um comando de pausa anterior. (Isso é equivalente a selecionar o item "Continuar" no menu "Máquina" da GUI.)

VBoxManage controlvm <vm> resettem o mesmo efeito em uma máquina virtual do que pressionar o botão "Redefinir" em um computador real: uma reinicialização a frio da máquina virtual, que reiniciará e inicializará o sistema operacional convidado imediatamente imediatamente. O estado da VM não é salvo anteriormente e os dados podem ser perdidos. (Isso é equivalente a selecionar o item "Redefinir" no menu "Máquina" da GUI.)

VBoxManage controlvm <vm> powerofftem o mesmo efeito em uma máquina virtual que puxar o cabo de alimentação em um computador real. Novamente, o estado da VM não é salvo anteriormente e os dados podem ser perdidos. (Isso é equivalente a selecionar o item "Fechar" no menu "Máquina" da GUI ou pressionar o botão Fechar da janela e selecionar "Desligar a máquina" na caixa de diálogo.)

Depois disso, o estado da VM será "Desligado".

Nikhil Mulley
fonte
Observe que em alguns sistemas, é vboxmanage(tudo em minúsculas).
Arcege
2
Obrigado pela sua resposta, mas, infelizmente, isso não soluciona o meu problema: preciso encerrar o hóspede normalmente , ou seja, emitir um "shutdown -h now" dentro do hóspede e esperar que o host aguarde até que o hóspede seja desligado completamente. Nenhum dos VBoxManage controlvmsubcomandos faz isso.
jstarek
Você pode ter certeza de que, verificando novamente todas as vms estão inativas no host antes que o host seja desativado. Se você precisar controlar o host de dentro do convidado, virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol, mas isso pode não fornecer o que você está procurando. Você deve escrever um script de inicialização, como o /etc/init.d/vboxvms-servicescript no sistema host, que, ao iniciar, fará com que todos os vms sejam ativados e interrompidos, fará com que todos os vms sejam desativados.
Nikhil Mulley
VBoxManage controlvm savestateé outra possibilidade (pelo menos o google me diz), ele salva o status das máquinas e o desliga de maneira limpa, mas ainda não há como forçar o host a esperar.
Baarn
5

Para um sistema baseado em systemd, você pode tentar isso.

Etapa 1: criar um arquivo de serviço

[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

Etapa 2: ativar o arquivo de serviço

$ sudo systemctl enable vboxvmservice@vm_name.service

Referências

Jan Rüegg
fonte
11
É preferível incluir uma resposta aqui e, opcionalmente, fornecer links para informações mais detalhadas. Os destinos do link desaparecem sem aviso prévio, tornando sua resposta inútil.
Anthon
Bem, o problema é que eu realmente não posso copiar todo o arquivo systemd no link 1 aqui, ou devo fazer isso?
Jan Rüegg
Bem, infelizmente, "link rot" é um grande problema nesses casos ... Acho que, para a posteridade, as duas linhas a seguir capturam a idéia básica por trás do seu Link: Está criando um serviço que é usado VBoxHeadless -s %ipara iniciar e VBoxManage controlvm %i savestateparar a VM.
Jstarek
Tentei isso no Debian Jessie, mas não funcionou. Usuário e grupo criados, defina a propriedade de todos os arquivos (incluindo / dev / vbox *). Mas quando o serviço é iniciado, ele não consegue encontrar a VM, mesmo que o nome esteja correto. Afinal, usará o script init normal.
mivk
3

Que tal enviar o comando via ssh do host para o convidado?

Não tenho certeza se funciona e se você pode verificar o status da máquina posteriormente ou obter algo como um status de saída, mas deve estar limpo pelo menos.

Baarn
fonte
Bom pensamento, mas isso garantiria que a VM convidada pudesse ser acessada via rede a partir do host, pelo menos na porta ssh (22).
Nikhil Mulley
Basicamente, isso funcionaria, o dispositivo pode ser acessado em toda a LAN através de sua entrada DNS. No entanto, suponha que eu escrevi um script que ssh'd no dispositivo sempre que o host for desativado - ele ainda precisará bloquear (pausar) até que o convidado seja desligado completamente. Este é precisamente o ponto da minha pergunta: como o script pode saber quando o convidado está inativo, para que ele possa gerar o fluxo de controle de volta ao SysV-Init e o host pode continuar sendo desligado?
jstarek
11
Seu comentário pressupõe que tudo funcionará sem problemas no sistema host e não no sistema convidado. E se o cabo de alimentação estiver conectado ao sistema host? É uma discussão diferente. Seu SysV-init no sistema host aguardará o script de serviço interromper as VMs, contanto que o script de serviço entenda a lógica para desativar as VMs convidadas da maneira correta (desligamento executivo em host remoto ou desligamento através da interface vbox) e em seguida, retorne o status de sucesso ou falha ao console ou init.
Nikhil Mulley
11
Em relação a: como o script sabe quando o convidado está inativo, tente uma verificação simples se o vm está ativado ou desativado na interface do VboxManager e se o convidado é ssh'able. Além disso, coloque algum monitoramento no sistema host para verificar se a VM está disponível no Vboxmanager e se pode ser ssh'able em tempo hábil.
Nikhil Mulley
1

Minha solução: neste shellscript, 'root' é o invocador e 'theuser' é o proprietário de 'thevm'

Eu sei que o vms terminou quando a saída do comando VBoxManage list runningvmsretorna uma string vazia.

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

Para iniciar o vm:

VBoxManage startvm VMNAME --type headless

Para parar o vm:

VBoxManage controlvm VMNAME savestate

Listar todos os vm em execução:

VBoxManage list runningvms
RIT
fonte
0

Talvez isso ajude como parte da solução.

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

Por que você não entra no seu convidado e encerra a partir daí?

A menos que você tenha um bom motivo para não instalar o sshd e acessar a VM realmente por meio do VBox, eu optaria por um script que apenas emita um ssh shutdown -h now. Para ser sincero, eu criaria um script para cada máquina que a desligasse corretamente e realizaria algumas verificações enquanto estava nela.

Apenas compacte um script /etc/init.d/shutdown_vm que chame o outro do host, a chamada será bloqueada até que esteja pronto. Esse processo (conforme descrito) adiciona uma dependência do Linux no convidado, mas remove a dependência do VBox no host.

Direto ao assunto: você não precisa acessar o VBox para desligar uma máquina, se você tiver algum meio de acessá-lo (por exemplo, ssh), o sistema operacional sempre terá alguns meios para isso (ativá-lo, é diferente, é claro)

estani
fonte
Duas razões: primeiro, como declarado na pergunta original, eu não queria alterar o SO convidado fortemente modificado, se não fosse realmente necessário. Em segundo lugar, e mais importante, o objetivo era fornecer uma maneira limpa de desligar automaticamente todas as VMs em execução se o host fosse desligado.
jstarek
@ jstarek Mas você não precisa modificar o SO convidado se não quiser (99,99% do tempo você tem alguns meios para fazer login, ou isso é uma exceção). E exatamente essa é a ideia: se o host ficar inativo, o script apropriado será chamado ao alterar o tempo de execução, e isso só será registrado no convidado e desligado de "dentro", que é o que o vagabundo faz de qualquer maneira ... antes de ficar "brutal" forçar "que é ... #
1100 estani