Enter namespaces before context setup.
[util-vserver.git] / scripts / vserver.functions
index 1a73094..d979401 100644 (file)
@@ -41,13 +41,16 @@ declare -a ENTER_SHELL=()
 declare -a OPTS_VCONTEXT_CREATE=()
 declare -a OPTS_VCONTEXT_MIGRATE=()
 declare -a OPTS_VCONTEXT_ENTER=()
+OPT_VCONTEXT_CHROOT=--chroot
 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 OPTS_VSPACE=()
+declare -a OPTS_VSPACE=( --default )
+declare -a OPTS_VSPACE_SHARED=()
+declare -a VSPACE_SHARED_CMD=()
 
 declare -a STOPCMD_PREPARE=()
 
@@ -146,6 +149,8 @@ function _generateIONiceCommand
     local ionice_class=2
     local ionice_priority=0
 
+    test -n "$_IONICE" || return 0
+
     test -r "$vdir/ionice/class" && read ionice_class <"$vdir"/ionice/class
     test -r "$vdir/ionice/priority" && read ionice_priority <"$vdir"/ionice/priority
 
@@ -341,11 +346,19 @@ function _generateInitOptions
                panic "init-vserver.sh not found; aborting"
            fi
 
-           INITCMD_START=( env TERM=$TERM $RC_WRAP "$RUNLEVEL_START" )
+           OPTS_ENV=( "${OPTS_ENV[@]}" TERM=$TERM )
+           INITCMD_START=( $RC_WRAP "$RUNLEVEL_START" )
            INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
            INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
            ;;
 
+       (xarch)
+           test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
+           INITCMD_START=( /etc/rc.multi )
+           INITCMD_STOP=( /etc/rc.shutdown )
+           INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
+           ;;
+
        (x) ;;
        (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
     esac
@@ -374,10 +387,12 @@ function _generateInitOptions
 function _generateFlagOptions
 {
     local vdir=$1
+    local file
 
     CHCONTEXT_FLAG_OPTS=()
 
-    test ! -e "$vdir"/flags || \
+    findFile file "$vdir"/cflags "$vdir"/flags ""
+    test -z "$file" || \
     while read flag; do
        case x"$flag" in
            (x|x\#*)            ;;
@@ -391,11 +406,13 @@ function _generateFlagOptions
                                      --flag "$flag" )
                ;;
        esac
-    done <"$vdir"/flags
+    done <"$file"
 
     isAvoidNamespace "$vdir" || {
        USE_VNAMESPACE=1
        CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
+       ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+           OPT_VCONTEXT_CHROOT=--pivot-root
     }
 }
 
@@ -772,16 +789,30 @@ function _generateSpaceOptions
 {
     local vdir="$1"
     local d="$vdir"/spaces
+    local shared
 
-    ( test ! -e "$d"/pid ) || \
-       OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
+    if test -e "$d"/pid; then
+       getFileValue shared "$d"/pid
+       if test -z "$shared"; then
+           OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
+       else
+           OPTS_VSPACE_SHARED=( "${OPTS_VSPACE_SHARED[@]}" --pid )
+           VSPACE_SHARED_CMD=( "${VSPACE_SHARED_CMD[@]}" $_VSPACE --enter "$shared" --pid -- )
+       fi
+    fi
 
-    test ! -e "$d"/net || {
-       OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
+    if test -e "$d"/net; then
+       getFileValue shared "$d"/net
        # network context and namespace don't make much sense
        _HAVE_CHBIND_OPTIONS=1
        CHBIND_CMD=()
-    }
+       if test -z "$shared"; then
+           OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
+       else
+           OPTS_VSPACE_SHARED=( "${OPTS_VSPACE_SHARED[@]}" --net )
+           VSPACE_SHARED_CMD=( "${VSPACE_SHARED_CMD[@]}" $_VSPACE --enter "$shared" --net -- )
+       fi
+    fi
 
     local mask
     getFileValue mask "$d"/mask || \
@@ -794,8 +825,8 @@ function prepareInit
     pushd "$1/vdir" >/dev/null
     case "$INITSTYLE" in
        sysv)
-           { find var/run  ! -type d -print0; \
-             find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
+           { $_FIND var/run  ! -type d -print0; \
+             $_FIND var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
            ;;
        plain)
            $_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
@@ -904,6 +935,10 @@ function _mountVserverInternal
     # magic regarding the mtab file; when etc/mtab can not be touched,
     # add the '-n' flag to mount
     test -w etc -o -w etc/mtab || xflag=-n
+    if test -h etc/mtab; then
+       local l=$($_READLINK etc/mtab)
+       test "${l##/proc/}" = "$l" || xflag=-n
+    fi
     "$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
     popd >/dev/null
 }
@@ -931,6 +966,8 @@ function mountVserver
     local ns_opt=$2
     local vdir=$1/vdir
     local mtab_src
+    local extra_opt=
+    local real_vdir
 
     test -e "$cfgdir"/fstab -o \
          -e "$cfgdir"/fstab.local -o \
@@ -951,8 +988,11 @@ function mountVserver
     isNamespaceCleanup "$cfgdir" && \
         _namespaceCleanup "$cfgdir"
 
+    real_vdir=$(getPhysicalDir "$vdir")
     isAvoidNamespace "$cfgdir" || \
-       $_SECURE_MOUNT --rbind -n "$vdir" "/"
+       $_SECURE_MOUNT --rbind -n -o dev "$vdir" "$real_vdir"
+    ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+       $_SECURE_MOUNT -n -o shared,rec "$real_vdir" "$real_vdir"
 }
 
 function _umountVserverInternal
