From e9dbc55173098ecca52e6100d985964c3d0e0b0c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jan=20R=C4=99korajski?= Date: Mon, 22 Jul 2013 18:13:50 +0200 Subject: [PATCH] - fix building documentation with latest perl and texinfo - replace our xendomains script with one from debian (much cleaner and simpler) - added xendomains systemd service - package all files under /usr/lib/xen/bin on all archs --- xen-doc.patch | 114 ++++++++++ xen-init-list | 77 +++++++ xen-toolstack | 33 +++ xen.spec | 22 +- xendomains.init | 552 +++++++++++++++++---------------------------- xendomains.service | 16 ++ xendomains.sh | 220 ++++++++++++++++++ 7 files changed, 677 insertions(+), 357 deletions(-) create mode 100644 xen-doc.patch create mode 100755 xen-init-list create mode 100755 xen-toolstack mode change 100644 => 100755 xendomains.init create mode 100644 xendomains.service create mode 100755 xendomains.sh diff --git a/xen-doc.patch b/xen-doc.patch new file mode 100644 index 0000000..1f185b0 --- /dev/null +++ b/xen-doc.patch @@ -0,0 +1,114 @@ +diff -ur xen-4.2.2/docs/man/xl.cfg.pod.5 xen-4.2.2.doc/docs/man/xl.cfg.pod.5 +--- xen-4.2.2/docs/man/xl.cfg.pod.5 2013-04-23 18:42:55.000000000 +0200 ++++ xen-4.2.2.doc/docs/man/xl.cfg.pod.5 2013-07-22 13:43:13.044717979 +0200 +@@ -402,10 +402,10 @@ + + =back + +-=item B +- + =over 4 + ++=item B ++ + Allow guest to access specific legacy I/O ports. Each B + is given in hexadecimal and may either a span e.g. C<2f8-2ff> + (inclusive) or a single I/O port C<2f8>. +@@ -415,10 +415,10 @@ + + =back + +-=item B +- + =over 4 + ++=item B ++ + Allow a guest to access specific physical IRQs. + + It is recommended to use this option only for trusted VMs under +@@ -680,8 +680,6 @@ + + =back + +-=back +- + Please see F for more information on this option. + + =item B +@@ -692,6 +690,8 @@ + + Set the real time clock offset in seconds. 0 by default. + ++=back ++ + =head3 Support for Paravirtualisation of HVM Guests + + The following options allow Paravirtualised features (such as devices) +diff -ur xen-4.2.2/docs/man/xl.pod.1 xen-4.2.2.doc/docs/man/xl.pod.1 +--- xen-4.2.2/docs/man/xl.pod.1 2013-04-23 18:42:55.000000000 +0200 ++++ xen-4.2.2.doc/docs/man/xl.pod.1 2013-07-22 13:41:46.400526793 +0200 +@@ -851,8 +851,6 @@ + + =item B<-p [pool] -d>... : Illegal + +-=item +- + =back + + =item B [I] +--- xen-4.2.2/tools/qemu-xen/qemu-options.hx~ 2013-04-06 01:39:54.000000000 +0200 ++++ xen-4.2.2/tools/qemu-xen/qemu-options.hx 2013-07-22 14:17:13.970296816 +0200 +@@ -1799,7 +1799,7 @@ + devices. + + Syntax for specifying a sheepdog device +-@table @list ++@table @code + ``sheepdog:'' + + ``sheepdog::'' +--- xen-4.2.2/tools/qemu-xen/scripts/texi2pod.pl~ 2013-04-06 01:39:54.000000000 +0200 ++++ xen-4.2.2/tools/qemu-xen/scripts/texi2pod.pl 2013-07-22 14:27:37.959914694 +0200 +@@ -339,6 +339,8 @@ + $sects{NAME} = "$fn \- $tl\n"; + $sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES}; + ++print "=encoding utf8\n"; ++ + for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES + BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) { + if(exists $sects{$sect}) { +--- xen-4.2.2/tools/qemu-xen-traditional/texi2pod.pl~ 2013-04-06 01:39:54.000000000 +0200 ++++ xen-4.2.2/tools/qemu-xen-traditional/texi2pod.pl 2013-07-22 14:27:37.959914694 +0200 +@@ -339,6 +339,8 @@ + $sects{NAME} = "$fn \- $tl\n"; + $sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES}; + ++print "=encoding utf8\n"; ++ + for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES + BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) { + if(exists $sects{$sect}) { +--- xen-4.2.2/tools/qemu-xen-traditional/configure~ 2013-07-22 14:35:56.118261587 +0200 ++++ xen-4.2.2/tools/qemu-xen-traditional/configure 2013-07-22 14:43:48.376345178 +0200 +@@ -1087,7 +1087,7 @@ + fi + + # Check if tools are available to build documentation. +-if [ -x "`which texi2html 2>/dev/null`" ] && \ ++if [ -x "`which texi2any 2>/dev/null`" ] && \ + [ -x "`which pod2man 2>/dev/null`" ]; then + build_docs="yes" + fi +--- xen-4.2.2/tools/qemu-xen-traditional/Makefile~ 2013-01-17 17:00:26.000000000 +0100 ++++ xen-4.2.2/tools/qemu-xen-traditional/Makefile 2013-07-22 14:44:29.273423099 +0200 +@@ -275,7 +275,7 @@ + + # documentation + %.html: %.texi +- texi2html -monolithic -number $< ++ texi2any --html --no-split --number-sections $< + + %.info: %.texi + makeinfo $< -o $@ diff --git a/xen-init-list b/xen-init-list new file mode 100755 index 0000000..66b6256 --- /dev/null +++ b/xen-init-list @@ -0,0 +1,77 @@ +#!/usr/bin/python + +from __future__ import print_function + +import json +import re +import sys +import subprocess + + +class SXPParser(object): + tokenizer_rules = r""" (?P \( ) | (?P \) ) | (?P \s+ ) | [^()^\s]+ """ + tokenizer_re = re.compile(tokenizer_rules, re.X) + + def __init__(self): + self.stack = [] + self.data = [] + + def __call__(self, input): + for match in self.tokenizer_re.finditer(input): + if match.group('open'): + self.stack.append([]) + elif match.group('close'): + top = self.stack.pop() + if self.stack: + self.stack[-1].append(top) + else: + self.data.append(top) + elif match.group('whitespace'): + pass + else: + if self.stack: + self.stack[-1].append(match.group()) + return self.data + + +class Data(object): + def __call__(self, out): + for domid, info in sorted(self.data.iteritems(), reverse=True): + print(str(domid), *info) + + +class DataJSON(Data): + def __init__(self, p): + s = json.loads(p) + self.data = d = {} + for i in s: + domid = i['domid'] + name = i['config']['c_info']['name'] + d[domid] = (name, ) + + +class DataSXP(Data): + def __init__(self, p): + s = SXPParser()(p) + self.data = d = {} + for i in s: + if i and i[0] == 'domain': + try: + data = dict(j for j in i if len(j) == 2) + domid = int(data['domid']) + name = data['name'] + if domid == 0: + continue + d[domid] = (name, ) + except (KeyError, ValueError) as e: + pass + + +if __name__ == '__main__': + p = subprocess.check_output(('/usr/lib/xen/bin/xen-toolstack', 'list', '-l')) + if p[0] == '(': + d = DataSXP(p) + else: + d = DataJSON(p) + d(sys.stdout) + diff --git a/xen-toolstack b/xen-toolstack new file mode 100755 index 0000000..261f069 --- /dev/null +++ b/xen-toolstack @@ -0,0 +1,33 @@ +#!/bin/sh -e + +if [ -r /etc/sysconfig/xen ]; then + . /etc/sysconfig/xen +fi + +if [ -n "$TOOLSTACK" ]; then + cmd=$(command -v "$TOOLSTACK" || :) + if [ -z "$cmd" ]; then + echo "WARING: Can't find toolstack $TOOLSTACK, fallback to default!" >&2 + TOOLSTACK= + fi +fi + +if [ -z "$TOOLSTACK" ]; then + cmd_xl=$(command -v xl || :) + cmd_xm=$(command -v xm || :) + if [ -n "$cmd_xl" ]; then + cmd="$cmd_xl" + elif [ -n "$cmd_xm" ]; then + cmd="$cmd_xm" + else + echo "ERROR: Toolstack not specifed and nothing detected, bailing out!" >&2 + exit 127 + fi +fi + +if [ "$1" == "toolstack" ]; then + echo $cmd + exit 0 +fi + +exec "$cmd" "$@" diff --git a/xen.spec b/xen.spec index c120a63..02105d2 100644 --- a/xen.spec +++ b/xen.spec @@ -65,6 +65,8 @@ Source39: xend.service Source40: xend.tmpfiles Source41: xen-watchdog.service Source42: xen-dom0-modules-load.conf +Source43: xendomains.sh +Source44: xendomains.service # sysvinit scripts Source50: xend.init Source51: xenconsoled.init @@ -76,6 +78,8 @@ Source56: xen.tmpfiles Source57: xen.cfg Source58: xen.efi-boot-update Source59: vif-openvswitch +Source60: xen-init-list +Source61: xen-toolstack Patch0: %{name}-python_scripts.patch Patch1: %{name}-symbols.patch Patch2: %{name}-curses.patch @@ -93,6 +97,7 @@ Patch12: %{name}-scripts-locking.patch Patch13: %{name}-close_lockfd_after_lock_attempt.patch Patch14: %{name}-librt.patch Patch15: %{name}-ulong.patch +Patch16: %{name}-doc.patch URL: http://www.xen.org/products/xenhyp.html %{?with_opengl:BuildRequires: OpenGL-devel} %{?with_sdl:BuildRequires: SDL-devel >= 1.2.1} @@ -381,6 +386,7 @@ Nadzorca Xen w postaci, która może być uruchomiona wprost z firmware %patch13 -p1 %patch14 -p1 %patch15 -p1 +%patch16 -p1 # stubdom sources ln -s %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} stubdom @@ -455,6 +461,8 @@ install %{SOURCE39} $RPM_BUILD_ROOT%{systemdunitdir}/xend.service install %{SOURCE40} $RPM_BUILD_ROOT%{systemdtmpfilesdir}/xend.conf install %{SOURCE41} $RPM_BUILD_ROOT%{systemdunitdir}/xen-watchdog.service install %{SOURCE42} $RPM_BUILD_ROOT/etc/modules-load.d/xen-dom0.conf +install %{SOURCE43} $RPM_BUILD_ROOT%{_prefix}/lib/%{name}/bin/xendomains.sh +install %{SOURCE44} $RPM_BUILD_ROOT%{systemdunitdir}/xendomains.service # sysvinit scripts %{__rm} $RPM_BUILD_ROOT/etc/rc.d/init.d/* install %{SOURCE50} $RPM_BUILD_ROOT/etc/rc.d/init.d/xend @@ -465,6 +473,9 @@ install %{SOURCE54} $RPM_BUILD_ROOT/etc/rc.d/init.d/xendomains install %{SOURCE55} $RPM_BUILD_ROOT/etc/logrotate.d/xen install %{SOURCE56} $RPM_BUILD_ROOT%{systemdtmpfilesdir}/xen.conf +install %{SOURCE60} $RPM_BUILD_ROOT%{_prefix}/lib/%{name}/bin/xen-init-list +install %{SOURCE61} $RPM_BUILD_ROOT%{_prefix}/lib/%{name}/bin/xen-toolstack + %if %{with efi} install %{SOURCE57} $RPM_BUILD_ROOT/etc/efi-boot/xen.cfg sed -e's;@libdir@;%{_libdir};g' -e's;@target_cpu@;%{_target_cpu};g' \ @@ -508,7 +519,7 @@ rm -rf $RPM_BUILD_ROOT /sbin/chkconfig --add xenconsoled /sbin/chkconfig --add xenstored /sbin/chkconfig --add xendomains -%systemd_post xen-watchdog.service xenconsoled.service xenstored.service +%systemd_post xen-watchdog.service xenconsoled.service xenstored.service xendomains.service %preun if [ "$1" = "0" ]; then @@ -524,7 +535,7 @@ if [ "$1" = "0" ]; then %service xen-watchdog stop /sbin/chkconfig --del xen-watchdog fi -%systemd_preun xen-watchdog.service xenconsoled.service xenstored.service +%systemd_preun xen-watchdog.service xenconsoled.service xenstored.service xendomains.service %postun %systemd_reload @@ -554,7 +565,7 @@ fi %files %defattr(644,root,root,755) -%doc COPYING README* docs/misc/* +%doc COPYING README* docs/misc/* %doc docs/html/* %doc tools/qemu-xen-dir/*.html %doc _doc/* @@ -576,6 +587,7 @@ fi %{systemdunitdir}/xen-watchdog.service %{systemdunitdir}/xenconsoled.service %{systemdunitdir}/xenstored.service +%{systemdunitdir}/xendomains.service %dir %{_sysconfdir}/xen %dir %{_sysconfdir}/xen/auto %dir %{_sysconfdir}/xen/examples @@ -625,9 +637,7 @@ fi %if "%{_lib}" != "lib" %dir %{_prefix}/lib/%{name} %dir %{_prefix}/lib/%{name}/bin -%attr(755,root,root) %{_prefix}/lib/%{name}/bin/qemu-dm -%attr(755,root,root) %{_prefix}/lib/%{name}/bin/stubdom-dm -%attr(755,root,root) %{_prefix}/lib/%{name}/bin/stubdompath.sh +%attr(755,root,root) %{_prefix}/lib/%{name}/bin/* %endif %dir %{_prefix}/lib/%{name}/boot %{_prefix}/lib/%{name}/boot/ioemu-stubdom.gz diff --git a/xendomains.init b/xendomains.init old mode 100644 new mode 100755 index 494e013..7981b2f --- a/xendomains.init +++ b/xendomains.init @@ -1,398 +1,248 @@ -#!/bin/sh +#!/bin/bash # -# xendomains Start / stop domains automatically when domain 0 boots / shuts down. +# 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 -# +# chkconfig: 345 99 00 +# description: Start / stop Xen domains. # . /etc/rc.d/init.d/functions -CMD=xm -$CMD list >/dev/null 2>/dev/null || CMD=xl -$CMD list >/dev/null 2>/dev/null || exit 0 +if ! [ -e /proc/xen/privcmd ]; then + exit 0 +fi -[ -e /proc/xen/privcmd ] || exit 0 +TOOLSTACK=$(/usr/lib/xen/bin/xen-toolstack toolstack 2>/dev/null) +if [ $? -ne 0 ]; then + echo "No usable Xen toolstack selected" + exit 0 +fi +if [ "$(basename "$TOOLSTACK")" != xl ] && [ "$(basename "$TOOLSTACK")" != xm ]; then + exit 0 +fi -if [ -r /etc/sysconfig/xendomains ]; then - . /etc/sysconfig/xendomains -else - echo "/etc/sysconfig/xendomains does not exist" - if [ "$1" = "stop" ]; then - exit 0 - else - exit 6 - fi +if ! /usr/lib/xen/bin/xen-toolstack list >/dev/null 2>&1 ; then + exit 0; fi -## -# 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 +[ -r /etc/sysconfig/xendomains ] && . /etc/sysconfig/xendomains + +shopt -s nullglob + +check_config_name() +{ + /usr/lib/xen/bin/xen-toolstack create --quiet --dryrun --defconfig "$1" | sed -n 's/^.*\("name":"\([^"]*\)",.*\)\|(name \(.*\))$/\2\3/p' } -# read name from xen config file -rdname() { - NM=$($CMD create --quiet --dryrun --defconfig "$1" 2>&1 | sed -n 's/^.*\(name \(.*\)\)\|\("name": "\([^"]*\)",\?\)$/\2\4/p') - NM=$(echo $NM) +check_running() +{ + /usr/lib/xen/bin/xen-toolstack domid "$1" >/dev/null 2>&1 + return $? } -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; +timeout_coproc() +{ + local TIMEOUT=$1 + shift + + coproc "$@" >/dev/null 2>&1 + + local COPROC_OUT + exec {COPROC_OUT}<&"${COPROC[0]}" + local PID="$COPROC_PID" + + for no in $(seq 0 $TIMEOUT); do + if [ -z "$COPROC_PID" ]; then break; fi + sleep 1 + done + + kill -INT "$COPROC_PID" >/dev/null 2>&1 + wait $PID + local rc=$? + if [ $rc -eq 0 ]; then + ok else - NAMES="$NAMES|$NM" + fail fi - done + + [ $rc -gt 0 ] && cat <&$COPROC_OUT + exec <&$COPROC_OUT- } -parseln() { - if [[ "$1" = *"(domain"* ]]; then - name=;id= - elif [[ "$1" = *"\"domid\"":* ]]; then - name= - id=$(echo $1 | sed -s 's/^.*: \([0-9]*\),$/\1/') - elif [[ "$1" = *"\"name\":"* ]]; then - name=$(echo $1 | sed -s 's/^.*: "\([^"]*\)",$/\1/') - elif [[ "$1" = *"(name"* ]]; then - name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/') - elif [[ "$1" = *"(domid"* ]]; then - id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/') - fi - [ -n "$name" -a -n "$id" ] && return 0 || return 1 +timeout_domain() +{ + name="$1" + TIMEOUT="$2" + for no in $(seq 0 $TIMEOUT); do + if ! check_running "$name"; then return 0; fi + sleep 1 + done + return 1 } -is_running() { - rdname $1 - name=;id= - $CMD list -l | grep '[("]\(domain\|domid\|name\)' | \ - while read LN; do - parseln "$LN" || continue - [ $id = 0 ] && continue - case $name in - ($NM) - return 0 - ;; - esac - done - return 1 +do_start_restore() +{ + [ -n "$XENDOMAINS_SAVE" ] || return + [ -d "$XENDOMAINS_SAVE" ] || return + [ -n "$XENDOMAINS_RESTORE" ] || return + + for file in $XENDOMAINS_SAVE/*; do + if [ -f $file ] ; then + name="${file##*/}" + show "Restoring Xen domain $name (from $file)" + busy + + out=$(/usr/lib/xen/bin/xen-toolstack restore "$file" >/dev/null 2>&1) + case "$?" in + 0) + rm "$file" + domains[$name]='started' + ok + ;; + *) + domains[$name]='failed' + fail + echo "$out" + ;; + esac + fi + done } -start() { - if [ -f /var/lock/subsys/xendomains ]; then - echo -e "xendomains already running (lockfile exists)" - return - fi +do_start_auto() +{ + [ -n "$XENDOMAINS_AUTO" ] || return + [ -d "$XENDOMAINS_AUTO" ] || return - saved_domains=" " - if [ "$XENDOMAINS_RESTORE" = "true" ] && contains_something "$XENDOMAINS_SAVE"; then - mkdir -p $(dirname "/var/lock/subsys/xendomains") - touch /var/lock/subsys/xendomains - 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" - echo -e '!' - else - # mv $dom ${dom%/*}/.${dom##*/} - rm $dom - fi - fi - fi - done - echo -e - fi - - if contains_something "$XENDOMAINS_AUTO" ; then - touch /var/lock/subsys/xendomains - 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" - echo -e '!' + for file in $XENDOMAINS_AUTO/*; do + name="$(check_config_name $file)" + + if [ "${domains[$name]}" = started ]; then + : + elif check_running "$name"; then + echo "Xen domain $name already running" else - usleep $XENDOMAINS_CREATE_USLEEP + show "Starting Xen domain $name (from $file)" + busy + + if [ "${domains[$name]}" = failed ]; then + fail + else + out=$(/usr/lib/xen/bin/xen-toolstack create --quiet --defconfig "$file" >/dev/null 2>&1) + case "$?" in + 0) + ok + ;; + *) + fail + echo "$out" + ;; + esac + fi fi - fi done - fi } -all_zombies() { - name=;id= - $CMD list -l | grep '[("]\(domain\|domid\|name\)' | \ - 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; +do_start() +{ + declare -A domains + + if [ -f /var/lock/subsys/xendomains ]; then + msg_already_running "xendomains" + return fi - done - 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 - PSPID=$($PSAX | awk '{ print $3 }') - # kill $CMD $1 - kill $PSPID >/dev/null 2>&1 - - echo -e . + do_start_restore + do_start_auto + + touch /var/lock/subsys/xendomains } -stop() { - # Collect list of domains to shut down - if test "$XENDOMAINS_AUTO_ONLY" = "true"; then - rdnames - fi - echo -n "Shutting down Xen domains:" - name=;id= - $CMD list -l | grep '[("]\(domain\|domid\|name\)' | \ - 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" - 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" - 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" - 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" - echo -e '!' - fi - kill $WDOG_PID >/dev/null 2>&1 - fi - done - - # 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" - echo -e '!' - fi - kill $WDOG_PID >/dev/null 2>&1 - fi +do_stop_migrate() +{ + [ -n "$XENDOMAINS_MIGRATE" ] || return - # Unconditionally delete lock file - rm -f /var/lock/subsys/xendomains + while read id name rest; do + show "Migrating Xen domain $name ($id)" + busy + (timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" /usr/lib/xen/bin/xen-toolstack migrate $id $XENDOMAINS_MIGRATE) + done < <(/usr/lib/xen/bin/xen-init-list) } -check_domain_up() +do_stop_save() { - local result - result=1 - name=;id= - $CMD list -l | grep '[("]\(domain\|domid\|name\)' | \ - while read LN; do - parseln "$LN" || continue - if test $id = 0; then continue; fi - if [ "$name" = "$1" ] ; then - echo 1 - break - fi - done + [ -n "$XENDOMAINS_SAVE" ] || return + [ -d "$XENDOMAINS_SAVE" ] || mkdir -m 0700 -p "$XENDOMAINS_SAVE" + + while read id name rest; do + show "Saving Xen domain $name ($id)" + busy + (timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" /usr/lib/xen/bin/xen-toolstack save $id $XENDOMAINS_SAVE/$name) + done < <(/usr/lib/xen/bin/xen-init-list) } -check_all_auto_domains_up() +do_stop_shutdown() { - if ! contains_something "$XENDOMAINS_AUTO"; then - return 0 - fi - missing= - for nm in $XENDOMAINS_AUTO/*; do - rdname $nm - found=0 - if [ -n "$(check_domain_up "$NM")" ] ; then - echo -n " $NM" - else - missing="$missing $NM" - fi - done - if test -n "$missing"; then - echo -n " MISS AUTO:$missing" - return 1 - fi - return 0 + while read id name rest; do + show "Shutting down Xen domain $name ($id)" + busy + /usr/lib/xen/bin/xen-toolstack shutdown $id >/dev/null 2>&1 + if [ $? -eq 0 ]; then + ok + else + fail + fi + done < <(/usr/lib/xen/bin/xen-init-list) + while read id name rest; do + show "Waiting for Xen domain $name ($id) to shut down" + busy + timeout_domain "$name" "$XENDOMAINS_STOP_MAXWAIT" + if [ $? -eq 0 ]; then + ok + else + fail + fi + done < <(/usr/lib/xen/bin/xen-init-list) } -check_all_saved_domains_up() +do_stop() { - if ! contains_something "$XENDOMAINS_SAVE"; then - return 0 - fi - missing=`/bin/ls $XENDOMAINS_SAVE` - echo -n " MISS SAVED: " $missing - return 1 + if [ ! -f /var/lock/subsys/xendomains ]; then + msg_not_running "xendomains" + return + fi + + do_stop_migrate + do_stop_save + do_stop_shutdown + + rm -f /var/lock/subsys/xendomains } -RETVAL=0 -# See how we were called. case "$1" in - start) - start - ;; - stop) - stop - ;; - restart|reload) -# 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. - stop - start - ;; - status) - if [ -f /var/lock/subsys/xendomains ]; then - echo -n "Checking for xendomains:" - check_all_auto_domains_up - check_all_saved_domains_up - echo - fi - ;; - *) - msg_usage "$0 {start|stop|restart|reload|status}" - ;; + start) + do_start + ;; + stop) + do_stop + ;; + restart) + do_stop + do_start + ;; + reload|force-reload) + do_stop + do_start + ;; + status) + if [ -f /var/lock/subsys/xendomains ]; then + /usr/lib/xen/bin/xen-toolstack list -v + fi + ;; + *) + echo "Usage: $0 {start|stop|status|restart|reload|force-reload}" + exit 3 + ;; esac -exit $RETVAL +exit 0 diff --git a/xendomains.service b/xendomains.service new file mode 100644 index 0000000..f0f4d9f --- /dev/null +++ b/xendomains.service @@ -0,0 +1,16 @@ +[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 +ConditionPathExists=/proc/xen + +[Service] +Type=oneshot +RemainAfterExit=true +ExecStartPre=/bin/grep -q control_d /proc/xen/capabilities +ExecStart=-/usr/lib/xen/bin/xendomains.sh start +ExecStop=/usr/lib/xen/bin/xendomains.sh stop +ExecReload=/usr/lib/xen/bin/xendomains.sh restart + +[Install] +WantedBy=multi-user.target diff --git a/xendomains.sh b/xendomains.sh new file mode 100755 index 0000000..7f451f4 --- /dev/null +++ b/xendomains.sh @@ -0,0 +1,220 @@ +#!/bin/bash + +if ! [ -e /proc/xen/privcmd ]; then + exit 0 +fi + +TOOLSTACK=$(/usr/lib/xen/bin/xen-toolstack toolstack 2>/dev/null) +if [ $? -ne 0 ]; then + echo "No usable Xen toolstack selected" + exit 0 +fi +if [ "$(basename "$TOOLSTACK")" != xl ] && [ "$(basename "$TOOLSTACK")" != xm ]; then + exit 0 +fi + +if ! /usr/lib/xen/bin/xen-toolstack list >/dev/null 2>&1 ; then + exit 0; +fi + +[ -r /etc/sysconfig/xendomains ] && . /etc/sysconfig/xendomains + +shopt -s nullglob + +check_config_name() +{ + /usr/lib/xen/bin/xen-toolstack create --quiet --dryrun --defconfig "$1" | sed -n 's/^.*\("name":"\([^"]*\)",.*\)\|(name \(.*\))$/\2\3/p' +} + +check_running() +{ + /usr/lib/xen/bin/xen-toolstack domid "$1" >/dev/null 2>&1 + return $? +} + +timeout_coproc() +{ + local TIMEOUT=$1 + shift + + coproc "$@" >/dev/null 2>&1 + + local COPROC_OUT + exec {COPROC_OUT}<&"${COPROC[0]}" + local PID="$COPROC_PID" + + for no in $(seq 0 $TIMEOUT); do + if [ -z "$COPROC_PID" ]; then break; fi + sleep 1 + done + + kill -INT "$COPROC_PID" >/dev/null 2>&1 + wait $PID + local rc=$? + if [ $rc -eq 0 ]; then + echo "ok" + else + echo "fail ($rc)" + fi + + [ $rc -gt 0 ] && cat <&$COPROC_OUT + exec <&$COPROC_OUT- +} + +timeout_domain() +{ + name="$1" + TIMEOUT="$2" + for no in $(seq 0 $TIMEOUT); do + if ! check_running "$name"; then return 0; fi + sleep 1 + done + return 1 +} + +do_start_restore() +{ + [ -n "$XENDOMAINS_SAVE" ] || return + [ -d "$XENDOMAINS_SAVE" ] || return + [ -n "$XENDOMAINS_RESTORE" ] || return + + for file in $XENDOMAINS_SAVE/*; do + if [ -f $file ] ; then + name="${file##*/}" + echo -n "Restoring Xen domain $name (from $file): " + + out=$(/usr/lib/xen/bin/xen-toolstack restore "$file" >/dev/null 2>&1) + case "$?" in + 0) + rm "$file" + domains[$name]='started' + echo "ok" + ;; + *) + domains[$name]='failed' + echo "fail" + echo "$out" + ;; + esac + fi + done +} + +do_start_auto() +{ + [ -n "$XENDOMAINS_AUTO" ] || return + [ -d "$XENDOMAINS_AUTO" ] || return + + for file in $XENDOMAINS_AUTO/*; do + name="$(check_config_name $file)" + + if [ "${domains[$name]}" = started ]; then + : + elif check_running "$name"; then + echo "Xen domain $name already running" + else + echo -n "Starting Xen domain $name (from $file): " + + if [ "${domains[$name]}" = failed ]; then + echo "fail" + else + out=$(/usr/lib/xen/bin/xen-toolstack create --quiet --defconfig "$file" >/dev/null 2>&1) + case "$?" in + 0) + echo "ok" + ;; + *) + echo "fail" + echo "$out" + ;; + esac + fi + fi + done +} + +do_start() +{ + declare -A domains + + do_start_restore + do_start_auto +} + +do_stop_migrate() +{ + [ -n "$XENDOMAINS_MIGRATE" ] || return + + while read id name rest; do + echo -n "Migrating Xen domain $name ($id): " + (timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" /usr/lib/xen/bin/xen-toolstack migrate $id $XENDOMAINS_MIGRATE) + done < <(/usr/lib/xen/bin/xen-init-list) +} + +do_stop_save() +{ + [ -n "$XENDOMAINS_SAVE" ] || return + [ -d "$XENDOMAINS_SAVE" ] || mkdir -m 0700 -p "$XENDOMAINS_SAVE" + + while read id name rest; do + echo -n "Saving Xen domain $name ($id): " + (timeout_coproc "$XENDOMAINS_STOP_MAXWAIT" /usr/lib/xen/bin/xen-toolstack save $id $XENDOMAINS_SAVE/$name) + done < <(/usr/lib/xen/bin/xen-init-list) +} + +do_stop_shutdown() +{ + while read id name rest; do + echo -n "Shutting down Xen domain $name ($id): " + /usr/lib/xen/bin/xen-toolstack shutdown $id >/dev/null 2>&1 + rc=$? + if [ $rc -eq 0 ]; then + echo "ok" + else + echo "fail ($rc)" + fi + done < <(/usr/lib/xen/bin/xen-init-list) + while read id name rest; do + echo -n "Waiting for Xen domain $name ($id) to shut down: " + timeout_domain "$name" "$XENDOMAINS_STOP_MAXWAIT" + rc=$? + if [ $rc -eq 0 ]; then + echo "ok" + else + echo "fail ($rc)" + fi + done < <(/usr/lib/xen/bin/xen-init-list) +} + +do_stop() +{ + do_stop_migrate + do_stop_save + do_stop_shutdown +} + +case "$1" in + start) + do_start + ;; + stop) + do_stop + ;; + restart) + do_stop + do_start + ;; + reload|force-reload) + do_stop + do_start + ;; + status) + /usr/lib/xen/bin/xen-toolstack list -v + ;; + *) + echo "Usage: $0 {start|stop|status|restart|reload|force-reload}" + exit 3 + ;; +esac + +exit 0 -- 2.44.0