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