#!/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=$IFSexport 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_MOUNTexport PART_DEVexport PART_COUNT=0export PART_NUMBER=0export PART_NEED_EXTENDED=0export PART_NEED_FILL=0export NO_FILE_SYSTEM=0#======================================# Exports (Status)#--------------------------------------export SYSTEM_INTEGRITYexport SYSTEM_MD5STATUS#======================================# Functions#--------------------------------------. /include#======================================# Beautify Startup#--------------------------------------clearecho "Loading KIWI Boot-System..."echo "---------------------------"#======================================# 1) Mounting local file systems#--------------------------------------mountSystemFilesystems >/dev/null 2>&1closeKernelConsole#======================================# 2) Prepare module load support #--------------------------------------touch /etc/modules.conftouch /lib/modules/*/modules.dep#======================================# 3) run udevd#--------------------------------------udevStart#======================================# 4) Include proc/cmdline information#--------------------------------------includeKernelParametersif [ ! -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#======================================# 5) 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" fifi#======================================# 6) Setup network interface and DNS#--------------------------------------if [ $LOCAL_BOOT = "no" ];then setupNetworkfi#======================================# 7) 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" if ! ping -c 1 $TSERVER >/dev/null 2>&1;then Echo "TFTP Server: $TSERVER not found" Echo "Using: $DHCPSIADDR from dhcpcd-info" TSERVER=$DHCPSIADDR fifi#======================================# 8) Load configuration#--------------------------------------if [ $LOCAL_BOOT = "no" ];then CONFIG=/etc/config.netclient #====================================== # Connection/access check for TSERVER #-------------------------------------- while true;do Echo "Checking for config file: config.$DHCPCHADDR" 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 #====================================== # Check alternative config names #-------------------------------------- if test ! -s $CONFIG;then searchAlternativeConfig fi #====================================== # No config found register new client #-------------------------------------- if test ! -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]: " && \ read -t $NAME SYSALIAS fi fi hwinfo --all --log=hwinfo.$DHCPCHADDR >/dev/null echo "NCNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR echo "CRNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR echo "IPADDR=$IPADDR" >> hwtype.$DHCPCHADDR echo "ARCHITECTURE=$ARCH" >> hwtype.$DHCPCHADDR #======================================== # Try to get BIOS data if tools are there #---------------------------------------- if [ -f /sbin/posbios ];then HWBIOS=`/sbin/posbios -b` echo "HWBIOS=$HWBIOS" >> hwtype.$DHCPCHADDR HWTYPE=`/sbin/posbios -ms` echo "HWTYPE=$HWTYPE" >> hwtype.$DHCPCHADDR fi 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..." Echo "Checking for config file: config.$DHCPCHADDR" dhcpcd -n atftp -g -r KIWI/config.$DHCPCHADDR \ -l $CONFIG $TSERVER \ >/dev/null 2>&1 if test ! -s $CONFIG;then searchAlternativeConfig fi test -s $CONFIG || { Echo "Couldn't get image configuration" Echo "sleeping [60 sec]..." sleep 60 } done fi importFile < $CONFIGfi#======================================# 9) Load Device modules#--------------------------------------probeDevicesexport systemIntegrity="unknown"#======================================# 10) Is this a diskful station#--------------------------------------if [ $LOCAL_BOOT = "no" ];thenif [ ! -z "$PART" ] && [ -z "$NFSROOT" ] && [ -z "$NBDROOT" ];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 fififi#======================================# 11) Download network client image#--------------------------------------if [ -z "$NFSROOT" ] && [ -z "$NBDROOT" ];then 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 probeFileSystem $imageRootDevice 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 "Resize EXT2 filesystem to full partition space..." resize2fs -f -F -p $imageDevice Echo "Checking EXT2 filesystem..." e2fsck -f $imageDevice -y INITRD_MODULES="$INITRD_MODULES ext2" fi if test "$FSTYPE" = "ext3";then Echo "Resize EXT3 filesystem to full partition space..." resize2fs -f -F -p $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 doneelse #====================================== # 11.1) Check for NFS root #-------------------------------------- if [ ! -z "$NFSROOT" ];then IFS="," ; for i in $NFSROOT;do field=0 IFS=";" ; for n in $i;do case $field in 0) nfsRootServer=$n ; field=1 ;; 1) nfsRootDevice=$n ; field=2 esac done done Echo "Mounting NFS root system: $nfsRootServer:$nfsRootDevice..." imageRootDevice="-o nolock,rw $nfsRootServer:$nfsRootDevice" export UNIONFS_CONFIG="/dev/ram1,"$imageRootDevice",aufs" imageRootName="NFSRoot-System" systemIntegrity="clean" fi #====================================== # 11.2) Check for NBD root #-------------------------------------- if [ ! -z "$NBDROOT" ];then if ! modprobe nbd;then systemException "Failed to load network blk device module" "reboot" fi IFS="," ; for i in $NBDROOT;do field=0 IFS=";" ; for n in $i;do case $field in 0) nbdServer=$n ; field=1 ;; 1) nbdPort=$n ; field=2 ;; 2) nbdDevice=$n ; field=3 ;; 3) nbdswapPort=$n ; field=4 ;; 4) nbdswapDevice=$n ; field=5 esac done done if [ -z "$nbdDevice" ];then nbdDevice="/dev/nbd0" fi if [ -z "$nbdswapDevice" ];then nbdDevice="/dev/nbd1" fi if [ -z "$nbdswapPort" ];then nbdswapPort="9210" fi Echo "Mounting NBD root system: $nbdServer $nbdPort [$nbdDevice]..." if ! /usr/sbin/nbd-client $nbdServer $nbdPort $nbdDevice;then systemException "Failed to setup $nbdDevice device" "reboot" fi # /.../ # try to get swap from the server if we dont have # enough ram (less than 48M) # ---- min_ram=49152 real_ram=$(cat /proc/meminfo |grep MemTotal|tr -d " [a-z][A-Z]:") if [ ${real_ram} -lt ${min_ram} ];then Echo "NBD: memory is below required 48M" Echo "NBD: Mounting NBD swap: $nbdServer $nbdPort [$nbdDevice]..." if ! /usr/sbin/nbd-client $nbdServer $nbdswapPort $nbdswapDevice then systemException "Failed to setup $nbdswapDevice device" "reboot" fi /sbin/mkswap $nbdswapDevice || true /sbin/swapon $nbdswapDevice || true fi imageRootDevice=$nbdDevice probeFileSystem $imageRootDevice Echo "Filesystem of remote root system is: $FSTYPE" if test "$FSTYPE" = "squashfs";then export UNIONFS_CONFIG="/dev/ram1,"$imageRootDevice",aufs" fi imageRootName="NBDRoot-System" systemIntegrity="clean" fifi#======================================# 12) 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 fifi#======================================# 13) Mount OS image to /mnt#--------------------------------------if ! mountSystem;then systemException "Failed to mount root filesystem" "reboot"fi#======================================# 14) 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 if [ ! -z $KIWI_KERNEL ];then Echo "Import KIWI kernel file: $KIWI_KERNEL" atftp -g -r $KIWI_KERNEL -l /mnt/boot/vmlinuz \ $TSERVER \ >/dev/null 2>&1 fi 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 fifi#======================================# 15) send DHCP_RELEASE, reset cache#--------------------------------------if [ $LOCAL_BOOT = "no" ] && [ -z "$NFSROOT" ] && [ -z "$NBDROOT" ];then if test $systemIntegrity = "clean";then dhcpcd -k fifi#======================================# 16) Check if this is a split image#--------------------------------------if [ ! -z "$COMBINED_IMAGE" ] && [ -z "$NFSROOT" ] && [ -z "$NBDROOT" ]; 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#======================================# 17) check filesystem and kernels#--------------------------------------if [ $LOCAL_BOOT = "no" ];then if test $systemIntegrity = "clean";then probeFileSystem $imageRootDevice kernelList /mnt fifi#======================================# 18) make 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 /dev/shm/boot2 rm -rf /mnt/boot mv /dev/shm/boot2 /mnt/boot fifi#======================================# 19) Create system dependant files#--------------------------------------if [ $LOCAL_BOOT = "no" ];then if test $systemIntegrity = "clean";then setupDefaultFstab /config updateRootDeviceFstab /config $imageRootDevice if test ! -z $DISK;then updateSwapDeviceFstab /config ${DISK}1 updateOtherDeviceFstab /config setupBootLoaderGrub /mnt /config 1 ${DISK}2 NET ${DISK}1 setupKernelModules /config fi fifi#======================================# 20) If image is new, notify#--------------------------------------if [ $LOCAL_BOOT = "no" ];then if test $systemIntegrity = "clean"; then count=0 IFS="," ; for i in $IMAGE;do count=$(($count + 1)) field=0 IFS=";" ; for n in $i;do case $field in 0) field=1 ;; 1) imageName=$n ; field=2 ;; 2) imageVersion=$n; field=3 ;; 3) imageServer=$n ; field=4 ;; 4) imageBlkSize=$n esac done Echo "Notify of new image: image/$imageName" echo "image/$imageName" > bootversion.$DHCPCHADDR echo "$imageVersion" >> bootversion.$DHCPCHADDR atftp --option "blksize 1024" -p -l bootversion.$DHCPCHADDR \ -r upload/bootversion.$DHCPCHADDR $TSERVER >/dev/null 2>&1 rm -f bootversion.$DHCPCHADDR done fifi#======================================# 21) 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 fifiecho 256 > /proc/sys/kernel/real-root-dev#======================================# 22) umount system filesystems#--------------------------------------umountSystemFilesystems#======================================# 23) copy initrd files to image#--------------------------------------if [ -f /image/loader/message ];then mv /image/loader/message /mnt/bootficp /preinit /mntcp /include /mnt#======================================# 24) check if reboot is required#--------------------------------------kernelCheck /mnt#======================================# 25) Activate new root#--------------------------------------Echo "Activating Image: [$imageRootName]"/sbin/udevsettle --timeout=30mount --move /dev /mnt/devudevKillEcho "Calling preinit phase..."cd /mnt && exec < dev/console >dev/console 2>&1reopenKernelConsole/mnt/sbin/pivot_root . mnt >/dev/null 2>&1if test $? != 0;then PIVOT=false cleanInitrd && mount --move . / && chroot . ./preinit chroot . rm -f ./preinit chroot . rm -f ./include chroot . rm -rf ./imageelse PIVOT=true ./preinit rm -f ./preinit rm -f ./include rm -rf ./imagefi#======================================# 26) reboot system if specified#--------------------------------------if [ $LOCAL_BOOT = "no" ];then if test ! -z $REBOOT_IMAGE;then Echo "Rebooting System to activate new kernel..." /sbin/reboot -f -i >/dev/null 2>&1 fifi#======================================# 27) Unmount initrd / system init#--------------------------------------echo " "echo "Booting into final System..."echo "----------------------------"export IFS=$IFS_ORIGmount -n -o remount,rw / 2>/dev/nullif [ $PIVOT = "true" ];then exec umount -n -l /mntelse exec chroot . /sbin/init $@fi