#!/bin/sh
# Copyright (c) 2003..2006 - RZ Uni Freiburg
# Copyright (c) 2006..2014 - OpenSLX GmbH
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your feedback to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org
#
# Main script for initial ramfs for OpenSLX linux stateless clients
#############################################################################
# fixme: the primary init script should never fail, so move all critical code
# into sub script calls (see ticket 259)
export PATH=/bin:/sbin:/usr/bin/:/usr/sbin
# device files get their own filesystem (to be move mounted later)
devdir="/dev"
mount -n -t devtmpfs -o 'size=25%,mode=0755' initramfsdevs ${devdir}
mkdir -p /run
mount -n -t tmpfs -o 'mode=755' run "/run"
# mount the important standard directories
[ ! -f /proc/cpuinfo ] && mount -n -t proc proc /proc
[ ! -d /sys/class ] && mount -n -t sysfs sysfs /sys
mkdir -p ${devdir}/pts ${devdir}/shm ${devdir}/.udevdb ${devdir}/.udev \
${devdir}/.initramfs /var/log
mount -t devpts devpts /dev/pts
# redirect kernel messages to tty10 instead of the standard console
getty -i -n -l /bin/cat 38400 tty10 &
setlogcons 10
# source functions file common for all distros, messages contains all error
# and info output (for some reason the error output is not produced properly
# - crash)
# how do the localization here? There is not yet a country-Variable
. /etc/messages
. /etc/functions || ( echo -e $init_mff && sleep 100 )
. /etc/distro-functions || ( echo -e $init_dff && sleep 100 )
# configuration settings for this slx system's environment
. /etc/slxsystem.conf 2>/dev/null || ( echo -e ${init_sscf} && \
sleep 100 )
# initramfs-setup configuration (common initial settings for all clients using
# a certain InitRamFS generated by slxconfig-demuxer)
[ -f /etc/initramfs-setup ] && . /etc/initramfs-setup 2>/dev/null
export date="${slxconf_date}"
export DEBUGLEVEL=0
export KERNEL="${slxconf_kernver}"
export NWMODULES="${slxconf_listnwmod}"
export DISTRO_NAME="${slxconf_distro_name}"
export DISTRO_VER="${slxconf_distro_ver}"
export SYSTEM_NAME="${slxconf_system_name}"
export SLXVERSION="${slxconf_slxver}"
# do not use dnbd cache file
nodnbdcache="yes"
# set a default LAN interface, might be modified for WLAN, bridge setups or
# on machines with more than one ethernet card built in
export nwif="eth0"
# load usb modules for keyboard (reenable usb keyboards, otherwise the
# admin has to wait until second run of hwsetup late in stage3) and the
# network adaptor modules, search for pci modules to load later on
hwautocfg base
# if no kernel version is set, try to get it directly from /proc
if [ -z $KERNEL ] ; then
KERNEL=$(cat /proc/version)
KERNEL=${KERNEL#*version }
KERNEL=${KERNEL% (*) (*}
fi
# set defaults for some important variables, might be overwritten via
# kernel commandline
tmpfssize="$(expr $(grep -i "memtotal" /proc/meminfo | awk '{print $2}') \
/ 100 \* 75 - 128000)k" # in kbyte
cowsize="50%"
rwdir=/dev/shm
nfsro="nfs"
aufs=1
unionfs=1
fuse=1
runinithook '00-started'
# run pre init script and user defined preinit.local, copied by mkdxsinitrd
# from /var/lib/openslx/config/... in stage2
preinit
[ -f /bin/preinit.local ] && {
[ $DEBUGLEVEL -gt 0 ] && \
echo -n "Running script /bin/preinit.local ... "
chmod u+x /bin/preinit.local
/bin/preinit.local
[ $DEBUGLEVEL -gt 0 ] && echo "ok"; }
# switch off the several configuration methods, will be switched on
# according to kernel commandline settings
echo "noldap" > /tmp/ldap-done
# external configuration file retrieval (per tftp) must be done, as otherwise
# we will never get the initramfs-setup file. By default, we try a predefined
# standard path (.../tftpboot/client-config/ ...)
file="yes"
# read kernel commandline
read KCMDLINE < /proc/cmdline
export KCMDLINE
# read the system wide initramfs-setup and then the kernel commandline
for opts in $(sed "s/#.*//" /etc/initramfs-setup) ${KCMDLINE} ; do
case ${opts} in
# shut down pc
shutdown)
cat <<EOL
SHUTTING DOWN PC!
EOL
echo "o" >/proc/sysrq-trigger
;;
# from IPAPPEND
BOOTIF=*)
bootmac=$(echo ${opts} | sed "s/.*=01-//;s/-/:/g")
;;
# localization
country=*)
COUNTRY=${opts#country=}
grep -q -E "country=" /etc/initramfs-setup &&
echo -e "\n# localization information gotten via kernel command line \
in $0\ncountry=\"${COUNTRY}\"" >>/etc/initramfs-setup
;;
# single token for debugging ...
debug)
DEBUGLEVEL=1
;;
# ... or a specified debug level
debug=*)
DEBUGLEVEL=${opts#debug=}
if [ $DEBUGLEVEL -eq 8 -o $DEBUGLEVEL -eq 20 ] ; then
echo "** SLX init started near $(sysup)"
elif [ $DEBUGLEVEL -ge 3 -a $DEBUGLEVEL -le 20 ] ; then
# create, start a debug shell process
echo "Debug shell started on second console (tty2)"
echo -e "#!/bin/sh\nsh" >/bin/debugshell
chmod u+x /bin/debugshell
getty -i -n -l /bin/debugshell 38400 tty2 &
# start logging (debuglevel >=3)
# fixme: SuSE hangs in Creating /var/log/boot.msg if activated
echo "Syslogd started on third console (tty3)"
# just to have some name in syslog
echo "(slx init)" >/proc/sys/kernel/hostname
syslogd -C2048
klogd
logread -f > /dev/tty3 2>/dev/null &
logread -f >> /var/log/messages 2>/dev/null &
fi
;;
# if configuration should not be gathered by dhcp client
nodhcp)
nodhcp="yes"
echo "nodhcp" >/tmp/dhcp-done
;;
nofile)
unset file
echo "nofile" >/tmp/file-done
;;
# if ldap configuration should be triggered
ldap)
ldap="yes"
rm /tmp/ldap-done
;;
# ldap configuration with host and port to contact (base)
ldap=*)
ldap="yes"
rm /tmp/ldap-done
;;
# file source with tftp server and file location on the server
file=*|file)
if [ "${opts}" != "file" ] ; then
fileprot=$(uri_token ${opts#file=} prot)
fileserv=$(uri_token ${opts#file=} server)
filepath=$(uri_token ${opts#file=} path)
fi
;;
# if ld.so.cache should be generated; should be switched on when composing
# rootfs from more than one source
ldsc)
ldsc="yes";;
# simple union of base ro rootdir with tempfs on top
nounionfs)
unionfs=0;;
# additional source to unify root filesystem with; the top layer will be
# the tempfs
unionfs=*)
unionfs=1
uniondirs=${opts#unionfs=}
# most probably it is a good idea to run ldconfig, so enable it
ldsc="yes"
;;
noldsc)
ldsc="";;
# same for AUFS; alternative to unionfs
noaufs)
aufs=0;;
nofuse)
fuse=0;;
aufs=*)
aufs=1
uniondirs=${opts#aufs=}
# most probably it is a good idea to run ldconfig, so enable it
ldsc="yes"
;;
noldsc)
ldsc="";;
# if cowloop should be used, only ontop of network block device and in
# combination with classical fs, like ext2 useful
cowloop=*)
cowloop=1
#cowsize=${opts#cowloop=}
;;
# rootfs will void the variables (d)nbdroot, nfsroot ...
# fixme: allow multiple rootfs sources to be unioned!?
# if strinstr " " "$rootfs" ...
rootfs=*)
rootfs=${opts#rootfs=}
rootfs=${rootfs#\"}
rootfs=${rootfs%%\"}
srvproto=$(uri_token $rootfs prot)
case $srvproto in
nfs)
# nfsroot consists of two components
nfspath=$(uri_token $rootfs path)
nfsserver=$(uri_token $rootfs server)
grep -q -E "nfsserver" /etc/initramfs-setup || \
echo -e "# nfs root information gotten via kernel command \
line in $0\nnfsserver=\"${nfsserver}\"\nnfspath=\"${nfspath}\"" \
>>/etc/initramfs-setup
;;
*nbd*)
bldmod=$srvproto
# get settings for nbd-client, filesystem equals to path in URI
# notation (remove leading slash from filesystem at the end)
bldhost=$(uri_token $rootfs server)
bldport=$(uri_token $rootfs port)
path=$(uri_token $rootfs path)
bldrfst=${path##*/}
bldopt=${path%/*}
bldopt=${bldopt#/*}
;;
aoe)
echo "Not implemented yet"
bldmod=
;;
iscsi)
echo "Not implemented yet"
bldmod=
#iscsiserver=$(uri_token $rootfs server)
#iscsiport=$(uri_token $rootfs port)
#iscsitarget=$(uri_token $rootfs path)
;;
lbd)
# use a local device for mounting root block device with given
# filesystem directly or a root filesystem container from another
# filesystem, e.g. rootfs=lbd://sda1/squashfs (bldmod cannot be
# empty, use loop or the real device stuff)
bldmod=loop
blddev=$(uri_token $rootfs server)
bldfst=$(uri_token $rootfs path)
bldfst=${bldfst#/*}
;;
esac
;;
# size of cache dnbd should use within ram
dcsize=*)
dnbdcachesize=${opts#dcsize=};;
# ip configuration client-ip:server-ip:gateway:netmask
ip=*)
ipinfo=${opts#ip=};;
# deprecated: nfs server and path (rewritten to standard style)
nfsroot=*)
srvproto=nfs
nfsroot=${opts#nfsroot=}
nfspath=${nfsroot#*:}
nfsserver=${nfsroot%:/*}
grep -q -E "nfsserver" /etc/initramfs-setup || \
echo -e "\n# nfs root information gotten via kernel command line \n\
in $0\n# deprecated: please use rootfs=nfs://...\nnfsserver=\"${nfsserver}\"\
\nnfspath=\"${nfspath}\"">> /etc/initramfs-setup
;;
# size of tempfs if not max. 50% of RAM should be used
tmpfssize=*)
tmpfssize=${opts#tmpfssize=};;
# vendor code identifier for dhcp requests, that way OpenSLX clients could
# be distinguished from other (dhcp) clients
vci=*)
vci=${opts#vci=};;
# option for ddcinfo
ddcinfo=*)
ddcinfo=${opts#ddcinfo=};;
esac
done
runinithook '05-have-kernelvars'
# at this point a timer should be started to ensure an automated reboot
# or halt of the machine if SLX init does not succeed (e.g. missing kernel
# module for the network adaptor)
if [ ${DEBUGLEVEL} -lt 3 -o ${DEBUGLEVEL} = 8 ] ; then
cat<<EOF > /bin/watchdog
#!/bin/sh
echo \$$ > /tmp/watchdogpid
[ ! -f /proc/version ] && mount -n -t proc proc /proc
sleep 120 2> /dev/null
echo "o" > /proc/sysrq-trigger
EOF
chmod u+x /bin/watchdog
watchdog &
fi
# check if at least one type of IP configuration is availabe
if [ -n "$nodhcp" -a -z "$ldap" -a -z "$ipinfo" -a $srvproto != "lbd" ]
then echo -e "# You did not specify any advanced configuration mode for \
your clients. You\n# might want to add the token 'dhcp' for DHCP config, \
'file(=source)'\n# for config file get via TFTP or 'ldap(=source)' for LDAP \
configuration to\n# your kernel command line." >> /etc/initramfs-setup
if strinfile "clientip" /etc/initramfs-setup ; then
# IP configuration seems to be present in initramfs-setup file
# TODO: FIX this, as it will clobber all kernel-cmdline values!
. /etc/initramfs-setup
ipinfo="ip=$clientip:$serverip:$gateway:$subnet_mask"
else
error "$init_errip"
fi
fi
# for ldap configuration at least basic IP setup is needed to contact the
# server
[ -n "$nodhcp" -a -n "$ldap" -a -z "$ipinfo" ] && error "$init_errldap"
# set debug level and logfile
if [ $DEBUGLEVEL -eq 20 ] ; then
echo "** Setting debuglevel to ${DEBUGLEVEL} at $(sysup)"
elif [ $DEBUGLEVEL -ne 0 ] ; then
echo "Setting debuglevel to ${DEBUGLEVEL}"
fi
export MODPRV=" "
export LOGFILE
if [ "${DEBUGLEVEL}" -gt 0 -a "${DEBUGLEVEL}" != 8 ] ; then
# set LOGFILE and move it later on into stage4
LOGFILE="/var/log/slx-boot.log"
echo "Starting OpenSLX client boot logging at $(date)" >$LOGFILE
echo "1 4 1 7" >/proc/sys/kernel/printk
[ "${DEBUGLEVEL}" -ge 2 ] && MODPRV="-v"
[ "${DEBUGLEVEL}" -gt 3 -a "${DEBUGLEVEL}" -le 10 ] && {
set -x
# and the kernel too
echo "7 7 7 7" >/proc/sys/kernel/printk; }
[ "${DEBUGLEVEL}" -gt 10 -a "${DEBUGLEVEL}" -le 20 ] && set +x
else
# switch off most of kernel debug output
echo "0 0 0 0" >/proc/sys/kernel/printk
# modprobe should stay quiet
MODPRV="-q"
LOGFILE="/dev/null"
fi
runinithook '10-nw-if-config'
# check for multiple ethernet interfaces (we have at least the mac of PXE boot
# device in $bootmac)
# check here for the active ethernet link (skip non-ethN interfaces)
if strinstr "eth" "$nwif" ; then
for ethif in eth0 eth1 eth2 eth3 ; do
export macaddr=$(ip link show dev $ethif 2>/dev/null | \
grep -i link.ether | awk '{print $2}')
# if there is no bootmac present in kernel commandline any checks are
# useless
if [ -z "$bootmac" ] ; then
bootmac="$macaddr"
[ "$ethif" != "eth0" ] && error "$init_bootmac" nonfatal
fi
if [ "$macaddr" = "$bootmac" ] ; then
nwif=$ethif
break
elif [ "x$macaddr" = "x" ] ; then
# if the macaddr is empty on the first interface tried, there is no
# network adaptor visible (missing kernel module)
if [ "$ethif" = "eth0" ] ; then
error "$init_errnwad"
else
# assume a forcedeth problem here (nonmatching MACs)
macaddr=${bootmac}
fi
break
fi
done
fi
# quickfix for proper nwif passing ... (to be fixed in a more general way)
sed "s/nwif=.*/nwif=\"${nwif}\"/" -i /tmp/env/wrapper.env
oldnwif=$nwif
# hook to setup bridging (several virtualization tools ...
runinithook '20-nw-bridge-config'
# set up loopback networking
[ $DEBUGLEVEL -eq 20 ] && echo "** starting ip config at $(sysup)"
ip link set dev lo up 2>/dev/null
ip addr add 127.0.0.1/8 dev lo 2>/dev/null
ip link set dev $nwif up 2>/dev/null || error "$init_noeth"
# analyze ip information from the kernel command line and put parts
# of it into several variables
if [ -n "$ipinfo" ] ; then
getip () {
local val="$ipinfo:"; i=$(($1 - 1));
while [ $i -gt 0 ] ; do
val=${val#*:} ; i=$(($i - 1));
done;
echo $val|sed "s/:.*//"; }
clientip=$(getip 1)
serverip=$(getip 2)
gateway=$(getip 3)
subnet_mask=$(getip 4)
broadcast_address=$(ipcalc -s -b $clientip $subnet_mask|sed s/.*=//)
[ -z "$broadcast_address" ] && broadcast_address=255.255.255.255
# we might have an idea of the dns server via preboot
dns_srv=$(getip 5)
[ -n "$dns_srv" ] && echo nameserver $dns_srv >/etc/resolv.conf;
echo -e "# ip configuration written by $0 script:\nclientip=$clientip\n\
subnet_mask=$subnet_mask\ngateway=$gateway\nserverip=$serverip\n\
broadcast_address=$broadcast_address" >>/etc/initramfs-setup
# set static ip address
ip addr add $clientip/$(ipcalc -s -p $clientip $subnet_mask|sed s/.*=//) \
broadcast $broadcast_address dev $nwif 2>/dev/null
ip route add default via $gateway 2>/dev/null
else
noipyet="yes"
fi
# get configuration data via dhcp (with vendor code identifier if present
# in ${vci} from kernel command line or initramfs-setup) ...
if [ -z "$nodhcp" ] ; then
( rundhcp ${vci}; echo "dhcp finished at $(sysup)" >/tmp/dhcp-done ) &
if [ -n "$noipyet" ] ; then
waitfor /tmp/dhcp-done 20000
. /tmp/confviadhcp
# by now there should be a proper ip configuration present
if [ -z "$clientip" -o -z "$subnet_mask" -o -z "$broadcast_address" ]
then error "$init_errdhcp"
else
{ ip addr add \
$clientip/$(ipcalc -s -p $clientip $subnet_mask|sed s/.*=//) \
broadcast $broadcast_address dev $nwif 2>/dev/null || \
error "$init_erripcfg"; }
# if gateway is available set it
[ -n $gateway ] && ip route add default via $gateway 2>/dev/null
fi
# fixme: to be checked!!
# else
# if [ -n "$file" -a "$srvproto" = "lbd" ] ; then
# error "$init_erripcfg" nonfatal
# else
# error "$init_erripcfg"
# fi
# fi
fi
fi
# check if serverip is set as variable @@@serverip@@@
sed "s,@@@serverip@@@,$serverip," -i /etc/initramfs-setup
[ $DEBUGLEVEL -eq 20 ] && echo "** finished ip config at $(sysup)"
# on some network adaptors we need to wait for the link to come up
dmesg | grep -q "link down" && for i in 1 1 1 1 ; do
dmesg | grep -q "link up" && break
[ $DEBUGLEVEL -ge 1 ] && echo "network: waited half a second for the \
link to come up" >>$LOGFILE
sleep $i
done
# ... or ldap if available (in background)
[ -n "$ldap" ] && ldapconf &
# ... or via (t)ftp/http file get (in background)
[ -n "$file" ] && fileget &
runinithook '25-have-ip-config'
## netconsole is disabled in the default config
# config_netconsole $clientip $oldnwif $nwif $serverip
# if root filesystem should be imported via local or a network block device
if [ -n "${bldmod}" ] ; then
# load block device driver(s) if needed
for module in ${bldmod} ; do
modprobe ${MODPRV} ${module} || error "$init_errbld"
done
[ -z "$bldrfst" ] && bldrfst=squashfs
bldhost=$(checkip $bldhost)
if [ $DEBUGLEVEL -eq 20 ] ; then
echo "** starting setup of ${bldmod} at $(sysup)"
else
echo "Stateless client using ${bldmod} on $bldhost:$bldport with $bldrfst"
fi
# fixme: check for fs in /proc/filesystems before trying to load the module
modprobe ${MODPRV} ${bldrfst} || error "$init_errbld" nonfatal
# for debugging: interface might not be properly up - check reachability
[ $DEBUGLEVEL -ge 1 ] && ping -c 1 -w 15 ${bldhost} >/dev/null 2>&1
case "${srvproto}" in
# network block device present in standard kernel
nbd)
RDEV=/dev/nbd0
waitfor "${RDEV}" 20000 || error "$init_nbddev"
i=0
# QUICKFIX: busybox version doesn't support "-persist" yet
# but default behaviour is comparable
# OLD CMD: while ! nbd-client $bldhost $bldport ${RDEV} -persist ; do
while ! nbd-client $bldhost $bldport ${RDEV} ; do
usleep 100000
i=$(($i + 1))
if [ $i -ge 1000 ] ; then
error "$init_nbds"; break
fi
done
usleep 100
echo deadline > /sys/block/nbd0/queue/scheduler
# echo "32" > /sys/block/nbd0/queue/read_ahead_kb
;;
# dnbd3 by Johann Latocha
dnbd3)
RDEV=/dev/dnbd0
waitfor "${RDEV}" 20000 || error "$init_nbddev"
i=0
vid=${bldopt%/*}
rid=${bldopt#*/}
echo "blkopt: $bldopt"
echo "vid: $vid"
echo "rid: $rid"
[ "x" == "x$bldport" ] || bldporrt="-p $bldport"
tryagain=1
while [ "x$tryagain" == "x1" ] ; do
dnbd3-client -h $bldhost $bldport -d ${RDEV} -v $vid -r $rid
usleep 10000
if [ "$(cat /sys/block/dnbd0/net/cur_server_ip)x" != "x" ]; then
tryagain=0
else
echo -n "retry: "
fi
done
sleep 1
;;
# dnbd2 by Vito Di Leo
dnbd2)
RDEV=/dev/vnbd0
waitfor "${RDEV}" 20000 || error "$init_nbddev"
# quickhack, should be read in from URI
echo 1 > /sys/block/vnbd0/config/vid
echo 1 > /sys/block/vnbd0/config/rid
# check for others in initramfs-setup and then kernel cmdline
rootfs="$(sed -n "/rootfs=/p" /etc/initramfs-setup| \
sed "s,rootfs=,,;s,\",,g") "
[ "$rootfs" = " " ] && \
rootfs="$(cat /proc/cmdline|sed "s,.*rootfs=\",,;s,\".*,,") "
i=0
# assume no more than 16 different dnbd2 servers (default 4)
while [ "x$bldhost" != "x" -a $i -lt 16 ]; do
#echo "I: $i R: $rootfs P:$bldport H:$bldhost"
echo $bldhost $bldport > /sys/block/vnbd0/server${i}/sock
i=$(($i + 1))
rootfs=${rootfs#* }
bldsp=$(echo ${rootfs}|sed "s, .*,,")
bldhost=$(uri_token $bldsp server)
bldport=$(uri_token $bldsp port)
done
# the cfq scheduler seem not a good idea here
echo deadline > /sys/block/vnbd0/queue/scheduler
# needed for some reason to settle initialization
sleep 1
i=0
while [ $(cat /sys/block/vnbd0/config/running) != 1 ] ; do
usleep 100000
echo 1 > /sys/block/vnbd0/config/running
i=$(($i + 1))
if [ $i -ge 50 ] ; then
error "$init_dnbd2s"; break
fi
done
echo "64" > /sys/block/vnbd0/queue/read_ahead_kb
;;
# dnbd by Thorsten Zitterell
dnbd)
# quickhack
RDEV=/dev/dnbd0
if [ -z $nodnbdcache ] ; then # variable not really used yet
mkdir /dnbd
mount -n -o 'size=20%' -t tmpfs tmpfs /dnbd
( cat /dev/zero > /dnbd/cache 2>/dev/null || echo "ok" >/tmp/cache ) &
clientopt="-c /dnbd/cache"
waitfor /tmp/cache 10000
fi
[ $(echo $bldhost|sed "s,\..*,,") -ge 224 ] && \
ip route add 224.0.0.0/4 dev $nwif
waitfor /dev/dnbd0 10000 || error "$init_nbddev"
echo "dnbd-client -b $bldhost -d $RDEV $clientopt"
while ! dnbd-client -b $bldhost -d $RDEV $clientopt ; do
usleep 10000
done
# problem with squashfs and cfq scheduler
echo noop > /sys/block/dnbd0/queue/scheduler
echo 0 > /sys/block/dnbd0/queue/read_ahead_kb
;;
lbd)
# using clients local block device (disk partition is to be specified
RDEV=/dev/$blddev
echo "$bldrfst" >>/etc/filesystems
realbldrfst=$bldrfst
# we might need to mount the base layer filesystem first before accessing
# e.g. a squashfs container file on it
bldrfst=auto
;;
esac
RWRO="ro"
if [ -n "${cowloop}" -a -x /bin/cowdev ] ; then
modprobe ${MODPRV} cowloop || {
error "$init_loadcow" nonfatal
unset cowloop; }
fi
if [ -n "${cowloop}" ] ; then
if [ -n "${unionfs}" -o -n "${aufs}" ] ; then
error "$init_cownobld"
unset unionfs aufs
fi
echo "Using Copy-on-Write block device for rw access"
mount -n -t tmpfs -o size=${cowsize} ramfs ${rwdir}
mkdir /dev/cow && mknod /dev/cow/ctl b 241 255
usleep 200
ln -s /dev/cowloop0 /dev/cow/0
# fixme - cowdev depending on blockdev choosen above ...
cowdev -a /dev/nbd0 ${rwdir}/nbd.cow
usleep 200
RWRO="rw"
RDEV=/dev/cow/0
# run ldconfig if not switched off via kernel command line
ldcfg
else
# use normal UnionFS behaviour because rootfs is not NFS
unset nfsro
fi
# finally mount the configured network/local block device
for i in 0 5000 20000 100000 500000 1000000 ; do
usleep $i
mount -n -t $bldrfst -o $RWRO $RDEV /mnt 2>/dev/null && break
done
# check if we got the rootfilesystem directly or need to mount a container
# file from the mounted block device
if [ "${srvproto}" = "lbd" -a -f /mnt/boot/${slxconf_system_name} ]; then
mkdir /dev/bootdisk
mount --move /mnt /dev/bootdisk
mount -t ${realbldrfst} -o loop \
/dev/bootdisk/boot/${slxconf_system_name} /mnt || error "$init_errloop"
fi
[ $DEBUGLEVEL -eq 20 ] && echo "** finished blockdev setup stuff at $(sysup)"
elif [ -n ${iscsiserver} ] ; then
[ $DEBUGLEVEL -eq 20 ] && echo "** started setting up iSCSI initiator at \
$(sysup)"
#if [ -n ${iscsitarget} ] ; then
# echo "InitiatorName=${iscsitarget}"|sed "s,@@@serverip@@@,$serverip," \
# >/etc/initiatorname.iscsi
#else
# discovery
#fi
#echo -e "node.startup = automatic">/etc/iscsid.conf
#iscsid -c /etc/iscsid.conf
# the cowloop part has to be moved (option for iscsi devices too)
# and should be generalized for nbd, dnbd, iscsi
fi
# if no type of root filesystem is passed via kernel command line try
# information gathered from dhcp process (only valid for nfs)
if [ -z "${bldmod}" -a -z "${bldhost}" -a -z "${nfsserver}" ] ; then
# information has to be read from dhcp and ldap configuration
# cfgcomplete merges all configuration files
cfgcomplete
fi
# mount nfs rootfs
if [ -z "${bldmod}" -a -z "${bldserver}" ] ; then
[ $DEBUGLEVEL -eq 20 ] && echo "** started nfs mount"
# read in extended initramfs-setup
. /etc/initramfs-setup
# prefer nfsserver and nfspath from kernel commandline over the information
# gotten from dhcp server
if [ -n "${nfsserver}" -a -n "${nfspath}" ] ; then
# check if nfsserver is set as variable @@@serverip@@@
nfsserver=$(checkip $nfsserver)
else
# we got a problem here
error "$init_nfssp" fatal
fi
# interface might not be properly up - check reachability
ping -c 1 -w 15 ${nfsserver} >/dev/null 2>&1
# mount the rootfs via nfs readonly (ro)
fsmount nfs ${nfsserver} ${nfspath} /mnt ro
#for transport in tcp udp fail; do
# [ $proto = "fail" ] && { error "$init_nfs"; break; }
# mount -n -t nfs -o ro,nolock,${transport} ${nfsroot} /mnt && break
#done
[ $DEBUGLEVEL -eq 20 ] && echo "** finished nfs mount at $(sysup)"
fi
runinithook '35-have-network-root'
# get the complete collection of kernel modules and firmwares available
testmkd /lib/firmware
mount -n --bind /mnt/lib/modules /lib/modules && \
mount -n --bind /mnt/lib/firmware /lib/firmware || error "$init_moddir"
# start hardware configuration as background process if not a special
# debuglevel (21) is used for the option of manual hwautocfg start
if [ ${DEBUGLEVEL} = 21 ] ; then
echo "You can run 'hwautocfg main &' manually now ..."
/bin/sh
else
[ $DEBUGLEVEL -eq 20 ] && echo "** started hwautocfg in background at \
$(sysup)"
hwautocfg main &
fi
runinithook '40-started-hw-config'
# unionfs/aufs modules visible by now if installed or directly compiled into
# the kernel, try to use aufs for rw access if available
union_type=""
if [ ${aufs} -eq 1 ]; then
aufs_in_kernel=$(grep -c aufs /proc/filesystems)
if [ ${aufs_in_kernel} -eq 0 ]; then
modprobe ${MODPRV} aufs 2>/dev/null
aufs_have_module=$(lsmod | grep -ce "^aufs")
[ ${aufs_have_module} -ne 0 ] && union_type="AUFS"
else
union_type="AUFS"
fi
fi
if [ -z ${union_type} ] && [ ${unionfs} -eq 1 ]; then
unionfs_in_kernel=$(grep -c unionfs /proc/filesystems)
if [ ${unionfs_in_kernel} -eq 0 ]; then
modprobe ${MODPRV} unionfs 2>/dev/null
unionfs_have_module=$(lsmod | grep -ce "^unionfs")
[ ${unionfs_have_module} -ne 0 ] && union_type="UnionFS"
else
union_type="UnionFS"
fi
fi
if [ -z ${union_type} ] && [ ${fuse} -eq 1 ]; then
fuse_in_kernel=$(grep -c fuse /proc/filesystems)
if [ ${fuse_in_kernel} -eq 0 ]; then
modprobe ${MODPRV} fuse 2>/dev/null
fuse_have_module=$(lsmod | grep -ce "^fuse")
[ ${fuse_have_module} -ne 0 ] && union_type="Fuse"
else
union_type="Fuse"
fi
fi
if [ -z ${union_type} ]; then
if [ ${fuse} -eq 0 -a ${aufs} -eq 0 -a ${unionfs} -eq 0 -a -z "${cowloop}" ] ; then
error "$init_deselau" nonfatal
unset fuse aufs unionfs
else
error "$init_loadaufs" nonfatal
unset aufs unionfs
fi
fi
# runtimer
[ $DEBUGLEVEL -eq 8 -o $DEBUGLEVEL -eq 20 ] && \
echo "** Filesystem setup started at $(sysup)"
# setup of client root filesystem dependent on the availability of UnionFS
if [ "x${union_type}" != "x" ] ; then
echo "Using ${union_type} for rw access"
mkdir -p ${rwdir}/union ${rwdir}/uniontmp /rorootfs
# adapting tempfs size of the device directory (takes /tmp in stage4)
mount -o remount,size=${tmpfssize} ${devdir}
mount -n -t tmpfs -o size=${tmpfssize} none ${rwdir}/uniontmp
# hack for handling unionfs with patched run-init
mount -n --move /mnt /rorootfs
if [ "$union_type" == "UnionFS" ]; then
mount -n -t unionfs -o dirs=${rwdir}/uniontmp:/rorootfs=${nfsro}ro \
none /mnt
mkdir -p /mnt/uniontmp
mount -n --move ${rwdir}/uniontmp /mnt/uniontmp
chmod 0755 /mnt/uniontmp /mnt
elif [ "$union_type" == "AUFS" ]; then
mount -n -t aufs -o br:/${rwdir}/uniontmp:/rorootfs=ro none /mnt
mkdir -p /mnt/uniontmp
mount -n --move ${rwdir}/uniontmp /mnt/uniontmp
chmod 0755 /mnt/uniontmp /mnt
elif [ "$union_type" == "Fuse" ]; then
mkdir -p /tmp/union/rorootfs /tmp/union/uniontmp
mount -n --move /rorootfs /tmp/union/rorootfs
mount -n --move ${rwdir}/uniontmp /tmp/union/uniontmp
unionfs -o cow,max_files=32768,allow_other,use_ino,suid,dev \
-o nonempty,chroot=/tmp/union \
/uniontmp=RW:/rorootfs=RO /mnt
fi
# running hardware disk/tmp setup now
hwautocfg disk &
# run ldconfig if switched on via kernel command line (token ldsc) or
# triggered by unionized root filesystem
ldcfg
elif [ -z "${cowloop}" ] ; then
# fire up hardware disk/tmp setup first
hwautocfg disk &
echo "Using bind mounts to ramdisk for rw access"
mount -n -t tmpfs -o size=75% ramfs ${rwdir}
for path in ${D_BINDMPTS} ; do
mkdir -p ${rwdir}/${path} >/dev/null 2>&1
mount -n --bind ${rwdir}/${path} /mnt/${path}
[ ${DEBUGLEVEL} -gt 1 -a ${DEBUGLEVEL} != 8 ] && \
echo "Created ${rwdir}/${path} and mounted it to /mnt/$path"
done
# see above ...
ldcfg
# save the RO directories mentioned in the distro-specific
# config to a temporary directory. They will later on be restored
for path in ${D_RODIRSINRW}; do
if [ -d /mnt/${path} ] ; then
list="${path} ${list}"
# exclude them from etc copy process too
echo "${path}/*"|sed -e "s,/root/,,;s,^/,," >>/tmp/etc.exclude
mkdir -p /root/${path} >/dev/null 2>&1
mount -n --bind /mnt/${path} /root/${path} >/dev/null 2>&1
fi
done
for path in /etc/${D_SYSCONFDIR} ${D_DIRINBINDMNT} ${list}; do
mkdir -p ${rwdir}/${path}
done
testmkd ${rwdir}/var/tmp 1777
# exclude all sysv runlevel link stuff
for i in ${D_RCDIRS} ${D_INITBOOTD} ; do
echo "*$i/*" >>/tmp/etc.exclude
done
# add list of files to be excluded and common excludes to the filter list
echo -e "-\ndhcp*\n*~\n*.old\n*-\nxorg.conf*" >>/tmp/etc.exclude
# if ld.so.cache is to be generated then do not copy the file
[ -n "${ldsc}" ] && echo -e "ld.so.cache*" >>/tmp/etc.exclude
# for tar exclude lists might be used, more difficult for cp
cd /mnt
tar -X /tmp/etc.exclude -cp etc/*|tar -xp -C ${rwdir} 2>/dev/null
cd /
mount -n --bind ${rwdir}/etc /mnt/etc
mount -n --bind ${rwdir}/var /mnt/var
# get the "covered" mounts back into filesystem structure
for path in ${list}; do
mount -n --move /root/$path /mnt/$path #>>$LOGFILE 2>&1
done
#rm -rf /root/* >/dev/null 2>&1
# run some specific stuff !?
fi
runinithook '50-have-layered-fs'
# generate a set of default directories
. /etc/openslx.conf
for dir in $OPENSLX_DEFAULT_LOGDIR $OPENSLX_DEFAULT_BINDIR \
$OPENSLX_DEFAULT_LIBDIR $OPENSLX_DEFAULT_VIRTDIR; do
testmkd /mnt/$dir
done
chmod -R 1777 /mnt/${OPENSLX_DEFAULT_LOGDIR}
# script for stuff to execute during early bootup
d_mkrlscript init boot.slx "Running configuration postponed from InitRamFS"
echo "fs complete at $(sysup)" >/tmp/fscmpl
# runtimer
[ $DEBUGLEVEL -eq 8 -o $DEBUGLEVEL -eq 20 ] && \
echo "** Filesystem setup completed at $(sysup)"
# write debug file information after filesystem setup completed
echo -e "# /etc${D_SYSCONFDIR}/logfile - file created by $0 (initramfs \
from $date)\n#\n# logfile \
for linux diskless client specific debugging output\nLOGFILE=\"$LOGFILE\"\n#\
\n# debug level\nDEBUGLEVEL=\"$DEBUGLEVEL\"" \
> /mnt/etc/${D_SYSCONFDIR}/logfile || error "$init_errlog"
# run distribution independent and dependent configuration of files and
# services (offer debug shell in runlevel 22)
if [ ${DEBUGLEVEL} = 22 ] ; then
/bin/sh
else
servconfig &
fi
for path in @@@COMDIRINDXS@@@ ${D_DIRINDXS} ${D_DIRINBINDMNT} ; do
testmkd /mnt/${path}
done
# Needed writable subdirs nested in readonly subdirs of writable one
for path in ${D_RWDIRSINRO}; do
mount -n -t tmpfs none /mnt/${path}
done
for i in /var/run/utmp /var/log/wtmp /var/log/lastlog /etc/mtab ; do
echo -n > /mnt/$i
done
chown 65534:0 /mnt/var/lib/nobody
echo -e "# /etc/fstab - file generated by $0 (initramfs from $date)\n#\
\tOpenSLX Project, info@openslx.com\n\nrootfs\t\t/\t\trootfs\t\tro\t\t 0 0\n\
proc\t\t/proc\t\tproc\t\tdefaults\t 0 0\ninitramdevfs\t/dev\t\tdevtmpfs\
\trw\t\t 0 0\ndevpts\t\t/dev/pts\tdevpts\t\tmode=0620,gid=5\t 0 0" \
>/mnt/etc/fstab || error "$init_fstab"
echo -e "rootfs / rootfs rw 0 0\ninitramdevs /dev tmpfs rw\
0 0" > /mnt/etc/mtab
# copy library cache if generated
if [ -n "${ldsc}" ] ; then
# creating library cache takes a while ...
if waitfor /tmp/ldcfg 50000 ; then
test -s /mnt/tmp/ld.so.cache && \
mv /mnt/tmp/ld.so.cache /mnt/etc/ld.so.cache
else
error "$init_errldcfg"
fi
else
[ $DEBUGLEVEL -gt 2 ] && error "$init_infldcfg" nonfatal
fi
runinithook '60-have-servconfig'
# wait a while for hardware setup to complete and start cleanup procedure
[ $DEBUGLEVEL -gt 1 ] && echo "Waiting for hwautocfg to finish ..."
waitfor /tmp/hwcfg 20000 || error "$init_errhw"
hwautocfg finish &
# wait a while for services setup to complete
[ $DEBUGLEVEL -gt 1 ] && echo "Waiting for servconfig to finish ..."
waitfor /tmp/svcfg 10000 || error "$init_errsw"
# IP configuration is complete and should not be updated automatically
killall -9 udhcpc 2>/dev/null
# if uniondirs is not set yet, maybe the unions were given via initramfs-setup
if [ -z "$uniondirs" ]; then
if [ "$union_type" == "AUFS" ]; then
# does it contain "://"?
if [ "$aufs" != "${aufs#*://}" ]; then
uniondirs="$aufs"
fi
elif [ "$union_type" == "UnionFS" ]; then
# does it contain "://"?
if [ "$unionfs" != "${unionfs#*://}" ]; then
uniondirs="$unionfs"
fi
fi
fi
# if locations are given that should be unioned with the fs root, do it
if [ -n "$uniondirs" ]; then
include_in_fsroot_union "$union_type" "$uniondirs"
fi
runinithook '70-before-plugins'
# ddcinfo temporary overwrite (with kernel cmdline ddcinfo=1)
if [ "${ddcinfo}" = "1" -a -f /initramfs/plugin-conf/xserver.conf ]; then
echo 'xserver_ddcinfo="1"' >> /initramfs/plugin-conf/xserver.conf
fi
# runtimer
[ $DEBUGLEVEL -eq 8 -o $DEBUGLEVEL -eq 20 ] && \
echo "** Plugin configuration started at $(sysup)"
# check for any plugin-specific runlevel scripts and run them, if found:
if [ ${DEBUGLEVEL} = 25 ] ; then
/bin/sh
else
if [ -d /etc/plugin-init.d ]; then
for plugin_starter in /etc/plugin-init.d/*.sh; do
if [ -e $plugin_starter ]; then
[ $DEBUGLEVEL -gt 0 ] \
&& echo -n "Running plugin starter $plugin_starter ..."
[ $DEBUGLEVEL -eq 15 ] \
&& sed '/^#!/ a\\set -x' -i $plugin_starter
init-wrapper $plugin_starter >>/tmp/plugin_starter 2>&1
if [ $? -eq 0 ]; then
[ $DEBUGLEVEL -gt 0 ] \
&& echo " ok"
else
[ $DEBUGLEVEL -gt 0 ] \
&& echo " failed"
fi
fi
done
# load variables defined by plugins to current environment
[ -f /tmp/env/wrapper.env ] && . /tmp/env/wrapper.env
fi
fi
runinithook '80-after-plugins'
# runtimer
[ $DEBUGLEVEL -eq 8 -o $DEBUGLEVEL -eq 20 ] && \
echo "** Plugin configuration finished at $(sysup)"
# create links for initial stage4 boot scripts
initial_boot
runinithook '85-have-initial-boot'
# post init for some distro specific stuff to run
postinit
# general postinit.local configurable by the admin via openslx/config/<system>
if [ -f /initramfs/postinit.local ]
then
[ $DEBUGLEVEL -gt 0 ] \
&& echo -n "Running script /initramfs/postinit.local ... "
chmod u+x /initramfs/postinit.local
/initramfs/postinit.local
[ $DEBUGLEVEL -gt 0 ] && echo "ok"
elif [ -f /bin/postinit.local ]
then
[ $DEBUGLEVEL -gt 0 ] \
&& echo -n "Running script /bin/postinit.local ... "
chmod u+x /bin/postinit.local
/bin/postinit.local
[ $DEBUGLEVEL -gt 0 ] && echo "ok"
fi
# start a debug shell in higher debug levels
[ $DEBUGLEVEL -gt 2 -a $DEBUGLEVEL != 8 ] \
&& echo "DEBUGLEVEL>2: starting debug-shell, exit with CTRL+D" && /bin/sh
runinithook '90-postinit-done'
# unmount the bind mounted modules, firmware directories and nfs /tmp/scratch
# (if present)
export ticks
for ticks in 0 1 2 5 10 20 30; do
sleep $ticks && umount -n /lib/modules 2>/dev/null && break
error "$init_wait" nonfatal
done
for ticks in 0 1 2 5 10 20 30; do
sleep $ticks && umount -n /lib/firmware 2>/dev/null && break
error "$init_wait" nonfatal
done
mount 2>/dev/null | grep -q "/tmp/scratch type nfs" && \
for ticks in 0 1 2 5 10 20 30; do
sleep $ticks && umount -n /tmp/scratch 2>/dev/null && break
done
mount 2>/dev/null | grep -q /lib/modules && error "$init_errumnt"
# close runlevel script for stuff to execute during early bootup
d_mkrlscript close boot.slx ""
# put /tmp into stage4 mtab and add stuff to stage4 fstab
sed -n "s,/mnt,,;/\/tmp /p" /proc/mounts >> /mnt/etc/mtab
[ -f /tmp/fstab ] && cat /tmp/fstab >> /mnt/etc/fstab
# preparations to leave initramfs - umounting ...
umount -n /sys || error "$init_errsys" nonfatal
chmod 1777 /dev/shm /mnt/tmp 2>/dev/null
runinithook '95-cleanup'
# kill hwautocfg, servconfig, hwinfo, syslogd, etc.
killall -9 hwautocfg servconfig debugshell hwinfo syslogd logread 2>/dev/null
# runtimer
[ $DEBUGLEVEL -eq 8 -o $DEBUGLEVEL -eq 20 ] && \
echo "** SLX init ended near $(sysup)"
# kill the watchdog (autopoweroff, if stage3 init never finishes)
[ -f /tmp/watchdogpid ] && kill $(cat /tmp/watchdogpid) 2>/dev/null
# stop logging services if required and move logfile into stage4 filesystem
# (if exists)
killall klogd 2>/dev/null
[ -f /var/log/slx-boot.log ] && mv /var/log/slx-boot.log \
/mnt/var/log/slx-s3boot.log
[ -f /var/log/messages ] && cp /var/log/messages \
/mnt/var/log/slx_messages 2>/dev/null
# if no syslog plugin was configured, start the daemon again writing to no
# logfile directly (useless fake test as placeholder)
# THIS IS NOT WORKING SOMEHOW!!
#[ ! -d /mnt/opt/openslx/plugin-repo/syslog/ ] && syslogd -O /mnt/var/log/testfile
# move /dev and unmount /proc and unset all old, unneeded environment
# variables
mount -n --move /dev /mnt/dev
mkdir -p /mnt/run
mount -n --move /run /mnt/run
umount -n /proc
unset client debug date initrd ip bldroot macaddr nwif nfsroot rootfs ticks \
vci vga
unset BOOT_IMAGE KCMDLINE KERNEL MODPRV NWMODULES OLDPWD UDEVD_EVENT_TIMEOUT \
SLXVERSION UDEVD_EXPECTED_SEQNUM PATH
runinithook '99-handing-over'
# new style of pivoting (switch_root or run-init)
# Ubuntu Upstart is a nasty mess, enable debugging from level 4 and above
exec /sbin/switch_root -c dev/console /mnt /sbin/init $DEBUG_UPSTART || \
error "$init_runinit"