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 _generateChbindOptions
83 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
85 local f=$vdir/interfaces/bcast
86 getFileValue bcast "$f"
88 getFileValue nid "$vdir/ncontext" "$vdir/context"
90 CHBIND_OPTS=( $SILENT_OPT ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
92 for i in "${INTERFACES[@]}"; do
93 CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
96 _HAVE_CHBIND_OPTIONS=1
99 function _generateNiceCommand
103 local current_nice=`$_NICE`
105 test -r "$vdir/nice" && read nice <"$vdir"/nice
107 let nice=$nice-$current_nice || :
108 NICE_CMD=( $_NICE -n $nice )
112 function _generatePersonalityOptions
115 local f="$vdir"/personality
118 test -s "$f" || return 0
127 (*) flags=$flags$delim$tmp
134 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
135 --personality-type "$type"
136 ${flags:+--personality-flags "$flags"} )
139 function _generateCCapabilityOptions
143 local f="$vdir"/ccapabilities
145 test -e "$f" || return 0
149 (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --ccap "$cap" );;
154 function _generateBCapabilityOptions
158 local f="$vdir"/bcapabilities
160 test -e "$f" || return 0
164 (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --bcap "$cap" );;
169 function _generateCapabilityOptions
174 _generateBCapabilityOptions "$vdir"
175 _generateCCapabilityOptions "$vdir"
177 test -e "$vdir"/capabilities || return 0
186 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
187 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
190 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
193 done <"$vdir"/capabilities
196 function getEnterShell
203 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
205 test -n "$ENTER_SHELL" || {
207 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
209 test -x "$vdir/vdir/$1" || continue
216 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
217 function sendKillSequence
223 while isCtxRunning "$ctx"; do
224 test -z "$wait" || sleep "$wait"
226 killContext "$ctx" "$1"
227 test -n "$2" || break
233 function _generateInitOptions
236 local cfgdir=$vdir/apps/init
241 INITCMD_START_SYNC=()
246 INITKILL_SEQ=( 15 5 9 )
247 CHCONTEXT_INIT_OPTS=()
250 getFileValue INITSTYLE "$cfgdir"/style
251 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
252 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
253 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
254 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
256 findFile _gio_env "$cfgdir"/environment \
257 "$__CONFDIR"/.defaults/apps/init/environment \
258 "$__PKGLIBDEFAULTDIR"/environment
259 getFileArray OPTS_ENV "$_gio_env" || :
261 case x"$INITSTYLE" in
263 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
264 INITCMD_STOP=( /sbin/killall5 )
270 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
271 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
273 for i in /etc/init.d/rc /etc/rc.d/rc; do
274 test -x "$vdir/vdir/$i" || continue
275 INITCMD_START=( "$i" "$RUNLEVEL_START" )
276 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
278 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
282 INITCMD_START=( /sbin/init )
283 INITCMD_STOP=( /sbin/init )
285 _NEED_VSHELPER_SYNC=1
286 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
287 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
291 INITCMD_START=( /sbin/minit-start )
292 INITCMD_STOP=( /sbin/minit-stop )
294 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
295 _NEED_VSHELPER_SYNC=1
296 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
297 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
298 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
302 INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh )
303 INITCMD_STOP=( /sbin/rc shutdown )
305 pushd "$vdir"/vdir &>/dev/null
306 basever=$($_CHROOT_SH cat /etc/gentoo-release | $_AWK '{print $5}')
309 basemaj=${basever/.*}
310 basemin=${basever#*.}
311 basemin=${basemin/.*}
313 test "$basemaj" -lt 1 -o "$basemin" -lt 13 && \
315 Using init-style 'gentoo' requires >=baselayout-1.13 inside the vserver!
317 Your vserver ($(basename "$vdir")) seems to have baselayout-$basever,
318 please use 'plain' init-style instead!"
322 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
325 if test x"$INITSTYLE" != xrescue; then
326 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
327 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
328 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
329 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
330 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
333 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
334 INITCMD_START_SYNC=()
339 if vshelper.isEnabled; then
340 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
346 function _generateFlagOptions
350 CHCONTEXT_FLAG_OPTS=()
352 test ! -e "$vdir"/flags || \
361 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
362 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
368 isAvoidNamespace "$vdir" || {
370 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
374 function _generateChcontextOptions
377 local ctx hostname domainname
382 read ctx <"$vdir"/context || :
384 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
385 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
388 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
390 _generateCapabilityOptions "$vdir"
391 _generateFlagOptions "$vdir"
393 CHCONTEXT_OPTS=( $SILENT_OPT \
394 "${CHCONTEXT_FLAG_OPTS[@]}" \
397 ${ctx:+--ctx "$ctx"} \
398 ${hostname:+--hostname "$hostname"} \
399 ${domainname:+--domainname "$domainname"} )
401 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
402 ${ctx:+--xid "$ctx"} )
403 ## put '--secure' at front so that it can be overridden
404 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
407 function _generateScheduleOptions
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
548 if vlan_info=$(_getVLANInfo "$dev"); then
549 test -d /proc/net/vlan || {
550 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
553 test -e "$iface/vlandev" \
554 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
555 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
556 -a ! -e "$iface/novlandev" \
557 -a ! -e "$iface/../novlandev" \) && {
558 _addInterfaceCmd VCONFIG $vlan_info
562 if ! test -e "$iface"/indirect; then
563 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
564 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
565 _addInterfaceCmd IP_LINK "$dev" $up
566 elif ! test -n "$ctx"; then
567 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
570 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
571 _addInterfaceCmd MODPROBE dummy "$dev"
572 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
573 _addInterfaceCmd NAMEIF "$dev" "$mac"
574 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
575 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
582 ## Usage: _generateInterfaceOptions <vserver-directory>
583 function _generateInterfaceOptions
588 test ! -e "$1"/context || read ctx <"$1"/context
590 for iface in "$1/interfaces/"*; do
591 test -d "$iface" || continue
592 test ! -e "$iface"/disabled || continue
594 _processSingleInterface "$iface"
596 _HAVE_INTERFACE_OPTIONS=1
599 function enableInterfaces
604 lock "$__LOCKDIR"/vserver.interfaces
606 while test $i -lt $INTERFACE_CMDS_IDX; do
607 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
618 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
620 NAMEIF) $_NAMEIF "$@";;
621 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
622 $_VCONFIG add "$2" "$3" >/dev/null;;
623 IP_ADDR) $_IP addr add "$@";;
624 IP_ADDR_FLUSH) $_IP addr flush "$@";;
625 IP_LINK) $_IP link set "$@";;
626 IP_ROUTE) $_IP route add "$@";;
627 *) echo "Unknown interface-command type '$type'" >&2; false;;
636 function disableInterfaces
638 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
640 local i=$INTERFACE_CMDS_IDX
643 lock "$__LOCKDIR"/vserver.interfaces
645 while test $i -gt 0; do
648 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
655 MODPROBE) $_RMMOD "${2:-$1}";;
657 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
658 IP_ADDR) $_IP addr del "$@";;
660 IP_LINK) ;; ## Ignore the link-down command for now
661 IP_ROUTE) $_IP route del "$@";;
662 *) echo "Unknown interface-command type '$type'" >&2; false;;
669 ## Usage: prepareInit <vserver-directory>
672 pushd "$1/vdir" >/dev/null
675 { find var/run ! -type d -print0; \
676 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
679 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
680 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
685 "${INITCMD_PREPARE[@]}"
689 ## Usage: prepareInit <vserver-directory>
692 pushd "$1/vdir" >/dev/null
695 export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
698 "${STOPCMD_PREPARE[@]}"
703 function generateOptions
705 _generateInterfaceOptions "$1"
706 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
707 _generateNiceCommand "$1"
708 _generateInitOptions "$1"
709 _generateChcontextOptions "$1"
710 _generateScheduleOptions "$1"
711 _generatePersonalityOptions "$1"
713 if test -n "$_IS_FAKEINIT"; then
714 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
715 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
723 local f="$vdir"/cpuset
727 test -d "$f" || return 0
728 test -e "$f"/name || return 0
730 read cpuset < "$f"/name
731 test -e "$f"/nocreate || {
732 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
733 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
734 if test -e "$f"/"$i"; then
735 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
743 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
744 if [ "$configured" -ne 0 ]; then
746 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
747 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
752 function removeCPUSET
756 local f="$vdir"/cpuset
758 test -d "$f" || return 0
759 test -e "$f"/name || return 0
761 read cpuset < "$f"/name
762 test -e "$f"/nocreate || {
763 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
767 function _mountVserverInternal
772 test -e "$fstab" || return 0
775 pushd "$vdir" >/dev/null
776 # check whether / is mounted readonly or whether there is special
777 # magic regarding the mtab file; when etc/mtab can not be touched,
778 # add the '-n' flag to mount
779 test -w etc -o -w etc/mtab || xflag=-n
780 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
788 local fstab="$cfgdir"/fstab
791 test -e "$fstab" || return 0
792 pushd "$vdir" >/dev/null
793 # check whether / is mounted readonly or whether there is special
794 # magic regarding the mtab file; when etc/mtab can not be touched,
795 # add the '-n' flag to mount
796 test -w etc -o -w etc/mtab || xflag=-n
797 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
801 function mountVserver
808 test -e "$cfgdir"/fstab -o \
809 -e "$cfgdir"/fstab.local -o \
810 -e "$cfgdir"/fstab.remote || return 0
812 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
814 pushd "$vdir" >/dev/null
815 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
818 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
820 _mountVserverInternal "$cfgdir"/fstab
821 _mountVserverInternal "$cfgdir"/fstab.local
822 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
824 isNamespaceCleanup "$cfgdir" && \
825 _namespaceCleanup "$cfgdir"
827 isAvoidNamespace "$cfgdir" || \
828 $_SECURE_MOUNT --rbind -n "$vdir" "/"
831 function _umountVserverInternal
834 test -e "$fstab" || return 0
839 while read src dst tmp; do
840 test -n "$tmp" || continue
846 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
852 function umountVserver
858 isAvoidNamespace "$cfgdir" || return 0
859 test -e "$cfgdir"/fstab -o \
860 -e "$cfgdir"/fstab.local -o \
861 -e "$cfgdir"/fstab.remote || return 0
862 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
864 pushd "$vdir/" >/dev/null || return 1
865 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
866 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
867 _umountVserverInternal "$cfgdir"/fstab || is_ok=
868 popd >/dev/null || return 1
873 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
877 test -n "$_NEED_VSHELPER_SYNC" && \
878 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
880 vshelper.initSync "$1" "$3" "$_is_meth"
883 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
886 if $_VSERVER_INFO - FEATURE vwait; then
888 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
891 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
893 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
896 if test "$rc" -ne 0 -a "$rc" -ne 1; then
897 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
898 killContext "$S_CONTEXT" 9
902 ) 4>$_is_tmpdir/procs &
904 echo "$!" >$_is_tmpdir/pid
905 eval "$3"=$_is_tmpdir
910 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
911 function _waitForVWait
916 declare -r procs=$(cat $4)
918 getFileArray status "$2"
923 'vwait' exited with error '$2' which indicates that vserver could not
928 A timeout occured while waiting for the vserver to finish and it was
929 killed by sending a SIGKILL signal. Please investigate the reasons
930 and/or increase the timeout in apps/vshelper/sync-timeout."
933 (TIMEOUT) warning $"\
934 A timeout occured while waiting for the vserver to finish and it will
935 be killed by sending a SIGKILL signal. The following process list
936 might be useful for finding out the reason of this behavior:
938 ----------------------------------------------------------------------
940 }----------------------------------------------------------------------"
943 (\?\?\?|*) warning $"\
944 internal error: 'vwait' exited with an unexpected status '$1'; I will
945 try to continue but be prepared for unexpected events."
952 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
957 local vwait_statdir=$3
960 if test -d "$vwait_statdir"; then
961 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
962 elif test -n "$_NEED_VSHELPER_SYNC"; then
963 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
965 A timeout or other error occured while waiting for the synchronization
966 signal from vserver '$VSERVER_NAME'.
967 The vserver will be killed nevertheless..."
968 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
969 "${INITCMD_STOP_SYNC[@]}" || \
971 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
972 will be killed nevertheless..."
975 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
981 local vdir name flavor start i already_handled base
985 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
986 function execScriptlets
993 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
994 local DONT_SKIP_DEFAULTS=
995 local already_handled=
997 for i in "$base/$flavor" "$base/$flavor.d"/*; do
998 isRegularFile "$i" || continue
999 test -r "$i" || continue
1003 test -x "$i" || start=_sourceWrap
1004 $start "$i" "$flavor" "$name"
1007 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1012 function sanityCheck
1014 declare -r cfgdir=$1
1016 ! test -e "$cfgdir"/fstab.local ||
1018 WARNING: 'fstab' will *not* be executed in the network context of the
1019 vserver anymore. Therefore, 'fstab.local' has the same functionality
1020 and is obsoleted. When you need the old behaviour, put the mounts
1021 into 'fstab.remote'"
1023 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1025 WARNING: The hostname is now configured in 'uts/nodename' but not in
1028 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1030 WARNING: The domainname is now configured in 'uts/domainname' but not
1031 in 'domainname'." >&2
1035 for i in "$cfgdir"/interfaces/*/only_ip; do
1036 if test -e "$i"; then
1038 iface=${i##$cfgdir/interfaces/}
1039 iface=${iface%%/only_ip}
1041 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1046 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1048 WARNING: There is no cachedirectory configured for this vserver;
1049 please create '$cfgdir/cache' e.g. by executing
1051 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1054 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1056 vshelper.doSanityCheck
1058 $_VSERVER_INFO - VERIFYCAP ||
1059 panic $"capabilities are not enabled in kernel-setup"
1061 $_VSERVER_INFO - VERIFYPROC ||
1063 /proc/uptime can not be accessed. Usually, this is caused by
1064 procfs-security. Please read the FAQ for more details
1065 http://www.linux-vserver.org/index.php?page=Linux-Vserver+FAQ"
1069 function _setSingleDiskLimit
1081 getFileValue ctx "$vdir/context"
1082 getFileValue directory "$dlimit/directory" || return 0
1083 getFileValue space_total "$dlimit/space_total" || return 0
1084 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1085 getFileValue reserved "$dlimit/reserved" || return 0
1087 local cachename=$ctx$directory
1088 cachename=dlimits/${cachename//\//_}
1090 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1091 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1092 $_RM -f "$vdir/cache/$cachename"
1094 if test -z "$inodes_used" -o -z "$space_used"; then
1096 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1097 inodes_used=${tmpvdu##* }
1098 space_used=${tmpvdu%% *}
1101 $_VDLIMIT --xid $ctx \
1102 --set space_used=$space_used \
1103 --set space_total=$space_total \
1104 --set inodes_used=$inodes_used \
1105 --set inodes_total=$inodes_total \
1106 --set reserved=$reserved \
1111 function setDiskLimits
1116 # Disk Limits without a static context are useless
1117 test -e "$vdir"/context || return 0
1119 for dlimit in "$vdir/dlimits/"*; do
1120 test -d "$dlimit" || continue
1121 test ! -e "$dlimit/disabled" || continue
1123 _setSingleDiskLimit "$vdir" "$dlimit"
1128 function _saveSingleDiskLimit
1135 getFileValue ctx "$vdir/context"
1136 getFileValue directory "$dlimit/directory" || return 0
1138 local cachename=$ctx$directory
1139 cachename=${cachename//\//_}
1141 # Things are getting ugly here... LFS says that /var/cache (where
1142 # cachename is usually pointing to) can vanish and applications
1143 # have to deal with it. So, we have to interprete the $vdir/cache
1144 # symlink and have to create the needed directories manually.
1145 if test -d "$vdir/cache"; then
1146 : # ok, exists already
1147 elif test -L "$vdir/cache"; then
1148 # it's a dangling symlink
1150 link=$($_READLINK "$vdir/cache")
1151 ( cd $vdir && $_MKDIR -p "$link" )
1156 test -d "$vdir/cache"
1157 $_MKDIR -p "$vdir"/cache/dlimits
1159 $_VDLIMIT --xid $ctx "$directory" | \
1160 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1164 function saveDiskLimits
1169 test -e "$vdir"/context || return 0
1171 for dlimit in "$vdir/dlimits/"*; do
1172 test -d "$dlimit" || continue
1173 test ! -e "$dlimit/disabled" || continue
1175 _saveSingleDiskLimit "$vdir" "$dlimit"
1179 function _namespaceCleanup
1182 local root=$($_VSERVER_INFO "$1" VDIR 1)
1187 getFileArray skip "$vdir"/namespace-cleanup-skip \
1188 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1190 # these are things that have to be accessible post-cleanup
1191 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1192 "$__PKGSTATEDIR" "${skip[@]}"; do
1193 while test -n "$tmp"; do
1194 list=( "${list[@]}" "$tmp" )
1199 local -a list_umount
1200 while read dev path opts; do
1201 test -n "$path" || continue
1202 for i in "$root" /dev /proc; do
1203 test "${path#$i}" != "$path" && continue 2
1205 for i in "${list[@]}" /; do
1206 test "$path" = "$i" && continue 2
1208 # unmount them in reverse order so mounts further down the tree get unmounted first
1209 list_umount=( "$path" "${list_umount[@]}" )
1211 # separate loop to avoid races while reading /proc/mounts
1212 for i in "${list_umount[@]}"; do