ia64/xen-unstable

view tools/examples/init.d/xendomains @ 12849:a330509abb20

This patch checks the contents of XENDOMAINS_SAVE before the restore
process begins, and prevents xendomains from attempting to start any
domain that appears there, whether the domain started successfully or
not.

Signed off by: Hugh Brock <hbrock@redhat.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Dec 07 12:23:35 2006 +0000 (2006-12-07)
parents e229687561cf
children d2646466e0a7
line source
1 #!/bin/bash
2 #
3 # /etc/init.d/xendomains
4 # Start / stop domains automatically when domain 0 boots / shuts down.
5 #
6 # chkconfig: 345 99 00
7 # description: Start / stop Xen domains.
8 #
9 # This script offers fairly basic functionality. It should work on Redhat
10 # but also on LSB-compliant SuSE releases and on Debian with the LSB package
11 # installed. (LSB is the Linux Standard Base)
12 #
13 # Based on the example in the "Designing High Quality Integrated Linux
14 # Applications HOWTO" by Avi Alkalay
15 # <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
16 #
17 ### BEGIN INIT INFO
18 # Provides: xendomains
19 # Required-Start: $syslog $remote_fs xend
20 # Should-Start:
21 # Required-Stop: $syslog $remote_fs xend
22 # Should-Stop:
23 # Default-Start: 3 4 5
24 # Default-Stop: 0 1 2 6
25 # Default-Enabled: yes
26 # Short-Description: Start/stop secondary xen domains
27 # Description: Start / stop domains automatically when domain 0
28 # boots / shuts down.
29 ### END INIT INFO
31 # Correct exit code would probably be 5, but it's enough
32 # if xend complains if we're not running as privileged domain
33 if ! [ -e /proc/xen/privcmd ]; then
34 exit 0
35 fi
37 LOCKFILE=/var/lock/subsys/xendomains
38 XENDOM_CONFIG=/etc/sysconfig/xendomains
40 test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
41 if [ "$1" = "stop" ]; then exit 0;
42 else exit 6; fi; }
44 . $XENDOM_CONFIG
46 # Use the SUSE rc_ init script functions;
47 # emulate them on LSB, RH and other systems
48 if test -e /etc/rc.status; then
49 # SUSE rc script library
50 . /etc/rc.status
51 else
52 _cmd=$1
53 declare -a _SMSG
54 if test "${_cmd}" = "status"; then
55 _SMSG=(running dead dead unused unknown)
56 _RC_UNUSED=3
57 else
58 _SMSG=(done failed failed missed failed skipped unused failed failed)
59 _RC_UNUSED=6
60 fi
61 if test -e /lib/lsb/init-functions; then
62 # LSB
63 . /lib/lsb/init-functions
64 echo_rc()
65 {
66 if test ${_RC_RV} = 0; then
67 log_success_msg " [${_SMSG[${_RC_RV}]}] "
68 else
69 log_failure_msg " [${_SMSG[${_RC_RV}]}] "
70 fi
71 }
72 elif test -e /etc/init.d/functions; then
73 # REDHAT
74 . /etc/init.d/functions
75 echo_rc()
76 {
77 #echo -n " [${_SMSG[${_RC_RV}]}] "
78 if test ${_RC_RV} = 0; then
79 success " [${_SMSG[${_RC_RV}]}] "
80 else
81 failure " [${_SMSG[${_RC_RV}]}] "
82 fi
83 }
84 else
85 # emulate it
86 echo_rc()
87 {
88 echo " [${_SMSG[${_RC_RV}]}] "
89 }
90 fi
91 rc_reset() { _RC_RV=0; }
92 rc_failed()
93 {
94 if test -z "$1"; then
95 _RC_RV=1;
96 elif test "$1" != "0"; then
97 _RC_RV=$1;
98 fi
99 return ${_RC_RV}
100 }
101 rc_check()
102 {
103 return rc_failed $?
104 }
105 rc_status()
106 {
107 rc_failed $?
108 if test "$1" = "-r"; then _RC_RV=0; shift; fi
109 if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
110 if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
111 if test "$1" = "-v"; then echo_rc; shift; fi
112 if test "$1" = "-r"; then _RC_RV=0; shift; fi
113 return ${_RC_RV}
114 }
115 rc_exit() { exit ${_RC_RV}; }
116 rc_active()
117 {
118 if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
119 if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
120 return 1
121 }
122 fi
124 if ! which usleep >&/dev/null
125 then
126 usleep()
127 {
128 if [ -n "$1" ]
129 then
130 sleep $(( $1 / 1000000 ))
131 fi
132 }
133 fi
135 # Reset status of this service
136 rc_reset
138 ##
139 # Returns 0 (success) if the given parameter names a directory, and that
140 # directory is not empty.
141 #
142 contains_something()
143 {
144 if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
145 then
146 return 0
147 else
148 return 1
149 fi
150 }
152 # read name from xen config file
153 rdname()
154 {
155 NM=$(xm create --quiet --dryrun --defconfig "$1" |
156 sed -n 's/^.*(name \(.*\))$/\1/p')
157 }
159 rdnames()
160 {
161 NAMES=
162 if ! contains_something "$XENDOMAINS_AUTO"
163 then
164 return
165 fi
166 for dom in $XENDOMAINS_AUTO/*; do
167 rdname $dom
168 if test -z $NAMES; then
169 NAMES=$NM;
170 else
171 NAMES="$NAMES|$NM"
172 fi
173 done
174 }
176 parseln()
177 {
178 name=`echo "$1" | cut -c0-17`
179 name=${name%% *}
180 rest=`echo "$1" | cut -c18- `
181 read id mem cpu vcpu state tm < <(echo "$rest")
182 }
184 is_running()
185 {
186 rdname $1
187 RC=1
188 while read LN; do
189 parseln "$LN"
190 if test $id = 0; then continue; fi
191 case $name in
192 ($NM)
193 RC=0
194 ;;
195 esac
196 done < <(xm list | grep -v '^Name')
197 return $RC
198 }
200 start()
201 {
202 if [ -f $LOCKFILE ]; then
203 echo -n "xendomains already running (lockfile exists)"
204 return;
205 fi
207 saved_domains=" "
208 if [ "$XENDOMAINS_RESTORE" = "true" ] &&
209 contains_something "$XENDOMAINS_SAVE"
210 then
211 mkdir -p $(dirname "$LOCKFILE")
212 touch $LOCKFILE
213 echo -n "Restoring Xen domains:"
214 saved_domains=`ls $XENDOMAINS_SAVE`
215 for dom in $XENDOMAINS_SAVE/*; do
216 echo -n " ${dom##*/}"
217 xm restore $dom
218 if [ $? -ne 0 ]; then
219 rc_failed $?
220 echo -n '!'
221 else
222 # mv $dom ${dom%/*}/.${dom##*/}
223 rm $dom
224 fi
225 done
226 echo .
227 fi
229 if contains_something "$XENDOMAINS_AUTO"
230 then
231 touch $LOCKFILE
232 echo -n "Starting auto Xen domains:"
233 # We expect config scripts for auto starting domains to be in
234 # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
236 # Create all domains with config files in XENDOMAINS_AUTO.
237 # TODO: We should record which domain name belongs
238 # so we have the option to selectively shut down / migrate later
239 # If a domain statefile from $XENDOMAINS_SAVE matches a domain name
240 # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't
241 # restore correctly it requires administrative attention.
242 for dom in $XENDOMAINS_AUTO/*; do
243 echo -n " ${dom##*/}"
244 shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
245 echo $saved_domains | grep -w $shortdom > /dev/null
246 if [ $? -eq 0 ] || is_running $dom; then
247 echo -n "(skip)"
248 else
249 xm create --quiet --defconfig $dom
250 if [ $? -ne 0 ]; then
251 rc_failed $?
252 echo -n '!'
253 else
254 usleep $XENDOMAINS_CREATE_USLEEP
255 fi
256 fi
257 done
258 fi
259 }
261 all_zombies()
262 {
263 while read LN; do
264 parseln "$LN"
265 if test $id = 0; then continue; fi
266 if test "$state" != "-b---d" -a "$state" != "-----d"; then
267 return 1;
268 fi
269 done < <(xm list | grep -v '^Name')
270 return 0
271 }
273 # Wait for max $XENDOMAINS_STOP_MAXWAIT for xm $1 to finish;
274 # if it has not exited by that time kill it, so the init script will
275 # succeed within a finite amount of time; if $2 is nonnull, it will
276 # kill the command as well as soon as no domain (except for zombies)
277 # are left (used for shutdown --all).
278 watchdog_xm()
279 {
280 if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
281 exit
282 fi
283 usleep 20000
284 for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
285 # exit if xm save/migrate/shutdown is finished
286 PSAX=`ps axlw | grep "xm $1" | grep -v grep`
287 if test -z "$PSAX"; then exit; fi
288 echo -n "."; sleep 1
289 # go to kill immediately if there's only zombies left
290 if all_zombies && test -n "$2"; then break; fi
291 done
292 sleep 1
293 read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
294 # kill xm $1
295 kill $PSPID >/dev/null 2>&1
296 }
298 stop()
299 {
300 # Collect list of domains to shut down
301 if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
302 rdnames
303 fi
304 echo -n "Shutting down Xen domains:"
305 while read LN; do
306 parseln "$LN"
307 if test $id = 0; then continue; fi
308 echo -n " $name"
309 if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
310 case $name in
311 ($NAMES)
312 # nothing
313 ;;
314 (*)
315 echo -n "(skip)"
316 continue
317 ;;
318 esac
319 fi
320 # XENDOMAINS_SYSRQ chould be something like just "s"
321 # or "s e i u" or even "s e s i u o"
322 # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
323 if test -n "$XENDOMAINS_SYSRQ"; then
324 for sysrq in $XENDOMAINS_SYSRQ; do
325 echo -n "(SR-$sysrq)"
326 xm sysrq $id $sysrq
327 if test $? -ne 0; then
328 rc_failed $?
329 echo -n '!'
330 fi
331 # usleep just ignores empty arg
332 usleep $XENDOMAINS_USLEEP
333 done
334 fi
335 if test "$state" = "-b---d" -o "$state" = "-----d"; then
336 echo -n "(zomb)"
337 continue
338 fi
339 if test -n "$XENDOMAINS_MIGRATE"; then
340 echo -n "(migr)"
341 watchdog_xm migrate &
342 WDOG_PID=$!
343 xm migrate $id $XENDOMAINS_MIGRATE
344 if test $? -ne 0; then
345 rc_failed $?
346 echo -n '!'
347 kill $WDOG_PID >/dev/null 2>&1
348 else
349 kill $WDOG_PID >/dev/null 2>&1
350 continue
351 fi
352 fi
353 if test -n "$XENDOMAINS_SAVE"; then
354 echo -n "(save)"
355 watchdog_xm save &
356 WDOG_PID=$!
357 mkdir -p "$XENDOMAINS_SAVE"
358 xm save $id $XENDOMAINS_SAVE/$name
359 if test $? -ne 0; then
360 rc_failed $?
361 echo -n '!'
362 kill $WDOG_PID >/dev/null 2>&1
363 else
364 kill $WDOG_PID >/dev/null 2>&1
365 continue
366 fi
367 fi
368 if test -n "$XENDOMAINS_SHUTDOWN"; then
369 # XENDOMAINS_SHUTDOWN should be "--halt --wait"
370 echo -n "(shut)"
371 watchdog_xm shutdown &
372 WDOG_PID=$!
373 xm shutdown $id $XENDOMAINS_SHUTDOWN
374 if test $? -ne 0; then
375 rc_failed $?
376 echo -n '!'
377 fi
378 kill $WDOG_PID >/dev/null 2>&1
379 fi
380 done < <(xm list | grep -v '^Name')
382 # NB. this shuts down ALL Xen domains (politely), not just the ones in
383 # AUTODIR/*
384 # This is because it's easier to do ;-) but arguably if this script is run
385 # on system shutdown then it's also the right thing to do.
386 if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
387 # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
388 echo -n " SHUTDOWN_ALL "
389 watchdog_xm shutdown 1 &
390 WDOG_PID=$!
391 xm shutdown $XENDOMAINS_SHUTDOWN_ALL
392 if test $? -ne 0; then
393 rc_failed $?
394 echo -n '!'
395 fi
396 kill $WDOG_PID >/dev/null 2>&1
397 fi
399 # Unconditionally delete lock file
400 rm -f $LOCKFILE
401 }
403 check_domain_up()
404 {
405 while read LN; do
406 parseln "$LN"
407 if test $id = 0; then continue; fi
408 case $name in
409 ($1)
410 return 0
411 ;;
412 esac
413 done < <(xm list | grep -v "^Name")
414 return 1
415 }
417 check_all_auto_domains_up()
418 {
419 if ! contains_something "$XENDOMAINS_AUTO"
420 then
421 return 0
422 fi
423 missing=
424 for nm in $XENDOMAINS_AUTO/*; do
425 rdname $nm
426 found=0
427 if check_domain_up "$NM"; then
428 echo -n " $name"
429 else
430 missing="$missing $NM"
431 fi
432 done
433 if test -n "$missing"; then
434 echo -n " MISS AUTO:$missing"
435 return 1
436 fi
437 return 0
438 }
440 check_all_saved_domains_up()
441 {
442 if ! contains_something "$XENDOMAINS_SAVE"
443 then
444 return 0
445 fi
446 missing=`/bin/ls $XENDOMAINS_SAVE`
447 echo -n " MISS SAVED: " $missing
448 return 1
449 }
451 # This does NOT necessarily restart all running domains: instead it
452 # stops all running domains and then boots all the domains specified in
453 # AUTODIR. If other domains have been started manually then they will
454 # not get restarted.
455 # Commented out to avoid confusion!
457 restart()
458 {
459 stop
460 start
461 }
463 reload()
464 {
465 restart
466 }
469 case "$1" in
470 start)
471 start
472 rc_status
473 if test -f $LOCKFILE; then rc_status -v; fi
474 ;;
476 stop)
477 stop
478 rc_status -v
479 ;;
481 restart)
482 restart
483 ;;
484 reload)
485 reload
486 ;;
488 status)
489 echo -n "Checking for xendomains:"
490 if test ! -f $LOCKFILE; then
491 rc_failed 3
492 else
493 check_all_auto_domains_up
494 rc_status
495 check_all_saved_domains_up
496 rc_status
497 fi
498 rc_status -v
499 ;;
501 *)
502 echo "Usage: $0 {start|stop|restart|reload|status}"
503 rc_failed 3
504 rc_status -v
505 ;;
506 esac
508 rc_exit