Don't check the VLAN stuff if novlandev was specified.
[util-vserver.git] / scripts / vserver.functions
index 7a9b6a8..3139ac6 100644 (file)
@@ -42,6 +42,7 @@ 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 STOPCMD_PREPARE=()
 
@@ -72,6 +73,22 @@ 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"
@@ -86,24 +103,28 @@ function _generateChbindOptions
 
     getFileValue nid "$vdir/ncontext" "$vdir/context"
     
-    CHBIND_OPTS=( $SILENT_OPT ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
+    CHBIND_OPTS=( $SILENT_OPT --secure ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
 
     for i in "${INTERFACES[@]}"; do
        CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
     done
 
+    _readFileToArray "$vdir"/nflags        CHBIND_OPTS --flag
+    _readFileToArray "$vdir"/ncapabilities CHBIND_OPTS --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 +158,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 +250,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)
@@ -292,7 +301,27 @@ function _generateInitOptions
            ;;
 
        (xgentoo)
-           panic "init-style '$INITSTYLE' is no longer supported; please use plain instead; aborting";;
+           test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
+
+           INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
+           INITCMD_STOP=( /sbin/rc shutdown )
+           INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
+
+           pushd "$vdir"/vdir &>/dev/null
+           basever=$($_CHROOT_SH cat /etc/gentoo-release | $_AWK '{print $5}')
+           popd &>/dev/null
+
+           basemaj=${basever/.*}
+           basemin=${basever#*.}
+           basemin=${basemin/.*}
+
+           test "$basemaj" -lt 1 -o "$basemin" -lt 13 && \
+           panic "\
+Using init-style 'gentoo' requires >=baselayout-1.13 inside the vserver!
+
+Your vserver ($(basename "$vdir")) seems to have baselayout-$basever,
+please use 'plain' init-style instead!"
+           ;;
 
        (x) ;;
        (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
@@ -383,6 +412,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
 
@@ -520,16 +554,20 @@ 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"
@@ -688,6 +726,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"
@@ -741,13 +827,13 @@ 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[@]}"
 
+    isNamespaceCleanup "$cfgdir" && \
+        _namespaceCleanup "$cfgdir"
+
     isAvoidNamespace "$cfgdir" || \
        $_SECURE_MOUNT --rbind -n "$vdir" "/"
 }
@@ -986,7 +1072,7 @@ 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"
 }
 
 
@@ -1099,3 +1185,42 @@ 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 tmp
+
+    getFileArray skip "$vdir"/namespace-cleanup-skip \
+       "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
+
+    # these are things that have to be accessible post-cleanup
+    for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
+       "$__PKGSTATEDIR" "${skip[@]}"; do
+       while test -n "$tmp"; do
+           list=( "${list[@]}" "$tmp" )
+           tmp="${tmp%/*}"
+       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
+}
+