#!/bin/bash

# SLES 9 only
# This script is written in bash (instead of ksh) as it invokes SLES scripts

install_script=/usr/lpp/mmfs/samples/nfscluster/install_ha-nfs.sh

error() {
    echo "Error: $*"
}

usage() {
    echo "Usage: $0 [-a] nfsdefs nodes.list"
    echo "$@"
    exit 1
}

# Exit if status is not 0
statusCheck() {
    status=$?
    if [ $status -ne 0 ]; then
        grep "Error:\|Warning:" $LOGFILE
        [ -s $LOGFILE ] && echo -n "See $LOGFILE for details."
        echo ""
        exit $status
    fi
}

config() {
    # Check for SUSE distribution
    dist=$(cat /etc/issue | grep "SUSE LINUX Enterprise Server 9")
    if [ -z "$dist" ]; then
	error "Install will work only for SUSE LINUX Enterprise Server 9"
	return 1
    fi

    # Check the GPFS is not running
    gpfs=$(mmfsadm dump version 2> /dev/null | grep "Current daemon version")
    if [ -n "$gpfs" ]; then
	error "GPFS must be stopped before installation."
	return 1
    fi

    # Ensure programs required for HA are available
    if [ ! -e /etc/ha.d/resource.d/IPaddr ]; then
        error "Cannot find heartbeat in /etc/ha.d/resource.d. Please install the heartbeat RPMs required for high-availability. Installation will not continue."
        return 1
    fi

    # Ensure all public interfaces used for NFS are static (no DHCP)
    gpfsip=$(myGPFSIP)
    nfsIPs=$(getNfsIPs $gpfsip)
    for ip in $nfsIPs; do
        # Find its ifcfg file
        ifcfg=$(getifcfg $ip)
	if [ -z "$ifcfg" ]; then
            error "Cannot find configuration file for $ip in $IFPATH"
            error "$ip has to be a static IP address defined in $IFPATH. DHCP is not permitted as an NFS address."
            return 1
        fi
        bootproto=$(grep ^BOOTPROTO $ifcfg | awk -F\' '{print $2}')
        if [ "$bootproto" != "static" ]; then
            error "$ip has to be a static IP address in $ifcfg. DHCP is not permitted as an NFS address."
            return 1
        fi
    done

    # Check if sm-notify works with host names. Warn, otherwise
    # Use any one of NFS IPs
    sm-notify -m 1 -d -v $ip 2> /dev/null
    if [ $? -ne 0 ]; then
        echo "Warning: The installed version of sm-notify does not support notification of failures on IP takeover for NLM lock recovery. Please upgrade (see README) if you intend to use byte-range locking over NFS."
    fi

    typeset -i portAssigned=1
    configNLMPorts $gpfsip
    [ $? -ne 0 ] && portAssigned=0
 
    # Check if kernel supports manipulating grace period
    checkDynamicGrace
    if [ $? -eq 0 ]; then
        echo "Warning: The running kernel ($(uname -r)) does not support setting grace period for NFS locking. On single node failure, all NFS locks will be released cluster-wide and reclaimed by clients."
    fi

    # Copy files from samples
    [ -d /var/mmfs/etc ] && cp -a /var/mmfs/etc /var/mmfs/etc.bak
    cp -dp /usr/lpp/mmfs/samples/nfscluster/* /var/mmfs/etc

    log cp -dp /usr/lpp/mmfs/samples/nfscluster/init.d.gpfs /etc/init.d/gpfs &&
    log insserv gpfs
    # Undo GPFS autoload from inittab
    sed -i 's/^gpfs:\(.*\)/# gpfs:\1	# Disabled by HA-NFS/g' /etc/inittab

    # Set default start mode of interfaces to be used for HA-NFS to "manual"
    # This is required so clients do not detect active connections on failover
    # or failback before GPFS is active
    for ip in $nfsIPs; do
        # Find its ifcfg file
        ifcfg=$(getifcfg $ip)
	[ -z "$ifcfg" ] && continue
        iface=$(getifname $ip)
        if grep -q "^STARTMODE.*='onboot'" $ifcfg; then
	    . $ifcfg
	    for ipval in ${!IPADDR*}; do
		index=${ipval#IPADDR}
		ipaddr=${!ipval}
		if [ "$ip" == "$ipaddr" ]; then
			mode=STARTMODE$index
			break
		fi
	    done
            # SuSE
            sed -i "s/^$mode='onboot'/$mode='manual'	# added for HA-NFS/g" $ifcfg
            echo "Installation has changed the start mode of interface $iface to manual."
        elif grep -q "^ONBOOT=yes" $ifcfg; then
            # RedHat
            sed -i "s/^ONBOOT=yes/ONBOOT=no	# added for HA-NFS/g" $ifcfg
            echo "Installation has changed the start mode of interface $iface to manual."
        fi
    done

    if [ $portAssigned -eq 0 ]; then
	echo "Warning: Cannot assign requested ports for NLM. Reboot required to complete installation."
    fi
}

install() {
    echo -n "Synchronizing install files to all nodes in the cluster "
    for ip in $gpfsIPs; do
	log $GPFS_rcpPath $defs $ip:/var/mmfs/etc
	log $GPFS_rcpPath $nodes $ip:$NODELIST
    done
    rc_status -v
    statusCheck

    echo -n "Installing HA-NFS on all nodes in the cluster "
    gpfsIPs=$(echo $gpfsIPs | sed 's/ /,/g')
    log mmdshcmdRC $gpfsIPs $install_script -c
    rc_status -v
    statusCheck
}

chconfig() {
    nodeList=$*

    # Autoload GPFS on boot.
    if [ "$AUTOSTART" == "1" ]; then 
	options="autoload=yes"
    else
	options="autoload=no"
    fi

    # For better read performance of large files set the following option.
    options="$options,nfsprefetchstrategy=1"

    # After creating the GPFS cluster turn on the GPFS HA-NFS option.
    options="$options,enablenfscluster=yes"

    echo -n "Configuring GPFS cluster for HA-NFS "
    log mmchconfig "$options $nodeList"

    # Following options have to be run on all nodes of the cluster
    
    if [ -n "$allflag" ]; then
        # Current lease time and wait time are 35+35 seconds.
        # set leaserecoverywait to no less than 10 second.
        options="$options,leaserecoverywait=10"

        # set leaseDuration to no less than 20 second.
        options="$options,leaseDuration=20"

        log mmchconfig "$options"
    fi
    rc_status -v
}

touch /var/mmfs/etc/nfsdefs # workaround to get nfsfuncs to work
funcs=/usr/lpp/mmfs/samples/nfscluster/nfsfuncs
[ -f $funcs ] || die "Cannot find $funcs"
. $funcs

. /etc/rc.status
rc_reset

LOGFILE=/tmp/install-ha-nfs.log
> $LOGFILE

allflag=""
while getopts acv OPT; do
    case $OPT in
	a)
	    [ -n "$allflag" ] && usage "specify '$OPT' option only once"
	    allflag=yes
	    ;;
	c)
	    config
	    exit $?
	    ;;
	*)
	    usage "$OPTARG is not valid"
	    ;;
    esac
done

shift $(($OPTIND-1))
[ $# -eq 2 ] || usage

defs=$1; nodes=$2

[ -f $defs ] || die "Cannot find $defs. See /usr/lpp/mmfs/samples/nfscluster/README for installation instructions"
[ -f $nodes ] || die "Cannot find $nodes. See /usr/lpp/mmfs/samples/nfscluster/README for installation instructions"

cp -dp $defs /var/mmfs/etc
cp -dp $nodes /var/mmfs/etc

. $defs

# Reset log file that might be overwritten by $defs
LOGFILE=/tmp/install-ha-nfs.log

if [ -n "$GPFS_RSH" ]; then
    GPFS_rshPath=$(which $GPFS_RSH)
else
    GPFS_rshPath=$(which rsh)
fi
if [ -n "$GPFS_RCP" ]; then
    GPFS_rcpPath=$(which $GPFS_RCP)
else
    GPFS_rcpPath=$(which rcp)
fi

# Check that mandatory parameters have been defined
[ -n "$SHARED_ROOT" ] || die "The system directory (SHARED_ROOT) for HA-NFS not defined in $defs"
[ -n "$NODELIST" ] || die "The list of GPFS nodes (NODELIST) for HA-NFS not defined in $defs"

if [ -z "$allflag" ]; then
    config
    opts="-N $(myGPFSIP)"
else
    # Run configuration on all GPFS nodes
    temp=$NODELIST
    NODELIST=$nodes 		# used by getAllGPFSIPs
    gpfsIPs=$(getAllGPFSIPs)
    list=$(echo $gpfsIPs | sed 's/ /,/g')
    opts="-N $list"
    NODELIST=$temp

    myip=$(myGPFSIP)
    if [ -z "$myip" ]; then
	error "Install will work only from one of the nodes in nfs.nodes"
	exit 1
    fi

    install $gpfsIPs
fi
chconfig $opts

statusCheck
grep "Warning:" $LOGFILE
echo -n "Installation is complete. "
[ -s $LOGFILE ] && echo "See $LOGFILE for details."
exit 0
