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"
615 test -n "$tag" || return 0
617 OPTS_VTAG_CREATE=( --tag "$tag" )
618 OPTS_VTAG_ENTER=( --tag "$tag" )
621 function enableInterfaces
626 lock "$__LOCKDIR"/vserver.interfaces
628 while test $i -lt $INTERFACE_CMDS_IDX; do
629 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
640 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
642 NAMEIF) $_NAMEIF "$@";;
643 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
644 $_VCONFIG add "$2" "$3" >/dev/null;;
645 IP_ADDR) $_IP addr add "$@";;
646 IP_ADDR_FLUSH) $_IP addr flush "$@";;
647 IP_LINK) $_IP link set "$@";;
648 IP_ROUTE) $_IP route add "$@";;
649 *) echo "Unknown interface-command type '$type'" >&2; false;;
658 function disableInterfaces
660 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
662 local i=$INTERFACE_CMDS_IDX
665 lock "$__LOCKDIR"/vserver.interfaces
667 while test $i -gt 0; do
670 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
677 MODPROBE) $_RMMOD "${2:-$1}";;
679 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
680 IP_ADDR) $_IP addr del "$@";;
682 IP_LINK) ;; ## Ignore the link-down command for now
683 IP_ROUTE) $_IP route del "$@";;
684 *) echo "Unknown interface-command type '$type'" >&2; false;;
691 ## Usage: prepareInit <vserver-directory>
694 pushd "$1/vdir" >/dev/null
697 { find var/run ! -type d -print0; \
698 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
701 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
702 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
707 "${INITCMD_PREPARE[@]}"
711 ## Usage: prepareInit <vserver-directory>
714 pushd "$1/vdir" >/dev/null
717 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
720 "${STOPCMD_PREPARE[@]}"
725 function generateOptions
727 _generateInterfaceOptions "$1"
728 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
729 _generateNiceCommand "$1"
730 _generateInitOptions "$1"
731 _generateChcontextOptions "$1"
732 _generateScheduleOptions "$1"
733 _generatePersonalityOptions "$1"
734 _generateTagOptions "$1"
736 if test -n "$_IS_FAKEINIT"; then
737 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
738 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
746 local f="$vdir"/cpuset
750 test -d "$f" || return 0
751 test -e "$f"/name || return 0
753 read cpuset < "$f"/name
754 test -e "$f"/nocreate || {
755 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
756 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
757 if test -e "$f"/"$i"; then
758 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
766 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
767 if [ "$configured" -ne 0 ]; then
769 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
770 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
775 function removeCPUSET
779 local f="$vdir"/cpuset
781 test -d "$f" || return 0
782 test -e "$f"/name || return 0
784 read cpuset < "$f"/name
785 test -e "$f"/nocreate || {
786 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
790 function _mountVserverInternal
795 test -e "$fstab" || return 0
798 pushd "$vdir" >/dev/null
799 # check whether / is mounted readonly or whether there is special
800 # magic regarding the mtab file; when etc/mtab can not be touched,
801 # add the '-n' flag to mount
802 test -w etc -o -w etc/mtab || xflag=-n
803 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
811 local fstab="$cfgdir"/fstab
814 test -e "$fstab" || return 0
815 pushd "$vdir" >/dev/null
816 # check whether / is mounted readonly or whether there is special
817 # magic regarding the mtab file; when etc/mtab can not be touched,
818 # add the '-n' flag to mount
819 test -w etc -o -w etc/mtab || xflag=-n
820 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
824 function mountVserver
831 test -e "$cfgdir"/fstab -o \
832 -e "$cfgdir"/fstab.local -o \
833 -e "$cfgdir"/fstab.remote || return 0
835 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
837 pushd "$vdir" >/dev/null
838 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
841 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
843 _mountVserverInternal "$cfgdir"/fstab
844 _mountVserverInternal "$cfgdir"/fstab.local
845 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
847 isNamespaceCleanup "$cfgdir" && \
848 _namespaceCleanup "$cfgdir"
850 isAvoidNamespace "$cfgdir" || \
851 $_SECURE_MOUNT --rbind -n "$vdir" "/"
854 function _umountVserverInternal
857 test -e "$fstab" || return 0
862 while read src dst tmp; do
863 test -n "$tmp" || continue
869 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
875 function umountVserver
881 isAvoidNamespace "$cfgdir" || return 0
882 test -e "$cfgdir"/fstab -o \
883 -e "$cfgdir"/fstab.local -o \
884 -e "$cfgdir"/fstab.remote || return 0
885 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
887 pushd "$vdir/" >/dev/null || return 1
888 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
889 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
890 _umountVserverInternal "$cfgdir"/fstab || is_ok=
891 popd >/dev/null || return 1
896 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
900 test -n "$_NEED_VSHELPER_SYNC" && \
901 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
903 vshelper.initSync "$1" "$3" "$_is_meth"
906 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
909 if $_VSERVER_INFO - FEATURE vwait; then
911 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
914 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
916 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
919 if test "$rc" -ne 0 -a "$rc" -ne 1; then
920 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
921 killContext "$S_CONTEXT" 9
925 ) 4>$_is_tmpdir/procs &
927 echo "$!" >$_is_tmpdir/pid
928 eval "$3"=$_is_tmpdir
933 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
934 function _waitForVWait
939 declare -r procs=$(cat $4)
941 getFileArray status "$2"
946 'vwait' exited with error '$2' which indicates that vserver could not
951 A timeout occured while waiting for the vserver to finish and it was
952 killed by sending a SIGKILL signal. Please investigate the reasons
953 and/or increase the timeout in apps/vshelper/sync-timeout."
956 (TIMEOUT) warning $"\
957 A timeout occured while waiting for the vserver to finish and it will
958 be killed by sending a SIGKILL signal. The following process list
959 might be useful for finding out the reason of this behavior:
961 ----------------------------------------------------------------------
963 }----------------------------------------------------------------------"
966 (\?\?\?|*) warning $"\
967 internal error: 'vwait' exited with an unexpected status '$1'; I will
968 try to continue but be prepared for unexpected events."
975 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
980 local vwait_statdir=$3
983 if test -d "$vwait_statdir"; then
984 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
985 elif test -n "$_NEED_VSHELPER_SYNC"; then
986 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
988 A timeout or other error occured while waiting for the synchronization
989 signal from vserver '$VSERVER_NAME'.
990 The vserver will be killed nevertheless..."
991 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
992 "${INITCMD_STOP_SYNC[@]}" || \
994 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
995 will be killed nevertheless..."
998 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1002 function _sourceWrap
1004 local vdir name flavor start i already_handled base
1008 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1009 function execScriptlets
1013 declare -r flavor=$3
1016 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1017 local DONT_SKIP_DEFAULTS=
1018 local already_handled=
1020 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1021 isRegularFile "$i" || continue
1022 test -r "$i" || continue
1026 test -x "$i" || start=_sourceWrap
1027 $start "$i" "$flavor" "$name"
1030 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1035 function sanityCheck
1037 declare -r cfgdir=$1
1039 ! test -e "$cfgdir"/fstab.local ||
1041 WARNING: 'fstab' will *not* be executed in the network context of the
1042 vserver anymore. Therefore, 'fstab.local' has the same functionality
1043 and is obsoleted. When you need the old behaviour, put the mounts
1044 into 'fstab.remote'"
1046 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1048 WARNING: The hostname is now configured in 'uts/nodename' but not in
1051 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1053 WARNING: The domainname is now configured in 'uts/domainname' but not
1054 in 'domainname'." >&2
1058 for i in "$cfgdir"/interfaces/*/only_ip; do
1059 if test -e "$i"; then
1061 iface=${i##$cfgdir/interfaces/}
1062 iface=${iface%%/only_ip}
1064 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1069 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1071 WARNING: There is no cachedirectory configured for this vserver;
1072 please create '$cfgdir/cache' e.g. by executing
1074 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1077 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1079 vshelper.doSanityCheck
1081 $_VSERVER_INFO - VERIFYCAP ||
1082 panic $"capabilities are not enabled in kernel-setup"
1084 $_VSERVER_INFO - VERIFYPROC ||
1086 /proc/uptime can not be accessed. Usually, this is caused by
1087 procfs-security. Please read the FAQ for more details
1088 http://linux-vserver.org/Proc-Security"
1090 test -e "$cfgdir"/context || {
1091 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1092 test "$TYPE" != "static" || panic $"\
1093 The kernel does not have dynamic contexts enabled. Please configure
1094 a static one by executing
1096 echo [number between 2 and 49151] > $cfgdir/context"
1101 function _setSingleDiskLimit
1113 getFileValue ctx "$vdir/context"
1114 getFileValue directory "$dlimit/directory" || return 0
1115 getFileValue space_total "$dlimit/space_total" || return 0
1116 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1117 getFileValue reserved "$dlimit/reserved" || return 0
1119 local cachename=$ctx$directory
1120 cachename=dlimits/${cachename//\//_}
1122 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1123 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1124 $_RM -f "$vdir/cache/$cachename"
1126 if test -z "$inodes_used" -o -z "$space_used"; then
1128 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1129 inodes_used=${tmpvdu##* }
1130 space_used=${tmpvdu%% *}
1133 $_VDLIMIT --xid $ctx \
1134 --set space_used=$space_used \
1135 --set space_total=$space_total \
1136 --set inodes_used=$inodes_used \
1137 --set inodes_total=$inodes_total \
1138 --set reserved=$reserved \
1143 function setDiskLimits
1148 # Disk Limits without a static context are useless
1149 test -e "$vdir"/context || return 0
1151 for dlimit in "$vdir/dlimits/"*; do
1152 test -d "$dlimit" || continue
1153 test ! -e "$dlimit/disabled" || continue
1155 _setSingleDiskLimit "$vdir" "$dlimit"
1160 function _saveSingleDiskLimit
1167 getFileValue ctx "$vdir/context"
1168 getFileValue directory "$dlimit/directory" || return 0
1170 local cachename=$ctx$directory
1171 cachename=${cachename//\//_}
1173 # Things are getting ugly here... LFS says that /var/cache (where
1174 # cachename is usually pointing to) can vanish and applications
1175 # have to deal with it. So, we have to interprete the $vdir/cache
1176 # symlink and have to create the needed directories manually.
1177 if test -d "$vdir/cache"; then
1178 : # ok, exists already
1179 elif test -L "$vdir/cache"; then
1180 # it's a dangling symlink
1182 link=$($_READLINK "$vdir/cache")
1183 ( cd $vdir && $_MKDIR -p "$link" )
1188 test -d "$vdir/cache"
1189 $_MKDIR -p "$vdir"/cache/dlimits
1191 $_VDLIMIT --xid $ctx "$directory" | \
1192 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1194 $_VDLIMIT --xid $ctx --remove "$directory"
1198 function saveDiskLimits
1203 test -e "$vdir"/context || return 0
1205 for dlimit in "$vdir/dlimits/"*; do
1206 test -d "$dlimit" || continue
1207 test ! -e "$dlimit/disabled" || continue
1209 _saveSingleDiskLimit "$vdir" "$dlimit"
1213 function _namespaceCleanup
1216 local root=$($_VSERVER_INFO "$1" VDIR 1)
1222 getFileArray skip "$vdir"/namespace-cleanup-skip \
1223 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1225 # these are things that have to be accessible post-cleanup
1226 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1227 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1228 local real=`readlink -f "$i"`
1229 test "$i" != "$real" || real=
1230 for j in "$i" "$real"; do
1231 while test -n "$j"; do
1232 list=( "${list[@]}" "$j" )
1238 local -a list_umount
1239 while read dev path opts; do
1240 test -n "$path" || continue
1241 for i in "$root" /dev /proc; do
1242 test "${path#$i}" != "$path" && continue 2
1244 for i in "${list[@]}" /; do
1245 test "$path" = "$i" && continue 2
1247 # unmount them in reverse order so mounts further down the tree get unmounted first
1248 list_umount=( "$path" "${list_umount[@]}" )
1250 # separate loop to avoid races while reading /proc/mounts
1251 for i in "${list_umount[@]}"; do
1256 function loadDeviceMap
1260 local flags device target
1262 test -d "$dir" || return 0
1264 for i in "$dir"/*; do
1265 test -d "$i" || continue
1267 local -a vdevmap_opts=()
1268 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1269 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1270 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1272 getFileValue flags "$i/flags" || :
1273 getFileValue device "$i/device" || :
1274 getFileValue target "$i/target" || :
1275 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1276 ${device:+--device "$device"} ${target:+--target "$target"} )
1278 $_VDEVMAP --xid "$xid" --set "${vdevmap_opts[@]}" || return $?