#!/bin/bash

# Warewulf wwmkchroot general functions

# Set default WW environment
eval $(wwconfig -as)

# Set temporary media mount directory within the node image;
# directory is also be created on the host, with symlinks to
# media within the node image (for node image bootstrap)
MEDIA_TMP="/tmp/wwmkchroot.mount"

# Set temporary mountpath within the chroot
MEDIA_MOUNTPATH="${CHROOTDIR}${MEDIA_TMP}"

export FUNCTIONS="sanity_check
                  distro_check
                  init
                  prechroot
                  buildchroot
                  postchroot
                  configure_fstab
                  configure_network
                  configure_ntp
                  configure_pam
                  configure_authentication
                  configure_sshkeys
                  configure_rootacct
                  configure_runlevel
                  configure_services
                  configure_timezone
                  finalize
                  cleanup"


set_as_overlay() {
    FUNCTIONS="sanity_check
               distro_check
               init
               set_overlay
               buildchroot
               configure_services
               finalize
               cleanup"
}

sanity_check() {
    if [ ! -x $WAREWULF_PREFIX/bin/cluster-env ]; then
        echo "The \"warewulf-cluster\" package is recommended on nodes where you are building VNFS images."
        sleep 2
    else
        $WAREWULF_PREFIX/bin/cluster-env;
    fi
    if [ -z "$PKGLIST" ]; then
        echo "ERROR: You must define the \$PKGLIST variable in the template"
        return 1
    else
       test -n "$DEBUG" && echo "_PACKAGES_ $PKGLIST" | tr -s [:space:] "\n" | sort
    fi
    return 0
}

distro_check() {
    return 0
}

init() {
    # Create the chroot directory
    if [ ! -d "$CHROOTDIR" ]; then
        if ! mkdir -p "$CHROOTDIR"; then
            echo "ERROR: Could not create directory $CHROOTDIR"
            exit 1
        fi
    fi
    test -n "$VERBOSE" && echo "Installing into $(readlink -e $CHROOTDIR)"

    # If ISOs are defined, mount them into the chroot temp directory
    # Symlinks are added outside of the chroot for bootstrapping
    if [ -n "$INSTALL_ISO" ]; then
        test -n "$DEBUG" && echo INSTALL_ISO=$INSTALL_ISO
        count=0
        mkdir -p $MEDIA_TMP
        for i in $(echo $INSTALL_ISO | sed -e 's/,/ /'); do
            if [ -f "$i" ]; then
                j=$(readlink -enq $i)
                test -n "$VERBOSE" && echo Mounting $count:$j
                if ! mount | grep -q "^$j"; then
                    mkdir -p $MEDIA_MOUNTPATH/$count
                    ln -sT $MEDIA_MOUNTPATH/$count $MEDIA_TMP/$count
                    if ! mount -o loop $j $MEDIA_MOUNTPATH/$count; then
                        echo "ERROR: Could not mount: $j"
                        cleanup
                        exit 1
                    else
                        test -n "$DEBUG" && grep "^$j" /proc/mounts
                    fi
                    count=$(expr $count + 1)
                else
                    test -n "$VERBOSE" && echo " - Already mounted"
                fi
            else
                echo "ERROR: Could not locate INSTALL_ISO: $INSTALL_ISO"
                cleanup
                exit 1
            fi
        done
    fi
    return 0
}

set_overlay() {
    return 0
}

prechroot() {
    return 0
}

buildchroot() {
    $PKGR_CMD
    if [ $? -ne 0 ]; then
        echo "ERROR: Failed to install packages"
        cleanup
        return 1
    fi
    return 0   
}

postchroot() {
    return 0
}

configure_pam() {
    if [ -f "$CHROOTDIR/etc/pam.d/system-auth" ]; then
        sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' $CHROOTDIR/etc/pam.d/system-auth
    fi

    if [ -f "$CHROOTDIR/etc/pam.d/password-auth" ]; then
        sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' $CHROOTDIR/etc/pam.d/password-auth
    fi
    return 0
}

