Diese Frage klarstellenvon hier.
Ich verwende Archlinux und habe neben dem System oft auch eine VM darauf laufen. Eigentlich die meiste Zeit.
Mein Ziel ist es, folgendes Verhalten zu erzeugen:
- Ein Shutdown- / Poweroff- / Reboot- / Halt-Signal wird an das System gesendet
- Keine Aktion außer dem Versuch, die virtuellen Maschinen ordnungsgemäß herunterzufahren.
- Wenn die VMs nach X Sekunden ordnungsgemäß heruntergefahren werden, wird auch mit dem Herunterfahren des Hostsystems fortgefahren.
- Wenn nicht, führen Sie einen anderen Befehl aus
Geben Sie mir einfach eine gute Idee, woran ich arbeiten soll, denn ich weiß nicht einmal, wo ich anfangen soll. Ich vermute, es gibt einen Aufruf an den Kernel, der angeschaut werden kann.
Lass es mich wissen.
Mein aktueller Code
Im Moment verwende ich diese Skripte, um meine virtuellen KVM-Maschinen ordnungsgemäß herunterzufahren, und es funktioniert! Aber nur, solange mein Benutzer einenabschaltenoder einNeustartmit seiner Shell. In jedem anderen Fall würde es nicht funktionieren.
Dieser Alias:
alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "
Lösen diese Funktion aus:
#!/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 $@
Dadurch wird bei Bedarf dieses Skript gestartet:
#!/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
Systemd-Einheit
Um die Ausführung meiner VM zu verwalten, habe ich außerdem den folgenden Entwurf erstellt:
[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
Aber wie kann ich dem System sagen, dass es die Desktop-Umgebung nicht herunterfahren soll, sondern so bleiben soll, wie sie ist?BISdie VM wurde erfolgreich heruntergefahren? Denn wenn das System die VM nicht herunterfahren kann, möchte ich dies tun, während ich mich noch in meiner DE befinde. Ich möchte nicht, dass der Computer beginnt, alle Dienste zu stoppen und hängen bleibt, bis er einfach das Herunterfahren erzwingt.
Antwort1
Seltsame Methode zur Steuerung einer VM. Gute Methode: Verwenden Sie systemd zum automatischen Starten und Stoppen einer VM. Beispiel:
/etc/systemd/system/[email geschützt]
[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
... Und natürlich Konfiguration(en) zum Ausführen von VMs:
/etc/conf.d/qemu.d/eins
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"
... und eine andere VM-Konfiguration:
/etc/conf.d/qemu.d/zwei
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"
Und so weiter. Danke an die ArchWiki-Mitwirkendenfür diesen Artikel.
Antwort2
Der Entwurf des Originalbeitrags und die Antwort von @Oxyd sind nützlich, wenn Sie jede virtuelle Maschine einzeln steuern müssen.
Wenn jedoch das Herunterfahren/Starten gewünscht wirdalle VMsman könnte die libvirt-Gäste verwenden, wie erwähnt aufLibvirt-Dokumente.
- Bearbeiten Sie die Datei
/etc/conf.d/libvirt-guests
oder/etc/sysconfig/libvirt-guests
für CentOS, dann setzenON_SHUTDOWN=shutdown
undSHUTDOWN_TIMEOUT=0
- Ich denke, man muss den Dienst auch aktivieren
libvirt-guests
, zum Beispielsystemctl enable libvirt-guests
undsystemctl start libvirt-guests