minor cosmetical cleanups...
[util-vserver.git] / util-vserver / scripts / vserver.functions
index e5763c9..d666cbc 100644 (file)
@@ -1,4 +1,4 @@
-#! /bin/bash
+# $Id$  --*- sh -*--
 
 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
 #  
@@ -33,56 +33,50 @@ declare -a INITCMD_START_SYNC=()
 declare -a INITCMD_STOP=()
 declare -a INITCMD_STOP_SYNC=()
 declare -a INITCMD_PREPARE=()
+declare -a INITKILL_SEQ=()
+declare -a ENTER_SHELL=()
+
+declare -a OPTS_VCONTEXT_CREATE=()
+declare -a OPTS_VCONTEXT_MIGRATE=()
+declare -a OPTS_VATTRIBUTE=()
+USE_VNAMESPACE=
 
 INTERFACE_CMDS_IDX=0
+_HAVE_INTERFACE_OPTIONS=
+_HAVE_CHBIND_OPTIONS=
 
 INITSTYLE=sysv
 
 S_CONTEXT=
 
 SILENT_OPT=
-_NEWLINE='
-'
-_NEWLINE=${_NEWLINE:0-1}
 
 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
 
-if test -e "$VSERVER_DIR"/noisy; then
+if test -e "$VSERVER_DIR"/noisy -o "$OPTION_VERBOSE"; then
     SILENT_OPT=
 else
     SILENT_OPT='--silent'
 fi
 
-## Called as '_getFileValue <varname> <filename>'
-function _getFileValue
-{
-    test -r "$2" || return 0
-    eval read "$1" <"$2"
-}
-
-## Called as '_getFileArray <varname> <filename>'
-function _getFileArray
-{
-    test -r "$2" || return 0
-    
-    local IFS=$_NEWLINE
-    eval "$1"='( $(< "$2") )'
-}
-
 function _generateChbindOptions
 {
     local vdir="$1"
     local i
     local bcast=
 
+    test "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
+
     local f=$vdir/interfaces/bcast
-    _getFileValue bcast "$f"
+    getFileValue bcast "$f"
     
     CHBIND_OPTS=( $SILENT_OPT ${bcast:+--bcast "$bcast"} )
 
     for i in "${INTERFACES[@]}"; do
        CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
     done
+
+    _HAVE_CHBIND_OPTIONS=1
 }
 
 function _generateNiceCommand
@@ -96,11 +90,44 @@ function _generateNiceCommand
     NICE_CMD=( $_NICE -$nice )
 }
 
+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"
+}
+
+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"
+}
+
 function _generateCapabilityOptions
 {
     local vdir=$1
     local cap
 
+    _generateBCapabilityOptions "$vdir"
+    _generateCCapabilityOptions "$vdir"
+    
     test -e "$vdir"/capabilities || return 0
 
     CAP_OPTS=()
@@ -108,24 +135,60 @@ function _generateCapabilityOptions
 
     while read cap; do
        case x"$cap" in
-           x|x#)       ;;
-           !CAP_SYSCHROOT)
+           (x|x\#)     ;;
+           (!CAP_SYSCHROOT)
                CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
                CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot )
                ;;
-           *)
-               CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" );;
+           (*)
+               CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" )
+               ;;
        esac
     done <"$vdir"/capabilities
 }
 
+function getEnterShell
+{
+    local vdir=$1
+
+    ENTER_SHELL=()
+    
+    getFileValue ENTER_SHELL    "$vdir"/shell
+    
+    test "$ENTER_SHELL" || {
+       local i
+       for i in "/bin/bash -login" "/bin/sh -l" /bin/csh; do
+           set -- $i
+           test -x "$vdir/vdir/$1" || continue
+           ENTER_SHELL=( "$@" )
+           break
+       done
+    }
+}
+
+## Usage: sendKillSequence <ctx> <signal> [<wait> <signal>]*
+function sendKillSequence
+{
+    local ctx=$1
+    local wait=
+    shift
+
+    while isCtxRunning "$ctx"; do
+       test -z "$wait" || sleep "$wait"
+       
+       $_VKILL -c "$ctx" ${1:+-s "$1"}
+       test "$2" || break
+       wait="$2"
+       shift 2
+    done
+}
 
 function _generateInitOptions
 {
     local vdir=$1
     local cfgdir=$vdir/apps/init
-    local runlevel_start=3
-    local runlevel_stop=6
+    local runlevel_start
+    local runlevel_stop
     local i f
 
     INITCMD_START=()
@@ -133,16 +196,22 @@ function _generateInitOptions
     INITCMD_START_SYNC=()
     INITCMD_STOP_SYNC=()
     INITCMD_PREPARE=()
-    
+
+    INITKILL_SEQ=( 15 5 9 )
     CHCONTEXT_INIT_OPTS=()
-    
-    _getFileValue INITSTYLE      "$cfgdir"/style
-    _getFileValue runlevel_start "$cfgdir"/runlevel
-    _getFileValue runlevel_start "$cfgdir"/runlevel.start
-    _getFileValue runlevel_stop  "$cfgdir"/runlevel.stop
+
+
+    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
 
     case x"$INITSTYLE" in
-       xsysv)
+       (xsysv)
+           test "$runlevel_start" || runlevel_start=3
+           test "$runlevel_stop"  || runlevel_stop=6
+
            for i in /etc/init.d/rc /etc/rc.d/rc; do
                test -x "$vdir/vdir/$i" || continue
                INITCMD_START=( "$i" "$runlevel_start" )
