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 test -n "$INITSTYLE" || \
251 getFileValue INITSTYLE "$cfgdir"/style
252 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
253 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
254 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
255 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
257 findFile _gio_env "$cfgdir"/environment \
258 "$__CONFDIR"/.defaults/apps/init/environment \
259 "$__PKGLIBDEFAULTDIR"/environment
260 getFileArray OPTS_ENV "$_gio_env" || :
262 case x"$INITSTYLE" in
264 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
265 INITCMD_STOP=( /sbin/killall5 )
269 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
270 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
272 for i in /etc/init.d/rc /etc/rc.d/rc; do
273 test -x "$vdir/vdir/$i" || continue
274 INITCMD_START=( "$i" "$RUNLEVEL_START" )
275 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
277 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
281 INITCMD_START=( /sbin/init )
282 INITCMD_STOP=( /sbin/init )
284 _NEED_VSHELPER_SYNC=1
285 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
286 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
290 INITCMD_START=( /sbin/minit-start )
291 INITCMD_STOP=( /sbin/minit-stop )
293 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
294 _NEED_VSHELPER_SYNC=1
295 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
296 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
297 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
301 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
303 INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
304 INITCMD_STOP=( /sbin/rc shutdown )
305 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
307 pushd "$vdir"/vdir &>/dev/null
308 basever=$($_CHROOT_SH cat /etc/gentoo-release | $_AWK '{print $5}')
311 basemaj=${basever/.*}
312 basemin=${basever#*.}
313 basemin=${basemin/.*}
315 test "$basemaj" -lt 1 -o "$basemin" -lt 13 && \
317 Using init-style 'gentoo' requires >=baselayout-1.13 inside the vserver!
319 Your vserver ($(basename "$vdir")) seems to have baselayout-$basever,
320 please use 'plain' init-style instead!"
324 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
327 if test x"$INITSTYLE" != xrescue; then
328 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
329 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
330 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
331 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
332 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
335 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
336 INITCMD_START_SYNC=()
341 if vshelper.isEnabled; then
342 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
348 function _generateFlagOptions
352 CHCONTEXT_FLAG_OPTS=()
354 test ! -e "$vdir"/flags || \
363 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
364 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
370 isAvoidNamespace "$vdir" || {
372 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
376 function _generateChcontextOptions
379 local ctx hostname domainname
384 read ctx <"$vdir"/context || :
386 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
387 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
390 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
392 _generateCapabilityOptions "$vdir"
393 _generateFlagOptions "$vdir"
395 CHCONTEXT_OPTS=( $SILENT_OPT \
396 "${CHCONTEXT_FLAG_OPTS[@]}" \
399 ${ctx:+--ctx "$ctx"} \
400 ${hostname:+--hostname "$hostname"} \
401 ${domainname:+--domainname "$domainname"} )
403 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
404 ${ctx:+--xid "$ctx"} )
405 ## put '--secure' at front so that it can be overridden
406 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
409 function _generateScheduleOptions
412 if test -d "$vdir"/sched; then
413 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
417 local f="$vdir"/schedule
418 test -e "$f" || return 0
420 local fill_rate interval tokens tokens_min tokens_max prio_bias
428 read prio_bias || prio_bias=
432 test -n "$prio_bias" || {
433 echo $"Bad content in '$f'; aborting..." >&2
437 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
438 --tokens "$tokens" --tokens_min "$tokens_min" \
439 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
442 function _getInterfaceValue
452 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
455 : ${_giv_tmp:=$_giv_dflt}
456 eval $_giv_val=\$_giv_tmp
459 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
460 function _transformMask2Prefix
464 test -n "$_tm2p_tmp" || {
465 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
472 function _addInterfaceCmd
474 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
475 let ++INTERFACE_CMDS_IDX
478 ## Usage: _generateMac <var> <iface> <ctx>
479 function _generateMac
482 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
486 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
489 function _getVLANInfo
494 creation of VLAN_PLUS_VID devices is not supported; please create them
495 before starting the vserver and use the 'nodev' flag then"
496 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
500 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
501 create them before starting the vserver and use the 'nodev' flag then"
502 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
504 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
505 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
512 ## Usage: _processSingleInterface <interface-directory>
513 function _processSingleInterface
528 _getInterfaceValue ip '' "$iface"
529 _getInterfaceValue extip '' "$iface" "$iface/.."
530 _getInterfaceValue dev '' "$iface" "$iface/.."
531 _getInterfaceValue prefix '' "$iface" "$iface/.."
532 _getInterfaceValue mask '' "$iface" "$iface/.."
533 _getInterfaceValue bcast '' "$iface" "$iface/.."
534 _getInterfaceValue name '' "$iface"
535 _getInterfaceValue scope '' "$iface" "$iface/.."
536 _getInterfaceValue mac '' "$iface"
538 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
539 test -n "$dev" -o -e "$iface"/nodev || {
540 echo $"No device specified for '$iface'" >&2
544 test ! -e "$iface"/down || up=
547 _transformMask2Prefix prefix "$prefix" "$mask"
548 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
550 test ! -e "$iface"/nodev || break
552 test ! -e "$iface"/only_ip || break
555 if vlan_info=$(_getVLANInfo "$dev"); then
556 test -d /proc/net/vlan || {
557 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
560 test -e "$iface/vlandev" \
561 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
562 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
563 -a ! -e "$iface/novlandev" \
564 -a ! -e "$iface/../novlandev" \) && {
565 _addInterfaceCmd VCONFIG $vlan_info
569 if ! test -e "$iface"/indirect; then
570 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
571 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
572 _addInterfaceCmd IP_LINK "$dev" $up
573 elif ! test -n "$ctx"; then
574 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
577 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
578 _addInterfaceCmd MODPROBE dummy "$dev"
579 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
580 _addInterfaceCmd NAMEIF "$dev" "$mac"
581 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
582 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
589 ## Usage: _generateInterfaceOptions <vserver-directory>
590 function _generateInterfaceOptions
595 test ! -e "$1"/context || read ctx <"$1"/context
597 for iface in "$1/interfaces/"*; do
598 test -d "$iface" || continue
599 test ! -e "$iface"/disabled || continue
601 _processSingleInterface "$iface"
603 _HAVE_INTERFACE_OPTIONS=1
606 function enableInterfaces
611 lock "$__LOCKDIR"/vserver.interfaces
613 while test $i -lt $INTERFACE_CMDS_IDX; do
614 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
625 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
627 NAMEIF) $_NAMEIF "$@";;
628 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
629 $_VCONFIG add "$2" "$3" >/dev/null;;
630 IP_ADDR) $_IP addr add "$@";;
631 IP_ADDR_FLUSH) $_IP addr flush "$@";;
632 IP_LINK) $_IP link set "$@";;
633 IP_ROUTE) $_IP route add "$@";;
634 *) echo "Unknown interface-command type '$type'" >&2; false;;
643 function disableInterfaces
645 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
647 local i=$INTERFACE_CMDS_IDX
650 lock "$__LOCKDIR"/vserver.interfaces
652 while test $i -gt 0; do
655 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
662 MODPROBE) $_RMMOD "${2:-$1}";;
664 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
665 IP_ADDR) $_IP addr del "$@";;
667 IP_LINK) ;; ## Ignore the link-down command for now
668 IP_ROUTE) $_IP route del "$@";;
669 *) echo "Unknown interface-command type '$type'" >&2; false;;
676 ## Usage: prepareInit <vserver-directory>
679 pushd "$1/vdir" >/dev/null
682 { find var/run ! -type d -print0; \
683 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
686 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
687 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
692 "${INITCMD_PREPARE[@]}"
696 ## Usage: prepareInit <vserver-directory>
699 pushd "$1/vdir" >/dev/null
702 export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
705 "${STOPCMD_PREPARE[@]}"
710 function generateOptions
712 _generateInterfaceOptions "$1"
713 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
714 _generateNiceCommand "$1"
715 _generateInitOptions "$1"
716 _generateChcontextOptions "$1"
717 _generateScheduleOptions "$1"
718 _generatePersonalityOptions "$1"
720 if test -n "$_IS_FAKEINIT"; then
721 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
722 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
730 local f="$vdir"/cpuset
734 test -d "$f" || return 0
735 test -e "$f"/name || return 0
737 read cpuset < "$f"/name
738 test -e "$f"/nocreate || {
739 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
740 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
741 if test -e "$f"/"$i"; then
742 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
750 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
751 if [ "$configured" -ne 0 ]; then
753 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
754 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
759 function removeCPUSET
763 local f="$vdir"/cpuset
765 test -d "$f" || return 0
766 test -e "$f"/name || return 0
768 read cpuset < "$f"/name
769 test -e "$f"/nocreate || {
770 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
774 function _mountVserverInternal
779 test -e "$fstab" || return 0
782 pushd "$vdir" >/dev/null
783 # check whether / is mounted readonly or whether there is special
784 # magic regarding the mtab file; when etc/mtab can not be touched,
785 # add the '-n' flag to mount
786 test -w etc -o -w etc/mtab || xflag=-n
787 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
795 local fstab="$cfgdir"/fstab
798 test -e "$fstab" || return 0
799 pushd "$vdir" >/dev/null
800 # check whether / is mounted readonly or whether there is special
801 # magic regarding the mtab file; when etc/mtab can not be touched,
802 # add the '-n' flag to mount
803 test -w etc -o -w etc/mtab || xflag=-n
804 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
808 function mountVserver
815 test -e "$cfgdir"/fstab -o \
816 -e "$cfgdir"/fstab.local -o \
817 -e "$cfgdir"/fstab.remote || return 0
819 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
821 pushd "$vdir" >/dev/null
822 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
825 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
827 _mountVserverInternal "$cfgdir"/fstab
828 _mountVserverInternal "$cfgdir"/fstab.local
829 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
831 isNamespaceCleanup "$cfgdir" && \
832 _namespaceCleanup "$cfgdir"
834 isAvoidNamespace "$cfgdir" || \
835 $_SECURE_MOUNT --rbind -n "$vdir" "/"
838 function _umountVserverInternal
841 test -e "$fstab" || return 0
846 while read src dst tmp; do
847 test -n "$tmp" || continue
853 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
859 function umountVserver
865 isAvoidNamespace "$cfgdir" || return 0
866 test -e "$cfgdir"/fstab -o \
867 -e "$cfgdir"/fstab.local -o \
868 -e "$cfgdir"/fstab.remote || return 0
869 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
871 pushd "$vdir/" >/dev/null || return 1
872 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
873 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
874 _umountVserverInternal "$cfgdir"/fstab || is_ok=
875 popd >/dev/null || return 1
880 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
884 test -n "$_NEED_VSHELPER_SYNC" && \
885 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
887 vshelper.initSync "$1" "$3" "$_is_meth"
890 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
893 if $_VSERVER_INFO - FEATURE vwait; then
895 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
898 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
900 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
903 if test "$rc" -ne 0 -a "$rc" -ne 1; then
904 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
905 killContext "$S_CONTEXT" 9
909 ) 4>$_is_tmpdir/procs &
911 echo "$!" >$_is_tmpdir/pid
912 eval "$3"=$_is_tmpdir
917 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
918 function _waitForVWait
923 declare -r procs=$(cat $4)
925 getFileArray status "$2"
930 'vwait' exited with error '$2' which indicates that vserver could not
935 A timeout occured while waiting for the vserver to finish and it was
936 killed by sending a SIGKILL signal. Please investigate the reasons
937 and/or increase the timeout in apps/vshelper/sync-timeout."
940 (TIMEOUT) warning $"\
941 A timeout occured while waiting for the vserver to finish and it will
942 be killed by sending a SIGKILL signal. The following process list
943 might be useful for finding out the reason of this behavior:
945 ----------------------------------------------------------------------
947 }----------------------------------------------------------------------"
950 (\?\?\?|*) warning $"\
951 internal error: 'vwait' exited with an unexpected status '$1'; I will
952 try to continue but be prepared for unexpected events."
959 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
964 local vwait_statdir=$3
967 if test -d "$vwait_statdir"; then
968 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
969 elif test -n "$_NEED_VSHELPER_SYNC"; then
970 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
972 A timeout or other error occured while waiting for the synchronization
973 signal from vserver '$VSERVER_NAME'.
974 The vserver will be killed nevertheless..."
975 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
976 "${INITCMD_STOP_SYNC[@]}" || \
978 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
979 will be killed nevertheless..."
982 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
988 local vdir name flavor start i already_handled base
992 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
993 function execScriptlets
1000 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1001 local DONT_SKIP_DEFAULTS=
1002 local already_handled=
1004 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1005 isRegularFile "$i" || continue
1006 test -r "$i" || continue
1010 test -x "$i" || start=_sourceWrap
1011 $start "$i" "$flavor" "$name"
1014 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1019 function sanityCheck
1021 declare -r cfgdir=$1
1023 ! test -e "$cfgdir"/fstab.local ||
1025 WARNING: 'fstab' will *not* be executed in the network context of the
1026 vserver anymore. Therefore, 'fstab.local' has the same functionality
1027 and is obsoleted. When you need the old behaviour, put the mounts
1028 into 'fstab.remote'"
1030 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1032 WARNING: The hostname is now configured in 'uts/nodename' but not in
1035 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1037 WARNING: The domainname is now configured in 'uts/domainname' but not
1038 in 'domainname'." >&2
1042 for i in "$cfgdir"/interfaces/*/only_ip; do
1043 if test -e "$i"; then
1045 iface=${i##$cfgdir/interfaces/}
1046 iface=${iface%%/only_ip}
1048 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1053 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1055 WARNING: There is no cachedirectory configured for this vserver;
1056 please create '$cfgdir/cache' e.g. by executing
1058 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1061 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1063 vshelper.doSanityCheck
1065 $_VSERVER_INFO - VERIFYCAP ||
1066 panic $"capabilities are not enabled in kernel-setup"
1068 $_VSERVER_INFO - VERIFYPROC ||
1070 /proc/uptime can not be accessed. Usually, this is caused by
1071 procfs-security. Please read the FAQ for more details
1072 http://www.linux-vserver.org/index.php?page=Linux-Vserver+FAQ"
1076 function _setSingleDiskLimit
1088 getFileValue ctx "$vdir/context"
1089 getFileValue directory "$dlimit/directory" || return 0
1090 getFileValue space_total "$dlimit/space_total" || return 0
1091 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1092 getFileValue reserved "$dlimit/reserved" || return 0
1094 local cachename=$ctx$directory
1095 cachename=dlimits/${cachename//\//_}
1097 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1098 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1099 $_RM -f "$vdir/cache/$cachename"
1101 if test -z "$inodes_used" -o -z "$space_used"; then
1103 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1104 inodes_used=${tmpvdu##* }
1105 space_used=${tmpvdu%% *}
1108 $_VDLIMIT --xid $ctx \
1109 --set space_used=$space_used \
1110 --set space_total=$space_total \
1111 --set inodes_used=$inodes_used \
1112 --set inodes_total=$inodes_total \
1113 --set reserved=$reserved \
1118 function setDiskLimits
1123 # Disk Limits without a static context are useless
1124 test -e "$vdir"/context || return 0
1126 for dlimit in "$vdir/dlimits/"*; do
1127 test -d "$dlimit" || continue
1128 test ! -e "$dlimit/disabled" || continue
1130 _setSingleDiskLimit "$vdir" "$dlimit"
1135 function _saveSingleDiskLimit
1142 getFileValue ctx "$vdir/context"
1143 getFileValue directory "$dlimit/directory" || return 0
1145 local cachename=$ctx$directory
1146 cachename=${cachename//\//_}
1148 # Things are getting ugly here... LFS says that /var/cache (where
1149 # cachename is usually pointing to) can vanish and applications
1150 # have to deal with it. So, we have to interprete the $vdir/cache
1151 # symlink and have to create the needed directories manually.
1152 if test -d "$vdir/cache"; then
1153 : # ok, exists already
1154 elif test -L "$vdir/cache"; then
1155 # it's a dangling symlink
1157 link=$($_READLINK "$vdir/cache")
1158 ( cd $vdir && $_MKDIR -p "$link" )
1163 test -d "$vdir/cache"
1164 $_MKDIR -p "$vdir"/cache/dlimits
1166 $_VDLIMIT --xid $ctx "$directory" | \
1167 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1171 function saveDiskLimits
1176 test -e "$vdir"/context || return 0
1178 for dlimit in "$vdir/dlimits/"*; do
1179 test -d "$dlimit" || continue
1180 test ! -e "$dlimit/disabled" || continue
1182 _saveSingleDiskLimit "$vdir" "$dlimit"
1186 function _namespaceCleanup
1189 local root=$($_VSERVER_INFO "$1" VDIR 1)
1194 getFileArray skip "$vdir"/namespace-cleanup-skip \
1195 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1197 # these are things that have to be accessible post-cleanup
1198 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1199 "$__PKGSTATEDIR" "${skip[@]}"; do
1200 while test -n "$tmp"; do
1201 list=( "${list[@]}" "$tmp" )
1206 local -a list_umount
1207 while read dev path opts; do
1208 test -n "$path" || continue
1209 for i in "$root" /dev /proc; do
1210 test "${path#$i}" != "$path" && continue 2
1212 for i in "${list[@]}" /; do
1213 test "$path" = "$i" && continue 2
1215 # unmount them in reverse order so mounts further down the tree get unmounted first
1216 list_umount=( "$path" "${list_umount[@]}" )
1218 # separate loop to avoid races while reading /proc/mounts
1219 for i in "${list_umount[@]}"; do