use 'killContext()' instead of invoking 'vkill' manually
[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 -n "$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 -n "$_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 -n "$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         killContext "$ctx" "$1"
191         test -n "$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 -n "$RUNLEVEL_START" || RUNLEVEL_START=3
223             test -n "$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             ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
251             ;;
252
253         (xgentoo)
254             INITCMD_START=( /sbin/rc default  )
255             INITCMD_STOP=(  /sbin/rc shutdown )
256             ;;
257
258         (x) ;;
259         (*) echo "Unknown init-style '$INITSTYLE'; aborting" >&2;
260             exit 1;;
261     esac
262
263     getFileArray INITCMD_START      "$cfgdir"/cmd.start      || :
264     getFileArray INITCMD_STOP       "$cfgdir"/cmd.stop       || :
265     getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
266     getFileArray INITCMD_STOP_SYNC  "$cfgdir"/cmd.stop-sync  || :
267     getFileArray INITCMD_PREPARE    "$cfgdir"/cmd.prepare    || :
268
269     
270     test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
271         INITCMD_START_SYNC=()
272         INITCMD_STOP_SYNC=()
273         _NEED_VSHELPER_SYNC=
274     }
275
276     if vshelper.isEnabled; then
277         vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
278     else
279         _NEED_VSHELPER_SYNC=
280     fi
281 }
282
283 function _generateFlagOptions
284 {
285     local vdir=$1
286
287     CHCONTEXT_FLAG_OPTS=()
288
289     test ! -e "$vdir"/flags || \
290     while read flag; do
291         case x"$flag" in
292             (x|x\#)             ;;
293             (xnamespace)        ;;
294             (xfakeinit)
295                 _IS_FAKEINIT=1
296                 ;;
297             (*)
298                 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
299                 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
300                                       --flag "$flag" )
301                 ;;
302         esac
303     done <"$vdir"/flags
304
305     isAvoidNamespace "$vdir" || {
306         USE_VNAMESPACE=1
307         CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
308     }
309 }
310
311 function _generateChcontextOptions
312 {
313     local vdir=$1
314     local ctx hostname domainname
315     local cap_opts
316     local flag
317
318     {
319         read ctx        <"$vdir"/context        || :
320         ## LEGACY ALERT
321         read hostname   <"$vdir"/uts/nodename   || read hostname   <"$vdir"/hostname   || :
322         read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
323     } 2>/dev/null
324
325     test -z "$S_CONTEXT" || ctx=$S_CONTEXT
326
327     _generateCapabilityOptions "$vdir"
328     _generateFlagOptions       "$vdir"
329
330     CHCONTEXT_OPTS=( $SILENT_OPT \
331                      "${CHCONTEXT_FLAG_OPTS[@]}" \
332                      "${CAP_OPTS[@]}" \
333                      --secure
334                      ${ctx:+--ctx "$ctx"} \
335                      ${hostname:+--hostname "$hostname"} \
336                      ${domainname:+--domainname "$domainname"} )
337
338     OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
339                            ${ctx:+--xid "$ctx"} )
340     ## put '--secure' at front so that it can be overridden
341     OPTS_VATTRIBUTE=( --secure "${OPTS_VATTRIBUTE[@]}" )
342 }
343
344 function _generateScheduleOptions
345 {
346     local vdir=$1
347     local f="$vdir"/schedule
348     test -e "$f" || return 0
349
350     local fill_rate interval tokens tokens_min tokens_max prio_bias
351     {
352         {
353             read fill_rate   && \
354             read interval    && \
355             read tokens      && \
356             read tokens_min  && \
357             read tokens_max  && \
358             read prio_bias   || prio_bias=
359         } <"$f"
360     } 2>/dev/null
361
362     test -n "$prio_bias" || {
363         echo $"Bad content in '$f'; aborting..." >&2
364         false
365     }
366
367     OPTS_VSCHED=( --fill-rate  "$fill_rate"  --interval "$interval" \
368                   --tokens     "$tokens"     --tokens_min "$tokens_min" \
369                   --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
370 }
371
372 function _getInterfaceValue
373 {
374     local _giv_val=$1
375     local _giv_dflt=$2
376     shift 2
377     
378     local _giv_i
379     local _giv_tmp
380
381     for _giv_i; do
382         read _giv_tmp  <"$_giv_i/$_giv_val" && break || :
383     done 2>/dev/null
384
385     : ${_giv_tmp:=$_giv_dflt}
386     eval $_giv_val=\$_giv_tmp
387 }
388
389 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
390 function _transformMask2Prefix
391 {
392     local _tm2p_tmp=$2
393     
394     test -n "$_tm2p_tmp" || {
395         $_MASK2PREFIX "$3" || _tm2p_tmp=$?
396     }
397
398     eval $1=\$_tm2p_tmp
399     return 0
400 }
401
402 function _addInterfaceCmd
403 {
404     eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
405     let ++INTERFACE_CMDS_IDX
406 }
407
408 ## Usage: _generateMac <var> <iface> <ctx>
409 function _generateMac
410 {
411     isNumber "$2" || {
412         echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
413         return 1
414     }
415
416     eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
417 }
418
419 ## Usage: _processSingleInterface <interface-directory>
420 function _processSingleInterface
421 {
422     local iface=$1
423
424     local ip
425     local dev
426     local prefix
427     local mask
428     local bcast
429     local name
430     local scope
431     local mac
432     local extip
433     local up="up"
434
435     _getInterfaceValue ip     '' "$iface"
436     _getInterfaceValue extip  '' "$iface" "$iface/.."
437     _getInterfaceValue dev    '' "$iface" "$iface/.."
438     _getInterfaceValue prefix '' "$iface" "$iface/.."
439     _getInterfaceValue mask   '' "$iface" "$iface/.."
440     _getInterfaceValue bcast  '' "$iface" "$iface/.."
441     _getInterfaceValue name   '' "$iface"
442     _getInterfaceValue scope  '' "$iface" "$iface/.."
443     _getInterfaceValue mac    '' "$iface"
444
445     test -n "$ip" || { echo $"Can not read ip for '$iface'"  >&2; return 1; }
446     test -n "$dev" -o -e "$iface"/nodev || {
447         echo $"No device specified for '$iface'" >&2
448         return 1;
449     }
450
451     test ! -e "$iface"/down || up=
452
453     while true; do
454         _transformMask2Prefix prefix "$prefix" "$mask"
455         INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
456
457         test ! -e "$iface"/nodev   || break
458         ## LEGACY ALERT
459         test ! -e "$iface"/only_ip || break
460
461         case "$dev" in
462             (*.*)
463                 test -d /proc/net/vlan || {
464                     echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers"  >&2
465                     return 1
466                 }
467                 test -f /proc/net/vlan || {
468                     _addInterfaceCmd VCONFIG ${dev/./ }
469                     _addInterfaceCmd IP_ADDR 127.0.0.1/8 broadcast 127.255.255.255 dev "$dev"
470                     _addInterfaceCmd IP_LINK "$dev" $up
471                 }
472                 ;;
473         esac
474
475         if ! test -e "$iface"/indirect; then
476             _addInterfaceCmd IP_ADDR  "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
477             #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
478             _addInterfaceCmd IP_LINK  "$dev" $up
479         elif ! test -n "$ctx"; then
480             echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
481             return 1
482         else
483             test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
484             _addInterfaceCmd MODPROBE dummy "$dev"
485             _addInterfaceCmd IP_LINK  dev dummy0 address "$mac"
486             _addInterfaceCmd NAMEIF   "$dev" "$mac"
487             _addInterfaceCmd IP_ADDR  "$ip${prefix:+/$prefix}" dev "$dev"
488             test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
489         fi
490
491         break
492     done
493 }
494
495 ## Usage: _generateInterfaceOptions <vserver-directory>
496 function _generateInterfaceOptions
497 {
498     local iface
499     local ctx
500
501     test ! -e "$1"/context || read ctx <"$1"/context
502
503     for iface in "$1/interfaces/"*; do
504         test   -d "$iface"          || continue
505         test ! -e "$iface"/disabled || continue
506     
507         _processSingleInterface "$iface"
508     done
509     _HAVE_INTERFACE_OPTIONS=1
510 }
511
512 function enableInterfaces
513 {
514     local i=0
515     declare -a var
516
517     lock "$__LOCKDIR"/vserver.interfaces
518
519     while test $i -lt $INTERFACE_CMDS_IDX; do
520         eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
521         local type=${var[0]}
522         unset var[0]
523
524         set -- "${var[@]}"
525         case "$type" in
526             IPTABLES)   ;; ## TODO
527             MODPROBE)
528                 local mod=$1
529                 local name=$2
530                 shift 2
531                 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
532                 ;;
533             NAMEIF)             $_NAMEIF "$@";;
534             VCONFIG)            $_VCONFIG  add   "$@";;
535             IP_ADDR)            $_IP addr  add   "$@";;
536             IP_ADDR_FLUSH)      $_IP addr  flush "$@";;
537             IP_LINK)            $_IP link  set   "$@";;
538             IP_ROUTE)           $_IP route add   "$@";;
539             *)                  echo "Unknown interface-command type '$type'" >&2; false;;
540         esac
541
542         let ++i
543     done
544
545     unlock 1
546 }
547
548 function disableInterfaces
549 {
550     test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
551
552     local i=$INTERFACE_CMDS_IDX
553     declare -a var
554
555     lock "$__LOCKDIR"/vserver.interfaces
556     
557     while test $i -gt 0; do
558         let --i || :
559
560         eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
561         local type=${var[0]}
562         unset var[0]
563         
564         set -- "${var[@]}"
565         case "$type" in
566             IPTABLES)           ;; ## TODO
567             MODPROBE)           $_RMMOD "${2:-$1}";;
568             NAMEIF)             ;;
569             VCONFIG)            $_VCONFIG  rem "$@";;
570             IP_ADDR)            $_IP addr  del "$@";;
571             IP_ADDR_FLUSH)      ;;
572             IP_LINK)            ;; ## Ignore the link-down command for now
573             IP_ROUTE)           $_IP route del "$@";;
574             *)                  echo "Unknown interface-command type '$type'" >&2; false;;
575         esac
576     done
577
578     unlock 1
579 }
580
581 ## Usage: prepareInit <vserver-directory>
582 function prepareInit
583 {
584     pushd "$1/vdir" >/dev/null
585     case "$INITSTYLE" in
586         sysv)
587             { find var/run  ! -type d -print0; \
588               find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_RM
589             ;;
590         plain)
591             $_CHROOT_RM .autofsck forcefsck 2>/dev/null || :
592             : | $_CHROOT_CAT fastboot       2>/dev/null || :
593             ;;
594         minit)
595             ;;
596     esac
597     "${INITCMD_PREPARE[@]}"
598     popd >/dev/null
599 }
600
601 ## Usage: prepareInit <vserver-directory>
602 function prepareStop
603 {
604     pushd "$1/vdir" >/dev/null
605     case "$INITSTYLE" in
606         (sysv)
607             export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
608             ;;
609     esac
610     "${STOPCMD_PREPARE[@]}"
611     popd >/dev/null
612 }
613
614
615 function generateOptions
616 {
617     _generateInterfaceOptions  "$1"
618     test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1" 
619     _generateNiceCommand       "$1"
620     _generateInitOptions       "$1"
621     _generateChcontextOptions  "$1"
622     _generateScheduleOptions   "$1"
623
624     if test -n "$_IS_FAKEINIT"; then
625         CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
626         OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
627     fi
628 }
629
630 function _mountVserverInternal
631 {
632     local fstab="$1"
633     test -e "$fstab" || return 0
634     shift
635
636     pushd "$vdir" >/dev/null
637     "$@" $_SECURE_MOUNT -a --chroot --fstab "$fstab" --rootfs no
638     popd >/dev/null
639 }
640
641 function mountRootFS
642 {
643     local cfgdir=$1
644     local vdir=$1/vdir
645     local fstab="$cfgdir"/fstab
646
647     test -e "$fstab" || return 0
648     pushd "$vdir" >/dev/null
649     $_SECURE_MOUNT -a --chroot --fstab "$fstab" --rootfs only -n
650     popd >/dev/null
651 }
652
653 function mountVserver
654 {
655     local cfgdir=$1
656     local ns_opt=$2
657     local vdir=$1/vdir
658     local mtab_src
659
660     test -e "$cfgdir"/fstab -o \
661          -e "$cfgdir"/fstab.local -o \
662          -e "$cfgdir"/fstab.remote || return 0
663
664     findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
665     
666     pushd "$vdir" >/dev/null
667     $_CHROOT_CAT /etc/mtab <"$mtab_src"
668     popd >/dev/null
669
670     test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
671
672     test -z "$NAMESPACE_CLEANUP" || isAvoidNamespace "$cfgdir" || \
673         $_VNAMESPACE --cleanup
674
675     _mountVserverInternal "$cfgdir"/fstab
676     _mountVserverInternal "$cfgdir"/fstab.local
677     _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
678
679     isAvoidNamespace "$cfgdir" || \
680         $_SECURE_MOUNT --rbind -n "$vdir" "/"
681 }
682
683 function _umountVserverInternal
684 {
685     local fstab="$1"
686     test -e "$fstab" || return 0
687     shift
688
689     $_TAC "$fstab" | {
690         is_ok=1
691         while read src dst tmp; do
692             test -n "$tmp" || continue
693             case x"$src" in
694                 (x\#*)  continue;;
695             esac
696
697         
698             "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
699         done
700         test -n "$is_ok"
701     }
702 }
703
704 function umountVserver
705 {
706     local cfgdir=$1
707     local vdir=$1/vdir
708     local is_ok=1
709
710     isAvoidNamespace "$cfgdir"    || return 0
711     test -e "$cfgdir"/fstab -o \
712          -e "$cfgdir"/fstab.local || return 0
713     test -n "$_HAVE_CHBIND_OPTIONS"  || _generateChbindOptions "$cfgdir"
714     
715     pushd "$vdir/" >/dev/null || return 1
716         _umountVserverInternal  "$cfgdir"/fstab.local                              || is_ok=
717         _umountVserverInternal  "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
718     popd >/dev/null           || return 1
719
720     test -n "$is_ok"
721 }
722
723 ## Usage: waitForSync <vserver> <vshelper-fifo-varname>
724 function initSync
725 {
726     local _is_meth=sync
727     test -n "$_NEED_VSHELPER_SYNC" || _is_meth=async
728
729     vshelper.initSync "$1" "$2" "$_is_meth"
730 }
731
732 ## Usage: waitForSync <vserver> [<vshelper-fifo>]
733 function waitForSync
734 {
735     local cfgdir=$1
736     local fifo=$2
737     
738     if test -n "$_NEED_VSHELPER_SYNC"; then
739         $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
740             warning $"\
741 A timeout or other error occured while waiting for the synchronization
742 signal from vserver '$VSERVER_NAME'.
743 The vserver will be killed nevertheless..."
744     elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
745         "${INITCMD_STOP_SYNC[@]}" || \
746             warning $"\
747 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
748 will be killed nevertheless..."
749     fi
750
751     test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
752         sleep 1
753 }
754
755 function _sourceWrap
756 {
757     local vdir name flavor start i already_handled base
758     . "$@"
759 }
760
761 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
762 function execScriptlets
763 {
764     declare -r vdir=$1
765     declare -r name=$2
766     declare -r flavor=$3
767     local base i
768
769     for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
770         local   DONT_SKIP_DEFAULTS=
771         local   already_handled=
772         
773         for i in "$base/$flavor" "$base/$flavor.d"/*; do
774             test -f "$i" -a -r "$i" || continue
775             already_handled=1
776             local start=
777             test -x "$i" || start=_sourceWrap
778             $start "$i" "$flavor" "$name"
779         done
780
781         test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
782     done
783 }
784
785
786 function sanityCheck
787 {
788     declare -r cfgdir=$1
789
790     ! test -e "$cfgdir"/fstab.local ||
791         warning $"\
792 WARNING: 'fstab' will *not* be executed in the network context of the
793   vserver anymore. Therefore, 'fstab.local' has the same functionality
794   and is obsoleted. When you need the old behaviour, put the mounts
795   into 'fstab.remote'"
796
797     ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
798         warning $"\
799 WARNING: The hostname is now configured in 'uts/nodename' but not in
800   'hostname'."
801
802     ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
803         warning $"\
804 WARNING: The domainname is now configured in 'uts/domainname' but not
805   in 'domainname'." >&2
806
807   
808     local i
809     for i in "$cfgdir"/interfaces/*/only_ip; do
810         if test -e "$i"; then
811             local iface
812             iface=${i##$cfgdir/interfaces/}
813             iface=${iface%%/only_ip}
814             warning $"\
815 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
816   'nodev' instead of"
817         fi
818     done
819
820     find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
821
822     vshelper.doSanityCheck
823
824     $_VSERVER_INFO - VERIFYCAP ||
825         panic $"capabilities are not enabled in kernel-setup"
826 }