2010-05-14 17:37:55 +04:00
#!/bin/sh
# the following is the LSB init header
#
### BEGIN INIT INFO
# Provides: libvirt-guests
# Required-Start: libvirtd
# Required-Stop: libvirtd
2010-12-05 21:49:39 +03:00
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
2010-05-14 17:37:55 +04:00
# 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
#
2010-09-22 17:46:04 +04:00
# chkconfig: 345 99 01
2010-05-14 17:37:55 +04:00
# description: This is a script for suspending active libvirt guests \
# on shutdown and resuming them on next boot \
# See http://libvirt.org
#
2011-01-04 21:13:56 +03:00
sysconfdir = "@sysconfdir@"
localstatedir = "@localstatedir@"
libvirtd = "@sbindir@" /libvirtd
2010-05-14 17:37:55 +04:00
# Source function library.
2010-12-18 03:26:03 +03:00
test ! -r " $sysconfdir " /rc.d/init.d/functions ||
2011-01-04 21:13:56 +03:00
. " $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@"
2010-05-14 17:37:55 +04:00
URIS = default
ON_BOOT = start
ON_SHUTDOWN = suspend
SHUTDOWN_TIMEOUT = 0
2011-04-15 12:57:06 +04:00
START_DELAY = 0
2011-07-15 03:22:53 +04:00
BYPASS_CACHE = 0
2010-05-14 17:37:55 +04:00
2011-01-04 21:13:56 +03:00
test -f " $sysconfdir " /sysconfig/libvirt-guests &&
. " $sysconfdir " /sysconfig/libvirt-guests
2010-05-14 17:37:55 +04:00
LISTFILE = " $localstatedir " /lib/libvirt/libvirt-guests
2010-05-27 16:47:11 +04:00
VAR_SUBSYS_LIBVIRT_GUESTS = " $localstatedir " /lock/subsys/libvirt-guests
2010-05-14 17:37:55 +04:00
RETVAL = 0
retval( ) {
" $@ "
if [ $? -ne 0 ] ; then
RETVAL = 1
return 1
else
return 0
fi
}
run_virsh( ) {
uri = $1
shift
if [ " x $uri " = xdefault ] ; then
2011-03-09 11:54:57 +03:00
virsh " $@ " </dev/null
2010-05-14 17:37:55 +04:00
else
2011-03-09 11:54:57 +03:00
virsh -c " $uri " " $@ " </dev/null
2010-05-14 17:37:55 +04:00
fi
}
run_virsh_c( ) {
( export LC_ALL = C; run_virsh " $@ " )
}
list_guests( ) {
uri = $1
2011-03-09 11:54:57 +03:00
list = $( run_virsh_c " $uri " list)
2010-05-14 17:37:55 +04:00
if [ $? -ne 0 ] ; then
RETVAL = 1
return 1
fi
uuids =
for id in $( echo " $list " | awk 'NR > 2 {print $1}' ) ; do
2011-03-09 11:54:57 +03:00
uuid = $( run_virsh_c " $uri " dominfo " $id " | awk '/^UUID:/{print $2}' )
2010-05-14 17:37:55 +04:00
if [ -z " $uuid " ] ; then
RETVAL = 1
return 1
fi
uuids = " $uuids $uuid "
done
echo $uuids
}
guest_name( ) {
uri = $1
uuid = $2
2011-03-09 11:54:57 +03:00
name = $( run_virsh_c " $uri " dominfo " $uuid " 2>/dev/null | \
2011-03-01 20:57:01 +03:00
sed -ne 's/^Name: *//p' )
2010-05-14 17:37:55 +04:00
[ -n " $name " ] || name = $uuid
echo " $name "
}
guest_is_on( ) {
uri = $1
uuid = $2
guest_running = false
2011-03-09 11:54:57 +03:00
info = $( run_virsh_c " $uri " dominfo " $uuid " )
2010-05-14 17:37:55 +04:00
if [ $? -ne 0 ] ; then
RETVAL = 1
return 1
fi
id = $( echo " $info " | awk '/^Id:/{print $2}' )
[ -n " $id " ] && [ " x $id " != x- ] && guest_running = true
return 0
}
2010-05-27 16:47:11 +04:00
started( ) {
touch " $VAR_SUBSYS_LIBVIRT_GUESTS "
}
2010-05-14 17:37:55 +04:00
start( ) {
2010-05-27 16:47:11 +04:00
[ -f " $LISTFILE " ] || { started; return 0; }
2010-05-14 17:37:55 +04:00
if [ " x $ON_BOOT " != xstart ] ; then
2011-01-04 21:13:56 +03:00
gettext "libvirt-guests is configured not to start any guests on boot"
echo
2010-05-27 16:47:11 +04:00
rm -f " $LISTFILE "
started
2010-05-14 17:37:55 +04:00
return 0
fi
2011-04-15 12:57:06 +04:00
isfirst = true
2011-07-15 03:22:53 +04:00
bypass =
test " x $BYPASS_CACHE " = x0 || bypass = --bypass-cache
2010-05-14 17:37:55 +04:00
while read uri list; do
configured = false
2011-03-12 00:06:09 +03:00
set -f
2010-05-14 17:37:55 +04:00
for confuri in $URIS ; do
2011-03-12 00:06:09 +03:00
set +f
2011-03-09 11:54:57 +03:00
if [ " x $confuri " = " x $uri " ] ; then
2010-05-14 17:37:55 +04:00
configured = true
break
fi
done
2011-03-12 00:06:09 +03:00
set +f
2011-03-09 11:54:57 +03:00
if ! " $configured " ; then
2011-01-04 21:13:56 +03:00
eval_gettext "Ignoring guests on \$uri URI" ; echo
2010-05-14 17:37:55 +04:00
continue
fi
2011-01-04 21:13:56 +03:00
eval_gettext "Resuming guests on \$uri URI..." ; echo
2010-05-14 17:37:55 +04:00
for guest in $list ; do
2011-03-09 11:54:57 +03:00
name = $( guest_name " $uri " " $guest " )
2011-01-04 21:13:56 +03:00
eval_gettext "Resuming guest \$name: "
2011-03-09 11:54:57 +03:00
if guest_is_on " $uri " " $guest " ; then
if " $guest_running " ; then
2011-01-04 21:13:56 +03:00
gettext "already active" ; echo
2010-05-14 17:37:55 +04:00
else
2011-04-15 12:57:06 +04:00
if " $isfirst " ; then
isfirst = false
else
sleep $START_DELAY
fi
2011-07-15 03:22:53 +04:00
retval run_virsh " $uri " start $bypass " $name " \
>/dev/null && \
2011-01-04 21:13:56 +03:00
gettext "done" ; echo
2010-05-14 17:37:55 +04:00
fi
fi
done
2010-05-27 16:47:11 +04:00
done <" $LISTFILE "
2010-05-14 17:37:55 +04:00
2010-05-27 16:47:11 +04:00
rm -f " $LISTFILE "
started
2010-05-14 17:37:55 +04:00
}
suspend_guest( )
{
uri = $1
guest = $2
2011-03-09 11:54:57 +03:00
name = $( guest_name " $uri " " $guest " )
2011-01-04 21:13:56 +03:00
label = $( eval_gettext "Suspending \$name: " )
2011-07-15 03:22:53 +04:00
bypass =
test " x $BYPASS_CACHE " = x0 || bypass = --bypass-cache
2011-01-04 21:13:56 +03:00
printf %s " $label "
2011-07-15 03:22:53 +04:00
run_virsh " $uri " managedsave $bypass " $guest " >/dev/null &
2010-05-14 17:37:55 +04:00
virsh_pid = $!
while true; do
sleep 1
2011-03-09 11:54:57 +03:00
kill -0 " $virsh_pid " >/dev/null 2>& 1 || break
progress = $( run_virsh_c " $uri " domjobinfo " $guest " 2>/dev/null | \
2010-05-14 17:37:55 +04:00
awk '/^Data processed:/{print $3, $4}' )
if [ -n " $progress " ] ; then
printf '\r%s%12s ' " $label " " $progress "
else
printf '\r%s%-12s ' " $label " "..."
fi
done
2011-03-09 11:54:57 +03:00
retval wait " $virsh_pid " && printf '\r%s%-12s\n' " $label " " $( gettext "done" ) "
2010-05-14 17:37:55 +04:00
}
shutdown_guest( )
{
uri = $1
guest = $2
2011-03-09 11:54:57 +03:00
name = $( guest_name " $uri " " $guest " )
2011-01-04 21:13:56 +03:00
label = $( eval_gettext "Shutting down \$name: " )
printf %s " $label "
2011-03-09 11:54:57 +03:00
retval run_virsh " $uri " shutdown " $guest " >/dev/null || return
2010-05-14 17:37:55 +04:00
timeout = $SHUTDOWN_TIMEOUT
2011-03-09 11:54:57 +03:00
while [ " $timeout " -gt 0 ] ; do
2010-05-14 17:37:55 +04:00
sleep 1
2011-01-04 21:13:56 +03:00
timeout = $(( timeout - 1 ))
2011-03-09 11:54:57 +03:00
guest_is_on " $uri " " $guest " || return
" $guest_running " || break
printf '\r%s%-12d ' " $label " " $timeout "
2010-05-14 17:37:55 +04:00
done
2011-03-09 11:54:57 +03:00
if guest_is_on " $uri " " $guest " ; then
if " $guest_running " ; then
2011-01-04 21:13:56 +03:00
printf '\r%s%-12s\n' " $label " \
" $( gettext "failed to shutdown in time" ) "
2010-05-14 17:37:55 +04:00
else
2011-01-04 21:13:56 +03:00
printf '\r%s%-12s\n' " $label " " $( gettext "done" ) "
2010-05-14 17:37:55 +04:00
fi
fi
}
stop( ) {
# last stop was not followed by start
2010-05-27 16:47:11 +04:00
[ -f " $LISTFILE " ] && return 0
2010-05-14 17:37:55 +04:00
suspending = true
if [ " x $ON_SHUTDOWN " = xshutdown ] ; then
suspending = false
if [ $SHUTDOWN_TIMEOUT -le 0 ] ; then
2011-01-04 21:13:56 +03:00
gettext "Shutdown action requested but SHUTDOWN_TIMEOUT was not set"
echo
2010-05-14 17:37:55 +04:00
RETVAL = 6
return
fi
fi
2010-05-27 16:47:11 +04:00
: >" $LISTFILE "
2011-03-12 00:06:09 +03:00
set -f
2010-05-14 17:37:55 +04:00
for uri in $URIS ; do
2011-03-12 00:06:09 +03:00
set +f
2011-01-04 21:13:56 +03:00
eval_gettext "Running guests on \$uri URI: "
2010-07-27 16:21:51 +04:00
if [ " x $uri " = xdefault ] && [ ! -x " $libvirtd " ] ; then
2011-01-04 21:13:56 +03:00
gettext "libvirtd not installed; skipping this URI." ; echo
2010-07-27 16:21:51 +04:00
continue
fi
2011-03-09 11:54:57 +03:00
list = $( list_guests " $uri " )
2010-05-14 17:37:55 +04:00
if [ $? -eq 0 ] ; then
empty = true
for uuid in $list ; do
2011-03-09 11:54:57 +03:00
" $empty " || printf ", "
printf %s " $( guest_name " $uri " " $uuid " ) "
2010-05-14 17:37:55 +04:00
empty = false
done
2011-03-09 11:54:57 +03:00
if " $empty " ; then
2011-01-04 21:13:56 +03:00
gettext "no running guests." ; echo
2010-05-14 17:37:55 +04:00
else
echo
2011-03-09 11:54:57 +03:00
echo " $uri " " $list " >>" $LISTFILE "
2010-05-14 17:37:55 +04:00
fi
fi
done
2011-03-12 00:06:09 +03:00
set +f
2010-05-14 17:37:55 +04:00
while read uri list; do
2011-03-09 11:54:57 +03:00
if " $suspending " ; then
2011-01-04 21:13:56 +03:00
eval_gettext "Suspending guests on \$uri URI..." ; echo
2010-05-14 17:37:55 +04:00
else
2011-01-04 21:13:56 +03:00
eval_gettext "Shutting down guests on \$uri URI..." ; echo
2010-05-14 17:37:55 +04:00
fi
for guest in $list ; do
2011-03-09 11:54:57 +03:00
if " $suspending " ; then
suspend_guest " $uri " " $guest "
2010-05-14 17:37:55 +04:00
else
2011-03-09 11:54:57 +03:00
shutdown_guest " $uri " " $guest "
2010-05-14 17:37:55 +04:00
fi
done
2010-05-27 16:47:11 +04:00
done <" $LISTFILE "
rm -f " $VAR_SUBSYS_LIBVIRT_GUESTS "
2010-05-14 17:37:55 +04:00
}
gueststatus( ) {
2011-03-12 00:06:09 +03:00
set -f
2010-05-14 17:37:55 +04:00
for uri in $URIS ; do
2011-03-12 00:06:09 +03:00
set +f
2010-05-14 17:37:55 +04:00
echo " * $uri URI: "
2011-03-09 11:54:57 +03:00
retval run_virsh " $uri " list || echo
2010-05-14 17:37:55 +04:00
done
2011-03-12 00:06:09 +03:00
set +f
2010-05-14 17:37:55 +04:00
}
2010-07-27 23:50:35 +04:00
# 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
2011-01-04 21:13:56 +03:00
gettext "stopped, with saved guests" ; echo
2010-07-27 23:50:35 +04:00
RETVAL = 3
else
if [ -f " $VAR_SUBSYS_LIBVIRT_GUESTS " ] ; then
2011-01-04 21:13:56 +03:00
gettext "started" ; echo
2010-07-27 23:50:35 +04:00
else
2011-01-04 21:13:56 +03:00
gettext "stopped, with no saved guests" ; echo
2010-07-27 23:50:35 +04:00
fi
RETVAL = 0
fi
}
2010-07-27 22:05:27 +04:00
# usage [val]
# Display usage string, then exit with VAL (defaults to 2).
usage( ) {
2011-01-04 21:13:56 +03:00
program_name = $0
eval_gettext "Usage: \$program_name {start|stop|status|restart|" \
"condrestart|try-restart|reload|force-reload|gueststatus|shutdown}" ; echo
2010-07-27 22:05:27 +04:00
exit ${ 1 -2 }
}
2010-05-14 17:37:55 +04:00
# See how we were called.
2010-07-27 22:05:27 +04:00
if test $# != 1; then
usage
fi
2010-05-14 17:37:55 +04:00
case " $1 " in
2010-07-27 22:05:27 +04:00
--help)
usage 0
; ;
2010-05-14 17:37:55 +04:00
start| stop| gueststatus)
2011-03-09 11:54:57 +03:00
" $1 "
2010-05-14 17:37:55 +04:00
; ;
restart)
stop && start
; ;
2010-07-27 22:21:31 +04:00
condrestart| try-restart)
[ -f " $VAR_SUBSYS_LIBVIRT_GUESTS " ] && stop && start
; ;
reload| force-reload)
# Nothing to do; we reread configuration on each invocation
2010-05-14 17:37:55 +04:00
; ;
status)
2010-07-27 23:50:35 +04:00
rh_status
2010-05-14 17:37:55 +04:00
; ;
shutdown)
ON_SHUTDOWN = shutdown
stop
; ;
*)
2010-07-27 22:05:27 +04:00
usage
2010-05-14 17:37:55 +04:00
; ;
esac
exit $RETVAL