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