#!/bin/bash
# -*-  indent-tabs-mode:nil;  -*- 
#
# Copyright (C) 2001-2008,2012-2014 Andreas Lang-Nevyjel
#
# Send feedback to: <lang-nevyjel@init.at>
#
# This file is part of cluster-backbone
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

BM_MESG="boot maintenance (stage2)"
PS_NORMAL="preparing normal mode"
PS_TEST="preparing test mode"
PS_RESCUE="preparing rescue mode"
JT_NORMAL="starting"
JT_TEST="starting test mode"
JT_RESCUE="starting rescue mode"
JT_CLEAN="starting clean mode"
PART_MESG="partitioning"
FORM_MESG="formatting"
MP_MESG="creating mountpoints"
UNP_MESG="unpacking"
INS_MESG="installing"
RSYNC_MESG="rsyncing"
RSYNC_REFRESH_MESG="rsyncing"
FIX_MESG="fixing directory structure"
PACK_MESG="installing packages"
COPY_CONF="copying config for"
INSTALL_KERNEL="installing new kernel"
GENERATE_INITRD="generating initrd"
START_SYSLOG="start syslog"
LILO_MSG="running lilo"
GRUB_MSG="running grub"
REBOOT_MSG="down to runlevel 6"
S2_DONE="stage2 finished"
MOUNT_STRING="mounting config"
# see hoststatus_zmq.c, stage1, stage2
HOSTSTAT_FILE=/conf/.hoststat

if [ true ] ; then
    BOLD="\033[1m"
    RED="\033[31m"
    GREEN="\033[32m"
    YELLOW="\033[33m"
    OFF="\033[m"
fi

[ ! -f /bin/sh ] && ln -s /bin/bash /bin/sh

basedir="new"

export LS_OPTIONS="-a -N --color=tty -T 0"
alias l='ls -alF'
alias la='ls -la'
alias ll='ls -l'
alias ls='ls $LS_OPTIONS'
alias ls-l='ls -l'
alias ..='cd ..'
alias ...='cd ../..'

RW_MOUNTOPTS="-o nolock,rw,tcp,rsize=8192,wsize=8192,noac,vers=3"
RO_MOUNTOPTS="-o nolock,ro,tcp,rsize=8192,wsize=8192,noac,vers=3"
MOUNT_RETRIES=10
MOUNT_SLEEP=30

export PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/cluster/bin:/opt/cluster/sbin

# modify reboot
cp -a /sbin/reboot /sbin/reboot.old
rm /sbin/reboot
echo "#!/bin/bash" > /sbin/reboot
echo "/sbin/reboot.old -f " >> /sbin/reboot
chmod +x /sbin/reboot

function start_shell() {
    echo "Starting /bin/bash" | logger -s
    mkdir -p /root
    alias > /root/.bashrc
    chmod 0540 /etc/shadow
    echo $motherserver > /root/.rhosts
    /bin/bash  2>&1
}

function reboot() {
    set_hoststat ${REBOOT_MSG}
    /sbin/sync
    /sbin/reboot -f
}

function set_hoststat() {
    [ "x$1" != "x-q" ] && \
        echo "setting hoststatus to "$@ || \
        shift
    [ ! -d /conf ] && mkdir /conf
    echo $@ > ${HOSTSTAT_FILE}
    t_mother $@
}

function t_mother() {
    if [ ${motherserver:-0} = "0" ] ; then
        echo -e "${READ}Server not set, can't connect to mother${OFF}"
    else
        tell_mother_zmq -i $ipaddr -m $motherserver -p 8000 "$@" || echo -e "${RED}Connection problem with mother${OFF}"
    fi
}

function send_info() {
    if [ ${motherserver:-0} = "0" ] ; then
        echo -e "Server not set, can't connect to mother"
    else
        tell_mother_zmq -i $ipaddr -m $motherserver -p 8000 -w "*$@" || echo -e "Connection problem with mother"
    fi
}

function copy_static_files() {
    echo -e "Copying static files"
    if [ -d /conf/static_files ] ; then
        flist=$(find /conf/static_files -type 'f' | cut -d "/" -f 4- )
        for f in $flist ; do
            cp -a /conf/static_files/$f /$basedir/$f
        done
    fi
}

