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_OPTS=()
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=()
47 declare -a STOPCMD_PREPARE=()
49 declare -a VSERVER_EXTRA_CMDS=()
52 VSHELPER_SYNC_TIMEOUT=30
57 _HAVE_INTERFACE_OPTIONS=
68 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
70 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
76 function _readFileToArray
83 test -e "$_rfta_f" || return 0
84 while read _rfta_v; do
87 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
92 function _generateChbindOptions
99 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
101 local f=$vdir/interfaces/bcast
102 getFileValue bcast "$f"
104 getFileValue nid "$vdir/ncontext" "$vdir/context"
106 CHBIND_OPTS=( $SILENT_OPT --secure ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
108 for i in "${INTERFACES[@]}"; do
109 CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
112 _readFileToArray "$vdir"/nflags CHBIND_OPTS --flag
113 _readFileToArray "$vdir"/ncapabilities CHBIND_OPTS --ncap
115 _HAVE_CHBIND_OPTIONS=1
118 function _generateNiceCommand
122 local current_nice=`$_NICE`
124 test -r "$vdir/nice" && read nice <"$vdir"/nice
126 let nice=$nice-$current_nice || :
127 NICE_CMD=( $_NICE -n $nice )
131 function _generatePersonalityOptions
134 local f="$vdir"/personality
137 test -s "$f" || return 0
146 (*) flags=$flags$delim$tmp
153 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
154 --personality-type "$type"
155 ${flags:+--personality-flags "$flags"} )
158 function _generateCCapabilityOptions
162 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
165 function _generateBCapabilityOptions
169 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
172 function _generateCapabilityOptions
177 _generateBCapabilityOptions "$vdir"
178 _generateCCapabilityOptions "$vdir"
180 test -e "$vdir"/capabilities || return 0
189 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
190 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
193 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
196 done <"$vdir"/capabilities
199 function getEnterShell
206 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
208 test -n "$ENTER_SHELL" || {
210 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
212 test -x "$vdir/vdir/$1" || continue
219 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
220 function sendKillSequence
226 while isCtxRunning "$ctx"; do
227 test -z "$wait" || sleep "$wait"
229 killContext "$ctx" "$1"
230 test -n "$2" || break
236 function _generateInitOptions
239 local cfgdir=$vdir/apps/init
244 INITCMD_START_SYNC=()
249 INITKILL_SEQ=( 15 5 9 )
250 CHCONTEXT_INIT_OPTS=()
253 test x"$INITSTYLE" = xrescue || \
254 getFileValue INITSTYLE "$cfgdir"/style
255 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
256 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
257 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
258 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
260 findFile _gio_env "$cfgdir"/environment \
261 "$__CONFDIR"/.defaults/apps/init/environment \
262 "$__PKGLIBDEFAULTDIR"/environment
263 getFileArray OPTS_ENV "$_gio_env" || :
265 case x"$INITSTYLE" in
267 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
268 INITCMD_STOP=( /sbin/killall5 )
272 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
273 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
275 for i in /etc/init.d/rc /etc/rc.d/rc; do
276 test -x "$vdir/vdir/$i" || continue
277 INITCMD_START=( "$i" "$RUNLEVEL_START" )
278 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
280 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
284 INITCMD_START=( /sbin/init )
285 INITCMD_STOP=( /sbin/init )
287 _NEED_VSHELPER_SYNC=1
288 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
289 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
293 INITCMD_START=( /sbin/minit-start )
294 INITCMD_STOP=( /sbin/minit-stop )
296 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
297 _NEED_VSHELPER_SYNC=1
298 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
299 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
300 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
304 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
306 INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
307 INITCMD_STOP=( /sbin/rc shutdown )
308 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
310 pushd "$vdir"/vdir &>/dev/null
311 basever=$($_CHROOT_SH cat /etc/gentoo-release | $_AWK '{print $5}')
314 basemaj=${basever/.*}
315 basemin=${basever#*.}
316 basemin=${basemin/.*}
318 test "$basemaj" -lt 1 -o "$basemin" -lt 13 && \
320 Using init-style 'gentoo' requires >=baselayout-1.13 inside the vserver!
322 Your vserver ($(basename "$vdir")) seems to have baselayout-$basever,
323 please use 'plain' init-style instead!"
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
573 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${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 enableInterfaces
614 lock "$__LOCKDIR"/vserver.interfaces
616 while test $i -lt $INTERFACE_CMDS_IDX; do
617 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
628 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
630 NAMEIF) $_NAMEIF "$@";;
631 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
632 $_VCONFIG add "$2" "$3" >/dev/null;;
633 IP_ADDR) $_IP addr add "$@";;
634 IP_ADDR_FLUSH) $_IP addr flush "$@";;
635 IP_LINK) $_IP link set "$@";;
636 IP_ROUTE) $_IP route add "$@";;
637 *) echo "Unknown interface-command type '$type'" >&2; false;;
646 function disableInterfaces
648 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
650 local i=$INTERFACE_CMDS_IDX
653 lock "$__LOCKDIR"/vserver.interfaces
655 while test $i -gt 0; do
658 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
665 MODPROBE) $_RMMOD "${2:-$1}";;
667 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
668 IP_ADDR) $_IP addr del "$@";;
670 IP_LINK) ;; ## Ignore the link-down command for now
671 IP_ROUTE) $_IP route del "$@";;
672 *) echo "Unknown interface-command type '$type'" >&2; false;;
679 ## Usage: prepareInit <vserver-directory>
682 pushd "$1/vdir" >/dev/null
685 { find var/run ! -type d -print0; \
686 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
689 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
690 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
695 "${INITCMD_PREPARE[@]}"
699 ## Usage: prepareInit <vserver-directory>
702 pushd "$1/vdir" >/dev/null
705 export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
708 "${STOPCMD_PREPARE[@]}"
713 function generateOptions
715 _generateInterfaceOptions "$1"
716 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
717 _generateNiceCommand "$1"
718 _generateInitOptions "$1"
719 _generateChcontextOptions "$1"
720 _generateScheduleOptions "$1"
721 _generatePersonalityOptions "$1"
723 if test -n "$_IS_FAKEINIT"; then
724 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
725 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
733 local f="$vdir"/cpuset
737 test -d "$f" || return 0
738 test -e "$f"/name || return 0
740 read cpuset < "$f"/name
741 test -e "$f"/nocreate || {
742 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
743 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
744 if test -e "$f"/"$i"; then
745 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
753 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
754 if [ "$configured" -ne 0 ]; then
756 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
757 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
762 function removeCPUSET
766 local f="$vdir"/cpuset
768 test -d "$f" || return 0
769 test -e "$f"/name || return 0
771 read cpuset < "$f"/name
772 test -e "$f"/nocreate || {
773 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
777 function _mountVserverInternal
782 test -e "$fstab" || return 0
785 pushd "$vdir" >/dev/null
786 # check whether / is mounted readonly or whether there is special
787 # magic regarding the mtab file; when etc/mtab can not be touched,
788 # add the '-n' flag to mount
789 test -w etc -o -w etc/mtab || xflag=-n
790 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
798 local fstab="$cfgdir"/fstab
801 test -e "$fstab" || return 0
802 pushd "$vdir" >/dev/null
803 # check whether / is mounted readonly or whether there is special
804 # magic regarding the mtab file; when etc/mtab can not be touched,
805 # add the '-n' flag to mount
806 test -w etc -o -w etc/mtab || xflag=-n
807 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
811 function mountVserver
818 test -e "$cfgdir"/fstab -o \
819 -e "$cfgdir"/fstab.local -o \
820 -e "$cfgdir"/fstab.remote || return 0
822 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
824 pushd "$vdir" >/dev/null
825 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
828 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
830 _mountVserverInternal "$cfgdir"/fstab
831 _mountVserverInternal "$cfgdir"/fstab.local
832 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
834 isNamespaceCleanup "$cfgdir" && \
835 _namespaceCleanup "$cfgdir"
837 isAvoidNamespace "$cfgdir" || \
838 $_SECURE_MOUNT --rbind -n "$vdir" "/"
841 function _umountVserverInternal
844 test -e "$fstab" || return 0
849 while read src dst tmp; do
850 test -n "$tmp" || continue
856 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
862 function umountVserver
868 isAvoidNamespace "$cfgdir" || return 0
869 test -e "$cfgdir"/fstab -o \
870 -e "$cfgdir"/fstab.local -o \
871 -e "$cfgdir"/fstab.remote || return 0
872 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
874 pushd "$vdir/" >/dev/null || return 1
875 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
876 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
877 _umountVserverInternal "$cfgdir"/fstab || is_ok=
878 popd >/dev/null || return 1
883 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
887 test -n "$_NEED_VSHELPER_SYNC" && \
888 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
890 vshelper.initSync "$1" "$3" "$_is_meth"
893 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
896 if $_VSERVER_INFO - FEATURE vwait; then
898 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
901 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
903 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
906 if test "$rc" -ne 0 -a "$rc" -ne 1; then
907 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
908 killContext "$S_CONTEXT" 9
912 ) 4>$_is_tmpdir/procs &
914 echo "$!" >$_is_tmpdir/pid
915 eval "$3"=$_is_tmpdir
920 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
921 function _waitForVWait
926 declare -r procs=$(cat $4)
928 getFileArray status "$2"
933 'vwait' exited with error '$2' which indicates that vserver could not
938 A timeout occured while waiting for the vserver to finish and it was
939 killed by sending a SIGKILL signal. Please investigate the reasons
940 and/or increase the timeout in apps/vshelper/sync-timeout."
943 (TIMEOUT) warning $"\
944 A timeout occured while waiting for the vserver to finish and it will
945 be killed by sending a SIGKILL signal. The following process list
946 might be useful for finding out the reason of this behavior:
948 ----------------------------------------------------------------------
950 }----------------------------------------------------------------------"
953 (\?\?\?|*) warning $"\
954 internal error: 'vwait' exited with an unexpected status '$1'; I will
955 try to continue but be prepared for unexpected events."
962 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
967 local vwait_statdir=$3
970 if test -d "$vwait_statdir"; then
971 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
972 elif test -n "$_NEED_VSHELPER_SYNC"; then
973 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
975 A timeout or other error occured while waiting for the synchronization
976 signal from vserver '$VSERVER_NAME'.
977 The vserver will be killed nevertheless..."
978 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
979 "${INITCMD_STOP_SYNC[@]}" || \
981 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
982 will be killed nevertheless..."
985 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
991 local vdir name flavor start i already_handled base
995 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
996 function execScriptlets
1000 declare -r flavor=$3
1003 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1004 local DONT_SKIP_DEFAULTS=
1005 local already_handled=
1007 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1008 isRegularFile "$i" || continue
1009 test -r "$i" || continue
1013 test -x "$i" || start=_sourceWrap
1014 $start "$i" "$flavor" "$name"
1017 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1022 function sanityCheck
1024 declare -r cfgdir=$1
1026 ! test -e "$cfgdir"/fstab.local ||
1028 WARNING: 'fstab' will *not* be executed in the network context of the
1029 vserver anymore. Therefore, 'fstab.local' has the same functionality
1030 and is obsoleted. When you need the old behaviour, put the mounts
1031 into 'fstab.remote'"
1033 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1035 WARNING: The hostname is now configured in 'uts/nodename' but not in
1038 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1040 WARNING: The domainname is now configured in 'uts/domainname' but not
1041 in 'domainname'." >&2
1045 for i in "$cfgdir"/interfaces/*/only_ip; do
1046 if test -e "$i"; then
1048 iface=${i##$cfgdir/interfaces/}
1049 iface=${iface%%/only_ip}
1051 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1056 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1058 WARNING: There is no cachedirectory configured for this vserver;
1059 please create '$cfgdir/cache' e.g. by executing
1061 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1064 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1066 vshelper.doSanityCheck
1068 $_VSERVER_INFO - VERIFYCAP ||
1069 panic $"capabilities are not enabled in kernel-setup"
1071 $_VSERVER_INFO - VERIFYPROC ||
1073 /proc/uptime can not be accessed. Usually, this is caused by
1074 procfs-security. Please read the FAQ for more details
1075 http://linux-vserver.org/Proc-Security"
1079 function _setSingleDiskLimit
1091 getFileValue ctx "$vdir/context"
1092 getFileValue directory "$dlimit/directory" || return 0
1093 getFileValue space_total "$dlimit/space_total" || return 0
1094 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1095 getFileValue reserved "$dlimit/reserved" || return 0
1097 local cachename=$ctx$directory
1098 cachename=dlimits/${cachename//\//_}
1100 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1101 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1102 $_RM -f "$vdir/cache/$cachename"
1104 if test -z "$inodes_used" -o -z "$space_used"; then
1106 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1107 inodes_used=${tmpvdu##* }
1108 space_used=${tmpvdu%% *}
1111 $_VDLIMIT --xid $ctx \
1112 --set space_used=$space_used \
1113 --set space_total=$space_total \
1114 --set inodes_used=$inodes_used \
1115 --set inodes_total=$inodes_total \
1116 --set reserved=$reserved \
1121 function setDiskLimits
1126 # Disk Limits without a static context are useless
1127 test -e "$vdir"/context || return 0
1129 for dlimit in "$vdir/dlimits/"*; do
1130 test -d "$dlimit" || continue
1131 test ! -e "$dlimit/disabled" || continue
1133 _setSingleDiskLimit "$vdir" "$dlimit"
1138 function _saveSingleDiskLimit
1145 getFileValue ctx "$vdir/context"
1146 getFileValue directory "$dlimit/directory" || return 0
1148 local cachename=$ctx$directory
1149 cachename=${cachename//\//_}
1151 # Things are getting ugly here... LFS says that /var/cache (where
1152 # cachename is usually pointing to) can vanish and applications
1153 # have to deal with it. So, we have to interprete the $vdir/cache
1154 # symlink and have to create the needed directories manually.
1155 if test -d "$vdir/cache"; then
1156 : # ok, exists already
1157 elif test -L "$vdir/cache"; then
1158 # it's a dangling symlink
1160 link=$($_READLINK "$vdir/cache")
1161 ( cd $vdir && $_MKDIR -p "$link" )
1166 test -d "$vdir/cache"
1167 $_MKDIR -p "$vdir"/cache/dlimits
1169 $_VDLIMIT --xid $ctx "$directory" | \
1170 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1172 $_VDLIMIT --xid $ctx --remove "$directory"
1176 function saveDiskLimits
1181 test -e "$vdir"/context || return 0
1183 for dlimit in "$vdir/dlimits/"*; do
1184 test -d "$dlimit" || continue
1185 test ! -e "$dlimit/disabled" || continue
1187 _saveSingleDiskLimit "$vdir" "$dlimit"
1191 function _namespaceCleanup
1194 local root=$($_VSERVER_INFO "$1" VDIR 1)
1199 getFileArray skip "$vdir"/namespace-cleanup-skip \
1200 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1202 # these are things that have to be accessible post-cleanup
1203 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1204 "$__PKGSTATEDIR" "${skip[@]}"; do
1205 while test -n "$tmp"; do
1206 list=( "${list[@]}" "$tmp" )
1211 local -a list_umount
1212 while read dev path opts; do
1213 test -n "$path" || continue
1214 for i in "$root" /dev /proc; do
1215 test "${path#$i}" != "$path" && continue 2
1217 for i in "${list[@]}" /; do
1218 test "$path" = "$i" && continue 2
1220 # unmount them in reverse order so mounts further down the tree get unmounted first
1221 list_umount=( "$path" "${list_umount[@]}" )
1223 # separate loop to avoid races while reading /proc/mounts
1224 for i in "${list_umount[@]}"; do
1229 function loadDeviceMap
1233 local flags device target
1235 test -d "$dir" || return 0
1237 for i in "$dir"/*; do
1238 test -d "$i" || continue
1240 local -a vdevmap_opts=()
1241 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1242 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1243 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1245 getFileValue flags "$i/flags" || :
1246 getFileValue device "$i/device" || :
1247 getFileValue target "$i/target" || :
1248 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1249 ${device:+--device "$device"} ${target:+--target "$target"} )
1251 $_VDEVMAP --xid "$xid" "${vdevmap_opts[@]}" || return $?