@@ -151,34 +220,37 @@ function _generateInitOptions
            INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$runlevel_start" /var/run/utmp )
            ;;
            
-       xplain)
+       (xplain)
            INITCMD_START=( /sbin/init )
            INITCMD_STOP=(  /sbin/init )
            CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
+           OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --fakeinit --disconnect )
            test -z "$runlevel_start" || INITCMD_START=( "${INITCMD_START[@]}" "$runlevel_start" )
            test -z "$runlevel_stop"  || INITCMD_STOP=(  "${INITCMD_STOP[@]}"  "$runlevel_stop"  )
            ;;
            
-       xminit)
+       (xminit)
            INITCMD_START=( /sbin/minit-start )
            INITCMD_STOP=(  /sbin/minit-stop  )
            CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
            INITCMD_START_SYNC=( "$_INITSYNC_MINIT_START" "$vdir" )
            INITCMD_STOP_SYNC=(  "$_INITSYNC_MINIT_STOP"  "$vdir" )
+           OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --fakeinit --disconnect )
            test -z "$runlevel_start" || INITCMD_START=( "${INITCMD_START[@]}" "$runlevel_start" )
            test -z "$runlevel_stop"  || INITCMD_STOP=(  "${INITCMD_STOP[@]}"  "$runlevel_stop"  )
            ;;
 
-       x)  ;;
-       *)  echo "Unknown init-style '$INITSTYLE'; aborting" >&2;
+       (x) ;;
+       (*) echo "Unknown init-style '$INITSTYLE'; aborting" >&2;
            exit 1;;
     esac
 
-    _getFileArray INITCMD_START      "$cfgdir"/cmd.start
-    _getFileArray INITCMD_STOP       "$cfgdir"/cmd.stop
-    _getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync
-    _getFileArray INITCMD_STOP_SYNC  "$cfgdir"/cmd.stop-sync
-    _getFileArray INITCMD_PREPARE    "$cfgdir"/cmd.prepare
+    getFileArray INITCMD_START      "$cfgdir"/cmd.start
+    getFileArray INITCMD_STOP       "$cfgdir"/cmd.stop
+    getFileArray INITCMD_START_SYNC "$cfgdir"/cmd.start-sync
+    getFileArray INITCMD_STOP_SYNC  "$cfgdir"/cmd.stop-sync
+    getFileArray INITCMD_PREPARE    "$cfgdir"/cmd.prepare
+
     
     test -e "$cfgdir"/sync -o "$OPTION_FORCE_SYNC" || {
        INITCMD_START_SYNC=()
@@ -196,18 +268,24 @@ function _generateFlagOptions
 
     while read flag; do
        case x"$flag" in
-           x|x#)               ;;
-           dummy)              ;;
-           fakeinit)
-               CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" 
-                                     --disconnect --flag --fakeinit )
+           (x|x\#)             ;;
+           (xnamespace)        ;;
+           (xfakeinit)
+               CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
+               OPTS_VCONTEXT_MIGRATE=( "${OPTS_VCONTEXT_MIGRATE[@]}" --fakeinit --disconnect )
                ;;
-           *)
+           (*)
+               OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --flag "$flag" )
                CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}"
                                      --flag "$flag" )
                ;;
        esac
     done <"$vdir"/flags
+
+    isAvoidNamespace "$cfgdir" || {
+       USE_VNAMESPACE=1
+       CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
+    }
 }
 
 function _generateChcontextOptions
@@ -218,9 +296,9 @@ function _generateChcontextOptions
     local flag
 
     {
-       read ctx        <"$vdir"/context
-       read hostname   <"$vdir"/hostname
-       read domainname <"$vdir"/domainname
+       read ctx        <"$vdir"/context     || :
+       read hostname   <"$vdir"/hostname    || :
+       read domainname <"$vdir"/domainname  || :
     } 2>/dev/null
 
     test -z "$S_CONTEXT" || ctx=$S_CONTEXT
