ready for tagging
[util-vserver.git] / scripts / vserver.functions
index 18438fd..23bb531 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: vserver.functions 2418 2006-12-08 13:28:02Z dhozac $  --*- sh -*--
+# $Id: vserver.functions 2599 2007-08-26 21:30:50Z dhozac $  --*- sh -*--
 
 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
 #  
@@ -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=()
@@ -43,6 +43,8 @@ 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 STOPCMD_PREPARE=()
 
@@ -94,23 +96,28 @@ 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 --secure ${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_OPTS --flag
-    _readFileToArray "$vdir"/ncapabilities CHBIND_OPTS --ncap
+    _readFileToArray "$vdir"/nflags        CHBIND_CMD --flag
+    _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
 
     _HAVE_CHBIND_OPTIONS=1
 }
@@ -278,6 +285,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)
@@ -303,24 +315,9 @@ function _generateInitOptions
        (xgentoo)
            test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
 
-           INITCMD_START=( /lib/rcscripts/sh/init-vserver.sh "$RUNLEVEL_START" )
-           INITCMD_STOP=( /sbin/rc shutdown )
+           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 )
-
-           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) ;;
@@ -554,23 +551,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 -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" \) && {
+       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
@@ -606,6 +606,17 @@ function _generateInterfaceOptions
     _HAVE_INTERFACE_OPTIONS=1
 }
 
+function _generateTagOptions
+{
+    local vdir="$1"
+    local tag
+
+    getFileValue tag "$vdir/tag" "$vdir/context" || return 0
+
+    OPTS_VTAG_CREATE=( --tag "$tag" )
+    OPTS_VTAG_ENTER=( --tag "$tag" )
+}
+
 function enableInterfaces
 {
     local i=0
@@ -702,7 +713,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[@]}"
@@ -719,6 +730,7 @@ function generateOptions
     _generateChcontextOptions   "$1"
     _generateScheduleOptions    "$1"
     _generatePersonalityOptions "$1"
+    _generateTagOptions         "$1"
 
     if test -n "$_IS_FAKEINIT"; then
        CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
@@ -829,7 +841,7 @@ function mountVserver
 
     _mountVserverInternal "$cfgdir"/fstab
     _mountVserverInternal "$cfgdir"/fstab.local
-    _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
+    _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
 
     isNamespaceCleanup "$cfgdir" && \
         _namespaceCleanup "$cfgdir"
@@ -872,9 +884,9 @@ function umountVserver
     test -n "$_HAVE_CHBIND_OPTIONS"  || _generateChbindOptions "$cfgdir"
     
     pushd "$vdir/" >/dev/null || return 1
-       _umountVserverInternal  "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
-       _umountVserverInternal  "$cfgdir"/fstab.local                               || is_ok=
-       _umountVserverInternal  "$cfgdir"/fstab                                     || 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"
@@ -1073,6 +1085,15 @@ WARNING: There is no cachedirectory configured for this vserver;
 /proc/uptime can not be accessed. Usually, this is caused by
 procfs-security. Please read the FAQ for more details
 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"
+    }
 }
 
 
@@ -1168,6 +1189,8 @@ function _saveSingleDiskLimit
 
     $_VDLIMIT --xid $ctx "$directory" | \
        $_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
+
+    $_VDLIMIT --xid $ctx --remove "$directory"
 }
 
 
@@ -1199,7 +1222,7 @@ function _namespaceCleanup
 
     # these are things that have to be accessible post-cleanup
     for tmp in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
-       "$__PKGSTATEDIR" "${skip[@]}"; do
+       "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
        while test -n "$tmp"; do
            list=( "${list[@]}" "$tmp" )
            tmp="${tmp%/*}"
@@ -1224,3 +1247,28 @@ function _namespaceCleanup
     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" "${vdevmap_opts[@]}" || return $?
+    done
+}