~ubuntu-branches/ubuntu/trusty/xen-common/trusty

« back to all changes in this revision

Viewing changes to tools/hotplug/Linux/init.d/xendomains

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2009-11-22 16:51:53 UTC
  • mfrom: (5.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20091122165153-d36l98kbx8a930h2
Tags: 3.4.2-2
* Redefine Xen version tests to allow detection of bare metal.
  (closes: #556859)
* Support oldstyle Xen kernel without xenfs. (closes: #557151)
* Use debhelper compat level 7.
* Remove oldstable-only conflicts.
* Add wrapper for xenpm.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 /etc/init.d/functions; then
 
62
        # REDHAT
 
63
        . /etc/init.d/functions
 
64
        echo_rc()
 
65
        {
 
66
            #echo -n "  [${_SMSG[${_RC_RV}]}] "
 
67
            if test ${_RC_RV} = 0; then
 
68
                success "  [${_SMSG[${_RC_RV}]}] "
 
69
            else
 
70
                failure "  [${_SMSG[${_RC_RV}]}] "
 
71
            fi
 
72
        }
 
73
    elif test -e /lib/lsb/init-functions; then
 
74
        # LSB    
 
75
        . /lib/lsb/init-functions
 
76
        if alias log_success_msg >/dev/null 2>/dev/null; then
 
77
          echo_rc()
 
78
          {
 
79
               echo "  [${_SMSG[${_RC_RV}]}] "
 
80
          }
 
81
        else
 
82
          echo_rc()
 
83
          {
 
84
            if test ${_RC_RV} = 0; then
 
85
                log_success_msg "  [${_SMSG[${_RC_RV}]}] "
 
86
            else
 
87
                log_failure_msg "  [${_SMSG[${_RC_RV}]}] "
 
88
            fi
 
89
          }
 
90
        fi
 
91
    else    
 
92
        # emulate it
 
93
        echo_rc()
 
94
        {
 
95
            echo "  [${_SMSG[${_RC_RV}]}] "
 
96
        }
 
97
    fi
 
98
    rc_reset() { _RC_RV=0; }
 
99
    rc_failed()
 
100
    {
 
101
        if test -z "$1"; then 
 
102
            _RC_RV=1;
 
103
        elif test "$1" != "0"; then 
 
104
            _RC_RV=$1; 
 
105
        fi
 
106
        return ${_RC_RV}
 
107
    }
 
108
    rc_check()
 
109
    {
 
110
        return rc_failed $?
 
111
    }   
 
112
    rc_status()
 
113
    {
 
114
        rc_failed $?
 
115
        if test "$1" = "-r"; then _RC_RV=0; shift; fi
 
116
        if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
 
117
        if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
 
118
        if test "$1" = "-v"; then echo_rc; shift; fi
 
119
        if test "$1" = "-r"; then _RC_RV=0; shift; fi
 
120
        return ${_RC_RV}
 
121
    }
 
122
    rc_exit() { exit ${_RC_RV}; }
 
123
    rc_active() 
 
124
    {
 
125
        if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
 
126
        if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
 
127
        return 1
 
128
    }
 
129
fi
 
130
 
 
131
if ! which usleep >&/dev/null
 
132
then
 
133
  usleep()
 
134
  {
 
135
    if [ -n "$1" ]
 
136
    then
 
137
      sleep $(( $1 / 1000000 ))
 
138
    fi
 
139
  }
 
140
fi
 
141
 
 
142
# Reset status of this service
 
143
rc_reset
 
144
 
 
145
##
 
146
# Returns 0 (success) if the given parameter names a directory, and that
 
147
# directory is not empty.
 
148
#
 
149
contains_something()
 
150
{
 
151
  if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
 
152
  then
 
153
    return 0
 
154
  else
 
155
    return 1
 
156
  fi
 
157
}
 
158
 
 
159
# read name from xen config file
 
160
rdname()
 
161
{
 
162
    NM=$(xm create --quiet --dryrun --defconfig "$1" |
 
163
         sed -n 's/^.*(name \(.*\))$/\1/p')
 
164
}
 
165
 
 
166
rdnames()
 
167
{
 
168
    NAMES=
 
169
    if ! contains_something "$XENDOMAINS_AUTO"
 
170
    then 
 
171
        return
 
172
    fi
 
173
    for dom in $XENDOMAINS_AUTO/*; do
 
174
        rdname $dom
 
175
        if test -z $NAMES; then 
 
176
            NAMES=$NM; 
 
177
        else
 
178
            NAMES="$NAMES|$NM"
 
179
        fi
 
180
    done
 
181
}
 
182
 
 
183
parseln()
 
184
{
 
185
    if [[ "$1" =~ "\(domain" ]]; then
 
186
        name=;id=
 
187
    else if [[ "$1" =~ "\(name" ]]; then
 
188
        name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
 
189
    else if [[ "$1" =~ "\(domid" ]]; then
 
190
        id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
 
191
    fi; fi; fi
 
192
 
 
193
    [ -n "$name" -a -n "$id" ] && return 0 || return 1
 
194
}
 
195
 
 
196
is_running()
 
197
{
 
198
    rdname $1
 
199
    RC=1
 
200
    name=;id=
 
201
    while read LN; do
 
202
        parseln "$LN" || continue
 
203
        if test $id = 0; then continue; fi
 
204
        case $name in 
 
205
            ($NM)
 
206
                RC=0
 
207
                ;;
 
208
        esac
 
209
    done < <(xm list -l | grep '(\(domain\|domid\|name\)')
 
210
    return $RC
 
211
}
 
212
 
 
213
start() 
 
214
{
 
215
    if [ -f $LOCKFILE ]; then 
 
216
        echo -e "xendomains already running (lockfile exists)"
 
217
        return; 
 
218
    fi
 
219
 
 
220
    saved_domains=" "
 
221
    if [ "$XENDOMAINS_RESTORE" = "true" ] &&
 
222
       contains_something "$XENDOMAINS_SAVE"
 
223
    then
 
224
        mkdir -p $(dirname "$LOCKFILE")
 
225
        touch $LOCKFILE
 
226
        echo -n "Restoring Xen domains:"
 
227
        saved_domains=`ls $XENDOMAINS_SAVE`
 
228
        for dom in $XENDOMAINS_SAVE/*; do
 
229
            if [ -f $dom ] ; then
 
230
                HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
 
231
                if [ $HEADER = "LinuxGuestRecord" ]; then
 
232
                    echo -n " ${dom##*/}"
 
233
                    XMR=`xm restore $dom 2>&1 1>/dev/null`
 
234
                    #xm restore $dom
 
235
                    if [ $? -ne 0 ]; then
 
236
                        echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR"
 
237
                        rc_failed $?
 
238
                        echo -e '!'
 
239
                    else
 
240
                        # mv $dom ${dom%/*}/.${dom##*/}
 
241
                        rm $dom
 
242
                    fi
 
243
                fi
 
244
            fi
 
245
        done
 
246
        echo -e
 
247
    fi
 
248
 
 
249
    if contains_something "$XENDOMAINS_AUTO"
 
250
    then
 
251
        touch $LOCKFILE
 
252
        echo -n "Starting auto Xen domains:"
 
253
        # We expect config scripts for auto starting domains to be in
 
254
        # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
 
255
 
 
256
        # Create all domains with config files in XENDOMAINS_AUTO.
 
257
        # TODO: We should record which domain name belongs 
 
258
        # so we have the option to selectively shut down / migrate later
 
259
        # If a domain statefile from $XENDOMAINS_SAVE matches a domain name
 
260
        # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't 
 
261
        # restore correctly it requires administrative attention.
 
262
        for dom in $XENDOMAINS_AUTO/*; do
 
263
            echo -n " ${dom##*/}"
 
264
            shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
 
265
            echo $saved_domains | grep -w $shortdom > /dev/null
 
266
            if [ $? -eq 0 ] || is_running $dom; then
 
267
                echo -n "(skip)"
 
268
            else
 
269
                XMC=`xm create --quiet --defconfig $dom`
 
270
                if [ $? -ne 0 ]; then
 
271
                    echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n"
 
272
                    rc_failed $?
 
273
                    echo -e '!'
 
274
                else
 
275
                    usleep $XENDOMAINS_CREATE_USLEEP
 
276
                fi
 
277
            fi
 
278
        done
 
279
    fi
 
280
}
 
281
 
 
282
all_zombies()
 
283
{
 
284
    name=;id=
 
285
    while read LN; do
 
286
        parseln "$LN" || continue
 
287
        if test $id = 0; then continue; fi
 
288
        if test "$state" != "-b---d" -a "$state" != "-----d"; then
 
289
            return 1;
 
290
        fi
 
291
    done < <(xm list -l | grep '(\(domain\|domid\|name\)')
 
292
    return 0
 
293
}
 
294
 
 
295
# Wait for max $XENDOMAINS_STOP_MAXWAIT for xm $1 to finish;
 
296
# if it has not exited by that time kill it, so the init script will
 
297
# succeed within a finite amount of time; if $2 is nonnull, it will
 
298
# kill the command as well as soon as no domain (except for zombies)
 
299
# are left (used for shutdown --all). Third parameter, if any, suppresses
 
300
# output of dots per working state (formatting issues)
 
301
watchdog_xm()
 
302
{
 
303
    if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
 
304
        exit
 
305
    fi
 
306
 
 
307
    usleep 20000
 
308
    for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
 
309
        # exit if xm save/migrate/shutdown is finished
 
310
        PSAX=`ps axlw | grep "xm $1" | grep -v grep`
 
311
        if test -z "$PSAX"; then exit; fi
 
312
        if ! test -n "$3"; then echo -n '.'; fi
 
313
        sleep 1
 
314
        # go to kill immediately if there's only zombies left
 
315
        if all_zombies && test -n "$2"; then break; fi
 
316
    done
 
317
    sleep 1
 
318
    read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
 
319
    # kill xm $1
 
320
    kill $PSPID >/dev/null 2>&1
 
321
    
 
322
    echo -e .
 
323
}
 
324
 
 
325
stop()
 
326
{
 
327
    exec 3>&2 2> /dev/null
 
328
    
 
329
    # Collect list of domains to shut down
 
330
    if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
 
331
        rdnames
 
332
    fi
 
333
    echo -n "Shutting down Xen domains:"
 
334
    name=;id=
 
335
    while read LN; do
 
336
        parseln "$LN" || continue
 
337
        if test $id = 0; then continue; fi
 
338
        echo -n " $name"
 
339
        if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
 
340
            eval "
 
341
            case \"\$name\" in
 
342
                ($NAMES)
 
343
                    # nothing
 
344
                    ;;
 
345
                (*)
 
346
                    echo -e '(skip)'
 
347
                    continue
 
348
                    ;;
 
349
            esac
 
350
            "
 
351
        fi
 
352
        # XENDOMAINS_SYSRQ chould be something like just "s" 
 
353
        # or "s e i u" or even "s e s i u o"
 
354
        # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
 
355
        if test -n "$XENDOMAINS_SYSRQ"; then
 
356
            for sysrq in $XENDOMAINS_SYSRQ; do
 
357
                echo -n "(SR-$sysrq)"
 
358
                XMR=`xm sysrq $id $sysrq 2>&1 1>/dev/null`
 
359
                if test $? -ne 0; then
 
360
                    echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n"
 
361
                    rc_failed $?
 
362
                    echo -n '!'
 
363
                fi
 
364
                # usleep just ignores empty arg
 
365
                usleep $XENDOMAINS_USLEEP
 
366
            done
 
367
        fi
 
368
        if test "$state" = "-b---d" -o "$state" = "-----d"; then
 
369
            echo -n "(zomb)"
 
370
            continue
 
371
        fi
 
372
        if test -n "$XENDOMAINS_MIGRATE"; then
 
373
            echo -n "(migr)"
 
374
            watchdog_xm migrate &
 
375
            WDOG_PID=$!
 
376
            XMR=`xm migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null`
 
377
            if test $? -ne 0; then
 
378
                echo -e "\nAn error occurred while migrating domain:\n$XMR\n"
 
379
                rc_failed $?
 
380
                echo -e '!'
 
381
 
 
382
                kill $WDOG_PID >/dev/null 2>&1
 
383
            else
 
384
                kill $WDOG_PID >/dev/null 2>&1
 
385
                
 
386
                echo -e .
 
387
                usleep 1000
 
388
                continue
 
389
            fi
 
390
        fi
 
391
        if test -n "$XENDOMAINS_SAVE"; then
 
392
            echo -n "(save)"
 
393
            watchdog_xm save &
 
394
            WDOG_PID=$!
 
395
            mkdir -p "$XENDOMAINS_SAVE"
 
396
            XMR=`xm save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null`
 
397
            if test $? -ne 0; then
 
398
                echo -e "\nAn error occurred while saving domain:\n$XMR\n"
 
399
                rc_failed $?
 
400
                echo -e '!'
 
401
                kill $WDOG_PID >/dev/null 2>&1
 
402
            else
 
403
                kill $WDOG_PID >/dev/null 2>&1
 
404
                echo -e .
 
405
                usleep 1000
 
406
                continue
 
407
            fi
 
408
        fi
 
409
        if test -n "$XENDOMAINS_SHUTDOWN"; then
 
410
            # XENDOMAINS_SHUTDOWN should be "--halt --wait"
 
411
            echo -n "(shut)"
 
412
            watchdog_xm shutdown &
 
413
            WDOG_PID=$!
 
414
            XMR=`xm shutdown $id $XENDOMAINS_SHUTDOWN 2>&1 1>/dev/null`
 
415
            if test $? -ne 0; then
 
416
                echo -e "\nAn error occurred while shutting down domain:\n$XMR\n"
 
417
                rc_failed $?
 
418
                echo -e '!'
 
419
            fi
 
420
            kill $WDOG_PID >/dev/null 2>&1
 
421
        fi
 
422
    done < <(xm list -l | grep '(\(domain\|domid\|name\)')
 
423
 
 
424
    # NB. this shuts down ALL Xen domains (politely), not just the ones in
 
425
    # AUTODIR/*
 
426
    # This is because it's easier to do ;-) but arguably if this script is run
 
427
    # on system shutdown then it's also the right thing to do.
 
428
    if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
 
429
        # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
 
430
        echo -n " SHUTDOWN_ALL "
 
431
        watchdog_xm shutdown 1 false &
 
432
        WDOG_PID=$!
 
433
        XMR=`xm shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null`
 
434
        if test $? -ne 0; then
 
435
            echo -e "\nAn error occurred while shutting down all domains: $XMR\n"
 
436
            rc_failed $?
 
437
            echo -e '!'
 
438
        fi
 
439
        kill $WDOG_PID >/dev/null 2>&1
 
440
    fi
 
441
 
 
442
    # Unconditionally delete lock file
 
443
    rm -f $LOCKFILE
 
444
    
 
445
    exec 2>&3
 
446
}
 
447
 
 
448
check_domain_up()
 
449
{
 
450
    name=;id=
 
451
    while read LN; do
 
452
        parseln "$LN" || continue
 
453
        if test $id = 0; then continue; fi
 
454
        case $name in 
 
455
            ($1)
 
456
                return 0
 
457
                ;;
 
458
        esac
 
459
    done < <(xm list -l | grep '(\(domain\|domid\|name\)')
 
460
    return 1
 
461
}
 
462
 
 
463
check_all_auto_domains_up()
 
464
{
 
465
    if ! contains_something "$XENDOMAINS_AUTO"
 
466
    then
 
467
      return 0
 
468
    fi
 
469
    missing=
 
470
    for nm in $XENDOMAINS_AUTO/*; do
 
471
        rdname $nm
 
472
        found=0
 
473
        if check_domain_up "$NM"; then 
 
474
            echo -n " $name"
 
475
        else 
 
476
            missing="$missing $NM"
 
477
        fi
 
478
    done
 
479
    if test -n "$missing"; then
 
480
        echo -n " MISS AUTO:$missing"
 
481
        return 1
 
482
    fi
 
483
    return 0
 
484
}
 
485
 
 
486
check_all_saved_domains_up()
 
487
{
 
488
    if ! contains_something "$XENDOMAINS_SAVE" 
 
489
    then
 
490
      return 0
 
491
    fi
 
492
    missing=`/bin/ls $XENDOMAINS_SAVE`
 
493
    echo -n " MISS SAVED: " $missing
 
494
    return 1
 
495
}
 
496
 
 
497
# This does NOT necessarily restart all running domains: instead it
 
498
# stops all running domains and then boots all the domains specified in
 
499
# AUTODIR.  If other domains have been started manually then they will
 
500
# not get restarted.
 
501
# Commented out to avoid confusion!
 
502
 
 
503
restart()
 
504
{
 
505
    stop
 
506
    start
 
507
}
 
508
 
 
509
reload()
 
510
{
 
511
    restart
 
512
}
 
513
 
 
514
 
 
515
case "$1" in
 
516
    start)
 
517
        start
 
518
        rc_status
 
519
        if test -f $LOCKFILE; then rc_status -v; fi
 
520
        ;;
 
521
 
 
522
    stop)
 
523
        stop
 
524
        rc_status -v
 
525
        ;;
 
526
 
 
527
    restart)
 
528
        restart
 
529
        ;;
 
530
    reload)
 
531
        reload
 
532
        ;;
 
533
 
 
534
    status)
 
535
        echo -n "Checking for xendomains:" 
 
536
        if test ! -f $LOCKFILE; then 
 
537
            rc_failed 3
 
538
        else
 
539
            check_all_auto_domains_up
 
540
            rc_status
 
541
            check_all_saved_domains_up
 
542
            rc_status
 
543
        fi
 
544
        rc_status -v
 
545
        ;;
 
546
 
 
547
    *)
 
548
        echo "Usage: $0 {start|stop|restart|reload|status}"
 
549
        rc_failed 3
 
550
        rc_status -v
 
551
        ;;
 
552
esac
 
553
 
 
554
rc_exit