From 05fd902d03c77ee517795a332310904394ef758b Mon Sep 17 00:00:00 2001 From: Michael Young Date: Mar 08 2012 00:59:26 +0000 Subject: migrate xendomains to systemd, fix an error in an rpm script --- diff --git a/libexec.xendomains b/libexec.xendomains new file mode 100755 index 0000000..d908948 --- /dev/null +++ b/libexec.xendomains @@ -0,0 +1,564 @@ +#!/bin/bash +# +# /etc/init.d/xendomains +# Start / stop domains automatically when domain 0 boots / shuts down. +# +# chkconfig: 345 99 00 +# description: Start / stop Xen domains. +# +# This script offers fairly basic functionality. It should work on Redhat +# but also on LSB-compliant SuSE releases and on Debian with the LSB package +# installed. (LSB is the Linux Standard Base) +# +# Based on the example in the "Designing High Quality Integrated Linux +# Applications HOWTO" by Avi Alkalay +# +# +### BEGIN INIT INFO +# Provides: xendomains +# Required-Start: $syslog $remote_fs xenstored xenconsoled +# Should-Start: xend +# Required-Stop: $syslog $remote_fs xenstored xenconsoled +# Should-Stop: xend +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start/stop secondary xen domains +# Description: Start / stop domains automatically when domain 0 +# boots / shuts down. +### END INIT INFO + +CMD=xl +$CMD list &> /dev/null +if test $? -ne 0 +then + CMD=xm +fi + +$CMD list &> /dev/null +if test $? -ne 0 +then + exit 0; +fi + +# Correct exit code would probably be 5, but it's enough +# if xend complains if we're not running as privileged domain +if ! [ -e /proc/xen/privcmd ]; then + exit 0 +fi + +# See docs/misc/distro_mapping.txt +if [ -d /var/lock/subsys ]; then + LOCKFILE=/var/lock/subsys/xendomains +else + LOCKFILE=/var/lock/xendomains +fi + +if [ -d /etc/sysconfig ]; then + XENDOM_CONFIG=/etc/sysconfig/xendomains +else + XENDOM_CONFIG=/etc/default/xendomains +fi + +test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing"; + if [ "$1" = "stop" ]; then exit 0; + else exit 6; fi; } + +. $XENDOM_CONFIG + +# Use the SUSE rc_ init script functions; +# emulate them on LSB, RH and other systems +if test -e /etc/rc.status; then + # SUSE rc script library + . /etc/rc.status +else + _cmd=$1 + declare -a _SMSG + if test "${_cmd}" = "status"; then + _SMSG=(running dead dead unused unknown) + _RC_UNUSED=3 + else + _SMSG=(done failed failed missed failed skipped unused failed failed) + _RC_UNUSED=6 + fi + if test -e /lib/lsb/init-functions; then + # LSB + . /lib/lsb/init-functions + if alias log_success_msg >/dev/null 2>/dev/null; then + echo_rc() + { + echo " [${_SMSG[${_RC_RV}]}] " + } + else + echo_rc() + { + if test ${_RC_RV} = 0; then + log_success_msg " [${_SMSG[${_RC_RV}]}] " + else + log_failure_msg " [${_SMSG[${_RC_RV}]}] " + fi + } + fi + else + # emulate it + echo_rc() + { + echo " [${_SMSG[${_RC_RV}]}] " + } + fi + rc_reset() { _RC_RV=0; } + rc_failed() + { + if test -z "$1"; then + _RC_RV=1; + elif test "$1" != "0"; then + _RC_RV=$1; + fi + return ${_RC_RV} + } + rc_check() + { + return rc_failed $? + } + rc_status() + { + rc_failed $? + if test "$1" = "-r"; then _RC_RV=0; shift; fi + if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi + if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi + if test "$1" = "-v"; then echo_rc; shift; fi + if test "$1" = "-r"; then _RC_RV=0; shift; fi + return ${_RC_RV} + } + rc_exit() { exit ${_RC_RV}; } + rc_active() + { + if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi + if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi + return 1 + } +fi + +if ! which usleep >&/dev/null +then + usleep() + { + if [ -n "$1" ] + then + sleep $(( $1 / 1000000 )) + fi + } +fi + +# Reset status of this service +rc_reset + +## +# Returns 0 (success) if the given parameter names a directory, and that +# directory is not empty. +# +contains_something() +{ + if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ] + then + return 0 + else + return 1 + fi +} + +# read name from xen config file +rdname() +{ + NM=$($CMD create --quiet --dryrun --defconfig "$1" | + sed -n 's/^.*(name \(.*\))$/\1/p') +} + +rdnames() +{ + NAMES= + if ! contains_something "$XENDOMAINS_AUTO" + then + return + fi + for dom in $XENDOMAINS_AUTO/*; do + rdname $dom + if test -z $NAMES; then + NAMES=$NM; + else + NAMES="$NAMES|$NM" + fi + done +} + +parseln() +{ + if [[ "$1" =~ '(domain' ]]; then + name=;id= + else if [[ "$1" =~ '(name' ]]; then + name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/') + else if [[ "$1" =~ '(domid' ]]; then + id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/') + fi; fi; fi + + [ -n "$name" -a -n "$id" ] && return 0 || return 1 +} + +is_running() +{ + rdname $1 + RC=1 + name=;id= + while read LN; do + parseln "$LN" || continue + if test $id = 0; then continue; fi + case $name in + ($NM) + RC=0 + ;; + esac + done < <($CMD list -l | grep '(\(domain\|domid\|name\)') + return $RC +} + +start() +{ + if [ -f $LOCKFILE ]; then + echo -e "xendomains already running (lockfile exists)" + return; + fi + + saved_domains=" " + if [ "$XENDOMAINS_RESTORE" = "true" ] && + contains_something "$XENDOMAINS_SAVE" + then + mkdir -p $(dirname "$LOCKFILE") + touch $LOCKFILE + echo -n "Restoring Xen domains:" + saved_domains=`ls $XENDOMAINS_SAVE` + for dom in $XENDOMAINS_SAVE/*; do + if [ -f $dom ] ; then + HEADER=`head -c 16 $dom | head -n 1 2> /dev/null` + if [ $HEADER = "LinuxGuestRecord" ]; then + echo -n " ${dom##*/}" + XMR=`$CMD restore $dom 2>&1 1>/dev/null` + #$CMD restore $dom + if [ $? -ne 0 ]; then + echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR" + rc_failed $? + echo -e '!' + else + # mv $dom ${dom%/*}/.${dom##*/} + rm $dom + fi + fi + fi + done + echo -e + fi + + if contains_something "$XENDOMAINS_AUTO" + then + touch $LOCKFILE + echo -n "Starting auto Xen domains:" + # We expect config scripts for auto starting domains to be in + # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere + + # Create all domains with config files in XENDOMAINS_AUTO. + # TODO: We should record which domain name belongs + # so we have the option to selectively shut down / migrate later + # If a domain statefile from $XENDOMAINS_SAVE matches a domain name + # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't + # restore correctly it requires administrative attention. + for dom in $XENDOMAINS_AUTO/*; do + echo -n " ${dom##*/}" + shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p') + echo $saved_domains | grep -w $shortdom > /dev/null + if [ $? -eq 0 ] || is_running $dom; then + echo -n "(skip)" + else + XMC=`$CMD create --quiet --defconfig $dom` + if [ $? -ne 0 ]; then + echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n" + rc_failed $? + echo -e '!' + else + usleep $XENDOMAINS_CREATE_USLEEP + fi + fi + done + fi +} + +all_zombies() +{ + name=;id= + while read LN; do + parseln "$LN" || continue + if test $id = 0; then continue; fi + if test "$state" != "-b---d" -a "$state" != "-----d"; then + return 1; + fi + done < <($CMD list -l | grep '(\(domain\|domid\|name\)') + return 0 +} + +# Wait for max $XENDOMAINS_STOP_MAXWAIT for $CMD $1 to finish; +# if it has not exited by that time kill it, so the init script will +# succeed within a finite amount of time; if $2 is nonnull, it will +# kill the command as well as soon as no domain (except for zombies) +# are left (used for shutdown --all). Third parameter, if any, suppresses +# output of dots per working state (formatting issues) +watchdog_xencmd() +{ + if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then + exit + fi + + usleep 20000 + for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do + # exit if $CMD save/migrate/shutdown is finished + PSAX=`ps axlw | grep "$CMD $1" | grep -v grep` + if test -z "$PSAX"; then exit; fi + if ! test -n "$3"; then echo -n '.'; fi + sleep 1 + # go to kill immediately if there's only zombies left + if all_zombies && test -n "$2"; then break; fi + done + sleep 1 + read PSF PSUID PSPID PSPPID < <(echo "$PSAX") + # kill $CMD $1 + kill $PSPID >/dev/null 2>&1 + + echo -e . +} + +stop() +{ + exec 3>&2 2> /dev/null + + # Collect list of domains to shut down + if test "$XENDOMAINS_AUTO_ONLY" = "true"; then + rdnames + fi + echo -n "Shutting down Xen domains:" + name=;id= + while read LN; do + parseln "$LN" || continue + if test $id = 0; then continue; fi + echo -n " $name" + if test "$XENDOMAINS_AUTO_ONLY" = "true"; then + eval " + case \"\$name\" in + ($NAMES) + # nothing + ;; + (*) + echo -e '(skip)' + continue + ;; + esac + " + fi + # XENDOMAINS_SYSRQ chould be something like just "s" + # or "s e i u" or even "s e s i u o" + # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so + if test -n "$XENDOMAINS_SYSRQ"; then + for sysrq in $XENDOMAINS_SYSRQ; do + echo -n "(SR-$sysrq)" + XMR=`$CMD sysrq $id $sysrq 2>&1 1>/dev/null` + if test $? -ne 0; then + echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n" + rc_failed $? + echo -n '!' + fi + # usleep just ignores empty arg + usleep $XENDOMAINS_USLEEP + done + fi + if test "$state" = "-b---d" -o "$state" = "-----d"; then + echo -n "(zomb)" + continue + fi + if test -n "$XENDOMAINS_MIGRATE"; then + echo -n "(migr)" + watchdog_xencmd migrate & + WDOG_PID=$! + XMR=`$CMD migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null` + if test $? -ne 0; then + echo -e "\nAn error occurred while migrating domain:\n$XMR\n" + rc_failed $? + echo -e '!' + + kill $WDOG_PID >/dev/null 2>&1 + else + kill $WDOG_PID >/dev/null 2>&1 + + echo -e . + usleep 1000 + continue + fi + fi + if test -n "$XENDOMAINS_SAVE"; then + echo -n "(save)" + watchdog_xencmd save & + WDOG_PID=$! + mkdir -p "$XENDOMAINS_SAVE" + XMR=`$CMD save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null` + if test $? -ne 0; then + echo -e "\nAn error occurred while saving domain:\n$XMR\n" + rc_failed $? + echo -e '!' + kill $WDOG_PID >/dev/null 2>&1 + else + kill $WDOG_PID >/dev/null 2>&1 + echo -e . + usleep 1000 + continue + fi + fi + if test -n "$XENDOMAINS_SHUTDOWN"; then + # XENDOMAINS_SHUTDOWN should be "--halt --wait" + echo -n "(shut)" + watchdog_xencmd shutdown & + WDOG_PID=$! + XMR=`$CMD shutdown $id $XENDOMAINS_SHUTDOWN 2>&1 1>/dev/null` + if test $? -ne 0; then + echo -e "\nAn error occurred while shutting down domain:\n$XMR\n" + rc_failed $? + echo -e '!' + fi + kill $WDOG_PID >/dev/null 2>&1 + fi + done < <($CMD list -l | grep '(\(domain\|domid\|name\)') + + # NB. this shuts down ALL Xen domains (politely), not just the ones in + # AUTODIR/* + # This is because it's easier to do ;-) but arguably if this script is run + # on system shutdown then it's also the right thing to do. + if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then + # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait" + echo -n " SHUTDOWN_ALL " + watchdog_xencmd shutdown 1 false & + WDOG_PID=$! + XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null` + if test $? -ne 0; then + echo -e "\nAn error occurred while shutting down all domains: $XMR\n" + rc_failed $? + echo -e '!' + fi + kill $WDOG_PID >/dev/null 2>&1 + fi + + # Unconditionally delete lock file + rm -f $LOCKFILE + + exec 2>&3 +} + +check_domain_up() +{ + name=;id= + while read LN; do + parseln "$LN" || continue + if test $id = 0; then continue; fi + case $name in + ($1) + return 0 + ;; + esac + done < <($CMD list -l | grep '(\(domain\|domid\|name\)') + return 1 +} + +check_all_auto_domains_up() +{ + if ! contains_something "$XENDOMAINS_AUTO" + then + return 0 + fi + missing= + for nm in $XENDOMAINS_AUTO/*; do + rdname $nm + found=0 + if check_domain_up "$NM"; then + echo -n " $name" + else + missing="$missing $NM" + fi + done + if test -n "$missing"; then + echo -n " MISS AUTO:$missing" + return 1 + fi + return 0 +} + +check_all_saved_domains_up() +{ + if ! contains_something "$XENDOMAINS_SAVE" + then + return 0 + fi + missing=`/bin/ls $XENDOMAINS_SAVE` + echo -n " MISS SAVED: " $missing + return 1 +} + +# This does NOT necessarily restart all running domains: instead it +# stops all running domains and then boots all the domains specified in +# AUTODIR. If other domains have been started manually then they will +# not get restarted. +# Commented out to avoid confusion! + +restart() +{ + stop + start +} + +reload() +{ + restart +} + + +case "$1" in + start) + start + rc_status + if test -f $LOCKFILE; then rc_status -v; fi + ;; + + stop) + stop + rc_status -v + ;; + + restart) + restart + ;; + reload) + reload + ;; + + status) + echo -n "Checking for xendomains:" + if test ! -f $LOCKFILE; then + rc_failed 3 + else + check_all_auto_domains_up + rc_status + check_all_saved_domains_up + rc_status + fi + rc_status -v + ;; + + *) + echo "Usage: $0 {start|stop|restart|reload|status}" + rc_failed 3 + rc_status -v + ;; +esac + +rc_exit diff --git a/xen.spec b/xen.spec index 3ddb5ff..b613ce4 100644 --- a/xen.spec +++ b/xen.spec @@ -20,7 +20,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.1.2 -Release: 11%{?dist} +Release: 12%{?dist} Group: Development/Libraries License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ @@ -51,6 +51,8 @@ Source43: blktapctrl.service Source44: xend.service Source45: xenconsoled.service Source46: xen-watchdog.service +Source47: xendomains.service +Source48: libexec.xendomains Patch1: xen-initscript.patch Patch4: xen-dumpdir.patch @@ -357,6 +359,9 @@ install -m 644 %{SOURCE43} %{buildroot}%{_unitdir}/blktapctrl.service install -m 644 %{SOURCE44} %{buildroot}%{_unitdir}/xend.service install -m 644 %{SOURCE45} %{buildroot}%{_unitdir}/xenconsoled.service install -m 644 %{SOURCE46} %{buildroot}%{_unitdir}/xen-watchdog.service +install -m 644 %{SOURCE47} %{buildroot}%{_unitdir}/xendomains.service +mkdir -p %{buildroot}%{_libexecdir} +install -m 644 %{SOURCE48} %{buildroot}%{_libexecdir}/xendomains %endif # config file only used for hotplug, Fedora uses udev instead @@ -397,8 +402,11 @@ done %post %if %with_sysv /sbin/chkconfig --add xend -%endif /sbin/chkconfig --add xendomains +%endif +%if %with_systemd +/bin/systemctl enable xendomains.service +%endif %if %with_sysv if [ $1 != 0 ]; then @@ -410,8 +418,11 @@ fi if [ $1 = 0 ]; then %if %with_sysv /sbin/chkconfig --del xend -%endif /sbin/chkconfig --del xendomains +%endif +%if %with_systemd +/bin/systemctl enable xendomains.service +%endif fi %post runtime @@ -431,8 +442,8 @@ fi %endif %preun runtime -%if %with_sysv if [ $1 = 0 ]; then +%if %with_sysv /sbin/chkconfig --del xenconsoled /sbin/chkconfig --del xenstored /sbin/chkconfig --del blktapctrl @@ -476,8 +487,8 @@ rm -rf %{buildroot} # Startup script %if %with_sysv %{_sysconfdir}/rc.d/init.d/xend -%endif %{_sysconfdir}/rc.d/init.d/xendomains +%endif # Guest config files %config(noreplace) %{_sysconfdir}/%{name}/xmexample* # Daemon config @@ -491,6 +502,8 @@ rm -rf %{buildroot} %if %with_systemd %{_unitdir}/xend.service +%{_unitdir}/xendomains.service +%{_libexecdir}/xendomains %endif # Persistent state for XenD @@ -683,6 +696,10 @@ rm -rf %{buildroot} %endif %changelog +* Thu Mar 08 2012 Michael Young - 4.1.2-12 +- fix an error in an rpm script from the sysv configuration removal +- migrate xendomains script to systemd + * Wed Feb 29 2012 Michael Young - 4.1.2-11 - put the systemd files back in the right place diff --git a/xendomains.service b/xendomains.service new file mode 100644 index 0000000..d0d0e6c --- /dev/null +++ b/xendomains.service @@ -0,0 +1,14 @@ +[Unit] +Description=Xendomains - start and stop guests on boot and shutdown +Requires=proc-xen.mount xenstored.service +After=proc-xen.mount xenstored.service xenconsoled.service + +[Service] +Type=oneshot +RemainAfterExit=true +ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities +ExecStart=/usr/libexec/xendomains start +ExecStop=/usr/libexec/xendomains stop + +[Install] +WantedBy=multi-user.target