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 )
281 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
282 if test -n "$OPTION_DEBUG_SYSV"; then
283 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
284 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
289 INITCMD_START=( /sbin/init )
290 INITCMD_STOP=( /sbin/init )
292 _NEED_VSHELPER_SYNC=1
293 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
294 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
298 INITCMD_START=( /sbin/minit-start )
299 INITCMD_STOP=( /sbin/minit-stop )
301 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
302 _NEED_VSHELPER_SYNC=1
303 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
304 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
305 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
309 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
311 INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
312 INITCMD_STOP=( env -i TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
313 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
317 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
320 if test x"$INITSTYLE" != xrescue; then
321 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
322 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
323 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
324 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
325 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
328 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
329 INITCMD_START_SYNC=()
334 if vshelper.isEnabled; then
335 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
341 function _generateFlagOptions
345 CHCONTEXT_FLAG_OPTS=()
347 test ! -e "$vdir"/flags || \
356 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
357 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
363 isAvoidNamespace "$vdir" || {
365 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
369 function _generateChcontextOptions
372 local ctx hostname domainname
377 read ctx <"$vdir"/context || :
379 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
380 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
383 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
385 _generateCapabilityOptions "$vdir"
386 _generateFlagOptions "$vdir"
388 CHCONTEXT_OPTS=( $SILENT_OPT \
389 "${CHCONTEXT_FLAG_OPTS[@]}" \
392 ${ctx:+--ctx "$ctx"} \
393 ${hostname:+--hostname "$hostname"} \
394 ${domainname:+--domainname "$domainname"} )
396 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
397 ${ctx:+--xid "$ctx"} )
398 ## put '--secure' at front so that it can be overridden
399 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
402 function _generateScheduleOptions
405 if test -d "$vdir"/sched; then
406 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
410 local f="$vdir"/schedule
411 test -e "$f" || return 0
413 local fill_rate interval tokens tokens_min tokens_max prio_bias
421 read prio_bias || prio_bias=
425 test -n "$prio_bias" || {
426 echo $"Bad content in '$f'; aborting..." >&2
430 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
431 --tokens "$tokens" --tokens_min "$tokens_min" \
432 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
435 function _getInterfaceValue
445 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
448 : ${_giv_tmp:=$_giv_dflt}
449 eval $_giv_val=\$_giv_tmp
452 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
453 function _transformMask2Prefix
457 test -n "$_tm2p_tmp" || {
458 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
465 function _addInterfaceCmd
467 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
468 let ++INTERFACE_CMDS_IDX
471 ## Usage: _generateMac <var> <iface> <ctx>
472 function _generateMac
475 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
479 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
482 function _getVLANInfo
487 creation of VLAN_PLUS_VID devices is not supported; please create them
488 before starting the vserver and use the 'nodev' flag then"
489 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
493 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
494 create them before starting the vserver and use the 'nodev' flag then"
495 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
497 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
498 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
505 ## Usage: _processSingleInterface <interface-directory>
506 function _processSingleInterface
521 _getInterfaceValue ip '' "$iface"
522 _getInterfaceValue extip '' "$iface" "$iface/.."
523 _getInterfaceValue dev '' "$iface" "$iface/.."
524 _getInterfaceValue prefix '' "$iface" "$iface/.."
525 _getInterfaceValue mask '' "$iface" "$iface/.."
526 _getInterfaceValue bcast '' "$iface" "$iface/.."
527 _getInterfaceValue name '' "$iface"
528 _getInterfaceValue scope '' "$iface" "$iface/.."
529 _getInterfaceValue mac '' "$iface"
531 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
532 test -n "$dev" -o -e "$iface"/nodev || {
533 echo $"No device specified for '$iface'" >&2
537 test ! -e "$iface"/down || up=
540 _transformMask2Prefix prefix "$prefix" "$mask"
541 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
543 test ! -e "$iface"/nodev || break
545 test ! -e "$iface"/only_ip || break
547 test -e "$iface/vlandev" \
548 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
549 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
550 -a ! -e "$iface/novlandev" \
551 -a ! -e "$iface/../novlandev" \) && {
553 if vlan_info=$(_getVLANInfo "$dev"); then
554 test -d /proc/net/vlan || {
555 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
558 _addInterfaceCmd VCONFIG $vlan_info
562 if ! test -e "$iface"/indirect; then
564 use_bcast="broadcast ${bcast:-+}"
565 echo "$ip" | $_GREP -q : && use_bcast=
566 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
567 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
568 _addInterfaceCmd IP_LINK "$dev" $up
569 elif ! test -n "$ctx"; then
570 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
573 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
574 _addInterfaceCmd MODPROBE dummy "$dev"
575 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
576 _addInterfaceCmd NAMEIF "$dev" "$mac"
577 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
578 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
585 ## Usage: _generateInterfaceOptions <vserver-directory>
586 function _generateInterfaceOptions
591 test ! -e "$1"/context || read ctx <"$1"/context
593 for iface in "$1/interfaces/"*; do
594 test -d "$iface" || continue
595 test ! -e "$iface"/disabled || continue
597 _processSingleInterface "$iface"
599 _HAVE_INTERFACE_OPTIONS=1
602 function enableInterfaces
607 lock "$__LOCKDIR"/vserver.interfaces
609 while test $i -lt $INTERFACE_CMDS_IDX; do
610 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
621 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
623 NAMEIF) $_NAMEIF "$@";;
624 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
625 $_VCONFIG add "$2" "$3" >/dev/null;;
626 IP_ADDR) $_IP addr add "$@";;
627 IP_ADDR_FLUSH) $_IP addr flush "$@";;
628 IP_LINK) $_IP link set "$@";;
629 IP_ROUTE) $_IP route add "$@";;
630 *) echo "Unknown interface-command type '$type'" >&2; false;;
639 function disableInterfaces
641 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
643 local i=$INTERFACE_CMDS_IDX
646 lock "$__LOCKDIR"/vserver.interfaces
648 while test $i -gt 0; do
651 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
658 MODPROBE) $_RMMOD "${2:-$1}";;
660 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
661 IP_ADDR) $_IP addr del "$@";;
663 IP_LINK) ;; ## Ignore the link-down command for now
664 IP_ROUTE) $_IP route del "$@";;
665 *) echo "Unknown interface-command type '$type'" >&2; false;;
672 ## Usage: prepareInit <vserver-directory>
675 pushd "$1/vdir" >/dev/null
678 { find var/run ! -type d -print0; \
679 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
682 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
683 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
688 "${INITCMD_PREPARE[@]}"
692 ## Usage: prepareInit <vserver-directory>
695 pushd "$1/vdir" >/dev/null
698 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
701 "${STOPCMD_PREPARE[@]}"
706 function generateOptions
708 _generateInterfaceOptions "$1"
709 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
710 _generateNiceCommand "$1"
711 _generateInitOptions "$1"
712 _generateChcontextOptions "$1"
713 _generateScheduleOptions "$1"
714 _generatePersonalityOptions "$1"
716 if test -n "$_IS_FAKEINIT"; then
717 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
718 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
726 local f="$vdir"/cpuset
730 test -d "$f" || return 0
731 test -e "$f"/name || return 0
733 read cpuset < "$f"/name
734 test -e "$f"/nocreate || {
735 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
736 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
737 if test -e "$f"/"$i"; then
738 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
746 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
747 if [ "$configured" -ne 0 ]; then
749 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
750 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
755 function removeCPUSET
759 local f="$vdir"/cpuset
761 test -d "$f" || return 0
762 test -e "$f"/name || return 0
764 read cpuset < "$f"/name
765 test -e "$f"/nocreate || {
766 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
770 function _mountVserverInternal
775 test -e "$fstab" || return 0
778 pushd "$vdir" >/dev/null
779 # check whether / is mounted readonly or whether there is special
780 # magic regarding the mtab file; when etc/mtab can not be touched,
781 # add the '-n' flag to mount
782 test -w etc -o -w etc/mtab || xflag=-n
783 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
791 local fstab="$cfgdir"/fstab
794 test -e "$fstab" || return 0
795 pushd "$vdir" >/dev/null
796 # check whether / is mounted readonly or whether there is special
797 # magic regarding the mtab file; when etc/mtab can not be touched,
798 # add the '-n' flag to mount
799 test -w etc -o -w etc/mtab || xflag=-n
800 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
804 function mountVserver
811 test -e "$cfgdir"/fstab -o \
812 -e "$cfgdir"/fstab.local -o \
813 -e "$cfgdir"/fstab.remote || return 0
815 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
817 pushd "$vdir" >/dev/null
818 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
821 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
823 _mountVserverInternal "$cfgdir"/fstab
824 _mountVserverInternal "$cfgdir"/fstab.local
825 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
827 isNamespaceCleanup "$cfgdir" && \
828 _namespaceCleanup "$cfgdir"
830 isAvoidNamespace "$cfgdir" || \
831 $_SECURE_MOUNT --rbind -n "$vdir" "/"
834 function _umountVserverInternal
837 test -e "$fstab" || return 0
842 while read src dst tmp; do
843 test -n "$tmp" || continue
849 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
855 function umountVserver
861 isAvoidNamespace "$cfgdir" || return 0
862 test -e "$cfgdir"/fstab -o \
863 -e "$cfgdir"/fstab.local -o \
864 -e "$cfgdir"/fstab.remote || return 0
865 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
867 pushd "$vdir/" >/dev/null || return 1
868 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
869 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
870 _umountVserverInternal "$cfgdir"/fstab || is_ok=
871 popd >/dev/null || return 1
876 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
880 test -n "$_NEED_VSHELPER_SYNC" && \
881 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
883 vshelper.initSync "$1" "$3" "$_is_meth"
886 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
889 if $_VSERVER_INFO - FEATURE vwait; then
891 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
894 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
896 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
899 if test "$rc" -ne 0 -a "$rc" -ne 1; then
900 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
901 killContext "$S_CONTEXT" 9
905 ) 4>$_is_tmpdir/procs &
907 echo "$!" >$_is_tmpdir/pid
908 eval "$3"=$_is_tmpdir
913 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
914 function _waitForVWait
919 declare -r procs=$(cat $4)
921 getFileArray status "$2"
926 'vwait' exited with error '$2' which indicates that vserver could not
931 A timeout occured while waiting for the vserver to finish and it was
932 killed by sending a SIGKILL signal. Please investigate the reasons
933 and/or increase the timeout in apps/vshelper/sync-timeout."
936 (TIMEOUT) warning $"\
937 A timeout occured while waiting for the vserver to finish and it will
938 be killed by sending a SIGKILL signal. The following process list
939 might be useful for finding out the reason of this behavior:
941 ----------------------------------------------------------------------
943 }----------------------------------------------------------------------"
946 (\?\?\?|*) warning $"\
947 internal error: 'vwait' exited with an unexpected status '$1'; I will
948 try to continue but be prepared for unexpected events."
955 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
960 local vwait_statdir=$3
963 if test -d "$vwait_statdir"; then
964 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
965 elif test -n "$_NEED_VSHELPER_SYNC"; then
966 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
968 A timeout or other error occured while waiting for the synchronization
969 signal from vserver '$VSERVER_NAME'.
970 The vserver will be killed nevertheless..."
971 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
972 "${INITCMD_STOP_SYNC[@]}" || \
974 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
975 will be killed nevertheless..."
978 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
984 local vdir name flavor start i already_handled base
988 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
989 function execScriptlets
996 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
997 local DONT_SKIP_DEFAULTS=
998 local already_handled=
1000 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1001 isRegularFile "$i" || continue
1002 test -r "$i" || continue
1006 test -x "$i" || start=_sourceWrap
1007 $start "$i" "$flavor" "$name"
1010 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1015 function sanityCheck
1017 declare -r cfgdir=$1
1019 ! test -e "$cfgdir"/fstab.local ||
1021 WARNING: 'fstab' will *not* be executed in the network context of the
1022 vserver anymore. Therefore, 'fstab.local' has the same functionality
1023 and is obsoleted. When you need the old behaviour, put the mounts
1024 into 'fstab.remote'"
1026 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1028 WARNING: The hostname is now configured in 'uts/nodename' but not in
1031 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1033 WARNING: The domainname is now configured in 'uts/domainname' but not
1034 in 'domainname'." >&2
1038 for i in "$cfgdir"/interfaces/*/only_ip; do
1039 if test -e "$i"; then
1041 iface=${i##$cfgdir/interfaces/}
1042 iface=${iface%%/only_ip}
1044 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1049 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1051 WARNING: There is no cachedirectory configured for this vserver;
1052 please create '$cfgdir/cache' e.g. by executing
1054 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1057 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1059 vshelper.doSanityCheck
1061 $_VSERVER_INFO - VERIFYCAP ||
1062 panic $"capabilities are not enabled in kernel-setup"
1064 $_VSERVER_INFO - VERIFYPROC ||
1066 /proc/uptime can not be accessed. Usually, this is caused by
1067 procfs-security. Please read the FAQ for more details
1068 http://linux-vserver.org/Proc-Security"
1072 function _setSingleDiskLimit
1084 getFileValue ctx "$vdir/context"
1085 getFileValue directory "$dlimit/directory" || return 0
1086 getFileValue space_total "$dlimit/space_total" || return 0
1087 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1088 getFileValue reserved "$dlimit/reserved" || return 0
1090 local cachename=$ctx$directory
1091 cachename=dlimits/${cachename//\//_}
1093 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1094 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1095 $_RM -f "$vdir/cache/$cachename"
1097 if test -z "$inodes_used" -o -z "$space_used"; then
1099 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1100 inodes_used=${tmpvdu##* }
1101 space_used=${tmpvdu%% *}
1104 $_VDLIMIT --xid $ctx \
1105 --set space_used=$space_used \
1106 --set space_total=$space_total \
1107 --set inodes_used=$inodes_used \
1108 --set inodes_total=$inodes_total \
1109 --set reserved=$reserved \
1114 function setDiskLimits
1119 # Disk Limits without a static context are useless
1120 test -e "$vdir"/context || return 0
1122 for dlimit in "$vdir/dlimits/"*; do
1123 test -d "$dlimit" || continue
1124 test ! -e "$dlimit/disabled" || continue
1126 _setSingleDiskLimit "$vdir" "$dlimit"
1131 function _saveSingleDiskLimit
1138 getFileValue ctx "$vdir/context"
1139 getFileValue directory "$dlimit/directory" || return 0
1141 local cachename=$ctx$directory
1142 cachename=${cachename//\//_}
1144 # Things are getting ugly here... LFS says that /var/cache (where
1145 # cachename is usually pointing to) can vanish and applications
1146 # have to deal with it. So, we have to interprete the $vdir/cache
1147 # symlink and have to create the needed directories manually.
1148 if test -d "$vdir/cache"; then
1149 : # ok, exists already
1150 elif test -L "$vdir/cache"; then
1151 # it's a dangling symlink
1153 link=$($_READLINK "$vdir/cache")
1154 ( cd $vdir && $_MKDIR -p "$link" )
1159 test -d "$vdir/cache"
1160 $_MKDIR -p "$vdir"/cache/dlimits
1162 $_VDLIMIT --xid $ctx "$directory" | \
1163 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1165 $_VDLIMIT --xid $ctx --remove "$directory"
1169 function saveDiskLimits
1174 test -e "$vdir"/context || return 0
1176 for dlimit in "$vdir/dlimits/"*; do
1177 test -d "$dlimit" || continue
1178 test ! -e "$dlimit/disabled" || continue
1180 _saveSingleDiskLimit "$vdir" "$dlimit"
1184 function _namespaceCleanup
1187 local root=$($_VSERVER_INFO "$1" VDIR 1)
1192 getFileArray skip "$vdir"/namespace-cleanup-skip \
1193 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1195 # these are things that have to be accessible post-cleanup
1196 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1197 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1198 while test -n "$tmp"; do
1199 list=( "${list[@]}" "$tmp" )
1204 local -a list_umount
1205 while read dev path opts; do
1206 test -n "$path" || continue
1207 for i in "$root" /dev /proc; do
1208 test "${path#$i}" != "$path" && continue 2
1210 for i in "${list[@]}" /; do
1211 test "$path" = "$i" && continue 2
1213 # unmount them in reverse order so mounts further down the tree get unmounted first
1214 list_umount=( "$path" "${list_umount[@]}" )
1216 # separate loop to avoid races while reading /proc/mounts
1217 for i in "${list_umount[@]}"; do
1222 function loadDeviceMap
1226 local flags device target
1228 test -d "$dir" || return 0
1230 for i in "$dir"/*; do
1231 test -d "$i" || continue
1233 local -a vdevmap_opts=()
1234 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1235 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1236 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1238 getFileValue flags "$i/flags" || :
1239 getFileValue device "$i/device" || :
1240 getFileValue target "$i/target" || :
1241 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1242 ${device:+--device "$device"} ${target:+--target "$target"} )
1244 $_VDEVMAP --xid "$xid" "${vdevmap_opts[@]}" || return $?