]> git.pld-linux.org Git - packages/xen.git/blob - xen-xendomains.init
- subpackage for hypervisor
[packages/xen.git] / xen-xendomains.init
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
30
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
36
37 LOCKFILE=/var/lock/subsys/xendomains
38 XENDOM_CONFIG=/etc/sysconfig/xendomains
39
40 test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
41         if [ "$1" = "stop" ]; then exit 0;
42         else exit 6; fi; }
43
44 . $XENDOM_CONFIG
45
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
123
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
134
135 # Reset status of this service
136 rc_reset
137
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 }
151
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 }
158
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 }
175
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 }
183
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 }
199
200 start() 
201 {
202     if [ -f $LOCKFILE ]; then 
203         echo -n "xendomains already running (lockfile exists)"
204         return; 
205     fi
206
207     if [ "$XENDOMAINS_RESTORE" = "true" ] &&
208        contains_something "$XENDOMAINS_SAVE"
209     then
210         mkdir -p $(dirname "$LOCKFILE")
211         touch $LOCKFILE
212         echo -n "Restoring Xen domains:"
213         for dom in $XENDOMAINS_SAVE/*; do
214             echo -n " ${dom##*/}"
215             xm restore $dom
216             if [ $? -ne 0 ]; then
217                 rc_failed $?
218                 echo -n '!'
219             else
220                 # mv $dom ${dom%/*}/.${dom##*/}
221                 rm $dom
222             fi
223         done
224         echo .
225     fi
226
227     if contains_something "$XENDOMAINS_AUTO"
228     then
229         touch $LOCKFILE
230         echo -n "Starting auto Xen domains:"
231         # We expect config scripts for auto starting domains to be in
232         # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
233
234         # Create all domains with config files in XENDOMAINS_AUTO.
235         # TODO: We should record which domain name belongs 
236         # so we have the option to selectively shut down / migrate later
237         for dom in $XENDOMAINS_AUTO/*; do
238             echo -n " ${dom##*/}"
239             if is_running $dom; then
240                 echo -n "(skip)"
241             else
242                 xm create --quiet --defconfig $dom
243                 if [ $? -ne 0 ]; then
244                     rc_failed $?
245                     echo -n '!'
246                 else
247                     usleep $XENDOMAINS_CREATE_USLEEP
248                 fi
249             fi
250         done
251     fi  
252 }
253
254 all_zombies()
255 {
256     while read LN; do
257         parseln "$LN"
258         if test $id = 0; then continue; fi
259         if test "$state" != "-b---d" -a "$state" != "-----d"; then
260             return 1;
261         fi
262     done < <(xm list | grep -v '^Name')
263     return 0
264 }
265
266 # Wait for max $XENDOMAINS_STOP_MAXWAIT for xm $1 to finish;
267 # if it has not exited by that time kill it, so the init script will
268 # succeed within a finite amount of time; if $2 is nonnull, it will
269 # kill the command as well as soon as no domain (except for zombies)
270 # are left (used for shutdown --all).
271 watchdog_xm()
272 {
273     if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
274         exit
275     fi
276     usleep 20000
277     for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
278         # exit if xm save/migrate/shutdown is finished
279         PSAX=`ps axlw | grep "xm $1" | grep -v grep`
280         if test -z "$PSAX"; then exit; fi
281         echo -n "."; sleep 1
282         # go to kill immediately if there's only zombies left
283         if all_zombies && test -n "$2"; then break; fi
284     done
285     sleep 1
286     read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
287     # kill xm $1
288     kill $PSPID >/dev/null 2>&1
289 }
290
291 stop()
292 {
293     # Collect list of domains to shut down
294     if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
295         rdnames
296     fi
297     echo -n "Shutting down Xen domains:"
298     while read LN; do
299         parseln "$LN"
300         if test $id = 0; then continue; fi
301         echo -n " $name"
302         if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
303             case $name in
304                 ($NAMES)
305                     # nothing
306                     ;;
307                 (*)
308                     echo -n "(skip)"
309                     continue
310                     ;;
311             esac
312         fi
313         # XENDOMAINS_SYSRQ chould be something like just "s" 
314         # or "s e i u" or even "s e s i u o"
315         # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
316         if test -n "$XENDOMAINS_SYSRQ"; then
317             for sysrq in $XENDOMAINS_SYSRQ; do
318                 echo -n "(SR-$sysrq)"
319                 xm sysrq $id $sysrq
320                 if test $? -ne 0; then
321                     rc_failed $?
322                     echo -n '!'
323                 fi
324                 # usleep just ignores empty arg
325                 usleep $XENDOMAINS_USLEEP
326             done
327         fi
328         if test "$state" = "-b---d" -o "$state" = "-----d"; then
329             echo -n "(zomb)"
330             continue
331         fi
332         if test -n "$XENDOMAINS_MIGRATE"; then
333             echo -n "(migr)"
334             watchdog_xm migrate &
335             WDOG_PID=$!
336             xm migrate $id $XENDOMAINS_MIGRATE
337             if test $? -ne 0; then
338                 rc_failed $?
339                 echo -n '!'
340                 kill $WDOG_PID >/dev/null 2>&1
341             else
342                 kill $WDOG_PID >/dev/null 2>&1
343                 continue
344             fi
345         fi
346         if test -n "$XENDOMAINS_SAVE"; then
347             echo -n "(save)"
348             watchdog_xm save &
349             WDOG_PID=$!
350             mkdir -p "$XENDOMAINS_SAVE"
351             xm save $id $XENDOMAINS_SAVE/$name
352             if test $? -ne 0; then
353                 rc_failed $?
354                 echo -n '!'
355                 kill $WDOG_PIG >/dev/null 2>&1
356             else
357                 kill $WDOG_PIG >/dev/null 2>&1
358                 continue
359             fi
360         fi
361         if test -n "$XENDOMAINS_SHUTDOWN"; then
362             # XENDOMAINS_SHUTDOWN should be "--halt --wait"
363             echo -n "(shut)"
364             watchdog_xm shutdown &
365             WDOG_PID=$!
366             xm shutdown $id $XENDOMAINS_SHUTDOWN
367             if test $? -ne 0; then
368                 rc_failed $?
369                 echo -n '!'
370             fi
371             kill $WDOG_PIG >/dev/null 2>&1
372         fi
373     done < <(xm list | grep -v '^Name')
374
375     # NB. this shuts down ALL Xen domains (politely), not just the ones in
376     # AUTODIR/*
377     # This is because it's easier to do ;-) but arguably if this script is run
378     # on system shutdown then it's also the right thing to do.
379     if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
380         # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
381         echo -n " SHUTDOWN_ALL "
382         watchdog_xm shutdown 1 &
383         WDOG_PID=$!
384         xm shutdown $XENDOMAINS_SHUTDOWN_ALL
385         if test $? -ne 0; then
386             rc_failed $?
387             echo -n '!'
388         fi
389         kill $WDOG_PID >/dev/null 2>&1
390     fi
391
392     # Unconditionally delete lock file
393     rm -f $LOCKFILE
394 }
395
396 check_domain_up()
397 {
398     while read LN; do
399         parseln "$LN"
400         if test $id = 0; then continue; fi
401         case $name in 
402             ($1)
403                 return 0
404                 ;;
405         esac
406     done < <(xm list | grep -v "^Name")
407     return 1
408 }
409
410 check_all_auto_domains_up()
411 {
412     if ! contains_something "$XENDOMAINS_AUTO"
413     then
414       return 0
415     fi
416     missing=
417     for nm in $XENDOMAINS_AUTO/*; do
418         rdname $nm
419         found=0
420         if check_domain_up "$NM"; then 
421             echo -n " $name"
422         else 
423             missing="$missing $NM"
424         fi
425     done
426     if test -n "$missing"; then
427         echo -n " MISS AUTO:$missing"
428         return 1
429     fi
430     return 0
431 }
432
433 check_all_saved_domains_up()
434 {
435     if ! contains_something "$XENDOMAINS_SAVE" 
436     then
437       return 0
438     fi
439     missing=`/bin/ls $XENDOMAINS_SAVE`
440     echo -n " MISS SAVED: " $missing
441     return 1
442 }
443
444 # This does NOT necessarily restart all running domains: instead it
445 # stops all running domains and then boots all the domains specified in
446 # AUTODIR.  If other domains have been started manually then they will
447 # not get restarted.
448 # Commented out to avoid confusion!
449
450 restart()
451 {
452     stop
453     start
454 }
455
456 reload()
457 {
458     restart
459 }
460
461
462 case "$1" in
463     start)
464         start
465         rc_status
466         if test -f $LOCKFILE; then rc_status -v; fi
467         ;;
468
469     stop)
470         stop
471         rc_status -v
472         ;;
473
474     restart)
475         restart
476         ;;
477     reload)
478         reload
479         ;;
480
481     status)
482         echo -n "Checking for xendomains:" 
483         if test ! -f $LOCKFILE; then 
484             rc_failed 3
485         else
486             check_all_auto_domains_up
487             rc_status
488             check_all_saved_domains_up
489             rc_status
490         fi
491         rc_status -v
492         ;;
493
494     *)
495         echo "Usage: $0 {start|stop|restart|reload|status}"
496         rc_failed 3
497         rc_status -v
498         ;;
499 esac
500
501 rc_exit
This page took 0.072616 seconds and 3 git commands to generate.