[libvirt] [PATCH v2] libvirt-guests: Add parallel startup and shutdown of guests

Peter Krempa pkrempa at redhat.com
Thu Mar 1 14:23:47 UTC 2012


With this patch, it's possible to shut down guests in parallel. Parallel
startup was possible before, but this functionality was not documented
properly.

To enable parallel startup set the START_DELAY to 0.

Parallel shutdown has a configurable parameter PARALLEL_SHUTDOWN that
defines the number of machines being shut down in parallel. Enabling
this feature changes the semantics of SHUTDOWN_TIMEOUT parameter that is
applied as a cumulative timeout to shutdown all guests on a URI.
---
Diff to v1:
-changed "domains" to "guests"
-used efficient code to avoid subshells
-remove unused helper functions
-added error message when loosing track of guest in case of error
-added docs that setting of SHUTDOWN_TIMEOUT is needed with shutdown action
-added initialisation of PARALLEL_SHUTDOWN
-fixed output redirections
-fixed typo in sysconfig file

 tools/libvirt-guests.init.sh |  116 +++++++++++++++++++++++++++++++++++++++---
 tools/libvirt-guests.sysconf |   12 ++++-
 2 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/tools/libvirt-guests.init.sh b/tools/libvirt-guests.init.sh
index c867ece..141d7fa 100644
--- a/tools/libvirt-guests.init.sh
+++ b/tools/libvirt-guests.init.sh
@@ -42,6 +42,7 @@ URIS=default
 ON_BOOT=start
 ON_SHUTDOWN=suspend
 SHUTDOWN_TIMEOUT=0
+PARALLEL_SHUTDOWN=0
 START_DELAY=0
 BYPASS_CACHE=0

@@ -273,6 +274,102 @@ shutdown_guest()
     fi
 }

+# shutdown_guest_async URI GUEST
+# Start a ACPI shutdown of GUEST on URI. This function returns after the command
+# was issued to libvirt to allow parallel shutdown.
+shutdown_guest_async()
+{
+    uri=$1
+    guest=$2
+
+    name=$(guest_name "$uri" "$guest")
+    eval_gettext "Starting shutdown on guest: \$name"
+    echo
+    retval run_virsh "$uri" shutdown "$guest" > /dev/null
+}
+
+# guest_count GUEST_LIST
+# Returns number of guests in GUEST_LIST
+guest_count()
+{
+    set -- $1
+    echo $#
+}
+
+# check_guests_shutdown URI GUESTS
+# check if shutdown is complete on guests in "GUESTS" and returns only
+# guests that are still shutting down
+check_guests_shutdown()
+{
+    uri=$1
+    guests=$2
+
+    guests_up=
+    for guest in $guests; do
+        if ! guest_is_on "$uri" "$guest" >/dev/null 2>&1; then
+            eval_gettext "Failed to determine state of guest: \$guest. Not tracking it anymore."
+            echo
+            continue
+        fi
+        if "$guest_running"; then
+            guests_up="$guests_up $guest"
+        fi
+    done
+    echo "$guests_up"
+}
+
+# print_guests_shutdown URI BEFORE AFTER
+# Checks for differences in the lists BEFORE and AFTER and prints
+# a shutdown complete notice for guests that have finished
+print_guests_shutdown()
+{
+    uri=$1
+    before=$2
+    after=$3
+
+    for guest in $before; do
+        case " $after " in
+            *" $guest "*) continue;;
+        esac
+
+        name=$(guest_name "$uri" "$guest")
+        eval_gettext "Shutdown of guest \$name complete."
+        echo
+    done
+}
+
+# shutdown_guests_parallel URI GUESTS
+# Shutdown guests GUESTS on machine URI in parallel
+shutdown_guests_parallel()
+{
+    uri=$1
+    guests=$2
+
+    on_shutdown=
+    timeout=$SHUTDOWN_TIMEOUT
+    while [ -n "$on_shutdown" ] || [ -n "$guests" ]; do
+        while [ -n "$guests" ] &&
+              [ $(guest_count "$on_shutdown") -lt "$PARALLEL_SHUTDOWN" ]; do
+            set -- $guests
+            guest=$1
+            shift
+            guests=$*
+            shutdown_guest_async "$uri" "$guest"
+            on_shutdown="$on_shutdown $guest"
+        done
+        sleep 1
+        timeout=$(($timeout - 1))
+        if [ $timeout -le 0 ]; then
+            eval_gettext "Timeout expired while shutting down domains"; echo
+            RETVAL=1
+            return
+        fi
+        on_shutdown_prev=$on_shutdown
+        on_shutdown=$(check_guests_shutdown "$uri" "$on_shutdown")
+        print_guests_shutdown "$uri" "$on_shutdown_prev" "$on_shutdown"
+    done
+}
+
 # stop
 # Shutdown or save guests on the configured uris
 stop() {
@@ -359,13 +456,18 @@ stop() {
             eval_gettext "Shutting down guests on \$uri URI..."; echo
         fi

-        for guest in $list; do
-            if "$suspending"; then
-                suspend_guest "$uri" "$guest"
-            else
-                shutdown_guest "$uri" "$guest"
-            fi
-        done
+        if [ "$PARALLEL_SHUTDOWN" -gt 1 ] &&
+           ! "$suspending"; then
+            shutdown_guests_parallel "$uri" "$list"
+        else
+            for guest in $list; do
+                if "$suspending"; then
+                    suspend_guest "$uri" "$guest"
+                else
+                    shutdown_guest "$uri" "$guest"
+                fi
+            done
+        fi
     done <"$LISTFILE"

     rm -f "$VAR_SUBSYS_LIBVIRT_GUESTS"
diff --git a/tools/libvirt-guests.sysconf b/tools/libvirt-guests.sysconf
index 9b8b64f..3e0db46 100644
--- a/tools/libvirt-guests.sysconf
+++ b/tools/libvirt-guests.sysconf
@@ -10,7 +10,8 @@
 #           libvirtd
 #ON_BOOT=start

-# number of seconds to wait between each guest start
+# Number of seconds to wait between each guest start. Set to 0 to allow
+# parallel startup.
 #START_DELAY=0

 # action taken on host shutdown
@@ -23,7 +24,14 @@
 #             value suitable for your guests.
 #ON_SHUTDOWN=suspend

-# number of seconds we're willing to wait for a guest to shut down
+# If set to non-zero, shutdown will suspend guests concurrently. Number of
+# guests on shutdown at any time will not exceed number set in this variable.
+#PARALLEL_SHUTDOWN=0
+
+# Number of seconds we're willing to wait for a guest to shut down. If parallel
+# shutdown is enabled, this timeout applies as a timeout for shutting down all
+# guests on a single URI defined in the variable URIS. This must be set to
+# a nonzero positive value if the shutdown action is requested.
 #SHUTDOWN_TIMEOUT=0

 # If non-zero, try to bypass the file system cache when saving and
-- 
1.7.3.4




More information about the libvir-list mailing list