Как узнать, когда завершено выключение виртуальной машины QEMU (инициированное через Telnet с использованием QMP)

Как узнать, когда завершено выключение виртуальной машины QEMU (инициированное через Telnet с использованием QMP)

Когда я запускаю виртуальную машину QEMU (Windows Server 2003) с

-qmp tcp:127.0.0.1:4444,server,nowait

Я могу заставить его выключиться с помощью следующего скрипта

#!/bin/bash
telnet 127.0.0.1 4444 <<JSON 
{ "execute": "qmp_capabilities" } 
{ "execute": "system_powerdown" } 

JSON

Но есть две проблемы:

  1. скрипт завершается с $? = 1 и выдает сообщение "Соединение закрыто внешним хостом". Можно ли сделать так, чтобы он завершился чисто?

  2. Процесс выключения происходит асинхронно. Таким образом, скрипт возвращается сразу, не дожидаясь, пока виртуальная машина завершит выключение. Как узнать, когда это будет сделано (без grepping ps для qemu или чего-то вроде этого)?

Предыстория такова: я хочу разместить установку Windows Server 2003 внутри виртуальной машины на хосте Linux и хочу использовать ИБП. В случае отключения электроэнергии я хочу выключить виртуальную машину, а затем хост — и, конечно, хост должен начать выключение не раньше, чем виртуальная машина завершит работу.

решение1

Это возможно с помощью expect. Событие под названием "SHUTDOWN" будет выдано, когда виртуальная машина завершит работу. Итак, следующий скрипт запускает выключение и ждет его завершения:

#!/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"

Поскольку я уже получил отрицательные отзывы за свой вопрос, и особенно учитывая следующее утверждение

Если вы делаете что-то вроде вышеперечисленного, то все остальное, скорее всего, представляет собой полный бардак, который едва работает и сломается, если вы посмотрите на него неправильно.

Я должен сказать еще одну вещь. Я действительно не понимаю, почему делать что-то подобное - "вероятно, полный беспорядок", особенно сама виртуальная машина. При запуске через libvirt делается то же самое, что и скрипт оболочки, выполняющий эту работу. Почему это должно "едва работать"?! Кроме того, QMP был разработан и доступен через что-то вроде telnet, чтобы сделать возможным делать "что-то подобное" таким образом, не так ли?

И разве libvirt не является всего лишь оберткой для интерфейсов нескольких решений виртуализации, чтобы можно было одинаково управлять несколькими установками vm, запущенными разными гипервизорами? Так зачем мне его использовать, если я запускаю только одну vm в одном гипервизоре?

Возможно, я здесь совершенно не прав, но, по крайней мере, это то, как можно завершить работу виртуальной машины QEMU с помощью скрипта (Bash) и узнать, когда это будет сделано корректным образом, без необходимости использования libvirt.

решение2

Наткнулся на это, пытаясь выключить виртуальную машину без libvirtd. Что касается причины, libvirtd не запускался из-за сбоя устройства подкачки. Я хотел аккуратно выключить виртуальную машину и не мог использовать libvirt для сохранения на диск. С вышеизложенным я пришел к

в /var/lib/libvirt/qemu

для sock в $(find | grep monitor); do printf "{ 'execute': 'qmp_capabilities' }\n{ 'execute': 'system_powerdown' }\n" | socat - UNIX-CONNECT:$sock; done

Это для UBUNTU. Так что в целом да, я обычно использую libvirt, но я знал, что это интерфейс к какой-то другой команде для выключения. Знание того, что на самом деле делает libvirt, позволило мне аккуратно выключить виртуальные машины.

Связанный контент