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 ! $_VSERVER_INFO PIDSPACE FEATURE ) || \
774 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
776 test ! -e "$d"/net || {
777 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
778 # network context and namespace don't make much sense
779 _HAVE_CHBIND_OPTIONS=1
784 getFileValue mask "$d"/mask || \
785 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
788 ## Usage: prepareInit <vserver-directory>
791 pushd "$1/vdir" >/dev/null
794 { find var/run ! -type d -print0; \
795 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
798 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
799 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
804 "${INITCMD_PREPARE[@]}"
808 ## Usage: prepareInit <vserver-directory>
811 pushd "$1/vdir" >/dev/null
814 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
817 "${STOPCMD_PREPARE[@]}"
822 function generateOptions
824 _generateInterfaceOptions "$1"
825 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
826 _generateNiceCommand "$1"
827 _generateIONiceCommand "$1"
828 _generateInitOptions "$1"
829 _generateChcontextOptions "$1"
830 _generateScheduleOptions "$1"
831 _generatePersonalityOptions "$1"
832 _generateTagOptions "$1"
833 _generateMemctrlOptions "$1"
834 _generateSpaceOptions "$1"
836 if test -n "$_IS_FAKEINIT"; then
837 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
838 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
846 local f="$vdir"/cpuset
850 test -d "$f" || return 0
851 test -e "$f"/name || return 0
853 read cpuset < "$f"/name
854 test -e "$f"/nocreate || {
855 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
856 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
857 if test -e "$f"/"$i"; then
858 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
866 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
867 if [ "$configured" -ne 0 ]; then
869 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
870 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
875 function removeCPUSET
879 local f="$vdir"/cpuset
881 test -d "$f" || return 0
882 test -e "$f"/name || return 0
884 read cpuset < "$f"/name
885 test -e "$f"/nocreate || {
886 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
890 function _mountVserverInternal
895 test -e "$fstab" || return 0
898 pushd "$vdir" >/dev/null
899 # check whether / is mounted readonly or whether there is special
900 # magic regarding the mtab file; when etc/mtab can not be touched,
901 # add the '-n' flag to mount
902 test -w etc -o -w etc/mtab || xflag=-n
903 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
911 local fstab="$cfgdir"/fstab
914 test -e "$fstab" || return 0
915 pushd "$vdir" >/dev/null
916 # check whether / is mounted readonly or whether there is special
917 # magic regarding the mtab file; when etc/mtab can not be touched,
918 # add the '-n' flag to mount
919 test -w etc -o -w etc/mtab || xflag=-n
920 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
924 function mountVserver
931 test -e "$cfgdir"/fstab -o \
932 -e "$cfgdir"/fstab.local -o \
933 -e "$cfgdir"/fstab.remote || return 0
935 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
937 pushd "$vdir" >/dev/null
938 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
941 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
943 _mountVserverInternal "$cfgdir"/fstab
944 _mountVserverInternal "$cfgdir"/fstab.local
945 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
947 isNamespaceCleanup "$cfgdir" && \
948 _namespaceCleanup "$cfgdir"
950 isAvoidNamespace "$cfgdir" || \
951 $_SECURE_MOUNT --rbind -n "$vdir" "/"
954 function _umountVserverInternal
957 test -e "$fstab" || return 0
962 while read src dst tmp; do
963 test -n "$tmp" || continue
969 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
975 function umountVserver
981 isAvoidNamespace "$cfgdir" || return 0
982 test -e "$cfgdir"/fstab -o \
983 -e "$cfgdir"/fstab.local -o \
984 -e "$cfgdir"/fstab.remote || return 0
985 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
987 pushd "$vdir/" >/dev/null || return 1
988 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
989 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
990 _umountVserverInternal "$cfgdir"/fstab || is_ok=
991 popd >/dev/null || return 1
999 local fstab="$cfgdir"/fstab
1003 test -e "$fstab" || return 0
1005 export FSTAB_FILE="$fstab"
1008 test "$fsck_exitcode" -eq 0 -o \
1009 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
1012 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
1016 test -n "$_NEED_VSHELPER_SYNC" && \
1017 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
1019 vshelper.initSync "$1" "$3" "$_is_meth"
1022 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
1025 if $_VSERVER_INFO - FEATURE vwait; then
1027 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
1030 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
1031 --status-fd 3 "$2" \
1032 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
1035 if test "$rc" -ne 0 -a "$rc" -ne 1; then
1036 $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
1037 killContext "$S_CONTEXT" 9
1041 ) 4>$_is_tmpdir/procs &
1043 echo "$!" >$_is_tmpdir/pid
1044 eval "$3"=$_is_tmpdir
1049 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
1050 function _waitForVWait
1055 declare -r procs=$(cat $4)
1057 getFileArray status "$2"
1062 'vwait' exited with error '$2' which indicates that vserver could not
1063 be stopped properly"
1066 (KILLED) warning $"\
1067 A timeout occured while waiting for the vserver to finish and it was
1068 killed by sending a SIGKILL signal. Please investigate the reasons
1069 and/or increase the timeout in apps/vshelper/sync-timeout."
1072 (TIMEOUT) warning $"\
1073 A timeout occured while waiting for the vserver to finish and it will
1074 be killed by sending a SIGKILL signal. The following process list
1075 might be useful for finding out the reason of this behavior:
1077 ----------------------------------------------------------------------
1079 }----------------------------------------------------------------------"
1082 (\?\?\?|*) warning $"\
1083 internal error: 'vwait' exited with an unexpected status '$1'; I will
1084 try to continue but be prepared for unexpected events."
1091 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1092 function waitForSync
1096 local vwait_statdir=$3
1099 if test -d "$vwait_statdir"; then
1100 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1101 elif test -n "$_NEED_VSHELPER_SYNC"; then
1102 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1104 A timeout or other error occured while waiting for the synchronization
1105 signal from vserver '$VSERVER_NAME'.
1106 The vserver will be killed nevertheless..."
1107 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1108 "${INITCMD_STOP_SYNC[@]}" || \
1110 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1111 will be killed nevertheless..."
1114 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1118 function _sourceWrap
1120 local vdir name flavor start i already_handled base
1124 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1125 function execScriptlets
1129 declare -r flavor=$3
1132 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1133 local DONT_SKIP_DEFAULTS=
1134 local already_handled=
1136 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1137 isRegularFile "$i" || continue
1138 test -r "$i" || continue
1142 test -x "$i" || start=_sourceWrap
1143 $start "$i" "$flavor" "$name"
1146 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1151 function sanityCheck
1153 declare -r cfgdir=$1
1155 ! test -e "$cfgdir"/fstab.local ||
1157 WARNING: 'fstab' will *not* be executed in the network context of the
1158 vserver anymore. Therefore, 'fstab.local' has the same functionality
1159 and is obsoleted. When you need the old behaviour, put the mounts
1160 into 'fstab.remote'"
1162 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1164 WARNING: The hostname is now configured in 'uts/nodename' but not in
1167 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1169 WARNING: The domainname is now configured in 'uts/domainname' but not
1170 in 'domainname'." >&2
1174 for i in "$cfgdir"/interfaces/*/only_ip; do
1175 if test -e "$i"; then
1177 iface=${i##$cfgdir/interfaces/}
1178 iface=${iface%%/only_ip}
1180 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1185 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1187 WARNING: There is no cachedirectory configured for this vserver;
1188 please create '$cfgdir/cache' e.g. by executing
1190 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1193 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1195 vshelper.doSanityCheck
1197 $_VSERVER_INFO - VERIFYCAP ||
1198 panic $"capabilities are not enabled in kernel-setup"
1200 $_VSERVER_INFO - VERIFYPROC ||
1202 /proc/uptime can not be accessed. Usually, this is caused by
1203 procfs-security. Please read the FAQ for more details
1204 http://linux-vserver.org/Proc-Security"
1206 test -e "$cfgdir"/context || {
1207 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1208 test "$TYPE" != "static" || panic $"\
1209 The kernel does not have dynamic contexts enabled. Please configure
1210 a static one by executing
1212 echo [number between 2 and 49151] > $cfgdir/context"
1217 function _setSingleDiskLimit
1229 getFileValue ctx "$vdir/context"
1230 getFileValue directory "$dlimit/directory" || return 0
1231 getFileValue space_total "$dlimit/space_total" || return 0
1232 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1233 getFileValue reserved "$dlimit/reserved" || return 0
1235 local cachename=$ctx$directory
1236 cachename=dlimits/${cachename//\//_}
1238 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1239 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1240 $_RM -f "$vdir/cache/$cachename"
1242 if test -z "$inodes_used" -o -z "$space_used"; then
1244 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1245 inodes_used=${tmpvdu##* }
1246 space_used=${tmpvdu%% *}
1249 $_VDLIMIT --xid $ctx \
1250 --set space_used=$space_used \
1251 --set space_total=$space_total \
1252 --set inodes_used=$inodes_used \
1253 --set inodes_total=$inodes_total \
1254 --set reserved=$reserved \
1259 function setDiskLimits
1264 # Disk Limits without a static context are useless
1265 test -e "$vdir"/context || return 0
1267 for dlimit in "$vdir/dlimits/"*; do
1268 test -d "$dlimit" || continue
1269 test ! -e "$dlimit/disabled" || continue
1271 _setSingleDiskLimit "$vdir" "$dlimit"
1276 function _saveSingleDiskLimit
1283 getFileValue ctx "$vdir/context"
1284 getFileValue directory "$dlimit/directory" || return 0
1286 local cachename=$ctx$directory
1287 cachename=${cachename//\//_}
1289 # Things are getting ugly here... LFS says that /var/cache (where
1290 # cachename is usually pointing to) can vanish and applications
1291 # have to deal with it. So, we have to interprete the $vdir/cache
1292 # symlink and have to create the needed directories manually.
1293 if test -d "$vdir/cache"; then
1294 : # ok, exists already
1295 elif test -L "$vdir/cache"; then
1296 # it's a dangling symlink
1298 link=$($_READLINK "$vdir/cache")
1299 ( cd $vdir && $_MKDIR -p "$link" )
1304 test -d "$vdir/cache"
1305 $_MKDIR -p "$vdir"/cache/dlimits
1307 $_VDLIMIT --xid $ctx "$directory" | \
1308 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1310 $_VDLIMIT --xid $ctx --remove "$directory"
1314 function saveDiskLimits
1319 test -e "$vdir"/context || return 0
1321 for dlimit in "$vdir/dlimits/"*; do
1322 test -d "$dlimit" || continue
1323 test ! -e "$dlimit/disabled" || continue
1325 _saveSingleDiskLimit "$vdir" "$dlimit"
1329 function _namespaceCleanup
1332 local root=$($_VSERVER_INFO "$1" VDIR 1)
1338 getFileArray skip "$vdir"/namespace-cleanup-skip \
1339 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1341 # these are things that have to be accessible post-cleanup
1342 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1343 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1344 local real=`getPhysicalDir "$i"`
1345 test "$i" != "$real" || real=
1346 for j in "$i" "$real"; do
1347 while test -n "$j"; do
1348 list=( "${list[@]}" "$j" )
1354 local -a list_umount
1355 while read -r dev path opts; do
1356 test -n "$path" || continue
1357 for i in "$root" /dev /proc; do
1358 test "${path#$i}" != "$path" && continue 2
1360 for i in "${list[@]}" /; do
1361 test "$path" = "$i" && continue 2
1363 # unmount them in reverse order so mounts further down the tree get unmounted first
1364 list_umount=( "$path" "${list_umount[@]}" )
1366 # separate loop to avoid races while reading /proc/mounts
1367 for i in "${list_umount[@]}"; do
1368 $_UMOUNT -l -n -i "$i"
1372 function handleDeviceMap
1377 local flags device target
1379 test -d "$dir" || return 0
1380 test -n "$xid" || return 0
1382 for i in "$dir"/*; do
1383 test -d "$i" || continue
1385 local -a vdevmap_opts=()
1386 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1387 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1388 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1390 getFileValue flags "$i/flags" || :
1391 getFileValue device "$i/device" || :
1392 getFileValue target "$i/target" || :
1393 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1394 ${device:+--device "$device"} ${target:+--target "$target"} )
1396 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?