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