function cleanup_udev() {
    echo -e "cleaning udev-rules"
    rm -f /$basedir/etc/udev/rules.d/*persisten*
}

function set_root_passwd() {
    echo -e "Checking for root password change"
    root_pw=`get_conf_str "get_root_passwd" | cut -d " " -f 3- `
    set_pw=0
    if [ "${#root_pw}" -le "4" ] ; then
        echo -e "  got empty password, checking if any is set"
        cat /$basedir/etc/shadow | grep "^root::" > /dev/null && { echo "No root-pw set, using default one" ; 
            set_pw=1;
            root_pw="10sWHACSjCCeA" ;
        }
    else
        set_pw=1
    fi
    if [ "$set_pw" = "1" ] ; then
        echo -ne "Setting root password"
        echo "#!/bin/bash" > /$basedir/tmp/pwf
        echo "echo root:${root_pw} | /usr/sbin/chpasswd -e" >> /$basedir/tmp/pwf
        chmod +x /$basedir/tmp/pwf
        chroot /$basedir /tmp/pwf
        rm -f /$basedir/tmp/pwf
        echo -e "  done"
    fi
}

function prepare_for_yp() {
    echo -e "Preparing /etc/passwd and /etc/group for yp-users and groups"
    cat /$basedir/etc/group  | grep "^+::" >/dev/null || echo "+::0:"   >> /$basedir/etc/group
    cat /$basedir/etc/passwd | grep "^+::" >/dev/null || echo "+::::::" >> /$basedir/etc/passwd
}

function make_nsswitch_local() {
    echo -e "installing a local-lookup only nsswitch.conf"
    cp -a /$basedir/etc/nsswitch.conf /$basedir/etc/.nsswitch.conf.orig
    echo -e "passwd: compat\ngroup: compat\nshadow: compat\nhosts: files\nnetworks: files\nprotocols: db files\nservices: db files\nethers: db files\nrpc: db files\n" > /$basedir/etc/nsswitch.conf
}

function restore_nsswitch() {
    echo -e "restoring nsswitch.conf"
    if [ -x /bin/mv ] ; then
        mv /$basedir/etc/.nsswitch.conf.orig /$basedir/etc/nsswitch.conf
    else
        cp -a /$basedir/etc/.nsswitch.conf.orig /$basedir/etc/nsswitch.conf
        rm -f /$basedir/etc/.nsswitch.conf.orig
    fi
}

function install_packages() {
    echo -e "Installing additional packages"
    package_str=`get_conf_str "get_package_server"`
    stat=$(echo $package_str| cut -d " " -f 2)
    if [ "$stat" = "ok" ] ; then
        set_hoststat ${PACK_MESG}
        package_server=$(echo $package_str | cut -d " " -f 3)
        add_packs=`get_conf_str "get_additional_packages"`
        packs=$(echo $add_packs | cut -d " " -f 3-)
        if [ "${packs:-0}" != "0" ] ; then
            echo -e "${GREEN}Installing $(echo $packs | wc -w) packages from $package_server${OFF}"
            mkdir /packages
            mount_it "additional_packages" ${package_server}:/usr/local/share/packages/RPMs/additional_packages /packages "${RO_MOUNTOPTS}"
            cd /packages
            for pack in $packs ; do 
                inst_package=$(ls -t -1 ${pack}* 2>&1 | head -1 )
                if [ -f "$inst_package" ] ; then
                    echo -e "${GREEN}Installing package named ${pack} found${OFF}"
                    cp -a $inst_package /$basedir/tmp
                    chroot /$basedir /bin/rpm -Uvh /tmp/$inst_package
                    rm -f /$basedir/tmp/$inst_package
                else
                    echo -e "${YELLOW}No Package named ${pack} found${OFF}"
                fi
            done
            cd ..
            umount /packages
        fi
    fi
}

function copy_chroot_exec() {
    chroot_files=""
    for s_dir in usr/bin usr/sbin bin sbin ; do
        chroot_files="$chroot_files "$(find /$basedir/$s_dir -name chroot)
    done
    cp -a $chroot_files /$basedir
}

function add_groups_and_users() {
    dusers=`get_conf_str "get_del_user" | cut -d " " -f 3- `
    echo -e "Deleting users $dusers"
    for u in $dusers ; do
        echo -e "Trying to delete user $u"
        chroot /$basedir /usr/sbin/userdel $u
    done
    dgroups=`get_conf_str "get_del_group" | cut -d " " -f 3- `
    echo -e "Deleting groups $dgroups"
    for g in $dgroups ; do
        echo -e "Trying to delete group $g"
        chroot /$basedir /usr/sbin/groupdel $g
    done
    groups=`get_conf_str "get_add_group" | cut -d " " -f 3- `
    echo -e "Adding groups $groups"
    for g in $groups ; do
        gname=`echo $g| cut -d ":" -f 1`
        gid=`echo $g| cut -d ":" -f 2`
        echo -e "Trying to add group $gname (gid $gid)"
        chroot /$basedir /usr/sbin/groupadd -g $gid $gname  >> /conf/.output/useradd 2>&1
    done
    users=`get_conf_str "get_add_user" | cut -d " " -f 3- `
    echo -e "Adding users $users"
    for u in $users ; do
        name=`echo $u | cut -d ":" -f 1`
        uid=`echo $u | cut -d ":" -f 2`
        group=`echo $u | cut -d ":" -f 3`
        uinfo=`echo $u | cut -d ":" -f 4`
        uhome=`echo $u | cut -d ":" -f 5`
        ushell=`echo $u | cut -d ":" -f 6`
        passwd=`echo $u | cut -d ":" -f 7`
        echo -e "Trying to add user $name (uid $uid, group $group, info $uinfo, home $uhome, shell $ushell)"
        chroot /$basedir /usr/sbin/useradd -u $uid -g $group -c "$uinfo" -d "$uhome" -s "$ushell" $name >> /conf/.output/useradd 2>&1 
        echo "${name}:${passwd}" > /$basedir/tmp/pwf
        chroot /$basedir cat /tmp/pwf | /usr/sbin/chpasswd
        rm -f /$basedir/pwf
    done
}

function handle_runlevel_links() {
    echo -e "Handling runlevel links"
    stop_levs=`get_conf_str "get_stop_scripts" | cut -d " " -f 3- `
    for sl in $stop_levs ; do 
        if [ -f /$basedir/etc/redhat-release ] ; then
            echo -e "Trying to chkconfig --del $sl"
            chroot /$basedir /sbin/chkconfig --del $sl
        elif [ -f /$basedir/etc/debian_version ] ; then
            echo -e "Trying to update-rc.d -f $sl remove"
            chroot /$basedir /usr/sbin/update-rc.d -f $sl remove
        else
            echo -e "Trying to insserv -r $sl"
            chroot /$basedir /sbin/insserv -r $sl
        fi
        if [ -x /$basedir/bin/systemctl ] ; then
            echo -e "disabling with systemctl"
            chroot /$basedir /bin/systemctl disable ${sl}.service
        fi
    done
    start_levs=`get_conf_str "get_start_scripts" | cut -d " " -f 3- `
    for sl in $start_levs ; do 
        if [ -f /$basedir/etc/redhat-release ] ; then
            echo -e "Trying to chkconfig --add $sl"
            chroot /$basedir /sbin/chkconfig --add $sl
            chroot /$basedir /sbin/chkconfig $sl on
        elif [ -f /$basedir/etc/debian_version ] ; then
            echo -e "Trying to update-rc.d $sl defaults"
            chroot /$basedir /usr/sbin/update-rc.d $sl defaults
        else
            echo -e "Trying to insserv $sl"
            chroot /$basedir /sbin/insserv $sl
        fi
        if [ -x /$basedir/bin/systemctl ] ; then
            echo -e "enabling with systemctl"
            chroot /$basedir /bin/systemctl enable ${sl}.service
        fi
    done
    # sleep 30
}

function do_sfdisk_call() {
    dev=$1
    if [ -x /usr/sbin/parted -o -x /sbin/parted ] ; then
        set_hoststat "${PART_MESG} using parted"
        parted -s $dev print > /conf/.output/parted_before
        dd if=/dev/zero of=$dev count=512 bs=1024
        parted -s $dev mklabel gpt
        # get the size of the disk; a little hack
        # two cases:
        # old parted (up to 1.6.21/22/23): report as <LOWER>-<UPPER> MB
        # new parted (starting with at least 1.6.24): report as <LOWER> - <UPPER>GB
        # new version as of 31.1.2006 (Novartis): rewrite \ -\ to - via sed
        # debian_etch parted reports as Disk <disk>: <size>GB, sigh ...
        # new version with parted -m (machine-printable output)
        # pre-debian version
        (
        size=0
        if [ "${size:-0}" = "0" ] ; then
            size=$(parted -s $dev print | grep Disk\ geo | sed s/\ -\ /-/g | cut -d "-" -f 2 | sed s/^\ //g | cut -d " " -f 1 | cut -d "." -f 1)
        fi
        if [ "${size:-0}" = "0" ] ; then
            # try with-debian version
            size=$(parted -s $dev print | grep Disk | tr " " "\n" | grep -e "GB\|MB" )
        fi
        #echo "***$size"
        echo $size | grep GB > /dev/null && {
            size=$(($(($(echo $(echo $size | cut -d "." -f 1) | tr -dc [:digit:] ) - 1 )) * 1000)) ;
        }
        #echo "***$size"
        echo $size | grep MB > /dev/null && {
            size=$(($(($(echo $(echo $size | cut -d "." -f 1) | tr -dc [:digit:] ) - 1 )) )) ;
        }
        #echo "***$size"
        if [ "${size:-0}" = "0" ] ; then
            err_exit "Unable to determine size of disk $dev"
        else
            echo -e "Size of disk $dev is $size"
            req_size=$(cat /conf/pinfo/parted  | tr -s " " | grep -v "extend" | cut -d " " -f 4 | sort -n | tail -1 | cut -d "." -f 1)
            cat /conf/pinfo/parted | sed s/_/$size/g > /parted
            cp -a /parted /conf/.output/parted
            [ $size -lt $req_size ] && { err_exit "$PART_MESG Disk to small ($size MB, requested $req_size MB)" ; }
            while read line ; do
                echo "Doing parted -s $dev $line ..."
                parted -s $dev $line
                # reread partition
                sfdisk -R $dev
            done < /parted
            parted -s $dev print > /conf/.output/parted_after
        fi
        ) > /conf/.output/parted_output 2>&1
    else
        set_hoststat "${PART_MESG} using sfdisk"
        cat /conf/pinfo/sfdisk | sfdisk --force -L -uM $dev > /conf/.output/sfdisk 2>&1 || { err_exit "$PART_MESG (code=$?)" ; }
    fi
}

function copy_config() {
    # get partition
    echo -e "Requesting configuration"
    conf_str=`get_conf_str "create_config"`
    num_req=`echo $conf_str| cut -d " " -f 1`
    sleep 2
    echo -e "Waiting for configuration ACK"
    conf_str=`get_conf_str "ack_config"`
    num_ack=`echo $conf_str| cut -d " " -f 1`
    tot_req=$(($num_req + $num_ack))
    send_info "got config for net $1 after $tot_req request(s)"
    set_hoststat "${COPY_CONF} $1 net"
    if [ -f /conf/.config_files -a "$2" = "0" ] ; then
        while read file ; do
            rm -f /$basedir/$file ;
        done < /conf/.config_files
    fi
    rm -f /conf/.config_files
    if [ -f /conf/config_dirs_${1} ] ; then
    echo -e "Generating directory for config $1 from server"
        while read num dir ; do
            num_w=`echo $dir | wc -w`
            if [ "${num_w}" -ge "4" ] ; then
                uid=`echo $dir | cut -d " " -f 1`
                gid=`echo $dir | cut -d " " -f 2`
                mode=`echo $dir | cut -d " " -f 3`
                dir=`echo $dir | cut -d " " -f 4-`
            else
                uid=0
                gid=0
                mode="0755"
            fi
            echo -e "Generating directory ${dir}"
            mkdir -p "/$basedir/$dir"
            chown ${uid}:${gid} "/$basedir/$dir"
            chmod ${mode} "/$basedir/$dir"
        done < /conf/config_dirs_${1}
    fi
    if [ -f /conf/config_delete_${1} ] ; then
        echo -e "Deleting files for config $1 from server"
        while read num recursive file ; do
            echo -e "Deleting $file"
            if [ "${recursive}" == "1" ] ; then
                rm -rf /$basedir/$file
            else
                rm -f /$basedir/$file
            fi
        done < /conf/config_delete_${1}
    fi
    if [ -f /conf/config_files_${1} ] ; then
        echo -e "Installing config files for config $1 from server"
        while read num uid gid mode file ; do
            echo -e "Installing $file"
            filedir=`dirname /$basedir/$file`
            echo "$file" >> /conf/.config_files
            [ ! -d "$filedir" ] && mkdir -p "$filedir"
            [ -d "$filedir" ] && {
                cp -a /conf/content_${1}/$num /$basedir/$file ;
                chown ${uid}:${gid} /$basedir/$file ;
                chmod ${mode} /$basedir/$file ;
            }
        done < /conf/config_files_${1}
    fi
    if [ -f /conf/config_links_${1} ] ; then
        echo -e "Linking files config $1 from server"
        while read num dest src ; do
            echo -e "Linking from $src to $dest"
            chroot /$basedir [ -L $src ] && rm -f /${basedir}/$src
            chroot /$basedir /bin/ln -sf $dest $src
            echo $src >> /conf/.config_files
        done < /conf/config_links_${1}
    fi
    if [ -f /conf/config_${1}.rc ] ; then
        echo -e "Installing rc.config for config $1 from server"
        file="etc/rc.config"
        echo "$file" >> /conf/.config_files
        cp -a /conf/config_${1}.rc /$basedir/$file
    fi
    return 0;
}

function err_exit() {
    set_hoststat "Error $@"
    echo -e "${RED}Some error occured ($@), executing /bin/bash${OFF}"
    echo "server root" > /root/.rhosts
    echo "mounting /dev/pts"
    [ ! -d /dev/pts ] && mkdir /dev/pts
    mount -n -t devpts -o mode=0620,gid=5 devpts /dev/pts 
    if [ -x /usr/sbin/xinetd ] ; then
        logger -s "starting /usr/sbin/xinetd"
        /usr/sbin/xinetd & 
    elif [ -x /usr/sbin/inetd ] ; then
        logger -s "starting /usr/sbin/inetd"
        /usr/sbin/inetd &
    else
        logger "no inetd or xinetd found "
        echo -e "${RED}No inetd found, skipping${OFF}"
    fi
    start_shell
#  exit -1
}

function install_kernel() {
    shift;
    # get partition
    echo -e "Requesting kernel"
    conf_str=`get_conf_str "get_kernel"`
    num=`echo $conf_str| cut -d " " -f 1`
    if [ "$(echo $conf_str | cut -d ' ' -f 3)" == "NEW" ] ; then
    # new_version
        kernel_server=`echo $conf_str | cut -d " " -f 4`
        full_newkernel=`echo $conf_str | cut -d " " -f 5`
        new_version=`echo $conf_str | cut -d " " -f 6`
        new_release=`echo $conf_str | cut -d " " -f 7`
    else
        kernel_server=$motherserver
        full_newkernel=`echo $conf_str | cut -d " " -f 3`
        new_version=`echo $conf_str | cut -d " " -f 4`
        new_release=`echo $conf_str | cut -d " " -f 5`
    fi
    newkernel_dir=$(dirname $full_newkernel)
    newkernel=$(basename $full_newkernel)
    new_version=${new_version:-?}
    new_release=${new_release:-?}
    send_info "got kernel $newkernel (dir $newkernel_dir, version $new_version, release $new_release) after $num request(s)"
    mkdir /kernel
    mount_it "kernel" ${kernel_server}:${newkernel_dir}/${newkernel} /kernel "${RO_MOUNTOPTS}"
    if [ "$new_version" = "?" ] ; then
        if [ -s /kernel/.version ] ; then
            newkversion=`cat /kernel/.version | grep -E "^VERSION" | cut -d "=" -f 2`
        fi
    else
        newkversion="$new_version.$new_release"
    fi
    if [ -s /conf/.kernel ] ; then
        oldkernel=`cat /conf/.kernel`
    else
        oldkernel="?"
    fi
    oldkversion="?"
    if [ -s /conf/.kversion ] ; then
        oldkversion=`cat /conf/.kversion`
    fi
        #echo $oldkernel"*"$newkernel"*"$oldkversion"*"$newkversion
    if [ "$oldkernel" = "$newkernel" -a "$oldkversion" = "$newkversion" ] ; then
        inst=0
    else
        inst=1
    fi
    gen_initrd=0
    #echo $oldkernel $newkernel $olkversion $newkversion $inst
    if [ $inst -eq 1 ] ; then
        gen_initrd=1
        initrd_cause="new kernel"
        get_conf_str "set_kernel $newkernel $newkversion"
        set_hoststat "${INSTALL_KERNEL} $newkernel ($newkversion)"
        [ -s /kernel/.version ] && cp -a /kernel/.version /$basedir/.kversion
        [ -s /kernel/.config ] && cp -a /kernel/.config /$basedir/boot/.config
        [ -s /kernel/.comment ] && cp -a /kernel/.comment /$basedir/boot/.comment
        echo -e "Installing kernel $newkernel , version $newkversion"
        echo $newkernel > /conf/.kernel
        echo $newkversion > /conf/.kversion
        cp -a /kernel/System.map /$basedir/boot/System.map
        cp -a /kernel/bzImage /$basedir/boot/vmlinuz
        rm -rf /$basedir/lib/modules/*
        if [ -f /kernel/modules.tar.bz2 ] ; then
            tar xjf /kernel/modules.tar.bz2 -C /$basedir/ 2>&1 | grep -v "s in the future"
        else
            echo -e "${YELLOW}No modules.tar.bz2 file found for actual kernel${OFF}"
        fi
    else
        echo $oldkernel > /conf/.kernel
        echo $oldkversion > /conf/.kversion
    fi
    [ -h /$basedir/boot/initrd ]  && rm -f  /$basedir/boot/initrd
    [ ! -f /$basedir/boot/initrd ] && { gen_initrd=1 ; initrd_cause="no initrd found"; }
    if [ ! -f /$basedir/boot/.mods ] ; then
        gen_initrd=1
        initrd_cause="no .mods-file found"
    elif [ "`cat /$basedir/boot/.mods`" != "$*" ] ; then
        gen_initrd=1
        initrd_cause="modules differ"
    fi
    if [ $gen_initrd -eq 1 ] ; then
    # create inital ramdisk
        send_info "${GENERATE_INITRD} for $newkernel ($newkversion), $initrd_cause, modules $*"
        echo "$*" > /$basedir/boot/.mods
    #if [ -f /$basedir/etc/redhat-release ] ; then
    #    chroot /$basedir mkinitrd -v -f --with "$*" /boot/initrd $newkernel
    #else 
    #    chroot /$basedir mkinitrd -i initrd -k vmlinuz -m "$*"
    #fi
    fi
    send_info "done. umounting kernel $newkernel"
    umount /kernel
    rmdir /kernel
    return 0;
}

function install_grub() {
    set_hoststat "${GRUB_MSG}"
    grubf="/$basedir/boot/grub/menu.lst"
    [ -f $grubf ] && cat $grubf > ${grubf}.backup
    rm -f $grubf
    echo "default 0" > $grubf
    echo "timeout 8" >> $grubf
# # grub for netboot
#     if [ -f /conf/netboot_lilo ] ; then
# 	cp -a /conf/netboot_lilo /$basedir/boot/netboot
# 	echo "image = /boot/netboot" >> $grubf
# 	echo "  label = netboot " >> $grubf
# 	netboot_str="with netboot"
#     else
# 	echo "Can't find netboot_lilo-file"
    netboot_str="without netboot"
#     fi
    # is /boot located on a separate partition or below / ?
    boot_pnum=$(( `df /$basedir/boot | grep dev | tr -s " " | cut -d " " -f 1 | sed s.$1..g` - 1 ))
    if [ "$(df /$basedir/boot | grep dev | tr -s " " | cut -d " " -f 6 )" = "/$basedir" ] ; then
        boot_dir=/boot
    else
        boot_dir=""
    fi
    echo "title Linux" >> $grubf
    echo "  kernel (hd0,$boot_pnum)$boot_dir/vmlinuz root=$2 " >> $grubf
    if [ -f /$basedir/boot/initrd ]  ; then
        echo "  initrd (hd0,$boot_pnum)$boot_dir/initrd " >> $grubf
        initrd_str="with initrd"
    else
        echo "no initrd found or needed"
        initrd_str="without initrd"
    fi
    send_info "${GRUB_MSG}, boot=$1, root=$2, $netboot_str, $initrd_str"
    echo "(hd0) $1" > /$basedir/boot/grub/device.map
    echo "root (hd0,$boot_pnum)" > /etc/grub.conf
    echo "install --stage2=/boot/grub/stage2 /boot/grub/stage1 d (hd0) /boot/grub/stage2 0x8000 (hd0,$boot_pnum)$boot_dir/grub/menu.lst" >> /etc/grub.conf
    echo "quit" >> /etc/grub.conf
    cp -a /etc/grub.conf /$basedir/etc/grub.conf
    chroot /$basedir grub --batch --device-map=/boot/grub/device.map </etc/grub.conf 
}

function install_lilo() {
    set_hoststat "${LILO_MSG}"
    lilof="/$basedir/etc/lilo.conf"
    [ -f $lilof ] && cp -a $lilof ${lilof}.backup
    echo "boot = $1" > $lilof
    echo "lba32" >> $lilof
    echo "prompt" >> $lilof
    echo "timeout=30" >> $lilof
# lilo for netboot
    if [ -f /conf/netboot_lilo ] ; then
        cp -a /conf/netboot_lilo /$basedir/boot/netboot
        echo "image = /boot/netboot" >> $lilof
        echo "  label = netboot " >> $lilof
        netboot_str="with netboot"
    else
        echo "Can't find netboot_lilo-file"
        netboot_str="without netboot"
    fi
    echo "image = /boot/vmlinuz" >> $lilof
    echo "  label = linux" >> $lilof
    if [ -f /$basedir/boot/initrd ]  ; then
        echo "  initrd = /boot/initrd " >> $lilof
        initrd_str="with initrd"
    else
        echo "no initrd found or needed"
        initrd_str="without initrd"
    fi
    echo "  root = $2" >> $lilof 
    send_info "${LILO_MSG}, boot=$1, root=$2, $netboot_str, $initrd_str"
    chroot /$basedir /sbin/lilo
}

function mount_partitions () {
    mounted=$(
        cat /conf/pinfo/fstab | grep -v -E "(^$|#)" | while read dev mp typ opt rest ; do
        #do not mount the root partition nor swap:
            [ "$mp" = "swap" -o "$mp" = "/" -o "$typ" = "proc" -o "$typ" = "sysfs" -o "$typ" = "devpts" -o "$typ" = "usbdevfs" -o "$typ" = "usbfs" ] && continue

            opt=$(echo $opt | sed -e "s/defaults//g" -e "s/,[\,]*/,/g")
            opt=$(echo $opt | sed -e "s/^[,]*//g")
            [ ".$opt" != "." ] && opt=$(echo \-o\ $opt)
            mp="/${basedir}${mp}"
            echo -e "Mounting $dev type $typ to $mp" >&2
            [ ! -d "$mp" ] && { mkdir -p "$mp" || err_exit "cannot create mountpoint '$mp' (code=$?)" ; }
            echo "mount -t $typ $opt $dev $mp" >&2
            mount -t $typ $opt $dev $mp
# || { err_exit "cannot mount $dev type $typ to $mp (code=$?)" ; }
            echo -n "$mp "
        done
    )
    echo $mounted
}

