X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fscripts%2Fvserver.start;h=a46b3f184df198d39d84ace4b24a049755d741ac;hb=dfa40e043f50b3ed0f89cdec01d0655c94c1e12e;hp=ecd667d67f14a50dc85b5e633474091d7f6cf250;hpb=4551c8bfa53910a937f2dcc1349115bc981145c2;p=util-vserver.git diff --git a/util-vserver/scripts/vserver.start b/util-vserver/scripts/vserver.start index ecd667d..a46b3f1 100644 --- a/util-vserver/scripts/vserver.start +++ b/util-vserver/scripts/vserver.start @@ -1,4 +1,4 @@ -#! /bin/bash +# $Id$ --*- sh -*-- # Copyright (C) 2003 Enrico Scholz # @@ -15,311 +15,160 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -## Expected env: -# $VSERVER_DIR ... path to vserver-cfg dir -# $VSERVER_NAME ... name of vserver -declare -a NICE_CMD=() -declare -a CHBIND_OPTS=() -declare -a CAP_OPTS=() -declare -a CHCONTEXT_FLAG_OPTS=() -declare -a CHCONTEXT_OPTS=() -declare -a CAPCHROOT_OPTS=() -declare -a INTERFACES=() -declare -a START_CMD=() +lock "$__LOCKDIR"/vserver."$($_VSERVER_INFO "$VSERVER_DIR" CANONIFY)".startup -SILENT_OPT= +if isVserverRunning "$VSERVER_DIR"; then + warning $"vserver '$VSERVER_NAME' already running" + exit 0 +fi -function _generateInterfaceList +function cleanup() { - local vdir="$1" - local iface - local ip + set +e - for iface in "$VSERVER_DIR/interfaces/"*; do - test -d "$iface" || continue - test ! -e "$iface"/disabled || continue + test -z "$startsync_pipe" || $_RM -f "$startsync_pipe" + test -z "$is_started" || { unlock; return 0; } - read ip <"$iface"/ip || continue - INTERFACES=( "${INTERFACES[@]}" "$ip" ) - done 2>/dev/null -} + if test -n "$is_configured" -a -z "$is_executed"; then + warning $" +An error occured while executing the vserver startup sequence; when +there are no other messages, it is very likely that the init-script +(${INITCMD_START[@]}) failed. -function _generateChbindOptions -{ - local vdir="$1" - local i - local bcast= +Common causes are: +* /etc/rc.d/rc on Fedora Core 1 and RH9 fails always; the 'apt-rpm' build + method knows how to deal with this, but on existing installations, + appending 'true' to this file will help." + fi - local f=$vdir/interfaces/bcast - test ! -e "$f" || read bcast <"$f" - - CHBIND_OPTS=( $SILENT_OPT ${bcast:+--bcast "$bcast"} ) + if test -n "$is_executed"; then + warning $" +An error occured after executing the vserver startup sequence. This +means that some processes may exist in the created context and the +manual execution of - for i in "${INTERFACES[@]}"; do - CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" ) - done -} + $_VSERVER '$VSERVER_DIR' stop -function _generateNiceCommand -{ - local vdir=$1 - local nice +is recommended to fix this." + else + warning $" - test -e "$vdir/nice" || return 0; - read nice <"$vdir"/nice +Failed to start vserver '$VSERVER_NAME'" + fi - NICE_CMD=( $_NICE -$nice ) -} + test -n "$OPTION_DEBUG" || exec 2>/dev/null >/dev/null + test -z "$is_mounted" || umountVserver "$VSERVER_DIR" || : + test -z "$have_interfaces" || disableInterfaces "$VSERVER_DIR" || : -function _generateCapabilityOptions -{ - local vdir=$1 - local cap - - test -e "$vdir"/capabilities || return 0 - - CAP_OPTS=() - CAPCHROOT_OPTS=() - - while read cap; do - case x"$cap" in - x|x#) ;; - !CAP_SYSCHROOT) - CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" ) - CAPCHROOT_OPTS=( "${CAPCHROOT_OPTS[@]}" --nochroot ) - ;; - *) - CAP_OPTS=( "${CAP_OPTS[@]}" --cap "$cap" );; - esac - done <"$vdir"/capabilities + unlock || : } -function _generateFlagOptions -{ - local vdir=$1 - local init_default=3 - - CHCONTEXT_FLAG_OPTS=() - - ## TODO: get_initdefault - START_CMD=( /etc/rc.d/rc $init_default ) - test ! -x "$vdir/etc/init.d/rc" || { - START_CMD=( /etc/init.d/rc $init_default ) - } - - test -e "$vdir"/flags || return 0 - - while read flag; do - case x"$flag" in - x|x#) ;; - dummy) ;; - minit|fakeinit) - CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" \ - --disconnect --flag --fakeinit ) - case "$flag" in - minit) START_CMD=( /sbin/minit-start );; - *) START_CMD=( /sbin/init );; - esac - ;; - *) - CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" - --flag "$flag" ) - ;; - esac - done <"$vdir"/flags -} - -function _generateChcontextOptions -{ - local vdir=$1 - local ctx hostname domainname - local cap_opts - local flag - - { - read ctx <"$vdir"/context - read hostname <"$vdir"/hostname - read domainname <"$vdir"/domainname - } 2>/dev/null - - _generateCapabilityOptions "$vdir" - _generateFlagOptions "$vdir" - - CHCONTEXT_OPTS=( $SILENT_OPT \ - "${CHCONTEXT_FLAG_OPTS[@]}" \ - "${CAP_OPTS[@]}" \ - --secure - ${ctx:+--ctx "$ctx"} \ - ${hostname:+--hostname "$hostname"} \ - ${domainname:+--domainname "$domainname"} ) -} - - -function enableSingleInterface -{ - local iface=$1 - - local dev - local ip - local mask - local bcast - local name - local scope - - read dev <"$iface"/dev || dev=$dev_default - read ip <"$iface"/ip || { echo $"Can not read ip for '$iface'" >&3; return 1; } - read prefix <"$iface"/prefix || prefix=$prefix_default - read mask <"$iface"/mask || mask=$mask_default - read bcast <"$iface"/bcast || bcast=$bcast_default - read name <"$iface"/name - read scope <"$iface"/scope - - test ! -e "$iface"/only_ip || unset dev - - if test "$dev"; then - test "$prefix" || { - $_MASK2PREFIX "$mask" || prefix=$? - test "$prefix" != 255 - } - - 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" - return 1 - } - test -f /proc/net/vlan || { - $_VCONFIG add ${dev/./ } - $_IP addr add 127.0.0.1/8 broadcast 127.255.255.255 dev "$dev" - $_IP link set "$dev" up - } - ;; - esac - - $_IP addr add "$ip${prefix:+/$prefix}" ${bcast:-broadcast +}${bcast:+broadcast "$bcast"} \ - ${name:+label "$dev:$name"} dev "$dev" - $_IP route add "$ip""${prefix:+/$prefix}" dev "$dev" - $_IP link set "$dev" up - fi 2>&3 -} - -function setInterfaceDefaults -{ - read dev_default <"$1"/dev - read mask_default <"$1"/mask - read prefix_default <"$1"/prefix - read bcast_default <"$1"/bcast - - test -z "mask_default" -o "$prefix_default" || { - $_MASK2PREFIX "$mask_default" || prefix_default=$? - test "$prefix_default" != 255 - } -} - -function enableInterfaces -{ - local VSERVER_DIR=$1 - local VSERVER_NAME=$2 - - local iface - - local dev_default - local mask_default - local bcast_default - local prefix_default - - declare -a all_ips - - setInterfaceDefaults 3>&2 2>/dev/null - - for iface in "$VSERVER_DIR/interfaces/"*; do - test -d "$iface" || continue - test ! -e "$iface"/disabled || continue - - enableSingleInterface "$iface" 3>&2 2>/dev/null - done -} - - +is_configured= +is_executed= +is_started= +is_mounted= +is_vshelper_init= +have_interfaces= +startsync_pipe= +have_initcmd= + +while test "$#" -gt 0; do + case "$1" in + (--rescue) INITSTYLE=rescue;; + (--rescue-cmd) + warning $"\ +The '--rescue-cmd' option is deprecated; just add the the initcmd +inclusive its arguments to the cmdline." + INITCMD_RESCUE=( $2 ); + have_initcmd=1 + shift;; + (--) shift; break;; + (-*) panic $"vserver ... start: unknown option '$1'";; + (*) break; + esac + shift +done + +if test x"$INITSTYLE" = xrescue -a -z "$have_initcmd" -a "$#" -gt 0; then + INITCMD_RESCUE=( "$@" ) +fi +set -e +trap "cleanup" EXIT -function generateOptions -{ - _generateInterfaceList "$1" - _generateChbindOptions "$1" - _generateNiceCommand "$1" - _generateChcontextOptions "$1" -} +sanityCheck "$VSERVER_DIR" -function mountVserver -{ - local cfgdir=$1 - local vdir=$1/vdir - local src dst type opts aux - local mountopts - - declare -a mountopts - - test -e "$cfgdir"/fstab || return 0 - - cat "$cfgdir"/fstab | while read src dst type opts aux; do - test "$src" -a "$dst" -a "$type" -a "$opts" || continue - - if test "$type" = "bind"; then - mountopts=( --bind ) - else - mountopts=( -type $type -o "$opts" ) - fi - - $_CHBIND "${CHBIND_OPTS[@]}" \ - $_MOUNT "${mountopts}" "$src" "$vdir$dst" - done -} +mountRootFS "$VSERVER_DIR" +generateOptions "$VSERVER_DIR" -function execScriptlets -{ - local vdir=$1 - local name=$2 - local flavor=$3 - local i - - for i in "$vdir/scripts/$flavor" "$vdir/scripts/$flavor.d"/*; do - test -f "$i" -a -x "$i" || continue - "$i" "$flavor" "$name" - done -} +pushd "$VSERVER_DIR" >/dev/null +execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" prepre-start +popd >/dev/null -############################################ +enableInterfaces "$VSERVER_DIR" && have_interfaces=1 -: ${VSERVER_NAME:=$(basename "$VSERVER_DIR")} +mountVserver "$VSERVER_DIR" && is_mounted=1 +prepareInit "$VSERVER_DIR" -if test -e "$VSERVER_DIR"/noisy; then - SILENT_OPT= +pushd "$VSERVER_DIR"/vdir/ >/dev/null +execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" pre-start +popd >/dev/null + +test -z "$OPTION_DEFAULTTTY" || setDefaultTTY "$VSERVER_DIR" + +pushd "$VSERVER_DIR"/vdir/ >/dev/null +is_configured=1 +if $_VSERVER_INFO - FEATURE migrate; then + ${NICE_CMD[@]} \ + $_CHBIND "${CHBIND_OPTS[@]}" -- \ + $_EXEC_ULIMIT "$VSERVER_DIR"/ulimits \ + $_VCONTEXT --create "${OPTS_VCONTEXT_CREATE[@]}" -- \ + ${USE_VNAMESPACE:+$_VNAMESPACE --set -- } \ + $_VLIMIT --dir "$VSERVER_DIR"/rlimits --missingok -- \ + $_VSCHED --xid self "${OPTS_VSCHED[@]}" -- \ + $_VUNAME --xid self --dir "$VSERVER_DIR"/uts --missingok -- \ + "${VSERVER_EXTRA_CMDS[@]}" \ + $_VUNAME --xid self --set -t context="$VSERVER_DIR" -- \ + $_VATTRIBUTE --set "${OPTS_VATTRIBUTE[@]}" -- \ + $_SAVE_CTXINFO "$VSERVER_DIR" \ + $_ENV -i -- \ + $_VCONTEXT --migrate-self --endsetup --chroot $SILENT_OPT \ + "${OPTS_VCONTEXT_MIGRATE[@]}" "${OPTS_VCONTEXT_ENTER[@]}" -- \ + "${INITCMD_START[@]}" else - SILENT_OPT='--silent' -fi - -if isVserverRunning "$VSERVER_DIR"; then - echo $"vserver '$VSERVER_NAME' already running; aborting..." - exit 1 + if test -n "$_IS_FAKEINIT"; then + startsync_pipe=$($_MKTEMP /tmp/vserver-start.XXXXXX) + $_RM -f "$startsync_pipe" + $_MKFIFO -m600 "$startsync_pipe" ## safe, since mkfifo does not follow symlinks + fi + + ${NICE_CMD[@]} \ + $_CHBIND "${CHBIND_OPTS[@]}" \ + $_EXEC_ULIMIT "$VSERVER_DIR/ulimits" \ + $_CHCONTEXT_COMPAT "${CHCONTEXT_OPTS[@]}" "${CHCONTEXT_INIT_OPTS[@]}" \ + $_SAVE_CTXINFO "$VSERVER_DIR" \ + $_ENV -i -- \ + $_CHAINECHO "${_IS_FAKEINIT:+$startsync_pipe}" "" \ + $_CAPCHROOT "${CAPCHROOT_OPTS[@]}" . \ + "${INITCMD_START[@]}" + + ## the additional synchronization step is needed since vshelper.doInit + ## below might be executed before needed context information were + ## saved by $_SAVE_CTXINFO + ${_IS_FAKEINIT:+cat "$startsync_pipe"} >/dev/null fi +is_executed=1 -execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" pre-start -generateOptions "$VSERVER_DIR" -enableInterfaces "$VSERVER_DIR" "$VSERVER_NAME" - -# TODO: utmp - -mountVserver "$VSERVER_DIR" +"${INITCMD_START_SYNC[@]}" +popd >/dev/null -cd "$VSERVER_DIR"/vdir/ +pushd "$VSERVER_DIR"/vdir/ >/dev/null +execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" post-start +popd >/dev/null -"${NICE_CMD[@]}" \ - "$_CHBIND" "${CHBIND_OPTS[@]}" \ - "$_CHCONTEXT" "${CHCONTEXT_OPTS[@]}" \ - "$_SAVE_CTXINFO" "$VSERVER_DIR" \ - "$_CAPCHROOT" "${CAPCHROOT_OPTS[@]}" . "${START_CMD[@]}" +is_vshelper_init=1 +! vshelper.isEnabled "" "$VSERVER_DIR" || vshelper.doInit "$VSERVER_DIR" -execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" post-start +is_started=1