#! /bin/bash # Copyright (C) 2003 Enrico Scholz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # 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=() SILENT_OPT= INITSTYLE=sysv RUNLEVEL=3 function _generateInterfaceList { local vdir="$1" local iface local ip mask prefix for iface in "$VSERVER_DIR/interfaces/"*; do test -d "$iface" || continue test ! -e "$iface"/disabled || continue _getInterfaceValue ip '' "$iface" _getInterfaceValue mask '' "$iface" "$iface/.." _getInterfaceValue prefix '' "$iface" "$iface/.." _transformMask2Prefix prefix "$prefix" "$mask" INTERFACES=( "${INTERFACES[@]}" "$ip${prefix:+/$prefix}" ) done 2>/dev/null } function _generateChbindOptions { local vdir="$1" local i local bcast= local f=$vdir/interfaces/bcast test ! -e "$f" || read bcast <"$f" CHBIND_OPTS=( $SILENT_OPT ${bcast:+--bcast "$bcast"} ) for i in "${INTERFACES[@]}"; do CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" ) done } function _generateNiceCommand { local vdir=$1 local nice test -e "$vdir/nice" || return 0; read nice <"$vdir"/nice NICE_CMD=( $_NICE -$nice ) } 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 } function _generateFlagOptions { local vdir=$1 CHCONTEXT_FLAG_OPTS=() ## TODO: get_initdefault START_CMD=( /etc/rc.d/rc "$RUNLEVEL" ) test ! -x "$vdir/etc/init.d/rc" || { START_CMD=( /etc/init.d/rc "$RUNLEVEL" ) } 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 ) INITSTYLE=minit ;; *) 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 _getInterfaceValue { local val=$1 local dflt=$2 shift 2 local i local tmp for i; do read tmp <"$i/$val" && break || : done 2>/dev/null eval $val=${tmp:-$dflt} } function _transformMask2Prefix { local tmp=$2 test "$tmp" || { $_MASK2PREFIX "$3" || tmp=$? } eval $1=$tmp return 0 } function enableSingleInterface { local iface=$1 local ip local dev local prefix local mask local bcast local name local scope _getInterfaceValue ip '' "$iface" _getInterfaceValue dev '' "$iface" "$iface/.." _getInterfaceValue prefix '' "$iface" "$iface/.." _getInterfaceValue mask '' "$iface" "$iface/.." _getInterfaceValue bcast '' "$iface" "$iface/.." _getInterfaceValue name '' "$iface" _getInterfaceValue scope '' "$iface" "$iface/.." test "$ip" || { echo $"Can not read ip for '$iface'"; return 1; } test ! -e "$iface"/only_ip || 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" 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}" broadcast ${bcast:-+} \ ${name:+label "$dev:$name"} dev "$dev" $_IP route add "$ip""${prefix:+/$prefix}" dev "$dev" $_IP link set "$dev" up fi } function enableInterfaces { local VSERVER_DIR=$1 local VSERVER_NAME=$2 local iface declare -a all_ips for iface in "$VSERVER_DIR/interfaces/"*; do test -d "$iface" || continue test ! -e "$iface"/disabled || continue enableSingleInterface "$iface" done } function prepareInit { local vdir=$1 local style=$2 pushd "$vdir/vdir" >/dev/null case "$style" in sysv) { find var/run ! -type d -print0; \ find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_RM $_FAKE_RUNLEVEL "$RUNLEVEL" /var/run/utmp ;; minit) ;; esac popd >/dev/null } function generateOptions { _generateInterfaceList "$1" _generateChbindOptions "$1" _generateNiceCommand "$1" _generateChcontextOptions "$1" } 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 $_CHBIND "${CHBIND_OPTS[@]}" \ $_SECURE_MOUNT -a --chroot "$vdir" --fstab "$cfgdir"/fstab } 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 } ############################################ : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")} if test -e "$VSERVER_DIR"/noisy; then SILENT_OPT= else SILENT_OPT='--silent' fi if isVserverRunning "$VSERVER_DIR"; then echo $"vserver '$VSERVER_NAME' already running; aborting..." exit 1 fi execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" prepre-start generateOptions "$VSERVER_DIR" enableInterfaces "$VSERVER_DIR" "$VSERVER_NAME" mountVserver "$VSERVER_DIR" prepareInit "$VSERVER_DIR" "$INITSTYLE" cd "$VSERVER_DIR"/vdir/ execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" pre-start "${NICE_CMD[@]}" \ "$_CHBIND" "${CHBIND_OPTS[@]}" \ "$_CHCONTEXT" "${CHCONTEXT_OPTS[@]}" \ "$_SAVE_CTXINFO" "$VSERVER_DIR" \ "$_CAPCHROOT" "${CAPCHROOT_OPTS[@]}" . "${START_CMD[@]}" execScriptlets "$VSERVER_DIR" "$VSERVER_NAME" post-start