function get_conf_str() {
    num_retries=1
    while true ; do 
        ret=`tell_mother_zmq -i $ipaddr -m $motherserver -p 8005 $@ 2>&1`  && {
            state=`echo $ret| cut -d " " -f 1`
            [ "$state" = "ok" ] && { echo >&2 -e "${GREEN}got $ret ($state) as answer for $@ ${OFF}" ; break ; }
        } || {
            state="error" ;
        }
        if [ "$state" = "wait" -o "$state" = "warn" ] ; then
            echo >&2 -e "${YELLOW}warning (server $motherserver, port 8005, command $@, $ret), will sleep for 10 seconds${OFF}"
        else
            echo >&2 -e "${RED}error (server $motherserver, port 8005, command $@, $ret), will sleep for 10 seconds${OFF}"
        fi
        num_retries=$(( $num_retries + 1))
        for i in $(seq 10) ; do 
            sleep 1
            echo >&2 -n "."
        done
        echo
    done
    echo "$num_retries $ret"
}

function generate_devicefiles() {
    mknod /dev/tty c 5 0
    mknod -m 0666 /dev/urandom c 1 9
    mknod -m 0666 /dev/random c 1 8
    for dsk in hda:3:0 hdb:3:64 hdc:22:0 hdd:22:64 hde:33:0 hdf:33:64 hdg:34:0 hdh:34:64 ; do
        bname=/dev/`echo $dsk | cut -d ":" -f 1`
        major=`echo $dsk | cut -d ":" -f 2`
        minor=`echo $dsk | cut -d ":" -f 3`
        mknod -m 0600 $bname b $major $minor
        for i in $(seq 31) ; do
            minor=$(( $minor + 1 ))
            mknod -m 0600 $bname$i b $major $minor
        done
    done
    major=8
    minor=0
    for dsk in a b c d e f g h i j k l m n o p ; do
        bname=/dev/sd$dsk
        mknod -m 0600 $bname b $major $minor
        for i in $(seq 15) ; do
            minor=$(( $minor + 1 ))
            mknod -m 0600 $bname$i b $major $minor
        done
        minor=$(( $minor + 1 ))
    done
    cpq=/dev/cciss
    mkdir $cpq
    major=104
    for cac in 0 1 ; do
        minor=0
        bname=${cpq}/c${cac}
        for dsk in $(seq 0 4) ; do 
            dname=${bname}d${dsk}
            mknod -m 0600 $dname b $major $minor
            minor=$(( $minor + 1 ))
            for i in $(seq 15) ; do
                mknod -m 0600 ${dname}p$i b $major $minor
                minor=$(( $minor + 1 ))
            done
        done
        major=$(( $major + 1 ))
    done
    cpq=/dev/ida
    mkdir $cpq
    major=72
    for cac in 0 1 ; do
        minor=0
        bname=${cpq}/c${cac}
        for dsk in $(seq 0 4) ; do
            dname=${bname}d${dsk}
            mknod -m 0600 $dname b $major $minor
            minor=$(( $minor + 1 ))
            for i in $(seq 15) ; do
                mknod -m 0600 ${dname}p$i b $major $minor
                minor=$(( $minor + 1 ))
            done
        done
        major=$(( $major + 1 ))
    done
}

