Bringing this question straight from here.
I am running archlinux and I have a VM running often on it along with the system. Most of the time actually.
My goal is to produce the following behaviour:
- A shutdown / poweroff / reboot / halt signal is sent to the system
- No action other then trying to shut down the virtual machines gracefully
- If the VMs are shut down gracefully after X seconds, proceeds with shutting down the host system too.
- If not, execute a different command
Just give me a good idea on what to work on, because I don’t even know from where to begin. I guess there is a call to the kernel that can be looked at.
Let me know.
My current code
At the moment I am using these scripts to gracefully shutdown my kvm virtual machines, and it works! But only as long as my user launches a shutdown or a reboot using his shell. Any other case wouldn’t work.
These alias:
alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "
Are triggering this function:
#!/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 $@
That launches this script if needed:
#!/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 Unit
I also made the following draft, to manage the execution of my VM:
bootvm@.service
[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
But how can I tell the system to don’t shut down the desktop environment, to stay as it is UNTIL the VM has been successfully shut down?
Because if the system can’t shut down the vm, I want to do it while still in my DE. I don’t want the computer to begin stopping all the services and remain hung until it just forces the shut down.