#!/bin/bash
#================
# FILE : linuxrc
#----------------
# PROJECT : OpenSuSE KIWI Image System
# COPYRIGHT : (c) 2006 SUSE LINUX Products GmbH. All rights reserved
# :
# AUTHOR : Marcus Schaefer <ms@suse.de>
# :
# BELONGS TO : Operating System images
# :
# DESCRIPTION : This file is changed to become the real
# : linuxrc script which is used to prepare the
# : operating system for the main image
# :
# :
# STATUS : BETA
#----------------
#======================================
# Exports (General)
#--------------------------------------
export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
export IFS_ORIG=$IFS
export ARCH=`arch`
export DEBUG=0
#======================================
# Exports (Booting)
#--------------------------------------
export DOMURD_MODULES="xennet xenblk"
export INITRD_MODULES="reiserfs"
export LOCAL_BOOT="no"
export KERNEL_LIST
#======================================
# Exports (Alias)
#--------------------------------------
export SYSALIAS="undefined"
export NAME=0
#======================================
# Exports (Partitioning)
#--------------------------------------
export PART_FILE="/etc/partition.table"
export PART_MOUNT
export PART_DEV
export PART_COUNT=0
export PART_NUMBER=0
export PART_NEED_EXTENDED=0
export PART_NEED_FILL=0
export NO_FILE_SYSTEM=0
#======================================
# Exports (Status)
#--------------------------------------
export SYSTEM_INTEGRITY
export SYSTEM_MD5STATUS
#======================================
# Functions
#--------------------------------------
. /include
#======================================
# Beautify Startup
#--------------------------------------
clear
echo "Loading KIWI Boot-System..."
echo "---------------------------"
#======================================
# 1) Mounting local file systems
#--------------------------------------
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devpts devpts /dev/pts
closeKernelConsole
#======================================
# 2) Prepare module load support
#--------------------------------------
touch /etc/modules.conf
touch /lib/modules/*/modules.dep
#======================================
# 3) Include proc/cmdline information
#--------------------------------------
includeKernelParameters
if [ ! -z $IMAGE ];then
# /.../
# if the image information is already in place at this stage
# it comes from the cmdline data which means we are not booting
# from the network but want to boot the local system
# ----
LOCAL_BOOT="yes"
fi
#======================================
# 4) Obtain/load network module
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
loaded=0
probeNetworkCard
IFS=":"
for i in $networkModule;do
if [ ! -z $i ];then
modprobe $i 2>/dev/null
if test $? = 0;then
loaded=1
fi
fi
done
IFS=$IFS_ORIG
if test $loaded = 0;then
systemException \
"Network module: Failed to load network module !" \
"reboot"
fi
fi
#======================================
# 5) Setup network interface and DNS
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
setupNetwork
fi
#======================================
# 6) get TFTP Server IP/name
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
checkTFTP
if [ -z $TSERVER ];then
TSERVER=tftp.$DOMAIN
fi
Echo "Checking TFTP Server name: $TSERVER"
ip=`host $TSERVER | cut -f4 -d' '`
if test $ip = "found:" -o $ip = "out;";then
Echo "TFTP Server: $TSERVER not found"
Echo "Using: $DHCPSIADDR from dhcpcd-info"
TSERVER=$DHCPSIADDR
fi
fi
#======================================
# 7) Load configuration
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
CONFIG=/etc/config.netclient
while true;do
result=`atftp -g \
-r KIWI/config.$DHCPCHADDR -l $CONFIG $TSERVER 2>&1 | head -n 1`
status1=`echo $result | cut -f2 -d" "`
status2=`echo $result | cut -f6,7 -d" "`
if test "$status1" = "unknown";then
Echo -n "TFTP Server unknown, enter IP: " && read TSERVER
elif test "$status2" = "<Access violation>";then
Echo -n "TFTP access violation, enter IP: " && read TSERVER
else
break
fi
if test -z $TSERVER;then
TSERVER=$DHCPSIADDR
fi
done
if test $? != 0 -o ! -s $CONFIG;then
#======================================
# Register new network client
#--------------------------------------
Echo "Registering new network client..."
if test $NAME -ne 0;then
if test $NAME -eq -1;then
Echo -n "Enter Alias Name for this system: " && \
read SYSALIAS
else
Echo -n "Enter Alias Name [timeout in $NAME sec]: " && \
SYSALIAS=`/sbin/timed $NAME`
fi
fi
hwinfo --all --log=hwinfo.$DHCPCHADDR >/dev/null
echo "NCNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR
echo "ARCHITECTURE=$ARCH" >> hwtype.$DHCPCHADDR
atftp -p -l hwtype.$DHCPCHADDR \
-r upload/hwtype.$DHCPCHADDR $TSERVER >/dev/null 2>&1
atftp -p -l hwinfo.$DHCPCHADDR \
-r upload/hwinfo.$DHCPCHADDR $TSERVER >/dev/null 2>&1
echo
Echo "Registered as: $DHCPCHADDR"
Echo "Waiting for configuration..."
sleep 60
#======================================
# Try to get config again
#--------------------------------------
while test ! -s $CONFIG;do
Echo "Lookup network client config file again..."
dhcpcd -n
atftp -g -r KIWI/config.$DHCPCHADDR \
-l $CONFIG $TSERVER \
>/dev/null 2>&1
test -s $CONFIG || {
Echo "Couldn't get image configuration"
Echo "sleeping [60 sec]..."
sleep 60
}
done
fi
importFile < $CONFIG
fi
#======================================
# (8) Load Device modules
#--------------------------------------
probeDevices
export systemIntegrity="unknown"
#======================================
# 9) Is this a diskful station
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if [ ! -z $PART ];then
#======================================
# Check for installed system
#--------------------------------------
count=0
IFS="," ; for i in $IMAGE;do
case $count in
0) {
field=0
IFS=";" ; for n in $i;do
case $field in
0) imageDevice=$n ; field=1 ;;
1) imageName=$n ; field=2 ;;
2) imageVersion=$n; field=3
esac
done
count=1
updateNeeded initialize
if linuxPartition $DISK;then
mountSystem $imageDevice
updateNeeded
umountSystem
systemIntegrity=`getSystemIntegrity 1`
if [ $systemIntegrity = "fine" ];then
Echo "Base system is up to date, activating disk system..."
fi
else
systemIntegrity="clean"
fi
}
;;
*)
# handle other images here...
;;
esac
done
#======================================
# Create partition table if needed
#--------------------------------------
if test $systemIntegrity = "clean";then
Echo "Creating partition table..."
partitionCount
createSwap
createPartition
writePartitionTable $DISK
IFS=":" ; for i in $PART_DEV;do
if test ! -z "$i";then
createFileSystem $i
fi
done
mkswap ${DISK}1 >/dev/null 2>&1
fi
fi
fi
#======================================
# 10) Download network client image
#--------------------------------------
count=0
IFS="," ; for i in $IMAGE;do
imageZipped="uncompressed"
count=$(($count + 1))
field=0
IFS=";" ; for n in $i;do
case $field in
0) imageDevice=$n ; field=1 ;;
1) imageName=$n ; field=2 ;;
2) imageVersion=$n; field=3 ;;
3) imageServer=$n ; field=4 ;;
4) imageBlkSize=$n; field=5 ;;
5) imageZipped=$n ;
esac
done
if [ $count = 1 ];then
imageRootDevice=$imageDevice
imageRootName=$imageName
fi
if [ $count = 2 ];then
imageNextRootDevice=$imageDevice
fi
if [ $LOCAL_BOOT = "yes" ];then
continue
fi
if test `getSystemIntegrity $count` = "fine";then
continue
fi
imageName="image/$imageName-$imageVersion"
imageMD5s="$imageName.md5"
[ -z "$imageServer" ] && imageServer=$TSERVER
[ -z "$imageBlkSize" ] && imageBlkSize=8192
while true;do
# /.../
# get image md5sum to be able to check for the size
# requirements if we are loading into RAM
# ---
loadStatus=`atftp -g \
-r $imageMD5s -l /etc/image.md5 $imageServer 2>&1`
if ! loadOK "$loadStatus";then
systemException \
"Failed to load image MD5: $imageName -> no such image MD5" \
"reboot"
fi
IFS=" "
read sum1 blocks blocksize < /etc/image.md5
if test -z $DISK;then
if ! validateRAM;then
systemException \
"Not enough RAM available for this image" \
"reboot"
fi
else
if ! validateSize;then
systemException \
"Not enough space available for this image" \
"reboot"
fi
fi
validateBlockSize
# /.../
# now load the image into the imageDevice
# ---
multicast="-m"
if test "$imageZipped" = "compressed"; then
Echo "Compressed image found: Disable multicast download"
multicast=""
test ! -p /dev/compressed_image && mkfifo /dev/compressed_image
cat /dev/compressed_image | gzip -d > $imageDevice 2>/dev/null &
imageDevice_orig=$imageDevice
imageName_orig=$imageName
imageDevice="/dev/compressed_image"
imageName="$imageName.gz"
fi
Echo "Loading $imageName [$imageDevice BS:$imageBlkSize Byte]..."
loadStatus=`atftp $multicast --option "blksize $imageBlkSize" -g \
-r $imageName -l $imageDevice $imageServer 2>&1`
if ! loadOK "$loadStatus";then
systemException \
"Failed to load image: $imageName -> no such image" \
"reboot"
fi
if test "$imageZipped" = "compressed"; then
imageDevice=$imageDevice_orig
imageName=$imageName_orig
fi
# /.../
# check the md5sum of the downloaded data records
# ----
Echo "Download complete, checking data..."
dd if=$imageDevice count=$blocks bs=$blocksize 2>/dev/null |\
md5sum - > /etc/ireal.md5
read sum2 dumy < /etc/ireal.md5
if test $sum1 = $sum2;then
Echo "Image checksum test: fine :-)"
break
fi
Echo "Image checksum test failed:"
Echo "Possible reasons:"
echo
Echo -b "1) Physical ethernet connection lost:"
Echo -b " please check cable"
echo
Echo -b "2) Data corruption while loading the image:"
Echo -b " will give it a new try..."
echo
Echo -b "3) wrong checksum file created for the image:"
Echo -b " check with the md5sum command if the image on the"
Echo -b " TFTP server provides the same md5 sum as included"
Echo -b " within the appropriate .md5 file for this image"
echo
if test -z $DISK;then
Echo -b "4) ramdisk size is too small for the image:"
Echo -b " check the ramdisk_size parameter of the PXE"
Echo -b " configuration file on the TFTP server"
else
Echo -b "4) partition size is too small for the image:"
Echo -b " check the PART line in the image config file on the"
Echo -b " TFTP server"
fi
echo
Echo "Retry to load image..."
sleep 15
done
echo $imageDevice | grep -q ram
haveDataInRam=$?
if test ! -z $DISK && test $haveDataInRam != 0;then
mountSystem $imageRootDevice
readFileSystem /mnt/image/config.xml
umountSystem
if test "$FSTYPE" = "reiserfs";then
Echo "Resize Reiser filesystem to full partition space..."
resize_reiserfs $imageDevice
INITRD_MODULES="$INITRD_MODULES reiserfs"
fi
if test "$FSTYPE" = "ext2";then
Echo "Checking EXT2 filesystem..."
e2fsck -f $imageDevice -y
Echo "Resize EXT2 filesystem to full partition space..."
resize2fs -F -p $imageDevice
Echo "Checking EXT2 filesystem..."
e2fsck -f $imageDevice -y
INITRD_MODULES="$INITRD_MODULES ext2"
fi
if test "$FSTYPE" = "ext3";then
Echo "Checking EXT3 filesystem..."
e2fsck -f $imageDevice -y
Echo "Resize EXT3 filesystem to full partition space..."
resize2fs -F -p $imageDevice
Echo "Adding EXT3 journal..."
tune2fs -j $imageDevice
Echo "Checking EXT3 filesystem..."
e2fsck -f $imageDevice -y
INITRD_MODULES="$INITRD_MODULES ext3"
fi
fi
if test ! -z $DISK && test $haveDataInRam = 0;then
Echo "Including RAM device data to disk..."
RELOAD_CONFIG="yes"
mkdir -p /config
mountSystem
rm -rf /mnt/lost+found
cp -a /mnt/* /config && rm -f /mnt/*
umountSystem
fi
rm -f /etc/ireal.md5
rm -f /etc/image.md5
done
#======================================
# 11) Check for RELOAD_CONFIG
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test ! -z $DISK;then
if test ! -z $RELOAD_CONFIG;then
systemIntegrity_save=$systemIntegrity
systemIntegrity="clean"
fi
fi
fi
#======================================
# 12) Mount OS image to /mnt
#--------------------------------------
if ! mountSystem;then
systemException "Failed to mount root filesystem" "reboot"
fi
#======================================
# 13) Import fixed configuration files
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test $systemIntegrity = "clean";then
mkdir -p /config
#======================================
# Get files from CONF value
#--------------------------------------
IFS="," ; for i in $CONF;do
field=0
IFS=";" ; for n in $i;do
case $field in
0) configSource=$n ; field=1 ;;
1) configDest=$n ; field=2 ;;
2) configServer=$n ; field=3 ;;
3) configBlkSize=$n;
esac
done
Echo "Import configuration file: $configDest"
dirs=`dirname $configDest`
mkdir -p /config/$dirs
atftp --option "blksize $configBlkSize" -g \
-r $configSource -l /config/$configDest $configServer \
>/dev/null 2>&1
done
#======================================
# Check for KIWI_INITRD
#--------------------------------------
if [ ! -z $KIWI_INITRD ];then
Echo "Import KIWI initrd file: $KIWI_INITRD"
rm -f /mnt/boot/initrd* && mkdir -p /mnt/boot
atftp -g -r $KIWI_INITRD -l /mnt/boot/initrd \
$TSERVER \
>/dev/null 2>&1
KIWI_INITRD_PARAMS="IMAGE=\"$IMAGE\""
if [ ! -z $COMBINED_IMAGE ]; then
SPLIT="COMBINED_IMAGE=$COMBINED_IMAGE"
KIWI_INITRD_PARAMS="$KIWI_INITRD_PARAMS $SPLIT"
fi
if [ ! -z "$UNIONFS_CONFIG" ]; then
UNIONED="UNIONFS_CONFIG=$UNIONFS_CONFIG"
KIWI_INITRD_PARAMS="$KIWI_INITRD_PARAMS $UNIONED"
fi
fi
fi
fi
#======================================
# 14) send DHCP_RELEASE, reset cache
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test $systemIntegrity = "clean";then
dhcpcd -k
fi
fi
#======================================
# 15) Check if this is a split image
#--------------------------------------
if test ! -z $COMBINED_IMAGE; then
READ_ONLY_SYSTEM=system
mkdir -p /mnt/$READ_ONLY_SYSTEM && \
mount $imageNextRootDevice /mnt/$READ_ONLY_SYSTEM
cd /mnt
for dir in bin boot lib opt sbin usr;do
ln -s $READ_ONLY_SYSTEM/$dir $dir
done
cd /
fi
#======================================
# 16) check filesystem and kernels
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test $systemIntegrity = "clean";then
readFileSystem /mnt/image/config.xml
kernelList /mnt
fi
fi
#======================================
# 17) make kernel/initrd available on unionfs
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test ! -z "$UNIONFS_CONFIG" && test $systemIntegrity = "clean";then
# /.../
# have to do this so that /boot gets copied to the
# ext2 partition, which is necessary for grub to find
# the stuff in there (it can't read squashfs)
# ----
cp -a /mnt/boot /mnt/boot2
rm -rf /mnt/boot
mv /mnt/boot2 /mnt/boot
fi
fi
#======================================
# 18) Create system dependant files
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test $systemIntegrity = "clean";then
mkdir -p /config/etc
cat > /config/etc/fstab < /dev/null
if [ -z "$UNIONFS_CONFIG" ]; then
echo "$imageRootDevice / $FSTYPE defaults 0 0" > /config/etc/fstab
fi
echo "devpts /dev/pts devpts mode=0620,gid=5 0 0" >> /config/etc/fstab
echo "proc /proc proc defaults 0 0" >> /config/etc/fstab
echo "sysfs /sys sysfs noauto 0 0" >> /config/etc/fstab
echo "tmpfs /dev/shm tmpfs defaults 0 0" >> /config/etc/fstab
if test ! -z $DISK;then
# a) /etc/fstab...
# ----------------
echo "${DISK}1 swap swap pri=42 0 0" >> /config/etc/fstab
index=0
IFS=":" ; for i in $PART_MOUNT;do
if test ! -z "$i";then
count=0
IFS=":" ; for n in $PART_DEV;do
device=$n
if test $count -eq $index;then
break
fi
count=`expr $count + 1`
done
index=`expr $index + 1`
if test ! $i = "/" && test ! $i = "x";then
probeFileSystem $device
echo "$device $i $FSTYPE defaults 1 1" >> /config/etc/fstab
fi
fi
done
# b) /boot/grub/menu.lst...
# -------------------------
console=""
mkdir -p /config/boot/grub
echo "timeout 10" > /config/boot/grub/menu.lst
IFS="," ; for i in $KERNEL_LIST;do
if test ! -z "$i";then
kernel=`echo $i | cut -f1 -d:`
initrd=`echo $i | cut -f2 -d:`
menu=/config/boot/grub/menu.lst
echo "title $kernel" >> $menu
if [ $kernel = "vmlinuz-xen" ];then
echo " root (hd0,1)" >> $menu
echo " kernel /boot/xen.gz" >> $menu
echo -n " module /boot/$kernel" >> $menu
echo -n " root=${DISK}2 $console" >> $menu
echo " $KIWI_INITRD_PARAMS" >> $menu
echo " module /boot/$initrd" >> $menu
else
echo -n " kernel (hd0,1)/boot/$kernel" >> $menu
echo -n " root=${DISK}2 $console" >> $menu
echo " $KIWI_INITRD_PARAMS" >> $menu
echo " initrd (hd0,1)/boot/$initrd" >> $menu
fi
fi
done
# c) /etc/grub.conf...
# -------------------------
mkdir -p /config/etc
gconf=/config/etc/grub.conf
echo -en "root (hd0,1)\ninstall" > $gconf
echo -n " --stage2=/boot/grub/stage2" >> $gconf
echo -n " /boot/grub/stage1 d (hd0)" >> $gconf
echo -n " /boot/grub/stage2 0x8000" >> $gconf
echo " (hd0,1)/boot/grub/menu.lst" >> $gconf
echo "quit" >> $gconf
# d) /etc/sysconfig/kernel...
# ---------------------------
mkdir -p /config/etc/sysconfig
syskernel=/config/etc/sysconfig/kernel
echo "INITRD_MODULES=\"$INITRD_MODULES\"" > $syskernel
echo "DOMU_INITRD_MODULES=\"$DOMURD_MODULES\"" >> $syskernel
fi
fi
fi
#======================================
# 19) copy system dependant files
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test $systemIntegrity = "clean";then
cd /config
find . -type d | while read d ; do mkdir -p /mnt/$d ; done
find . -type f | while read f ; do cp $f /mnt/$f ; done
cd /
rm -rf /config
fi
fi
echo 256 > /proc/sys/kernel/real-root-dev
#======================================
# 20) umount system filesystems
#--------------------------------------
umount /dev/pts
umount /sys
umount /proc
#======================================
# 21) copy initrd files to image
#--------------------------------------
cp /preinit /mnt
cp /include /mnt
#======================================
# 22) Activate new root
#--------------------------------------
Echo "Activating Image: [$imageRootName]"
cd /mnt && exec < dev/console >dev/console 2>&1
Echo "Calling preinit phase..."
/mnt/sbin/pivot_root . mnt >/dev/null 2>&1
if test $? != 0;then
PIVOT=false
mount --move . / && chroot . ./preinit
chroot . rm ./preinit
chroot . rm ./include
else
PIVOT=true
./preinit
rm ./preinit
rm ./include
fi
#======================================
# 23) reboot system if specified
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
if test ! -z $REBOOT_IMAGE;then
Echo "Rebooting System to activate new kernel..."
/sbin/restart >/dev/null 2>&1
fi
fi
#======================================
# 24) Unmount initrd / system init
#--------------------------------------
echo " "
echo "Booting into final System..."
echo "----------------------------"
reopenKernelConsole
mount -n -o remount,rw / 2>/dev/null
if [ $PIVOT = "true" ];then
exec umount -n -l /mnt
else
exec chroot . /sbin/init
fi