function mount_it() {
    what=$1
    # remove double-// from path (for NetApp devices)
    src=$(echo $2 | sed s.//./.g)
    dst=$3
    opts=$4
    iter=1
    while true ; do
        logger -s "trying: mount from ${src} (opt ${opts})"
        mount ${opts} ${src} ${dst} && { 
            break ; 
        } || {
            mc=$?;
            log_str="cannot mount $what for $device_name ($ipaddr) from "$(echo $src| cut -d ":" -f 1)" (code=$mc, $iter of $MOUNT_RETRIES)"
            logger $log_str
            echo -e "${RED}${log_str}${OFF}"
            if [ $iter -eq $MOUNT_RETRIES ] ; then
                echo
                err_exit "max MOUNT_RETRIES $MOUNT_RETRIES reached, exiting..." ; 
            else
                log_str=", retrying in $MOUNT_SLEEP seconds"
                logger -s $log_str
                echo -e "${RED}${log_str}${OFF}"
                sleep $MOUNT_SLEEP
            fi
            iter=$(($iter + 1))
        }
    done
    logger -s "successfull mount after $iter retries"
}

#python-init

echo
echo -e "\n${GREEN}${BOLD}init.at ClusterNetInstall stage2 (c) 2001-2013 init.at (lang-nevyjel@init.at)${OFF}"
echo "/dev/ram1 / ext2 rw 0 0" > /etc/mtab

echo -e "mounting /proc and /sys for stage2"
[ ! -d /proc ] && mkdir /proc
mount -n proc  /proc -t proc
[ ! -d /sys ] && mkdir /sys
mount -n sysfs  /sys -t sysfs
echo -e "generating device files"
generate_devicefiles
# init /etc/hosts for hoststatus
echo -e "127.0.0.1 localhost\n" > /etc/hosts

echo -e "${GREEN}setting status and starting hoststatus${OFF}"
set_hoststat ${BM_MESG}
hoststatus_zmq &

hostname bootsystem

echo -e "${GREEN}Logging stuff${OFF}"
set_hoststat ${START_SYSLOG}

syslog_str=`get_conf_str "get_syslog_server"`
logserver=`echo $syslog_str| cut -d " " -f 3`
echo -e "logging to '${logserver}'"

echo -e "$logserver logserver\n" >> /etc/hosts
echo -e "$motherserver server\n" >> /etc/hosts

if [ -x /sbin/syslog-ng ] ; then
    SYSLOG_BIN=syslog-ng
    mkdir -p /etc/syslog-ng
    echo "source src { unix-dgram('/dev/log'); internal(); };" > /etc/syslog-ng/syslog-ng.conf
    echo "destination ls { udp('$logserver' port(514)); };" >> /etc/syslog-ng/syslog-ng.conf
    echo "log { source(src);destination(ls);};" >> /etc/syslog-ng/syslog-ng.conf
    echo -e "starting syslog-ng"
    /sbin/syslog-ng &
elif [ -x /sbin/syslogd ] ; then
    SYSLOG_BIN=syslogd
    echo -e "*.*\t@logserver\n" > /etc/syslog.conf
    echo -e "starting syslogd"
    /sbin/syslogd &
elif [ -x /sbin/rsyslogd ] ; then
    SYSLOG_BIN=rsyslogd
    echo -e "\$ModLoad imuxsock.so" > /etc/rsyslog.conf
    echo -e "\$ModLoad imklog.so" >> /etc/rsyslog.conf
    echo -e "\$ModLoad imudp.so" >> /etc/rsyslog.conf
    echo -e "*.*\t@logserver:514\n" >> /etc/rsyslog.conf
    echo -e "starting rsyslogd"
    /sbin/rsyslogd -c 5 -f /etc/rsyslog.conf &
else
    SYSLOG_BIN=0
fi

echo -e "starting klogd"
/sbin/klogd -c 1 &

# say hello to the config-server
get_conf_str "hello"

# build pci id str for autodetection
pci_str=""
for dev in /sys/bus/pci/devices/* ; do
    pci_str="${pci_str} $(echo -n $(cat $dev/modalias)::$(cat $dev/class))" ;
done 

set_hoststat "Requesting modules"

mods=$(get_conf_str get_autodetect_mods base | cut -d " " -f 3- )

mods="${mods} $(get_conf_str get_autodetect_mods disk ${pci_str} | cut -d " " -f 3- )" 

mods="${mods} $(get_conf_str get_init_mods | cut -d " " -f 3- )"

echo -e "Loading modules: '${mods}'"

[ ! -d "/lib/modules/`uname -r`/kernel" ] && mkdir -p /lib/modules/`uname -r`/kernel

remote_mods=`get_conf_str locate_module ${mods} | cut -d " " -f 3- `
for mod in $remote_mods ; do
    echo -e "Transfering `basename $mod` from $motherserver"

    echo -e "\r\nconnect ${motherserver}\r\n binary\r\n get $mod /lib/modules/`uname -r`/kernel/`basename $mod`" | tftp > /dev/null
done

depmod -ae || depmod -ave

# network drivers from e1000 are stored in /.initrd_mods
intrd_mods=`cat /.initrd_mods`
# special handling of (lib)crc32c dependency problem
echo ${mods:-0} | grep crc32 > /dev/null && modprobe crc32c
for i in ${mods} ; do
    test -n "$i" && {
        newmod=`echo $i | cut -d "." -f 1` ; 
        modprobe $newmod
        initrd_mods="$initrd_mods $newmod ";
    } || continue
done

# get target_state
echo -e "Requesting target state/network"
conf_str=`get_conf_str "get_target_sn"`
num=`echo $conf_str| cut -d " " -f 1`
tstate=`echo $conf_str | cut -d " " -f 3`
prod_net=`echo $conf_str | cut -d " " -f 4`
rsync_flag=`echo $conf_str | cut -d " " -f 5`
rsync_compr=`echo $conf_str | cut -d " " -f 6`
device_name=`echo $conf_str | cut -d " " -f 7`
if [ $(echo $conf_str | wc -w) -eq 8 ] ; then
    config_server=$motherserver
    config_dir=`echo $conf_str | cut -d " " -f 8`
else
    config_server=`echo $conf_str | cut -d " " -f 8`
    config_dir=`echo $conf_str | cut -d " " -f 9`
fi

mkdir /conf
set_hoststat ${MOUNT_STRING}
mount_it "config" $config_server:/$config_dir/$device_name /conf "${RW_MOUNTOPTS}"

[ ! -d /conf/.output ] && { mkdir /conf/.output ; }

echo -e "saving environment variables"
set > /conf/.output/act_set
echo -e " netdevice given by server is ${nbd} (driver '$net_driver', options '$net_options', ethtool_options '$eto')" > /conf/.output/ethtool

sleep_time=0
incr_sleep_time=1
while true ; do
    [ -r /proc/partitions ] && {
        fdev=/dev/`cat /proc/partitions | sort -n | tr -s " " | egrep "^ [0-9]+ ? [0-9]+ (.*)" | grep -v "ram" | cut -d " "  -f 5 | head -1`
    } || {
        [ -d /sys/block ] && fdev=/dev/$(cd /sys/block;ls -1d * | egrep -v "^(ram|loop|fd)" | head -1)
    }

    # check if a valid disc has been found
    echo $fdev | grep -E "^/dev/.+$" > /dev/null && {
        break ; 
    } || {
        sleep_time=$(( $sleep_time + $incr_sleep_time ));
        incr_sleep_time=$(( $incr_sleep_time + 1 ));
        if [ "$sleep_time" -gt 30 ] ; then
            err_exit "no disc after $sleep_time seconds" ;
        else
            set_hoststat "no disc after $sleep_time seconds, waiting for $incr_sleep_time seconds"
        fi
        sleep $incr_sleep_time;
    }
done

echo -e "Will use device $fdev as install/boot device ."

if [ "$rsync_flag" = "0" ] ; then
    rsync_str="disabled"
elif [ "$rsync_flag" = "1" ] ; then
    rsync_str="only install"
else
    rsync_str="always"
fi
if [ "$rsync_compr" = "0" ] ; then
    rsync_c_str="no compression"
    rsync_flags="-a"
else
    rsync_c_str="with compression"
    rsync_flags="-az"
fi
send_info "got target_state $tstate (prod_net $prod_net, rsync-state is $rsync_str, $rsync_c_str) after $num request(s)"
echo -e "${GREEN}Target state $tstate: prod_net $prod_net, rsync-flag $rsync_str, $rsync_c_str${OFF}"

do_mount=0
do_install=0
we_are_clean=0
echo $tstate | grep -E "^(boot|install(ation)*)*(_clean)*$" >/dev/null && do_mount=1
echo $tstate | grep -E "^install(ation)*(_clean)*$" >/dev/null && do_install=1
echo $tstate | grep -E "^.*_clean$" > /dev/null && we_are_clean=1

if [ "$tstate" = "boot_rescue" ] ; then
    echo -e "generating ramdisk"
    mkfs.ext2 -m0 /dev/ram1 32768 > /dev/null

    mkdir /images /$basedir
    mount /dev/ram1 /$basedir

    mount ${RO_MOUNTOPTS} $motherserver:/tftpboot/images/rescue /images >/dev/null || { err_exit "cannot mount rescue from $motherserver (code=$?)" ; }

    cd /$basedir

    mkdir /$basedir/proc /$basedir/initrd /$basedir/sys

    echo -e "Installing rescue system"
    for dir in bin boot dev etc lib root sbin tmp usr var; do
    echo $dir
    tar -xzf /images/${dir}.tar.gz 2>/dev/null | grep -v "s in the future"
    done

    set_hoststat ${PS_RESCUE}
    umount /images /conf
    rmdir /images /conf

    /sbin/pivot_root . initrd
    umount initrd/proc

    set_hoststat ${JT_RESCUE}

    if [ -f /usr/bin/chroot ] ; then
        exec /usr/bin/chroot . /sbin/init 3 <dev/console >dev/console 2>&1
    else
        exec /usr/sbin/chroot . /sbin/init 3 <dev/console >dev/console 2>&1
    fi

elif [ "$do_mount" = "1" ] ; then
    # get partition
    echo -e "Requesting partition type"
    conf_str=`get_conf_str "get_partition $fdev"`
    num=`echo $conf_str| cut -d " " -f 1`
    pinfo=`echo $conf_str | cut -d " " -f 3`
    send_info "got partition $pinfo after $num request(s)"
    echo -e "Partition type is $pinfo"
#   dev=`cat /conf/pinfo/device `
    echo $fdev > /conf/.rdev

    rpart=`cat /conf/pinfo/rootpart `
    rparttype=`cat /conf/pinfo/rootparttype `
    echo -e "Root-device is $rpart ($rparttype)"

    [ -r /proc/partitions ] && {
        cat /proc/partitions > /conf/.output/partitions
    } || {
        [ -d /sys/block ] &&
        for i in $(cd /sys/block;ls -1d * | egrep -v "^(ram|loop|fd)") ; do
            (cd $i && echo */ | sed -e "s/(device|queue)\///g")
        done > /conf/.output/partitions
    }
    
    mkdir /$basedir
    if [ "$do_install" = "1" ] ; then
        echo -e "Using partition $pinfo for $PART_MESG disk $fdev"
        
        do_sfdisk_call $fdev
        echo ${pinfo} > /conf/.parttype
        set_hoststat ${FORM_MESG} $fdev
        for type in swap ext2 reiserfs ext3 ext4 xfs btrfs ; do
            rm -f /conf/.output/format_${type}
        done
        rm -f /conf/.output/format_*
        if [ -f /conf/pinfo/swapparts ] ; then
            swapp=`cat /conf/pinfo/swapparts | tr "\n" " "`
            echo -e "Generating swap-devices on partitions $swapp"
            for p in $swapp ; do
                set_hoststat ${FORM_MESG} swap $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                mkswap $p 2>&1 >>/conf/.output/format_swap
            done
        else
            echo -e "No swap-devices defined"
        fi
        
        if [ -f /conf/pinfo/ext2parts ]; then
            ext2p=`cat /conf/pinfo/ext2parts | tr "\n" " "`
            echo -e "$FORM_MESG ext2 partitions $ext2p"
            for p in $ext2p ; do
                set_hoststat ${FORM_MESG} ext2 $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                mkfs.ext2 -q $p >>/conf/.output/format_ext2 2>&1 || { set_hoststat "error $FORM_MESG ext2 partition '$p'" ; }
                tune2fs -T now $p
            done
        fi
        
        if [ -f /conf/pinfo/reiserfsparts ]; then
            reiserfsp=`cat /conf/pinfo/reiserfsparts | tr "\n" " "`
            echo -e "$FORM_MESG reiserfs partitions $reiserfsp"
            for p in $reiserfsp ; do
                set_hoststat ${FORM_MESG} reiserfs $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                echo y | mkfs.reiserfs --format 3.6 $p >>/conf/.output/format_reiserfs 2>&1 || { set_hoststat "error $FORM_MESG reiserfs partition '$p'" ; }
            done
        fi
        
        if [ -f /conf/pinfo/ext3parts ]; then
            ext3p=`cat /conf/pinfo/ext3parts | tr "\n" " "`
            echo -e "$FORM_MESG ext3 partitions $ext3p"
            for p in $ext3p ; do
                set_hoststat ${FORM_MESG} ext3 $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                mkfs.ext3 -j -O sparse_super -q $p >>/conf/.output/format_ext3 2>&1 || { set_hoststat "error $FORM_MESG ext3 partition '$p'" ; }
                tune2fs -T now $p
            done
        fi
        
        if [ -f /conf/pinfo/ext4parts ]; then
            ext4p=`cat /conf/pinfo/ext4parts | tr "\n" " "`
            echo -e "$FORM_MESG ext4 partitions $ext4p"
            for p in $ext4p ; do
                set_hoststat ${FORM_MESG} ext4 $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                mkfs.ext4 -j -O sparse_super -q $p >>/conf/.output/format_ext4 2>&1 || { set_hoststat "error $FORM_MESG ext4 partition '$p'" ; }
                tune2fs -T now $p
            done
        fi
        
        if [ -f /conf/pinfo/btrfsparts ]; then
            btrfsp=`cat /conf/pinfo/btrfsparts | tr "\n" " "`
            echo -e "$FORM_MESG btrfs partitions $btrfsp"
            for p in $btrfsp ; do
                set_hoststat ${FORM_MESG} btrfs $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                mkfs.btrfs $p >>/conf/.output/format_btrfs 2>&1 || { set_hoststat "error $FORM_MESG btrfs partition '$p'" ; }
            done
        fi

        if [ -f /conf/pinfo/xfsparts ]; then
            xfsp=`cat /conf/pinfo/xfsparts | tr "\n" " "`
            echo -e "$FORM_MESG xfs partitions $xfsp"
            for p in $xfsp ; do
                set_hoststat ${FORM_MESG} xfs $p
                dd if=/dev/zero of=$p bs=1024 count=1000 > /dev/null 2>&1
                mkfs.xfs -f $p >>/conf/.output/format_xfs 2>&1 || { set_hoststat "error $FORM_MESG xfs partition '$p'" ; }
            done
        fi
        
        mkdir /images
        # get partition
        echo -e "Creating mountpoints"
        
        mount -t $rparttype $rpart /$basedir >/tmp/mount_out 2>&1 || { err_code=$? ; cat /tmp/mount_out | logger -s ; err_exit "cannot mount root-partition $rpart (type $rparttype) to /$basedir (code=$err_code)" ; } || { echo "mounted root-partition $rpart (type $rparttype) to /$basedir" ; }
        
        set_hoststat ${MP_MESG}
        rm -rf /$basedir/*
        cd /$basedir
        
        [ ! -d sys  ] && mkdir sys
        [ ! -d proc ] && mkdir proc
        [ ! -d tmp  ] && mkdir tmp
        [ ! -d dev/shm  ] && mkdir -p dev/shm
        chmod 666 proc
        
# mount partitions and generate main directories
        mounts="`mount_partitions`"
        umounts=""
        for i in $mounts; do
            umounts="$i $umounts";
        done
# unpack images
        set_hoststat "Requesting image"
        conf_str=`get_conf_str "get_image"`
        num=`echo $conf_str| cut -d " " -f 1`
        if [ $(echo $conf_str | wc -w) -eq 6 ] ; then
        # old version
            image_server=$motherserver
            full_image=`echo $conf_str | cut -d " " -f 3`
            image=$(basename $full_image)
            image_dir=$(dirname $full_image)
            image_version=`echo $conf_str | cut -d " " -f 4`
            image_release=`echo $conf_str | cut -d " " -f 5`
            image_builds=`echo $conf_str | cut -d " " -f 6`
        else
        # new version with image_server_ip
            image_server=`echo $conf_str | cut -d " " -f 3`
            full_image=`echo $conf_str | cut -d " " -f 4`
            image=$(basename $full_image)
            image_dir=$(dirname $full_image)
            image_version=`echo $conf_str | cut -d " " -f 5`
            image_release=`echo $conf_str | cut -d " " -f 6`
            image_builds=`echo $conf_str | cut -d " " -f 7`
        fi
        send_info "got image $image after $num request(s)"
        date
        echo -ne "Installing image $image (dir $image_dir, ${image_version}.${image_release}, ${image_builds} builds)"
        if [ "$rsync_flag" = "0" ] ; then
            echo " via tar.gz/bz2"
            
            set_hoststat ${INS_MESG}
            mount_it "image" $image_server:$image_dir/$image /images "${RO_MOUNTOPTS}"
            if [ -f /images/sbin.tar.gz ] ; then
                imtype=gz
                tar_flags="-xzf"
            elif [ -f /images/sbin.tar.xz ] ; then
                imtype=xz
                tar_flags="-xJf"
            else
                imtype=bz2
                tar_flags="-xjf"
            fi
            dirperm_file=.tdir.tar.${imtype}
            for file in /images/*.${imtype} ; do
                basen=`basename $file`
                if [ "$basen" != "$dirperm_file" ] ; then
                    set_hoststat -q "${UNP_MESG} $basen"
                    echo -e "Unpacking $basen ($(ls -sh $file | cut -d'/' -f1 | tr -d " "))"
                    (tar ${tar_flags} $file || { err_exit "unpacking $basen" ; }) 2>&1 | grep -v "s in the future"
                fi
            done
            set_hoststat "${FIX_MESG}"
# set permissions
            if [ -f /images/${dirperm_file} ] ; then
                mkdir /tdir
                tar ${tar_flags} /images/${dirperm_file} -C /tdir 2>&1 | grep -v "s in the future"
                for dir in /tdir/* ; do
                    rd=`basename $dir`
                    [ ! -d ${rd} ] && mkdir -p ${rd}
                    echo -n "$rd "
                    chmod --reference=/tdir/${rd} ${rd}
                    chown --reference=/tdir/${rd} ${rd}
                done
                echo
                rm -rf /tdir
            else
                echo -e "Can't find dirperm-file ${dirperm_file}, using default"
                chmod 1777 /$basedir/tmp
                chmod 0700 /$basedir/root
            fi
            
            umount /images
            rmdir /images
            
        else
            echo " via rsync"
            
            set_hoststat ${RSYNC_MESG}
            rm -f /tmp/.rsync_exclude
            echo -e "Getting exlucde-paths for install"
            get_conf_str "get_install_ep" | cut -d " " -f 3- | tr " " "\n" > /tmp/.rsync_exclude
            echo "contents of exclude-list:"
            cat /tmp/.rsync_exclude | sed s/^/\ -\ /g
            echo -e "starting rsync from server $motherserver, image is $image"
            rsync ${rsync_flags} --exclude-from=/tmp/.rsync_exclude --stats ${motherserver}::${image} /${basedir} || err_exit "doing rsync-call"
        fi
# check for global /lost+found dir
        [ ! -d /${basedir}/lost+found ] && mkdir /${basedir}/lost+found
# image version
        echo -e "Renewing image info."
        echo "${image}" > /conf/.imagename
        echo "${image_version}.${image_release}" > /conf/.version
        echo "IMAGE_NAME=${image}" > /${basedir}/.imageinfo
        echo "IMAGE_VERSION=${image_version}.${image_release}" >> /${basedir}/.imageinfo
# fixing fstab
        rm -f /$basedir/etc/fstab /$basedir/etc/mtab
        cat /conf/pinfo/fstab > /$basedir/etc/fstab
        # /etc/mtab is now a link to /proc/self/mounts
        # /etc/mtab is now a link to /proc/self/mounts
        #touch /$basedir/etc/mtab
# force kernel install
        rm -f /conf/.kernel /conf/.kversion
    # go back to root-dir
        cd /
    else
#XXXXXXX
        echo -e "mount -t $rparttype $rpart /$basedir" >&2
        mount -t $rparttype $rpart /$basedir
# mount partitions
        mounts="`mount_partitions`"
        umounts=""
        for i in $mounts; do umounts="$i $umounts" ; done
        if [ "$rsync_flag" = "2" ] ; then
            echo " refreshing image via rsync"
            
            set_hoststat "Requesting image name"
            conf_str=`get_conf_str "get_image"`
            num=`echo $conf_str| cut -d " " -f 1`
            full_image=`echo $conf_str | cut -d " " -f 3`
            image=$(basename $full_image)
            image_dir=$(dirname $full_image)
            
            set_hoststat ${RSYNC_REFRESH_MESG}
            rm -f /tmp/.rsync_exclude
            echo -e "Getting exlucde-paths for refresh"
            get_conf_str "get_install_ep" | cut -d " " -f 3- | tr " " "\n" > /tmp/.rsync_exclude
            echo "contents of exclude-list:"
            cat /tmp/.rsync_exclude | sed s/^/\ -\ /g
            echo -e "starting rsync from server $motherserver, image is $image"
            rsync ${rsync_flags} --exclude-from=/tmp/.rsync_exclude --stats ${motherserver}::${image} /${basedir} || err_exit "doing rsync-call"
    # we have to request the fstab again (otherwise /etc/fstab will be overwritten)
            echo -e "Requesting partition type"
            conf_str=`get_conf_str "get_partition $fdev"`
            num=`echo $conf_str| cut -d " " -f 1`
            pinfo=`echo $conf_str | cut -d " " -f 3`
            send_info "got partition $pinfo after $num request(s)"
            echo -e "Partition type is $pinfo"
            rm -f /$basedir/etc/fstab /$basedir/etc/mtab
            cat /conf/pinfo/fstab > /$basedir/etc/fstab
            #touch /$basedir/etc/mtab
            
        fi
    fi
    if [ "$rsync_flag" = "1" -o "$rsync_flag" = "2" ] ; then
        echo -e "Getting exlucde-paths for upgrade"
        get_conf_str "get_upgrade_ep" | cut -d " " -f 3- | tr " " "\n" > /${basedir}/tmp/.rsync_exclude
    fi
# copy config
    if [ "$we_are_clean" = "0" ] ; then
# copy location of source config dir
        echo ${config_dir} > /$basedir/.config_dir
        copy_config ${prod_net} "$do_install"
        cleanup_udev
        make_nsswitch_local
        copy_static_files
        add_groups_and_users
        handle_runlevel_links
        set_root_passwd
        prepare_for_yp
        install_packages
        restore_nsswitch
    fi
    copy_chroot_exec
# check for new kernel
    if [ "$we_are_clean" = "0" ] ; then
        install_kernel $initrd_mods
        if [ "$(get_conf_str 'modify_bootloader')" = "yes" ] ; then
        echo -e "Modifying bootloader ..."
    # grub call
        if [ -x /$basedir/sbin/grub -o -x /$basedir/usr/sbin/grub ] ; then
        install_grub $fdev $rpart
    # lilo call
        elif [ -x /$basedir/sbin/lilo -o -x /$basedir/usr/sbin/lilo ] ; then
        install_lilo $fdev $rpart
        else
        echo -e "Neither grub nor lilo found"
        fi
        else
        echo -e "No modification of bootloader requested"
        fi
    fi
# unmount partitions
    echo -e "Unmounting partitions $umounts"
    for m in $umounts ; do umount $m ; done
    if [ "$we_are_clean" = "1" ] ; then
    ACT_MSG="${JT_CLEAN}"
    else
    ACT_MSG="${JT_NORMAL} in ${prod_net} net"
    fi
    echo $rpart $rparttype ${ACT_MSG} > /tmp/mother

else
    err_exit "Unknown target_state $tstate"
fi
set_hoststat ${S2_DONE}
# tear hoststatus down to allow umounting of /stage2

echo "Umounting new system from /$basedir"
umount /$basedir || err_exit "Cannot umount new system /$basedir"

killall hoststatus_zmq
umount /conf
# DEBUG
#err_exit
[ "$SYSLOG_BIN" != "0" ] && killall $SYSLOG_BIN
killall klogd
umount /sys
umount /proc

hostname ""

touch /success
