Quando inicio uma máquina virtual qemu (Windows Server 2003) com
-qmp tcp:127.0.0.1:4444,server,nowait
Posso desligá-lo com o seguinte script
#!/bin/bash
telnet 127.0.0.1 4444 <<JSON
{ "execute": "qmp_capabilities" }
{ "execute": "system_powerdown" }
JSON
Mas existem dois problemas:
o script sai com $? = 1 e diz "Conexão fechada por host estrangeiro". Posso sair de forma limpa?
O processo de desligamento acontece de forma assíncrona. Assim, o script retorna de uma vez, sem esperar que a VM termine o desligamento. Como posso saber quando está pronto (sem usar o grep ps para qemu ou algo assim)?
O pano de fundo é que desejo hospedar uma instalação do Windows Server 2003 dentro de uma VM em um host Linux e quero usar um UPS. No caso de um blecaute, quero desligar a VM e depois o host – e, claro, o host não deve iniciar o desligamento até que a VM seja concluída.
Responder1
É possível usar expect. Um evento chamado "SHUTDOWN" será emitido quando a VM terminar. Portanto, o script a seguir inicia o desligamento e aguarda sua conclusão:
#!/usr/bin/expect
set timeout -1
spawn telnet 127.0.0.1 4444
expect "QMP"
send "{ 'execute': 'qmp_capabilities' }\n"
expect "return"
send "{ 'execute': 'system_powerdown' }\n"
expect "SHUTDOWN"
Como já recebi votos negativos para minha pergunta e especialmente considerando a seguinte afirmação
Se você estiver fazendo coisas como as acima, então todo o resto provavelmente será uma bagunça completa que mal funciona e irá quebrar se você olhar da maneira errada.
Eu tenho que dizer outra coisa. Eu realmente não vejo por que fazer algo assim é "provavelmente uma bagunça completa", especialmente a própria VM. Ao iniciá-lo via libvirt, a mesma coisa é feita em comparação com um script shell fazendo o trabalho. Por que deveria “mal funcionar”?! Além disso, o QMP foi projetado e disponibilizado através de algo como telnet para tornar possível fazer "algo assim" dessa forma, não é?
E o libvirt não é nada além de um wrapper para as interfaces de várias soluções de virtualização para que se possa lidar com múltiplas instalações de VM executadas por diferentes hipervisores da mesma maneira? Então, por que devo usá-lo quando executo apenas uma VM em um hipervisor?
Provavelmente estou completamente errado aqui, mas pelo menos é assim que se pode desligar uma máquina virtual qemu usando um script (bash) e saber quando isso é feito de maneira decente, sem ter que usar o libvirt.
Responder2
Me deparei com isso tentando desligar uma VM sem libvirtd. Quanto ao motivo, o libvirtd não foi iniciado devido a uma falha no dispositivo de troca. Eu queria desligar as VMs de maneira limpa e não pude usar o libvirt para salvar no disco. Com o acima eu descobri
em /var/lib/libvirt/qemu
para meia em $(find | grep monitor); faça printf "{ 'executar': 'qmp_capabilities' }\n{ 'executar': 'system_powerdown' }\n" | socat - UNIX-CONNECT:$sock; feito
Isto é para o UBUNTU. Então, no geral, sim, eu normalmente usaria o libvirt, mas sabia que era uma interface para algum outro comando ser desligado. Saber o que o libvirt estava realmente fazendo me permitiu desligar as VMs de maneira limpa.