X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=scripts%2Fvserver.functions;h=0eab27e9d00193aa1a5980fd3af32d475b260f8e;hb=7751466c148d6f751c60b1b0f06b604840da13de;hp=09c6ee384d3e98cfe660729554e244fa3bfc6da9;hpb=9c78378bebc1a9f3d400f422df8ede9efea57dea;p=util-vserver.git diff --git a/scripts/vserver.functions b/scripts/vserver.functions index 09c6ee3..0eab27e 100644 --- a/scripts/vserver.functions +++ b/scripts/vserver.functions @@ -20,7 +20,7 @@ # $VSERVER_NAME ... name of vserver declare -a NICE_CMD=() -declare -a CHBIND_OPTS=() +declare -a CHBIND_CMD=() declare -a CAP_OPTS=() declare -a CHCONTEXT_INIT_OPTS=() declare -a CHCONTEXT_FLAG_OPTS=() @@ -42,6 +42,10 @@ declare -a OPTS_VCONTEXT_MIGRATE=() declare -a OPTS_VCONTEXT_ENTER=() declare -a OPTS_VATTRIBUTE=( --flag fakeinit ) declare -a OPTS_VSCHED=() +declare -a OPTS_ENV=() +declare -a OPTS_VTAG_CREATE=() +declare -a OPTS_VTAG_ENTER=() +declare -a OPTS_VMEMCTRL=() declare -a STOPCMD_PREPARE=() @@ -72,38 +76,63 @@ else SILENT_OPT='--silent' fi +function _readFileToArray +{ + local _rfta_f="$1" + local _rfta_a="$2" + local _rfta_p="$3" + local _rfta_v + + test -e "$_rfta_f" || return 0 + while read _rfta_v; do + case x"$_rfta_v" in + (x|x\#*) ;; + (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";; + esac + done <"$_rfta_f" +} + function _generateChbindOptions { local vdir="$1" local i local bcast= + local lback= local nid= test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir" - local f=$vdir/interfaces/bcast + local f="$vdir"/interfaces/bcast getFileValue bcast "$f" + f="$vdir"/interfaces/lback + getFileValue lback "$f" getFileValue nid "$vdir/ncontext" "$vdir/context" - CHBIND_OPTS=( $SILENT_OPT ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} ) + CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${nid:+--nid "$nid"} + ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"} + ) for i in "${INTERFACES[@]}"; do - CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" ) + CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" ) done + _readFileToArray "$vdir"/nflags CHBIND_CMD --flag + _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap + _HAVE_CHBIND_OPTIONS=1 } function _generateNiceCommand { local vdir=$1 - local nice + local nice=0 + local current_nice=`$_NICE` - test -r "$vdir/nice" || return 0; - read nice <"$vdir"/nice + test -r "$vdir/nice" && read nice <"$vdir"/nice - NICE_CMD=( $_NICE -$nice ) + let nice=$nice-$current_nice || : + NICE_CMD=( $_NICE -n $nice ) } @@ -137,31 +166,15 @@ function _generatePersonalityOptions function _generateCCapabilityOptions { local vdir=$1 - local cap - local f="$vdir"/ccapabilities - - test -e "$f" || return 0 - while read cap; do - case x"$cap" in - (x|x\#*) ;; - (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --ccap "$cap" );; - esac - done <"$f" + + _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap } function _generateBCapabilityOptions { local vdir=$1 - local cap - local f="$vdir"/bcapabilities - - test -e "$f" || return 0 - while read cap; do - case x"$cap" in - (x|x\#*) ;; - (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --bcap "$cap" );; - esac - done <"$f" + + _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap } function _generateCapabilityOptions @@ -245,18 +258,22 @@ function _generateInitOptions CHCONTEXT_INIT_OPTS=() - getFileValue INITSTYLE "$cfgdir"/style + test x"$INITSTYLE" = xrescue || \ + getFileValue INITSTYLE "$cfgdir"/style getFileValue RUNLEVEL_START "$cfgdir"/runlevel getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop getFileArray INITKILL_SEQ "$cfgdir"/killseq || : + findFile _gio_env "$cfgdir"/environment \ + "$__CONFDIR"/.defaults/apps/init/environment \ + "$__PKGLIBDEFAULTDIR"/environment + getFileArray OPTS_ENV "$_gio_env" || : + case x"$INITSTYLE" in (xrescue) INITCMD_START=( "${INITCMD_RESCUE[@]}" ) INITCMD_STOP=( /sbin/killall5 ) - _IS_FAKEINIT=1 - _NEED_VSHELPER_SYNC= ;; (xsysv) @@ -269,6 +286,11 @@ function _generateInitOptions INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" ) done INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp ) + OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" ) + if test -n "$OPTION_DEBUG_SYSV"; then + INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" ) + INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" ) + fi ;; (xplain) @@ -292,8 +314,11 @@ function _generateInitOptions ;; (xgentoo) - INITCMD_START=( /sbin/rc default ) - INITCMD_STOP=( /sbin/rc shutdown ) + test -n "$RUNLEVEL_START" || RUNLEVEL_START="default" + + INITCMD_START=( env TERM=$TERM /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" ) + INITCMD_STOP=( env -i TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown ) + INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp ) ;; (x) ;; @@ -385,6 +410,11 @@ function _generateChcontextOptions function _generateScheduleOptions { local vdir=$1 + if test -d "$vdir"/sched; then + OPTS_VSCHED=( --dir "$vdir"/sched --missingok ) + return 0 + fi + local f="$vdir"/schedule test -e "$f" || return 0 @@ -522,19 +552,26 @@ function _processSingleInterface ## LEGACY ALERT test ! -e "$iface"/only_ip || break - local vlan_info - if vlan_info=$(_getVLANInfo "$dev"); then - test -d /proc/net/vlan || { - echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2 - return 1 - } - test -f /proc/net/vlan -o -e "$iface"/novlandev || { + test -e "$iface/vlandev" \ + -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \ + -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \ + -a ! -e "$iface/novlandev" \ + -a ! -e "$iface/../novlandev" \) && { + local vlan_info + if vlan_info=$(_getVLANInfo "$dev"); then + test -d /proc/net/vlan || { + echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2 + return 1 + } _addInterfaceCmd VCONFIG $vlan_info - } - fi + fi + } if ! test -e "$iface"/indirect; then - _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev" + # XXX: IPv6 hack + use_bcast="broadcast ${bcast:-+}" + echo "$ip" | $_GREP -q : && use_bcast= + _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev" #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev" _addInterfaceCmd IP_LINK "$dev" $up elif ! test -n "$ctx"; then @@ -640,6 +677,29 @@ function disableInterfaces unlock 1 } +function _generateTagOptions +{ + local vdir="$1" + local tag + + getFileValue tag "$vdir/tag" "$vdir/context" + test -n "$tag" || return 0 + + OPTS_VTAG_CREATE=( --tag "$tag" ) + OPTS_VTAG_ENTER=( --tag "$tag" ) +} + +function _generateMemctrlOptions +{ + local vdir="$" + local badness + + getFileValue badness "$vdir/badness" + test -n "$badness" || return 0 + + OPTS_VMEMCTRL=( --badness "$badness" ) +} + ## Usage: prepareInit function prepareInit { @@ -666,7 +726,7 @@ function prepareStop pushd "$1/vdir" >/dev/null case "$INITSTYLE" in (sysv) - export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts + export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts ;; esac "${STOPCMD_PREPARE[@]}" @@ -683,6 +743,8 @@ function generateOptions _generateChcontextOptions "$1" _generateScheduleOptions "$1" _generatePersonalityOptions "$1" + _generateTagOptions "$1" + _generateMemctrlOptions "$1" if test -n "$_IS_FAKEINIT"; then CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit ) @@ -690,6 +752,54 @@ function generateOptions fi } +function addtoCPUSET +{ + local vdir=$1 + local cpuset + local f="$vdir"/cpuset + local i + local configured=0 + + test -d "$f" || return 0 + test -e "$f"/name || return 0 + + read cpuset < "$f"/name + test -e "$f"/nocreate || { + test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1 + for i in cpus mems cpu_exclusive mem_exclusive virtualized; do + if test -e "$f"/"$i"; then + cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || { + configured=1 + break + } + fi + done + } + + echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1 + if [ "$configured" -ne 0 ]; then + warning $"\ +WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2 + rmdir /dev/cpuset/"$cpuset" 2>/dev/null || : + return 0 + fi +} + +function removeCPUSET +{ + local vdir=$1 + local cpuset + local f="$vdir"/cpuset + + test -d "$f" || return 0 + test -e "$f"/name || return 0 + + read cpuset < "$f"/name + test -e "$f"/nocreate || { + rmdir /dev/cpuset/"$cpuset" 2>/dev/null || : + } +} + function _mountVserverInternal { local fstab="$1" @@ -743,12 +853,12 @@ function mountVserver test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir" - test -z "$NAMESPACE_CLEANUP" || isAvoidNamespace "$cfgdir" || \ - $_VNAMESPACE --cleanup - _mountVserverInternal "$cfgdir"/fstab _mountVserverInternal "$cfgdir"/fstab.local - _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" + _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" + + isNamespaceCleanup "$cfgdir" && \ + _namespaceCleanup "$cfgdir" isAvoidNamespace "$cfgdir" || \ $_SECURE_MOUNT --rbind -n "$vdir" "/" @@ -783,17 +893,35 @@ function umountVserver isAvoidNamespace "$cfgdir" || return 0 test -e "$cfgdir"/fstab -o \ - -e "$cfgdir"/fstab.local || return 0 + -e "$cfgdir"/fstab.local -o \ + -e "$cfgdir"/fstab.remote || return 0 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir" pushd "$vdir/" >/dev/null || return 1 - _umountVserverInternal "$cfgdir"/fstab.local || is_ok= - _umountVserverInternal "$cfgdir"/fstab $_CHBIND "${CHBIND_OPTS[@]}" || is_ok= + _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok= + _umountVserverInternal "$cfgdir"/fstab.local || is_ok= + _umountVserverInternal "$cfgdir"/fstab || is_ok= popd >/dev/null || return 1 test -n "$is_ok" } +function fsckAllFS +{ + local cfgdir=$1 + local fstab="$cfgdir"/fstab + local FSTAB_FILE + local fsck_exitcode + + test -e "$fstab" || return 0 + + export FSTAB_FILE="$fstab" + $_FSCK -s -n -A -T + fsck_exitcode=$? + test "$fsck_exitcode" -eq 0 -o \ + "$fsck_exitcode" -eq 1 || return $fsck_exitcode +} + ## Usage: waitForSync function initSync { @@ -986,7 +1114,16 @@ WARNING: There is no cachedirectory configured for this vserver; panic $"\ /proc/uptime can not be accessed. Usually, this is caused by procfs-security. Please read the FAQ for more details -http://www.linux-vserver.org/index.php?page=Linux-Vserver+FAQ" +http://linux-vserver.org/Proc-Security" + + test -e "$cfgdir"/context || { + TYPE=$( $_VSERVER_INFO 49152 XIDTYPE ) + test "$TYPE" != "static" || panic $"\ +The kernel does not have dynamic contexts enabled. Please configure +a static one by executing + + echo [number between 2 and 49151] > $cfgdir/context" + } } @@ -1082,6 +1219,8 @@ function _saveSingleDiskLimit $_VDLIMIT --xid $ctx "$directory" | \ $_GREP '_used=' > "$vdir/cache/dlimits/$cachename" + + $_VDLIMIT --xid $ctx --remove "$directory" } @@ -1099,3 +1238,72 @@ function saveDiskLimits _saveSingleDiskLimit "$vdir" "$dlimit" done } + +function _namespaceCleanup +{ + local vdir="$1" + local root=$($_VSERVER_INFO "$1" VDIR 1) + local -a list + local -a skip + local i + local j + + getFileArray skip "$vdir"/namespace-cleanup-skip \ + "$__CONFDIR"/.defaults/namespace-cleanup-skip || : + + # these are things that have to be accessible post-cleanup + for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \ + "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do + local real=`readlink -f "$i"` + test "$i" != "$real" || real= + for j in "$i" "$real"; do + while test -n "$j"; do + list=( "${list[@]}" "$j" ) + j="${j%/*}" + done + done + done + + local -a list_umount + while read dev path opts; do + test -n "$path" || continue + for i in "$root" /dev /proc; do + test "${path#$i}" != "$path" && continue 2 + done + for i in "${list[@]}" /; do + test "$path" = "$i" && continue 2 + done + # unmount them in reverse order so mounts further down the tree get unmounted first + list_umount=( "$path" "${list_umount[@]}" ) + done < /proc/mounts + # separate loop to avoid races while reading /proc/mounts + for i in "${list_umount[@]}"; do + $_UMOUNT -l -n "$i" + done +} + +function loadDeviceMap +{ + local xid="$1" + local dir="$2" + local flags device target + + test -d "$dir" || return 0 + + for i in "$dir"/*; do + test -d "$i" || continue + + local -a vdevmap_opts=() + test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create ) + test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open ) + test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap ) + + getFileValue flags "$i/flags" || : + getFileValue device "$i/device" || : + getFileValue target "$i/target" || : + vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \ + ${device:+--device "$device"} ${target:+--target "$target"} ) + + $_VDEVMAP --xid "$xid" --set "${vdevmap_opts[@]}" || return $? + done +}