configure_authentication() {
    if [ -x "/usr/sbin/chroot" ]; then
        /usr/sbin/chroot $CHROOTDIR /usr/sbin/pwconv
    elif [ -x "/usr/bin/chroot" ]; then
       /usr/bin/chroot $CHROOTDIR /usr/sbin/pwconv
    fi
    return 0
}

configure_rootacct() {
    sed -i -e 's/^root:[^:]*:/root:*:/' $CHROOTDIR/etc/passwd
    cp $CHROOTDIR/etc/skel/.[a-zA-Z]* $CHROOTDIR/root/ > /dev/null 2>&1
    return 0
}

configure_fstab() {
    WWIPADDR=$(perl -e '
        use Warewulf::Network;
        use Warewulf::Config;

        my $config = Warewulf::Config->new("provision.conf");
        my $netobj = Warewulf::Network->new();
        my $netdev = $config->get("network device");
        my $ipaddr = $netobj->ipaddr("$netdev");

        print "$ipaddr\n";
    ')

    echo "#GENERATED_ENTRIES#" > $CHROOTDIR/etc/fstab
    echo "tmpfs /dev/shm tmpfs defaults 0 0" >> $CHROOTDIR/etc/fstab
    echo "devpts /dev/pts devpts gid=5,mode=620 0 0" >> $CHROOTDIR/etc/fstab
    echo "sysfs /sys sysfs defaults 0 0" >> $CHROOTDIR/etc/fstab
    echo "proc /proc proc defaults 0 0" >> $CHROOTDIR/etc/fstab

    if [ -f /etc/exports ]; then
        grep "^#WWEXPORT:" /etc/exports  | while read i; do
            SHARE=`echo $i | cut -d : -f 2`
            echo "$WWIPADDR:$SHARE $SHARE nfs defaults 0 0" >> $CHROOTDIR/etc/fstab
            mkdir -p $CHROOTDIR/$SHARE
        done
    fi
    return 0
}

configure_sshkeys() {
    if [ -f "$WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_rsa_key" ]; then
        /bin/cp -a $WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_rsa_key* $CHROOTDIR/etc/ssh/
    elif [ ! -f "$CHROOTDIR/etc/ssh/ssh_host_rsa_key" ]; then
        /usr/bin/ssh-keygen -q -t rsa -f $CHROOTDIR/etc/ssh/ssh_host_rsa_key -C '' -N ''
    fi
    if [ -f "$WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_dsa_key" ]; then
        /bin/cp -a $WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_dsa_key* $CHROOTDIR/etc/ssh/
    elif [ ! -f "$CHROOTDIR/etc/ssh/ssh_host_dsa_key" ]; then
        /usr/bin/ssh-keygen -q -t dsa -f $CHROOTDIR/etc/ssh/ssh_host_dsa_key -C '' -N ''
    fi

    # This should fail silently as ECDSA isn't supported on older platforms.
    if [ -f "$WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_ecdsa_key" ]; then
        /bin/cp -a $WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_ecdsa_key* $CHROOTDIR/etc/ssh/
    elif [ ! -f "$CHROOTDIR/etc/ssh/ssh_host_ecdsa_key" ]; then
        /usr/bin/ssh-keygen -q -t ecdsa -f $CHROOTDIR/etc/ssh/ssh_host_ecdsa_key -C '' -N '' 2> /dev/null
    fi

    # This should fail silently as Ed25519 isn't supported on older platforms.
    if [ -f "$WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_ed25519_key" ]; then
        /bin/cp -a $WAREWULF_SYSCONFDIR/warewulf/vnfs/ssh/ssh_host_ed25519_key* $CHROOTDIR/etc/ssh/
    elif [ ! -f "$CHROOTDIR/etc/ssh/ssh_host_ed25519_key" ]; then
        /usr/bin/ssh-keygen -q -t ed25519 -f $CHROOTDIR/etc/ssh/ssh_host_ed25519_key -C '' -N '' 2> /dev/null
    fi

    mkdir -m 0700 -p $CHROOTDIR/root/.ssh 2>/dev/null
    > $CHROOTDIR/root/.ssh/authorized_keys
    for i in $(ls /root/.ssh/*.pub 2>/dev/null); do
        cat $i >> $CHROOTDIR/root/.ssh/authorized_keys
    done
    return 0
}

configure_network() {
    if [ -d $CHROOTDIR/etc/sysconfig/network ]; then
        return 0
    elif [ -d $CHROOTDIR/etc/sysconfig ]; then
        echo "NETWORKING=yes" > $CHROOTDIR/etc/sysconfig/network
    fi
    return 0
}

configure_runlevel() {
    if [ -f "$CHROOTDIR/etc/inittab" ]; then
        sed -i -e 's@id:.:initdefault:@id:3:initdefault:@' $CHROOTDIR/etc/inittab
    fi
    return 0
}

configure_timezone() {
    if [ -f "/etc/localtime" ]; then
        cp -a /etc/localtime $CHROOTDIR/etc/localtime
    fi
    if [ -f "/etc/adjtime" ]; then
        cp -a /etc/adjtime $CHROOTDIR/etc/adjtime
    fi
    return 0
}

configure_ntp() {
    NETDEV=$(sed -ne "/network device =/s/.*=\s*//p" $WAREWULF_SYSCONFDIR/warewulf/provision.conf)
    IPADDR=""
    BOOTPROTO=""
    if [ -f "/etc/sysconfig/network-scripts/ifcfg-$NETDEV" ]; then
        . /etc/sysconfig/network-scripts/ifcfg-$NETDEV
    elif [ -f "/etc/sysconfig/network/ifcfg-$NETDEV" ]; then
	. /etc/sysconfig/network/ifcfg-$NETDEV
    fi
    if [ -n "$IPADDR" -a "x$BOOTPROTO" == "xstatic" ]; then
	IPADDR=${IPADDR/\/*/}
        [ -n $VERBOSE ] && echo "Adding ntp and chrony configuration files to chroot"
        echo "# Written by Warewulf:wwmkchroot" > $CHROOTDIR/etc/ntp.conf
        echo "# Written by Warewulf:wwmkchroot" > $CHROOTDIR/etc/chrony.conf

        echo "driftfile /var/lib/ntp/drift" >> $CHROOTDIR/etc/ntp.conf
        echo "driftfile /var/lib/ntp/drift" >> $CHROOTDIR/etc/chrony.conf

        echo "restrict default kod nomodify notrap nopeer noquery" >> $CHROOTDIR/etc/ntp.conf
        echo "restrict -6 default kod nomodify notrap nopeer noquery" >> $CHROOTDIR/etc/ntp.conf
        echo "restrict 127.0.0.1" >> $CHROOTDIR/etc/ntp.conf
        echo "restrict -6 ::1" >> $CHROOTDIR/etc/ntp.conf

        echo "server $IPADDR prefer" >> $CHROOTDIR/etc/ntp.conf
        echo "server $IPADDR prefer" >> $CHROOTDIR/etc/chrony.conf

        echo "restrict $IPADDR mask 255.255.255.255 nomodify notrap noquery" >> $CHROOTDIR/etc/ntp.conf
        echo "allow $IPADDR" >> $CHROOTDIR/etc/chrony.conf
    fi
    return 0
}

configure_services() {
    return 0
}

cleanup() {
    if [ -n "$INSTALL_ISO" ]; then
        if [ -n "$DEBUG" ]; then
            echo "WARNING: Debug enabled; leaving media mounts in place!"
        else
            rm -f $MEDIA_TMP/*
            rmdir $MEDIA_TMP
            for i in $(ls -d $MEDIA_MOUNTPATH/*); do
                if umount $i; then
                    test -n "$VERBOSE" && echo "$i unmounted"
                    rmdir $i
                else
                    echo "WARNING: Could not unmount $i"
                fi
            done
        fi
    fi
    return 0
}

finalize() {
    return 0
}


# vim:filetype=sh:syntax=sh:expandtab:ts=4:sw=4:
