I am trying to use /etc/libvirt/hooks/qemu to control the startup of several guests with interdependencies. The goal is to delay the start of guest B until the DNS server on guest A is running. To accomplish
this, I wrote a qemu hook script that detects the normal startup of guest B and start a second script in the background to wait until the preconditions to start B are fulfilled, then start B using a call to the virsh command.
For this strategy to work, it must handle the case where libvirt has chosen guest B as the first guest to attempt to start. (Although renaming the symlinks in /etc/libvirt/qemu/autostart to force starting
the guests in a particular order might work, I do not want to rely on this undocumented behavior). In the case where libvirt happens to attempt to start guest B before it starts guest A, the hook script needs to somehow tell libvirt to skip guest B and go
on to starting the next guest. Otherwise a deadlock would result as libvirt waited for B to start, but B was waiting for A to start. I have tried to handle this by returning failure from the hook script for the initial attempt to start B once the background
script has been started to implement the DNS check and eventually the delayed start of B.
Unfortunately, I cannot find a way to force libvirt to continue until the background script exits. No combination of background execution, nohup, disown, setsid -f, or at seems to detach the process sufficiently
to “fool” libvirt into acting on the “exit 1” line in the qemu script and proceed on to start other guests. As a result, the dependency of B on A deadlocks, and neither guest ever starts.
Can someone please either find an error in my approach or propose a different strategy to implement this customized dependency of the startup of one guest on another?
Thanks –
======
Here is my qemu script:
#!/bin/bash
if [[ "$2" == 'start' ]]; then
echo "$0: Starting $1..." |& logger
if [[ "$1" == 'B' ]]; then
# The next line is where the background script is invoked
/bin/bash /usr/local/bin/startB &
# These also don’t work:
# (/bin/bash /usr/local/bin/startB) & ; disown
# setsid -f (/bin/bash /usr/local/bin/startB) & ; disown
# Unfortunately, the exit in the following line doesn’t force libvirt to move on to the next guest to start until the background command has itself exited
exit 1;
fi
fi
Here is the startB script, including a call to a program named in the $dnssuccess variable that does the testing of DNS availability on guest A:
#!/bin/bash
until $dnssuccess
do
echo "$0: Delaying start of guest B 10 seconds" |& logger
sleep 10;
done
# It’s now OK to start guest
echo "$0: Now starting guest B" |& logger
virsh start B;
=====