1 # $Id: vserver.functions 2831 2009-03-18 19:26:51Z dhozac $ --*- sh -*--
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 OPT_VCONTEXT_CHROOT=--chroot
45 declare -a OPTS_VATTRIBUTE=( --flag fakeinit )
46 declare -a OPTS_VSCHED=()
47 declare -a OPTS_ENV=()
48 declare -a OPTS_VTAG_CREATE=()
49 declare -a OPTS_VTAG_ENTER=()
50 declare -a OPTS_VMEMCTRL=()
51 declare -a OPTS_VSPACE=( --default )
53 declare -a STOPCMD_PREPARE=()
55 declare -a VSERVER_EXTRA_CMDS=()
58 VSHELPER_SYNC_TIMEOUT=30
63 _HAVE_INTERFACE_OPTIONS=
75 CGROUP_MNT=/dev/cgroup
77 declare -a CGROUP_INHERIT=( cpuset.cpus cpuset.mems )
79 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
81 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
87 function _readFileToArray
94 test -e "$_rfta_f" || return 0
95 while read _rfta_v; do
98 (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
103 function _generateChbindOptions
111 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
113 local f="$vdir"/interfaces/bcast
114 getFileValue bcast "$f"
115 f="$vdir"/interfaces/lback
116 getFileValue lback "$f"
118 CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${N_CONTEXT:+--nid "$N_CONTEXT"}
119 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
122 for i in "${INTERFACES[@]}"; do
123 CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
126 _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
127 _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
129 _HAVE_CHBIND_OPTIONS=1
132 function _generateNiceCommand
136 local current_nice=`$_NICE`
138 test -r "$vdir/nice" && read nice <"$vdir"/nice
140 let nice=$nice-$current_nice || :
141 NICE_CMD=( $_NICE -n $nice )
144 function _generateIONiceCommand
148 local ionice_priority=0
150 test -n "$_IONICE" || return 0
152 test -r "$vdir/ionice/class" && read ionice_class <"$vdir"/ionice/class
153 test -r "$vdir/ionice/priority" && read ionice_priority <"$vdir"/ionice/priority
155 IONICE_CMD=( $_IONICE -c$ionice_class -n$ionice_priority )
158 function _generatePersonalityOptions
161 local f="$vdir"/personality
164 test -s "$f" || return 0
173 (*) flags=$flags$delim$tmp
180 OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}"
181 --personality-type "$type"
182 ${flags:+--personality-flags "$flags"} )
185 function _generateCCapabilityOptions
189 _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
192 function _generateBCapabilityOptions
196 _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
199 function _generateCapabilityOptions
204 _generateBCapabilityOptions "$vdir"
205 _generateCCapabilityOptions "$vdir"
207 test -e "$vdir"/capabilities || return 0
216 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
217 CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
220 CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
223 done <"$vdir"/capabilities
226 function getEnterShell
233 getFileValue ENTER_SHELL "$vdir"/shell "$__CONFDIR"/.defaults/shell
235 test -n "$ENTER_SHELL" || {
237 for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
239 test -x "$vdir/vdir/$1" || continue
246 ## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
247 function sendKillSequence
253 while isCtxRunning "$ctx"; do
254 test -z "$wait" || sleep "$wait"
256 killContext "$ctx" "$1"
257 test -n "$2" || break
263 function _generateInitOptions
266 local cfgdir=$vdir/apps/init
271 INITCMD_START_SYNC=()
276 INITKILL_SEQ=( 15 5 9 )
277 CHCONTEXT_INIT_OPTS=()
280 test x"$INITSTYLE" = xrescue || \
281 getFileValue INITSTYLE "$cfgdir"/style
282 getFileValue RUNLEVEL_START "$cfgdir"/runlevel
283 getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
284 getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
285 getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
287 findFile _gio_env "$cfgdir"/environment \
288 "$__CONFDIR"/.defaults/apps/init/environment \
289 "$__PKGLIBDEFAULTDIR"/environment
290 getFileArray OPTS_ENV "$_gio_env" || :
292 case x"$INITSTYLE" in
294 INITCMD_START=( "${INITCMD_RESCUE[@]}" )
295 INITCMD_STOP=( /sbin/killall5 )
299 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
300 test -n "$RUNLEVEL_STOP" || RUNLEVEL_STOP=6
302 for i in /etc/init.d/rc /etc/rc.d/rc; do
303 test -x "$vdir/vdir/$i" || continue
304 INITCMD_START=( "$i" "$RUNLEVEL_START" )
305 INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
307 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
308 OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
309 if test -n "$OPTION_DEBUG_SYSV"; then
310 INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
311 INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
316 INITCMD_START=( /sbin/init )
317 INITCMD_STOP=( /sbin/init )
319 _NEED_VSHELPER_SYNC=1
320 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
321 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
325 INITCMD_START=( /sbin/minit-start )
326 INITCMD_STOP=( /sbin/minit-stop )
328 INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
329 _NEED_VSHELPER_SYNC=1
330 test -z "$RUNLEVEL_START" || INITCMD_START=( "${INITCMD_START[@]}" "$RUNLEVEL_START" )
331 test -z "$RUNLEVEL_STOP" || INITCMD_STOP=( "${INITCMD_STOP[@]}" "$RUNLEVEL_STOP" )
332 ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp )
336 test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
337 RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
339 if test -x "$vdir/vdir/lib/rcscripts/sh/init-vserver.sh"; then
340 RC_WRAP=/lib/rcscripts/sh/init-vserver.sh
341 elif test -x "$vdir/vdir/lib/rc/sh/init-vserver.sh"; then
342 RC_WRAP=/lib/rc/sh/init-vserver.sh
344 panic "init-vserver.sh not found; aborting"
347 INITCMD_START=( env TERM=$TERM $RC_WRAP "$RUNLEVEL_START" )
348 INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
349 INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
353 test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
354 INITCMD_START=( /etc/rc.multi )
355 INITCMD_STOP=( /etc/rc.shutdown )
356 INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
360 (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
363 if test x"$INITSTYLE" != xrescue; then
364 getFileArray INITCMD_START "$cfgdir"/cmd.start || :
365 getFileArray INITCMD_STOP "$cfgdir"/cmd.stop || :
366 getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync || :
367 getFileArray INITCMD_STOP_SYNC "$cfgdir"/cmd.stop-sync || :
368 getFileArray INITCMD_PREPARE "$cfgdir"/cmd.prepare || :
371 test -n "$OPTION_FORCE_SYNC" -o -e "$cfgdir"/sync || {
372 INITCMD_START_SYNC=()
377 if vshelper.isEnabled; then
378 vshelper.getSyncTimeout "$vdir" VSHELPER_SYNC_TIMEOUT || :
384 function _generateFlagOptions
389 CHCONTEXT_FLAG_OPTS=()
391 findFile file "$vdir"/cflags "$vdir"/flags ""
401 OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
402 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
408 isAvoidNamespace "$vdir" || {
410 CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
411 ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
412 OPT_VCONTEXT_CHROOT=--pivot-root
416 function _generateChcontextOptions
419 local ctx hostname domainname
424 read ctx <"$vdir"/context || :
426 read hostname <"$vdir"/uts/nodename || read hostname <"$vdir"/hostname || :
427 read domainname <"$vdir"/uts/domainname || read domainname <"$vdir"/domainname || :
430 test -z "$S_CONTEXT" || ctx=$S_CONTEXT
432 _generateCapabilityOptions "$vdir"
433 _generateFlagOptions "$vdir"
435 CHCONTEXT_OPTS=( $SILENT_OPT \
436 "${CHCONTEXT_FLAG_OPTS[@]}" \
439 ${ctx:+--ctx "$ctx"} \
440 ${hostname:+--hostname "$hostname"} \
441 ${domainname:+--domainname "$domainname"} )
443 OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
444 ${ctx:+--xid "$ctx"} )
445 ## put '--secure' at front so that it can be overridden
446 OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" )
449 function _generateScheduleOptions
452 if test -d "$vdir"/sched; then
453 OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
457 local f="$vdir"/schedule
458 test -e "$f" || return 0
460 local fill_rate interval tokens tokens_min tokens_max prio_bias
468 read prio_bias || prio_bias=
472 test -n "$prio_bias" || {
473 echo $"Bad content in '$f'; aborting..." >&2
477 OPTS_VSCHED=( --fill-rate "$fill_rate" --interval "$interval" \
478 --tokens "$tokens" --tokens_min "$tokens_min" \
479 --tokens_max "$tokens_max" --priority-bias "$prio_bias" )
482 function _getInterfaceValue
492 read _giv_tmp <"$_giv_i/$_giv_val" && break || :
495 : ${_giv_tmp:=$_giv_dflt}
496 eval $_giv_val=\$_giv_tmp
499 ## Usage: _transformMask2Prefix <result-varname> <prefix> <mask>
500 function _transformMask2Prefix
504 test -n "$_tm2p_tmp" || {
505 $_MASK2PREFIX "$3" || _tm2p_tmp=$?
512 function _addInterfaceCmd
514 eval INTERFACE_CMDS_${INTERFACE_CMDS_IDX}='( "$@" )'
515 let ++INTERFACE_CMDS_IDX
518 ## Usage: _generateMac <var> <iface> <ctx>
519 function _generateMac
522 echo $"Interface basename '$iface' must be either a number, or the mac must be configured explicitly" >&2
526 eval $1=$(printf "f0:ff:%02x:%02x:%02x:%02x" $[ (~($2>>8)) & 0xff ] $[ ($2 & 0xff) ] $[ ($3>>8) & 0xff ] $[ $3 & 0xff ])
529 function _getVLANInfo
534 creation of VLAN_PLUS_VID devices is not supported; please create them
535 before starting the vserver and use the 'nodev' flag then"
536 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID"
540 creation of VLAN_PLUS_VID_NO_PAD devices is not supported; please
541 create them before starting the vserver and use the 'nodev' flag then"
542 echo "$1 vlan ${1##vlan} VLAN_PLUS_VID_N0_PAD"
544 (*.????) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID";;
545 (*.*) echo "$1 ${1%%.*} ${1##*.} DEV_PLUS_VID_NO_PAD";;
556 test -e "$iface/tun" -o -e "$iface/tap" || return 1
557 test ! -e "$iface/tun" || echo --tun
558 test ! -e "$iface/tap" || echo --tap
559 test ! -e "$iface/nocsum" || echo --~checksum
560 test -e "$iface/shared" || echo --nid-failure-ok "$N_CONTEXT"
561 if test -e "$iface/uid"; then
563 getFileValue uid "$iface/uid"
566 if test -e "$iface/gid"; then
568 getFileValue gid "$iface/gid"
571 if test -e "$iface/linktype"; then
573 getFileValue linktype "$iface/linktype"
574 echo --linktype "$linktype"
579 ## Usage: _processSingleInterface <interface-directory>
580 function _processSingleInterface
596 _getInterfaceValue ip '' "$iface"
597 _getInterfaceValue extip '' "$iface" "$iface/.."
598 _getInterfaceValue dev '' "$iface" "$iface/.."
599 _getInterfaceValue prefix '' "$iface" "$iface/.."
600 _getInterfaceValue mask '' "$iface" "$iface/.."
601 _getInterfaceValue bcast '' "$iface" "$iface/.."
602 _getInterfaceValue name '' "$iface"
603 _getInterfaceValue scope '' "$iface" "$iface/.."
604 _getInterfaceValue mac '' "$iface"
605 _getInterfaceValue peer '' "$iface"
607 test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
608 test -n "$dev" -o -e "$iface"/nodev || {
609 echo $"No device specified for '$iface'" >&2
613 test ! -e "$iface"/down || up=
616 _transformMask2Prefix prefix "$prefix" "$mask"
617 INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" )
619 test ! -e "$iface"/nodev || break
621 test ! -e "$iface"/only_ip || break
623 test -e "$iface/vlandev" \
624 -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
625 -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
626 -a ! -e "$iface/novlandev" \
627 -a ! -e "$iface/../novlandev" \) && {
629 if vlan_info=$(_getVLANInfo "$dev"); then
630 test -d /proc/net/vlan || {
631 echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
634 _addInterfaceCmd VCONFIG $vlan_info
638 if ! test -e "$iface"/indirect; then
640 local use_bcast="broadcast ${bcast:-+}"
641 echo "$ip" | $_GREP -q : && use_bcast=
644 if tun_info=$(_getTunInfo "$iface"); then
645 _addInterfaceCmd TUNCTL "$dev" $tun_info
648 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev" ${peer:+peer "$peer"}
649 #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
650 _addInterfaceCmd IP_LINK "$dev" $up
651 elif ! test -n "$N_CONTEXT"; then
652 echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
655 test -z "$mac" || _generateMac mac "$(basename $iface)" "$N_CONTEXT" || return 1
656 _addInterfaceCmd MODPROBE dummy "$dev"
657 _addInterfaceCmd IP_LINK dev dummy0 address "$mac"
658 _addInterfaceCmd NAMEIF "$dev" "$mac"
659 _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
660 test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$N_CONTEXT" "$extip"
667 ## Usage: _generateInterfaceOptions <vserver-directory>
668 function _generateInterfaceOptions
672 # XXX: This is here instead of in _generateChbindOptions
673 # to avoid a circular dependency
674 getFileValue N_CONTEXT "$1/ncontext" "$1/context"
675 test -n "$N_CONTEXT" -o -z "$S_CONTEXT" || N_CONTEXT="$S_CONTEXT"
677 for iface in "$1/interfaces/"*; do
678 test -d "$iface" || continue
679 test ! -e "$iface"/disabled || continue
681 _processSingleInterface "$iface"
683 _HAVE_INTERFACE_OPTIONS=1
686 function enableInterfaces
691 lock "$__LOCKDIR"/vserver.interfaces
693 while test $i -lt $INTERFACE_CMDS_IDX; do
694 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
705 $_MODPROBE ${name:+-o "$name"} "$mod" "$@"
707 NAMEIF) $_NAMEIF "$@";;
708 VCONFIG) $_VCONFIG set_name_type "$4" >/dev/null
709 $_VCONFIG add "$2" "$3" >/dev/null;;
710 IP_ADDR) $_IP addr add "$@";;
711 IP_ADDR_FLUSH) $_IP addr flush "$@";;
712 IP_LINK) $_IP link set "$@";;
713 IP_ROUTE) $_IP route add "$@";;
717 $_TUNCTL --persist "$@" "$dev"
719 *) echo "Unknown interface-command type '$type'" >&2; false;;
728 function disableInterfaces
730 test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
732 local i=$INTERFACE_CMDS_IDX
735 lock "$__LOCKDIR"/vserver.interfaces
737 while test $i -gt 0; do
740 eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
747 MODPROBE) $_RMMOD "${2:-$1}";;
749 VCONFIG) $_VCONFIG rem "$2.$3" >/dev/null;;
750 IP_ADDR) $_IP addr del "$@";;
752 IP_LINK) ;; ## Ignore the link-down command for now
753 IP_ROUTE) $_IP route del "$@";;
754 TUNCTL) $_TUNCTL --~persist "$1";;
755 *) echo "Unknown interface-command type '$type'" >&2; false;;
762 function _generateTagOptions
767 getFileValue tag "$vdir/tag" "$vdir/context"
768 test -n "$tag" || return 0
770 OPTS_VTAG_CREATE=( --tag "$tag" )
771 OPTS_VTAG_ENTER=( --tag "$tag" )
774 function _generateMemctrlOptions
779 getFileValue badness "$vdir/badness"
780 test -n "$badness" || return 0
782 OPTS_VMEMCTRL=( --badness "$badness" )
785 function _generateSpaceOptions
788 local d="$vdir"/spaces
790 ( test ! -e "$d"/pid ) || \
791 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
793 test ! -e "$d"/net || {
794 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
795 # network context and namespace don't make much sense
796 _HAVE_CHBIND_OPTIONS=1
801 getFileValue mask "$d"/mask || \
802 OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
805 ## Usage: prepareInit <vserver-directory>
808 pushd "$1/vdir" >/dev/null
811 { find var/run ! -type d -print0; \
812 find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
815 $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
816 : | $_CHROOT_SH truncate fastboot 2>/dev/null || :
821 "${INITCMD_PREPARE[@]}"
825 ## Usage: prepareInit <vserver-directory>
828 pushd "$1/vdir" >/dev/null
831 export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
834 "${STOPCMD_PREPARE[@]}"
839 function generateOptions
841 _generateInterfaceOptions "$1"
842 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
843 _generateNiceCommand "$1"
844 _generateIONiceCommand "$1"
845 _generateInitOptions "$1"
846 _generateChcontextOptions "$1"
847 _generateScheduleOptions "$1"
848 _generatePersonalityOptions "$1"
849 _generateTagOptions "$1"
850 _generateMemctrlOptions "$1"
851 _generateSpaceOptions "$1"
852 _generateCgroupOptions
854 if test -n "$_IS_FAKEINIT"; then
855 CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
856 OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --initpid --disconnect )
864 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 test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
874 for i in cpus mems cpu_exclusive mem_exclusive virtualized; do
875 if test -e "$f"/"$i"; then
876 cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
884 echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
885 if [ "$configured" -ne 0 ]; then
887 WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
888 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
893 function removeCPUSET
897 local f="$vdir"/cpuset
899 test -d "$f" || return 0
900 test -e "$f"/name || return 0
902 read cpuset < "$f"/name
903 test -e "$f"/nocreate || {
904 rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
908 function _mountVserverInternal
913 test -e "$fstab" || return 0
916 pushd "$vdir" >/dev/null
917 # check whether / is mounted readonly or whether there is special
918 # magic regarding the mtab file; when etc/mtab can not be touched,
919 # add the '-n' flag to mount
920 test -w etc -o -w etc/mtab || xflag=-n
921 "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
929 local fstab="$cfgdir"/fstab
932 test -e "$fstab" || return 0
933 pushd "$vdir" >/dev/null
934 # check whether / is mounted readonly or whether there is special
935 # magic regarding the mtab file; when etc/mtab can not be touched,
936 # add the '-n' flag to mount
937 test -w etc -o -w etc/mtab || xflag=-n
938 $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs only -n
942 function mountVserver
951 test -e "$cfgdir"/fstab -o \
952 -e "$cfgdir"/fstab.local -o \
953 -e "$cfgdir"/fstab.remote || return 0
955 findObject -r mtab_src "$cfgdir"/apps/init/mtab "$__CONFDIR"/.defaults/init/mtab "$__PKGLIBDEFAULTDIR"/mtab /dev/null
957 pushd "$vdir" >/dev/null
958 $_CHROOT_SH truncate /etc/mtab <"$mtab_src"
961 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
963 _mountVserverInternal "$cfgdir"/fstab
964 _mountVserverInternal "$cfgdir"/fstab.local
965 _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
967 isNamespaceCleanup "$cfgdir" && \
968 _namespaceCleanup "$cfgdir"
970 real_vdir=$(getPhysicalDir "$vdir")
971 isAvoidNamespace "$cfgdir" || \
972 $_SECURE_MOUNT --rbind -n -o dev "$vdir" "$real_vdir"
973 ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
974 $_SECURE_MOUNT -n -o shared,rec "$real_vdir" "$real_vdir"
977 function _umountVserverInternal
980 test -e "$fstab" || return 0
985 while read src dst tmp; do
986 test -n "$tmp" || continue
992 "$@" $_EXEC_CD "$dst" $_UMOUNT -lfn . || is_ok=
998 function umountVserver
1004 isAvoidNamespace "$cfgdir" || return 0
1005 test -e "$cfgdir"/fstab -o \
1006 -e "$cfgdir"/fstab.local -o \
1007 -e "$cfgdir"/fstab.remote || return 0
1008 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
1010 pushd "$vdir/" >/dev/null || return 1
1011 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
1012 _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
1013 _umountVserverInternal "$cfgdir"/fstab || is_ok=
1014 popd >/dev/null || return 1
1022 local fstab="$cfgdir"/fstab
1026 test -e "$fstab" || return 0
1028 export FSTAB_FILE="$fstab"
1031 test "$fsck_exitcode" -eq 0 -o \
1032 "$fsck_exitcode" -eq 1 || return $fsck_exitcode
1035 ## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
1039 test -n "$_NEED_VSHELPER_SYNC" && \
1040 ! $_VSERVER_INFO - FEATURE vwait || _is_meth=async
1042 vshelper.initSync "$1" "$3" "$_is_meth"
1045 ## Usage: initWait <vserver> <context> <vwait-tmpdir-varname>
1048 if $_VSERVER_INFO - FEATURE vwait; then
1050 _is_tmpdir=$($_MKTEMPDIR vwaitstat.XXXXXX)
1053 $_VWAIT --timeout "$VSHELPER_SYNC_TIMEOUT" \
1054 --status-fd 3 "$2" \
1055 >>$_is_tmpdir/out 2>$_is_tmpdir/err 3>$_is_tmpdir/fifo
1058 if test "$rc" -ne 0 -a "$rc" -ne 1; then
1059 $_VPS axf | $_EGREP -e "^[ \t]*[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
1060 killContext "$S_CONTEXT" 9
1064 ) 4>$_is_tmpdir/procs &
1066 echo "$!" >$_is_tmpdir/pid
1067 eval "$3"=$_is_tmpdir
1072 ## Usage: _waitForVWait <vserver> <fifo> <pid> <procs>
1073 function _waitForVWait
1078 declare -r procs=$(cat $4)
1080 getFileArray status "$2"
1085 'vwait' exited with error '$2' which indicates that vserver could not
1086 be stopped properly"
1089 (KILLED) warning $"\
1090 A timeout occured while waiting for the vserver to finish and it was
1091 killed by sending a SIGKILL signal. Please investigate the reasons
1092 and/or increase the timeout in apps/vshelper/sync-timeout."
1095 (TIMEOUT) warning $"\
1096 A timeout occured while waiting for the vserver to finish and it will
1097 be killed by sending a SIGKILL signal. The following process list
1098 might be useful for finding out the reason of this behavior:
1100 ----------------------------------------------------------------------
1102 }----------------------------------------------------------------------"
1105 (\?\?\?|*) warning $"\
1106 internal error: 'vwait' exited with an unexpected status '$1'; I will
1107 try to continue but be prepared for unexpected events."
1114 ## Usage: waitForSync <vserver> [<vshelper-fifo>] [<vwait-statdir>]
1115 function waitForSync
1119 local vwait_statdir=$3
1122 if test -d "$vwait_statdir"; then
1123 _waitForVWait "$cfgdir" "$vwait_statdir/fifo" "$( <$vwait_statdir/pid )" "$vwait_statdir/procs"
1124 elif test -n "$_NEED_VSHELPER_SYNC"; then
1125 $_VSHELPER_SYNC "$fifo" "$VSHELPER_SYNC_TIMEOUT" || \
1127 A timeout or other error occured while waiting for the synchronization
1128 signal from vserver '$VSERVER_NAME'.
1129 The vserver will be killed nevertheless..."
1130 elif test "${#INITCMD_STOP_SYNC[@]}" -ne 0; then
1131 "${INITCMD_STOP_SYNC[@]}" || \
1133 Stop-synchronization for vserver '$VSERVER_NAME' failed. The vserver
1134 will be killed nevertheless..."
1137 test -z "$OPTION_FORCE_SYNC" -a ! -e "$cfgdir"/sync ||
1141 function _sourceWrap
1143 local vdir name flavor start i already_handled base
1147 ## Usage: execScriptlets <vserver-cfgdir> <vserver-name> <script-flavor>
1148 function execScriptlets
1152 declare -r flavor=$3
1155 for base in "$vdir"/scripts "$__CONFDIR"/.defaults/scripts; do
1156 local DONT_SKIP_DEFAULTS=
1157 local already_handled=
1159 for i in "$base/$flavor" "$base/$flavor.d"/*; do
1160 isRegularFile "$i" || continue
1161 test -r "$i" || continue
1165 test -x "$i" || start=_sourceWrap
1166 $start "$i" "$flavor" "$name"
1169 test -z "$already_handled" -o -n "$DONT_SKIP_DEFAULTS" || break
1174 function sanityCheck
1176 declare -r cfgdir=$1
1178 ! test -e "$cfgdir"/fstab.local ||
1180 WARNING: 'fstab' will *not* be executed in the network context of the
1181 vserver anymore. Therefore, 'fstab.local' has the same functionality
1182 and is obsoleted. When you need the old behaviour, put the mounts
1183 into 'fstab.remote'"
1185 ! test -e "$cfgdir"/hostname -a ! -L "$cfgdir"/hostname ||
1187 WARNING: The hostname is now configured in 'uts/nodename' but not in
1190 ! test -e "$cfgdir"/domainname -a ! -L "$cfgdir"/domainname ||
1192 WARNING: The domainname is now configured in 'uts/domainname' but not
1193 in 'domainname'." >&2
1197 for i in "$cfgdir"/interfaces/*/only_ip; do
1198 if test -e "$i"; then
1200 iface=${i##$cfgdir/interfaces/}
1201 iface=${iface%%/only_ip}
1203 WARNING: The 'only_ip' flag for interface '$iface' is deprecated; use
1208 test ! -d "$cfgdir"/dlimits -o -L "$cfgdir/cache" || \
1210 WARNING: There is no cachedirectory configured for this vserver;
1211 please create '$cfgdir/cache' e.g. by executing
1213 ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
1216 find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
1218 vshelper.doSanityCheck
1220 $_VSERVER_INFO - VERIFYCAP ||
1221 panic $"capabilities are not enabled in kernel-setup"
1223 $_VSERVER_INFO - VERIFYPROC ||
1225 /proc/uptime can not be accessed. Usually, this is caused by
1226 procfs-security. Please read the FAQ for more details
1227 http://linux-vserver.org/Proc-Security"
1229 test -e "$cfgdir"/context || {
1230 TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
1231 test "$TYPE" != "static" || panic $"\
1232 The kernel does not have dynamic contexts enabled. Please configure
1233 a static one by executing
1235 echo [number between 2 and 49151] > $cfgdir/context"
1240 function _setSingleDiskLimit
1252 getFileValue ctx "$vdir/context"
1253 getFileValue directory "$dlimit/directory" || return 0
1254 getFileValue space_total "$dlimit/space_total" || return 0
1255 getFileValue inodes_total "$dlimit/inodes_total" || return 0
1256 getFileValue reserved "$dlimit/reserved" || return 0
1258 local cachename=$ctx$directory
1259 cachename=dlimits/${cachename//\//_}
1261 test -e "$vdir/cache/$cachename" && . "$vdir/cache/$cachename"
1262 # Remove the cache so if the machine goes down unexpectedly, we won't have a stale cache
1263 $_RM -f "$vdir/cache/$cachename"
1265 if test -z "$inodes_used" -o -z "$space_used"; then
1267 tmpvdu=`$_VDU --xid $ctx --space --inodes --script "$directory"`
1268 inodes_used=${tmpvdu##* }
1269 space_used=${tmpvdu%% *}
1272 $_VDLIMIT --xid $ctx \
1273 --set space_used=$space_used \
1274 --set space_total=$space_total \
1275 --set inodes_used=$inodes_used \
1276 --set inodes_total=$inodes_total \
1277 --set reserved=$reserved \
1282 function setDiskLimits
1287 # Disk Limits without a static context are useless
1288 test -e "$vdir"/context || return 0
1290 for dlimit in "$vdir/dlimits/"*; do
1291 test -d "$dlimit" || continue
1292 test ! -e "$dlimit/disabled" || continue
1294 _setSingleDiskLimit "$vdir" "$dlimit"
1299 function _saveSingleDiskLimit
1306 getFileValue ctx "$vdir/context"
1307 getFileValue directory "$dlimit/directory" || return 0
1309 local cachename=$ctx$directory
1310 cachename=${cachename//\//_}
1312 # Things are getting ugly here... LFS says that /var/cache (where
1313 # cachename is usually pointing to) can vanish and applications
1314 # have to deal with it. So, we have to interprete the $vdir/cache
1315 # symlink and have to create the needed directories manually.
1316 if test -d "$vdir/cache"; then
1317 : # ok, exists already
1318 elif test -L "$vdir/cache"; then
1319 # it's a dangling symlink
1321 link=$($_READLINK "$vdir/cache")
1322 ( cd $vdir && $_MKDIR -p "$link" )
1327 test -d "$vdir/cache"
1328 $_MKDIR -p "$vdir"/cache/dlimits
1330 $_VDLIMIT --xid $ctx "$directory" | \
1331 $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
1333 $_VDLIMIT --xid $ctx --remove "$directory"
1337 function saveDiskLimits
1342 test -e "$vdir"/context || return 0
1344 for dlimit in "$vdir/dlimits/"*; do
1345 test -d "$dlimit" || continue
1346 test ! -e "$dlimit/disabled" || continue
1348 _saveSingleDiskLimit "$vdir" "$dlimit"
1352 function _namespaceCleanup
1355 local root=$($_VSERVER_INFO "$1" VDIR 1)
1361 getFileArray skip "$vdir"/namespace-cleanup-skip \
1362 "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
1364 # these are things that have to be accessible post-cleanup
1365 for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
1366 "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
1367 local real=`getPhysicalDir "$i"`
1368 test "$i" != "$real" || real=
1369 for j in "$i" "$real"; do
1370 while test -n "$j"; do
1371 list=( "${list[@]}" "$j" )
1377 local -a list_umount
1378 while read -r dev path opts; do
1379 test -n "$path" || continue
1380 for i in "$root" /dev /proc; do
1381 test "${path#$i}" != "$path" && continue 2
1383 for i in "${list[@]}" /; do
1384 test "$path" = "$i" && continue 2
1386 # unmount them in reverse order so mounts further down the tree get unmounted first
1387 list_umount=( "$path" "${list_umount[@]}" )
1389 # separate loop to avoid races while reading /proc/mounts
1390 for i in "${list_umount[@]}"; do
1391 $_UMOUNT -l -n -i "$i"
1395 function handleDeviceMap
1400 local flags device target
1402 test -d "$dir" || return 0
1403 test -n "$xid" || return 0
1405 for i in "$dir"/*; do
1406 test -d "$i" || continue
1408 local -a vdevmap_opts=()
1409 test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
1410 test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
1411 test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
1413 getFileValue flags "$i/flags" || :
1414 getFileValue device "$i/device" || :
1415 getFileValue target "$i/target" || :
1416 vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
1417 ${device:+--device "$device"} ${target:+--target "$target"} )
1419 $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?
1425 $_GREP -q "cgroup" /proc/filesystems
1428 function _generateCgroupOptions
1432 hasCgroup || return 0
1434 findFile file "$__CONFDIR/.defaults/cgroup/mnt" ""
1435 if test -n "$file"; then
1436 read CGROUP_MNT < "$file"
1438 findFile file "$__CONFDIR/.defaults/cgroup/subsys" ""
1439 if test -n "$file"; then
1440 read CGROUP_SUBSYS < "$file"
1442 findFile file "$__CONFDIR/.defaults/cgroup/inherit" ""
1443 if test -n "$file"; then
1444 _readFileToArray CGROUP_INHERIT "$file" ""
1452 hasCgroup || return 1
1453 test -d "$CGROUP_MNT" || return 1
1454 test -d "$1/cgroup" -o \
1455 \( -d "$__CONFDIR/.defaults/cgroup" -a \
1456 ! -e "$1/nocgroup" \)
1459 function _handleCgroup
1468 useCgroup "$vdir" || return 0
1470 findDir dir "$vdir/cgroup" "$__CONFDIR/.defaults/cgroup" ""
1471 test -d "$dir" || return 0
1473 if test -r "$dir"/name; then
1474 read name < "$dir"/name
1476 name="$VSERVER_NAME"
1479 if test "$action" = "attach"; then
1480 if mkdir "$CGROUP_MNT/$name" 2>/dev/null; then
1481 parent="$CGROUP_MNT/$name"
1482 parent="${parent%/*}"
1483 for i in "${CGROUP_INHERIT[@]}"; do
1484 test -f "$parent/$i" || continue
1485 cat "$parent/$i" > "$CGROUP_MNT/$name/$i"
1489 for i in "$dir"/*; do
1490 cat "$i" > "$CGROUP_MNT/$name/${i##*/}"
1493 echo "$$" > "$CGROUP_MNT/$name/tasks"
1494 elif test "$action" = "destroy"; then
1495 rmdir "$CGROUP_MNT/$name" 2>/dev/null || :
1501 function attachToCgroup
1503 _handleCgroup attach "$@"
1506 function destroyCgroup
1508 _handleCgroup destroy "$@"