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=()
49 declare -a STOPCMD_PREPARE=()
51 declare -a VSERVER_EXTRA_CMDS=()
54 VSHELPER_SYNC_TIMEOUT=30
59 _HAVE_INTERFACE_OPTIONS=
70 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
72 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
78 function _readFileToArray
85 test -e "$_rfta_f" || return 0
86 while read _rfta_v; do
89 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
94 function _generateChbindOptions
102 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
104 local f="$vdir"/interfaces/bcast
105 getFileValue bcast "$f"
106 f="$vdir"/interfaces/lback
107 getFileValue lback "$f"
109 getFileValue nid "$vdir/ncontext" "$vdir/context"
111 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${nid:+--nid "$nid"}
112 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
115 for i in "${INTERFACES[@]}"; do
116 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
119 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
120 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
122 _HAVE_CHBIND_OPTIONS=1
125 function _generateNiceCommand
129 local current_nice=`$_NICE`
131 test -r "$vdir/nice" && read nice <"$vdir"/nice
133 let nice=$nice-$current_nice || :
134 NICE_CMD=( $_NICE -n $nice )
138 function _generatePersonalityOptions
141 local f="$vdir"/personality
144 test -s "$f" || return 0
153 (*) flags=$flags$delim$tmp
160 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
161 --personality-type "$type"
162 ${flags:+--personality-flags "$flags"} )
165 function _generateCCapabilityOptions
169 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
172 function _generateBCapabilityOptions
176 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
179 function _generateCapabilityOptions
184 _generateBCapabilityOptions "$vdir"
185 _generateCCapabilityOptions "$vdir"
187 test -e "$vdir"/capabilities || return 0
196 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
197 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
200 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
203 done <"$vdir"/capabilities
206 function getEnterShell
213 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
215 test -n "$ENTER_SHELL" || {
217 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
219 test -x "$vdir/vdir/$1" || continue
226 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
227 function sendKillSequence
233 while isCtxRunning "$ctx"; do
234 test -z "$wait" || sleep "$wait"
236 killContext "$ctx" "$1"
237 test -n "$2" || break
243 function _generateInitOptions
246 local cfgdir=$vdir/apps/init
251 INITCMD_START_SYNC=()
256 INITKILL_SEQ=( 15 5 9 )
257 CHCONTEXT_INIT_OPTS=()
260 test x"$INITSTYLE" = xrescue || \
261 getFileValue INITSTYLE "$cfgdir"/style
262 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
263 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
264 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
265 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
267 findFile _gio_env "$cfgdir"/environment \
268 "$__CONFDIR"/.defaults/apps/init/environment \
269 "$__PKGLIBDEFAULTDIR"/environment
270 getFileArray OPTS_ENV "$_gio_env" || :
272 case x"$INITSTYLE" in
274 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
275 INITCMD_STOP=( /sbin/killall5 )
279 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
280 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
282 for i in /etc/init.d/rc /etc/rc.d/rc; do
283 test -x "$vdir/vdir/$i" || continue
284 INITCMD_START=( "$i" "$RUNLEVEL_START" )
285 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
287 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
288 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
289 if test -n "$OPTION_DEBUG_SYSV"; then
290 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
291 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
296 INITCMD_START=( /sbin/init )
297 INITCMD_STOP=( /sbin/init )
299 _NEED_VSHELPER_SYNC=1
300 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
301 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
305 INITCMD_START=( /sbin/minit-start )
306 INITCMD_STOP=( /sbin/minit-stop )
308 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
309 _NEED_VSHELPER_SYNC=1
310 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
311 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
312 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
316 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
318 INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
319 INITCMD_STOP=( env -i TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
320 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
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
554 test -e "$iface/vlandev" \
555 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
556 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
557 -a ! -e "$iface/novlandev" \
558 -a ! -e "$iface/../novlandev" \) && {
560 if vlan_info=$(_getVLANInfo "$dev"); then
561 test -d /proc/net/vlan || {
562 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
565 _addInterfaceCmd VCONFIG $vlan_info
569 if ! test -e "$iface"/indirect; then
571 use_bcast="broadcast ${bcast:-+}"
572 echo "$ip" | $_GREP -q : && use_bcast=
573 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
574 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
575 _addInterfaceCmd IP_LINK "$dev" $up
576 elif ! test -n "$ctx"; then
577 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
580 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
581 _addInterfaceCmd MODPROBE dummy "$dev"
582 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
583 _addInterfaceCmd NAMEIF "$dev" "$mac"
584 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
585 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
592 ## Usage: _generateInterfaceOptions <vserver-directory>
593 function _generateInterfaceOptions
598 test ! -e "$1"/context || read ctx <"$1"/context
600 for iface in "$1/interfaces/"*; do
601 test -d "$iface" || continue
602 test ! -e "$iface"/disabled || continue
604 _processSingleInterface "$iface"
606 _HAVE_INTERFACE_OPTIONS=1
609 function _generateTagOptions
614 getFileValue tag "$vdir/tag" "$vdir/context" || return 0
616 OPTS_VTAG_CREATE=( --tag "$tag" )
617 OPTS_VTAG_ENTER=( --tag "$tag" )
620 function enableInterfaces
625 lock "$__LOCKDIR"/vserver.interfaces
627 while test $i -lt $INTERFACE_CMDS_IDX; do
628 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
639 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
641 NAMEIF) $_NAMEIF "$@";;
642 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
643 $_VCONFIG add "$2" "$3" >/dev/null;;
644 IP_ADDR) $_IP addr add "$@";;
645 IP_ADDR_FLUSH) $_IP addr flush "$@";;
646 IP_LINK) $_IP link set "$@";;
647 IP_ROUTE) $_IP route add "$@";;
648 *) echo "Unknown interface-command type '$type'" >&2; false;;
657 function disableInterfaces
659 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
661 local i=$INTERFACE_CMDS_IDX
664 lock "$__LOCKDIR"/vserver.interfaces
666 while test $i -gt 0; do
669 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
676 MODPROBE) $_RMMOD "${2:-$1}";;
678 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
679 IP_ADDR) $_IP addr del "$@";;
681 IP_LINK) ;; ## Ignore the link-down command for now
682 IP_ROUTE) $_IP route del "$@";;
683 *) echo "Unknown interface-command type '$type'" >&2; false;;
690 ## Usage: prepareInit <vserver-directory>
693 pushd "$1/vdir" >/dev/null
696 { find var/run ! -type d -print0; \
697 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
700 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
701 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
706 "${INITCMD_PREPARE[@]}"
710 ## Usage: prepareInit <vserver-directory>
713 pushd "$1/vdir" >/dev/null
716 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
719 "${STOPCMD_PREPARE[@]}"
724 function generateOptions
726 _generateInterfaceOptions "$1"
727 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
728 _generateNiceCommand "$1"
729 _generateInitOptions "$1"
730 _generateChcontextOptions "$1"
731 _generateScheduleOptions "$1"
732 _generatePersonalityOptions "$1"
733 _generateTagOptions "$1"
735 if test -n "$_IS_FAKEINIT"; then
736 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
737 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
745 local f="$vdir"/cpuset
749 test -d "$f" || return 0
750 test -e "$f"/name || return 0
752 read cpuset < "$f"/name
753 test -e "$f"/nocreate || {
754 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
755 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
756 if test -e "$f"/"$i"; then
757 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
765 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
766 if [ "$configured" -ne 0 ]; then
768 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
769 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
774 function removeCPUSET
778 local f="$vdir"/cpuset
780 test -d "$f" || return 0
781 test -e "$f"/name || return 0
783 read cpuset < "$f"/name
784 test -e "$f"/nocreate || {
785 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
789 function _mountVserverInternal
794 test -e "$fstab" || return 0
797 pushd "$vdir" >/dev/null
798 # check whether / is mounted readonly or whether there is special
799 # magic regarding the mtab file; when etc/mtab can not be touched,
800 # add the '-n' flag to mount
801 test -w etc -o -w etc/mtab || xflag=-n
802 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
810 local fstab="$cfgdir"/fstab
813 test -e "$fstab" || return 0
814 pushd "$vdir" >/dev/null
815 # check whether / is mounted readonly or whether there is special
816 # magic regarding the mtab file; when etc/mtab can not be touched,
817 # add the '-n' flag to mount
818 test -w etc -o -w etc/mtab || xflag=-n
819 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
823 function mountVserver
830 test -e "$cfgdir"/fstab -o \
831 -e "$cfgdir"/fstab.local -o \
832 -e "$cfgdir"/fstab.remote || return 0
834 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
836 pushd "$vdir" >/dev/null
837 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
840 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
842 _mountVserverInternal "$cfgdir"/fstab
843 _mountVserverInternal "$cfgdir"/fstab.local
844 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
846 isNamespaceCleanup "$cfgdir" && \
847 _namespaceCleanup "$cfgdir"
849 isAvoidNamespace "$cfgdir" || \
850 $_SECURE_MOUNT --rbind -n "$vdir" "/"
853 function _umountVserverInternal
856 test -e "$fstab" || return 0
861 while read src dst tmp; do
862 test -n "$tmp" || continue
868 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
874 function umountVserver
880 isAvoidNamespace "$cfgdir" || return 0
881 test -e "$cfgdir"/fstab -o \
882 -e "$cfgdir"/fstab.local -o \
883 -e "$cfgdir"/fstab.remote || return 0
884 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
886 pushd "$vdir/" >/dev/null || return 1
887 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
888 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
889 _umountVserverInternal "$cfgdir"/fstab || is_ok=
890 popd >/dev/null || return 1
895 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
899 test -n "$_NEED_VSHELPER_SYNC" && \
900 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
902 vshelper.initSync "$1" "$3" "$_is_meth"
905 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
908 if $_VSERVER_INFO - FEATURE vwait; then
910 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
913 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
915 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
918 if test "$rc" -ne 0 -a "$rc" -ne 1; then
919 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
920 killContext "$S_CONTEXT" 9
924 ) 4>$_is_tmpdir/procs &
926 echo "$!" >$_is_tmpdir/pid
927 eval "$3"=$_is_tmpdir
932 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
933 function _waitForVWait
938 declare -r procs=$(cat $4)
940 getFileArray status "$2"
945 'vwait' exited with error '$2' which indicates that vserver could not
950 A timeout occured while waiting for the vserver to finish and it was
951 killed by sending a SIGKILL signal. Please investigate the reasons
952 and/or increase the timeout in apps/vshelper/sync-timeout."
955 (TIMEOUT) warning $"\
956 A timeout occured while waiting for the vserver to finish and it will
957 be killed by sending a SIGKILL signal. The following process list
958 might be useful for finding out the reason of this behavior:
960 ----------------------------------------------------------------------
962 }----------------------------------------------------------------------"
965 (\?\?\?|*) warning $"\
966 internal error: 'vwait' exited with an unexpected status '$1'; I will
967 try to continue but be prepared for unexpected events."
974 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
979 local vwait_statdir=$3
982 if test -d "$vwait_statdir"; then
983 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
984 elif test -n "$_NEED_VSHELPER_SYNC"; then
985 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
987 A timeout or other error occured while waiting for the synchronization
988 signal from vserver '$VSERVER_NAME'.
989 The vserver will be killed nevertheless..."
990 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
991 "${INITCMD_STOP_SYNC[@]}" || \
993 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
994 will be killed nevertheless..."
997 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1001 function _sourceWrap
1003 local vdir name flavor start i already_handled base
1007 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1008 function execScriptlets
1012 declare -r flavor=$3
1015 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1016 local DONT_SKIP_DEFAULTS=
1017 local already_handled=
1019 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1020 isRegularFile "$i" || continue
1021 test -r "$i" || continue
1025 test -x "$i" || start=_sourceWrap
1026 $start "$i" "$flavor" "$name"
1029 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1034 function sanityCheck
1036 declare -r cfgdir=$1
1038 ! test -e "$cfgdir"/fstab.local ||
1040 WARNING: 'fstab' will *not* be executed in the network context of the
1041 vserver anymore. Therefore, 'fstab.local' has the same functionality
1042 and is obsoleted. When you need the old behaviour, put the mounts
1043 into 'fstab.remote'"
1045 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1047 WARNING: The hostname is now configured in 'uts/nodename' but not in
1050 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1052 WARNING: The domainname is now configured in 'uts/domainname' but not
1053 in 'domainname'." >&2
1057 for i in "$cfgdir"/interfaces/*/only_ip; do
1058 if test -e "$i"; then
1060 iface=${i##$cfgdir/interfaces/}
1061 iface=${iface%%/only_ip}
1063 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1068 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1070 WARNING: There is no cachedirectory configured for this vserver;
1071 please create '$cfgdir/cache' e.g. by executing
1073 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1076 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1078 vshelper.doSanityCheck
1080 $_VSERVER_INFO - VERIFYCAP ||
1081 panic $"capabilities are not enabled in kernel-setup"
1083 $_VSERVER_INFO - VERIFYPROC ||
1085 /proc/uptime can not be accessed. Usually, this is caused by
1086 procfs-security. Please read the FAQ for more details
1087 http://linux-vserver.org/Proc-Security"
1089 test -e "$cfgdir"/context || {
1090 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1091 test "$TYPE" != "static" || panic $"\
1092 The kernel does not have dynamic contexts enabled. Please configure
1093 a static one by executing
1095 echo [number between 2 and 49151] > $cfgdir/context"
1100 function _setSingleDiskLimit
1112 getFileValue ctx "$vdir/context"
1113 getFileValue directory "$dlimit/directory" || return 0
1114 getFileValue space_total "$dlimit/space_total" || return 0
1115 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1116 getFileValue reserved "$dlimit/reserved" || return 0
1118 local cachename=$ctx$directory
1119 cachename=dlimits/${cachename//\//_}
1121 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1122 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1123 $_RM -f "$vdir/cache/$cachename"
1125 if test -z "$inodes_used" -o -z "$space_used"; then
1127 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1128 inodes_used=${tmpvdu##* }
1129 space_used=${tmpvdu%% *}
1132 $_VDLIMIT --xid $ctx \
1133 --set space_used=$space_used \
1134 --set space_total=$space_total \
1135 --set inodes_used=$inodes_used \
1136 --set inodes_total=$inodes_total \
1137 --set reserved=$reserved \
1142 function setDiskLimits
1147 # Disk Limits without a static context are useless
1148 test -e "$vdir"/context || return 0
1150 for dlimit in "$vdir/dlimits/"*; do
1151 test -d "$dlimit" || continue
1152 test ! -e "$dlimit/disabled" || continue
1154 _setSingleDiskLimit "$vdir" "$dlimit"
1159 function _saveSingleDiskLimit
1166 getFileValue ctx "$vdir/context"
1167 getFileValue directory "$dlimit/directory" || return 0
1169 local cachename=$ctx$directory
1170 cachename=${cachename//\//_}
1172 # Things are getting ugly here... LFS says that /var/cache (where
1173 # cachename is usually pointing to) can vanish and applications
1174 # have to deal with it. So, we have to interprete the $vdir/cache
1175 # symlink and have to create the needed directories manually.
1176 if test -d "$vdir/cache"; then
1177 : # ok, exists already
1178 elif test -L "$vdir/cache"; then
1179 # it's a dangling symlink
1181 link=$($_READLINK "$vdir/cache")
1182 ( cd $vdir && $_MKDIR -p "$link" )
1187 test -d "$vdir/cache"
1188 $_MKDIR -p "$vdir"/cache/dlimits
1190 $_VDLIMIT --xid $ctx "$directory" | \
1191 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1193 $_VDLIMIT --xid $ctx --remove "$directory"
1197 function saveDiskLimits
1202 test -e "$vdir"/context || return 0
1204 for dlimit in "$vdir/dlimits/"*; do
1205 test -d "$dlimit" || continue
1206 test ! -e "$dlimit/disabled" || continue
1208 _saveSingleDiskLimit "$vdir" "$dlimit"
1212 function _namespaceCleanup
1215 local root=$($_VSERVER_INFO "$1" VDIR 1)
1220 getFileArray skip "$vdir"/namespace-cleanup-skip \
1221 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1223 # these are things that have to be accessible post-cleanup
1224 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1225 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1226 while test -n "$tmp"; do
1227 list=( "${list[@]}" "$tmp" )
1232 local -a list_umount
1233 while read dev path opts; do
1234 test -n "$path" || continue
1235 for i in "$root" /dev /proc; do
1236 test "${path#$i}" != "$path" && continue 2
1238 for i in "${list[@]}" /; do
1239 test "$path" = "$i" && continue 2
1241 # unmount them in reverse order so mounts further down the tree get unmounted first
1242 list_umount=( "$path" "${list_umount[@]}" )
1244 # separate loop to avoid races while reading /proc/mounts
1245 for i in "${list_umount[@]}"; do
1250 function loadDeviceMap
1254 local flags device target
1256 test -d "$dir" || return 0
1258 for i in "$dir"/*; do
1259 test -d "$i" || continue
1261 local -a vdevmap_opts=()
1262 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1263 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1264 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1266 getFileValue flags "$i/flags" || :
1267 getFileValue device "$i/device" || :
1268 getFileValue target "$i/target" || :
1269 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1270 ${device:+--device "$device"} ${target:+--target "$target"} )
1272 $_VDEVMAP --xid "$xid" "${vdevmap_opts[@]}" || return $?