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 _readFileToArray
83 test -e "$_rfta_f" || return 0
84 while read _rfta_v; do
87 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
92 function _generateChbindOptions
99 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
101 local f=$vdir/interfaces/bcast
102 getFileValue bcast "$f"
104 getFileValue nid "$vdir/ncontext" "$vdir/context"
106 CHBIND_OPTS=( $SILENT_OPT --secure ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
108 for i in "${INTERFACES[@]}"; do
109 CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
112 _readFileToArray "$vdir"/nflags CHBIND_OPTS --flag
113 _readFileToArray "$vdir"/ncapabilities CHBIND_OPTS --ncap
115 _HAVE_CHBIND_OPTIONS=1
118 function _generateNiceCommand
122 local current_nice=`$_NICE`
124 test -r "$vdir/nice" && read nice <"$vdir"/nice
126 let nice=$nice-$current_nice || :
127 NICE_CMD=( $_NICE -n $nice )
131 function _generatePersonalityOptions
134 local f="$vdir"/personality
137 test -s "$f" || return 0
146 (*) flags=$flags$delim$tmp
153 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
154 --personality-type "$type"
155 ${flags:+--personality-flags "$flags"} )
158 function _generateCCapabilityOptions
162 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
165 function _generateBCapabilityOptions
169 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
172 function _generateCapabilityOptions
177 _generateBCapabilityOptions "$vdir"
178 _generateCCapabilityOptions "$vdir"
180 test -e "$vdir"/capabilities || return 0
189 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
190 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
193 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
196 done <"$vdir"/capabilities
199 function getEnterShell
206 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
208 test -n "$ENTER_SHELL" || {
210 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
212 test -x "$vdir/vdir/$1" || continue
219 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
220 function sendKillSequence
226 while isCtxRunning "$ctx"; do
227 test -z "$wait" || sleep "$wait"
229 killContext "$ctx" "$1"
230 test -n "$2" || break
236 function _generateInitOptions
239 local cfgdir=$vdir/apps/init
244 INITCMD_START_SYNC=()
249 INITKILL_SEQ=( 15 5 9 )
250 CHCONTEXT_INIT_OPTS=()
253 test x"$INITSTYLE" = xrescue || \
254 getFileValue INITSTYLE "$cfgdir"/style
255 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
256 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
257 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
258 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
260 findFile _gio_env "$cfgdir"/environment \
261 "$__CONFDIR"/.defaults/apps/init/environment \
262 "$__PKGLIBDEFAULTDIR"/environment
263 getFileArray OPTS_ENV "$_gio_env" || :
265 case x"$INITSTYLE" in
267 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
268 INITCMD_STOP=( /sbin/killall5 )
272 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
273 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
275 for i in /etc/init.d/rc /etc/rc.d/rc; do
276 test -x "$vdir/vdir/$i" || continue
277 INITCMD_START=( "$i" "$RUNLEVEL_START" )
278 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
280 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
284 INITCMD_START=( /sbin/init )
285 INITCMD_STOP=( /sbin/init )
287 _NEED_VSHELPER_SYNC=1
288 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
289 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
293 INITCMD_START=( /sbin/minit-start )
294 INITCMD_STOP=( /sbin/minit-stop )
296 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
297 _NEED_VSHELPER_SYNC=1
298 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
299 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
300 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
304 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
306 INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
307 INITCMD_STOP=( /sbin/rc shutdown )
308 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
312 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
315 if test x"$INITSTYLE" != xrescue; then
316 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
317 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
318 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
319 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
320 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
323 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
324 INITCMD_START_SYNC=()
329 if vshelper.isEnabled; then
330 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
336 function _generateFlagOptions
340 CHCONTEXT_FLAG_OPTS=()
342 test ! -e "$vdir"/flags || \
351 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
352 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
358 isAvoidNamespace "$vdir" || {
360 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
364 function _generateChcontextOptions
367 local ctx hostname domainname
372 read ctx <"$vdir"/context || :
374 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
375 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
378 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
380 _generateCapabilityOptions "$vdir"
381 _generateFlagOptions "$vdir"
383 CHCONTEXT_OPTS=( $SILENT_OPT \
384 "${CHCONTEXT_FLAG_OPTS[@]}" \
387 ${ctx:+--ctx "$ctx"} \
388 ${hostname:+--hostname "$hostname"} \
389 ${domainname:+--domainname "$domainname"} )
391 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
392 ${ctx:+--xid "$ctx"} )
393 ## put '--secure' at front so that it can be overridden
394 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
397 function _generateScheduleOptions
400 if test -d "$vdir"/sched; then
401 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
405 local f="$vdir"/schedule
406 test -e "$f" || return 0
408 local fill_rate interval tokens tokens_min tokens_max prio_bias
416 read prio_bias || prio_bias=
420 test -n "$prio_bias" || {
421 echo $"Bad content in '$f'; aborting..." >&2
425 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
426 --tokens "$tokens" --tokens_min "$tokens_min" \
427 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
430 function _getInterfaceValue
440 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
443 : ${_giv_tmp:=$_giv_dflt}
444 eval $_giv_val=\$_giv_tmp
447 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
448 function _transformMask2Prefix
452 test -n "$_tm2p_tmp" || {
453 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
460 function _addInterfaceCmd
462 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
463 let ++INTERFACE_CMDS_IDX
466 ## Usage: _generateMac <var> <iface> <ctx>
467 function _generateMac
470 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
474 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
477 function _getVLANInfo
482 creation of VLAN_PLUS_VID devices is not supported; please create them
483 before starting the vserver and use the 'nodev' flag then"
484 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
488 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
489 create them before starting the vserver and use the 'nodev' flag then"
490 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
492 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
493 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
500 ## Usage: _processSingleInterface <interface-directory>
501 function _processSingleInterface
516 _getInterfaceValue ip '' "$iface"
517 _getInterfaceValue extip '' "$iface" "$iface/.."
518 _getInterfaceValue dev '' "$iface" "$iface/.."
519 _getInterfaceValue prefix '' "$iface" "$iface/.."
520 _getInterfaceValue mask '' "$iface" "$iface/.."
521 _getInterfaceValue bcast '' "$iface" "$iface/.."
522 _getInterfaceValue name '' "$iface"
523 _getInterfaceValue scope '' "$iface" "$iface/.."
524 _getInterfaceValue mac '' "$iface"
526 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
527 test -n "$dev" -o -e "$iface"/nodev || {
528 echo $"No device specified for '$iface'" >&2
532 test ! -e "$iface"/down || up=
535 _transformMask2Prefix prefix "$prefix" "$mask"
536 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
538 test ! -e "$iface"/nodev || break
540 test ! -e "$iface"/only_ip || break
542 test -e "$iface/vlandev" \
543 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
544 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
545 -a ! -e "$iface/novlandev" \
546 -a ! -e "$iface/../novlandev" \) && {
548 if vlan_info=$(_getVLANInfo "$dev"); then
549 test -d /proc/net/vlan || {
550 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
553 _addInterfaceCmd VCONFIG $vlan_info
557 if ! test -e "$iface"/indirect; then
558 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
559 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
560 _addInterfaceCmd IP_LINK "$dev" $up
561 elif ! test -n "$ctx"; then
562 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
565 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
566 _addInterfaceCmd MODPROBE dummy "$dev"
567 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
568 _addInterfaceCmd NAMEIF "$dev" "$mac"
569 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
570 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
577 ## Usage: _generateInterfaceOptions <vserver-directory>
578 function _generateInterfaceOptions
583 test ! -e "$1"/context || read ctx <"$1"/context
585 for iface in "$1/interfaces/"*; do
586 test -d "$iface" || continue
587 test ! -e "$iface"/disabled || continue
589 _processSingleInterface "$iface"
591 _HAVE_INTERFACE_OPTIONS=1
594 function enableInterfaces
599 lock "$__LOCKDIR"/vserver.interfaces
601 while test $i -lt $INTERFACE_CMDS_IDX; do
602 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
613 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
615 NAMEIF) $_NAMEIF "$@";;
616 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
617 $_VCONFIG add "$2" "$3" >/dev/null;;
618 IP_ADDR) $_IP addr add "$@";;
619 IP_ADDR_FLUSH) $_IP addr flush "$@";;
620 IP_LINK) $_IP link set "$@";;
621 IP_ROUTE) $_IP route add "$@";;
622 *) echo "Unknown interface-command type '$type'" >&2; false;;
631 function disableInterfaces
633 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
635 local i=$INTERFACE_CMDS_IDX
638 lock "$__LOCKDIR"/vserver.interfaces
640 while test $i -gt 0; do
643 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
650 MODPROBE) $_RMMOD "${2:-$1}";;
652 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
653 IP_ADDR) $_IP addr del "$@";;
655 IP_LINK) ;; ## Ignore the link-down command for now
656 IP_ROUTE) $_IP route del "$@";;
657 *) echo "Unknown interface-command type '$type'" >&2; false;;
664 ## Usage: prepareInit <vserver-directory>
667 pushd "$1/vdir" >/dev/null
670 { find var/run ! -type d -print0; \
671 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
674 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
675 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
680 "${INITCMD_PREPARE[@]}"
684 ## Usage: prepareInit <vserver-directory>
687 pushd "$1/vdir" >/dev/null
690 export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
693 "${STOPCMD_PREPARE[@]}"
698 function generateOptions
700 _generateInterfaceOptions "$1"
701 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
702 _generateNiceCommand "$1"
703 _generateInitOptions "$1"
704 _generateChcontextOptions "$1"
705 _generateScheduleOptions "$1"
706 _generatePersonalityOptions "$1"
708 if test -n "$_IS_FAKEINIT"; then
709 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
710 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
718 local f="$vdir"/cpuset
722 test -d "$f" || return 0
723 test -e "$f"/name || return 0
725 read cpuset < "$f"/name
726 test -e "$f"/nocreate || {
727 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
728 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
729 if test -e "$f"/"$i"; then
730 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
738 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
739 if [ "$configured" -ne 0 ]; then
741 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
742 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
747 function removeCPUSET
751 local f="$vdir"/cpuset
753 test -d "$f" || return 0
754 test -e "$f"/name || return 0
756 read cpuset < "$f"/name
757 test -e "$f"/nocreate || {
758 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
762 function _mountVserverInternal
767 test -e "$fstab" || return 0
770 pushd "$vdir" >/dev/null
771 # check whether / is mounted readonly or whether there is special
772 # magic regarding the mtab file; when etc/mtab can not be touched,
773 # add the '-n' flag to mount
774 test -w etc -o -w etc/mtab || xflag=-n
775 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
783 local fstab="$cfgdir"/fstab
786 test -e "$fstab" || return 0
787 pushd "$vdir" >/dev/null
788 # check whether / is mounted readonly or whether there is special
789 # magic regarding the mtab file; when etc/mtab can not be touched,
790 # add the '-n' flag to mount
791 test -w etc -o -w etc/mtab || xflag=-n
792 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
796 function mountVserver
803 test -e "$cfgdir"/fstab -o \
804 -e "$cfgdir"/fstab.local -o \
805 -e "$cfgdir"/fstab.remote || return 0
807 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
809 pushd "$vdir" >/dev/null
810 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
813 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
815 _mountVserverInternal "$cfgdir"/fstab
816 _mountVserverInternal "$cfgdir"/fstab.local
817 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
819 isNamespaceCleanup "$cfgdir" && \
820 _namespaceCleanup "$cfgdir"
822 isAvoidNamespace "$cfgdir" || \
823 $_SECURE_MOUNT --rbind -n "$vdir" "/"
826 function _umountVserverInternal
829 test -e "$fstab" || return 0
834 while read src dst tmp; do
835 test -n "$tmp" || continue
841 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
847 function umountVserver
853 isAvoidNamespace "$cfgdir" || return 0
854 test -e "$cfgdir"/fstab -o \
855 -e "$cfgdir"/fstab.local -o \
856 -e "$cfgdir"/fstab.remote || return 0
857 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
859 pushd "$vdir/" >/dev/null || return 1
860 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
861 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
862 _umountVserverInternal "$cfgdir"/fstab || is_ok=
863 popd >/dev/null || return 1
868 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
872 test -n "$_NEED_VSHELPER_SYNC" && \
873 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
875 vshelper.initSync "$1" "$3" "$_is_meth"
878 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
881 if $_VSERVER_INFO - FEATURE vwait; then
883 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
886 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
888 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
891 if test "$rc" -ne 0 -a "$rc" -ne 1; then
892 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
893 killContext "$S_CONTEXT" 9
897 ) 4>$_is_tmpdir/procs &
899 echo "$!" >$_is_tmpdir/pid
900 eval "$3"=$_is_tmpdir
905 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
906 function _waitForVWait
911 declare -r procs=$(cat $4)
913 getFileArray status "$2"
918 'vwait' exited with error '$2' which indicates that vserver could not
923 A timeout occured while waiting for the vserver to finish and it was
924 killed by sending a SIGKILL signal. Please investigate the reasons
925 and/or increase the timeout in apps/vshelper/sync-timeout."
928 (TIMEOUT) warning $"\
929 A timeout occured while waiting for the vserver to finish and it will
930 be killed by sending a SIGKILL signal. The following process list
931 might be useful for finding out the reason of this behavior:
933 ----------------------------------------------------------------------
935 }----------------------------------------------------------------------"
938 (\?\?\?|*) warning $"\
939 internal error: 'vwait' exited with an unexpected status '$1'; I will
940 try to continue but be prepared for unexpected events."
947 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
952 local vwait_statdir=$3
955 if test -d "$vwait_statdir"; then
956 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
957 elif test -n "$_NEED_VSHELPER_SYNC"; then
958 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
960 A timeout or other error occured while waiting for the synchronization
961 signal from vserver '$VSERVER_NAME'.
962 The vserver will be killed nevertheless..."
963 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
964 "${INITCMD_STOP_SYNC[@]}" || \
966 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
967 will be killed nevertheless..."
970 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
976 local vdir name flavor start i already_handled base
980 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
981 function execScriptlets
988 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
989 local DONT_SKIP_DEFAULTS=
990 local already_handled=
992 for i in "$base/$flavor" "$base/$flavor.d"/*; do
993 isRegularFile "$i" || continue
994 test -r "$i" || continue
998 test -x "$i" || start=_sourceWrap
999 $start "$i" "$flavor" "$name"
1002 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1007 function sanityCheck
1009 declare -r cfgdir=$1
1011 ! test -e "$cfgdir"/fstab.local ||
1013 WARNING: 'fstab' will *not* be executed in the network context of the
1014 vserver anymore. Therefore, 'fstab.local' has the same functionality
1015 and is obsoleted. When you need the old behaviour, put the mounts
1016 into 'fstab.remote'"
1018 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1020 WARNING: The hostname is now configured in 'uts/nodename' but not in
1023 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1025 WARNING: The domainname is now configured in 'uts/domainname' but not
1026 in 'domainname'." >&2
1030 for i in "$cfgdir"/interfaces/*/only_ip; do
1031 if test -e "$i"; then
1033 iface=${i##$cfgdir/interfaces/}
1034 iface=${iface%%/only_ip}
1036 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1041 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1043 WARNING: There is no cachedirectory configured for this vserver;
1044 please create '$cfgdir/cache' e.g. by executing
1046 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1049 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1051 vshelper.doSanityCheck
1053 $_VSERVER_INFO - VERIFYCAP ||
1054 panic $"capabilities are not enabled in kernel-setup"
1056 $_VSERVER_INFO - VERIFYPROC ||
1058 /proc/uptime can not be accessed. Usually, this is caused by
1059 procfs-security. Please read the FAQ for more details
1060 http://linux-vserver.org/Proc-Security"
1064 function _setSingleDiskLimit
1076 getFileValue ctx "$vdir/context"
1077 getFileValue directory "$dlimit/directory" || return 0
1078 getFileValue space_total "$dlimit/space_total" || return 0
1079 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1080 getFileValue reserved "$dlimit/reserved" || return 0
1082 local cachename=$ctx$directory
1083 cachename=dlimits/${cachename//\//_}
1085 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1086 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1087 $_RM -f "$vdir/cache/$cachename"
1089 if test -z "$inodes_used" -o -z "$space_used"; then
1091 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1092 inodes_used=${tmpvdu##* }
1093 space_used=${tmpvdu%% *}
1096 $_VDLIMIT --xid $ctx \
1097 --set space_used=$space_used \
1098 --set space_total=$space_total \
1099 --set inodes_used=$inodes_used \
1100 --set inodes_total=$inodes_total \
1101 --set reserved=$reserved \
1106 function setDiskLimits
1111 # Disk Limits without a static context are useless
1112 test -e "$vdir"/context || return 0
1114 for dlimit in "$vdir/dlimits/"*; do
1115 test -d "$dlimit" || continue
1116 test ! -e "$dlimit/disabled" || continue
1118 _setSingleDiskLimit "$vdir" "$dlimit"
1123 function _saveSingleDiskLimit
1130 getFileValue ctx "$vdir/context"
1131 getFileValue directory "$dlimit/directory" || return 0
1133 local cachename=$ctx$directory
1134 cachename=${cachename//\//_}
1136 # Things are getting ugly here... LFS says that /var/cache (where
1137 # cachename is usually pointing to) can vanish and applications
1138 # have to deal with it. So, we have to interprete the $vdir/cache
1139 # symlink and have to create the needed directories manually.
1140 if test -d "$vdir/cache"; then
1141 : # ok, exists already
1142 elif test -L "$vdir/cache"; then
1143 # it's a dangling symlink
1145 link=$($_READLINK "$vdir/cache")
1146 ( cd $vdir && $_MKDIR -p "$link" )
1151 test -d "$vdir/cache"
1152 $_MKDIR -p "$vdir"/cache/dlimits
1154 $_VDLIMIT --xid $ctx "$directory" | \
1155 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1157 $_VDLIMIT --xid $ctx --remove "$directory"
1161 function saveDiskLimits
1166 test -e "$vdir"/context || return 0
1168 for dlimit in "$vdir/dlimits/"*; do
1169 test -d "$dlimit" || continue
1170 test ! -e "$dlimit/disabled" || continue
1172 _saveSingleDiskLimit "$vdir" "$dlimit"
1176 function _namespaceCleanup
1179 local root=$($_VSERVER_INFO "$1" VDIR 1)
1184 getFileArray skip "$vdir"/namespace-cleanup-skip \
1185 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1187 # these are things that have to be accessible post-cleanup
1188 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1189 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1190 while test -n "$tmp"; do
1191 list=( "${list[@]}" "$tmp" )
1196 local -a list_umount
1197 while read dev path opts; do
1198 test -n "$path" || continue
1199 for i in "$root" /dev /proc; do
1200 test "${path#$i}" != "$path" && continue 2
1202 for i in "${list[@]}" /; do
1203 test "$path" = "$i" && continue 2
1205 # unmount them in reverse order so mounts further down the tree get unmounted first
1206 list_umount=( "$path" "${list_umount[@]}" )
1208 # separate loop to avoid races while reading /proc/mounts
1209 for i in "${list_umount[@]}"; do
1214 function loadDeviceMap
1218 local flags device target
1220 test -d "$dir" || return 0
1222 for i in "$dir"/*; do
1223 test -d "$i" || continue
1225 local -a vdevmap_opts=()
1226 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1227 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1228 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1230 getFileValue flags "$i/flags" || :
1231 getFileValue device "$i/device" || :
1232 getFileValue target "$i/target" || :
1233 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1234 ${device:+--device "$device"} ${target:+--target "$target"} )
1236 $_VDEVMAP --xid "$xid" "${vdevmap_opts[@]}" || return $?