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=()
49 declare -a OPTS_VSPACE=()
51 declare -a STOPCMD_PREPARE=()
53 declare -a VSERVER_EXTRA_CMDS=()
56 VSHELPER_SYNC_TIMEOUT=30
61 _HAVE_INTERFACE_OPTIONS=
72 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
74 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
80 function _readFileToArray
87 test -e "$_rfta_f" || return 0
88 while read _rfta_v; do
91 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
96 function _generateChbindOptions
104 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
106 local f="$vdir"/interfaces/bcast
107 getFileValue bcast "$f"
108 f="$vdir"/interfaces/lback
109 getFileValue lback "$f"
111 getFileValue nid "$vdir/ncontext" "$vdir/context"
113 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${nid:+--nid "$nid"}
114 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
117 for i in "${INTERFACES[@]}"; do
118 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
121 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
122 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
124 _HAVE_CHBIND_OPTIONS=1
127 function _generateNiceCommand
131 local current_nice=`$_NICE`
133 test -r "$vdir/nice" && read nice <"$vdir"/nice
135 let nice=$nice-$current_nice || :
136 NICE_CMD=( $_NICE -n $nice )
140 function _generatePersonalityOptions
143 local f="$vdir"/personality
146 test -s "$f" || return 0
155 (*) flags=$flags$delim$tmp
162 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
163 --personality-type "$type"
164 ${flags:+--personality-flags "$flags"} )
167 function _generateCCapabilityOptions
171 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
174 function _generateBCapabilityOptions
178 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
181 function _generateCapabilityOptions
186 _generateBCapabilityOptions "$vdir"
187 _generateCCapabilityOptions "$vdir"
189 test -e "$vdir"/capabilities || return 0
198 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
199 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
202 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
205 done <"$vdir"/capabilities
208 function getEnterShell
215 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
217 test -n "$ENTER_SHELL" || {
219 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
221 test -x "$vdir/vdir/$1" || continue
228 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
229 function sendKillSequence
235 while isCtxRunning "$ctx"; do
236 test -z "$wait" || sleep "$wait"
238 killContext "$ctx" "$1"
239 test -n "$2" || break
245 function _generateInitOptions
248 local cfgdir=$vdir/apps/init
253 INITCMD_START_SYNC=()
258 INITKILL_SEQ=( 15 5 9 )
259 CHCONTEXT_INIT_OPTS=()
262 test x"$INITSTYLE" = xrescue || \
263 getFileValue INITSTYLE "$cfgdir"/style
264 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
265 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
266 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
267 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
269 findFile _gio_env "$cfgdir"/environment \
270 "$__CONFDIR"/.defaults/apps/init/environment \
271 "$__PKGLIBDEFAULTDIR"/environment
272 getFileArray OPTS_ENV "$_gio_env" || :
274 case x"$INITSTYLE" in
276 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
277 INITCMD_STOP=( /sbin/killall5 )
281 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
282 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
284 for i in /etc/init.d/rc /etc/rc.d/rc; do
285 test -x "$vdir/vdir/$i" || continue
286 INITCMD_START=( "$i" "$RUNLEVEL_START" )
287 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
289 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
290 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
291 if test -n "$OPTION_DEBUG_SYSV"; then
292 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
293 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
298 INITCMD_START=( /sbin/init )
299 INITCMD_STOP=( /sbin/init )
301 _NEED_VSHELPER_SYNC=1
302 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
303 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
307 INITCMD_START=( /sbin/minit-start )
308 INITCMD_STOP=( /sbin/minit-stop )
310 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
311 _NEED_VSHELPER_SYNC=1
312 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
313 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
314 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
318 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
319 RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
321 INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
322 INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
323 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
327 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
330 if test x"$INITSTYLE" != xrescue; then
331 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
332 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
333 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
334 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
335 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
338 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
339 INITCMD_START_SYNC=()
344 if vshelper.isEnabled; then
345 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
351 function _generateFlagOptions
355 CHCONTEXT_FLAG_OPTS=()
357 test ! -e "$vdir"/flags || \
366 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
367 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
373 isAvoidNamespace "$vdir" || {
375 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
379 function _generateChcontextOptions
382 local ctx hostname domainname
387 read ctx <"$vdir"/context || :
389 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
390 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
393 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
395 _generateCapabilityOptions "$vdir"
396 _generateFlagOptions "$vdir"
398 CHCONTEXT_OPTS=( $SILENT_OPT \
399 "${CHCONTEXT_FLAG_OPTS[@]}" \
402 ${ctx:+--ctx "$ctx"} \
403 ${hostname:+--hostname "$hostname"} \
404 ${domainname:+--domainname "$domainname"} )
406 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
407 ${ctx:+--xid "$ctx"} )
408 ## put '--secure' at front so that it can be overridden
409 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
412 function _generateScheduleOptions
415 if test -d "$vdir"/sched; then
416 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
420 local f="$vdir"/schedule
421 test -e "$f" || return 0
423 local fill_rate interval tokens tokens_min tokens_max prio_bias
431 read prio_bias || prio_bias=
435 test -n "$prio_bias" || {
436 echo $"Bad content in '$f'; aborting..." >&2
440 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
441 --tokens "$tokens" --tokens_min "$tokens_min" \
442 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
445 function _getInterfaceValue
455 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
458 : ${_giv_tmp:=$_giv_dflt}
459 eval $_giv_val=\$_giv_tmp
462 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
463 function _transformMask2Prefix
467 test -n "$_tm2p_tmp" || {
468 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
475 function _addInterfaceCmd
477 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
478 let ++INTERFACE_CMDS_IDX
481 ## Usage: _generateMac <var> <iface> <ctx>
482 function _generateMac
485 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
489 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
492 function _getVLANInfo
497 creation of VLAN_PLUS_VID devices is not supported; please create them
498 before starting the vserver and use the 'nodev' flag then"
499 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
503 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
504 create them before starting the vserver and use the 'nodev' flag then"
505 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
507 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
508 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
515 ## Usage: _processSingleInterface <interface-directory>
516 function _processSingleInterface
531 _getInterfaceValue ip '' "$iface"
532 _getInterfaceValue extip '' "$iface" "$iface/.."
533 _getInterfaceValue dev '' "$iface" "$iface/.."
534 _getInterfaceValue prefix '' "$iface" "$iface/.."
535 _getInterfaceValue mask '' "$iface" "$iface/.."
536 _getInterfaceValue bcast '' "$iface" "$iface/.."
537 _getInterfaceValue name '' "$iface"
538 _getInterfaceValue scope '' "$iface" "$iface/.."
539 _getInterfaceValue mac '' "$iface"
541 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
542 test -n "$dev" -o -e "$iface"/nodev || {
543 echo $"No device specified for '$iface'" >&2
547 test ! -e "$iface"/down || up=
550 _transformMask2Prefix prefix "$prefix" "$mask"
551 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
553 test ! -e "$iface"/nodev || break
555 test ! -e "$iface"/only_ip || break
557 test -e "$iface/vlandev" \
558 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
559 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
560 -a ! -e "$iface/novlandev" \
561 -a ! -e "$iface/../novlandev" \) && {
563 if vlan_info=$(_getVLANInfo "$dev"); then
564 test -d /proc/net/vlan || {
565 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
568 _addInterfaceCmd VCONFIG $vlan_info
572 if ! test -e "$iface"/indirect; then
574 use_bcast="broadcast ${bcast:-+}"
575 echo "$ip" | $_GREP -q : && use_bcast=
576 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
577 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
578 _addInterfaceCmd IP_LINK "$dev" $up
579 elif ! test -n "$ctx"; then
580 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
583 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
584 _addInterfaceCmd MODPROBE dummy "$dev"
585 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
586 _addInterfaceCmd NAMEIF "$dev" "$mac"
587 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
588 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
595 ## Usage: _generateInterfaceOptions <vserver-directory>
596 function _generateInterfaceOptions
601 test ! -e "$1"/context || read ctx <"$1"/context
603 for iface in "$1/interfaces/"*; do
604 test -d "$iface" || continue
605 test ! -e "$iface"/disabled || continue
607 _processSingleInterface "$iface"
609 _HAVE_INTERFACE_OPTIONS=1
612 function enableInterfaces
617 lock "$__LOCKDIR"/vserver.interfaces
619 while test $i -lt $INTERFACE_CMDS_IDX; do
620 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
631 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
633 NAMEIF) $_NAMEIF "$@";;
634 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
635 $_VCONFIG add "$2" "$3" >/dev/null;;
636 IP_ADDR) $_IP addr add "$@";;
637 IP_ADDR_FLUSH) $_IP addr flush "$@";;
638 IP_LINK) $_IP link set "$@";;
639 IP_ROUTE) $_IP route add "$@";;
640 *) echo "Unknown interface-command type '$type'" >&2; false;;
649 function disableInterfaces
651 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
653 local i=$INTERFACE_CMDS_IDX
656 lock "$__LOCKDIR"/vserver.interfaces
658 while test $i -gt 0; do
661 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
668 MODPROBE) $_RMMOD "${2:-$1}";;
670 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
671 IP_ADDR) $_IP addr del "$@";;
673 IP_LINK) ;; ## Ignore the link-down command for now
674 IP_ROUTE) $_IP route del "$@";;
675 *) echo "Unknown interface-command type '$type'" >&2; false;;
682 function _generateTagOptions
687 getFileValue tag "$vdir/tag" "$vdir/context"
688 test -n "$tag" || return 0
690 OPTS_VTAG_CREATE=( --tag "$tag" )
691 OPTS_VTAG_ENTER=( --tag "$tag" )
694 function _generateMemctrlOptions
699 getFileValue badness "$vdir/badness"
700 test -n "$badness" || return 0
702 OPTS_VMEMCTRL=( --badness "$badness" )
705 function _generateSpaceOptions
708 local d="$vdir"/spaces
710 test ! -e "$d"/pid || \
711 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
713 test ! -e "$d"/net || {
714 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
715 # network context and namespace don't make much sense
716 _HAVE_CHBIND_OPTIONS=1
721 getFileValue mask "$d"/mask || \
722 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
725 ## Usage: prepareInit <vserver-directory>
728 pushd "$1/vdir" >/dev/null
731 { find var/run ! -type d -print0; \
732 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
735 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
736 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
741 "${INITCMD_PREPARE[@]}"
745 ## Usage: prepareInit <vserver-directory>
748 pushd "$1/vdir" >/dev/null
751 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
754 "${STOPCMD_PREPARE[@]}"
759 function generateOptions
761 _generateInterfaceOptions "$1"
762 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
763 _generateNiceCommand "$1"
764 _generateInitOptions "$1"
765 _generateChcontextOptions "$1"
766 _generateScheduleOptions "$1"
767 _generatePersonalityOptions "$1"
768 _generateTagOptions "$1"
769 _generateMemctrlOptions "$1"
770 _generateSpaceOptions "$1"
772 if test -n "$_IS_FAKEINIT"; then
773 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
774 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
782 local f="$vdir"/cpuset
786 test -d "$f" || return 0
787 test -e "$f"/name || return 0
789 read cpuset < "$f"/name
790 test -e "$f"/nocreate || {
791 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
792 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
793 if test -e "$f"/"$i"; then
794 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
802 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
803 if [ "$configured" -ne 0 ]; then
805 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
806 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
811 function removeCPUSET
815 local f="$vdir"/cpuset
817 test -d "$f" || return 0
818 test -e "$f"/name || return 0
820 read cpuset < "$f"/name
821 test -e "$f"/nocreate || {
822 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
826 function _mountVserverInternal
831 test -e "$fstab" || return 0
834 pushd "$vdir" >/dev/null
835 # check whether / is mounted readonly or whether there is special
836 # magic regarding the mtab file; when etc/mtab can not be touched,
837 # add the '-n' flag to mount
838 test -w etc -o -w etc/mtab || xflag=-n
839 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
847 local fstab="$cfgdir"/fstab
850 test -e "$fstab" || return 0
851 pushd "$vdir" >/dev/null
852 # check whether / is mounted readonly or whether there is special
853 # magic regarding the mtab file; when etc/mtab can not be touched,
854 # add the '-n' flag to mount
855 test -w etc -o -w etc/mtab || xflag=-n
856 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
860 function mountVserver
867 test -e "$cfgdir"/fstab -o \
868 -e "$cfgdir"/fstab.local -o \
869 -e "$cfgdir"/fstab.remote || return 0
871 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
873 pushd "$vdir" >/dev/null
874 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
877 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
879 _mountVserverInternal "$cfgdir"/fstab
880 _mountVserverInternal "$cfgdir"/fstab.local
881 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
883 isNamespaceCleanup "$cfgdir" && \
884 _namespaceCleanup "$cfgdir"
886 isAvoidNamespace "$cfgdir" || \
887 $_SECURE_MOUNT --rbind -n "$vdir" "/"
890 function _umountVserverInternal
893 test -e "$fstab" || return 0
898 while read src dst tmp; do
899 test -n "$tmp" || continue
905 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
911 function umountVserver
917 isAvoidNamespace "$cfgdir" || return 0
918 test -e "$cfgdir"/fstab -o \
919 -e "$cfgdir"/fstab.local -o \
920 -e "$cfgdir"/fstab.remote || return 0
921 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
923 pushd "$vdir/" >/dev/null || return 1
924 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
925 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
926 _umountVserverInternal "$cfgdir"/fstab || is_ok=
927 popd >/dev/null || return 1
935 local fstab="$cfgdir"/fstab
939 test -e "$fstab" || return 0
941 export FSTAB_FILE="$fstab"
944 test "$fsck_exitcode" -eq 0 -o \
945 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
948 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
952 test -n "$_NEED_VSHELPER_SYNC" && \
953 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
955 vshelper.initSync "$1" "$3" "$_is_meth"
958 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
961 if $_VSERVER_INFO - FEATURE vwait; then
963 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
966 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
968 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
971 if test "$rc" -ne 0 -a "$rc" -ne 1; then
972 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
973 killContext "$S_CONTEXT" 9
977 ) 4>$_is_tmpdir/procs &
979 echo "$!" >$_is_tmpdir/pid
980 eval "$3"=$_is_tmpdir
985 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
986 function _waitForVWait
991 declare -r procs=$(cat $4)
993 getFileArray status "$2"
998 'vwait' exited with error '$2' which indicates that vserver could not
1002 (KILLED) warning $"\
1003 A timeout occured while waiting for the vserver to finish and it was
1004 killed by sending a SIGKILL signal. Please investigate the reasons
1005 and/or increase the timeout in apps/vshelper/sync-timeout."
1008 (TIMEOUT) warning $"\
1009 A timeout occured while waiting for the vserver to finish and it will
1010 be killed by sending a SIGKILL signal. The following process list
1011 might be useful for finding out the reason of this behavior:
1013 ----------------------------------------------------------------------
1015 }----------------------------------------------------------------------"
1018 (\?\?\?|*) warning $"\
1019 internal error: 'vwait' exited with an unexpected status '$1'; I will
1020 try to continue but be prepared for unexpected events."
1027 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1028 function waitForSync
1032 local vwait_statdir=$3
1035 if test -d "$vwait_statdir"; then
1036 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1037 elif test -n "$_NEED_VSHELPER_SYNC"; then
1038 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1040 A timeout or other error occured while waiting for the synchronization
1041 signal from vserver '$VSERVER_NAME'.
1042 The vserver will be killed nevertheless..."
1043 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1044 "${INITCMD_STOP_SYNC[@]}" || \
1046 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1047 will be killed nevertheless..."
1050 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1054 function _sourceWrap
1056 local vdir name flavor start i already_handled base
1060 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1061 function execScriptlets
1065 declare -r flavor=$3
1068 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1069 local DONT_SKIP_DEFAULTS=
1070 local already_handled=
1072 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1073 isRegularFile "$i" || continue
1074 test -r "$i" || continue
1078 test -x "$i" || start=_sourceWrap
1079 $start "$i" "$flavor" "$name"
1082 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1087 function sanityCheck
1089 declare -r cfgdir=$1
1091 ! test -e "$cfgdir"/fstab.local ||
1093 WARNING: 'fstab' will *not* be executed in the network context of the
1094 vserver anymore. Therefore, 'fstab.local' has the same functionality
1095 and is obsoleted. When you need the old behaviour, put the mounts
1096 into 'fstab.remote'"
1098 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1100 WARNING: The hostname is now configured in 'uts/nodename' but not in
1103 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1105 WARNING: The domainname is now configured in 'uts/domainname' but not
1106 in 'domainname'." >&2
1110 for i in "$cfgdir"/interfaces/*/only_ip; do
1111 if test -e "$i"; then
1113 iface=${i##$cfgdir/interfaces/}
1114 iface=${iface%%/only_ip}
1116 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1121 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1123 WARNING: There is no cachedirectory configured for this vserver;
1124 please create '$cfgdir/cache' e.g. by executing
1126 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1129 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1131 vshelper.doSanityCheck
1133 $_VSERVER_INFO - VERIFYCAP ||
1134 panic $"capabilities are not enabled in kernel-setup"
1136 $_VSERVER_INFO - VERIFYPROC ||
1138 /proc/uptime can not be accessed. Usually, this is caused by
1139 procfs-security. Please read the FAQ for more details
1140 http://linux-vserver.org/Proc-Security"
1142 test -e "$cfgdir"/context || {
1143 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1144 test "$TYPE" != "static" || panic $"\
1145 The kernel does not have dynamic contexts enabled. Please configure
1146 a static one by executing
1148 echo [number between 2 and 49151] > $cfgdir/context"
1153 function _setSingleDiskLimit
1165 getFileValue ctx "$vdir/context"
1166 getFileValue directory "$dlimit/directory" || return 0
1167 getFileValue space_total "$dlimit/space_total" || return 0
1168 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1169 getFileValue reserved "$dlimit/reserved" || return 0
1171 local cachename=$ctx$directory
1172 cachename=dlimits/${cachename//\//_}
1174 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1175 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1176 $_RM -f "$vdir/cache/$cachename"
1178 if test -z "$inodes_used" -o -z "$space_used"; then
1180 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1181 inodes_used=${tmpvdu##* }
1182 space_used=${tmpvdu%% *}
1185 $_VDLIMIT --xid $ctx \
1186 --set space_used=$space_used \
1187 --set space_total=$space_total \
1188 --set inodes_used=$inodes_used \
1189 --set inodes_total=$inodes_total \
1190 --set reserved=$reserved \
1195 function setDiskLimits
1200 # Disk Limits without a static context are useless
1201 test -e "$vdir"/context || return 0
1203 for dlimit in "$vdir/dlimits/"*; do
1204 test -d "$dlimit" || continue
1205 test ! -e "$dlimit/disabled" || continue
1207 _setSingleDiskLimit "$vdir" "$dlimit"
1212 function _saveSingleDiskLimit
1219 getFileValue ctx "$vdir/context"
1220 getFileValue directory "$dlimit/directory" || return 0
1222 local cachename=$ctx$directory
1223 cachename=${cachename//\//_}
1225 # Things are getting ugly here... LFS says that /var/cache (where
1226 # cachename is usually pointing to) can vanish and applications
1227 # have to deal with it. So, we have to interprete the $vdir/cache
1228 # symlink and have to create the needed directories manually.
1229 if test -d "$vdir/cache"; then
1230 : # ok, exists already
1231 elif test -L "$vdir/cache"; then
1232 # it's a dangling symlink
1234 link=$($_READLINK "$vdir/cache")
1235 ( cd $vdir && $_MKDIR -p "$link" )
1240 test -d "$vdir/cache"
1241 $_MKDIR -p "$vdir"/cache/dlimits
1243 $_VDLIMIT --xid $ctx "$directory" | \
1244 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1246 $_VDLIMIT --xid $ctx --remove "$directory"
1250 function saveDiskLimits
1255 test -e "$vdir"/context || return 0
1257 for dlimit in "$vdir/dlimits/"*; do
1258 test -d "$dlimit" || continue
1259 test ! -e "$dlimit/disabled" || continue
1261 _saveSingleDiskLimit "$vdir" "$dlimit"
1265 function _namespaceCleanup
1268 local root=$($_VSERVER_INFO "$1" VDIR 1)
1274 getFileArray skip "$vdir"/namespace-cleanup-skip \
1275 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1277 # these are things that have to be accessible post-cleanup
1278 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1279 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1280 local real=`getPhysicalDir "$i"`
1281 test "$i" != "$real" || real=
1282 for j in "$i" "$real"; do
1283 while test -n "$j"; do
1284 list=( "${list[@]}" "$j" )
1290 local -a list_umount
1291 while read -r dev path opts; do
1292 test -n "$path" || continue
1293 for i in "$root" /dev /proc; do
1294 test "${path#$i}" != "$path" && continue 2
1296 for i in "${list[@]}" /; do
1297 test "$path" = "$i" && continue 2
1299 # unmount them in reverse order so mounts further down the tree get unmounted first
1300 list_umount=( "$path" "${list_umount[@]}" )
1302 # separate loop to avoid races while reading /proc/mounts
1303 for i in "${list_umount[@]}"; do
1308 function handleDeviceMap
1313 local flags device target
1315 test -d "$dir" || return 0
1316 test -n "$xid" || return 0
1318 for i in "$dir"/*; do
1319 test -d "$i" || continue
1321 local -a vdevmap_opts=()
1322 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1323 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1324 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1326 getFileValue flags "$i/flags" || :
1327 getFileValue device "$i/device" || :
1328 getFileValue target "$i/target" || :
1329 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1330 ${device:+--device "$device"} ${target:+--target "$target"} )
1332 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?