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_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=()
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=()
47 declare -a STOPCMD_PREPARE=()
49 declare -a VSERVER_EXTRA_CMDS=()
52 VSHELPER_SYNC_TIMEOUT=30
57 _HAVE_INTERFACE_OPTIONS=
68 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
70 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
76 function _generateChbindOptions
83 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
85 local f=$vdir/interfaces/bcast
86 getFileValue bcast "$f"
88 getFileValue nid "$vdir/ncontext" "$vdir/context"
90 CHBIND_OPTS=( $SILENT_OPT ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
92 for i in "${INTERFACES[@]}"; do
93 CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
96 _HAVE_CHBIND_OPTIONS=1
99 function _generateNiceCommand
103 local current_nice=`$_NICE`
105 test -r "$vdir/nice" && read nice <"$vdir"/nice
107 let nice=$nice-$current_nice || :
108 NICE_CMD=( $_NICE -n $nice )
112 function _generatePersonalityOptions
115 local f="$vdir"/personality
118 test -s "$f" || return 0
127 (*) flags=$flags$delim$tmp
134 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
135 --personality-type "$type"
136 ${flags:+--personality-flags "$flags"} )
139 function _generateCCapabilityOptions
143 local f="$vdir"/ccapabilities
145 test -e "$f" || return 0
149 (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --ccap "$cap" );;
154 function _generateBCapabilityOptions
158 local f="$vdir"/bcapabilities
160 test -e "$f" || return 0
164 (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --bcap "$cap" );;
169 function _generateCapabilityOptions
174 _generateBCapabilityOptions "$vdir"
175 _generateCCapabilityOptions "$vdir"
177 test -e "$vdir"/capabilities || return 0
186 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
187 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
190 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
193 done <"$vdir"/capabilities
196 function getEnterShell
203 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
205 test -n "$ENTER_SHELL" || {
207 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
209 test -x "$vdir/vdir/$1" || continue
216 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
217 function sendKillSequence
223 while isCtxRunning "$ctx"; do
224 test -z "$wait" || sleep "$wait"
226 killContext "$ctx" "$1"
227 test -n "$2" || break
233 function _generateInitOptions
236 local cfgdir=$vdir/apps/init
241 INITCMD_START_SYNC=()
246 INITKILL_SEQ=( 15 5 9 )
247 CHCONTEXT_INIT_OPTS=()
250 getFileValue INITSTYLE "$cfgdir"/style
251 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
252 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
253 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
254 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
256 findFile _gio_env "$cfgdir"/environment \
257 "$__CONFDIR"/.defaults/apps/init/environment \
258 "$__PKGLIBDEFAULTDIR"/environment
259 getFileArray OPTS_ENV "$_gio_env" || :
261 case x"$INITSTYLE" in
263 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
264 INITCMD_STOP=( /sbin/killall5 )
270 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
271 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
273 for i in /etc/init.d/rc /etc/rc.d/rc; do
274 test -x "$vdir/vdir/$i" || continue
275 INITCMD_START=( "$i" "$RUNLEVEL_START" )
276 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
278 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
282 INITCMD_START=( /sbin/init )
283 INITCMD_STOP=( /sbin/init )
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" )
291 INITCMD_START=( /sbin/minit-start )
292 INITCMD_STOP=( /sbin/minit-stop )
294 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
295 _NEED_VSHELPER_SYNC=1
296 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
297 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
298 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
302 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
304 INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
305 INITCMD_STOP=( /sbin/rc shutdown )
306 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
308 pushd "$vdir"/vdir &>/dev/null
309 basever=$($_CHROOT_SH cat /etc/gentoo-release | $_AWK '{print $5}')
312 basemaj=${basever/.*}
313 basemin=${basever#*.}
314 basemin=${basemin/.*}
316 test "$basemaj" -lt 1 -o "$basemin" -lt 13 && \
318 Using init-style 'gentoo' requires >=baselayout-1.13 inside the vserver!
320 Your vserver ($(basename "$vdir")) seems to have baselayout-$basever,
321 please use 'plain' init-style instead!"
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 local f="$vdir"/schedule
414 test -e "$f" || return 0
416 local fill_rate interval tokens tokens_min tokens_max prio_bias
424 read prio_bias || prio_bias=
428 test -n "$prio_bias" || {
429 echo $"Bad content in '$f'; aborting..." >&2
433 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
434 --tokens "$tokens" --tokens_min "$tokens_min" \
435 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
438 function _getInterfaceValue
448 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
451 : ${_giv_tmp:=$_giv_dflt}
452 eval $_giv_val=\$_giv_tmp
455 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
456 function _transformMask2Prefix
460 test -n "$_tm2p_tmp" || {
461 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
468 function _addInterfaceCmd
470 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
471 let ++INTERFACE_CMDS_IDX
474 ## Usage: _generateMac <var> <iface> <ctx>
475 function _generateMac
478 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
482 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
485 function _getVLANInfo
490 creation of VLAN_PLUS_VID devices is not supported; please create them
491 before starting the vserver and use the 'nodev' flag then"
492 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
496 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
497 create them before starting the vserver and use the 'nodev' flag then"
498 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
500 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
501 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
508 ## Usage: _processSingleInterface <interface-directory>
509 function _processSingleInterface
524 _getInterfaceValue ip '' "$iface"
525 _getInterfaceValue extip '' "$iface" "$iface/.."
526 _getInterfaceValue dev '' "$iface" "$iface/.."
527 _getInterfaceValue prefix '' "$iface" "$iface/.."
528 _getInterfaceValue mask '' "$iface" "$iface/.."
529 _getInterfaceValue bcast '' "$iface" "$iface/.."
530 _getInterfaceValue name '' "$iface"
531 _getInterfaceValue scope '' "$iface" "$iface/.."
532 _getInterfaceValue mac '' "$iface"
534 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
535 test -n "$dev" -o -e "$iface"/nodev || {
536 echo $"No device specified for '$iface'" >&2
540 test ! -e "$iface"/down || up=
543 _transformMask2Prefix prefix "$prefix" "$mask"
544 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
546 test ! -e "$iface"/nodev || break
548 test ! -e "$iface"/only_ip || break
551 if vlan_info=$(_getVLANInfo "$dev"); then
552 test -d /proc/net/vlan || {
553 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
556 test -e "$iface/vlandev" \
557 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
558 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
559 -a ! -e "$iface/novlandev" \
560 -a ! -e "$iface/../novlandev" \) && {
561 _addInterfaceCmd VCONFIG $vlan_info
565 if ! test -e "$iface"/indirect; then
566 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
567 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
568 _addInterfaceCmd IP_LINK "$dev" $up
569 elif ! test -n "$ctx"; then
570 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
573 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
574 _addInterfaceCmd MODPROBE dummy "$dev"
575 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
576 _addInterfaceCmd NAMEIF "$dev" "$mac"
577 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
578 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
585 ## Usage: _generateInterfaceOptions <vserver-directory>
586 function _generateInterfaceOptions
591 test ! -e "$1"/context || read ctx <"$1"/context
593 for iface in "$1/interfaces/"*; do
594 test -d "$iface" || continue
595 test ! -e "$iface"/disabled || continue
597 _processSingleInterface "$iface"
599 _HAVE_INTERFACE_OPTIONS=1
602 function enableInterfaces
607 lock "$__LOCKDIR"/vserver.interfaces
609 while test $i -lt $INTERFACE_CMDS_IDX; do
610 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
621 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
623 NAMEIF) $_NAMEIF "$@";;
624 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
625 $_VCONFIG add "$2" "$3" >/dev/null;;
626 IP_ADDR) $_IP addr add "$@";;
627 IP_ADDR_FLUSH) $_IP addr flush "$@";;
628 IP_LINK) $_IP link set "$@";;
629 IP_ROUTE) $_IP route add "$@";;
630 *) echo "Unknown interface-command type '$type'" >&2; false;;
639 function disableInterfaces
641 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
643 local i=$INTERFACE_CMDS_IDX
646 lock "$__LOCKDIR"/vserver.interfaces
648 while test $i -gt 0; do
651 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
658 MODPROBE) $_RMMOD "${2:-$1}";;
660 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
661 IP_ADDR) $_IP addr del "$@";;
663 IP_LINK) ;; ## Ignore the link-down command for now
664 IP_ROUTE) $_IP route del "$@";;
665 *) echo "Unknown interface-command type '$type'" >&2; false;;
672 ## Usage: prepareInit <vserver-directory>
675 pushd "$1/vdir" >/dev/null
678 { find var/run ! -type d -print0; \
679 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
682 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
683 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
688 "${INITCMD_PREPARE[@]}"
692 ## Usage: prepareInit <vserver-directory>
695 pushd "$1/vdir" >/dev/null
698 export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
701 "${STOPCMD_PREPARE[@]}"
706 function generateOptions
708 _generateInterfaceOptions "$1"
709 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
710 _generateNiceCommand "$1"
711 _generateInitOptions "$1"
712 _generateChcontextOptions "$1"
713 _generateScheduleOptions "$1"
714 _generatePersonalityOptions "$1"
716 if test -n "$_IS_FAKEINIT"; then
717 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
718 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
726 local f="$vdir"/cpuset
730 test -d "$f" || return 0
731 test -e "$f"/name || return 0
733 read cpuset < "$f"/name
734 test -e "$f"/nocreate || {
735 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
736 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
737 if test -e "$f"/"$i"; then
738 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
746 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
747 if [ "$configured" -ne 0 ]; then
749 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
750 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
755 function removeCPUSET
759 local f="$vdir"/cpuset
761 test -d "$f" || return 0
762 test -e "$f"/name || return 0
764 read cpuset < "$f"/name
765 test -e "$f"/nocreate || {
766 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
770 function _mountVserverInternal
775 test -e "$fstab" || return 0
778 pushd "$vdir" >/dev/null
779 # check whether / is mounted readonly or whether there is special
780 # magic regarding the mtab file; when etc/mtab can not be touched,
781 # add the '-n' flag to mount
782 test -w etc -o -w etc/mtab || xflag=-n
783 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
791 local fstab="$cfgdir"/fstab
794 test -e "$fstab" || return 0
795 pushd "$vdir" >/dev/null
796 # check whether / is mounted readonly or whether there is special
797 # magic regarding the mtab file; when etc/mtab can not be touched,
798 # add the '-n' flag to mount
799 test -w etc -o -w etc/mtab || xflag=-n
800 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
804 function mountVserver
811 test -e "$cfgdir"/fstab -o \
812 -e "$cfgdir"/fstab.local -o \
813 -e "$cfgdir"/fstab.remote || return 0
815 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
817 pushd "$vdir" >/dev/null
818 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
821 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
823 _mountVserverInternal "$cfgdir"/fstab
824 _mountVserverInternal "$cfgdir"/fstab.local
825 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
827 isNamespaceCleanup "$cfgdir" && \
828 _namespaceCleanup "$cfgdir"
830 isAvoidNamespace "$cfgdir" || \
831 $_SECURE_MOUNT --rbind -n "$vdir" "/"
834 function _umountVserverInternal
837 test -e "$fstab" || return 0
842 while read src dst tmp; do
843 test -n "$tmp" || continue
849 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
855 function umountVserver
861 isAvoidNamespace "$cfgdir" || return 0
862 test -e "$cfgdir"/fstab -o \
863 -e "$cfgdir"/fstab.local -o \
864 -e "$cfgdir"/fstab.remote || return 0
865 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
867 pushd "$vdir/" >/dev/null || return 1
868 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
869 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
870 _umountVserverInternal "$cfgdir"/fstab || is_ok=
871 popd >/dev/null || return 1
876 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
880 test -n "$_NEED_VSHELPER_SYNC" && \
881 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
883 vshelper.initSync "$1" "$3" "$_is_meth"
886 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
889 if $_VSERVER_INFO - FEATURE vwait; then
891 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
894 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
896 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
899 if test "$rc" -ne 0 -a "$rc" -ne 1; then
900 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
901 killContext "$S_CONTEXT" 9
905 ) 4>$_is_tmpdir/procs &
907 echo "$!" >$_is_tmpdir/pid
908 eval "$3"=$_is_tmpdir
913 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
914 function _waitForVWait
919 declare -r procs=$(cat $4)
921 getFileArray status "$2"
926 'vwait' exited with error '$2' which indicates that vserver could not
931 A timeout occured while waiting for the vserver to finish and it was
932 killed by sending a SIGKILL signal. Please investigate the reasons
933 and/or increase the timeout in apps/vshelper/sync-timeout."
936 (TIMEOUT) warning $"\
937 A timeout occured while waiting for the vserver to finish and it will
938 be killed by sending a SIGKILL signal. The following process list
939 might be useful for finding out the reason of this behavior:
941 ----------------------------------------------------------------------
943 }----------------------------------------------------------------------"
946 (\?\?\?|*) warning $"\
947 internal error: 'vwait' exited with an unexpected status '$1'; I will
948 try to continue but be prepared for unexpected events."
955 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
960 local vwait_statdir=$3
963 if test -d "$vwait_statdir"; then
964 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
965 elif test -n "$_NEED_VSHELPER_SYNC"; then
966 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
968 A timeout or other error occured while waiting for the synchronization
969 signal from vserver '$VSERVER_NAME'.
970 The vserver will be killed nevertheless..."
971 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
972 "${INITCMD_STOP_SYNC[@]}" || \
974 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
975 will be killed nevertheless..."
978 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
984 local vdir name flavor start i already_handled base
988 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
989 function execScriptlets
996 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
997 local DONT_SKIP_DEFAULTS=
998 local already_handled=
1000 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1001 isRegularFile "$i" || continue
1002 test -r "$i" || continue
1006 test -x "$i" || start=_sourceWrap
1007 $start "$i" "$flavor" "$name"
1010 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1015 function sanityCheck
1017 declare -r cfgdir=$1
1019 ! test -e "$cfgdir"/fstab.local ||
1021 WARNING: 'fstab' will *not* be executed in the network context of the
1022 vserver anymore. Therefore, 'fstab.local' has the same functionality
1023 and is obsoleted. When you need the old behaviour, put the mounts
1024 into 'fstab.remote'"
1026 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1028 WARNING: The hostname is now configured in 'uts/nodename' but not in
1031 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1033 WARNING: The domainname is now configured in 'uts/domainname' but not
1034 in 'domainname'." >&2
1038 for i in "$cfgdir"/interfaces/*/only_ip; do
1039 if test -e "$i"; then
1041 iface=${i##$cfgdir/interfaces/}
1042 iface=${iface%%/only_ip}
1044 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1049 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1051 WARNING: There is no cachedirectory configured for this vserver;
1052 please create '$cfgdir/cache' e.g. by executing
1054 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1057 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1059 vshelper.doSanityCheck
1061 $_VSERVER_INFO - VERIFYCAP ||
1062 panic $"capabilities are not enabled in kernel-setup"
1064 $_VSERVER_INFO - VERIFYPROC ||
1066 /proc/uptime can not be accessed. Usually, this is caused by
1067 procfs-security. Please read the FAQ for more details
1068 http://www.linux-vserver.org/index.php?page=Linux-Vserver+FAQ"
1072 function _setSingleDiskLimit
1084 getFileValue ctx "$vdir/context"
1085 getFileValue directory "$dlimit/directory" || return 0
1086 getFileValue space_total "$dlimit/space_total" || return 0
1087 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1088 getFileValue reserved "$dlimit/reserved" || return 0
1090 local cachename=$ctx$directory
1091 cachename=dlimits/${cachename//\//_}
1093 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1094 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1095 $_RM -f "$vdir/cache/$cachename"
1097 if test -z "$inodes_used" -o -z "$space_used"; then
1099 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1100 inodes_used=${tmpvdu##* }
1101 space_used=${tmpvdu%% *}
1104 $_VDLIMIT --xid $ctx \
1105 --set space_used=$space_used \
1106 --set space_total=$space_total \
1107 --set inodes_used=$inodes_used \
1108 --set inodes_total=$inodes_total \
1109 --set reserved=$reserved \
1114 function setDiskLimits
1119 # Disk Limits without a static context are useless
1120 test -e "$vdir"/context || return 0
1122 for dlimit in "$vdir/dlimits/"*; do
1123 test -d "$dlimit" || continue
1124 test ! -e "$dlimit/disabled" || continue
1126 _setSingleDiskLimit "$vdir" "$dlimit"
1131 function _saveSingleDiskLimit
1138 getFileValue ctx "$vdir/context"
1139 getFileValue directory "$dlimit/directory" || return 0
1141 local cachename=$ctx$directory
1142 cachename=${cachename//\//_}
1144 # Things are getting ugly here... LFS says that /var/cache (where
1145 # cachename is usually pointing to) can vanish and applications
1146 # have to deal with it. So, we have to interprete the $vdir/cache
1147 # symlink and have to create the needed directories manually.
1148 if test -d "$vdir/cache"; then
1149 : # ok, exists already
1150 elif test -L "$vdir/cache"; then
1151 # it's a dangling symlink
1153 link=$($_READLINK "$vdir/cache")
1154 ( cd $vdir && $_MKDIR -p "$link" )
1159 test -d "$vdir/cache"
1160 $_MKDIR -p "$vdir"/cache/dlimits
1162 $_VDLIMIT --xid $ctx "$directory" | \
1163 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1167 function saveDiskLimits
1172 test -e "$vdir"/context || return 0
1174 for dlimit in "$vdir/dlimits/"*; do
1175 test -d "$dlimit" || continue
1176 test ! -e "$dlimit/disabled" || continue
1178 _saveSingleDiskLimit "$vdir" "$dlimit"
1182 function _namespaceCleanup
1185 local root=$($_VSERVER_INFO "$1" VDIR 1)
1190 getFileArray skip "$vdir"/namespace-cleanup-skip \
1191 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1193 # these are things that have to be accessible post-cleanup
1194 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1195 "$__PKGSTATEDIR" "${skip[@]}"; do
1196 while test -n "$tmp"; do
1197 list=( "${list[@]}" "$tmp" )
1202 local -a list_umount
1203 while read dev path opts; do
1204 test -n "$path" || continue
1205 for i in "$root" /dev /proc; do
1206 test "${path#$i}" != "$path" && continue 2
1208 for i in "${list[@]}" /; do
1209 test "$path" = "$i" && continue 2
1211 # unmount them in reverse order so mounts further down the tree get unmounted first
1212 list_umount=( "$path" "${list_umount[@]}" )
1214 # separate loop to avoid races while reading /proc/mounts
1215 for i in "${list_umount[@]}"; do