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=()
48 declare -a OPTS_VMEMCTRL=()
50 declare -a STOPCMD_PREPARE=()
52 declare -a VSERVER_EXTRA_CMDS=()
55 VSHELPER_SYNC_TIMEOUT=30
60 _HAVE_INTERFACE_OPTIONS=
71 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
73 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
79 function _readFileToArray
86 test -e "$_rfta_f" || return 0
87 while read _rfta_v; do
90 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
95 function _generateChbindOptions
103 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
105 local f="$vdir"/interfaces/bcast
106 getFileValue bcast "$f"
107 f="$vdir"/interfaces/lback
108 getFileValue lback "$f"
110 getFileValue nid "$vdir/ncontext" "$vdir/context"
112 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${nid:+--nid "$nid"}
113 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
116 for i in "${INTERFACES[@]}"; do
117 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
120 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
121 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
123 _HAVE_CHBIND_OPTIONS=1
126 function _generateNiceCommand
130 local current_nice=`$_NICE`
132 test -r "$vdir/nice" && read nice <"$vdir"/nice
134 let nice=$nice-$current_nice || :
135 NICE_CMD=( $_NICE -n $nice )
139 function _generatePersonalityOptions
142 local f="$vdir"/personality
145 test -s "$f" || return 0
154 (*) flags=$flags$delim$tmp
161 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
162 --personality-type "$type"
163 ${flags:+--personality-flags "$flags"} )
166 function _generateCCapabilityOptions
170 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
173 function _generateBCapabilityOptions
177 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
180 function _generateCapabilityOptions
185 _generateBCapabilityOptions "$vdir"
186 _generateCCapabilityOptions "$vdir"
188 test -e "$vdir"/capabilities || return 0
197 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
198 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
201 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
204 done <"$vdir"/capabilities
207 function getEnterShell
214 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
216 test -n "$ENTER_SHELL" || {
218 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
220 test -x "$vdir/vdir/$1" || continue
227 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
228 function sendKillSequence
234 while isCtxRunning "$ctx"; do
235 test -z "$wait" || sleep "$wait"
237 killContext "$ctx" "$1"
238 test -n "$2" || break
244 function _generateInitOptions
247 local cfgdir=$vdir/apps/init
252 INITCMD_START_SYNC=()
257 INITKILL_SEQ=( 15 5 9 )
258 CHCONTEXT_INIT_OPTS=()
261 test x"$INITSTYLE" = xrescue || \
262 getFileValue INITSTYLE "$cfgdir"/style
263 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
264 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
265 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
266 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
268 findFile _gio_env "$cfgdir"/environment \
269 "$__CONFDIR"/.defaults/apps/init/environment \
270 "$__PKGLIBDEFAULTDIR"/environment
271 getFileArray OPTS_ENV "$_gio_env" || :
273 case x"$INITSTYLE" in
275 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
276 INITCMD_STOP=( /sbin/killall5 )
280 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
281 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
283 for i in /etc/init.d/rc /etc/rc.d/rc; do
284 test -x "$vdir/vdir/$i" || continue
285 INITCMD_START=( "$i" "$RUNLEVEL_START" )
286 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
288 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
289 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
290 if test -n "$OPTION_DEBUG_SYSV"; then
291 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
292 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
297 INITCMD_START=( /sbin/init )
298 INITCMD_STOP=( /sbin/init )
300 _NEED_VSHELPER_SYNC=1
301 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
302 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
306 INITCMD_START=( /sbin/minit-start )
307 INITCMD_STOP=( /sbin/minit-stop )
309 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
310 _NEED_VSHELPER_SYNC=1
311 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
312 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
313 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
317 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
318 RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
320 INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
321 INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
322 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
326 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
329 if test x"$INITSTYLE" != xrescue; then
330 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
331 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
332 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
333 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
334 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
337 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
338 INITCMD_START_SYNC=()
343 if vshelper.isEnabled; then
344 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
350 function _generateFlagOptions
354 CHCONTEXT_FLAG_OPTS=()
356 test ! -e "$vdir"/flags || \
365 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
366 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
372 isAvoidNamespace "$vdir" || {
374 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
378 function _generateChcontextOptions
381 local ctx hostname domainname
386 read ctx <"$vdir"/context || :
388 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
389 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
392 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
394 _generateCapabilityOptions "$vdir"
395 _generateFlagOptions "$vdir"
397 CHCONTEXT_OPTS=( $SILENT_OPT \
398 "${CHCONTEXT_FLAG_OPTS[@]}" \
401 ${ctx:+--ctx "$ctx"} \
402 ${hostname:+--hostname "$hostname"} \
403 ${domainname:+--domainname "$domainname"} )
405 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
406 ${ctx:+--xid "$ctx"} )
407 ## put '--secure' at front so that it can be overridden
408 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
411 function _generateScheduleOptions
414 if test -d "$vdir"/sched; then
415 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
419 local f="$vdir"/schedule
420 test -e "$f" || return 0
422 local fill_rate interval tokens tokens_min tokens_max prio_bias
430 read prio_bias || prio_bias=
434 test -n "$prio_bias" || {
435 echo $"Bad content in '$f'; aborting..." >&2
439 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
440 --tokens "$tokens" --tokens_min "$tokens_min" \
441 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
444 function _getInterfaceValue
454 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
457 : ${_giv_tmp:=$_giv_dflt}
458 eval $_giv_val=\$_giv_tmp
461 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
462 function _transformMask2Prefix
466 test -n "$_tm2p_tmp" || {
467 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
474 function _addInterfaceCmd
476 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
477 let ++INTERFACE_CMDS_IDX
480 ## Usage: _generateMac <var> <iface> <ctx>
481 function _generateMac
484 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
488 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
491 function _getVLANInfo
496 creation of VLAN_PLUS_VID devices is not supported; please create them
497 before starting the vserver and use the 'nodev' flag then"
498 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
502 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
503 create them before starting the vserver and use the 'nodev' flag then"
504 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
506 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
507 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
514 ## Usage: _processSingleInterface <interface-directory>
515 function _processSingleInterface
530 _getInterfaceValue ip '' "$iface"
531 _getInterfaceValue extip '' "$iface" "$iface/.."
532 _getInterfaceValue dev '' "$iface" "$iface/.."
533 _getInterfaceValue prefix '' "$iface" "$iface/.."
534 _getInterfaceValue mask '' "$iface" "$iface/.."
535 _getInterfaceValue bcast '' "$iface" "$iface/.."
536 _getInterfaceValue name '' "$iface"
537 _getInterfaceValue scope '' "$iface" "$iface/.."
538 _getInterfaceValue mac '' "$iface"
540 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
541 test -n "$dev" -o -e "$iface"/nodev || {
542 echo $"No device specified for '$iface'" >&2
546 test ! -e "$iface"/down || up=
549 _transformMask2Prefix prefix "$prefix" "$mask"
550 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
552 test ! -e "$iface"/nodev || break
554 test ! -e "$iface"/only_ip || break
556 test -e "$iface/vlandev" \
557 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
558 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
559 -a ! -e "$iface/novlandev" \
560 -a ! -e "$iface/../novlandev" \) && {
562 if vlan_info=$(_getVLANInfo "$dev"); then
563 test -d /proc/net/vlan || {
564 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
567 _addInterfaceCmd VCONFIG $vlan_info
571 if ! test -e "$iface"/indirect; then
573 use_bcast="broadcast ${bcast:-+}"
574 echo "$ip" | $_GREP -q : && use_bcast=
575 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
576 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
577 _addInterfaceCmd IP_LINK "$dev" $up
578 elif ! test -n "$ctx"; then
579 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
582 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
583 _addInterfaceCmd MODPROBE dummy "$dev"
584 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
585 _addInterfaceCmd NAMEIF "$dev" "$mac"
586 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
587 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
594 ## Usage: _generateInterfaceOptions <vserver-directory>
595 function _generateInterfaceOptions
600 test ! -e "$1"/context || read ctx <"$1"/context
602 for iface in "$1/interfaces/"*; do
603 test -d "$iface" || continue
604 test ! -e "$iface"/disabled || continue
606 _processSingleInterface "$iface"
608 _HAVE_INTERFACE_OPTIONS=1
611 function enableInterfaces
616 lock "$__LOCKDIR"/vserver.interfaces
618 while test $i -lt $INTERFACE_CMDS_IDX; do
619 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
630 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
632 NAMEIF) $_NAMEIF "$@";;
633 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
634 $_VCONFIG add "$2" "$3" >/dev/null;;
635 IP_ADDR) $_IP addr add "$@";;
636 IP_ADDR_FLUSH) $_IP addr flush "$@";;
637 IP_LINK) $_IP link set "$@";;
638 IP_ROUTE) $_IP route add "$@";;
639 *) echo "Unknown interface-command type '$type'" >&2; false;;
648 function disableInterfaces
650 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
652 local i=$INTERFACE_CMDS_IDX
655 lock "$__LOCKDIR"/vserver.interfaces
657 while test $i -gt 0; do
660 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
667 MODPROBE) $_RMMOD "${2:-$1}";;
669 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
670 IP_ADDR) $_IP addr del "$@";;
672 IP_LINK) ;; ## Ignore the link-down command for now
673 IP_ROUTE) $_IP route del "$@";;
674 *) echo "Unknown interface-command type '$type'" >&2; false;;
681 function _generateTagOptions
686 getFileValue tag "$vdir/tag" "$vdir/context"
687 test -n "$tag" || return 0
689 OPTS_VTAG_CREATE=( --tag "$tag" )
690 OPTS_VTAG_ENTER=( --tag "$tag" )
693 function _generateMemctrlOptions
698 getFileValue badness "$vdir/badness"
699 test -n "$badness" || return 0
701 OPTS_VMEMCTRL=( --badness "$badness" )
704 ## Usage: prepareInit <vserver-directory>
707 pushd "$1/vdir" >/dev/null
710 { find var/run ! -type d -print0; \
711 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
714 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
715 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
720 "${INITCMD_PREPARE[@]}"
724 ## Usage: prepareInit <vserver-directory>
727 pushd "$1/vdir" >/dev/null
730 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
733 "${STOPCMD_PREPARE[@]}"
738 function generateOptions
740 _generateInterfaceOptions "$1"
741 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
742 _generateNiceCommand "$1"
743 _generateInitOptions "$1"
744 _generateChcontextOptions "$1"
745 _generateScheduleOptions "$1"
746 _generatePersonalityOptions "$1"
747 _generateTagOptions "$1"
748 _generateMemctrlOptions "$1"
750 if test -n "$_IS_FAKEINIT"; then
751 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
752 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
760 local f="$vdir"/cpuset
764 test -d "$f" || return 0
765 test -e "$f"/name || return 0
767 read cpuset < "$f"/name
768 test -e "$f"/nocreate || {
769 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
770 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
771 if test -e "$f"/"$i"; then
772 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
780 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
781 if [ "$configured" -ne 0 ]; then
783 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
784 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
789 function removeCPUSET
793 local f="$vdir"/cpuset
795 test -d "$f" || return 0
796 test -e "$f"/name || return 0
798 read cpuset < "$f"/name
799 test -e "$f"/nocreate || {
800 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
804 function _mountVserverInternal
809 test -e "$fstab" || return 0
812 pushd "$vdir" >/dev/null
813 # check whether / is mounted readonly or whether there is special
814 # magic regarding the mtab file; when etc/mtab can not be touched,
815 # add the '-n' flag to mount
816 test -w etc -o -w etc/mtab || xflag=-n
817 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
825 local fstab="$cfgdir"/fstab
828 test -e "$fstab" || return 0
829 pushd "$vdir" >/dev/null
830 # check whether / is mounted readonly or whether there is special
831 # magic regarding the mtab file; when etc/mtab can not be touched,
832 # add the '-n' flag to mount
833 test -w etc -o -w etc/mtab || xflag=-n
834 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
838 function mountVserver
845 test -e "$cfgdir"/fstab -o \
846 -e "$cfgdir"/fstab.local -o \
847 -e "$cfgdir"/fstab.remote || return 0
849 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
851 pushd "$vdir" >/dev/null
852 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
855 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
857 _mountVserverInternal "$cfgdir"/fstab
858 _mountVserverInternal "$cfgdir"/fstab.local
859 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
861 isNamespaceCleanup "$cfgdir" && \
862 _namespaceCleanup "$cfgdir"
864 isAvoidNamespace "$cfgdir" || \
865 $_SECURE_MOUNT --rbind -n "$vdir" "/"
868 function _umountVserverInternal
871 test -e "$fstab" || return 0
876 while read src dst tmp; do
877 test -n "$tmp" || continue
883 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
889 function umountVserver
895 isAvoidNamespace "$cfgdir" || return 0
896 test -e "$cfgdir"/fstab -o \
897 -e "$cfgdir"/fstab.local -o \
898 -e "$cfgdir"/fstab.remote || return 0
899 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
901 pushd "$vdir/" >/dev/null || return 1
902 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
903 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
904 _umountVserverInternal "$cfgdir"/fstab || is_ok=
905 popd >/dev/null || return 1
913 local fstab="$cfgdir"/fstab
917 test -e "$fstab" || return 0
919 export FSTAB_FILE="$fstab"
922 test "$fsck_exitcode" -eq 0 -o \
923 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
926 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
930 test -n "$_NEED_VSHELPER_SYNC" && \
931 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
933 vshelper.initSync "$1" "$3" "$_is_meth"
936 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
939 if $_VSERVER_INFO - FEATURE vwait; then
941 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
944 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
946 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
949 if test "$rc" -ne 0 -a "$rc" -ne 1; then
950 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
951 killContext "$S_CONTEXT" 9
955 ) 4>$_is_tmpdir/procs &
957 echo "$!" >$_is_tmpdir/pid
958 eval "$3"=$_is_tmpdir
963 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
964 function _waitForVWait
969 declare -r procs=$(cat $4)
971 getFileArray status "$2"
976 'vwait' exited with error '$2' which indicates that vserver could not
981 A timeout occured while waiting for the vserver to finish and it was
982 killed by sending a SIGKILL signal. Please investigate the reasons
983 and/or increase the timeout in apps/vshelper/sync-timeout."
986 (TIMEOUT) warning $"\
987 A timeout occured while waiting for the vserver to finish and it will
988 be killed by sending a SIGKILL signal. The following process list
989 might be useful for finding out the reason of this behavior:
991 ----------------------------------------------------------------------
993 }----------------------------------------------------------------------"
996 (\?\?\?|*) warning $"\
997 internal error: 'vwait' exited with an unexpected status '$1'; I will
998 try to continue but be prepared for unexpected events."
1005 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1006 function waitForSync
1010 local vwait_statdir=$3
1013 if test -d "$vwait_statdir"; then
1014 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1015 elif test -n "$_NEED_VSHELPER_SYNC"; then
1016 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1018 A timeout or other error occured while waiting for the synchronization
1019 signal from vserver '$VSERVER_NAME'.
1020 The vserver will be killed nevertheless..."
1021 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1022 "${INITCMD_STOP_SYNC[@]}" || \
1024 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1025 will be killed nevertheless..."
1028 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1032 function _sourceWrap
1034 local vdir name flavor start i already_handled base
1038 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1039 function execScriptlets
1043 declare -r flavor=$3
1046 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1047 local DONT_SKIP_DEFAULTS=
1048 local already_handled=
1050 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1051 isRegularFile "$i" || continue
1052 test -r "$i" || continue
1056 test -x "$i" || start=_sourceWrap
1057 $start "$i" "$flavor" "$name"
1060 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1065 function sanityCheck
1067 declare -r cfgdir=$1
1069 ! test -e "$cfgdir"/fstab.local ||
1071 WARNING: 'fstab' will *not* be executed in the network context of the
1072 vserver anymore. Therefore, 'fstab.local' has the same functionality
1073 and is obsoleted. When you need the old behaviour, put the mounts
1074 into 'fstab.remote'"
1076 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1078 WARNING: The hostname is now configured in 'uts/nodename' but not in
1081 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1083 WARNING: The domainname is now configured in 'uts/domainname' but not
1084 in 'domainname'." >&2
1088 for i in "$cfgdir"/interfaces/*/only_ip; do
1089 if test -e "$i"; then
1091 iface=${i##$cfgdir/interfaces/}
1092 iface=${iface%%/only_ip}
1094 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1099 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1101 WARNING: There is no cachedirectory configured for this vserver;
1102 please create '$cfgdir/cache' e.g. by executing
1104 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1107 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1109 vshelper.doSanityCheck
1111 $_VSERVER_INFO - VERIFYCAP ||
1112 panic $"capabilities are not enabled in kernel-setup"
1114 $_VSERVER_INFO - VERIFYPROC ||
1116 /proc/uptime can not be accessed. Usually, this is caused by
1117 procfs-security. Please read the FAQ for more details
1118 http://linux-vserver.org/Proc-Security"
1120 test -e "$cfgdir"/context || {
1121 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1122 test "$TYPE" != "static" || panic $"\
1123 The kernel does not have dynamic contexts enabled. Please configure
1124 a static one by executing
1126 echo [number between 2 and 49151] > $cfgdir/context"
1131 function _setSingleDiskLimit
1143 getFileValue ctx "$vdir/context"
1144 getFileValue directory "$dlimit/directory" || return 0
1145 getFileValue space_total "$dlimit/space_total" || return 0
1146 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1147 getFileValue reserved "$dlimit/reserved" || return 0
1149 local cachename=$ctx$directory
1150 cachename=dlimits/${cachename//\//_}
1152 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1153 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1154 $_RM -f "$vdir/cache/$cachename"
1156 if test -z "$inodes_used" -o -z "$space_used"; then
1158 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1159 inodes_used=${tmpvdu##* }
1160 space_used=${tmpvdu%% *}
1163 $_VDLIMIT --xid $ctx \
1164 --set space_used=$space_used \
1165 --set space_total=$space_total \
1166 --set inodes_used=$inodes_used \
1167 --set inodes_total=$inodes_total \
1168 --set reserved=$reserved \
1173 function setDiskLimits
1178 # Disk Limits without a static context are useless
1179 test -e "$vdir"/context || return 0
1181 for dlimit in "$vdir/dlimits/"*; do
1182 test -d "$dlimit" || continue
1183 test ! -e "$dlimit/disabled" || continue
1185 _setSingleDiskLimit "$vdir" "$dlimit"
1190 function _saveSingleDiskLimit
1197 getFileValue ctx "$vdir/context"
1198 getFileValue directory "$dlimit/directory" || return 0
1200 local cachename=$ctx$directory
1201 cachename=${cachename//\//_}
1203 # Things are getting ugly here... LFS says that /var/cache (where
1204 # cachename is usually pointing to) can vanish and applications
1205 # have to deal with it. So, we have to interprete the $vdir/cache
1206 # symlink and have to create the needed directories manually.
1207 if test -d "$vdir/cache"; then
1208 : # ok, exists already
1209 elif test -L "$vdir/cache"; then
1210 # it's a dangling symlink
1212 link=$($_READLINK "$vdir/cache")
1213 ( cd $vdir && $_MKDIR -p "$link" )
1218 test -d "$vdir/cache"
1219 $_MKDIR -p "$vdir"/cache/dlimits
1221 $_VDLIMIT --xid $ctx "$directory" | \
1222 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1224 $_VDLIMIT --xid $ctx --remove "$directory"
1228 function saveDiskLimits
1233 test -e "$vdir"/context || return 0
1235 for dlimit in "$vdir/dlimits/"*; do
1236 test -d "$dlimit" || continue
1237 test ! -e "$dlimit/disabled" || continue
1239 _saveSingleDiskLimit "$vdir" "$dlimit"
1243 function _namespaceCleanup
1246 local root=$($_VSERVER_INFO "$1" VDIR 1)
1252 getFileArray skip "$vdir"/namespace-cleanup-skip \
1253 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1255 # these are things that have to be accessible post-cleanup
1256 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1257 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1258 local real=`getPhysicalDir "$i"`
1259 test "$i" != "$real" || real=
1260 for j in "$i" "$real"; do
1261 while test -n "$j"; do
1262 list=( "${list[@]}" "$j" )
1268 local -a list_umount
1269 while read dev path opts; do
1270 test -n "$path" || continue
1271 for i in "$root" /dev /proc; do
1272 test "${path#$i}" != "$path" && continue 2
1274 for i in "${list[@]}" /; do
1275 test "$path" = "$i" && continue 2
1277 # unmount them in reverse order so mounts further down the tree get unmounted first
1278 list_umount=( "$path" "${list_umount[@]}" )
1280 # separate loop to avoid races while reading /proc/mounts
1281 for i in "${list_umount[@]}"; do
1286 function handleDeviceMap
1291 local flags device target
1293 test -d "$dir" || return 0
1294 test -n "$xid" || return 0
1296 for i in "$dir"/*; do
1297 test -d "$i" || continue
1299 local -a vdevmap_opts=()
1300 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1301 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1302 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1304 getFileValue flags "$i/flags" || :
1305 getFileValue device "$i/device" || :
1306 getFileValue target "$i/target" || :
1307 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1308 ${device:+--device "$device"} ${target:+--target "$target"} )
1310 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?