On 10/21/2012 04:45 PM, Cole Robinson wrote:
> 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
> ---
>
Ping on this too. I'd like to get this in before cutting 0.10.2 maint release.
Though this has a bit more going on so if anyone thinks it's risky I'm happy
to hold off.
Thanks,
Cole
> v2:
> Break out common functionality, move to /usr/libexec/libvirt-guests.sh
>
> .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 804eda4..1f1b26f 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -177,6 +177,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 ebebfab..d701977 100644
> --- a/libvirt.spec.in
> +++ b/libvirt.spec.in
> @@ -1380,8 +1380,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 \
> @@ -1600,10 +1598,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
> @@ -1865,7 +1866,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 9768528..cbf5bc6 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -190,7 +190,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 0d7822d..281f010 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
> @@ -177,7 +178,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
> @@ -198,7 +199,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' \
> @@ -209,20 +210,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) ||:
>
> @@ -241,6 +248,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
>
--
libvir-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libvir-list