#!/bin/ksh93
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/usr/sbin/cluster/cspoc/utilities/cl_change_efs.sh 1.8 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2011,2012 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 

. /usr/es/lib/ksh93/func_include
. /usr/es/sbin/cluster/cspoc/cl_federatedsec_source
fsec_init

typeset MountPt="/var/efs"
typeset SFS="/EFS_KS_JFS2"
typeset EXPORT_DIR=$SFS
typeset SIP  # Service IP
typeset VG   # shared volume group
typeset MODE # Mode
typeset NODES
typeset ks_rg="EFS_KeyStore"
typeset tmp_f="${FSEC_LOG_DIR}/efs_ks".$$
typeset UTIL_DIR="/usr/es/sbin/cluster/utilities"
typeset ADMIN_PW

_USAGE="$( dspmsg -s 129 cspoc.cat 114 "Usage: %s {-a 1 -A <password>} {-a 2 [-v <volume group>] [-s <service IP>]}\n" "$0")"

while getopts :s:v:m:A: option
do
    case $option in
        s)  #Service IP
            SIP=$OPTARG
        ;;
        v)  #VG Name
            VG=$OPTARG
        ;;
        m)  #mode
            MODE=$OPTARG
        ;;
		A)  #password
            ADMIN_PW=$OPTARG
        ;;
        *)  print -u2
             /usr/bin/dspmsg -s 4 utilities.cat 50 '%1$s: unknown option "%2$s"\n' "$(/usr/bin/basename $0)" "-$OPTARG" 1>&2
            print -u2 "\n$_USAGE\n"
            exit 1;;
    esac
done

odm_check

KS_mode=$(clodmget -n -q "group=EFSKeyStore AND name=mode" -f value HACMPLDAP 2>/dev/null)

[[ ! -z $KS_mode ]] || {
     dspmsg -s 129 cspoc.cat 156 "EFS Keystore is not configured for PowerHA SystemMirror.\n"
	exit 1
	}
	
if [[ $KS_mode == 1 ]]
then
	 dspmsg -s 129 cspoc.cat 77 "Already in LDAP mode.\n"
	 dspmsg -s 129 cspoc.cat 131 "Only change mode from Shared Filesystem to LDAP is allowed.\n"
	exit 1
fi

lssrc -ls clstrmgrES | grep ST_STABLE >/dev/null \
|| {  dspmsg -s 129 cspoc.cat 132 "Cluster services should be up and stable.\n"; exit 1; }

NODES=`/usr/es/sbin/cluster/utilities/cllsnode -c | awk -F: '(NR != 1) {print $1}'`

[[ -z $NODES ]] && { 
	 dspmsg -s 129 cspoc.cat 64 "Nodes are not configured in cluster.\n"
	exit 1
	}

if [[ $KS_mode -eq 2 ]] && [[ $MODE -eq 1 ]]
then
	 dspmsg -s 129 cspoc.cat 116 "INFORMATION: Volume group and Service IP is invalid and will be ignored in LDAP mode.\n"
	[[ -z $ADMIN_PW ]] && {  dspmsg -s 129 cspoc.cat 133 "Password should be supplied.\n"; exit 1; }
fi

EXPECT_FILE=

#Function to create a expect script file for running efsenable
function cr_expect_efsldapconf
{
        EXPECT_FILE="${FSEC_LOG_DIR}/powerha_efsldap.exp.$$"

        echo '#! /usr/bin/expect

set timeout 60
set ADMIN_PW [lindex $argv 0]
set BASE_DN [lindex $argv 1]

spawn /usr/sbin/efsenable -a -d $BASE_DN

expect {
        eof {
            catch wait result
            exit [lindex $result 3]
        }
}
expect {
        timeout {exit 1}
        "initial keystore:"
}
send "$ADMIN_PW\\r"
expect {
        timeout {exit 1}
        "password again:"
}
send "$ADMIN_PW\\r"

expect {
        timeout {exit 1}
    eof {}
}
catch wait result
exit [lindex $result 3]' > $EXPECT_FILE

        chmod +x $EXPECT_FILE
}

