implemented support for default-scriptlets (inspired by ideas of
[util-vserver.git] / util-vserver / scripts / vserver.functions
1 # $Id$  --*- sh -*--
2
3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 #  
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
8 #  
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #  
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 ## Expected env:
19 #  $VSERVER_DIR   ... path to vserver-cfg dir
20 #  $VSERVER_NAME  ... name of vserver
21
22 declare -a NICE_CMD=()
23 declare -a CHBIND_OPTS=()
24 declare -a CAP_OPTS=()
25 declare -a CHCONTEXT_INIT_OPTS=()
26 declare -a CHCONTEXT_FLAG_OPTS=()
27 declare -a CHCONTEXT_OPTS=()
28 declare -a CAPCHROOT_OPTS=()
29 declare -a INTERFACES=()
30
31 declare -a INITCMD_START=()
32 declare -a INITCMD_START_SYNC=()
33 declare -a INITCMD_STOP=()
34 declare -a INITCMD_STOP_SYNC=()
35 declare -a INITCMD_PREPARE=()
36 declare -a INITKILL_SEQ=()
37 declare -a ENTER_SHELL=()
38
39 declare -a OPTS_VCONTEXT_CREATE=()
40 declare -a OPTS_VCONTEXT_MIGRATE=()
41 declare -a OPTS_VATTRIBUTE=()
42 declare -a OPTS_VSCHED=()
43
44 declare -a VSERVER_EXTRA_CMDS=()
45
46 VSHELPER_SYNC_TIMEOUT=30
47 USE_VNAMESPACE=
48 INTERFACE_CMDS_IDX=0
49 _HAVE_INTERFACE_OPTIONS=
50 _HAVE_CHBIND_OPTIONS=
51 _NEED_VSHELPER_SYNC=
52 _IS_FAKEINIT=
53
54 INITSTYLE=sysv
55
56 S_CONTEXT=
57
58 SILENT_OPT=
59
60 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
61
62 if test -e "$VSERVER_DIR"/noisy -o "$OPTION_VERBOSE"; then
63     SILENT_OPT=
64 else
65     SILENT_OPT='--silent'
66 fi
67
68 function _generateChbindOptions
69 {
70     local vdir="$1"
71     local i
72     local bcast=
73
74     test "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
75
76     local f=$vdir/interfaces/bcast
77     getFileValue bcast "$f"
78     
79     CHBIND_OPTS=( $SILENT_OPT ${bcast:+--bcast "$bcast"} )
80
81     for i in "${INTERFACES[@]}"; do
82         CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
83     done
84
85     _HAVE_CHBIND_OPTIONS=1
86 }
87
88 function _generateNiceCommand
89 {
90     local vdir=$1
91     local nice
92
93     test -r "$vdir/nice" || return 0;
94     read nice <"$vdir"/nice
95
96     NICE_CMD=( $_NICE -$nice )
97 }
98
99 function _generateCCapabilityOptions
100 {
101     local vdir=$1
102     local cap
103     local f="$vdir"/ccapabilities
104     
105     test -e "$f" || return 0
106     while read cap; do
107         case x"$cap" in
108             (x|x\#)     ;;
109             (*)         OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --ccap "$cap" );;
110         esac
111     done <"$f"
112 }
113
114 function _generateBCapabilityOptions
115 {
116     local vdir=$1
117     local cap
118     local f="$vdir"/bcapabilities
119     
120     test -e "$f" || return 0
121     while read cap; do
122         case x"$cap" in
123             (x|x\#)     ;;
124             (*)         OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --bcap "$cap" );;
125         esac
126     done <"$f"
127 }
128
129 function _generateCapabilityOptions
130 {
131     local vdir=$1
132     local cap
133
134     _generateBCapabilityOptions "$vdir"
135     _generateCCapabilityOptions "$vdir"
136     
137     test -e "$vdir"/capabilities || return 0
138
139     CAP_OPTS=()
140     CAPCHROOT_OPTS=()
141
142     while read cap; do
143         case x"$cap" in
144             (x|x\#)     ;;
145             (!CAP_SYSCHROOT)
146                 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
147                 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
148                 ;;
149             (*)
150                 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
151                 ;;
152         esac
153     done <"$vdir"/capabilities
154 }
155
156 function getEnterShell
157 {
158     local vdir=$1
159
160     ENTER_SHELL=()
161     
162     getFileValue ENTER_SHELL     "$vdir"/shell
163     
164     test "$ENTER_SHELL" || {
165         local i
166         for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
167             set -- $i
168             test -x "$vdir/vdir/$1" || continue
169             ENTER_SHELL=( "$@" )
170             break
171         done
172     }
173 }
174
175 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
176 function sendKillSequence
177 {
178     local ctx=$1
179     local wait=
180     shift
181
182     while isCtxRunning "$ctx"; do
183         test -z "$wait" || sleep "$wait"
184         
185         $_VKILL -c "$ctx" ${1:+-s "$1"}
186         test "$2" || break
187         wait="$2"
188         shift 2
189     done
190 }
191
192 function _generateInitOptions
193 {
194     local vdir=$1
195     local cfgdir=$vdir/apps/init
196     local runlevel_start
197     local runlevel_stop
198     local i f
199
200     INITCMD_START=()
201     INITCMD_STOP=()
202     INITCMD_START_SYNC=()
203     INITCMD_STOP_SYNC=()
204     INITCMD_PREPARE=()
205
206     INITKILL_SEQ=( 15 5 9 )
207     CHCONTEXT_INIT_OPTS=()
208
209
210     getFileValue INITSTYLE      "$cfgdir"/style
211     getFileValue runlevel_start "$cfgdir"/runlevel
212     getFileValue runlevel_start "$cfgdir"/runlevel.start
213     getFileValue runlevel_stop  "$cfgdir"/runlevel.stop
214     getFileArray INITKILL_SEQ   "$cfgdir"/killseq || :
215
216     case x"$INITSTYLE" in
217         (xsysv)
218             test "$runlevel_start" || runlevel_start=3
219             test "$runlevel_stop"  || runlevel_stop=6
220
221             for i in /etc/init.d/rc /etc/rc.d/rc; do
222                 test -x "$vdir/vdir/$i" || continue
223                 INITCMD_START=( "$i" "$runlevel_start" )
224                 INITCMD_STOP=(  "$i" "$runlevel_stop"  )
225             done
226             INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$runlevel_start" /var/run/utmp )
227             ;;
228             
229         (xplain)
230             INITCMD_START=( /sbin/init )
231             INITCMD_STOP=(  /sbin/init )
232             _IS_FAKEINIT=1
233             _NEED_VSHELPER_SYNC=1
234             test -z "$runlevel_start" || INITCMD_START=( "${INITCMD_START[@]}" "$runlevel_start" )
235             test -z "$runlevel_stop"  || INITCMD_STOP=(  "${INITCMD_STOP[@]}"  "$runlevel_stop"  )
236             ;;
237             
238         (xminit)
239             INITCMD_START=( /sbin/minit-start )
240             INITCMD_STOP=(  /sbin/minit-stop  )
241             _IS_FAKEINIT=1
242             INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
243             _NEED_VSHELPER_SYNC=1
244             test -z "$runlevel_start" || INITCMD_START=( "${INITCMD_START[@]}" "$runlevel_start" )
245             test -z "$runlevel_stop"  || INITCMD_STOP=(  "${INITCMD_STOP[@]}"  "$runlevel_stop"  )
246             ;;
247
248         (xgentoo)
249             INITCMD_START=( /sbin/rc default  )
250             INITCMD_STOP=(  /sbin/rc shutdown )
251             ;;
252
253         (x) ;;
254         (*) echo "Unknown init-style '$INITSTYLE'; aborting" >&2;
255             exit 1;;
256     esac
257
258     getFileArray INITCMD_START      "$cfgdir"/cmd.start      || :
259     getFileArray INITCMD_STOP       "$cfgdir"/cmd.stop       || :
260     getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
261     getFileArray INITCMD_STOP_SYNC  "$cfgdir"/cmd.stop-sync  || :
262     getFileArray INITCMD_PREPARE    "$cfgdir"/cmd.prepare    || :
263
264     
265     test "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
266         INITCMD_START_SYNC=()
267         INITCMD_STOP_SYNC=()
268         _NEED_VSHELPER_SYNC=
269     }
270
271     if vshelper.isEnabled; then
272         vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
273     else
274         _NEED_VSHELPER_SYNC=
275     fi
276 }
277
278 function _generateFlagOptions
279 {
280     local vdir=$1
281
282     CHCONTEXT_FLAG_OPTS=()
283
284     test ! -e "$vdir"/flags || \
285     while read flag; do
286         case x"$flag" in
287             (x|x\#)             ;;
288             (xnamespace)        ;;
289             (xfakeinit)
290                 _IS_FAKEINIT=1
291                 ;;
292             (*)
293                 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
294                 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
295                                       --flag "$flag" )
296                 ;;
297         esac
298     done <"$vdir"/flags
299
300     isAvoidNamespace "$vdir" || {
301         USE_VNAMESPACE=1
302         CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
303     }
304 }
305
306 function _generateChcontextOptions
307 {
308     local vdir=$1
309     local ctx hostname domainname
310     local cap_opts
311     local flag
312
313     {
314         read ctx        <"$vdir"/context        || :
315         ## LEGACY ALERT
316         read hostname   <"$vdir"/uts/nodename   || read hostname   <"$vdir"/hostname   || :
317         read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
318     } 2>/dev/null
319
320     ## LEGACY ALERT
321     test \( ! -e "$vdir"/hostname   -o -e "$vdir"/uts/nodename   \) -a \
322          \( ! -e "$vdir"/domainname -o -e "$vdir"/uts/domainname \) || {
323         echo $"\
324 The hostname is now configured in 'uts/nodename' but not in 'hostname' anymore;
325 the old way is not supported when using 2.6 kernel patches so it is strongly
326 recommended to move these files.
327
328 The same applies to 'domainname' vs. 'uts/domainname'." >&2
329     }
330
331     test -z "$S_CONTEXT" || ctx=$S_CONTEXT
332
333     _generateCapabilityOptions "$vdir"
334     _generateFlagOptions       "$vdir"
335
336     CHCONTEXT_OPTS=( $SILENT_OPT \
337                      "${CHCONTEXT_FLAG_OPTS[@]}" \
338                      "${CAP_OPTS[@]}" \
339                      --secure
340                      ${ctx:+--ctx "$ctx"} \
341                      ${hostname:+--hostname "$hostname"} \
342                      ${domainname:+--domainname "$domainname"} )
343
344     OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
345                            ${ctx:+--xid "$ctx"} )
346     ## put '--secure' at front so that it can be overridden
347     OPTS_VATTRIBUTE=( --secure "${OPTS_VATTRIBUTE[@]}" )
348 }
349
350 function _generateScheduleOptions
351 {
352     local vdir=$1
353     local f="$vdir"/schedule
354     test -e "$f" || return 0
355
356     local fill_rate interval tokens tokens_min tokens_max cpu_mask
357     {
358         {
359             read fill_rate   && \
360             read interval    && \
361             read tokens      && \
362             read tokens_min  && \
363             read tokens_max  && \
364             read cpu_mask    || cpu_mask=
365         } <"$f"
366     } 2>/dev/null
367
368     test "$cpu_mask" || {
369         echo $"Bad content in '$f'; aborting..." >&2
370         false
371     }
372
373     OPTS_VSCHED=( --fill-rate  "$fill_rate"  --interval "$interval" \
374                   --tokens     "$tokens"     --tokens_min "$tokens_min" \
375                   --tokens_max "$tokens_max" --cpu_mask "$cpu_mask" )
376 }
377
378 function _getInterfaceValue
379 {
380     local val=$1
381     local dflt=$2
382     shift 2
383     
384     local i
385     local tmp
386
387     for i; do
388         read tmp  <"$i/$val" && break || :
389     done 2>/dev/null
390
391     : ${tmp:=$dflt}
392     eval $val=\$tmp
393 }
394
395 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
396 function _transformMask2Prefix
397 {
398     local tmp=$2
399     
400     test "$tmp" || {
401         $_MASK2PREFIX "$3" || tmp=$?
402     }
403
404     eval $1=\$tmp
405     return 0
406 }
407
408 function _addInterfaceCmd
409 {
410     eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
411     let ++INTERFACE_CMDS_IDX
412 }
413
414 ## Usage: _generateMac <var> <iface> <ctx>
415 function _generateMac
416 {
417     isNumber "$2" || {
418         echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
419         return 1
420     }
421
422     eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
423 }
424
425 ## Usage: _processSingleInterface <interface-directory>
426 function _processSingleInterface
427 {
428     local iface=$1
429
430     local ip
431     local dev
432     local prefix
433     local mask
434     local bcast
435     local name
436     local scope
437     local mac
438     local extip
439     local up="up"
440
441     _getInterfaceValue ip     '' "$iface"
442     _getInterfaceValue extip  '' "$iface" "$iface/.."
443     _getInterfaceValue dev    '' "$iface" "$iface/.."
444     _getInterfaceValue prefix '' "$iface" "$iface/.."
445     _getInterfaceValue mask   '' "$iface" "$iface/.."
446     _getInterfaceValue bcast  '' "$iface" "$iface/.."
447     _getInterfaceValue name   '' "$iface"
448     _getInterfaceValue scope  '' "$iface" "$iface/.."
449     _getInterfaceValue mac    '' "$iface"
450
451     test "$ip" || { echo $"Can not read ip for '$iface'"  >&2; return 1; }
452
453     test ! -e "$iface"/only_ip || {
454         ## LEGACY ALERT
455         echo $"The 'only_ip' flag for interface '$iface' is deprecated; use 'nodev' instead of" >&2
456         unset dev
457     }
458     test ! -e "$iface"/nodev   || unset dev
459     test ! -e "$iface"/down    || up=
460     
461     if test "$dev"; then
462         _transformMask2Prefix prefix "$prefix" "$mask"
463
464         case "$dev" in
465             (*.*)
466                 test -d /proc/net/vlan || {
467                     echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers"  >&2
468                     return 1
469                 }
470                 test -f /proc/net/vlan || {
471                     _addInterfaceCmd VCONFIG "${dev/./ }"
472                     _addInterfaceCmd IP_ADDR 127.0.0.1/8 broadcast 127.255.255.255 dev "$dev"
473                     _addInterfaceCmd IP_LINK "$dev" $up
474                 }
475                 ;;
476         esac
477
478         if ! test -e "$iface"/indirect; then
479             _addInterfaceCmd IP_ADDR  "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
480             #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
481             _addInterfaceCmd IP_LINK  "$dev" $up
482         elif ! test "$ctx"; then
483             echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
484             return 1
485         else
486             test "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
487             _addInterfaceCmd MODPROBE dummy "$dev"
488             _addInterfaceCmd IP_LINK  dev dummy0 address "$mac"
489             _addInterfaceCmd NAMEIF   "$dev" "$mac"
490             _addInterfaceCmd IP_ADDR  "$ip${prefix:+/$prefix}" dev "$dev"
491             test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
492         fi
493         INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
494     fi
495 }
496
497 ## Usage: _generateInterfaceOptions <vserver-directory>
498 function _generateInterfaceOptions
499 {
500     local iface
501     local ctx
502
503     test ! -e "$1"/context || read ctx <"$1"/context
504
505     for iface in "$1/interfaces/"*; do
506         test   -d "$iface"          || continue
507         test ! -e "$iface"/disabled || continue
508     
509         _processSingleInterface "$iface"
510     done
511     _HAVE_INTERFACE_OPTIONS=1
512 }
513
514 function enableInterfaces
515 {
516     local i=0
517     declare -a var
518
519     lock "$LOCKDIR"/vserver.interfaces
520
521     while test $i -lt $INTERFACE_CMDS_IDX; do
522         eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
523         local type=${var[0]}
524         unset var[0]
525
526         set -- "${var[@]}"
527         case "$type" in
528             IPTABLES)   ;; ## TODO
529             MODPROBE)
530                 local mod=$1
531                 local name=$2
532                 shift 2
533                 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
534                 ;;
535             NAMEIF)             $_NAMEIF "$@";;
536             VCONFIG)            $_VCONFIG  add   "$@";;
537             IP_ADDR)            $_IP addr  add   "$@";;
538             IP_ADDR_FLUSH)      $_IP addr  flush "$@";;
539             IP_LINK)            $_IP link  set   "$@";;
540             IP_ROUTE)           $_IP route add   "$@";;
541             *)                  echo "Unknown interface-command type '$type'" >&2; false;;
542         esac
543
544         let ++i
545     done
546
547     unlock 1
548 }
549
550 function disableInterfaces
551 {
552     test "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
553
554     local i=$INTERFACE_CMDS_IDX
555     declare -a var
556
557     lock "$LOCKDIR"/vserver.interfaces
558     
559     while test $i -gt 0; do
560         let --i || :
561
562         eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
563         local type=${var[0]}
564         unset var[0]
565         
566         set -- "${var[@]}"
567         case "$type" in
568             IPTABLES)           ;; ## TODO
569             MODPROBE)           $_RMMOD "${2:-$1}";;
570             NAMEIF)             ;;
571             VCONFIG)            $_VCONFIG  rem "$@";;
572             IP_ADDR)            $_IP addr  del "$@";;
573             IP_ADDR_FLUSH)      ;;
574             IP_LINK)            ;; ## Ignore the link-down command for now
575             IP_ROUTE)           $_IP route del "$@";;
576             *)                  echo "Unknown interface-command type '$type'" >&2; false;;
577         esac
578     done
579
580     unlock 1
581 }
582
583 ## Usage: prepareInit <vserver-directory>
584 function prepareInit
585 {
586     pushd "$1/vdir" >/dev/null
587     case "$INITSTYLE" in
588         sysv)
589             { find var/run  ! -type d -print0; \
590               find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_RM
591             ;;
592         minit)
593             ;;
594     esac
595     "${INITCMD_PREPARE[@]}"
596     popd >/dev/null
597 }
598
599 function generateOptions
600 {
601     _generateInterfaceOptions  "$1"
602     test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1" 
603     _generateNiceCommand       "$1"
604     _generateInitOptions       "$1"
605     _generateChcontextOptions  "$1"
606     _generateScheduleOptions   "$1"
607
608     if test "$_IS_FAKEINIT"; then
609         CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
610         OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --fakeinit --disconnect )
611     fi
612 }
613
614 function _mountVserverInternal
615 {
616     local fstab="$1"
617     test -e "$fstab" || return 0
618     shift
619     
620     "$@" $_SECURE_MOUNT -a --chroot "$vdir" --fstab "$fstab"
621 }
622
623 function mountVserver
624 {
625     local cfgdir=$1
626     local ns_opt=$2
627     local vdir=$1/vdir
628     local mtab_src
629
630     test -e "$cfgdir"/fstab -o \
631          -e "$cfgdir"/fstab.local || return 0
632
633     findObject -r mtab_src "$vdir"/apps/init/mtab "$CONFDIR"/.defaults/init/mtab "$PKGLIBDEFAULTDIR"/mtab /dev/null
634     
635     pushd "$vdir" >/dev/null
636     $_CHROOT_CAT /etc/mtab <"$mtab_src"
637     popd >/dev/null
638
639     test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
640
641     test -z "$NAMESPACE_CLEANUP" || isAvoidNamespace "$cfgdir" || \
642         $_VNAMESPACE --cleanup
643
644     _mountVserverInternal "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}"
645     _mountVserverInternal "$cfgdir"/fstab.local
646
647     isAvoidNamespace "$cfgdir" || \
648         $_SECURE_MOUNT --rbind -n "$vdir" "/"
649 }
650
651 function _umountVserverInternal
652 {
653     local fstab="$1"
654     test -e "$fstab" || return 0
655     shift
656
657     tac "$fstab" | {
658         is_ok=1
659         while read src dst tmp; do
660             test "$tmp" || continue
661             case x"$src" in
662                 (x\#*)  continue;;
663             esac
664
665         
666             "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
667         done
668         test "$is_ok"
669     }
670 }
671
672 function umountVserver
673 {
674     local cfgdir=$1
675     local vdir=$1/vdir
676     local is_ok=1
677
678     isAvoidNamespace "$cfgdir"    || return 0
679     test -e "$cfgdir"/fstab -o \
680          -e "$cfgdir"/fstab.local || return 0
681     test "$_HAVE_CHBIND_OPTIONS"  || _generateChbindOptions "$cfgdir"
682     
683     pushd "$vdir/" >/dev/null || return 1
684         _umountVserverInternal  "$cfgdir"/fstab.local                              || is_ok=
685         _umountVserverInternal  "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
686     popd >/dev/null           || return 1
687
688     test "$is_ok"
689 }
690
691 ## Usage: waitForSync <vserver> <vshelper-fifo-varname>
692 function initSync
693 {
694     test -z "$_NEED_VSHELPER_SYNC" || vshelper.initSync "$1" "$2"
695 }
696
697 ## Usage: waitForSync <vserver> [<vshelper-fifo>]
698 function waitForSync
699 {
700     local cfgdir=$1
701     local fifo=$2
702     
703     if test "$_NEED_VSHELPER_SYNC"; then
704         $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
705             warning $"\
706 A timeout or other error occured while waiting for the synchronization
707 signal from vserver '$VSERVER_NAME'.
708 The vserver will be killed nevertheless..."
709     elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
710         "${INITCMD_STOP_SYNC[@]}" || \
711             warning $"\
712 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
713 will be killed nevertheless..."
714     fi
715
716     test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
717         sleep 1
718 }
719
720 function _sourceWrap
721 {
722     local vdir name flavor start i
723     . "$@"
724 }
725
726 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
727 function execScriptlets
728 {
729     local vdir=$1
730     local name=$2
731     local flavor=$3
732     local start=
733     local base i
734     
735
736     for base in "$vdir"/scripts "$CONFDIR"/.defaults/scripts; do
737         local   DONT_SKIP_DEFAULTS=
738         local   already_handled=
739         
740         for i in "$base/$flavor" "$base/$flavor.d"/*; do
741             test -f "$i" -a -r "$i" || continue
742             already_handled=1
743             test -x "$i" || start=_sourceWrap
744             $start "$i" "$flavor" "$name"
745         done
746
747         test -z "$already_handled" -o "$DONT_SKIP_DEFAULTS" || break
748     done
749 }