@@ -230,12 +308,16 @@ function _generateChcontextOptions
 
     CHCONTEXT_OPTS=( $SILENT_OPT \
                      "${CHCONTEXT_FLAG_OPTS[@]}" \
-                    "${CHCONTEXT_INIT_OPTS[@]}" \
                     "${CAP_OPTS[@]}" \
                     --secure
                     ${ctx:+--ctx "$ctx"} \
                      ${hostname:+--hostname "$hostname"} \
                     ${domainname:+--domainname "$domainname"} )
+
+    OPTS_VCONTEXT_CREATE=( $SILENT_OPT \
+                          ${ctx:+--xid "$ctx"} )
+    ## put '--secure' at front so that it can be overridden
+    OPTS_VATTRIBUTE=( --secure "${OPTS_VATTRIBUTE[@]}" )
 }
 
 function _getInterfaceValue
@@ -295,17 +377,21 @@ function _processSingleInterface
     _getInterfaceValue name   '' "$iface"
     _getInterfaceValue scope  '' "$iface" "$iface/.."
 
-    test "$ip" || { echo $"Can not read ip for '$iface'"; return 1; }
+    test "$ip" || { echo $"Can not read ip for '$iface'"  >&2; return 1; }
     
-    test ! -e "$iface"/only_ip   || unset dev
+    test ! -e "$iface"/only_ip || {
+       echo $"The 'only_ip' flag for interface '$iface' is deprecated; use 'nodev' instead of" >&2
+       unset dev
+    }
+    test ! -e "$iface"/nodev   || unset dev
     
     if test "$dev"; then
        _transformMask2Prefix prefix "$prefix" "$mask"
 
        case "$dev" in
-           *.*)
+           (*.*)
                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"
+                   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 || {
@@ -334,6 +420,7 @@ function _generateInterfaceOptions
     
         _processSingleInterface "$iface"
     done
+    _HAVE_INTERFACE_OPTIONS=1
 }
 
 function enableInterfaces
@@ -360,11 +447,13 @@ function enableInterfaces
 
 function disableInterfaces
 {
+    test "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$1"
+
     local i=$INTERFACE_CMDS_IDX
     declare -a var
 
     while test $i -gt 0; do
-       let --i
+       let --i || :
 
        eval var='( "${INTERFACE_CMDS_'$i'[@]}" )'
        local type=${var[0]}
@@ -399,7 +488,7 @@ function prepareInit
 function generateOptions
 {
     _generateInterfaceOptions  "$1"
-    _generateChbindOptions     "$1"
+    test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1" 
     _generateNiceCommand       "$1"
     _generateInitOptions       "$1"
     _generateChcontextOptions  "$1"
@@ -408,11 +497,28 @@ function generateOptions
 function mountVserver
 {
     local cfgdir=$1
+    local ns_opt=$2
     local vdir=$1/vdir
+    local mtab_src
 
     test -e "$cfgdir"/fstab || return 0
+
+    findObject -r mtab_src "$vdir"/apps/init/mtab "$CONFDIR"/.defaults/init/mtab "$PKGLIBDEFAULTDIR"/mtab /dev/null
+    
+    pushd "$vdir" >/dev/null
+    $_CHROOT_CAT /etc/mtab <"$mtab_src"
+    popd >/dev/null
+
+    test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
+
+    test -z "$NAMESPACE_CLEANUP" || isAvoidNamespace "$cfgdir" || \
+       $_VNAMESPACE --cleanup
+       
     $_CHBIND "${CHBIND_OPTS[@]}" \
        $_SECURE_MOUNT -a --chroot "$vdir" --fstab "$cfgdir"/fstab
+
+    isAvoidNamespace "$cfgdir" || \
+       $_SECURE_MOUNT --rbind -n "$vdir" "/"
 }
 
 function umountVserver
@@ -422,17 +528,19 @@ function umountVserver
 
     is_ok=1
 
-    test -e "$cfgdir"/fstab || return 0
+    isAvoidNamespace "$cfgdir"   || return 0
+    test -e "$cfgdir"/fstab      || return 0
+    test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
     
     pushd "$vdir/" >/dev/null
     tac "$cfgdir"/fstab | while read src dst tmp; do
        test "$tmp" || continue
        case x"$src" in
-           x#*)        continue;;
+           (x\#*)      continue;;
        esac
 
-       $_CHBIND "${CHBIND_OPTS[@]}" \
-           $_SECURE_UMOUNT "$dst" || is_ok=
+       $_CHBIND "${CHBIND_OPTS[@]}" $_EXEC_CD "$dst" \
+           $_UMOUNT -lfn . || is_ok=
     done
     popd >/dev/null