#function to enable efs in ldap mode
function efs_ldap_conf
{
    typeset FSECFUNCNAME="efs_ldap_conf"
    [[ -n $FSECDEBUG ]] && set -x

    [[ -z `odmget -q "group=LDAPClient and name=ServerList" HACMPLDAP` ]] && {  dspmsg -s 129 cspoc.cat 134 "A LDAP client is not defined.\n"; exit 2; }
	#retrieve values for ldap client
	TDS_CLNT_PATH=$(clodmget -n -q "group=LDAPServer and name=BasePath" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $TDS_CLNT_PATH ]] && ret_fail "Client path not found." 1 
	BASE_DN=$(clodmget -n -q "group=LDAPClient and name=Suffix" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $BASE_DN ]] && ret_fail "Base DN not found." 1 
	SERVER_LIST=$(clodmget -n -q "group=LDAPClient and name=ServerList" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $SERVER_LIST ]] && ret_fail "Server list not found." 1 
	BIND_DN=$(clodmget -n -q "group=LDAPClient and name=BindDN" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $BIND_DN ]] && ret_fail "Bind DN not found." 1 
	BIND_DNPW=$(clodmget -n -q "group=LDAPClient and name=BindDNPwd" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $BIND_DNPW ]] && ret_fail "Bind DN password not found." 1 
	SSL_PORT_NUM=$(clodmget -n -q "group=LDAPClient and name=SSLPortNumber" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $SSL_PORT_NUM ]] && ret_fail "SSL port number not found." 1 
	CLNT_KDB_PATH=$(clodmget -n -q "group=LDAPClient and name=ClientKdbPath" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $CLNT_KDB_PATH ]] && ret_fail "Client key path not found." 1 
	CLNT_KDB_PW=$(clodmget -n -q "group=LDAPClient and name=ClientKdbPwd" -f value HACMPLDAP|sort -u 2>/dev/null) 
	[[ -z $CLNT_KDB_PW ]] && ret_fail "Client key password not found." 1 
	TMP_EFS_LDIF=${FSEC_LOG_DIR}/efstoexport.$$.ldif
	STANZAS="efsusrkeystore efsadmkeystore"
	TMP_HOST=$(host `echo $SERVER_LIST|awk -F, '{print $1}'`|awk '{print $1}')
	[[ -z $TMP_HOST ]] && ret_fail "First server communication path not found." 1 
	
	clRGinfo -c $ks_rg|grep -w "ONLINE" >/dev/null 2>&1 || {
	 dspmsg -s 129 cspoc.cat 109 "RG %s is not online, please make sure cluster services are up and stable to contiue with the EFS configuration.\n" "$ks_rg"
	exit 1
	}
	
	for i in $NODES
	do
		cl_rsh -n $i "efskstoldif -d $BASE_DN > $TMP_EFS_LDIF"
		cl_rsh -n $i ${TDS_CLNT_PATH}/bin/idsldapadd -h $TMP_HOST -D $BIND_DN -w  $BIND_DNPW -K $CLNT_KDB_PATH \
			-P $CLNT_KDB_PW -p $SSL_PORT_NUM -c -f $TMP_EFS_LDIF > ${FSEC_LOG_DIR}/ldapadd_efskstoldif.log.$$ 2>&1
		ret_code=$?
		if [[ $ret_code -ne 0 ]] && [[ $ret_code -ne 20 ]] && [[ $ret_code -ne 68 ]]
		then
			ret_fail "ldapadd failed." $ret_code
		fi
	done
	
	run_on_allnode "rm -rf /var/efs/*" >/dev/null || ret_fail "efsenabled file remove failed." $?
	clvt delete resource_group $ks_rg || {  dspmsg -s 129 cspoc.cat 157 "Cannot remove EFS keystore from cluster.\n"; exit 1; }
	run_on_allnode "odmdelete -o HACMPLDAP -q group=EFSKeyStore" >/dev/null 2>&1 || ret_fail "odmdelete failed" $?


	run_on_allnode "rm -rf /var/efs/*" >/dev/null || ret_fail "efsenabled file remove failed." $?
	cr_expect_efsldapconf
	
	for i in $NODES
	do
		/usr/es/sbin/cluster/utilities/cl_rcp $EXPECT_FILE ${i}:${EXPECT_FILE}1 >/dev/null || ret_fail "efs ldap expect file copy failed." $?
		cli_on_node -N $i "${EXPECT_FILE}1 $ADMIN_PW $BASE_DN" || ret_fail "efsenable failed on $i node" $?
		for X in $STANZAS
		do
			cl_rsh -n $i "chsec -f /etc/nscontrol.conf -s $X -a secorder=LDAP,files" >/dev/null \
				|| ret_fail "chsec command failed." $?
		done
		cl_rsh -n $i "chsec -f /etc/nscontrol.conf -s efsgrpkeystore -a secorder=files,LDAP" >/dev/null \
				|| ret_fail "chsec command failed." $?
	done
	lsuser -R LDAP -a ALL|xargs -i chuser efs_keystore_access=ldap {} >/dev/null || ret_fail "chuser command failed." $?
	lsgroup -R LDAP -a ALL|xargs -i chgroup efs_keystore_access=ldap {} >/dev/null || ret_fail "chgroup command failed." $?
	run_on_allnode "rm -f $TMP_EFS_LDIF $EXPECT_FILE" >/dev/null 2>&1
}
function cl_waitstable
{
    typeset FSECFUNCNAME="cl_waitstable"
    [[ -n $FSECDEBUG ]] && set -x

	ret_fail "Cluster is stabilizing..." 0
	i=0
	while [[ $i -le 180 ]]
	do
		print -n "."
		lssrc -ls clstrmgrES|grep ST_STABLE >/dev/null && break 
		sleep 2
		let i=i+2
	done
	if [[ $i == 182 ]]
	then
		ret_fail "Cluster failed to stabilize." 1
	fi	
}
function RG_check
{
    typeset FSECFUNCNAME="RG_check"
    [[ -n $FSECDEBUG ]] && set -x

	clRGinfo -c $ks_rg|grep -w "ONLINE"  >/dev/null || clRGmove -g $ks_rg -r -u -i >/dev/null || {
			 dspmsg -s 129 cspoc.cat 109 "RG %s is not online, please make sure cluster services are up and stable to contiue with the EFS configuration.\n" "$ks_rg"
			exit 1
		}
	cl_waitstable
}

