3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 # $VSERVER_DIR ... path to vserver-cfg dir
20 # $VSERVER_NAME ... name of vserver
22 declare -a NICE_CMD=()
23 declare -a CHBIND_CMD=()
24 declare -a CAP_OPTS=()
25 declare -a CHCONTEXT_INIT_OPTS=()
26 declare -a CHCONTEXT_FLAG_OPTS=()
27 declare -a CHCONTEXT_OPTS=()
28 declare -a CAPCHROOT_OPTS=()
29 declare -a INTERFACES=()
31 declare -a INITCMD_RESCUE=( /bin/sleep 900 )
32 declare -a INITCMD_START=()
33 declare -a INITCMD_START_SYNC=()
34 declare -a INITCMD_STOP=()
35 declare -a INITCMD_STOP_SYNC=()
36 declare -a INITCMD_PREPARE=()
37 declare -a INITKILL_SEQ=()
38 declare -a ENTER_SHELL=()
40 declare -a OPTS_VCONTEXT_CREATE=()
41 declare -a OPTS_VCONTEXT_MIGRATE=()
42 declare -a OPTS_VCONTEXT_ENTER=()
43 declare -a OPTS_VATTRIBUTE=( --flag fakeinit )
44 declare -a OPTS_VSCHED=()
45 declare -a OPTS_ENV=()
46 declare -a OPTS_VTAG_CREATE=()
47 declare -a OPTS_VTAG_ENTER=()
48 declare -a OPTS_VMEMCTRL=()
49 declare -a OPTS_VSPACE=()
51 declare -a STOPCMD_PREPARE=()
53 declare -a VSERVER_EXTRA_CMDS=()
56 VSHELPER_SYNC_TIMEOUT=30
61 _HAVE_INTERFACE_OPTIONS=
73 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
75 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
81 function _readFileToArray
88 test -e "$_rfta_f" || return 0
89 while read _rfta_v; do
92 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
97 function _generateChbindOptions
105 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
107 local f="$vdir"/interfaces/bcast
108 getFileValue bcast "$f"
109 f="$vdir"/interfaces/lback
110 getFileValue lback "$f"
112 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${N_CONTEXT:+--nid "$N_CONTEXT"}
113 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
116 for i in "${INTERFACES[@]}"; do
117 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
120 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
121 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
123 _HAVE_CHBIND_OPTIONS=1
126 function _generateNiceCommand
130 local current_nice=`$_NICE`
132 test -r "$vdir/nice" && read nice <"$vdir"/nice
134 let nice=$nice-$current_nice || :
135 NICE_CMD=( $_NICE -n $nice )
139 function _generatePersonalityOptions
142 local f="$vdir"/personality
145 test -s "$f" || return 0
154 (*) flags=$flags$delim$tmp
161 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
162 --personality-type "$type"
163 ${flags:+--personality-flags "$flags"} )
166 function _generateCCapabilityOptions
170 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
173 function _generateBCapabilityOptions
177 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
180 function _generateCapabilityOptions
185 _generateBCapabilityOptions "$vdir"
186 _generateCCapabilityOptions "$vdir"
188 test -e "$vdir"/capabilities || return 0
197 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
198 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
201 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
204 done <"$vdir"/capabilities
207 function getEnterShell
214 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
216 test -n "$ENTER_SHELL" || {
218 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
220 test -x "$vdir/vdir/$1" || continue
227 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
228 function sendKillSequence
234 while isCtxRunning "$ctx"; do
235 test -z "$wait" || sleep "$wait"
237 killContext "$ctx" "$1"
238 test -n "$2" || break
244 function _generateInitOptions
247 local cfgdir=$vdir/apps/init
252 INITCMD_START_SYNC=()
257 INITKILL_SEQ=( 15 5 9 )
258 CHCONTEXT_INIT_OPTS=()
261 test x"$INITSTYLE" = xrescue || \
262 getFileValue INITSTYLE "$cfgdir"/style
263 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
264 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
265 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
266 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
268 findFile _gio_env "$cfgdir"/environment \
269 "$__CONFDIR"/.defaults/apps/init/environment \
270 "$__PKGLIBDEFAULTDIR"/environment
271 getFileArray OPTS_ENV "$_gio_env" || :
273 case x"$INITSTYLE" in
275 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
276 INITCMD_STOP=( /sbin/killall5 )
280 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
281 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
283 for i in /etc/init.d/rc /etc/rc.d/rc; do
284 test -x "$vdir/vdir/$i" || continue
285 INITCMD_START=( "$i" "$RUNLEVEL_START" )
286 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
288 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
289 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
290 if test -n "$OPTION_DEBUG_SYSV"; then
291 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
292 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
297 INITCMD_START=( /sbin/init )
298 INITCMD_STOP=( /sbin/init )
300 _NEED_VSHELPER_SYNC=1
301 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
302 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
306 INITCMD_START=( /sbin/minit-start )
307 INITCMD_STOP=( /sbin/minit-stop )
309 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
310 _NEED_VSHELPER_SYNC=1
311 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
312 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
313 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
317 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
318 RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
320 if test -x "$vdir/vdir/lib/rcscripts/sh/init-vserver.sh"; then
321 RC_WRAP=/lib/rcscripts/sh/init-vserver.sh
322 elif test -x "$vdir/vdir/lib/rc/sh/init-vserver.sh"; then
323 RC_WRAP=/lib/rc/sh/init-vserver.sh
325 panic "init-vserver.sh not found; aborting"
328 INITCMD_START=( env TERM=$TERM $RC_WRAP "$RUNLEVEL_START" )
329 INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
330 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
334 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
337 if test x"$INITSTYLE" != xrescue; then
338 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
339 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
340 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
341 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
342 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
345 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
346 INITCMD_START_SYNC=()
351 if vshelper.isEnabled; then
352 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
358 function _generateFlagOptions
362 CHCONTEXT_FLAG_OPTS=()
364 test ! -e "$vdir"/flags || \
373 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
374 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
380 isAvoidNamespace "$vdir" || {
382 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
386 function _generateChcontextOptions
389 local ctx hostname domainname
394 read ctx <"$vdir"/context || :
396 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
397 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
400 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
402 _generateCapabilityOptions "$vdir"
403 _generateFlagOptions "$vdir"
405 CHCONTEXT_OPTS=( $SILENT_OPT \
406 "${CHCONTEXT_FLAG_OPTS[@]}" \
409 ${ctx:+--ctx "$ctx"} \
410 ${hostname:+--hostname "$hostname"} \
411 ${domainname:+--domainname "$domainname"} )
413 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
414 ${ctx:+--xid "$ctx"} )
415 ## put '--secure' at front so that it can be overridden
416 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
419 function _generateScheduleOptions
422 if test -d "$vdir"/sched; then
423 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
427 local f="$vdir"/schedule
428 test -e "$f" || return 0
430 local fill_rate interval tokens tokens_min tokens_max prio_bias
438 read prio_bias || prio_bias=
442 test -n "$prio_bias" || {
443 echo $"Bad content in '$f'; aborting..." >&2
447 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
448 --tokens "$tokens" --tokens_min "$tokens_min" \
449 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
452 function _getInterfaceValue
462 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
465 : ${_giv_tmp:=$_giv_dflt}
466 eval $_giv_val=\$_giv_tmp
469 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
470 function _transformMask2Prefix
474 test -n "$_tm2p_tmp" || {
475 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
482 function _addInterfaceCmd
484 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
485 let ++INTERFACE_CMDS_IDX
488 ## Usage: _generateMac <var> <iface> <ctx>
489 function _generateMac
492 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
496 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
499 function _getVLANInfo
504 creation of VLAN_PLUS_VID devices is not supported; please create them
505 before starting the vserver and use the 'nodev' flag then"
506 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
510 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
511 create them before starting the vserver and use the 'nodev' flag then"
512 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
514 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
515 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
526 test -e "$iface/tun" -o -e "$iface/tap" || return 1
527 test ! -e "$iface/tun" || echo --tun
528 test ! -e "$iface/tap" || echo --tap
529 test ! -e "$iface/nocsum" || echo --~checksum
530 test -e "$iface/shared" || echo --nid-failure-ok "$N_CONTEXT"
531 if test -e "$iface/uid"; then
533 getFileValue uid "$iface/uid"
536 if test -e "$iface/gid"; then
538 getFileValue gid "$iface/gid"
541 if test -e "$iface/linktype"; then
543 getFileValue linktype "$iface/linktype"
544 echo --linktype "$linktype"
549 ## Usage: _processSingleInterface <interface-directory>
550 function _processSingleInterface
566 _getInterfaceValue ip '' "$iface"
567 _getInterfaceValue extip '' "$iface" "$iface/.."
568 _getInterfaceValue dev '' "$iface" "$iface/.."
569 _getInterfaceValue prefix '' "$iface" "$iface/.."
570 _getInterfaceValue mask '' "$iface" "$iface/.."
571 _getInterfaceValue bcast '' "$iface" "$iface/.."
572 _getInterfaceValue name '' "$iface"
573 _getInterfaceValue scope '' "$iface" "$iface/.."
574 _getInterfaceValue mac '' "$iface"
575 _getInterfaceValue peer '' "$iface"
577 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
578 test -n "$dev" -o -e "$iface"/nodev || {
579 echo $"No device specified for '$iface'" >&2
583 test ! -e "$iface"/down || up=
586 _transformMask2Prefix prefix "$prefix" "$mask"
587 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
589 test ! -e "$iface"/nodev || break
591 test ! -e "$iface"/only_ip || break
593 test -e "$iface/vlandev" \
594 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
595 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
596 -a ! -e "$iface/novlandev" \
597 -a ! -e "$iface/../novlandev" \) && {
599 if vlan_info=$(_getVLANInfo "$dev"); then
600 test -d /proc/net/vlan || {
601 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
604 _addInterfaceCmd VCONFIG $vlan_info
608 if ! test -e "$iface"/indirect; then
610 local use_bcast="broadcast ${bcast:-+}"
611 echo "$ip" | $_GREP -q : && use_bcast=
614 if tun_info=$(_getTunInfo "$iface"); then
615 _addInterfaceCmd TUNCTL "$dev" $tun_info
618 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev" ${peer:+peer "$peer"}
619 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
620 _addInterfaceCmd IP_LINK "$dev" $up
621 elif ! test -n "$N_CONTEXT"; then
622 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
625 test -z "$mac" || _generateMac mac "$(basename $iface)" "$N_CONTEXT" || return 1
626 _addInterfaceCmd MODPROBE dummy "$dev"
627 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
628 _addInterfaceCmd NAMEIF "$dev" "$mac"
629 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
630 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$N_CONTEXT" "$extip"
637 ## Usage: _generateInterfaceOptions <vserver-directory>
638 function _generateInterfaceOptions
642 # XXX: This is here instead of in _generateChbindOptions
643 # to avoid a circular dependency
644 getFileValue N_CONTEXT "$1/ncontext" "$1/context"
645 test -n "$N_CONTEXT" -o -z "$S_CONTEXT" || N_CONTEXT="$S_CONTEXT"
647 for iface in "$1/interfaces/"*; do
648 test -d "$iface" || continue
649 test ! -e "$iface"/disabled || continue
651 _processSingleInterface "$iface"
653 _HAVE_INTERFACE_OPTIONS=1
656 function enableInterfaces
661 lock "$__LOCKDIR"/vserver.interfaces
663 while test $i -lt $INTERFACE_CMDS_IDX; do
664 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
675 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
677 NAMEIF) $_NAMEIF "$@";;
678 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
679 $_VCONFIG add "$2" "$3" >/dev/null;;
680 IP_ADDR) $_IP addr add "$@";;
681 IP_ADDR_FLUSH) $_IP addr flush "$@";;
682 IP_LINK) $_IP link set "$@";;
683 IP_ROUTE) $_IP route add "$@";;
687 $_TUNCTL --persist "$@" "$dev"
689 *) echo "Unknown interface-command type '$type'" >&2; false;;
698 function disableInterfaces
700 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
702 local i=$INTERFACE_CMDS_IDX
705 lock "$__LOCKDIR"/vserver.interfaces
707 while test $i -gt 0; do
710 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
717 MODPROBE) $_RMMOD "${2:-$1}";;
719 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
720 IP_ADDR) $_IP addr del "$@";;
722 IP_LINK) ;; ## Ignore the link-down command for now
723 IP_ROUTE) $_IP route del "$@";;
724 TUNCTL) $_TUNCTL --~persist "$1";;
725 *) echo "Unknown interface-command type '$type'" >&2; false;;
732 function _generateTagOptions
737 getFileValue tag "$vdir/tag" "$vdir/context"
738 test -n "$tag" || return 0
740 OPTS_VTAG_CREATE=( --tag "$tag" )
741 OPTS_VTAG_ENTER=( --tag "$tag" )
744 function _generateMemctrlOptions
749 getFileValue badness "$vdir/badness"
750 test -n "$badness" || return 0
752 OPTS_VMEMCTRL=( --badness "$badness" )
755 function _generateSpaceOptions
758 local d="$vdir"/spaces
760 ( test ! -e "$d"/pid &&
761 ! $_VSERVER_INFO PIDSPACE FEATURE ) || \
762 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
764 test ! -e "$d"/net || {
765 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
766 # network context and namespace don't make much sense
767 _HAVE_CHBIND_OPTIONS=1
772 getFileValue mask "$d"/mask || \
773 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
776 ## Usage: prepareInit <vserver-directory>
779 pushd "$1/vdir" >/dev/null
782 { find var/run ! -type d -print0; \
783 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
786 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
787 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
792 "${INITCMD_PREPARE[@]}"
796 ## Usage: prepareInit <vserver-directory>
799 pushd "$1/vdir" >/dev/null
802 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
805 "${STOPCMD_PREPARE[@]}"
810 function generateOptions
812 _generateInterfaceOptions "$1"
813 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
814 _generateNiceCommand "$1"
815 _generateInitOptions "$1"
816 _generateChcontextOptions "$1"
817 _generateScheduleOptions "$1"
818 _generatePersonalityOptions "$1"
819 _generateTagOptions "$1"
820 _generateMemctrlOptions "$1"
821 _generateSpaceOptions "$1"
823 if test -n "$_IS_FAKEINIT"; then
824 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
825 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
833 local f="$vdir"/cpuset
837 test -d "$f" || return 0
838 test -e "$f"/name || return 0
840 read cpuset < "$f"/name
841 test -e "$f"/nocreate || {
842 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
843 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
844 if test -e "$f"/"$i"; then
845 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
853 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
854 if [ "$configured" -ne 0 ]; then
856 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
857 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
862 function removeCPUSET
866 local f="$vdir"/cpuset
868 test -d "$f" || return 0
869 test -e "$f"/name || return 0
871 read cpuset < "$f"/name
872 test -e "$f"/nocreate || {
873 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
877 function _mountVserverInternal
882 test -e "$fstab" || return 0
885 pushd "$vdir" >/dev/null
886 # check whether / is mounted readonly or whether there is special
887 # magic regarding the mtab file; when etc/mtab can not be touched,
888 # add the '-n' flag to mount
889 test -w etc -o -w etc/mtab || xflag=-n
890 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
898 local fstab="$cfgdir"/fstab
901 test -e "$fstab" || return 0
902 pushd "$vdir" >/dev/null
903 # check whether / is mounted readonly or whether there is special
904 # magic regarding the mtab file; when etc/mtab can not be touched,
905 # add the '-n' flag to mount
906 test -w etc -o -w etc/mtab || xflag=-n
907 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
911 function mountVserver
918 test -e "$cfgdir"/fstab -o \
919 -e "$cfgdir"/fstab.local -o \
920 -e "$cfgdir"/fstab.remote || return 0
922 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
924 pushd "$vdir" >/dev/null
925 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
928 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
930 _mountVserverInternal "$cfgdir"/fstab
931 _mountVserverInternal "$cfgdir"/fstab.local
932 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
934 isNamespaceCleanup "$cfgdir" && \
935 _namespaceCleanup "$cfgdir"
937 isAvoidNamespace "$cfgdir" || \
938 $_SECURE_MOUNT --rbind -n "$vdir" "/"
941 function _umountVserverInternal
944 test -e "$fstab" || return 0
949 while read src dst tmp; do
950 test -n "$tmp" || continue
956 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
962 function umountVserver
968 isAvoidNamespace "$cfgdir" || return 0
969 test -e "$cfgdir"/fstab -o \
970 -e "$cfgdir"/fstab.local -o \
971 -e "$cfgdir"/fstab.remote || return 0
972 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
974 pushd "$vdir/" >/dev/null || return 1
975 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
976 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
977 _umountVserverInternal "$cfgdir"/fstab || is_ok=
978 popd >/dev/null || return 1
986 local fstab="$cfgdir"/fstab
990 test -e "$fstab" || return 0
992 export FSTAB_FILE="$fstab"
995 test "$fsck_exitcode" -eq 0 -o \
996 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
999 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
1003 test -n "$_NEED_VSHELPER_SYNC" && \
1004 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
1006 vshelper.initSync "$1" "$3" "$_is_meth"
1009 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
1012 if $_VSERVER_INFO - FEATURE vwait; then
1014 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
1017 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
1018 --status-fd 3 "$2" \
1019 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
1022 if test "$rc" -ne 0 -a "$rc" -ne 1; then
1023 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
1024 killContext "$S_CONTEXT" 9
1028 ) 4>$_is_tmpdir/procs &
1030 echo "$!" >$_is_tmpdir/pid
1031 eval "$3"=$_is_tmpdir
1036 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
1037 function _waitForVWait
1042 declare -r procs=$(cat $4)
1044 getFileArray status "$2"
1049 'vwait' exited with error '$2' which indicates that vserver could not
1050 be stopped properly"
1053 (KILLED) warning $"\
1054 A timeout occured while waiting for the vserver to finish and it was
1055 killed by sending a SIGKILL signal. Please investigate the reasons
1056 and/or increase the timeout in apps/vshelper/sync-timeout."
1059 (TIMEOUT) warning $"\
1060 A timeout occured while waiting for the vserver to finish and it will
1061 be killed by sending a SIGKILL signal. The following process list
1062 might be useful for finding out the reason of this behavior:
1064 ----------------------------------------------------------------------
1066 }----------------------------------------------------------------------"
1069 (\?\?\?|*) warning $"\
1070 internal error: 'vwait' exited with an unexpected status '$1'; I will
1071 try to continue but be prepared for unexpected events."
1078 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1079 function waitForSync
1083 local vwait_statdir=$3
1086 if test -d "$vwait_statdir"; then
1087 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1088 elif test -n "$_NEED_VSHELPER_SYNC"; then
1089 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1091 A timeout or other error occured while waiting for the synchronization
1092 signal from vserver '$VSERVER_NAME'.
1093 The vserver will be killed nevertheless..."
1094 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1095 "${INITCMD_STOP_SYNC[@]}" || \
1097 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1098 will be killed nevertheless..."
1101 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1105 function _sourceWrap
1107 local vdir name flavor start i already_handled base
1111 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1112 function execScriptlets
1116 declare -r flavor=$3
1119 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1120 local DONT_SKIP_DEFAULTS=
1121 local already_handled=
1123 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1124 isRegularFile "$i" || continue
1125 test -r "$i" || continue
1129 test -x "$i" || start=_sourceWrap
1130 $start "$i" "$flavor" "$name"
1133 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1138 function sanityCheck
1140 declare -r cfgdir=$1
1142 ! test -e "$cfgdir"/fstab.local ||
1144 WARNING: 'fstab' will *not* be executed in the network context of the
1145 vserver anymore. Therefore, 'fstab.local' has the same functionality
1146 and is obsoleted. When you need the old behaviour, put the mounts
1147 into 'fstab.remote'"
1149 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1151 WARNING: The hostname is now configured in 'uts/nodename' but not in
1154 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1156 WARNING: The domainname is now configured in 'uts/domainname' but not
1157 in 'domainname'." >&2
1161 for i in "$cfgdir"/interfaces/*/only_ip; do
1162 if test -e "$i"; then
1164 iface=${i##$cfgdir/interfaces/}
1165 iface=${iface%%/only_ip}
1167 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1172 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1174 WARNING: There is no cachedirectory configured for this vserver;
1175 please create '$cfgdir/cache' e.g. by executing
1177 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1180 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1182 vshelper.doSanityCheck
1184 $_VSERVER_INFO - VERIFYCAP ||
1185 panic $"capabilities are not enabled in kernel-setup"
1187 $_VSERVER_INFO - VERIFYPROC ||
1189 /proc/uptime can not be accessed. Usually, this is caused by
1190 procfs-security. Please read the FAQ for more details
1191 http://linux-vserver.org/Proc-Security"
1193 test -e "$cfgdir"/context || {
1194 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1195 test "$TYPE" != "static" || panic $"\
1196 The kernel does not have dynamic contexts enabled. Please configure
1197 a static one by executing
1199 echo [number between 2 and 49151] > $cfgdir/context"
1204 function _setSingleDiskLimit
1216 getFileValue ctx "$vdir/context"
1217 getFileValue directory "$dlimit/directory" || return 0
1218 getFileValue space_total "$dlimit/space_total" || return 0
1219 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1220 getFileValue reserved "$dlimit/reserved" || return 0
1222 local cachename=$ctx$directory
1223 cachename=dlimits/${cachename//\//_}
1225 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1226 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1227 $_RM -f "$vdir/cache/$cachename"
1229 if test -z "$inodes_used" -o -z "$space_used"; then
1231 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1232 inodes_used=${tmpvdu##* }
1233 space_used=${tmpvdu%% *}
1236 $_VDLIMIT --xid $ctx \
1237 --set space_used=$space_used \
1238 --set space_total=$space_total \
1239 --set inodes_used=$inodes_used \
1240 --set inodes_total=$inodes_total \
1241 --set reserved=$reserved \
1246 function setDiskLimits
1251 # Disk Limits without a static context are useless
1252 test -e "$vdir"/context || return 0
1254 for dlimit in "$vdir/dlimits/"*; do
1255 test -d "$dlimit" || continue
1256 test ! -e "$dlimit/disabled" || continue
1258 _setSingleDiskLimit "$vdir" "$dlimit"
1263 function _saveSingleDiskLimit
1270 getFileValue ctx "$vdir/context"
1271 getFileValue directory "$dlimit/directory" || return 0
1273 local cachename=$ctx$directory
1274 cachename=${cachename//\//_}
1276 # Things are getting ugly here... LFS says that /var/cache (where
1277 # cachename is usually pointing to) can vanish and applications
1278 # have to deal with it. So, we have to interprete the $vdir/cache
1279 # symlink and have to create the needed directories manually.
1280 if test -d "$vdir/cache"; then
1281 : # ok, exists already
1282 elif test -L "$vdir/cache"; then
1283 # it's a dangling symlink
1285 link=$($_READLINK "$vdir/cache")
1286 ( cd $vdir && $_MKDIR -p "$link" )
1291 test -d "$vdir/cache"
1292 $_MKDIR -p "$vdir"/cache/dlimits
1294 $_VDLIMIT --xid $ctx "$directory" | \
1295 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1297 $_VDLIMIT --xid $ctx --remove "$directory"
1301 function saveDiskLimits
1306 test -e "$vdir"/context || return 0
1308 for dlimit in "$vdir/dlimits/"*; do
1309 test -d "$dlimit" || continue
1310 test ! -e "$dlimit/disabled" || continue
1312 _saveSingleDiskLimit "$vdir" "$dlimit"
1316 function _namespaceCleanup
1319 local root=$($_VSERVER_INFO "$1" VDIR 1)
1325 getFileArray skip "$vdir"/namespace-cleanup-skip \
1326 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1328 # these are things that have to be accessible post-cleanup
1329 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1330 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1331 local real=`getPhysicalDir "$i"`
1332 test "$i" != "$real" || real=
1333 for j in "$i" "$real"; do
1334 while test -n "$j"; do
1335 list=( "${list[@]}" "$j" )
1341 local -a list_umount
1342 while read -r dev path opts; do
1343 test -n "$path" || continue
1344 for i in "$root" /dev /proc; do
1345 test "${path#$i}" != "$path" && continue 2
1347 for i in "${list[@]}" /; do
1348 test "$path" = "$i" && continue 2
1350 # unmount them in reverse order so mounts further down the tree get unmounted first
1351 list_umount=( "$path" "${list_umount[@]}" )
1353 # separate loop to avoid races while reading /proc/mounts
1354 for i in "${list_umount[@]}"; do
1355 $_UMOUNT -l -n -i "$i"
1359 function handleDeviceMap
1364 local flags device target
1366 test -d "$dir" || return 0
1367 test -n "$xid" || return 0
1369 for i in "$dir"/*; do
1370 test -d "$i" || continue
1372 local -a vdevmap_opts=()
1373 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1374 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1375 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1377 getFileValue flags "$i/flags" || :
1378 getFileValue device "$i/device" || :
1379 getFileValue target "$i/target" || :
1380 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1381 ${device:+--device "$device"} ${target:+--target "$target"} )
1383 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?