qemu-agent это программа-демон, которая запускается внутри виртуальной машины для помощи в управлении.
Например: "замораживать\размораживать" файловую систему, приостанавливать выполнение, исполнять комманды, создавать\редактировать файлы и т.д.
Данные функции являются неотъемлемыми частями администрирования виртуальной инфраструктурой, такие как: создания снапшотов, миграции, включения\выключения, конфигурирования сети и т.д.
Исходные данные:
Начнем с выполнения команд внутри данной виртуальной машины.
Например установим пакет dstat, в котором находится утилита dstat.
Для этого на хост машине выполним команду:
"arg":["install", "dstat", "-y"]
казалось бы - можно упростить и написать аргументы в одной строке не разделяя:
Вывод команды находится в out-data, он закодирован в base64, для раскодирования можно воспользоваться любым онлайн сервисом, я использовал https://www.base64decode.org или утилитой base64 из состава пакета coreutils. Пример:
Теперь предлагаю рассмотреть вариант, когда скрипт или команда выполняется не мгновенно:
Выполним еще раз - ага, пока выполняется:
Но после выполнения первый запрос к данным статуса, очищает эту информацию и повторное обращение выдаст ошибку:
Отлично, с этим разобрались. Теперь предлагаю посмотреть, что происходит если выполняемая программа завершается не успешно, например запуск sleep с опцией -1:
Переменные out-data и err-data заполняются потоками stdout и stderr (если те не пустые), т.е. даже при успешном выполнении команды, которая что-то выводит на stderr, в status'e будет фигурировать err-data.
Например вывод статуса команды:
В следующий раз я расскажу о чтении\редактировании файлов и других возможностях qemu-agent.
Например: "замораживать\размораживать" файловую систему, приостанавливать выполнение, исполнять комманды, создавать\редактировать файлы и т.д.
Данные функции являются неотъемлемыми частями администрирования виртуальной инфраструктурой, такие как: создания снапшотов, миграции, включения\выключения, конфигурирования сети и т.д.
Подготовка.
Для того чтобы использовать нужно настроить взаимодействие хост-машины и VDS-ки через агента.Исходные данные:
- установленный на хост машине qemu-kvm (у меня он версии 1.2.5)
- установленная и запущенная виртуалка с ubuntu 16
root@ubuntu16:~# apt-get install qemu-guest-agent -yТеперь остановим виртуальную машину:
root@host:~# virsh shutdown ubuntu16Отредактируем конфиг:
root@host:~# virsh edit ubuntu16Добавив в секцию devices следующие настройки:
Теперь запустим:
root@host:~# virsh start ubuntu16Внутри виртуальной машины появится устройство:
root@ubuntu16:~# ls -al /dev/virtio-ports/org.qemu.guest_agent.0 lrwxrwxrwx 1 root root 11 Sep 4 06:47 /dev/virtio-ports/org.qemu.guest_agent.0 -> ../vport1p1и процесс qemu-ga слушающий это устройство:
root@ubuntu16:~# pgrep -a qemu-ga 2165 /usr/sbin/qemu-ga --daemonize -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0
Исполнение команд guest-exec
Теперь мы можем использовать агент и делать с виртуалкой "все что захотим".Начнем с выполнения команд внутри данной виртуальной машины.
Например установим пакет dstat, в котором находится утилита dstat.
Для этого на хост машине выполним команду:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec", "arguments":{"path":"/usr/bin/apt","arg":["install", "dstat", "-y"]}}'на вывод команда выдаст что-то вроде:
{"return":{"pid":2328}}используя этот pid узнаем чем закончилось дело:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2328}}' {"return":{"exitcode":0,"exited":true}}
- exited:true - говорит о том что программа закончила свое выполнение
- exitcode:0 - указывает код возврата программы (0 как правило говорит о успешном выполнении)
"arg":["install", "dstat", "-y"]
казалось бы - можно упростить и написать аргументы в одной строке не разделяя:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec", "arguments":{"path":"/usr/bin/apt","arg":["install snmpd -y"]}}' {"return":{"pid":2333}}но нет:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2333}}' {"return":{"exitcode":100,"exited":true}}Для получения помимо exitcode вывода команды (stdout), нужно добавить в arguments опцию capture-output и установить ее в true:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec", "arguments":{"path":"/bin/df","capture-output":true}}' {"return":{"pid":2345}} # virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2345}}' {"return":{"exitcode":0,"out-data":"RmlsZXN5c3RlbSAgICAgMUstYmxvY2tzICAgIFVzZWQgQXZhaWxhYmxlIFVzZSUgTW91bnRlZCBvbgp1ZGV2ICAgICAgICAgICAgIDIwMDM3MTIgICAgICAgMCAgIDIwMDM3MTIgICAwJSAvZGV2CnRtcGZzICAgICAgICAgICAgIDM2MjA4NCAgICA1MTU2ICAgIDM1NjkyOCAgIDIlIC9ydW4KL2Rldi9zZGExICAgICAgIDE2MzgxODY0IDE4NzM4MjggIDEzNjUyODQ0ICAxMyUgLwp0bXBmcyAgICAgICAgICAgICA5NzQzMjAgICAgICAgMCAgICA5NzQzMjAgICAwJSAvZGV2L3NobQp0bXBmcyAgICAgICAgICAgICAgIDUxMjAgICAgICAgMCAgICAgIDUxMjAgICAwJSAvcnVuL2xvY2sKdG1wZnMgICAgICAgICAgICAgOTc0MzIwICAgICAgIDAgICAgOTc0MzIwICAgMCUgL3N5cy9mcy9jZ3JvdXAKdG1wZnMgICAgICAgICAgICAgMTk0ODY4ICAgICAgIDAgICAgMTk0ODY4ICAgMCUgL3J1bi91c2VyLzAK","exited":true}}
Вывод команды находится в out-data, он закодирован в base64, для раскодирования можно воспользоваться любым онлайн сервисом, я использовал https://www.base64decode.org или утилитой base64 из состава пакета coreutils. Пример:
echo "RmlsZXN5c3RlbSAgICAgMUstYmxvY2tzICAgIFVzZWQgQXZhaWxhYmxlIFVzZSUgTW91bnRlZCBvbgp1ZGV2ICAgICAgICAgICAgIDIwMDM3MTIgICAgICAgMCAgIDIwMDM3MTIgICAwJSAvZGV2CnRtcGZzICAgICAgICAgICAgIDM2MjA4NCAgICA1MTU2ICAgIDM1NjkyOCAgIDIlIC9ydW4KL2Rldi9zZGExICAgICAgIDE2MzgxODY0IDE4NzM4MjggIDEzNjUyODQ0ICAxMyUgLwp0bXBmcyAgICAgICAgICAgICA5NzQzMjAgICAgICAgMCAgICA5NzQzMjAgICAwJSAvZGV2L3NobQp0bXBmcyAgICAgICAgICAgICAgIDUxMjAgICAgICAgMCAgICAgIDUxMjAgICAwJSAvcnVuL2xvY2sKdG1wZnMgICAgICAgICAgICAgOTc0MzIwICAgICAgIDAgICAgOTc0MzIwICAgMCUgL3N5cy9mcy9jZ3JvdXAKdG1wZnMgICAgICAgICAgICAgMTk0ODY4ICAgICAgIDAgICAgMTk0ODY4ICAgMCUgL3J1bi91c2VyLzAK" | base64 --decodeв обоих случаях получается примерно такой вывод:
Filesystem 1K-blocks Used Available Use% Mounted on udev 2003712 0 2003712 0% /dev tmpfs 362084 5156 356928 2% /run /dev/sda1 16381864 1873828 13652844 13% / tmpfs 974320 0 974320 0% /dev/shm tmpfs 5120 0 5120 0% /run/lock tmpfs 974320 0 974320 0% /sys/fs/cgroup tmpfs 194868 0 194868 0% /run/user/0
Теперь предлагаю рассмотреть вариант, когда скрипт или команда выполняется не мгновенно:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec", "arguments":{"path":"/bin/sleep","arg":["60"],"capture-output":true}}' {"return":{"pid":2360}}Если запросить статус такой команды, в процессе выполнения, то в ответе будет exited: false:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2360}}' {"return":{"exited":false}}Внутри виртуальной машины в этот момент ситуация выглядит примерно так:
root 2165 0.0 0.1 95760 3140 ? Ssl 06:45 0:00 /usr/sbin/qemu-ga --daemonize -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0 root 2360 0.0 0.0 6012 712 ? S 08:05 0:00 \_ /bin/sleep 60Т.е. qemu агент является родительским процессом для наших команд.
Выполним еще раз - ага, пока выполняется:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2360}}' {"return":{"exited":false}}И наконец, когда команда или скрипт завершаются, в ответе будет "стандартный" статус :
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2360}}' {"return":{"exitcode":0,"exited":true}}Обращаю внимание, что пока команда не выполнилась, можно запрашивать ее статус по pid'у неограниченное кол-во раз.
Но после выполнения первый запрос к данным статуса, очищает эту информацию и повторное обращение выдаст ошибку:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2360}}' error: internal error: unable to execute QEMU agent command 'guest-exec-status': Invalid parameter 'pid'Этот момент очень важен для организации скриптов-обёрток или других систем, использользующих данные команды или их выводы.
Отлично, с этим разобрались. Теперь предлагаю посмотреть, что происходит если выполняемая программа завершается не успешно, например запуск sleep с опцией -1:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec", "arguments":{"path":"/bin/sleep","arg":["-1"],"capture-output":true}}' {"return":{"pid":2389}}Вывод ошибки помещается в err-data и кодируется base64:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":2389}}' {"return":{"exitcode":1,"err-data":"L2Jpbi9zbGVlcDogaW52YWxpZCBvcHRpb24gLS0gJzEnClRyeSAnL2Jpbi9zbGVlcCAtLWhlbHAnIGZvciBtb3JlIGluZm9ybWF0aW9uLgo=","exited":true}}в err-data помещается все что попадает на stderr'a:
/bin/sleep: invalid option -- '1' Try '/bin/sleep --help' for more information
Переменные out-data и err-data заполняются потоками stdout и stderr (если те не пустые), т.е. даже при успешном выполнении команды, которая что-то выводит на stderr, в status'e будет фигурировать err-data.
Например вывод статуса команды:
# virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec", "arguments":{"path":"/usr/bin/curl","arg":["www.com"],"capture-output":true}}' {"return":{"pid":3100}} # virsh qemu-agent-command ubuntu16 '{"execute":"guest-exec-status", "arguments":{"pid":3100}}'вернет нам заполненные err-data и out-data одновременно.
В следующий раз я расскажу о чтении\редактировании файлов и других возможностях qemu-agent.
А если у нас гостит Windows? (с агентом)
ОтветитьУдалить