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 IONICE_CMD=()
24 declare -a CHBIND_CMD=()
25 declare -a CAP_OPTS=()
26 declare -a CHCONTEXT_INIT_OPTS=()
27 declare -a CHCONTEXT_FLAG_OPTS=()
28 declare -a CHCONTEXT_OPTS=()
29 declare -a CAPCHROOT_OPTS=()
30 declare -a INTERFACES=()
32 declare -a INITCMD_RESCUE=( /bin/sleep 900 )
33 declare -a INITCMD_START=()
34 declare -a INITCMD_START_SYNC=()
35 declare -a INITCMD_STOP=()
36 declare -a INITCMD_STOP_SYNC=()
37 declare -a INITCMD_PREPARE=()
38 declare -a INITKILL_SEQ=()
39 declare -a ENTER_SHELL=()
41 declare -a OPTS_VCONTEXT_CREATE=()
42 declare -a OPTS_VCONTEXT_MIGRATE=()
43 declare -a OPTS_VCONTEXT_ENTER=()
44 declare -a OPTS_VATTRIBUTE=( --flag fakeinit )
45 declare -a OPTS_VSCHED=()
46 declare -a OPTS_ENV=()
47 declare -a OPTS_VTAG_CREATE=()
48 declare -a OPTS_VTAG_ENTER=()
49 declare -a OPTS_VMEMCTRL=()
50 declare -a OPTS_VSPACE=()
52 declare -a STOPCMD_PREPARE=()
54 declare -a VSERVER_EXTRA_CMDS=()
57 VSHELPER_SYNC_TIMEOUT=30
62 _HAVE_INTERFACE_OPTIONS=
74 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
76 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
82 function _readFileToArray
89 test -e "$_rfta_f" || return 0
90 while read _rfta_v; do
93 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
98 function _generateChbindOptions
106 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
108 local f="$vdir"/interfaces/bcast
109 getFileValue bcast "$f"
110 f="$vdir"/interfaces/lback
111 getFileValue lback "$f"
113 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${N_CONTEXT:+--nid "$N_CONTEXT"}
114 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
117 for i in "${INTERFACES[@]}"; do
118 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
121 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
122 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
124 _HAVE_CHBIND_OPTIONS=1
127 function _generateNiceCommand
131 local current_nice=`$_NICE`
133 test -r "$vdir/nice" && read nice <"$vdir"/nice
135 let nice=$nice-$current_nice || :
136 NICE_CMD=( $_NICE -n $nice )
139 function _generateIONiceCommand
143 local ionice_priority=0
145 test -r "$vdir/ionice/class" && read ionice_class <"$vdir"/ionice/class
146 test -r "$vdir/ionice/priority" && read ionice_priority <"$vdir"/ionice/priority
148 IONICE_CMD=( $_IONICE -c$ionice_class -n$ionice_priority )
151 function _generatePersonalityOptions
154 local f="$vdir"/personality
157 test -s "$f" || return 0
166 (*) flags=$flags$delim$tmp
173 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
174 --personality-type "$type"
175 ${flags:+--personality-flags "$flags"} )
178 function _generateCCapabilityOptions
182 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
185 function _generateBCapabilityOptions
189 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
192 function _generateCapabilityOptions
197 _generateBCapabilityOptions "$vdir"
198 _generateCCapabilityOptions "$vdir"
200 test -e "$vdir"/capabilities || return 0
209 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
210 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
213 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
216 done <"$vdir"/capabilities
219 function getEnterShell
226 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
228 test -n "$ENTER_SHELL" || {
230 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
232 test -x "$vdir/vdir/$1" || continue
239 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
240 function sendKillSequence
246 while isCtxRunning "$ctx"; do
247 test -z "$wait" || sleep "$wait"
249 killContext "$ctx" "$1"
250 test -n "$2" || break
256 function _generateInitOptions
259 local cfgdir=$vdir/apps/init
264 INITCMD_START_SYNC=()
269 INITKILL_SEQ=( 15 5 9 )
270 CHCONTEXT_INIT_OPTS=()
273 test x"$INITSTYLE" = xrescue || \
274 getFileValue INITSTYLE "$cfgdir"/style
275 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
276 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
277 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
278 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
280 findFile _gio_env "$cfgdir"/environment \
281 "$__CONFDIR"/.defaults/apps/init/environment \
282 "$__PKGLIBDEFAULTDIR"/environment
283 getFileArray OPTS_ENV "$_gio_env" || :
285 case x"$INITSTYLE" in
287 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
288 INITCMD_STOP=( /sbin/killall5 )
292 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
293 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
295 for i in /etc/init.d/rc /etc/rc.d/rc; do
296 test -x "$vdir/vdir/$i" || continue
297 INITCMD_START=( "$i" "$RUNLEVEL_START" )
298 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
300 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
301 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
302 if test -n "$OPTION_DEBUG_SYSV"; then
303 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
304 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
309 INITCMD_START=( /sbin/init )
310 INITCMD_STOP=( /sbin/init )
312 _NEED_VSHELPER_SYNC=1
313 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
314 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
318 INITCMD_START=( /sbin/minit-start )
319 INITCMD_STOP=( /sbin/minit-stop )
321 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
322 _NEED_VSHELPER_SYNC=1
323 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
324 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
325 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
329 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
330 RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
332 if test -x "$vdir/vdir/lib/rcscripts/sh/init-vserver.sh"; then
333 RC_WRAP=/lib/rcscripts/sh/init-vserver.sh
334 elif test -x "$vdir/vdir/lib/rc/sh/init-vserver.sh"; then
335 RC_WRAP=/lib/rc/sh/init-vserver.sh
337 panic "init-vserver.sh not found; aborting"
340 INITCMD_START=( env TERM=$TERM $RC_WRAP "$RUNLEVEL_START" )
341 INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
342 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
346 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
349 if test x"$INITSTYLE" != xrescue; then
350 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
351 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
352 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
353 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
354 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
357 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
358 INITCMD_START_SYNC=()
363 if vshelper.isEnabled; then
364 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
370 function _generateFlagOptions
374 CHCONTEXT_FLAG_OPTS=()
376 test ! -e "$vdir"/flags || \
385 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
386 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
392 isAvoidNamespace "$vdir" || {
394 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
398 function _generateChcontextOptions
401 local ctx hostname domainname
406 read ctx <"$vdir"/context || :
408 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
409 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
412 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
414 _generateCapabilityOptions "$vdir"
415 _generateFlagOptions "$vdir"
417 CHCONTEXT_OPTS=( $SILENT_OPT \
418 "${CHCONTEXT_FLAG_OPTS[@]}" \
421 ${ctx:+--ctx "$ctx"} \
422 ${hostname:+--hostname "$hostname"} \
423 ${domainname:+--domainname "$domainname"} )
425 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
426 ${ctx:+--xid "$ctx"} )
427 ## put '--secure' at front so that it can be overridden
428 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
431 function _generateScheduleOptions
434 if test -d "$vdir"/sched; then
435 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
439 local f="$vdir"/schedule
440 test -e "$f" || return 0
442 local fill_rate interval tokens tokens_min tokens_max prio_bias
450 read prio_bias || prio_bias=
454 test -n "$prio_bias" || {
455 echo $"Bad content in '$f'; aborting..." >&2
459 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
460 --tokens "$tokens" --tokens_min "$tokens_min" \
461 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
464 function _getInterfaceValue
474 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
477 : ${_giv_tmp:=$_giv_dflt}
478 eval $_giv_val=\$_giv_tmp
481 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
482 function _transformMask2Prefix
486 test -n "$_tm2p_tmp" || {
487 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
494 function _addInterfaceCmd
496 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
497 let ++INTERFACE_CMDS_IDX
500 ## Usage: _generateMac <var> <iface> <ctx>
501 function _generateMac
504 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
508 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
511 function _getVLANInfo
516 creation of VLAN_PLUS_VID devices is not supported; please create them
517 before starting the vserver and use the 'nodev' flag then"
518 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
522 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
523 create them before starting the vserver and use the 'nodev' flag then"
524 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
526 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
527 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
538 test -e "$iface/tun" -o -e "$iface/tap" || return 1
539 test ! -e "$iface/tun" || echo --tun
540 test ! -e "$iface/tap" || echo --tap
541 test ! -e "$iface/nocsum" || echo --~checksum
542 test -e "$iface/shared" || echo --nid-failure-ok "$N_CONTEXT"
543 if test -e "$iface/uid"; then
545 getFileValue uid "$iface/uid"
548 if test -e "$iface/gid"; then
550 getFileValue gid "$iface/gid"
553 if test -e "$iface/linktype"; then
555 getFileValue linktype "$iface/linktype"
556 echo --linktype "$linktype"
561 ## Usage: _processSingleInterface <interface-directory>
562 function _processSingleInterface
578 _getInterfaceValue ip '' "$iface"
579 _getInterfaceValue extip '' "$iface" "$iface/.."
580 _getInterfaceValue dev '' "$iface" "$iface/.."
581 _getInterfaceValue prefix '' "$iface" "$iface/.."
582 _getInterfaceValue mask '' "$iface" "$iface/.."
583 _getInterfaceValue bcast '' "$iface" "$iface/.."
584 _getInterfaceValue name '' "$iface"
585 _getInterfaceValue scope '' "$iface" "$iface/.."
586 _getInterfaceValue mac '' "$iface"
587 _getInterfaceValue peer '' "$iface"
589 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
590 test -n "$dev" -o -e "$iface"/nodev || {
591 echo $"No device specified for '$iface'" >&2
595 test ! -e "$iface"/down || up=
598 _transformMask2Prefix prefix "$prefix" "$mask"
599 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
601 test ! -e "$iface"/nodev || break
603 test ! -e "$iface"/only_ip || break
605 test -e "$iface/vlandev" \
606 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
607 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
608 -a ! -e "$iface/novlandev" \
609 -a ! -e "$iface/../novlandev" \) && {
611 if vlan_info=$(_getVLANInfo "$dev"); then
612 test -d /proc/net/vlan || {
613 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
616 _addInterfaceCmd VCONFIG $vlan_info
620 if ! test -e "$iface"/indirect; then
622 local use_bcast="broadcast ${bcast:-+}"
623 echo "$ip" | $_GREP -q : && use_bcast=
626 if tun_info=$(_getTunInfo "$iface"); then
627 _addInterfaceCmd TUNCTL "$dev" $tun_info
630 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev" ${peer:+peer "$peer"}
631 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
632 _addInterfaceCmd IP_LINK "$dev" $up
633 elif ! test -n "$N_CONTEXT"; then
634 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
637 test -z "$mac" || _generateMac mac "$(basename $iface)" "$N_CONTEXT" || return 1
638 _addInterfaceCmd MODPROBE dummy "$dev"
639 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
640 _addInterfaceCmd NAMEIF "$dev" "$mac"
641 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
642 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$N_CONTEXT" "$extip"
649 ## Usage: _generateInterfaceOptions <vserver-directory>
650 function _generateInterfaceOptions
654 # XXX: This is here instead of in _generateChbindOptions
655 # to avoid a circular dependency
656 getFileValue N_CONTEXT "$1/ncontext" "$1/context"
657 test -n "$N_CONTEXT" -o -z "$S_CONTEXT" || N_CONTEXT="$S_CONTEXT"
659 for iface in "$1/interfaces/"*; do
660 test -d "$iface" || continue
661 test ! -e "$iface"/disabled || continue
663 _processSingleInterface "$iface"
665 _HAVE_INTERFACE_OPTIONS=1
668 function enableInterfaces
673 lock "$__LOCKDIR"/vserver.interfaces
675 while test $i -lt $INTERFACE_CMDS_IDX; do
676 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
687 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
689 NAMEIF) $_NAMEIF "$@";;
690 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
691 $_VCONFIG add "$2" "$3" >/dev/null;;
692 IP_ADDR) $_IP addr add "$@";;
693 IP_ADDR_FLUSH) $_IP addr flush "$@";;
694 IP_LINK) $_IP link set "$@";;
695 IP_ROUTE) $_IP route add "$@";;
699 $_TUNCTL --persist "$@" "$dev"
701 *) echo "Unknown interface-command type '$type'" >&2; false;;
710 function disableInterfaces
712 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
714 local i=$INTERFACE_CMDS_IDX
717 lock "$__LOCKDIR"/vserver.interfaces
719 while test $i -gt 0; do
722 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
729 MODPROBE) $_RMMOD "${2:-$1}";;
731 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
732 IP_ADDR) $_IP addr del "$@";;
734 IP_LINK) ;; ## Ignore the link-down command for now
735 IP_ROUTE) $_IP route del "$@";;
736 TUNCTL) $_TUNCTL --~persist "$1";;
737 *) echo "Unknown interface-command type '$type'" >&2; false;;
744 function _generateTagOptions
749 getFileValue tag "$vdir/tag" "$vdir/context"
750 test -n "$tag" || return 0
752 OPTS_VTAG_CREATE=( --tag "$tag" )
753 OPTS_VTAG_ENTER=( --tag "$tag" )
756 function _generateMemctrlOptions
761 getFileValue badness "$vdir/badness"
762 test -n "$badness" || return 0
764 OPTS_VMEMCTRL=( --badness "$badness" )
767 function _generateSpaceOptions
770 local d="$vdir"/spaces
772 ( test ! -e "$d"/pid ) || \
773 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
775 test ! -e "$d"/net || {
776 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
777 # network context and namespace don't make much sense
778 _HAVE_CHBIND_OPTIONS=1
783 getFileValue mask "$d"/mask || \
784 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
787 ## Usage: prepareInit <vserver-directory>
790 pushd "$1/vdir" >/dev/null
793 { find var/run ! -type d -print0; \
794 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
797 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
798 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
803 "${INITCMD_PREPARE[@]}"
807 ## Usage: prepareInit <vserver-directory>
810 pushd "$1/vdir" >/dev/null
813 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
816 "${STOPCMD_PREPARE[@]}"
821 function generateOptions
823 _generateInterfaceOptions "$1"
824 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
825 _generateNiceCommand "$1"
826 _generateIONiceCommand "$1"
827 _generateInitOptions "$1"
828 _generateChcontextOptions "$1"
829 _generateScheduleOptions "$1"
830 _generatePersonalityOptions "$1"
831 _generateTagOptions "$1"
832 _generateMemctrlOptions "$1"
833 _generateSpaceOptions "$1"
835 if test -n "$_IS_FAKEINIT"; then
836 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
837 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
845 local f="$vdir"/cpuset
849 test -d "$f" || return 0
850 test -e "$f"/name || return 0
852 read cpuset < "$f"/name
853 test -e "$f"/nocreate || {
854 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
855 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
856 if test -e "$f"/"$i"; then
857 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
865 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
866 if [ "$configured" -ne 0 ]; then
868 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
869 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
874 function removeCPUSET
878 local f="$vdir"/cpuset
880 test -d "$f" || return 0
881 test -e "$f"/name || return 0
883 read cpuset < "$f"/name
884 test -e "$f"/nocreate || {
885 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
889 function _mountVserverInternal
894 test -e "$fstab" || return 0
897 pushd "$vdir" >/dev/null
898 # check whether / is mounted readonly or whether there is special
899 # magic regarding the mtab file; when etc/mtab can not be touched,
900 # add the '-n' flag to mount
901 test -w etc -o -w etc/mtab || xflag=-n
902 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
910 local fstab="$cfgdir"/fstab
913 test -e "$fstab" || return 0
914 pushd "$vdir" >/dev/null
915 # check whether / is mounted readonly or whether there is special
916 # magic regarding the mtab file; when etc/mtab can not be touched,
917 # add the '-n' flag to mount
918 test -w etc -o -w etc/mtab || xflag=-n
919 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
923 function mountVserver
930 test -e "$cfgdir"/fstab -o \
931 -e "$cfgdir"/fstab.local -o \
932 -e "$cfgdir"/fstab.remote || return 0
934 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
936 pushd "$vdir" >/dev/null
937 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
940 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
942 _mountVserverInternal "$cfgdir"/fstab
943 _mountVserverInternal "$cfgdir"/fstab.local
944 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
946 isNamespaceCleanup "$cfgdir" && \
947 _namespaceCleanup "$cfgdir"
949 isAvoidNamespace "$cfgdir" || \
950 $_SECURE_MOUNT --rbind -n "$vdir" "/"
953 function _umountVserverInternal
956 test -e "$fstab" || return 0
961 while read src dst tmp; do
962 test -n "$tmp" || continue
968 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
974 function umountVserver
980 isAvoidNamespace "$cfgdir" || return 0
981 test -e "$cfgdir"/fstab -o \
982 -e "$cfgdir"/fstab.local -o \
983 -e "$cfgdir"/fstab.remote || return 0
984 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
986 pushd "$vdir/" >/dev/null || return 1
987 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
988 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
989 _umountVserverInternal "$cfgdir"/fstab || is_ok=
990 popd >/dev/null || return 1
998 local fstab="$cfgdir"/fstab
1002 test -e "$fstab" || return 0
1004 export FSTAB_FILE="$fstab"
1007 test "$fsck_exitcode" -eq 0 -o \
1008 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
1011 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
1015 test -n "$_NEED_VSHELPER_SYNC" && \
1016 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
1018 vshelper.initSync "$1" "$3" "$_is_meth"
1021 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
1024 if $_VSERVER_INFO - FEATURE vwait; then
1026 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
1029 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
1030 --status-fd 3 "$2" \
1031 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
1034 if test "$rc" -ne 0 -a "$rc" -ne 1; then
1035 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
1036 killContext "$S_CONTEXT" 9
1040 ) 4>$_is_tmpdir/procs &
1042 echo "$!" >$_is_tmpdir/pid
1043 eval "$3"=$_is_tmpdir
1048 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
1049 function _waitForVWait
1054 declare -r procs=$(cat $4)
1056 getFileArray status "$2"
1061 'vwait' exited with error '$2' which indicates that vserver could not
1062 be stopped properly"
1065 (KILLED) warning $"\
1066 A timeout occured while waiting for the vserver to finish and it was
1067 killed by sending a SIGKILL signal. Please investigate the reasons
1068 and/or increase the timeout in apps/vshelper/sync-timeout."
1071 (TIMEOUT) warning $"\
1072 A timeout occured while waiting for the vserver to finish and it will
1073 be killed by sending a SIGKILL signal. The following process list
1074 might be useful for finding out the reason of this behavior:
1076 ----------------------------------------------------------------------
1078 }----------------------------------------------------------------------"
1081 (\?\?\?|*) warning $"\
1082 internal error: 'vwait' exited with an unexpected status '$1'; I will
1083 try to continue but be prepared for unexpected events."
1090 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1091 function waitForSync
1095 local vwait_statdir=$3
1098 if test -d "$vwait_statdir"; then
1099 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1100 elif test -n "$_NEED_VSHELPER_SYNC"; then
1101 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1103 A timeout or other error occured while waiting for the synchronization
1104 signal from vserver '$VSERVER_NAME'.
1105 The vserver will be killed nevertheless..."
1106 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1107 "${INITCMD_STOP_SYNC[@]}" || \
1109 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1110 will be killed nevertheless..."
1113 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1117 function _sourceWrap
1119 local vdir name flavor start i already_handled base
1123 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1124 function execScriptlets
1128 declare -r flavor=$3
1131 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1132 local DONT_SKIP_DEFAULTS=
1133 local already_handled=
1135 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1136 isRegularFile "$i" || continue
1137 test -r "$i" || continue
1141 test -x "$i" || start=_sourceWrap
1142 $start "$i" "$flavor" "$name"
1145 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1150 function sanityCheck
1152 declare -r cfgdir=$1
1154 ! test -e "$cfgdir"/fstab.local ||
1156 WARNING: 'fstab' will *not* be executed in the network context of the
1157 vserver anymore. Therefore, 'fstab.local' has the same functionality
1158 and is obsoleted. When you need the old behaviour, put the mounts
1159 into 'fstab.remote'"
1161 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1163 WARNING: The hostname is now configured in 'uts/nodename' but not in
1166 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1168 WARNING: The domainname is now configured in 'uts/domainname' but not
1169 in 'domainname'." >&2
1173 for i in "$cfgdir"/interfaces/*/only_ip; do
1174 if test -e "$i"; then
1176 iface=${i##$cfgdir/interfaces/}
1177 iface=${iface%%/only_ip}
1179 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1184 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1186 WARNING: There is no cachedirectory configured for this vserver;
1187 please create '$cfgdir/cache' e.g. by executing
1189 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1192 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1194 vshelper.doSanityCheck
1196 $_VSERVER_INFO - VERIFYCAP ||
1197 panic $"capabilities are not enabled in kernel-setup"
1199 $_VSERVER_INFO - VERIFYPROC ||
1201 /proc/uptime can not be accessed. Usually, this is caused by
1202 procfs-security. Please read the FAQ for more details
1203 http://linux-vserver.org/Proc-Security"
1205 test -e "$cfgdir"/context || {
1206 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1207 test "$TYPE" != "static" || panic $"\
1208 The kernel does not have dynamic contexts enabled. Please configure
1209 a static one by executing
1211 echo [number between 2 and 49151] > $cfgdir/context"
1216 function _setSingleDiskLimit
1228 getFileValue ctx "$vdir/context"
1229 getFileValue directory "$dlimit/directory" || return 0
1230 getFileValue space_total "$dlimit/space_total" || return 0
1231 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1232 getFileValue reserved "$dlimit/reserved" || return 0
1234 local cachename=$ctx$directory
1235 cachename=dlimits/${cachename//\//_}
1237 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1238 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1239 $_RM -f "$vdir/cache/$cachename"
1241 if test -z "$inodes_used" -o -z "$space_used"; then
1243 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1244 inodes_used=${tmpvdu##* }
1245 space_used=${tmpvdu%% *}
1248 $_VDLIMIT --xid $ctx \
1249 --set space_used=$space_used \
1250 --set space_total=$space_total \
1251 --set inodes_used=$inodes_used \
1252 --set inodes_total=$inodes_total \
1253 --set reserved=$reserved \
1258 function setDiskLimits
1263 # Disk Limits without a static context are useless
1264 test -e "$vdir"/context || return 0
1266 for dlimit in "$vdir/dlimits/"*; do
1267 test -d "$dlimit" || continue
1268 test ! -e "$dlimit/disabled" || continue
1270 _setSingleDiskLimit "$vdir" "$dlimit"
1275 function _saveSingleDiskLimit
1282 getFileValue ctx "$vdir/context"
1283 getFileValue directory "$dlimit/directory" || return 0
1285 local cachename=$ctx$directory
1286 cachename=${cachename//\//_}
1288 # Things are getting ugly here... LFS says that /var/cache (where
1289 # cachename is usually pointing to) can vanish and applications
1290 # have to deal with it. So, we have to interprete the $vdir/cache
1291 # symlink and have to create the needed directories manually.
1292 if test -d "$vdir/cache"; then
1293 : # ok, exists already
1294 elif test -L "$vdir/cache"; then
1295 # it's a dangling symlink
1297 link=$($_READLINK "$vdir/cache")
1298 ( cd $vdir && $_MKDIR -p "$link" )
1303 test -d "$vdir/cache"
1304 $_MKDIR -p "$vdir"/cache/dlimits
1306 $_VDLIMIT --xid $ctx "$directory" | \
1307 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1309 $_VDLIMIT --xid $ctx --remove "$directory"
1313 function saveDiskLimits
1318 test -e "$vdir"/context || return 0
1320 for dlimit in "$vdir/dlimits/"*; do
1321 test -d "$dlimit" || continue
1322 test ! -e "$dlimit/disabled" || continue
1324 _saveSingleDiskLimit "$vdir" "$dlimit"
1328 function _namespaceCleanup
1331 local root=$($_VSERVER_INFO "$1" VDIR 1)
1337 getFileArray skip "$vdir"/namespace-cleanup-skip \
1338 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1340 # these are things that have to be accessible post-cleanup
1341 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1342 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1343 local real=`getPhysicalDir "$i"`
1344 test "$i" != "$real" || real=
1345 for j in "$i" "$real"; do
1346 while test -n "$j"; do
1347 list=( "${list[@]}" "$j" )
1353 local -a list_umount
1354 while read -r dev path opts; do
1355 test -n "$path" || continue
1356 for i in "$root" /dev /proc; do
1357 test "${path#$i}" != "$path" && continue 2
1359 for i in "${list[@]}" /; do
1360 test "$path" = "$i" && continue 2
1362 # unmount them in reverse order so mounts further down the tree get unmounted first
1363 list_umount=( "$path" "${list_umount[@]}" )
1365 # separate loop to avoid races while reading /proc/mounts
1366 for i in "${list_umount[@]}"; do
1367 $_UMOUNT -l -n -i "$i"
1371 function handleDeviceMap
1376 local flags device target
1378 test -d "$dir" || return 0
1379 test -n "$xid" || return 0
1381 for i in "$dir"/*; do
1382 test -d "$i" || continue
1384 local -a vdevmap_opts=()
1385 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1386 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1387 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1389 getFileValue flags "$i/flags" || :
1390 getFileValue device "$i/device" || :
1391 getFileValue target "$i/target" || :
1392 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1393 ${device:+--device "$device"} ${target:+--target "$target"} )
1395 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?