@@ -1194,7 +1234,7 @@ WARNING: There is no cachedirectory configured for this vserver;
   ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
 "
 
-    find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
+    $_FIND "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
 
     vshelper.doSanityCheck
 
@@ -1359,7 +1399,8 @@ function _namespaceCleanup
     while read -r dev path opts; do
        test -n "$path" || continue
        for i in "$root" /dev /proc; do
-           test "${path#$i}" != "$path" && continue 2
+           path_dir="${path}/"
+           test "${path_dir#${i}/}" != "${path_dir}" && continue 2
        done
        for i in "${list[@]}" /; do
            test "$path" = "$i" && continue 2
@@ -1419,6 +1460,10 @@ function _generateCgroupOptions
     findFile file "$__CONFDIR/.defaults/cgroup/subsys" ""
     if test -n "$file"; then
        read CGROUP_SUBSYS < "$file"
+    elif $_GREP -q '^ns[[:space:]]' /proc/cgroups; then
+       # Hack for the ns subsystem, with which we are incompatible
+       CGROUP_SUBSYS=$($_SED '/^#/d;/^ns[[:space:]]/d;s/[[:space:]].*//' /proc/cgroups | \
+                       (s=""; while read x; do test -n "$s" && s="$s,"; s="$s$x"; done; echo "$s"))
     fi
     findFile file "$__CONFDIR/.defaults/cgroup/inherit" ""
     if test -n "$file"; then
@@ -1454,7 +1499,7 @@ function _handleCgroup
     if test -r "$dir"/name; then
        read name < "$dir"/name
     else
-       read name < "$vdir"/name
+       name="$VSERVER_NAME"
     fi
 
     if test "$action" = "attach"; then
@@ -1468,7 +1513,10 @@ function _handleCgroup
 
            shopt -s nullglob
            for i in "$dir"/*; do
-               cat "$i" > "$CGROUP_MNT/$name/${i##*/}"
+               f="${i##*/}"
+               test "$f" != mnt -a "$f" != subsys -a \
+                   "$f" != inherit -a "$f" != name || continue
+               cat "$i" > "$CGROUP_MNT/$name/$f"
            done
        fi
        echo "$$" > "$CGROUP_MNT/$name/tasks"