[libvirt] [PATCH RESEND] tools: Only install guests init script if --with-init=script=redhat

Cole Robinson crobinso at redhat.com
Sun Dec 9 03:23:57 UTC 2012


Most of this deals with moving the libvirt-guests.sh script which
does all the work to /usr/libexec, so it can be shared by both
systemd and traditional init. Previously systemd depended on
the script being in /etc/init.d

Required to fix https://bugzilla.redhat.com/show_bug.cgi?id=789747
---
Only change to the big script is dropping the LSB header

 .gitignore                      |   1 +
 libvirt.spec.in                 |   6 +-
 po/POTFILES.in                  |   2 +-
 tools/Makefile.am               |  18 +-
 tools/libvirt-guests.init.in    |  27 ++
 tools/libvirt-guests.init.sh    | 597 ----------------------------------------
 tools/libvirt-guests.service.in |   4 +-
 tools/libvirt-guests.sh.in      | 573 ++++++++++++++++++++++++++++++++++++++
 8 files changed, 620 insertions(+), 608 deletions(-)
 create mode 100644 tools/libvirt-guests.init.in
 delete mode 100644 tools/libvirt-guests.init.sh
 create mode 100644 tools/libvirt-guests.sh.in

diff --git a/.gitignore b/.gitignore
index 0dadd21..ca7d07a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -179,6 +179,7 @@
 /tools/*.[18]
 /tools/libvirt-guests.init
 /tools/libvirt-guests.service
+/tools/libvirt-guests.sh
 /tools/virsh
 /tools/virsh-*-edit.c
 /tools/virt-*-validate
diff --git a/libvirt.spec.in b/libvirt.spec.in
index d6e1fbe..d463c27 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1409,8 +1409,6 @@ rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.uml
 mv $RPM_BUILD_ROOT%{_datadir}/doc/libvirt-%{version} \
    $RPM_BUILD_ROOT%{_datadir}/doc/libvirt-docs-%{version}
 
-sed -i -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/libvirt-guests
-
 %if %{with_dtrace}
 %ifarch %{power64} s390x x86_64 ia64 alpha sparc64
 mv $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/libvirt_probes.stp \
@@ -1657,10 +1655,13 @@ fi
 
 %dir %attr(0700, root, root) %{_sysconfdir}/libvirt/nwfilter/
 
+%attr(0755, root, root) %{_libexecdir}/libvirt-guests.sh
 %if %{with_systemd}
 %{_unitdir}/libvirtd.service
+%{_unitdir}/libvirt-guests.service
 %else
 %{_sysconfdir}/rc.d/init.d/libvirtd
+%{_sysconfdir}/rc.d/init.d/libvirt-guests
 %endif
 %doc daemon/libvirtd.upstart
 %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
@@ -1925,7 +1926,6 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd
 
 %{_datadir}/libvirt/cpu_map.xml
 
-%{_sysconfdir}/rc.d/init.d/libvirt-guests
 %if %{with_systemd}
 %{_unitdir}/libvirt-guests.service
 %endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 586aa2b..6d78f48 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -194,7 +194,7 @@ src/xenapi/xenapi_utils.c
 src/xenxs/xen_sxpr.c
 src/xenxs/xen_xm.c
 tools/console.c
-tools/libvirt-guests.init.sh
+tools/libvirt-guests.sh.in
 tools/virsh.c
 tools/virsh-domain-monitor.c
 tools/virsh-domain.c
diff --git a/tools/Makefile.am b/tools/Makefile.am
index d646bab..605bf3b 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -41,6 +41,7 @@ DISTCLEANFILES =
 
 bin_SCRIPTS = virt-xml-validate virt-pki-validate
 bin_PROGRAMS = virsh virt-host-validate
+libexec_SCRIPTS = libvirt-guests.sh
 
 if HAVE_SANLOCK
 sbin_SCRIPTS = virt-sanlock-cleanup
@@ -187,7 +188,7 @@ uninstall-sysconfig:
 	rm -f $(DESTDIR)$(sysconfdir)/sysconfig/libvirt-guests
 	rmdir $(DESTDIR)$(sysconfdir)/sysconfig ||:
 
-EXTRA_DIST += libvirt-guests.init.sh
+EXTRA_DIST += libvirt-guests.sh.in libvirt-guests.init.in
 
 install-initscript: libvirt-guests.init
 	$(MKDIR_P) $(DESTDIR)$(sysconfdir)/rc.d/init.d
@@ -208,7 +209,7 @@ install-init:
 uninstall-init:
 endif # LIBVIRT_INIT_SCRIPT_RED_HAT
 
-libvirt-guests.init: libvirt-guests.init.sh $(top_builddir)/config.status
+libvirt-guests.sh: libvirt-guests.sh.in $(top_builddir)/config.status
 	$(AM_V_GEN)sed					\
 	    -e 's!\@PACKAGE\@!$(PACKAGE)!g'		\
 	    -e 's!\@bindir\@!$(bindir)!g'		\
@@ -219,20 +220,26 @@ libvirt-guests.init: libvirt-guests.init.sh $(top_builddir)/config.status
 	    < $< > $@-t &&				\
 	    chmod a+x $@-t &&				\
 	    mv $@-t $@
+BUILT_SOURCES += libvirt-guests.sh
 
+libvirt-guests.init: libvirt-guests.init.in libvirt-guests.sh
+	$(AM_V_GEN)sed \
+		-e 's!\@libexecdir\@!$(libexecdir)!g' \
+	< $< > $@-t && \
+	chmod a+x $@-t && \
+	mv $@-t $@
 
 
 EXTRA_DIST += libvirt-guests.service.in
-
 SYSTEMD_UNIT_DIR = /lib/systemd/system
 
 if LIBVIRT_INIT_SCRIPT_SYSTEMD
-install-systemd: libvirt-guests.service install-initscript install-sysconfig
+install-systemd: libvirt-guests.service install-sysconfig libvirt-guests.sh
 	$(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
 	$(INSTALL_DATA) libvirt-guests.service \
 	  $(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirt-guests.service
 
-uninstall-systemd: uninstall-initscript uninstall-sysconfig
+uninstall-systemd: uninstall-sysconfig
 	rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirt-guests.service
 	rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) ||:
 
@@ -251,6 +258,7 @@ libvirt-guests.service: libvirt-guests.service.in $(top_builddir)/config.status
 	    -e 's!\@localstatedir\@!$(localstatedir)!g'	\
 	    -e 's!\@sbindir\@!$(sbindir)!g'		\
 	    -e 's!\@sysconfdir\@!$(sysconfdir)!g'	\
+	    -e 's!\@libexecdir\@!$(libexecdir)!g'	\
 	    < $< > $@-t &&				\
 	    chmod a+x $@-t &&				\
 	    mv $@-t $@
diff --git a/tools/libvirt-guests.init.in b/tools/libvirt-guests.init.in
new file mode 100644
index 0000000..5f9a60e
--- /dev/null
+++ b/tools/libvirt-guests.init.in
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# the following is the LSB init header
+#
+### BEGIN INIT INFO
+# Provides: libvirt-guests
+# Required-Start: libvirtd
+# Required-Stop: libvirtd
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: suspend/resume libvirt guests on shutdown/boot
+# Description: This is a script for suspending active libvirt guests
+#              on shutdown and resuming them on next boot
+#              See http://libvirt.org
+### END INIT INFO
+
+# the following is chkconfig init header
+#
+# libvirt-guests:   suspend/resume libvirt guests on shutdown/boot
+#
+# chkconfig: 345 99 01
+# description:  This is a script for suspending active libvirt guests \
+#               on shutdown and resuming them on next boot \
+#               See http://libvirt.org
+#
+
+exec @libexecdir@/libvirt-guests.sh "$@"
diff --git a/tools/libvirt-guests.init.sh b/tools/libvirt-guests.init.sh
deleted file mode 100644
index 99ef331..0000000
--- a/tools/libvirt-guests.init.sh
+++ /dev/null
@@ -1,597 +0,0 @@
-#!/bin/sh
-
-# the following is the LSB init header
-#
-### BEGIN INIT INFO
-# Provides: libvirt-guests
-# Required-Start: libvirtd
-# Required-Stop: libvirtd
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: suspend/resume libvirt guests on shutdown/boot
-# Description: This is a script for suspending active libvirt guests
-#              on shutdown and resuming them on next boot
-#              See http://libvirt.org
-### END INIT INFO
-
-# the following is chkconfig init header
-#
-# libvirt-guests:   suspend/resume libvirt guests on shutdown/boot
-#
-# chkconfig: 345 99 01
-# description:  This is a script for suspending active libvirt guests \
-#               on shutdown and resuming them on next boot \
-#               See http://libvirt.org
-#
-
-sysconfdir="@sysconfdir@"
-localstatedir="@localstatedir@"
-libvirtd="@sbindir@"/libvirtd
-
-# Source function library.
-test ! -r "$sysconfdir"/rc.d/init.d/functions ||
-    . "$sysconfdir"/rc.d/init.d/functions
-
-# Source gettext library.
-# Make sure this file is recognized as having translations: _("dummy")
-. "@bindir@"/gettext.sh
-
-export TEXTDOMAIN="@PACKAGE@" TEXTDOMAINDIR="@localedir@"
-
-URIS=default
-ON_BOOT=start
-ON_SHUTDOWN=suspend
-SHUTDOWN_TIMEOUT=300
-PARALLEL_SHUTDOWN=0
-START_DELAY=0
-BYPASS_CACHE=0
-
-test -f "$sysconfdir"/sysconfig/libvirt-guests &&
-    . "$sysconfdir"/sysconfig/libvirt-guests
-
-LISTFILE="$localstatedir"/lib/libvirt/libvirt-guests
-VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/subsys/libvirt-guests
-
-RETVAL=0
-
-# retval COMMAND ARGUMENTS...
-# run command with arguments and convert non-zero return value to 1 and set
-# the global return variable
-retval() {
-    "$@"
-    if [ $? -ne 0 ]; then
-        RETVAL=1
-        return 1
-    else
-        return 0
-    fi
-}
-
-# run_virsh URI ARGUMENTS...
-# start virsh and let it execute ARGUMENTS on URI
-# If URI is "default" virsh is called without the "-c" argument
-# (using libvirt's default connection)
-run_virsh() {
-    uri=$1
-    shift
-
-    if [ "x$uri" = xdefault ]; then
-        virsh "$@" </dev/null
-    else
-        virsh -c "$uri" "$@" </dev/null
-    fi
-}
-
-# run_virsh_c URI ARGUMENTS
-# Same as "run_virsh" but the "C" locale is used instead of
-# the system's locale.
-run_virsh_c() {
-    ( export LC_ALL=C; run_virsh "$@" )
-}
-
-# test_connect URI
-# check if URI is reachable
-test_connect()
-{
-    uri=$1
-
-    run_virsh "$uri" connect 2>/dev/null
-    if [ $? -ne 0 ]; then
-        eval_gettext "Can't connect to \$uri. Skipping."
-        echo
-        return 1
-    fi
-}
-
-# list_guests URI PERSISTENT
-# List running guests on URI.
-# PERSISTENT argument options:
-# --persistent: list only persistent guests
-# --transient: list only transient guests
-# [none]: list both persistent and transient guests
-list_guests() {
-    uri=$1
-    persistent=$2
-
-    list=$(run_virsh_c "$uri" list --uuid $persistent)
-    if [ $? -ne 0 ]; then
-        RETVAL=1
-        return 1
-    fi
-
-    echo $list
-}
-
-# guest_name URI UUID
-# return name of guest UUID on URI
-guest_name() {
-    uri=$1
-    uuid=$2
-
-    run_virsh "$uri" domname "$uuid" 2>/dev/null
-}
-
-# guest_is_on URI UUID
-# check if guest UUID on URI is running
-# Result is returned by variable "guest_running"
-guest_is_on() {
-    uri=$1
-    uuid=$2
-
-    guest_running=false
-    id=$(run_virsh "$uri" domid "$uuid")
-    if [ $? -ne 0 ]; then
-        RETVAL=1
-        return 1
-    fi
-
-    [ -n "$id" ] && [ "x$id" != x- ] && guest_running=true
-    return 0
-}
-
-# started
-# Create the startup lock file
-started() {
-    touch "$VAR_SUBSYS_LIBVIRT_GUESTS"
-}
-
-# start
-# Start or resume the guests
-start() {
-    [ -f "$LISTFILE" ] || { started; return 0; }
-
-    if [ "x$ON_BOOT" != xstart ]; then
-        gettext "libvirt-guests is configured not to start any guests on boot"
-        echo
-        rm -f "$LISTFILE"
-        started
-        return 0
-    fi
-
-    isfirst=true
-    bypass=
-    test "x$BYPASS_CACHE" = x0 || bypass=--bypass-cache
-    while read uri list; do
-        configured=false
-        set -f
-        for confuri in $URIS; do
-            set +f
-            if [ "x$confuri" = "x$uri" ]; then
-                configured=true
-                break
-            fi
-        done
-        set +f
-        if ! "$configured"; then
-            eval_gettext "Ignoring guests on \$uri URI"; echo
-            continue
-        fi
-
-        test_connect "$uri" || continue
-
-        eval_gettext "Resuming guests on \$uri URI..."; echo
-        for guest in $list; do
-            name=$(guest_name "$uri" "$guest")
-            eval_gettext "Resuming guest \$name: "
-            if guest_is_on "$uri" "$guest"; then
-                if "$guest_running"; then
-                    gettext "already active"; echo
-                else
-                    if "$isfirst"; then
-                        isfirst=false
-                    else
-                        sleep $START_DELAY
-                    fi
-                    retval run_virsh "$uri" start $bypass "$name" \
-                        >/dev/null && \
-                    gettext "done"; echo
-                fi
-            fi
-        done
-    done <"$LISTFILE"
-
-    rm -f "$LISTFILE"
-    started
-}
-
-# suspend_guest URI GUEST
-# Do a managed save on a GUEST on URI. This function returns after the guest
-# was saved.
-suspend_guest()
-{
-    uri=$1
-    guest=$2
-
-    name=$(guest_name "$uri" "$guest")
-    label=$(eval_gettext "Suspending \$name: ")
-    bypass=
-    slept=0
-    test "x$BYPASS_CACHE" = x0 || bypass=--bypass-cache
-    printf '%s...\n' "$label"
-    run_virsh "$uri" managedsave $bypass "$guest" >/dev/null &
-    virsh_pid=$!
-    while true; do
-        sleep 1
-        kill -0 "$virsh_pid" >/dev/null 2>&1 || break
-
-        slept=$(($slept + 1))
-        if [ $(($slept % 5)) -eq 0 ]; then
-            progress=$(run_virsh_c "$uri" domjobinfo "$guest" 2>/dev/null | \
-                    awk '/^Data processed:/{print $3, $4}')
-            if [ -n "$progress" ]; then
-                printf '%s%s\n' "$label" "$progress"
-            else
-                printf '%s%s\n' "$label" "..."
-            fi
-        fi
-    done
-    retval wait "$virsh_pid" && printf '%s%s\n' "$label" "$(gettext "done")"
-}
-
-# shutdown_guest URI GUEST
-# Start a ACPI shutdown of GUEST on URI. This function return after the quest
-# was successfully shutdown or the timeout defined by $SHUTDOWN_TIMEOUT expires.
-shutdown_guest()
-{
-    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 || return
-    timeout=$SHUTDOWN_TIMEOUT
-    check_timeout=false
-    if [ $timeout -gt 0 ]; then
-        check_timeout=true
-        format=$(eval_gettext "Waiting for guest %s to shut down, %d seconds left\n")
-    else
-        slept=0
-        format=$(eval_gettext "Waiting for guest %s to shut down\n")
-    fi
-    while ! $check_timeout || [ "$timeout" -gt 0 ]; do
-        sleep 1
-        guest_is_on "$uri" "$guest" || return
-        "$guest_running" || break
-
-        if $check_timeout; then
-            if [ $(($timeout % 5)) -eq 0 ]; then
-                printf "$format" "$name" "$timeout"
-            fi
-            timeout=$(($timeout - 1))
-        else
-            slept=$(($slept + 1))
-            if [ $(($slept % 5)) -eq 0 ]; then
-                printf "$format" "$name"
-            fi
-        fi
-    done
-
-    if guest_is_on "$uri" "$guest"; then
-        if "$guest_running"; then
-            eval_gettext "Shutdown of guest \$name failed to complete in time."
-        else
-            eval_gettext "Shutdown of guest \$name complete."
-        fi
-    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=
-    check_timeout=false
-    timeout=$SHUTDOWN_TIMEOUT
-    if [ $timeout -gt 0 ]; then
-        check_timeout=true
-        format=$(eval_gettext "Waiting for %d guests to shut down, %d seconds left\n")
-    else
-        slept=0
-        format=$(eval_gettext "Waiting for %d guests to shut down\n")
-    fi
-    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
-
-        set -- $guests
-        guestcount=$#
-        set -- $on_shutdown
-        shutdowncount=$#
-
-        if $check_timeout; then
-            if [ $(($timeout % 5)) -eq 0 ]; then
-                printf "$format" $(($guestcount + $shutdowncount)) "$timeout"
-            fi
-            timeout=$(($timeout - 1))
-            if [ $timeout -le 0 ]; then
-                eval_gettext "Timeout expired while shutting down domains"; echo
-                RETVAL=1
-                return
-            fi
-        else
-            slept=$(($slept + 1))
-            if [ $(($slept % 5)) -eq 0 ]; then
-                printf "$format" $(($guestcount + $shutdowncount))
-            fi
-        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() {
-    # last stop was not followed by start
-    [ -f "$LISTFILE" ] && return 0
-
-    suspending=true
-    if [ "x$ON_SHUTDOWN" = xshutdown ]; then
-        suspending=false
-        if [ $SHUTDOWN_TIMEOUT -lt 0 ]; then
-            gettext "SHUTDOWN_TIMEOUT must be equal or greater than 0"
-            echo
-            RETVAL=6
-            return
-        fi
-    fi
-
-    : >"$LISTFILE"
-    set -f
-    for uri in $URIS; do
-        set +f
-
-        test_connect "$uri" || continue
-
-        eval_gettext "Running guests on \$uri URI: "
-
-        list=$(list_guests "$uri")
-        if [ $? -eq 0 ]; then
-            empty=true
-            for uuid in $list; do
-                "$empty" || printf ", "
-                printf %s "$(guest_name "$uri" "$uuid")"
-                empty=false
-            done
-
-            if "$empty"; then
-                gettext "no running guests."
-            fi
-            echo
-        fi
-
-        if "$suspending"; then
-            transient=$(list_guests "$uri" "--transient")
-            if [ $? -eq 0 ]; then
-                empty=true
-                for uuid in $transient; do
-                    if "$empty"; then
-                        eval_gettext "Not suspending transient guests on URI: \$uri: "
-                        empty=false
-                    else
-                        printf ", "
-                    fi
-                    printf %s "$(guest_name "$uri" "$uuid")"
-                done
-                echo
-                # reload domain list to contain only persistent guests
-                list=$(list_guests "$uri" "--persistent")
-                if [ $? -ne 0 ]; then
-                    eval_gettext "Failed to list persistent guests on \$uri"
-                    echo
-                    RETVAL=1
-                    set +f
-                    return
-                fi
-            else
-                gettext "Failed to list transient guests"
-                echo
-                RETVAL=1
-                set +f
-                return
-            fi
-        fi
-
-        if [ -n "$list" ]; then
-            echo "$uri" "$list" >>"$LISTFILE"
-        fi
-    done
-    set +f
-
-    if [ -s "$LISTFILE" ]; then
-        while read uri list; do
-            if "$suspending"; then
-                eval_gettext "Suspending guests on \$uri URI..."; echo
-            else
-                eval_gettext "Shutting down guests on \$uri URI..."; echo
-            fi
-
-            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"
-    else
-        rm -f "$LISTFILE"
-    fi
-
-    rm -f "$VAR_SUBSYS_LIBVIRT_GUESTS"
-}
-
-# gueststatus
-# List status of guests
-gueststatus() {
-    set -f
-    for uri in $URIS; do
-        set +f
-        echo "* $uri URI:"
-        retval run_virsh "$uri" list || echo
-    done
-    set +f
-}
-
-# rh_status
-# Display current status: whether saved state exists, and whether start
-# has been executed.  We cannot use status() from the functions library,
-# since there is no external daemon process matching this init script.
-rh_status() {
-    if [ -f "$LISTFILE" ]; then
-        gettext "stopped, with saved guests"; echo
-        RETVAL=3
-    else
-        if [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ]; then
-            gettext "started"; echo
-        else
-            gettext "stopped, with no saved guests"; echo
-        fi
-        RETVAL=0
-    fi
-}
-
-# usage [val]
-# Display usage string, then exit with VAL (defaults to 2).
-usage() {
-    program_name=$0
-    eval_gettext "Usage: \$program_name {start|stop|status|restart|"\
-"condrestart|try-restart|reload|force-reload|gueststatus|shutdown}"; echo
-    exit ${1-2}
-}
-
-# See how we were called.
-if test $# != 1; then
-    usage
-fi
-case "$1" in
-    --help)
-        usage 0
-        ;;
-    start|stop|gueststatus)
-        "$1"
-        ;;
-    restart)
-        stop && start
-        ;;
-    condrestart|try-restart)
-        [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ] && stop && start
-        ;;
-    reload|force-reload)
-        # Nothing to do; we reread configuration on each invocation
-        ;;
-    status)
-        rh_status
-        ;;
-    shutdown)
-        ON_SHUTDOWN=shutdown
-        stop
-        ;;
-    *)
-        usage
-        ;;
-esac
-exit $RETVAL
diff --git a/tools/libvirt-guests.service.in b/tools/libvirt-guests.service.in
index 0f0c41c..d41bf2b 100644
--- a/tools/libvirt-guests.service.in
+++ b/tools/libvirt-guests.service.in
@@ -6,8 +6,8 @@ After=syslog.target network.target
 EnvironmentFile=-/etc/sysconfig/libvirt-guests
 # Hack just call traditional service until we factor
 # out the code
-ExecStart=/etc/init.d/libvirt-guests start
-ExecStop=/etc/init.d/libvirt-guests stop
+ExecStart=@libexecdir@/libvirt-guests.sh start
+ExecStop=@libexecdir@/libvirt-guests.sh stop
 Type=oneshot
 RemainAfterExit=yes
 StandardOutput=journal+console
diff --git a/tools/libvirt-guests.sh.in b/tools/libvirt-guests.sh.in
new file mode 100644
index 0000000..1c9c46b
--- /dev/null
+++ b/tools/libvirt-guests.sh.in
@@ -0,0 +1,573 @@
+#!/bin/sh
+
+sysconfdir="@sysconfdir@"
+localstatedir="@localstatedir@"
+libvirtd="@sbindir@"/libvirtd
+
+# Source function library.
+test ! -r "$sysconfdir"/rc.d/init.d/functions ||
+    . "$sysconfdir"/rc.d/init.d/functions
+
+# Source gettext library.
+# Make sure this file is recognized as having translations: _("dummy")
+. "@bindir@"/gettext.sh
+
+export TEXTDOMAIN="@PACKAGE@" TEXTDOMAINDIR="@localedir@"
+
+URIS=default
+ON_BOOT=start
+ON_SHUTDOWN=suspend
+SHUTDOWN_TIMEOUT=300
+PARALLEL_SHUTDOWN=0
+START_DELAY=0
+BYPASS_CACHE=0
+
+test -f "$sysconfdir"/sysconfig/libvirt-guests &&
+    . "$sysconfdir"/sysconfig/libvirt-guests
+
+LISTFILE="$localstatedir"/lib/libvirt/libvirt-guests
+VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/subsys/libvirt-guests
+
+RETVAL=0
+
+# retval COMMAND ARGUMENTS...
+# run command with arguments and convert non-zero return value to 1 and set
+# the global return variable
+retval() {
+    "$@"
+    if [ $? -ne 0 ]; then
+        RETVAL=1
+        return 1
+    else
+        return 0
+    fi
+}
+
+# run_virsh URI ARGUMENTS...
+# start virsh and let it execute ARGUMENTS on URI
+# If URI is "default" virsh is called without the "-c" argument
+# (using libvirt's default connection)
+run_virsh() {
+    uri=$1
+    shift
+
+    if [ "x$uri" = xdefault ]; then
+        virsh "$@" </dev/null
+    else
+        virsh -c "$uri" "$@" </dev/null
+    fi
+}
+
+# run_virsh_c URI ARGUMENTS
+# Same as "run_virsh" but the "C" locale is used instead of
+# the system's locale.
+run_virsh_c() {
+    ( export LC_ALL=C; run_virsh "$@" )
+}
+
+# test_connect URI
+# check if URI is reachable
+test_connect()
+{
+    uri=$1
+
+    run_virsh "$uri" connect 2>/dev/null
+    if [ $? -ne 0 ]; then
+        eval_gettext "Can't connect to \$uri. Skipping."
+        echo
+        return 1
+    fi
+}
+
+# list_guests URI PERSISTENT
+# List running guests on URI.
+# PERSISTENT argument options:
+# --persistent: list only persistent guests
+# --transient: list only transient guests
+# [none]: list both persistent and transient guests
+list_guests() {
+    uri=$1
+    persistent=$2
+
+    list=$(run_virsh_c "$uri" list --uuid $persistent)
+    if [ $? -ne 0 ]; then
+        RETVAL=1
+        return 1
+    fi
+
+    echo $list
+}
+
+# guest_name URI UUID
+# return name of guest UUID on URI
+guest_name() {
+    uri=$1
+    uuid=$2
+
+    run_virsh "$uri" domname "$uuid" 2>/dev/null
+}
+
+# guest_is_on URI UUID
+# check if guest UUID on URI is running
+# Result is returned by variable "guest_running"
+guest_is_on() {
+    uri=$1
+    uuid=$2
+
+    guest_running=false
+    id=$(run_virsh "$uri" domid "$uuid")
+    if [ $? -ne 0 ]; then
+        RETVAL=1
+        return 1
+    fi
+
+    [ -n "$id" ] && [ "x$id" != x- ] && guest_running=true
+    return 0
+}
+
+# started
+# Create the startup lock file
+started() {
+    touch "$VAR_SUBSYS_LIBVIRT_GUESTS"
+}
+
+# start
+# Start or resume the guests
+start() {
+    [ -f "$LISTFILE" ] || { started; return 0; }
+
+    if [ "x$ON_BOOT" != xstart ]; then
+        gettext "libvirt-guests is configured not to start any guests on boot"
+        echo
+        rm -f "$LISTFILE"
+        started
+        return 0
+    fi
+
+    isfirst=true
+    bypass=
+    test "x$BYPASS_CACHE" = x0 || bypass=--bypass-cache
+    while read uri list; do
+        configured=false
+        set -f
+        for confuri in $URIS; do
+            set +f
+            if [ "x$confuri" = "x$uri" ]; then
+                configured=true
+                break
+            fi
+        done
+        set +f
+        if ! "$configured"; then
+            eval_gettext "Ignoring guests on \$uri URI"; echo
+            continue
+        fi
+
+        test_connect "$uri" || continue
+
+        eval_gettext "Resuming guests on \$uri URI..."; echo
+        for guest in $list; do
+            name=$(guest_name "$uri" "$guest")
+            eval_gettext "Resuming guest \$name: "
+            if guest_is_on "$uri" "$guest"; then
+                if "$guest_running"; then
+                    gettext "already active"; echo
+                else
+                    if "$isfirst"; then
+                        isfirst=false
+                    else
+                        sleep $START_DELAY
+                    fi
+                    retval run_virsh "$uri" start $bypass "$name" \
+                        >/dev/null && \
+                    gettext "done"; echo
+                fi
+            fi
+        done
+    done <"$LISTFILE"
+
+    rm -f "$LISTFILE"
+    started
+}
+
+# suspend_guest URI GUEST
+# Do a managed save on a GUEST on URI. This function returns after the guest
+# was saved.
+suspend_guest()
+{
+    uri=$1
+    guest=$2
+
+    name=$(guest_name "$uri" "$guest")
+    label=$(eval_gettext "Suspending \$name: ")
+    bypass=
+    slept=0
+    test "x$BYPASS_CACHE" = x0 || bypass=--bypass-cache
+    printf '%s...\n' "$label"
+    run_virsh "$uri" managedsave $bypass "$guest" >/dev/null &
+    virsh_pid=$!
+    while true; do
+        sleep 1
+        kill -0 "$virsh_pid" >/dev/null 2>&1 || break
+
+        slept=$(($slept + 1))
+        if [ $(($slept % 5)) -eq 0 ]; then
+            progress=$(run_virsh_c "$uri" domjobinfo "$guest" 2>/dev/null | \
+                    awk '/^Data processed:/{print $3, $4}')
+            if [ -n "$progress" ]; then
+                printf '%s%s\n' "$label" "$progress"
+            else
+                printf '%s%s\n' "$label" "..."
+            fi
+        fi
+    done
+    retval wait "$virsh_pid" && printf '%s%s\n' "$label" "$(gettext "done")"
+}
+
+# shutdown_guest URI GUEST
+# Start a ACPI shutdown of GUEST on URI. This function return after the quest
+# was successfully shutdown or the timeout defined by $SHUTDOWN_TIMEOUT expires.
+shutdown_guest()
+{
+    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 || return
+    timeout=$SHUTDOWN_TIMEOUT
+    check_timeout=false
+    if [ $timeout -gt 0 ]; then
+        check_timeout=true
+        format=$(eval_gettext "Waiting for guest %s to shut down, %d seconds left\n")
+    else
+        slept=0
+        format=$(eval_gettext "Waiting for guest %s to shut down\n")
+    fi
+    while ! $check_timeout || [ "$timeout" -gt 0 ]; do
+        sleep 1
+        guest_is_on "$uri" "$guest" || return
+        "$guest_running" || break
+
+        if $check_timeout; then
+            if [ $(($timeout % 5)) -eq 0 ]; then
+                printf "$format" "$name" "$timeout"
+            fi
+            timeout=$(($timeout - 1))
+        else
+            slept=$(($slept + 1))
+            if [ $(($slept % 5)) -eq 0 ]; then
+                printf "$format" "$name"
+            fi
+        fi
+    done
+
+    if guest_is_on "$uri" "$guest"; then
+        if "$guest_running"; then
+            eval_gettext "Shutdown of guest \$name failed to complete in time."
+        else
+            eval_gettext "Shutdown of guest \$name complete."
+        fi
+    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=
+    check_timeout=false
+    timeout=$SHUTDOWN_TIMEOUT
+    if [ $timeout -gt 0 ]; then
+        check_timeout=true
+        format=$(eval_gettext "Waiting for %d guests to shut down, %d seconds left\n")
+    else
+        slept=0
+        format=$(eval_gettext "Waiting for %d guests to shut down\n")
+    fi
+    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
+
+        set -- $guests
+        guestcount=$#
+        set -- $on_shutdown
+        shutdowncount=$#
+
+        if $check_timeout; then
+            if [ $(($timeout % 5)) -eq 0 ]; then
+                printf "$format" $(($guestcount + $shutdowncount)) "$timeout"
+            fi
+            timeout=$(($timeout - 1))
+            if [ $timeout -le 0 ]; then
+                eval_gettext "Timeout expired while shutting down domains"; echo
+                RETVAL=1
+                return
+            fi
+        else
+            slept=$(($slept + 1))
+            if [ $(($slept % 5)) -eq 0 ]; then
+                printf "$format" $(($guestcount + $shutdowncount))
+            fi
+        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() {
+    # last stop was not followed by start
+    [ -f "$LISTFILE" ] && return 0
+
+    suspending=true
+    if [ "x$ON_SHUTDOWN" = xshutdown ]; then
+        suspending=false
+        if [ $SHUTDOWN_TIMEOUT -lt 0 ]; then
+            gettext "SHUTDOWN_TIMEOUT must be equal or greater than 0"
+            echo
+            RETVAL=6
+            return
+        fi
+    fi
+
+    : >"$LISTFILE"
+    set -f
+    for uri in $URIS; do
+        set +f
+
+        test_connect "$uri" || continue
+
+        eval_gettext "Running guests on \$uri URI: "
+
+        list=$(list_guests "$uri")
+        if [ $? -eq 0 ]; then
+            empty=true
+            for uuid in $list; do
+                "$empty" || printf ", "
+                printf %s "$(guest_name "$uri" "$uuid")"
+                empty=false
+            done
+
+            if "$empty"; then
+                gettext "no running guests."
+            fi
+            echo
+        fi
+
+        if "$suspending"; then
+            transient=$(list_guests "$uri" "--transient")
+            if [ $? -eq 0 ]; then
+                empty=true
+                for uuid in $transient; do
+                    if "$empty"; then
+                        eval_gettext "Not suspending transient guests on URI: \$uri: "
+                        empty=false
+                    else
+                        printf ", "
+                    fi
+                    printf %s "$(guest_name "$uri" "$uuid")"
+                done
+                echo
+                # reload domain list to contain only persistent guests
+                list=$(list_guests "$uri" "--persistent")
+                if [ $? -ne 0 ]; then
+                    eval_gettext "Failed to list persistent guests on \$uri"
+                    echo
+                    RETVAL=1
+                    set +f
+                    return
+                fi
+            else
+                gettext "Failed to list transient guests"
+                echo
+                RETVAL=1
+                set +f
+                return
+            fi
+        fi
+
+        if [ -n "$list" ]; then
+            echo "$uri" "$list" >>"$LISTFILE"
+        fi
+    done
+    set +f
+
+    if [ -s "$LISTFILE" ]; then
+        while read uri list; do
+            if "$suspending"; then
+                eval_gettext "Suspending guests on \$uri URI..."; echo
+            else
+                eval_gettext "Shutting down guests on \$uri URI..."; echo
+            fi
+
+            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"
+    else
+        rm -f "$LISTFILE"
+    fi
+
+    rm -f "$VAR_SUBSYS_LIBVIRT_GUESTS"
+}
+
+# gueststatus
+# List status of guests
+gueststatus() {
+    set -f
+    for uri in $URIS; do
+        set +f
+        echo "* $uri URI:"
+        retval run_virsh "$uri" list || echo
+    done
+    set +f
+}
+
+# rh_status
+# Display current status: whether saved state exists, and whether start
+# has been executed.  We cannot use status() from the functions library,
+# since there is no external daemon process matching this init script.
+rh_status() {
+    if [ -f "$LISTFILE" ]; then
+        gettext "stopped, with saved guests"; echo
+        RETVAL=3
+    else
+        if [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ]; then
+            gettext "started"; echo
+        else
+            gettext "stopped, with no saved guests"; echo
+        fi
+        RETVAL=0
+    fi
+}
+
+# usage [val]
+# Display usage string, then exit with VAL (defaults to 2).
+usage() {
+    program_name=$0
+    eval_gettext "Usage: \$program_name {start|stop|status|restart|"\
+"condrestart|try-restart|reload|force-reload|gueststatus|shutdown}"; echo
+    exit ${1-2}
+}
+
+# See how we were called.
+if test $# != 1; then
+    usage
+fi
+case "$1" in
+    --help)
+        usage 0
+        ;;
+    start|stop|gueststatus)
+        "$1"
+        ;;
+    restart)
+        stop && start
+        ;;
+    condrestart|try-restart)
+        [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ] && stop && start
+        ;;
+    reload|force-reload)
+        # Nothing to do; we reread configuration on each invocation
+        ;;
+    status)
+        rh_status
+        ;;
+    shutdown)
+        ON_SHUTDOWN=shutdown
+        stop
+        ;;
+    *)
+        usage
+        ;;
+esac
+exit $RETVAL
-- 
1.8.0.1




More information about the libvir-list mailing list