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 CGROUP_MNT=/dev/cgroup
76 declare -a CGROUP_INHERIT=( cpuset.cpus cpuset.mems )
78 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
80 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
86 function _readFileToArray
93 test -e "$_rfta_f" || return 0
94 while read _rfta_v; do
97 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
102 function _generateChbindOptions
110 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
112 local f="$vdir"/interfaces/bcast
113 getFileValue bcast "$f"
114 f="$vdir"/interfaces/lback
115 getFileValue lback "$f"
117 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${N_CONTEXT:+--nid "$N_CONTEXT"}
118 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
121 for i in "${INTERFACES[@]}"; do
122 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
125 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
126 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
128 _HAVE_CHBIND_OPTIONS=1
131 function _generateNiceCommand
135 local current_nice=`$_NICE`
137 test -r "$vdir/nice" && read nice <"$vdir"/nice
139 let nice=$nice-$current_nice || :
140 NICE_CMD=( $_NICE -n $nice )
143 function _generateIONiceCommand
147 local ionice_priority=0
149 test -r "$vdir/ionice/class" && read ionice_class <"$vdir"/ionice/class
150 test -r "$vdir/ionice/priority" && read ionice_priority <"$vdir"/ionice/priority
152 IONICE_CMD=( $_IONICE -c$ionice_class -n$ionice_priority )
155 function _generatePersonalityOptions
158 local f="$vdir"/personality
161 test -s "$f" || return 0
170 (*) flags=$flags$delim$tmp
177 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
178 --personality-type "$type"
179 ${flags:+--personality-flags "$flags"} )
182 function _generateCCapabilityOptions
186 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
189 function _generateBCapabilityOptions
193 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
196 function _generateCapabilityOptions
201 _generateBCapabilityOptions "$vdir"
202 _generateCCapabilityOptions "$vdir"
204 test -e "$vdir"/capabilities || return 0
213 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
214 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
217 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
220 done <"$vdir"/capabilities
223 function getEnterShell
230 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
232 test -n "$ENTER_SHELL" || {
234 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
236 test -x "$vdir/vdir/$1" || continue
243 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
244 function sendKillSequence
250 while isCtxRunning "$ctx"; do
251 test -z "$wait" || sleep "$wait"
253 killContext "$ctx" "$1"
254 test -n "$2" || break
260 function _generateInitOptions
263 local cfgdir=$vdir/apps/init
268 INITCMD_START_SYNC=()
273 INITKILL_SEQ=( 15 5 9 )
274 CHCONTEXT_INIT_OPTS=()
277 test x"$INITSTYLE" = xrescue || \
278 getFileValue INITSTYLE "$cfgdir"/style
279 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
280 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
281 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
282 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
284 findFile _gio_env "$cfgdir"/environment \
285 "$__CONFDIR"/.defaults/apps/init/environment \
286 "$__PKGLIBDEFAULTDIR"/environment
287 getFileArray OPTS_ENV "$_gio_env" || :
289 case x"$INITSTYLE" in
291 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
292 INITCMD_STOP=( /sbin/killall5 )
296 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
297 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
299 for i in /etc/init.d/rc /etc/rc.d/rc; do
300 test -x "$vdir/vdir/$i" || continue
301 INITCMD_START=( "$i" "$RUNLEVEL_START" )
302 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
304 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
305 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
306 if test -n "$OPTION_DEBUG_SYSV"; then
307 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
308 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
313 INITCMD_START=( /sbin/init )
314 INITCMD_STOP=( /sbin/init )
316 _NEED_VSHELPER_SYNC=1
317 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
318 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
322 INITCMD_START=( /sbin/minit-start )
323 INITCMD_STOP=( /sbin/minit-stop )
325 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
326 _NEED_VSHELPER_SYNC=1
327 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
328 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
329 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
333 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
334 RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
336 if test -x "$vdir/vdir/lib/rcscripts/sh/init-vserver.sh"; then
337 RC_WRAP=/lib/rcscripts/sh/init-vserver.sh
338 elif test -x "$vdir/vdir/lib/rc/sh/init-vserver.sh"; then
339 RC_WRAP=/lib/rc/sh/init-vserver.sh
341 panic "init-vserver.sh not found; aborting"
344 INITCMD_START=( env TERM=$TERM $RC_WRAP "$RUNLEVEL_START" )
345 INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
346 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
350 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
351 INITCMD_START=( /etc/rc.multi )
352 INITCMD_STOP=( /etc/rc.shutdown )
353 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
357 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
360 if test x"$INITSTYLE" != xrescue; then
361 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
362 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
363 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
364 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
365 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
368 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
369 INITCMD_START_SYNC=()
374 if vshelper.isEnabled; then
375 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
381 function _generateFlagOptions
386 CHCONTEXT_FLAG_OPTS=()
388 findFile file "$vdir"/cflags "$vdir"/flags ""
398 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
399 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
405 isAvoidNamespace "$vdir" || {
407 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
411 function _generateChcontextOptions
414 local ctx hostname domainname
419 read ctx <"$vdir"/context || :
421 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
422 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
425 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
427 _generateCapabilityOptions "$vdir"
428 _generateFlagOptions "$vdir"
430 CHCONTEXT_OPTS=( $SILENT_OPT \
431 "${CHCONTEXT_FLAG_OPTS[@]}" \
434 ${ctx:+--ctx "$ctx"} \
435 ${hostname:+--hostname "$hostname"} \
436 ${domainname:+--domainname "$domainname"} )
438 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
439 ${ctx:+--xid "$ctx"} )
440 ## put '--secure' at front so that it can be overridden
441 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
444 function _generateScheduleOptions
447 if test -d "$vdir"/sched; then
448 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
452 local f="$vdir"/schedule
453 test -e "$f" || return 0
455 local fill_rate interval tokens tokens_min tokens_max prio_bias
463 read prio_bias || prio_bias=
467 test -n "$prio_bias" || {
468 echo $"Bad content in '$f'; aborting..." >&2
472 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
473 --tokens "$tokens" --tokens_min "$tokens_min" \
474 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
477 function _getInterfaceValue
487 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
490 : ${_giv_tmp:=$_giv_dflt}
491 eval $_giv_val=\$_giv_tmp
494 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
495 function _transformMask2Prefix
499 test -n "$_tm2p_tmp" || {
500 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
507 function _addInterfaceCmd
509 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
510 let ++INTERFACE_CMDS_IDX
513 ## Usage: _generateMac <var> <iface> <ctx>
514 function _generateMac
517 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
521 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
524 function _getVLANInfo
529 creation of VLAN_PLUS_VID devices is not supported; please create them
530 before starting the vserver and use the 'nodev' flag then"
531 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
535 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
536 create them before starting the vserver and use the 'nodev' flag then"
537 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
539 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
540 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
551 test -e "$iface/tun" -o -e "$iface/tap" || return 1
552 test ! -e "$iface/tun" || echo --tun
553 test ! -e "$iface/tap" || echo --tap
554 test ! -e "$iface/nocsum" || echo --~checksum
555 test -e "$iface/shared" || echo --nid-failure-ok "$N_CONTEXT"
556 if test -e "$iface/uid"; then
558 getFileValue uid "$iface/uid"
561 if test -e "$iface/gid"; then
563 getFileValue gid "$iface/gid"
566 if test -e "$iface/linktype"; then
568 getFileValue linktype "$iface/linktype"
569 echo --linktype "$linktype"
574 ## Usage: _processSingleInterface <interface-directory>
575 function _processSingleInterface
591 _getInterfaceValue ip '' "$iface"
592 _getInterfaceValue extip '' "$iface" "$iface/.."
593 _getInterfaceValue dev '' "$iface" "$iface/.."
594 _getInterfaceValue prefix '' "$iface" "$iface/.."
595 _getInterfaceValue mask '' "$iface" "$iface/.."
596 _getInterfaceValue bcast '' "$iface" "$iface/.."
597 _getInterfaceValue name '' "$iface"
598 _getInterfaceValue scope '' "$iface" "$iface/.."
599 _getInterfaceValue mac '' "$iface"
600 _getInterfaceValue peer '' "$iface"
602 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
603 test -n "$dev" -o -e "$iface"/nodev || {
604 echo $"No device specified for '$iface'" >&2
608 test ! -e "$iface"/down || up=
611 _transformMask2Prefix prefix "$prefix" "$mask"
612 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
614 test ! -e "$iface"/nodev || break
616 test ! -e "$iface"/only_ip || break
618 test -e "$iface/vlandev" \
619 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
620 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
621 -a ! -e "$iface/novlandev" \
622 -a ! -e "$iface/../novlandev" \) && {
624 if vlan_info=$(_getVLANInfo "$dev"); then
625 test -d /proc/net/vlan || {
626 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
629 _addInterfaceCmd VCONFIG $vlan_info
633 if ! test -e "$iface"/indirect; then
635 local use_bcast="broadcast ${bcast:-+}"
636 echo "$ip" | $_GREP -q : && use_bcast=
639 if tun_info=$(_getTunInfo "$iface"); then
640 _addInterfaceCmd TUNCTL "$dev" $tun_info
643 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev" ${peer:+peer "$peer"}
644 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
645 _addInterfaceCmd IP_LINK "$dev" $up
646 elif ! test -n "$N_CONTEXT"; then
647 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
650 test -z "$mac" || _generateMac mac "$(basename $iface)" "$N_CONTEXT" || return 1
651 _addInterfaceCmd MODPROBE dummy "$dev"
652 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
653 _addInterfaceCmd NAMEIF "$dev" "$mac"
654 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
655 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$N_CONTEXT" "$extip"
662 ## Usage: _generateInterfaceOptions <vserver-directory>
663 function _generateInterfaceOptions
667 # XXX: This is here instead of in _generateChbindOptions
668 # to avoid a circular dependency
669 getFileValue N_CONTEXT "$1/ncontext" "$1/context"
670 test -n "$N_CONTEXT" -o -z "$S_CONTEXT" || N_CONTEXT="$S_CONTEXT"
672 for iface in "$1/interfaces/"*; do
673 test -d "$iface" || continue
674 test ! -e "$iface"/disabled || continue
676 _processSingleInterface "$iface"
678 _HAVE_INTERFACE_OPTIONS=1
681 function enableInterfaces
686 lock "$__LOCKDIR"/vserver.interfaces
688 while test $i -lt $INTERFACE_CMDS_IDX; do
689 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
700 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
702 NAMEIF) $_NAMEIF "$@";;
703 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
704 $_VCONFIG add "$2" "$3" >/dev/null;;
705 IP_ADDR) $_IP addr add "$@";;
706 IP_ADDR_FLUSH) $_IP addr flush "$@";;
707 IP_LINK) $_IP link set "$@";;
708 IP_ROUTE) $_IP route add "$@";;
712 $_TUNCTL --persist "$@" "$dev"
714 *) echo "Unknown interface-command type '$type'" >&2; false;;
723 function disableInterfaces
725 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
727 local i=$INTERFACE_CMDS_IDX
730 lock "$__LOCKDIR"/vserver.interfaces
732 while test $i -gt 0; do
735 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
742 MODPROBE) $_RMMOD "${2:-$1}";;
744 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
745 IP_ADDR) $_IP addr del "$@";;
747 IP_LINK) ;; ## Ignore the link-down command for now
748 IP_ROUTE) $_IP route del "$@";;
749 TUNCTL) $_TUNCTL --~persist "$1";;
750 *) echo "Unknown interface-command type '$type'" >&2; false;;
757 function _generateTagOptions
762 getFileValue tag "$vdir/tag" "$vdir/context"
763 test -n "$tag" || return 0
765 OPTS_VTAG_CREATE=( --tag "$tag" )
766 OPTS_VTAG_ENTER=( --tag "$tag" )
769 function _generateMemctrlOptions
774 getFileValue badness "$vdir/badness"
775 test -n "$badness" || return 0
777 OPTS_VMEMCTRL=( --badness "$badness" )
780 function _generateSpaceOptions
783 local d="$vdir"/spaces
785 ( test ! -e "$d"/pid ) || \
786 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
788 test ! -e "$d"/net || {
789 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
790 # network context and namespace don't make much sense
791 _HAVE_CHBIND_OPTIONS=1
796 getFileValue mask "$d"/mask || \
797 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
800 ## Usage: prepareInit <vserver-directory>
803 pushd "$1/vdir" >/dev/null
806 { find var/run ! -type d -print0; \
807 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
810 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
811 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
816 "${INITCMD_PREPARE[@]}"
820 ## Usage: prepareInit <vserver-directory>
823 pushd "$1/vdir" >/dev/null
826 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
829 "${STOPCMD_PREPARE[@]}"
834 function generateOptions
836 _generateInterfaceOptions "$1"
837 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
838 _generateNiceCommand "$1"
839 _generateIONiceCommand "$1"
840 _generateInitOptions "$1"
841 _generateChcontextOptions "$1"
842 _generateScheduleOptions "$1"
843 _generatePersonalityOptions "$1"
844 _generateTagOptions "$1"
845 _generateMemctrlOptions "$1"
846 _generateSpaceOptions "$1"
847 _generateCgroupOptions
849 if test -n "$_IS_FAKEINIT"; then
850 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
851 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
859 local f="$vdir"/cpuset
863 test -d "$f" || return 0
864 test -e "$f"/name || return 0
866 read cpuset < "$f"/name
867 test -e "$f"/nocreate || {
868 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
869 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
870 if test -e "$f"/"$i"; then
871 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
879 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
880 if [ "$configured" -ne 0 ]; then
882 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
883 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
888 function removeCPUSET
892 local f="$vdir"/cpuset
894 test -d "$f" || return 0
895 test -e "$f"/name || return 0
897 read cpuset < "$f"/name
898 test -e "$f"/nocreate || {
899 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
903 function _mountVserverInternal
908 test -e "$fstab" || return 0
911 pushd "$vdir" >/dev/null
912 # check whether / is mounted readonly or whether there is special
913 # magic regarding the mtab file; when etc/mtab can not be touched,
914 # add the '-n' flag to mount
915 test -w etc -o -w etc/mtab || xflag=-n
916 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
924 local fstab="$cfgdir"/fstab
927 test -e "$fstab" || return 0
928 pushd "$vdir" >/dev/null
929 # check whether / is mounted readonly or whether there is special
930 # magic regarding the mtab file; when etc/mtab can not be touched,
931 # add the '-n' flag to mount
932 test -w etc -o -w etc/mtab || xflag=-n
933 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
937 function mountVserver
944 test -e "$cfgdir"/fstab -o \
945 -e "$cfgdir"/fstab.local -o \
946 -e "$cfgdir"/fstab.remote || return 0
948 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
950 pushd "$vdir" >/dev/null
951 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
954 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
956 _mountVserverInternal "$cfgdir"/fstab
957 _mountVserverInternal "$cfgdir"/fstab.local
958 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
960 isNamespaceCleanup "$cfgdir" && \
961 _namespaceCleanup "$cfgdir"
963 isAvoidNamespace "$cfgdir" || \
964 $_SECURE_MOUNT --rbind -n -o dev "$vdir" "/"
967 function _umountVserverInternal
970 test -e "$fstab" || return 0
975 while read src dst tmp; do
976 test -n "$tmp" || continue
982 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
988 function umountVserver
994 isAvoidNamespace "$cfgdir" || return 0
995 test -e "$cfgdir"/fstab -o \
996 -e "$cfgdir"/fstab.local -o \
997 -e "$cfgdir"/fstab.remote || return 0
998 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
1000 pushd "$vdir/" >/dev/null || return 1
1001 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
1002 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
1003 _umountVserverInternal "$cfgdir"/fstab || is_ok=
1004 popd >/dev/null || return 1
1012 local fstab="$cfgdir"/fstab
1016 test -e "$fstab" || return 0
1018 export FSTAB_FILE="$fstab"
1021 test "$fsck_exitcode" -eq 0 -o \
1022 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
1025 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
1029 test -n "$_NEED_VSHELPER_SYNC" && \
1030 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
1032 vshelper.initSync "$1" "$3" "$_is_meth"
1035 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
1038 if $_VSERVER_INFO - FEATURE vwait; then
1040 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
1043 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
1044 --status-fd 3 "$2" \
1045 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
1048 if test "$rc" -ne 0 -a "$rc" -ne 1; then
1049 $_VPS axf | $_EGREP -e "^[ \t]*[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
1050 killContext "$S_CONTEXT" 9
1054 ) 4>$_is_tmpdir/procs &
1056 echo "$!" >$_is_tmpdir/pid
1057 eval "$3"=$_is_tmpdir
1062 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
1063 function _waitForVWait
1068 declare -r procs=$(cat $4)
1070 getFileArray status "$2"
1075 'vwait' exited with error '$2' which indicates that vserver could not
1076 be stopped properly"
1079 (KILLED) warning $"\
1080 A timeout occured while waiting for the vserver to finish and it was
1081 killed by sending a SIGKILL signal. Please investigate the reasons
1082 and/or increase the timeout in apps/vshelper/sync-timeout."
1085 (TIMEOUT) warning $"\
1086 A timeout occured while waiting for the vserver to finish and it will
1087 be killed by sending a SIGKILL signal. The following process list
1088 might be useful for finding out the reason of this behavior:
1090 ----------------------------------------------------------------------
1092 }----------------------------------------------------------------------"
1095 (\?\?\?|*) warning $"\
1096 internal error: 'vwait' exited with an unexpected status '$1'; I will
1097 try to continue but be prepared for unexpected events."
1104 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1105 function waitForSync
1109 local vwait_statdir=$3
1112 if test -d "$vwait_statdir"; then
1113 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1114 elif test -n "$_NEED_VSHELPER_SYNC"; then
1115 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1117 A timeout or other error occured while waiting for the synchronization
1118 signal from vserver '$VSERVER_NAME'.
1119 The vserver will be killed nevertheless..."
1120 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1121 "${INITCMD_STOP_SYNC[@]}" || \
1123 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1124 will be killed nevertheless..."
1127 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1131 function _sourceWrap
1133 local vdir name flavor start i already_handled base
1137 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1138 function execScriptlets
1142 declare -r flavor=$3
1145 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1146 local DONT_SKIP_DEFAULTS=
1147 local already_handled=
1149 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1150 isRegularFile "$i" || continue
1151 test -r "$i" || continue
1155 test -x "$i" || start=_sourceWrap
1156 $start "$i" "$flavor" "$name"
1159 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1164 function sanityCheck
1166 declare -r cfgdir=$1
1168 ! test -e "$cfgdir"/fstab.local ||
1170 WARNING: 'fstab' will *not* be executed in the network context of the
1171 vserver anymore. Therefore, 'fstab.local' has the same functionality
1172 and is obsoleted. When you need the old behaviour, put the mounts
1173 into 'fstab.remote'"
1175 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1177 WARNING: The hostname is now configured in 'uts/nodename' but not in
1180 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1182 WARNING: The domainname is now configured in 'uts/domainname' but not
1183 in 'domainname'." >&2
1187 for i in "$cfgdir"/interfaces/*/only_ip; do
1188 if test -e "$i"; then
1190 iface=${i##$cfgdir/interfaces/}
1191 iface=${iface%%/only_ip}
1193 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1198 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1200 WARNING: There is no cachedirectory configured for this vserver;
1201 please create '$cfgdir/cache' e.g. by executing
1203 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1206 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1208 vshelper.doSanityCheck
1210 $_VSERVER_INFO - VERIFYCAP ||
1211 panic $"capabilities are not enabled in kernel-setup"
1213 $_VSERVER_INFO - VERIFYPROC ||
1215 /proc/uptime can not be accessed. Usually, this is caused by
1216 procfs-security. Please read the FAQ for more details
1217 http://linux-vserver.org/Proc-Security"
1219 test -e "$cfgdir"/context || {
1220 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1221 test "$TYPE" != "static" || panic $"\
1222 The kernel does not have dynamic contexts enabled. Please configure
1223 a static one by executing
1225 echo [number between 2 and 49151] > $cfgdir/context"
1230 function _setSingleDiskLimit
1242 getFileValue ctx "$vdir/context"
1243 getFileValue directory "$dlimit/directory" || return 0
1244 getFileValue space_total "$dlimit/space_total" || return 0
1245 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1246 getFileValue reserved "$dlimit/reserved" || return 0
1248 local cachename=$ctx$directory
1249 cachename=dlimits/${cachename//\//_}
1251 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1252 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1253 $_RM -f "$vdir/cache/$cachename"
1255 if test -z "$inodes_used" -o -z "$space_used"; then
1257 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1258 inodes_used=${tmpvdu##* }
1259 space_used=${tmpvdu%% *}
1262 $_VDLIMIT --xid $ctx \
1263 --set space_used=$space_used \
1264 --set space_total=$space_total \
1265 --set inodes_used=$inodes_used \
1266 --set inodes_total=$inodes_total \
1267 --set reserved=$reserved \
1272 function setDiskLimits
1277 # Disk Limits without a static context are useless
1278 test -e "$vdir"/context || return 0
1280 for dlimit in "$vdir/dlimits/"*; do
1281 test -d "$dlimit" || continue
1282 test ! -e "$dlimit/disabled" || continue
1284 _setSingleDiskLimit "$vdir" "$dlimit"
1289 function _saveSingleDiskLimit
1296 getFileValue ctx "$vdir/context"
1297 getFileValue directory "$dlimit/directory" || return 0
1299 local cachename=$ctx$directory
1300 cachename=${cachename//\//_}
1302 # Things are getting ugly here... LFS says that /var/cache (where
1303 # cachename is usually pointing to) can vanish and applications
1304 # have to deal with it. So, we have to interprete the $vdir/cache
1305 # symlink and have to create the needed directories manually.
1306 if test -d "$vdir/cache"; then
1307 : # ok, exists already
1308 elif test -L "$vdir/cache"; then
1309 # it's a dangling symlink
1311 link=$($_READLINK "$vdir/cache")
1312 ( cd $vdir && $_MKDIR -p "$link" )
1317 test -d "$vdir/cache"
1318 $_MKDIR -p "$vdir"/cache/dlimits
1320 $_VDLIMIT --xid $ctx "$directory" | \
1321 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1323 $_VDLIMIT --xid $ctx --remove "$directory"
1327 function saveDiskLimits
1332 test -e "$vdir"/context || return 0
1334 for dlimit in "$vdir/dlimits/"*; do
1335 test -d "$dlimit" || continue
1336 test ! -e "$dlimit/disabled" || continue
1338 _saveSingleDiskLimit "$vdir" "$dlimit"
1342 function _namespaceCleanup
1345 local root=$($_VSERVER_INFO "$1" VDIR 1)
1351 getFileArray skip "$vdir"/namespace-cleanup-skip \
1352 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1354 # these are things that have to be accessible post-cleanup
1355 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1356 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1357 local real=`getPhysicalDir "$i"`
1358 test "$i" != "$real" || real=
1359 for j in "$i" "$real"; do
1360 while test -n "$j"; do
1361 list=( "${list[@]}" "$j" )
1367 local -a list_umount
1368 while read -r dev path opts; do
1369 test -n "$path" || continue
1370 for i in "$root" /dev /proc; do
1371 test "${path#$i}" != "$path" && continue 2
1373 for i in "${list[@]}" /; do
1374 test "$path" = "$i" && continue 2
1376 # unmount them in reverse order so mounts further down the tree get unmounted first
1377 list_umount=( "$path" "${list_umount[@]}" )
1379 # separate loop to avoid races while reading /proc/mounts
1380 for i in "${list_umount[@]}"; do
1381 $_UMOUNT -l -n -i "$i"
1385 function handleDeviceMap
1390 local flags device target
1392 test -d "$dir" || return 0
1393 test -n "$xid" || return 0
1395 for i in "$dir"/*; do
1396 test -d "$i" || continue
1398 local -a vdevmap_opts=()
1399 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1400 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1401 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1403 getFileValue flags "$i/flags" || :
1404 getFileValue device "$i/device" || :
1405 getFileValue target "$i/target" || :
1406 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1407 ${device:+--device "$device"} ${target:+--target "$target"} )
1409 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?
1415 $_GREP -q "cgroup" /proc/filesystems
1418 function _generateCgroupOptions
1422 hasCgroup || return 0
1424 findFile file "$__CONFDIR/.defaults/cgroup/mnt" ""
1425 if test -n "$file"; then
1426 read CGROUP_MNT < "$file"
1428 findFile file "$__CONFDIR/.defaults/cgroup/subsys" ""
1429 if test -n "$file"; then
1430 read CGROUP_SUBSYS < "$file"
1432 findFile file "$__CONFDIR/.defaults/cgroup/inherit" ""
1433 if test -n "$file"; then
1434 _readFileToArray CGROUP_INHERIT "$file" ""
1442 hasCgroup || return 1
1443 test -d "$CGROUP_MNT" || return 1
1444 test -d "$1/cgroup" -o \
1445 \( -d "$__CONFDIR/.defaults/cgroup" -a \
1446 ! -e "$1/nocgroup" \)
1449 function _handleCgroup
1458 useCgroup "$vdir" || return 0
1460 findDir dir "$vdir/cgroup" "$__CONFDIR/.defaults/cgroup" ""
1461 test -d "$dir" || return 0
1463 if test -r "$dir"/name; then
1464 read name < "$dir"/name
1466 name="$VSERVER_NAME"
1469 if test "$action" = "attach"; then
1470 if mkdir "$CGROUP_MNT/$name" 2>/dev/null; then
1471 parent="$CGROUP_MNT/$name"
1472 parent="${parent%/*}"
1473 for i in "${CGROUP_INHERIT[@]}"; do
1474 test -f "$parent/$i" || continue
1475 cat "$parent/$i" > "$CGROUP_MNT/$name/$i"
1479 for i in "$dir"/*; do
1480 cat "$i" > "$CGROUP_MNT/$name/${i##*/}"
1483 echo "$$" > "$CGROUP_MNT/$name/tasks"
1484 elif test "$action" = "destroy"; then
1485 rmdir "$CGROUP_MNT/$name" 2>/dev/null || :
1491 function attachToCgroup
1493 _handleCgroup attach "$@"
1496 function destroyCgroup
1498 _handleCgroup destroy "$@"