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;

 

=====