]>
Commit | Line | Data |
---|---|---|
2e8b91a6 JR |
1 | #!/bin/sh |
2 | # | |
3 | # xendomains Start / stop domains automatically when domain 0 boots / shuts down. | |
4 | # | |
5 | # chkconfig: 345 99 00 | |
6 | # description: Start / stop Xen domains. | |
7 | # | |
8 | # This script offers fairly basic functionality. It should work on Redhat | |
9 | # but also on LSB-compliant SuSE releases and on Debian with the LSB package | |
10 | # installed. (LSB is the Linux Standard Base) | |
11 | # | |
12 | # Based on the example in the "Designing High Quality Integrated Linux | |
13 | # Applications HOWTO" by Avi Alkalay | |
14 | # <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/> | |
15 | # | |
2e8b91a6 JR |
16 | |
17 | . /etc/rc.d/init.d/functions | |
18 | ||
19 | CMD=xm | |
20 | $CMD list >/dev/null 2>/dev/null || CMD=xl | |
21 | $CMD list >/dev/null 2>/dev/null || exit 0 | |
22 | ||
23 | [ -e /proc/xen/privcmd ] || exit 0 | |
24 | ||
25 | if [ -r /etc/sysconfig/xendomains ]; then | |
26 | . /etc/sysconfig/xendomains | |
27 | else | |
28 | echo "/etc/sysconfig/xendomains does not exist" | |
29 | if [ "$1" = "stop" ]; then | |
30 | exit 0 | |
31 | else | |
32 | exit 6 | |
33 | fi | |
34 | fi | |
35 | ||
36 | ## | |
37 | # Returns 0 (success) if the given parameter names a directory, and that | |
38 | # directory is not empty. | |
39 | # | |
40 | contains_something() { | |
41 | if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]; then | |
42 | return 0 | |
43 | else | |
44 | return 1 | |
45 | fi | |
46 | } | |
47 | ||
48 | # read name from xen config file | |
49 | rdname() { | |
50 | NM=$($CMD create --quiet --dryrun --defconfig "$1" | sed -n 's/^.*(name \(.*\))$/\1/p') | |
51 | } | |
52 | ||
53 | rdnames() { | |
54 | NAMES= | |
55 | if ! contains_something "$XENDOMAINS_AUTO"; then | |
56 | return | |
57 | fi | |
58 | for dom in $XENDOMAINS_AUTO/*; do | |
59 | rdname $dom | |
60 | if test -z $NAMES; then | |
61 | NAMES=$NM; | |
62 | else | |
63 | NAMES="$NAMES|$NM" | |
64 | fi | |
65 | done | |
66 | } | |
67 | ||
68 | parseln() { | |
ddb246ae | 69 | if [[ "$1" = "*(domain*" ]]; then |
2e8b91a6 | 70 | name=;id= |
ddb246ae | 71 | elif [[ "$1" = "*(name*" ]]; then |
2e8b91a6 | 72 | name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/') |
ddb246ae | 73 | elif [[ "$1" = "*(domid*" ]]; then |
2e8b91a6 | 74 | id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/') |
ddb246ae | 75 | fi |
2e8b91a6 JR |
76 | [ -n "$name" -a -n "$id" ] && return 0 || return 1 |
77 | } | |
78 | ||
79 | is_running() { | |
80 | rdname $1 | |
2e8b91a6 | 81 | name=;id= |
ddb246ae | 82 | $CMD list -l | grep '(\(domain\|domid\|name\)' | \ |
2e8b91a6 JR |
83 | while read LN; do |
84 | parseln "$LN" || continue | |
85 | [ $id = 0 ] && continue | |
86 | case $name in | |
87 | ($NM) | |
ddb246ae | 88 | return 0 |
2e8b91a6 JR |
89 | ;; |
90 | esac | |
ddb246ae JR |
91 | done |
92 | return 1 | |
2e8b91a6 JR |
93 | } |
94 | ||
95 | start() { | |
96 | if [ -f /var/lock/subsys/xendomains ]; then | |
97 | echo -e "xendomains already running (lockfile exists)" | |
98 | return | |
99 | fi | |
100 | ||
101 | saved_domains=" " | |
102 | if [ "$XENDOMAINS_RESTORE" = "true" ] && contains_something "$XENDOMAINS_SAVE"; then | |
103 | mkdir -p $(dirname "/var/lock/subsys/xendomains") | |
104 | touch /var/lock/subsys/xendomains | |
105 | echo -n "Restoring Xen domains:" | |
106 | saved_domains=`ls $XENDOMAINS_SAVE` | |
107 | for dom in $XENDOMAINS_SAVE/*; do | |
108 | if [ -f $dom ] ; then | |
109 | HEADER=`head -c 16 $dom | head -n 1 2> /dev/null` | |
110 | if [ $HEADER = "LinuxGuestRecord" ]; then | |
111 | echo -n " ${dom##*/}" | |
112 | XMR=`$CMD restore $dom 2>&1 1>/dev/null` | |
113 | #$CMD restore $dom | |
114 | if [ $? -ne 0 ]; then | |
115 | echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR" | |
116 | echo -e '!' | |
117 | else | |
118 | # mv $dom ${dom%/*}/.${dom##*/} | |
119 | rm $dom | |
120 | fi | |
121 | fi | |
122 | fi | |
123 | done | |
124 | echo -e | |
125 | fi | |
126 | ||
127 | if contains_something "$XENDOMAINS_AUTO" ; then | |
128 | touch /var/lock/subsys/xendomains | |
129 | echo -n "Starting auto Xen domains:" | |
130 | # We expect config scripts for auto starting domains to be in | |
131 | # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere | |
132 | ||
133 | # Create all domains with config files in XENDOMAINS_AUTO. | |
134 | # TODO: We should record which domain name belongs | |
135 | # so we have the option to selectively shut down / migrate later | |
136 | # If a domain statefile from $XENDOMAINS_SAVE matches a domain name | |
137 | # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't | |
138 | # restore correctly it requires administrative attention. | |
139 | for dom in $XENDOMAINS_AUTO/*; do | |
140 | echo -n " ${dom##*/}" | |
141 | shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p') | |
142 | echo $saved_domains | grep -w $shortdom > /dev/null | |
143 | if [ $? -eq 0 ] || is_running $dom; then | |
144 | echo -n "(skip)" | |
145 | else | |
146 | XMC=`$CMD create --quiet --defconfig $dom` | |
147 | if [ $? -ne 0 ]; then | |
148 | echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n" | |
149 | echo -e '!' | |
150 | else | |
151 | usleep $XENDOMAINS_CREATE_USLEEP | |
152 | fi | |
153 | fi | |
154 | done | |
155 | fi | |
156 | } | |
157 | ||
158 | all_zombies() { | |
159 | name=;id= | |
ddb246ae | 160 | $CMD list -l | grep '(\(domain\|domid\|name\)' | \ |
2e8b91a6 JR |
161 | while read LN; do |
162 | parseln "$LN" || continue | |
163 | if test $id = 0; then continue; fi | |
164 | if test "$state" != "-b---d" -a "$state" != "-----d"; then | |
165 | return 1; | |
166 | fi | |
ddb246ae | 167 | done |
2e8b91a6 JR |
168 | return 0 |
169 | } | |
170 | ||
171 | # Wait for max $XENDOMAINS_STOP_MAXWAIT for $CMD $1 to finish; | |
172 | # if it has not exited by that time kill it, so the init script will | |
173 | # succeed within a finite amount of time; if $2 is nonnull, it will | |
174 | # kill the command as well as soon as no domain (except for zombies) | |
175 | # are left (used for shutdown --all). Third parameter, if any, suppresses | |
176 | # output of dots per working state (formatting issues) | |
177 | watchdog_xencmd() { | |
178 | if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then | |
179 | exit | |
180 | fi | |
181 | ||
182 | usleep 20000 | |
183 | for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do | |
184 | # exit if $CMD save/migrate/shutdown is finished | |
185 | PSAX=`ps axlw | grep "$CMD $1" | grep -v grep` | |
186 | if test -z "$PSAX"; then exit; fi | |
187 | if ! test -n "$3"; then echo -n '.'; fi | |
188 | sleep 1 | |
189 | # go to kill immediately if there's only zombies left | |
190 | if all_zombies && test -n "$2"; then break; fi | |
191 | done | |
192 | sleep 1 | |
ddb246ae | 193 | PSPID=$($PSAX | awk '{ print $3 }') |
2e8b91a6 JR |
194 | # kill $CMD $1 |
195 | kill $PSPID >/dev/null 2>&1 | |
196 | ||
197 | echo -e . | |
198 | } | |
199 | ||
200 | stop() { | |
201 | # Collect list of domains to shut down | |
202 | if test "$XENDOMAINS_AUTO_ONLY" = "true"; then | |
203 | rdnames | |
204 | fi | |
205 | echo -n "Shutting down Xen domains:" | |
206 | name=;id= | |
ddb246ae | 207 | $CMD list -l | grep '(\(domain\|domid\|name\)' | \ |
2e8b91a6 JR |
208 | while read LN; do |
209 | parseln "$LN" || continue | |
210 | if test $id = 0; then continue; fi | |
211 | echo -n " $name" | |
212 | if test "$XENDOMAINS_AUTO_ONLY" = "true"; then | |
213 | eval " | |
214 | case \"\$name\" in | |
215 | ($NAMES) | |
216 | # nothing | |
217 | ;; | |
218 | (*) | |
219 | echo -e '(skip)' | |
220 | continue | |
221 | ;; | |
222 | esac | |
223 | " | |
224 | fi | |
225 | # XENDOMAINS_SYSRQ chould be something like just "s" | |
226 | # or "s e i u" or even "s e s i u o" | |
227 | # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so | |
228 | if test -n "$XENDOMAINS_SYSRQ"; then | |
229 | for sysrq in $XENDOMAINS_SYSRQ; do | |
230 | echo -n "(SR-$sysrq)" | |
231 | XMR=`$CMD sysrq $id $sysrq 2>&1 1>/dev/null` | |
232 | if test $? -ne 0; then | |
233 | echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n" | |
234 | echo -n '!' | |
235 | fi | |
236 | # usleep just ignores empty arg | |
237 | usleep $XENDOMAINS_USLEEP | |
238 | done | |
239 | fi | |
240 | if test "$state" = "-b---d" -o "$state" = "-----d"; then | |
241 | echo -n "(zomb)" | |
242 | continue | |
243 | fi | |
244 | if test -n "$XENDOMAINS_MIGRATE"; then | |
245 | echo -n "(migr)" | |
246 | watchdog_xencmd migrate & | |
247 | WDOG_PID=$! | |
248 | XMR=`$CMD migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null` | |
249 | if test $? -ne 0; then | |
250 | echo -e "\nAn error occurred while migrating domain:\n$XMR\n" | |
251 | echo -e '!' | |
252 | ||
253 | kill $WDOG_PID >/dev/null 2>&1 | |
254 | else | |
255 | kill $WDOG_PID >/dev/null 2>&1 | |
256 | ||
257 | echo -e . | |
258 | usleep 1000 | |
259 | continue | |
260 | fi | |
261 | fi | |
262 | if test -n "$XENDOMAINS_SAVE"; then | |
263 | echo -n "(save)" | |
264 | watchdog_xencmd save & | |
265 | WDOG_PID=$! | |
266 | mkdir -p "$XENDOMAINS_SAVE" | |
267 | XMR=`$CMD save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null` | |
268 | if test $? -ne 0; then | |
269 | echo -e "\nAn error occurred while saving domain:\n$XMR\n" | |
270 | echo -e '!' | |
271 | kill $WDOG_PID >/dev/null 2>&1 | |
272 | else | |
273 | kill $WDOG_PID >/dev/null 2>&1 | |
274 | echo -e . | |
275 | usleep 1000 | |
276 | continue | |
277 | fi | |
278 | fi | |
279 | if test -n "$XENDOMAINS_SHUTDOWN"; then | |
280 | # XENDOMAINS_SHUTDOWN should be "--halt --wait" | |
281 | echo -n "(shut)" | |
282 | watchdog_xencmd shutdown & | |
283 | WDOG_PID=$! | |
284 | XMR=`$CMD shutdown $id $XENDOMAINS_SHUTDOWN 2>&1 1>/dev/null` | |
285 | if test $? -ne 0; then | |
286 | echo -e "\nAn error occurred while shutting down domain:\n$XMR\n" | |
287 | echo -e '!' | |
288 | fi | |
289 | kill $WDOG_PID >/dev/null 2>&1 | |
290 | fi | |
ddb246ae | 291 | done |
2e8b91a6 JR |
292 | |
293 | # NB. this shuts down ALL Xen domains (politely), not just the ones in | |
294 | # AUTODIR/* | |
295 | # This is because it's easier to do ;-) but arguably if this script is run | |
296 | # on system shutdown then it's also the right thing to do. | |
297 | if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then | |
298 | # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait" | |
299 | echo -n " SHUTDOWN_ALL " | |
300 | watchdog_xencmd shutdown 1 false & | |
301 | WDOG_PID=$! | |
302 | XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null` | |
303 | if test $? -ne 0; then | |
304 | echo -e "\nAn error occurred while shutting down all domains: $XMR\n" | |
305 | echo -e '!' | |
306 | fi | |
307 | kill $WDOG_PID >/dev/null 2>&1 | |
308 | fi | |
309 | ||
310 | # Unconditionally delete lock file | |
311 | rm -f /var/lock/subsys/xendomains | |
312 | } | |
313 | ||
314 | check_domain_up() | |
315 | { | |
316 | name=;id= | |
ddb246ae | 317 | $CMD list -l | grep '(\(domain\|domid\|name\)' | \ |
2e8b91a6 JR |
318 | while read LN; do |
319 | parseln "$LN" || continue | |
320 | if test $id = 0; then continue; fi | |
321 | case $name in | |
322 | ($1) | |
323 | return 0 | |
324 | ;; | |
325 | esac | |
ddb246ae | 326 | done |
2e8b91a6 JR |
327 | return 1 |
328 | } | |
329 | ||
330 | check_all_auto_domains_up() | |
331 | { | |
332 | if ! contains_something "$XENDOMAINS_AUTO"; then | |
333 | return 0 | |
334 | fi | |
335 | missing= | |
336 | for nm in $XENDOMAINS_AUTO/*; do | |
337 | rdname $nm | |
338 | found=0 | |
339 | if check_domain_up "$NM"; then | |
340 | echo -n " $name" | |
341 | else | |
342 | missing="$missing $NM" | |
343 | fi | |
344 | done | |
345 | if test -n "$missing"; then | |
346 | echo -n " MISS AUTO:$missing" | |
347 | return 1 | |
348 | fi | |
349 | return 0 | |
350 | } | |
351 | ||
352 | check_all_saved_domains_up() | |
353 | { | |
354 | if ! contains_something "$XENDOMAINS_SAVE"; then | |
355 | return 0 | |
356 | fi | |
357 | missing=`/bin/ls $XENDOMAINS_SAVE` | |
358 | echo -n " MISS SAVED: " $missing | |
359 | return 1 | |
360 | } | |
361 | ||
362 | RETVAL=0 | |
363 | # See how we were called. | |
364 | case "$1" in | |
365 | start) | |
366 | start | |
367 | ;; | |
368 | stop) | |
369 | stop | |
370 | ;; | |
371 | restart|reload) | |
372 | # This does NOT necessarily restart all running domains: instead it | |
373 | # stops all running domains and then boots all the domains specified in | |
374 | # AUTODIR. If other domains have been started manually then they will | |
375 | # not get restarted. | |
376 | stop | |
377 | start | |
378 | ;; | |
379 | status) | |
380 | if [ -f /var/lock/subsys/xendomains; then | |
381 | echo -n "Checking for xendomains:" | |
382 | check_all_auto_domains_up | |
383 | check_all_saved_domains_up | |
384 | fi | |
385 | ;; | |
386 | *) | |
387 | msg_usage "$0 {start|stop|restart|reload|status}" | |
388 | ;; | |
389 | esac | |
390 | ||
391 | exit $RETVAL |