function change_efs
{
    typeset FSECFUNCNAME="change_efs"
    [[ -n $FSECDEBUG ]] && set -x

	if [[ -z $SIP ]] && [[ -z $VG ]]
	then
		 dspmsg -s 129 cspoc.cat 138 "Nothing to change.\n"
		exit 2
	fi
	NODE_STR=`clRGinfo -c $ks_rg|grep -w "ONLINE"|awk -F: '{print $3}'` 
	[[ -z $NODE_STR ]] && ret_fail "RG not online/found." 1 
	vg_tt=`/usr/es/sbin/cluster/utilities/clshowres -g $ks_rg |grep -w "^Volume Groups"|awk '{print $3}'`
	if [[ ! -z $SIP ]]
	then
		clRGmove -g $ks_rg -n "$NODE_STR" -d -i >/dev/null || ret_fail "Not able to move RG offline" $?
		cl_waitstable
		clvt modify resource_group $ks_rg SERVICE_LABEL="$SIP" || ret_fail "SERVICE_LABEL change failed." $?
		ret_fail "DARE is working, please wait..." 0
		cldare -rt -V 'modified' > ${FSEC_LOG_DIR}/efs_cldare.log.$$ 2>&1 || {  dspmsg -s 129 cspoc.cat 135 "DARE operation failed, please check logs and correct the failures.\n"; exit 2; }
		cl_waitstable
		RG_check
	fi
	
	if [[ ! -z $VG ]]
	then
		FLAG=0
		for i in $NODES
		do
			st=$(/usr/es/sbin/cluster/utilities/cl_rsh -n $i lsvg  | grep $VG) \
				|| {  dspmsg -s 129 cspoc.cat 65 "EFS VG does not exist on Node %s\n" "$i";	exit 1; }
			st=$(/usr/es/sbin/cluster/utilities/cl_rsh -n $i lsfs | grep -w "$SFS") \
				|| {  dspmsg -s 129 cspoc.cat 66 "EFS KeyStore FS does not exist on Node %s\n" "$i"; exit 1; }
		done
		
		RG_check
		EFS_BK_TAR=${FSEC_LOG_DIR}/efsbk.$$.tar
		 dspmsg -s 129 cspoc.cat 136 "INFO: Taking EFS keystore backup in %s . In case if setup failed in middle then, use this backup file to restore EFS keys. In case of failure perform 'Delete EFS' and then 'Enable EFS'. Once enabled, untar the backup file to restore keys.\n" "$EFS_BK_TAR"
		tar -cvf $EFS_BK_TAR /var/efs >/dev/null || ret_fail "Taking keystore backup failed." $?
		clRGmove -g $ks_rg -n "$NODE_STR" -d -i >/dev/null || ret_fail "Not able to move RG offline" $?
		cl_waitstable
		nodes_fs=`echo $NODES|sed 's/ /,/g'`
		run_on_allnode "varyoffvg $vg_tt" >/dev/null || ret_fail "varyoffvg failed." $?
		cl_rmfs $SFS >/dev/null || ret_fail "Removing old keystore filesystem failed." $?
		cl_crlvfs -cspoc -n "$node_fs" -v jfs2 -g "$VG" -F'G' -a size='1' -m "$SFS" -p'rw' -a agblksize='4096' >/dev/null \
			&& cl_lsfs | grep -w "$SFS" >/dev/null || ret_fail "EFS Keystore FileSystem creation failed." $?
		clvt modify resource_group $ks_rg VOLUME_GROUP="$VG" || ret_fail "VOLUME_GROUP change failed." $?
		ret_fail "DARE is working, please wait..." 0
		cldare -rt -V 'modified' > ${FSEC_LOG_DIR}/efs_cldare.log.$$ 2>&1 || {  dspmsg -s 129 cspoc.cat 135 "DARE operation failed, please check logs and correct the failures.\n"; exit 2; }
		cl_waitstable
		RG_check
		tar -xvf $EFS_BK_TAR >/dev/null ||  dspmsg -s 129 cspoc.cat 137 "Restoring EFS keys failed, try manually.\n"
	fi
	
	 dspmsg -s 129 cspoc.cat 108 "EFS Keystore is changed.\n"

	fsec_vsync "EFS Keystore change"

	exit 0
}

if [[ $MODE == 2 ]]
then
	change_efs
else
	efs_ldap_conf
fi

echo "HACMPLDAP:
       group="EFSKeyStore"
       type="EFS"
       name="mode"" > $tmp_f
echo "value="1  >>  $tmp_f
st=$(odmadd $tmp_f ) || { 
		 dspmsg -s 129 cspoc.cat 71 "ODM update is failed.\n"
		run_on_allnode "rm /var/efs/efsenabled" >/dev/null 2>&1
		exit 1
		}	
rm -f  $tmp_f
 dspmsg -s 129 cspoc.cat 108 "EFS Keystore is changed.\n"

fsec_vsync "EFS Keystore change" || ret_fail "clverify restriction failed" $?
run_on_allnode "rm -rf $FSEC_LOG_DIR" || ret_fail "Removing log directory failed." $?

exit 0