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
899 local fstab="$cfgdir"/fstab
903 test -e "$fstab" || return 0
905 export FSTAB_FILE="$fstab"
908 test "$fsck_exitcode" -eq 0 -o \
909 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
912 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
916 test -n "$_NEED_VSHELPER_SYNC" && \
917 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
919 vshelper.initSync "$1" "$3" "$_is_meth"
922 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
925 if $_VSERVER_INFO - FEATURE vwait; then
927 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
930 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
932 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
935 if test "$rc" -ne 0 -a "$rc" -ne 1; then
936 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
937 killContext "$S_CONTEXT" 9
941 ) 4>$_is_tmpdir/procs &
943 echo "$!" >$_is_tmpdir/pid
944 eval "$3"=$_is_tmpdir
949 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
950 function _waitForVWait
955 declare -r procs=$(cat $4)
957 getFileArray status "$2"
962 'vwait' exited with error '$2' which indicates that vserver could not
967 A timeout occured while waiting for the vserver to finish and it was
968 killed by sending a SIGKILL signal. Please investigate the reasons
969 and/or increase the timeout in apps/vshelper/sync-timeout."
972 (TIMEOUT) warning $"\
973 A timeout occured while waiting for the vserver to finish and it will
974 be killed by sending a SIGKILL signal. The following process list
975 might be useful for finding out the reason of this behavior:
977 ----------------------------------------------------------------------
979 }----------------------------------------------------------------------"
982 (\?\?\?|*) warning $"\
983 internal error: 'vwait' exited with an unexpected status '$1'; I will
984 try to continue but be prepared for unexpected events."
991 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
996 local vwait_statdir=$3
999 if test -d "$vwait_statdir"; then
1000 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1001 elif test -n "$_NEED_VSHELPER_SYNC"; then
1002 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1004 A timeout or other error occured while waiting for the synchronization
1005 signal from vserver '$VSERVER_NAME'.
1006 The vserver will be killed nevertheless..."
1007 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1008 "${INITCMD_STOP_SYNC[@]}" || \
1010 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1011 will be killed nevertheless..."
1014 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1018 function _sourceWrap
1020 local vdir name flavor start i already_handled base
1024 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1025 function execScriptlets
1029 declare -r flavor=$3
1032 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1033 local DONT_SKIP_DEFAULTS=
1034 local already_handled=
1036 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1037 isRegularFile "$i" || continue
1038 test -r "$i" || continue
1042 test -x "$i" || start=_sourceWrap
1043 $start "$i" "$flavor" "$name"
1046 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1051 function sanityCheck
1053 declare -r cfgdir=$1
1055 ! test -e "$cfgdir"/fstab.local ||
1057 WARNING: 'fstab' will *not* be executed in the network context of the
1058 vserver anymore. Therefore, 'fstab.local' has the same functionality
1059 and is obsoleted. When you need the old behaviour, put the mounts
1060 into 'fstab.remote'"
1062 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1064 WARNING: The hostname is now configured in 'uts/nodename' but not in
1067 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1069 WARNING: The domainname is now configured in 'uts/domainname' but not
1070 in 'domainname'." >&2
1074 for i in "$cfgdir"/interfaces/*/only_ip; do
1075 if test -e "$i"; then
1077 iface=${i##$cfgdir/interfaces/}
1078 iface=${iface%%/only_ip}
1080 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1085 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1087 WARNING: There is no cachedirectory configured for this vserver;
1088 please create '$cfgdir/cache' e.g. by executing
1090 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1093 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1095 vshelper.doSanityCheck
1097 $_VSERVER_INFO - VERIFYCAP ||
1098 panic $"capabilities are not enabled in kernel-setup"
1100 $_VSERVER_INFO - VERIFYPROC ||
1102 /proc/uptime can not be accessed. Usually, this is caused by
1103 procfs-security. Please read the FAQ for more details
1104 http://linux-vserver.org/Proc-Security"
1106 test -e "$cfgdir"/context || {
1107 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1108 test "$TYPE" != "static" || panic $"\
1109 The kernel does not have dynamic contexts enabled. Please configure
1110 a static one by executing
1112 echo [number between 2 and 49151] > $cfgdir/context"
1117 function _setSingleDiskLimit
1129 getFileValue ctx "$vdir/context"
1130 getFileValue directory "$dlimit/directory" || return 0
1131 getFileValue space_total "$dlimit/space_total" || return 0
1132 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1133 getFileValue reserved "$dlimit/reserved" || return 0
1135 local cachename=$ctx$directory
1136 cachename=dlimits/${cachename//\//_}
1138 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1139 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1140 $_RM -f "$vdir/cache/$cachename"
1142 if test -z "$inodes_used" -o -z "$space_used"; then
1144 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1145 inodes_used=${tmpvdu##* }
1146 space_used=${tmpvdu%% *}
1149 $_VDLIMIT --xid $ctx \
1150 --set space_used=$space_used \
1151 --set space_total=$space_total \
1152 --set inodes_used=$inodes_used \
1153 --set inodes_total=$inodes_total \
1154 --set reserved=$reserved \
1159 function setDiskLimits
1164 # Disk Limits without a static context are useless
1165 test -e "$vdir"/context || return 0
1167 for dlimit in "$vdir/dlimits/"*; do
1168 test -d "$dlimit" || continue
1169 test ! -e "$dlimit/disabled" || continue
1171 _setSingleDiskLimit "$vdir" "$dlimit"
1176 function _saveSingleDiskLimit
1183 getFileValue ctx "$vdir/context"
1184 getFileValue directory "$dlimit/directory" || return 0
1186 local cachename=$ctx$directory
1187 cachename=${cachename//\//_}
1189 # Things are getting ugly here... LFS says that /var/cache (where
1190 # cachename is usually pointing to) can vanish and applications
1191 # have to deal with it. So, we have to interprete the $vdir/cache
1192 # symlink and have to create the needed directories manually.
1193 if test -d "$vdir/cache"; then
1194 : # ok, exists already
1195 elif test -L "$vdir/cache"; then
1196 # it's a dangling symlink
1198 link=$($_READLINK "$vdir/cache")
1199 ( cd $vdir && $_MKDIR -p "$link" )
1204 test -d "$vdir/cache"
1205 $_MKDIR -p "$vdir"/cache/dlimits
1207 $_VDLIMIT --xid $ctx "$directory" | \
1208 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1210 $_VDLIMIT --xid $ctx --remove "$directory"
1214 function saveDiskLimits
1219 test -e "$vdir"/context || return 0
1221 for dlimit in "$vdir/dlimits/"*; do
1222 test -d "$dlimit" || continue
1223 test ! -e "$dlimit/disabled" || continue
1225 _saveSingleDiskLimit "$vdir" "$dlimit"
1229 function _namespaceCleanup
1232 local root=$($_VSERVER_INFO "$1" VDIR 1)
1238 getFileArray skip "$vdir"/namespace-cleanup-skip \
1239 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1241 # these are things that have to be accessible post-cleanup
1242 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1243 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1244 local real=`readlink -f "$i"`
1245 test "$i" != "$real" || real=
1246 for j in "$i" "$real"; do
1247 while test -n "$j"; do
1248 list=( "${list[@]}" "$j" )
1254 local -a list_umount
1255 while read dev path opts; do
1256 test -n "$path" || continue
1257 for i in "$root" /dev /proc; do
1258 test "${path#$i}" != "$path" && continue 2
1260 for i in "${list[@]}" /; do
1261 test "$path" = "$i" && continue 2
1263 # unmount them in reverse order so mounts further down the tree get unmounted first
1264 list_umount=( "$path" "${list_umount[@]}" )
1266 # separate loop to avoid races while reading /proc/mounts
1267 for i in "${list_umount[@]}"; do
1272 function loadDeviceMap
1276 local flags device target
1278 test -d "$dir" || return 0
1280 for i in "$dir"/*; do
1281 test -d "$i" || continue
1283 local -a vdevmap_opts=()
1284 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1285 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1286 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1288 getFileValue flags "$i/flags" || :
1289 getFileValue device "$i/device" || :
1290 getFileValue target "$i/target" || :
1291 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1292 ${device:+--device "$device"} ${target:+--target "$target"} )
1294 $_VDEVMAP --xid "$xid" --set "${vdevmap_opts[@]}" || return $?