Если поставить этот вопрос прямоотсюда.
Я использую archlinux и у меня часто работает виртуальная машина вместе с системой. На самом деле большую часть времени.
Моя цель — добиться следующего поведения:
- В систему отправляется сигнал выключения/выключения питания/перезагрузки/остановки
- Никаких действий, кроме попытки корректно завершить работу виртуальных машин.
- Если виртуальные машины корректно завершают работу через X секунд, выполняется также завершение работы хост-системы.
- Если нет, выполните другую команду.
Просто дайте мне хорошую идею, над чем работать, потому что я даже не знаю, с чего начать. Я думаю, есть вызов к ядру, который можно посмотреть.
Дайте мне знать.
Мой текущий код
В данный момент я использую эти скрипты для корректного завершения работы моих виртуальных машин kvm, и это работает! Но только до тех пор, пока мой пользователь запускаетнеисправностьилиперезагрузитьиспользуя его оболочку. Любой другой случай не сработал бы.
Эти псевдонимы:
alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "
Запускают эту функцию:
#!/bin/bash
# This script checks for what is being passed to sudo.
# If the command passed is poweroff or reboot, it
# launches a custom script instead, that also looks
# fur currently running virtual machines and shuts them.
sudocheck() {
if [ $1 == "poweroff" ] || [ $1 == "reboot" ]; then
eval "sudo /home/damiano/.script/graceful $@"
else
eval "sudo $@"
fi
}
sudocheck $@
При необходимости запустится этот скрипт:
#!/bin/bash
i=0
e=0
## if virsh finds VMs running
virsh -c qemu:///system list | awk '{ print $3}' | \
if grep running > /dev/null ; then
virsh -c qemu:///system list --all | grep running | awk '{print "-c qemu:///system shutdown "$2}' | \
## shuts them dow gracefully
xargs -L1 virsh
## wait 30 seconds for them to go down
until (( i >= 30 || e == 1 )) ; do
## check every second for their status
virsh -c qemu:///system list --all | awk '{ print $3}' | \
if grep -E '(running|shutdown)' > /dev/null ; then
## keep waiting if still running
if (( i <= 30 )) ; then
sleep 1 && let i++ && echo $i
else
e=1 && notify-send 'Shutdown has been canceled' 'Please check the status of your virtual machines: seems like even though a stop signal has been sent, some are still running.' --urgency=critical
fi
else
## if no machine is running anymore, original power command can be executed
e=1 && eval $@
fi
done
fi
Системный блок
Я также сделал следующий проект для управления выполнением моей виртуальной машины:
[Unit]
Description=This service manages the execution of the %i virtual machine
Documentation=https://libvirt.org/manpages/virsh.html
[Service]
ExecStartPre=virsh -c qemu:///system
ExecStart=virsh start %i
ExecStop=virsh -c qemu:///system
ExecStop=virsh shutdown %i
TimeoutStopSec=30
KillMode=none
[Install]
WantedBy=multi-user.target
Но как мне сказать системе не закрывать среду рабочего стола, чтобы она оставалась такой, какая она есть?ДОVM была успешно выключена? Потому что если система не может выключить vm, я хочу сделать это, пока я нахожусь в DE. Я не хочу, чтобы компьютер начал останавливать все службы и оставался зависшим, пока он просто принудительно не выключится.
решение1
Странный способ управления VM. Хороший способ — использовать systemd для автоматического запуска и остановки VM. Например:
/etc/systemd/system/[email protected]
[Unit]
Description=QEMU virtual machine
[Service]
Environment="type=system-x86_64" "haltcmd=kill -INT $MAINPID"
EnvironmentFile=/etc/conf.d/qemu.d/%i
ExecStart=/usr/bin/qemu-${type} -name %i -nographic $args
ExecStop=/bin/sh -c ${haltcmd}
TimeoutStopSec=30
KillMode=none
[Install]
WantedBy=multi-user.target
... И, конечно же, конфигурации для запуска виртуальных машин:
/etc/conf.d/qemu.d/one
type="system-x86_64"
args="-enable-kvm -m 512 -hda /dev/vg0/vm1 -net nic,macaddr=DE:AD:BE:EF:E0:00 \
-net tap,ifname=tap0 -serial telnet:localhost:7000,server,nowait,nodelay \
-monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0"
haltcmd="echo 'system_powerdown' | nc localhost 7100" # or netcat/ncat
# You can use other ways to shut down your VM correctly
#haltcmd="ssh powermanager@vm1 sudo poweroff"
...и еще одна конфигурация виртуальной машины:
/etc/conf.d/qemu.d/two
args="-enable-kvm -m 512 -hda /srv/kvm/vm2.img -net nic,macaddr=DE:AD:BE:EF:E0:01 \
-net tap,ifname=tap1 -serial telnet:localhost:7001,server,nowait,nodelay \
-monitor telnet:localhost:7101,server,nowait,nodelay -vnc :1"
haltcmd="echo 'system_powerdown' | nc localhost 7101"
И т.д. Спасибо всем, кто вносит свой вклад в ArchWikiдля этой статьи.
решение2
Черновик оригинального поста и ответ @Oxyd полезны, когда вам нужно управлять каждой виртуальной машиной по отдельности.
Однако, если требуется выключить/запуститьвсе виртуальные машиныможно использовать гостевые системы libvirt, как указано наДокументы Libvirt.
- Отредактируйте файл
/etc/conf.d/libvirt-guests
, или/etc/sysconfig/libvirt-guests
для CentOS, затем установитеON_SHUTDOWN=shutdown
иSHUTDOWN_TIMEOUT=0
- Я думаю, что также необходимо активировать
libvirt-guests
услугу, например,systemctl enable libvirt-guests
иsystemctl start libvirt-guests