diff options
Diffstat (limited to 'rescue/tree/ka/install.sh')
-rwxr-xr-x | rescue/tree/ka/install.sh | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/rescue/tree/ka/install.sh b/rescue/tree/ka/install.sh new file mode 100755 index 000000000..ee93c1e19 --- /dev/null +++ b/rescue/tree/ka/install.sh @@ -0,0 +1,641 @@ +#!/bin/bash + +# this script is run by at startup on the nfs_root system, and runs the ka-deploy client +# it also updates the 'step file' on the tftp server + +# $Revision$ +# $Author$ +# $Date$ +# $Header$ +# $Id$ +# $Log$ +# Revision 1.4 2005/08/28 21:38:32 oblin +# ka support (initially from Antoine Ginies and Erwan Velu) +# +# Revision 1.1.2.5 2003/06/17 06:34:33 erwan +# Removing remaining dchp cache for KA +# +# Revision 1.1.2.4 2003/06/11 18:04:28 erwan +# Fixing mkreiserfs call +# +# Revision 1.1.2.3 2002/11/07 15:10:52 erwan +# SCSI support now activated +# +# Revision 1.1.2.2 2002/11/05 15:49:13 erwan +# added some files +# +# Revision 1.1.2.1 2002/11/05 11:16:54 erwan +# added ka tools in rescue +# +# Revision 1.6 2001/12/03 16:28:02 sderr +# Completely new install script +# +# Revision 1.5 2001/10/10 13:55:04 sderr +# Updates in documentation +# +# Revision 1.4 2001/06/29 09:31:45 sderr +# *** empty log message *** +# +# Revision 1.3 2001/05/31 08:51:43 sderr +# scripts/doc update to match new command-line syntax +# +# Revision 1.2 2001/05/03 12:34:41 sderr +# Added CVS Keywords to most files. Mostly useless. +# +# $State$ + +# This script is provided as an exmaple and should probably not be run as is + + +unset LANG +unset LANGUAGE + +# needed for some for i in foo* loops +shopt -s nullglob + +bash < /dev/tty2 >/dev/tty2 2>&1 & + +# IDEA : maybe this option could be overriden by a kaopt= in the kernel command line ? +KA_SESSION_BASE="-s kainstall" + +ka_call_num=0 + +inc_ka_session() +{ + (( ka_call_num++ )) + cur_ka_session=$KA_SESSION_BASE$ka_call_num +} + + +# testing ? -- NOT FULLY IMPLEMENTED !!!!!!!!!!!!!!!!!!!! +#DONTWRITE=yes +DONTWRITE=no + +# Let's find out what our IP is +ip=`/sbin/ifconfig | grep -v 127.0.0.1 | grep "inet addr" | sed 's/^.*inet addr:\([^ ]*\) .*$/\1/g' | head -n 1` + +# the file tftpserver should contain the name of the .. tftpserver +server=`cat tftpserver` + + +# reverse a file +tac() +{ + awk '{ x[NR] = $0 } END { for (i = NR; i >= 1; i--) print x[i] }' +} + +# run a command, hide its output and print OK if it suceeds, print FAILED and show the output otherwise. +runcom() +{ + echo -n "$1..." 1>&2 + shift; + out=`"$@" 2>&1` + ret=$? + if [ $ret -eq 0 ]; then + echo $C_S"OK"$C_N 1>&2 + else + echo $C_F"Failed"$C_N 1>&2 + echo $C_W"$out"$C_N 1>&2 + fi + return $ret + +} + +# 5 4 3 2 1 zero ignition +countdown() +{ + t=$1 + while [ "$t" -ne 0 ]; do + echo -n "$t " + sleep 1 + # move the cursor back + # I use now tr instead of sed because busybox's sed adds a non-wanted carriage return + # busybox's tr does not seem to know about the [: :] stuff (?) + echo -n "$t " | tr " 0-9" $'\x08' + (( t-- )) + done + # backspace only moves the cursor back, so at this point there's still a "1" to erase + if [ "$1" -ne 0 ] ;then + echo -n " "$'\x08\x08' + fi +} + + +int_shell() +{ + echo $C_H"starting an interactive shell"$C_N + exec /bin/bash +} + +fail() +{ + echo $* + echo $C_F"--- The installation program FAILED ---"$C_N + echo "Check your configuration -- try to read previous error messages" + echo "This machine is going to reboot (Ctrl-S to block it) (Ctrl-C for an interactive shell)" + trap int_shell SIGINT + countdown 30 + do_reboot +} + +do_reboot() +{ + reboot + sleep 1234567 # do not continue the install script (/sbin/reboot does not block) +} + + + +# ahem this LILO function should be fixed someday +# right now this function assumes there is a properly configured lilo on the duplicated linux system +do_lilo() +{ + + +chroot /mnt/disk << EOF +lilo +EOF + + +} + + +run_chroot_command() +{ + + /usr/sbin/chroot /mnt/disk $* + +} + + +log() +{ + echo $* 1>&2 + echo $* >> /tmp/ginstlog +} + +# version for the standard tftp client +std_tftp_put_file() +{ + remotef=$2 + localf=$1 + err=`echo put $localf $remotef | tftp $server 2>&1` + err=`echo $err | grep Sent` + if [ -z "$err" ]; then + log tftp error: could not get/put file + return 1 + fi + return 0 +} + +# version for the tftp client built in busybox +busybox_tftp_put_file() +{ + remotef=$2 + localf=$1 + err=`tftp -p -l $localf -r $remotef $server 2>&1` + if [ $? -ne 0 ]; then + log tftp error: could not get/put file $err + return 1 + fi + return 0 +} + + +busybox_tftp_get_file() +{ + remotef=$1 + localf=$2 + err=`tftp -g -l $localf -r $remotef $server 2>&1` + if [ $? -ne 0 ]; then + log tftp error: could not get/put file $err + return 1 + fi + return 0 +} + + +std_tftp_get_file() +{ + remotef=$1 + localf=$2 + err=`echo get $remotef $localf | tftp $server 2>&1` + err=`echo $err | grep Received` + if [ -z "$err" ]; then + echo tftp error: could not get/put file + return 1 + fi + return 0 +} + +tftp_get_file() +{ + busybox_tftp_get_file "$@" +} + +tftp_put_file() +{ + busybox_tftp_put_file "$@" +} + +# write a string ($2) in a remote file ($1) +tftp_put_in() +{ + echo "$2" > $temp + err=`echo put $temp "$1" | tftp $server 2>&1` + rm -f $temp + err=`echo $err | grep Sent` + if [ -z "$err" ]; then + log tftp error: could not get/put file + return 1 + fi + return 0 +} + +get_var_bis() +{ + while read a; do + echo "$a" | grep -s -q "^ *#.*" + if [ $? -eq 0 ]; then + continue + fi + val=`echo "$a" | sed 's/[^"]*"\(.*[^\\]\)".*/\1/'` + var=`echo "$a" | sed 's/[^"]*".*[^\\]" *\$\([^ ]*\)/\1/'` + if [ "$var" = "$1" ]; then + echo $val + return 0 + fi + done + return 1 +} + +# fetch variable $2 from file $1 +get_var() +{ + (cat $1; echo) | get_var_bis $2 +} + +# find the current step in the kernel command line +get_step() +{ + step=install +# step=`cat /proc/cmdline | sed 's/.*kastep=\([^ ]*\).*/\1/'` + if [ "$step" ]; then + echo $step > /tmp/step + return 0 + fi + return 1 +} + + +# write a new file on the tftp server +# this file is a pxelinux config file +# do this by getting the 'template file' and adding a DEFAULT at the beginning +set_step() +{ + step=$1 + + + runcom "Getting template file" tftp_get_file "ka/pxelinux.cfg/template" /tmp/template || return 1 + + echo DEFAULT $step > /tmp/newcfg + cat /tmp/template >> /tmp/newcfg + + runcom "Sending back new pxelinux config file" tftp_put_file /tmp/newcfg "ka/pxelinux.cfg/IP/$ip" || return 1 + + return 0 +} + + + +# the mount_partition calls must be done in the same shell (NOT a subshell) because the global variable below has to be updated +# idea : maybe use a file instead of this variable (and since the tac function now exists, why not ?) +mounted_fs="" + +# mount a partition UNDER /disk !!! (/disk is prepended to $2) +mount_partition() +{ + dev=$1 + point=$2 + + echo -n "Mounting $C_H$1$C_N as /mnt/disk$C_H$point$C_N" + mkdir -p /mnt/disk$point + test -d /mnt/disk$point || return 1 + runcom "..." mount $dev /mnt/disk/$point || return 1 + mounted_fs="$dev $mounted_fs" + return 0 +} + +# umount all mounted partitions under /disk, in the reverse order +umount_partitions() +{ + for dev in $mounted_fs; do + retries=0 + while ! runcom "Umounting $dev" umount $dev ; do + sleep 3 + (( retries++ )) + if [ $retries -gt 3 ]; then + echo Failed too many times. giving up. + break + fi + done + done +} + + +# recreate excluded directories +# read stdin like this : u=rwx g=rwx o=rwx uid gid filename +recreate_dirs() +{ + while read line; do + declare -a fields + fields=( $line ) + file=/mnt/disk/${fields[5]} +# echo $file +# note : it is possible that the directory exists already, if it was a mount point +# we need to set the permissions/users anyway + mkdir -p $file +# echo chmod ${fields[0]},${fields[1]},${fields[2]} $file + chmod ${fields[0]},${fields[1]},${fields[2]} $file + # argl !! chmod o+t does not work with busybox's chmod ! + # we have to handle it alone + if echo ${fields[2]} | grep -q t; then + chmod +t $file + fi + chown ${fields[3]}.${fields[4]} $file + done +} + +make_partitions() +{ + # we must be in the partfiles directory + for file in partition_tab*; do + drive=`echo $file | sed 's/partition_tab//'` + cat $file | runcom "Writing partition table for $drive using sfdisk" /sbin/sfdisk /dev/$drive -uS --force || fail "error with sfdisk" + done + + for file in fdisk_commands*; do + drive=`echo $file | sed 's/fdisk_commands//'` + runcom "Cleaning hard drive" dd if=/dev/zero of=/dev/$drive bs=1M count=5 || fail "Can t clean drive$drive" + cat $file | runcom "Writing partition table for $drive using fdisk" fdisk /dev/$drive || fail "error with fdisk" + done + +} +checkDevEntries() +{ + if ! test -r /mnt/disk/dev/hda ; then + (cd /dev && tar c *) | (cd /mnt/disk/dev && tar x) + fi +} + +write_MBRs() +{ +# we must be in the partfiles directory also + for file in MBR*; do + drive=`echo $file | sed 's/MBR//'` + runcom "Writing new MBR for $drive" dd if=$file of=/dev/$drive bs=1 count=446 + done +} + + +# Colors +# Success +C_S=$'\033[1;32m' +# Failure +C_F=$'\033[1;31m' +# Warning +C_W=$'\033[1;33m' +# Normal +C_N=$'\033[0;39m' +# Hilight +C_H=$'\033[1;39m' + + +# Clear screen, fancy startup message. +echo $'\033'[2J$'\033'[H +echo "------| $C_H"Ka"$C_N |---- Install starting..." + +temp=/tmp/ginst + +# activate dma ? -- obsolete stuff I think +# runcom "Setting HD optimizations" hdparm -c1 -d1 -K1 $HD + +delay=0 + +if ! runcom "Getting step name" get_step; then + echo "Error: Could not get current step " + fail +else + step=`cat /tmp/step` +fi + +echo Next Server is `cat /ka/tftpserver` + +echo Current step for $ip is : \"$C_H$step$C_N\" + +echo -n "Finding install type : " +case $step in + shell) + echo No install, but interactive shell + ## drop the user to an interactive shell + exec /bin/bash + ;; + install) + install_type=install + nextstep=ready + echo Install Linux + ;; + test_install) + install_type=test_install + nextstep=ready + echo TEST TEST TEST + countdown 10 + echo Install Linux TEST + ;; +esac + + +if [ -z "$install_type" ]; then + echo FATAL : Could not recognize this step name + echo "Aborting... " + fail +fi + + + +# receive the partition table, fstab, etc from the source node +mkdir /tmp/partfiles +inc_ka_session +echo Current session is $cur_ka_session +runcom "Receiving partitions information" /ka/ka-d-client -w $cur_ka_session -e "( cd /tmp/partfiles && tar xvf - )" || fail + + + + +cd /tmp/partfiles +make_partitions + + +test -f /tmp/partfiles/streams || fail "Missing streams file" +first_stream=`cat /tmp/partfiles/streams | head -n 1` + +if [ "$first_stream" = linux ]; then + rcv_linux=yes +else + rcv_linux=no +fi + + + +#if we must receive a linux system, we need to format and mount the partitions +if [ $rcv_linux = yes ]; then + # format partitions + format_partitions() + { + while read line; do + declare -a fields + fields=( $line ) + + case ${fields[2]} in + reiserfs ) + runcom "Formatting ${fields[0]} as reiserfs" mkreiserfs -f ${fields[0]} || fail + ;; + jfs ) + runcom "Formatting ${fields[0]} as jfs" mkfs.jfs ${fields[0]} || fail + ;; + + xfs ) + runcom "Formatting ${fields[0]} as xfs" mkfs.xfs -f ${fields[0]} || fail + ;; + ext3 ) + runcom "Formatting ${fields[0]} as ext3" mkfs.ext2 -j ${fields[0]} || fail + ;; + ext2 ) + runcom "Formatting ${fields[0]} as ext2" mkfs.ext2 ${fields[0]} || fail + ;; + swap ) + runcom "Formatting ${fields[0]} as swap" mkswap ${fields[0]} || fail + ;; + esac + done + } + + format_partitions < /tmp/partfiles/pfstab + + + # mount the partitions + + mount_partitions() + { + while read line; do + declare -a fields + fields=( $line ) + + case ${fields[2]} in + reiserfs ) + mount_partition ${fields[0]} ${fields[1]} || fail + ;; + xfs ) + mount_partition ${fields[0]} ${fields[1]} || fail + ;; + jfs ) + mount_partition ${fields[0]} ${fields[1]} || fail + ;; + ext3 ) + mount_partition ${fields[0]} ${fields[1]} || fail + ;; + ext2 ) + mount_partition ${fields[0]} ${fields[1]} || fail + ;; + esac + done + } + + # NOTE + # I replaced cat truc | mount_partitions by mount_partitions < truc + # because in the former case mount_partitions runs in a subshell and the $mounted_fs value is lost + mount_partitions < /tmp/partfiles/pfstab + + echo ++++++++++++++++++++++++++ + mount + echo ++++++++++++++++++++++++++ + + delay=0 +else + delay=10 +fi + +if [ $DONTWRITE != yes ]; then + for stream in `cat /tmp/partfiles/streams`; do + if [ "$stream" = "linux" ]; then + # partitions already formatted/mounted, just copy now + # untar data from the master 'on the fly' + echo -n "Linux copy is about to start " + countdown $delay + echo + inc_ka_session + /ka/ka-d-client -w $cur_ka_session -e "(cd /mnt/disk; tar --extract --read-full-records --same-permissions --numeric-owner --sparse --file - ) 2>/dev/null" || fail + + runcom "Syncing disks" sync + echo Linux copy done. + echo Creating excluded directories + cat /tmp/partfiles/excluded | recreate_dirs + #echo Setting up networking + #/ka/setup_network.sh + #delay=10 + else + # maybe receive some raw partition dumps + echo Raw copy of $stream is about to start + countdown $delay + inc_ka_session + /ka/ka-d-client -w $cur_ka_session -e "dd of=$stream bs=65536" || fail + delay=10 + fi + done + + echo "Removing computing interfaces" + rm -f /mnt/disk/etc/sysconfig/network-scripts/ifcfg-eth1 >/dev/null 2>&1 + + echo "Removing duplicated dhcp cache" + rm -f /mnt/disk/etc/dhcpc/* >/dev/null 2>&1 + + echo "Writing modules.conf" + /usr/bin/perl /ka/gen_modules_conf.pl >/mnt/disk/etc/modules.conf + + echo "Writing modprobe.conf" + chroot /mnt/disk/ /sbin/generate-modprobe.conf >/mnt/disk/etc/modprobe.conf + + echo "Running mkinitrd" + /ka/make_initrd + + cd /tmp/partfiles + write_MBRs + + + if test -f /tmp/partfiles/command; then + checkDevEntries + command_to_run=`cat /tmp/partfiles/command` + runcom "Running $command_to_run" run_chroot_command "$command_to_run" + fi + +else + echo " I would run ka-deploy(s) and then lilo/mbr " + sleep 1 +fi + +# maybe there is a last dummy ka-deploy for synchronization +if test -f /tmp/partfiles/delay; then + sleep 1 + inc_ka_session + runcom "Waiting source node signal to end installation" /ka/ka-d-client -w $cur_ka_session -e "cat" || fail +fi + +umount_partitions + + +# Update the step file on the tftp server +#runcom 'Sending back new $step' set_step $nextstep || fail + +echo -n Rebooting... +countdown 3 +do_reboot |