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=()
46 declare -a OPTS_VTAG_CREATE=()
47 declare -a OPTS_VTAG_ENTER=()
49 declare -a STOPCMD_PREPARE=()
51 declare -a VSERVER_EXTRA_CMDS=()
54 VSHELPER_SYNC_TIMEOUT=30
59 _HAVE_INTERFACE_OPTIONS=
70 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
72 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
78 function _readFileToArray
85 test -e "$_rfta_f" || return 0
86 while read _rfta_v; do
89 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
94 function _generateChbindOptions
101 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
103 local f=$vdir/interfaces/bcast
104 getFileValue bcast "$f"
106 getFileValue nid "$vdir/ncontext" "$vdir/context"
108 CHBIND_OPTS=( $SILENT_OPT --secure ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
110 for i in "${INTERFACES[@]}"; do
111 CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
114 _readFileToArray "$vdir"/nflags CHBIND_OPTS --flag
115 _readFileToArray "$vdir"/ncapabilities CHBIND_OPTS --ncap
117 _HAVE_CHBIND_OPTIONS=1
120 function _generateNiceCommand
124 local current_nice=`$_NICE`
126 test -r "$vdir/nice" && read nice <"$vdir"/nice
128 let nice=$nice-$current_nice || :
129 NICE_CMD=( $_NICE -n $nice )
133 function _generatePersonalityOptions
136 local f="$vdir"/personality
139 test -s "$f" || return 0
148 (*) flags=$flags$delim$tmp
155 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
156 --personality-type "$type"
157 ${flags:+--personality-flags "$flags"} )
160 function _generateCCapabilityOptions
164 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
167 function _generateBCapabilityOptions
171 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
174 function _generateCapabilityOptions
179 _generateBCapabilityOptions "$vdir"
180 _generateCCapabilityOptions "$vdir"
182 test -e "$vdir"/capabilities || return 0
191 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
192 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
195 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
198 done <"$vdir"/capabilities
201 function getEnterShell
208 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
210 test -n "$ENTER_SHELL" || {
212 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
214 test -x "$vdir/vdir/$1" || continue
221 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
222 function sendKillSequence
228 while isCtxRunning "$ctx"; do
229 test -z "$wait" || sleep "$wait"
231 killContext "$ctx" "$1"
232 test -n "$2" || break
238 function _generateInitOptions
241 local cfgdir=$vdir/apps/init
246 INITCMD_START_SYNC=()
251 INITKILL_SEQ=( 15 5 9 )
252 CHCONTEXT_INIT_OPTS=()
255 test x"$INITSTYLE" = xrescue || \
256 getFileValue INITSTYLE "$cfgdir"/style
257 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
258 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
259 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
260 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
262 findFile _gio_env "$cfgdir"/environment \
263 "$__CONFDIR"/.defaults/apps/init/environment \
264 "$__PKGLIBDEFAULTDIR"/environment
265 getFileArray OPTS_ENV "$_gio_env" || :
267 case x"$INITSTYLE" in
269 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
270 INITCMD_STOP=( /sbin/killall5 )
274 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
275 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
277 for i in /etc/init.d/rc /etc/rc.d/rc; do
278 test -x "$vdir/vdir/$i" || continue
279 INITCMD_START=( "$i" "$RUNLEVEL_START" )
280 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
282 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
283 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
284 if test -n "$OPTION_DEBUG_SYSV"; then
285 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
286 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
291 INITCMD_START=( /sbin/init )
292 INITCMD_STOP=( /sbin/init )
294 _NEED_VSHELPER_SYNC=1
295 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
296 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
300 INITCMD_START=( /sbin/minit-start )
301 INITCMD_STOP=( /sbin/minit-stop )
303 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
304 _NEED_VSHELPER_SYNC=1
305 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
306 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
307 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
311 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
313 INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
314 INITCMD_STOP=( env -i TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
315 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
319 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
322 if test x"$INITSTYLE" != xrescue; then
323 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
324 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
325 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
326 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
327 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
330 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
331 INITCMD_START_SYNC=()
336 if vshelper.isEnabled; then
337 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
343 function _generateFlagOptions
347 CHCONTEXT_FLAG_OPTS=()
349 test ! -e "$vdir"/flags || \
358 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
359 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
365 isAvoidNamespace "$vdir" || {
367 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
371 function _generateChcontextOptions
374 local ctx hostname domainname
379 read ctx <"$vdir"/context || :
381 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
382 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
385 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
387 _generateCapabilityOptions "$vdir"
388 _generateFlagOptions "$vdir"
390 CHCONTEXT_OPTS=( $SILENT_OPT \
391 "${CHCONTEXT_FLAG_OPTS[@]}" \
394 ${ctx:+--ctx "$ctx"} \
395 ${hostname:+--hostname "$hostname"} \
396 ${domainname:+--domainname "$domainname"} )
398 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
399 ${ctx:+--xid "$ctx"} )
400 ## put '--secure' at front so that it can be overridden
401 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
404 function _generateScheduleOptions
407 if test -d "$vdir"/sched; then
408 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
412 local f="$vdir"/schedule
413 test -e "$f" || return 0
415 local fill_rate interval tokens tokens_min tokens_max prio_bias
423 read prio_bias || prio_bias=
427 test -n "$prio_bias" || {
428 echo $"Bad content in '$f'; aborting..." >&2
432 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
433 --tokens "$tokens" --tokens_min "$tokens_min" \
434 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
437 function _getInterfaceValue
447 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
450 : ${_giv_tmp:=$_giv_dflt}
451 eval $_giv_val=\$_giv_tmp
454 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
455 function _transformMask2Prefix
459 test -n "$_tm2p_tmp" || {
460 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
467 function _addInterfaceCmd
469 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
470 let ++INTERFACE_CMDS_IDX
473 ## Usage: _generateMac <var> <iface> <ctx>
474 function _generateMac
477 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
481 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
484 function _getVLANInfo
489 creation of VLAN_PLUS_VID devices is not supported; please create them
490 before starting the vserver and use the 'nodev' flag then"
491 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
495 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
496 create them before starting the vserver and use the 'nodev' flag then"
497 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
499 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
500 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
507 ## Usage: _processSingleInterface <interface-directory>
508 function _processSingleInterface
523 _getInterfaceValue ip '' "$iface"
524 _getInterfaceValue extip '' "$iface" "$iface/.."
525 _getInterfaceValue dev '' "$iface" "$iface/.."
526 _getInterfaceValue prefix '' "$iface" "$iface/.."
527 _getInterfaceValue mask '' "$iface" "$iface/.."
528 _getInterfaceValue bcast '' "$iface" "$iface/.."
529 _getInterfaceValue name '' "$iface"
530 _getInterfaceValue scope '' "$iface" "$iface/.."
531 _getInterfaceValue mac '' "$iface"
533 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
534 test -n "$dev" -o -e "$iface"/nodev || {
535 echo $"No device specified for '$iface'" >&2
539 test ! -e "$iface"/down || up=
542 _transformMask2Prefix prefix "$prefix" "$mask"
543 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
545 test ! -e "$iface"/nodev || break
547 test ! -e "$iface"/only_ip || break
549 test -e "$iface/vlandev" \
550 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
551 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
552 -a ! -e "$iface/novlandev" \
553 -a ! -e "$iface/../novlandev" \) && {
555 if vlan_info=$(_getVLANInfo "$dev"); then
556 test -d /proc/net/vlan || {
557 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
560 _addInterfaceCmd VCONFIG $vlan_info
564 if ! test -e "$iface"/indirect; then
566 use_bcast="broadcast ${bcast:-+}"
567 echo "$ip" | $_GREP -q : && use_bcast=
568 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
569 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
570 _addInterfaceCmd IP_LINK "$dev" $up
571 elif ! test -n "$ctx"; then
572 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
575 test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
576 _addInterfaceCmd MODPROBE dummy "$dev"
577 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
578 _addInterfaceCmd NAMEIF "$dev" "$mac"
579 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
580 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
587 ## Usage: _generateInterfaceOptions <vserver-directory>
588 function _generateInterfaceOptions
593 test ! -e "$1"/context || read ctx <"$1"/context
595 for iface in "$1/interfaces/"*; do
596 test -d "$iface" || continue
597 test ! -e "$iface"/disabled || continue
599 _processSingleInterface "$iface"
601 _HAVE_INTERFACE_OPTIONS=1
604 function _generateTagOptions
609 getFileValue tag "$vdir/tag" "$vdir/context" || return 0
611 OPTS_VTAG_CREATE=( --tag "$tag" )
612 OPTS_VTAG_ENTER=( --tag "$tag" )
615 function enableInterfaces
620 lock "$__LOCKDIR"/vserver.interfaces
622 while test $i -lt $INTERFACE_CMDS_IDX; do
623 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
634 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
636 NAMEIF) $_NAMEIF "$@";;
637 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
638 $_VCONFIG add "$2" "$3" >/dev/null;;
639 IP_ADDR) $_IP addr add "$@";;
640 IP_ADDR_FLUSH) $_IP addr flush "$@";;
641 IP_LINK) $_IP link set "$@";;
642 IP_ROUTE) $_IP route add "$@";;
643 *) echo "Unknown interface-command type '$type'" >&2; false;;
652 function disableInterfaces
654 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
656 local i=$INTERFACE_CMDS_IDX
659 lock "$__LOCKDIR"/vserver.interfaces
661 while test $i -gt 0; do
664 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
671 MODPROBE) $_RMMOD "${2:-$1}";;
673 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
674 IP_ADDR) $_IP addr del "$@";;
676 IP_LINK) ;; ## Ignore the link-down command for now
677 IP_ROUTE) $_IP route del "$@";;
678 *) echo "Unknown interface-command type '$type'" >&2; false;;
685 ## Usage: prepareInit <vserver-directory>
688 pushd "$1/vdir" >/dev/null
691 { find var/run ! -type d -print0; \
692 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
695 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
696 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
701 "${INITCMD_PREPARE[@]}"
705 ## Usage: prepareInit <vserver-directory>
708 pushd "$1/vdir" >/dev/null
711 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
714 "${STOPCMD_PREPARE[@]}"
719 function generateOptions
721 _generateInterfaceOptions "$1"
722 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
723 _generateNiceCommand "$1"
724 _generateInitOptions "$1"
725 _generateChcontextOptions "$1"
726 _generateScheduleOptions "$1"
727 _generatePersonalityOptions "$1"
728 _generateTagOptions "$1"
730 if test -n "$_IS_FAKEINIT"; then
731 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
732 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
740 local f="$vdir"/cpuset
744 test -d "$f" || return 0
745 test -e "$f"/name || return 0
747 read cpuset < "$f"/name
748 test -e "$f"/nocreate || {
749 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
750 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
751 if test -e "$f"/"$i"; then
752 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
760 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
761 if [ "$configured" -ne 0 ]; then
763 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
764 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
769 function removeCPUSET
773 local f="$vdir"/cpuset
775 test -d "$f" || return 0
776 test -e "$f"/name || return 0
778 read cpuset < "$f"/name
779 test -e "$f"/nocreate || {
780 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
784 function _mountVserverInternal
789 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 no
805 local fstab="$cfgdir"/fstab
808 test -e "$fstab" || return 0
809 pushd "$vdir" >/dev/null
810 # check whether / is mounted readonly or whether there is special
811 # magic regarding the mtab file; when etc/mtab can not be touched,
812 # add the '-n' flag to mount
813 test -w etc -o -w etc/mtab || xflag=-n
814 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
818 function mountVserver
825 test -e "$cfgdir"/fstab -o \
826 -e "$cfgdir"/fstab.local -o \
827 -e "$cfgdir"/fstab.remote || return 0
829 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
831 pushd "$vdir" >/dev/null
832 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
835 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
837 _mountVserverInternal "$cfgdir"/fstab
838 _mountVserverInternal "$cfgdir"/fstab.local
839 _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
841 isNamespaceCleanup "$cfgdir" && \
842 _namespaceCleanup "$cfgdir"
844 isAvoidNamespace "$cfgdir" || \
845 $_SECURE_MOUNT --rbind -n "$vdir" "/"
848 function _umountVserverInternal
851 test -e "$fstab" || return 0
856 while read src dst tmp; do
857 test -n "$tmp" || continue
863 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
869 function umountVserver
875 isAvoidNamespace "$cfgdir" || return 0
876 test -e "$cfgdir"/fstab -o \
877 -e "$cfgdir"/fstab.local -o \
878 -e "$cfgdir"/fstab.remote || return 0
879 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
881 pushd "$vdir/" >/dev/null || return 1
882 _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
883 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
884 _umountVserverInternal "$cfgdir"/fstab || is_ok=
885 popd >/dev/null || return 1
890 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
894 test -n "$_NEED_VSHELPER_SYNC" && \
895 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
897 vshelper.initSync "$1" "$3" "$_is_meth"
900 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
903 if $_VSERVER_INFO - FEATURE vwait; then
905 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
908 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
910 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
913 if test "$rc" -ne 0 -a "$rc" -ne 1; then
914 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
915 killContext "$S_CONTEXT" 9
919 ) 4>$_is_tmpdir/procs &
921 echo "$!" >$_is_tmpdir/pid
922 eval "$3"=$_is_tmpdir
927 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
928 function _waitForVWait
933 declare -r procs=$(cat $4)
935 getFileArray status "$2"
940 'vwait' exited with error '$2' which indicates that vserver could not
945 A timeout occured while waiting for the vserver to finish and it was
946 killed by sending a SIGKILL signal. Please investigate the reasons
947 and/or increase the timeout in apps/vshelper/sync-timeout."
950 (TIMEOUT) warning $"\
951 A timeout occured while waiting for the vserver to finish and it will
952 be killed by sending a SIGKILL signal. The following process list
953 might be useful for finding out the reason of this behavior:
955 ----------------------------------------------------------------------
957 }----------------------------------------------------------------------"
960 (\?\?\?|*) warning $"\
961 internal error: 'vwait' exited with an unexpected status '$1'; I will
962 try to continue but be prepared for unexpected events."
969 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
974 local vwait_statdir=$3
977 if test -d "$vwait_statdir"; then
978 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
979 elif test -n "$_NEED_VSHELPER_SYNC"; then
980 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
982 A timeout or other error occured while waiting for the synchronization
983 signal from vserver '$VSERVER_NAME'.
984 The vserver will be killed nevertheless..."
985 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
986 "${INITCMD_STOP_SYNC[@]}" || \
988 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
989 will be killed nevertheless..."
992 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
998 local vdir name flavor start i already_handled base
1002 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1003 function execScriptlets
1007 declare -r flavor=$3
1010 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1011 local DONT_SKIP_DEFAULTS=
1012 local already_handled=
1014 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1015 isRegularFile "$i" || continue
1016 test -r "$i" || continue
1020 test -x "$i" || start=_sourceWrap
1021 $start "$i" "$flavor" "$name"
1024 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1029 function sanityCheck
1031 declare -r cfgdir=$1
1033 ! test -e "$cfgdir"/fstab.local ||
1035 WARNING: 'fstab' will *not* be executed in the network context of the
1036 vserver anymore. Therefore, 'fstab.local' has the same functionality
1037 and is obsoleted. When you need the old behaviour, put the mounts
1038 into 'fstab.remote'"
1040 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1042 WARNING: The hostname is now configured in 'uts/nodename' but not in
1045 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1047 WARNING: The domainname is now configured in 'uts/domainname' but not
1048 in 'domainname'." >&2
1052 for i in "$cfgdir"/interfaces/*/only_ip; do
1053 if test -e "$i"; then
1055 iface=${i##$cfgdir/interfaces/}
1056 iface=${iface%%/only_ip}
1058 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1063 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1065 WARNING: There is no cachedirectory configured for this vserver;
1066 please create '$cfgdir/cache' e.g. by executing
1068 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1071 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1073 vshelper.doSanityCheck
1075 $_VSERVER_INFO - VERIFYCAP ||
1076 panic $"capabilities are not enabled in kernel-setup"
1078 $_VSERVER_INFO - VERIFYPROC ||
1080 /proc/uptime can not be accessed. Usually, this is caused by
1081 procfs-security. Please read the FAQ for more details
1082 http://linux-vserver.org/Proc-Security"
1086 function _setSingleDiskLimit
1098 getFileValue ctx "$vdir/context"
1099 getFileValue directory "$dlimit/directory" || return 0
1100 getFileValue space_total "$dlimit/space_total" || return 0
1101 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1102 getFileValue reserved "$dlimit/reserved" || return 0
1104 local cachename=$ctx$directory
1105 cachename=dlimits/${cachename//\//_}
1107 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1108 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1109 $_RM -f "$vdir/cache/$cachename"
1111 if test -z "$inodes_used" -o -z "$space_used"; then
1113 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1114 inodes_used=${tmpvdu##* }
1115 space_used=${tmpvdu%% *}
1118 $_VDLIMIT --xid $ctx \
1119 --set space_used=$space_used \
1120 --set space_total=$space_total \
1121 --set inodes_used=$inodes_used \
1122 --set inodes_total=$inodes_total \
1123 --set reserved=$reserved \
1128 function setDiskLimits
1133 # Disk Limits without a static context are useless
1134 test -e "$vdir"/context || return 0
1136 for dlimit in "$vdir/dlimits/"*; do
1137 test -d "$dlimit" || continue
1138 test ! -e "$dlimit/disabled" || continue
1140 _setSingleDiskLimit "$vdir" "$dlimit"
1145 function _saveSingleDiskLimit
1152 getFileValue ctx "$vdir/context"
1153 getFileValue directory "$dlimit/directory" || return 0
1155 local cachename=$ctx$directory
1156 cachename=${cachename//\//_}
1158 # Things are getting ugly here... LFS says that /var/cache (where
1159 # cachename is usually pointing to) can vanish and applications
1160 # have to deal with it. So, we have to interprete the $vdir/cache
1161 # symlink and have to create the needed directories manually.
1162 if test -d "$vdir/cache"; then
1163 : # ok, exists already
1164 elif test -L "$vdir/cache"; then
1165 # it's a dangling symlink
1167 link=$($_READLINK "$vdir/cache")
1168 ( cd $vdir && $_MKDIR -p "$link" )
1173 test -d "$vdir/cache"
1174 $_MKDIR -p "$vdir"/cache/dlimits
1176 $_VDLIMIT --xid $ctx "$directory" | \
1177 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1179 $_VDLIMIT --xid $ctx --remove "$directory"
1183 function saveDiskLimits
1188 test -e "$vdir"/context || return 0
1190 for dlimit in "$vdir/dlimits/"*; do
1191 test -d "$dlimit" || continue
1192 test ! -e "$dlimit/disabled" || continue
1194 _saveSingleDiskLimit "$vdir" "$dlimit"
1198 function _namespaceCleanup
1201 local root=$($_VSERVER_INFO "$1" VDIR 1)
1206 getFileArray skip "$vdir"/namespace-cleanup-skip \
1207 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1209 # these are things that have to be accessible post-cleanup
1210 for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1211 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1212 while test -n "$tmp"; do
1213 list=( "${list[@]}" "$tmp" )
1218 local -a list_umount
1219 while read dev path opts; do
1220 test -n "$path" || continue
1221 for i in "$root" /dev /proc; do
1222 test "${path#$i}" != "$path" && continue 2
1224 for i in "${list[@]}" /; do
1225 test "$path" = "$i" && continue 2
1227 # unmount them in reverse order so mounts further down the tree get unmounted first
1228 list_umount=( "$path" "${list_umount[@]}" )
1230 # separate loop to avoid races while reading /proc/mounts
1231 for i in "${list_umount[@]}"; do
1236 function loadDeviceMap
1240 local flags device target
1242 test -d "$dir" || return 0
1244 for i in "$dir"/*; do
1245 test -d "$i" || continue
1247 local -a vdevmap_opts=()
1248 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1249 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1250 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1252 getFileValue flags "$i/flags" || :
1253 getFileValue device "$i/device" || :
1254 getFileValue target "$i/target" || :
1255 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1256 ${device:+--device "$device"} ${target:+--target "$target"} )
1258 $_VDEVMAP --xid "$xid" "${vdevmap_opts[@]}" || return $?