3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
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.
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.
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.
19 # $VSERVER_DIR ... path to vserver-cfg dir
20 # $VSERVER_NAME ... name of vserver
22 declare -a NICE_CMD=()
23 declare -a CHBIND_CMD=()
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=()
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=()
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 declare -a OPTS_ENV=()
46 declare -a OPTS_VTAG_CREATE=()
47 declare -a OPTS_VTAG_ENTER=()
48 declare -a OPTS_VMEMCTRL=()
50 declare -a STOPCMD_PREPARE=()
52 declare -a VSERVER_EXTRA_CMDS=()
55 VSHELPER_SYNC_TIMEOUT=30
60 _HAVE_INTERFACE_OPTIONS=
71 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
73 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
79 function _readFileToArray
86 test -e "$_rfta_f" || return 0
87 while read _rfta_v; do
90 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
95 function _generateChbindOptions
103 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
105 local f="$vdir"/interfaces/bcast
106 getFileValue bcast "$f"
107 f="$vdir"/interfaces/lback
108 getFileValue lback "$f"
110 getFileValue nid "$vdir/ncontext" "$vdir/context"
112 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${nid:+--nid "$nid"}
113 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
116 for i in "${INTERFACES[@]}"; do
117 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
120 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
121 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
123 _HAVE_CHBIND_OPTIONS=1
126 function _generateNiceCommand
130 local current_nice=`$_NICE`
132 test -r "$vdir/nice" && read nice <"$vdir"/nice
134 let nice=$nice-$current_nice || :
135 NICE_CMD=( $_NICE -n $nice )
139 function _generatePersonalityOptions
142 local f="$vdir"/personality
145 test -s "$f" || return 0
154 (*) flags=$flags$delim$tmp
161 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
162 --personality-type "$type"
163 ${flags:+--personality-flags "$flags"} )
166 function _generateCCapabilityOptions
170 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
173 function _generateBCapabilityOptions
177 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
180 function _generateCapabilityOptions
185 _generateBCapabilityOptions "$vdir"
186 _generateCCapabilityOptions "$vdir"
188 test -e "$vdir"/capabilities || return 0
197 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
198 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
201 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
204 done <"$vdir"/capabilities
207 function getEnterShell
214 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
216 test -n "$ENTER_SHELL" || {
218 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
220 test -x "$vdir/vdir/$1" || continue
227 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
228 function sendKillSequence
234 while isCtxRunning "$ctx"; do
235 test -z "$wait" || sleep "$wait"
237 killContext "$ctx" "$1"
238 test -n "$2" || break
244 function _generateInitOptions
247 local cfgdir=$vdir/apps/init
252 INITCMD_START_SYNC=()
257 INITKILL_SEQ=( 15 5 9 )
258 CHCONTEXT_INIT_OPTS=()
261 test x"$INITSTYLE" = xrescue || \
262 getFileValue INITSTYLE "$cfgdir"/style
263 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
264 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
265 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
266 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
268 findFile _gio_env "$cfgdir"/environment \
269 "$__CONFDIR"/.defaults/apps/init/environment \
270 "$__PKGLIBDEFAULTDIR"/environment
271 getFileArray OPTS_ENV "$_gio_env" || :
273 case x"$INITSTYLE" in
275 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
276 INITCMD_STOP=( /sbin/killall5 )
280 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
281 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
283 for i in /etc/init.d/rc /etc/rc.d/rc; do
284 test -x "$vdir/vdir/$i" || continue
285 INITCMD_START=( "$i" "$RUNLEVEL_START" )
286 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
288 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
289 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
290 if test -n "$OPTION_DEBUG_SYSV"; then
291 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
292 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
297 INITCMD_START=( /sbin/init )
298 INITCMD_STOP=( /sbin/init )
300 _NEED_VSHELPER_SYNC=1
301 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
302 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
306 INITCMD_START=( /sbin/minit-start )
307 INITCMD_STOP=( /sbin/minit-stop )
309 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
310 _NEED_VSHELPER_SYNC=1
311 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
312 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
313 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
317 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
319 INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
320 INITCMD_STOP=( env -i TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
321 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
325 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
328 if test x"$INITSTYLE" != xrescue; then
329 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
330 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
331 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
332 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
333 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
336 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
337 INITCMD_START_SYNC=()
342 if vshelper.isEnabled; then
343 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
349 function _generateFlagOptions
353 CHCONTEXT_FLAG_OPTS=()
355 test ! -e "$vdir"/flags || \
364 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
365 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
371 isAvoidNamespace "$vdir" || {
373 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
377 function _generateChcontextOptions
380 local ctx hostname domainname
385 read ctx <"$vdir"/context || :
387 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
388 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
391 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
393 _generateCapabilityOptions "$vdir"
394 _generateFlagOptions "$vdir"
396 CHCONTEXT_OPTS=( $SILENT_OPT \
397 "${CHCONTEXT_FLAG_OPTS[@]}" \
400 ${ctx:+--ctx "$ctx"} \
401 ${hostname:+--hostname "$hostname"} \
402 ${domainname:+--domainname "$domainname"} )
404 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
405 ${ctx:+--xid "$ctx"} )
406 ## put '--secure' at front so that it can be overridden
407 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
410 function _generateScheduleOptions
413 if test -d "$vdir"/sched; then
414 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
418 local f="$vdir"/schedule
419 test -e "$f" || return 0
421 local fill_rate interval tokens tokens_min tokens_max prio_bias
429 read prio_bias || prio_bias=
433 test -n "$prio_bias" || {
434 echo $"Bad content in '$f'; aborting..." >&2
438 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
439 --tokens "$tokens" --tokens_min "$tokens_min" \
440 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
443 function _getInterfaceValue
453 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
456 : ${_giv_tmp:=$_giv_dflt}
457 eval $_giv_val=\$_giv_tmp
460 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
461 function _transformMask2Prefix
465 test -n "$_tm2p_tmp" || {
466 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
473 function _addInterfaceCmd
475 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
476 let ++INTERFACE_CMDS_IDX
479 ## Usage: _generateMac <var> <iface> <ctx>
480 function _generateMac
483 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
487 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
490 function _getVLANInfo
495 creation of VLAN_PLUS_VID devices is not supported; please create them
496 before starting the vserver and use the 'nodev' flag then"
497 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
501 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
502 create them before starting the vserver and use the 'nodev' flag then"
503 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
505 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
506 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
513 ## Usage: _processSingleInterface <interface-directory>
514 function _processSingleInterface
529 _getInterfaceValue ip '' "$iface"
530 _getInterfaceValue extip '' "$iface" "$iface/.."
531 _getInterfaceValue dev '' "$iface" "$iface/.."
532 _getInterfaceValue prefix '' "$iface" "$iface/.."
533 _getInterfaceValue mask '' "$iface" "$iface/.."
534 _getInterfaceValue bcast '' "$iface" "$iface/.."
535 _getInterfaceValue name '' "$iface"
536 _getInterfaceValue scope '' "$iface" "$iface/.."
537 _getInterfaceValue mac '' "$iface"
539 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
540 test -n "$dev" -o -e "$iface"/nodev || {
541 echo $"No device specified for '$iface'" >&2
545 test ! -e "$iface"/down || up=
548 _transformMask2Prefix prefix "$prefix" "$mask"
549 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
551 test ! -e "$iface"/nodev || break
553 test ! -e "$iface"/only_ip || break
555 test -e "$iface/vlandev" \
556 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
557 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
558 -a ! -e "$iface/novlandev" \
559 -a ! -e "$iface/../novlandev" \) && {
561 if vlan_info=$(_getVLANInfo "$dev"); then
562 test -d /proc/net/vlan || {
563 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
566 _addInterfaceCmd VCONFIG $vlan_info
570 if ! test -e "$iface"/indirect; then
572 use_bcast="broadcast ${bcast:-+}"
573 echo "$ip" | $_GREP -q : && use_bcast=
574 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
575 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
576 _addInterfaceCmd IP_LINK "$dev" $up
577 elif ! test -n "$ctx"; then
578 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
581 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
582 _addInterfaceCmd MODPROBE dummy "$dev"
583 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
584 _addInterfaceCmd NAMEIF "$dev" "$mac"
585 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
586 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
593 ## Usage: _generateInterfaceOptions <vserver-directory>
594 function _generateInterfaceOptions
599 test ! -e "$1"/context || read ctx <"$1"/context
601 for iface in "$1/interfaces/"*; do
602 test -d "$iface" || continue
603 test ! -e "$iface"/disabled || continue
605 _processSingleInterface "$iface"
607 _HAVE_INTERFACE_OPTIONS=1
610 function enableInterfaces
615 lock "$__LOCKDIR"/vserver.interfaces
617 while test $i -lt $INTERFACE_CMDS_IDX; do
618 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
629 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
631 NAMEIF) $_NAMEIF "$@";;
632 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
633 $_VCONFIG add "$2" "$3" >/dev/null;;
634 IP_ADDR) $_IP addr add "$@";;
635 IP_ADDR_FLUSH) $_IP addr flush "$@";;
636 IP_LINK) $_IP link set "$@";;
637 IP_ROUTE) $_IP route add "$@";;
638 *) echo "Unknown interface-command type '$type'" >&2; false;;
647 function disableInterfaces
649 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
651 local i=$INTERFACE_CMDS_IDX
654 lock "$__LOCKDIR"/vserver.interfaces
656 while test $i -gt 0; do
659 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
666 MODPROBE) $_RMMOD "${2:-$1}";;
668 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
669 IP_ADDR) $_IP addr del "$@";;
671 IP_LINK) ;; ## Ignore the link-down command for now
672 IP_ROUTE) $_IP route del "$@";;
673 *) echo "Unknown interface-command type '$type'" >&2; false;;
680 function _generateTagOptions
685 getFileValue tag "$vdir/tag" "$vdir/context"
686 test -n "$tag" || return 0
688 OPTS_VTAG_CREATE=( --tag "$tag" )
689 OPTS_VTAG_ENTER=( --tag "$tag" )
692 function _generateMemctrlOptions
697 getFileValue badness "$vdir/badness"
698 test -n "$badness" || return 0
700 OPTS_VMEMCTRL=( --badness "$badness" )
703 ## Usage: prepareInit <vserver-directory>
706 pushd "$1/vdir" >/dev/null
709 { find var/run ! -type d -print0; \
710 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
713 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
714 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
719 "${INITCMD_PREPARE[@]}"
723 ## Usage: prepareInit <vserver-directory>
726 pushd "$1/vdir" >/dev/null
729 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
732 "${STOPCMD_PREPARE[@]}"
737 function generateOptions
739 _generateInterfaceOptions "$1"
740 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
741 _generateNiceCommand "$1"
742 _generateInitOptions "$1"
743 _generateChcontextOptions "$1"
744 _generateScheduleOptions "$1"
745 _generatePersonalityOptions "$1"
746 _generateTagOptions "$1"
747 _generateMemctrlOptions "$1"
749 if test -n "$_IS_FAKEINIT"; then
750 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
751 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
759 local f="$vdir"/cpuset
763 test -d "$f" || return 0
764 test -e "$f"/name || return 0
766 read cpuset < "$f"/name
767 test -e "$f"/nocreate || {
768 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
769 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
770 if test -e "$f"/"$i"; then
771 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
779 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
780 if [ "$configured" -ne 0 ]; then
782 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
783 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
788 function removeCPUSET
792 local f="$vdir"/cpuset
794 test -d "$f" || return 0
795 test -e "$f"/name || return 0
797 read cpuset < "$f"/name
798 test -e "$f"/nocreate || {
799 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
803 function _mountVserverInternal
808 test -e "$fstab" || return 0
811 pushd "$vdir" >/dev/null
812 # check whether / is mounted readonly or whether there is special
813 # magic regarding the mtab file; when etc/mtab can not be touched,
814 # add the '-n' flag to mount
815 test -w etc -o -w etc/mtab || xflag=-n
816 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
824 local fstab="$cfgdir"/fstab
827 test -e "$fstab" || return 0
828 pushd "$vdir" >/dev/null
829 # check whether / is mounted readonly or whether there is special
830 # magic regarding the mtab file; when etc/mtab can not be touched,
831 # add the '-n' flag to mount
832 test -w etc -o -w etc/mtab || xflag=-n
833 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
837 function mountVserver
844 test -e "$cfgdir"/fstab -o \
845 -e "$cfgdir"/fstab.local -o \
846 -e "$cfgdir"/fstab.remote || return 0
848 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
850 pushd "$vdir" >/dev/null
851 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
854 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
856 _mountVserverInternal "$cfgdir"/fstab
857 _mountVserverInternal "$cfgdir"/fstab.local
858 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
860 isNamespaceCleanup "$cfgdir" && \
861 _namespaceCleanup "$cfgdir"
863 isAvoidNamespace "$cfgdir" || \
864 $_SECURE_MOUNT --rbind -n "$vdir" "/"
867 function _umountVserverInternal
870 test -e "$fstab" || return 0
875 while read src dst tmp; do
876 test -n "$tmp" || continue
882 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
888 function umountVserver
894 isAvoidNamespace "$cfgdir" || return 0
895 test -e "$cfgdir"/fstab -o \
896 -e "$cfgdir"/fstab.local -o \
897 -e "$cfgdir"/fstab.remote || return 0
898 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
900 pushd "$vdir/" >/dev/null || return 1
901 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
902 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
903 _umountVserverInternal "$cfgdir"/fstab || is_ok=
904 popd >/dev/null || return 1
912 local fstab="$cfgdir"/fstab
916 test -e "$fstab" || return 0
918 export FSTAB_FILE="$fstab"
921 test "$fsck_exitcode" -eq 0 -o \
922 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
925 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
929 test -n "$_NEED_VSHELPER_SYNC" && \
930 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
932 vshelper.initSync "$1" "$3" "$_is_meth"
935 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
938 if $_VSERVER_INFO - FEATURE vwait; then
940 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
943 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
945 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
948 if test "$rc" -ne 0 -a "$rc" -ne 1; then
949 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
950 killContext "$S_CONTEXT" 9
954 ) 4>$_is_tmpdir/procs &
956 echo "$!" >$_is_tmpdir/pid
957 eval "$3"=$_is_tmpdir
962 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
963 function _waitForVWait
968 declare -r procs=$(cat $4)
970 getFileArray status "$2"
975 'vwait' exited with error '$2' which indicates that vserver could not
980 A timeout occured while waiting for the vserver to finish and it was
981 killed by sending a SIGKILL signal. Please investigate the reasons
982 and/or increase the timeout in apps/vshelper/sync-timeout."
985 (TIMEOUT) warning $"\
986 A timeout occured while waiting for the vserver to finish and it will
987 be killed by sending a SIGKILL signal. The following process list
988 might be useful for finding out the reason of this behavior:
990 ----------------------------------------------------------------------
992 }----------------------------------------------------------------------"
995 (\?\?\?|*) warning $"\
996 internal error: 'vwait' exited with an unexpected status '$1'; I will
997 try to continue but be prepared for unexpected events."
1004 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1005 function waitForSync
1009 local vwait_statdir=$3
1012 if test -d "$vwait_statdir"; then
1013 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1014 elif test -n "$_NEED_VSHELPER_SYNC"; then
1015 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1017 A timeout or other error occured while waiting for the synchronization
1018 signal from vserver '$VSERVER_NAME'.
1019 The vserver will be killed nevertheless..."
1020 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1021 "${INITCMD_STOP_SYNC[@]}" || \
1023 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1024 will be killed nevertheless..."
1027 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1031 function _sourceWrap
1033 local vdir name flavor start i already_handled base
1037 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1038 function execScriptlets
1042 declare -r flavor=$3
1045 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1046 local DONT_SKIP_DEFAULTS=
1047 local already_handled=
1049 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1050 isRegularFile "$i" || continue
1051 test -r "$i" || continue
1055 test -x "$i" || start=_sourceWrap
1056 $start "$i" "$flavor" "$name"
1059 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1064 function sanityCheck
1066 declare -r cfgdir=$1
1068 ! test -e "$cfgdir"/fstab.local ||
1070 WARNING: 'fstab' will *not* be executed in the network context of the
1071 vserver anymore. Therefore, 'fstab.local' has the same functionality
1072 and is obsoleted. When you need the old behaviour, put the mounts
1073 into 'fstab.remote'"
1075 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1077 WARNING: The hostname is now configured in 'uts/nodename' but not in
1080 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1082 WARNING: The domainname is now configured in 'uts/domainname' but not
1083 in 'domainname'." >&2
1087 for i in "$cfgdir"/interfaces/*/only_ip; do
1088 if test -e "$i"; then
1090 iface=${i##$cfgdir/interfaces/}
1091 iface=${iface%%/only_ip}
1093 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1098 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1100 WARNING: There is no cachedirectory configured for this vserver;
1101 please create '$cfgdir/cache' e.g. by executing
1103 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1106 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1108 vshelper.doSanityCheck
1110 $_VSERVER_INFO - VERIFYCAP ||
1111 panic $"capabilities are not enabled in kernel-setup"
1113 $_VSERVER_INFO - VERIFYPROC ||
1115 /proc/uptime can not be accessed. Usually, this is caused by
1116 procfs-security. Please read the FAQ for more details
1117 http://linux-vserver.org/Proc-Security"
1119 test -e "$cfgdir"/context || {
1120 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1121 test "$TYPE" != "static" || panic $"\
1122 The kernel does not have dynamic contexts enabled. Please configure
1123 a static one by executing
1125 echo [number between 2 and 49151] > $cfgdir/context"
1130 function _setSingleDiskLimit
1142 getFileValue ctx "$vdir/context"
1143 getFileValue directory "$dlimit/directory" || return 0
1144 getFileValue space_total "$dlimit/space_total" || return 0
1145 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1146 getFileValue reserved "$dlimit/reserved" || return 0
1148 local cachename=$ctx$directory
1149 cachename=dlimits/${cachename//\//_}
1151 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1152 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1153 $_RM -f "$vdir/cache/$cachename"
1155 if test -z "$inodes_used" -o -z "$space_used"; then
1157 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1158 inodes_used=${tmpvdu##* }
1159 space_used=${tmpvdu%% *}
1162 $_VDLIMIT --xid $ctx \
1163 --set space_used=$space_used \
1164 --set space_total=$space_total \
1165 --set inodes_used=$inodes_used \
1166 --set inodes_total=$inodes_total \
1167 --set reserved=$reserved \
1172 function setDiskLimits
1177 # Disk Limits without a static context are useless
1178 test -e "$vdir"/context || return 0
1180 for dlimit in "$vdir/dlimits/"*; do
1181 test -d "$dlimit" || continue
1182 test ! -e "$dlimit/disabled" || continue
1184 _setSingleDiskLimit "$vdir" "$dlimit"
1189 function _saveSingleDiskLimit
1196 getFileValue ctx "$vdir/context"
1197 getFileValue directory "$dlimit/directory" || return 0
1199 local cachename=$ctx$directory
1200 cachename=${cachename//\//_}
1202 # Things are getting ugly here... LFS says that /var/cache (where
1203 # cachename is usually pointing to) can vanish and applications
1204 # have to deal with it. So, we have to interprete the $vdir/cache
1205 # symlink and have to create the needed directories manually.
1206 if test -d "$vdir/cache"; then
1207 : # ok, exists already
1208 elif test -L "$vdir/cache"; then
1209 # it's a dangling symlink
1211 link=$($_READLINK "$vdir/cache")
1212 ( cd $vdir && $_MKDIR -p "$link" )
1217 test -d "$vdir/cache"
1218 $_MKDIR -p "$vdir"/cache/dlimits
1220 $_VDLIMIT --xid $ctx "$directory" | \
1221 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1223 $_VDLIMIT --xid $ctx --remove "$directory"
1227 function saveDiskLimits
1232 test -e "$vdir"/context || return 0
1234 for dlimit in "$vdir/dlimits/"*; do
1235 test -d "$dlimit" || continue
1236 test ! -e "$dlimit/disabled" || continue
1238 _saveSingleDiskLimit "$vdir" "$dlimit"
1242 function _namespaceCleanup
1245 local root=$($_VSERVER_INFO "$1" VDIR 1)
1251 getFileArray skip "$vdir"/namespace-cleanup-skip \
1252 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1254 # these are things that have to be accessible post-cleanup
1255 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1256 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1257 local real=`readlink -f "$i"`
1258 test "$i" != "$real" || real=
1259 for j in "$i" "$real"; do
1260 while test -n "$j"; do
1261 list=( "${list[@]}" "$j" )
1267 local -a list_umount
1268 while read dev path opts; do
1269 test -n "$path" || continue
1270 for i in "$root" /dev /proc; do
1271 test "${path#$i}" != "$path" && continue 2
1273 for i in "${list[@]}" /; do
1274 test "$path" = "$i" && continue 2
1276 # unmount them in reverse order so mounts further down the tree get unmounted first
1277 list_umount=( "$path" "${list_umount[@]}" )
1279 # separate loop to avoid races while reading /proc/mounts
1280 for i in "${list_umount[@]}"; do
1285 function handleDeviceMap
1290 local flags device target
1292 test -d "$dir" || return 0
1293 test -n "$xid" || return 0
1295 for i in "$dir"/*; do
1296 test -d "$i" || continue
1298 local -a vdevmap_opts=()
1299 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1300 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1301 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1303 getFileValue flags "$i/flags" || :
1304 getFileValue device "$i/device" || :
1305 getFileValue target "$i/target" || :
1306 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1307 ${device:+--device "$device"} ${target:+--target "$target"} )
1309 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?