#!/bin/bash #================ # FILE : linuxrc #---------------- # PROJECT : OpenSuSE KIWI Image System # COPYRIGHT : (c) 2006 SUSE LINUX Products GmbH. All rights reserved # : # AUTHOR : Marcus Schaefer # : # 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" = "";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