#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2019,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r721 src/43haes/usr/sbin/cluster/cspoc/utilities/cl_enable_efs.sh 1.9 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2011,2016 
# 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 
# @(#)  7d4c34b 43haes/usr/sbin/cluster/cspoc/utilities/cl_enable_efs.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM 

#================================================
# The following, commented line enforces coding
# standards when this file is edited via vim.
#================================================
# vim:tabstop=4:shiftwidth=4:expandtab:smarttab
#================================================

#
:   Common set up for federated security
#
. /usr/es/lib/ksh93/func_include
. /usr/es/sbin/cluster/cspoc/cl_federatedsec_source
fsec_init

if [[ -z $FSECDEBUG && $VERBOSE_LOGGING == "high" ]]
then
    export PS4='${FSECPROGNAME}${FSECFUNCNAME:+:${FSECFUNCNAME}}[$LINENO]: '
    set -x
fi
version='1.9'

#
:   Constants
#
integer LDAP=1				#   Keystore to be placed in LDAP
integer FILE_SYSTEM=2			#   KeyStore to be placed in shared file system

#
:   Input parameters
#
typeset Service_IP			#   Service IP, for NFS cross mounts of shared file system
typeset EFS_KeyStore_VG			#   shared volume group to hold shared file system
typeset MODE				#   Mode, LDAP or FILE_SYSTEM
typeset ADMIN_PW			#   Initial administrator password
typeset Reset				#   Reset operation requested
typeset Query                           #   Query operation requested
typeset EFS_KeyStore_size=512M          #   default size of file system for EFS keystore
typeset EFS_SS_size=512M                #   default size of stable storeage file system for EFS keystore

#
:   Variables
#
typeset All_cluster_nodes		#   All cluster nodes, as currently defined
typeset EFS_enable_log="${FSEC_LOG_DIR}/EFS_enable.log.$$"
typeset EXPECT_FILE_FS			#   Holds pathname for expect script
typeset EXPECT_FILE_LDAP		#   Holds pathname for expect script
typeset EFS_KeyStore_RG="EFS_KeyStore"  #   resource group to hold file system key store
integer RC=0				#   Return code from last system operation


#######################################################################
#
#   Function:	cr_expect_efsconf
#
#   Purpose:	Build an expect script (that is, input for the "expect"
#		command) that will invoke the "efsenable" command and 
#		set up the initial keystore password.
#
#   Input:	None
#
#   Output:	An expect script is created in 
#		/var/hacmp/log/fsec/$(date +%Y.%m.%d.%Hh%Mm%Ss-FailedConf)/powerha_efs.exp.$$
#
#   Notes:	An arbitrary time out of 60 seconds is used.  This is
#		based on experience alone.
#
#######################################################################
function cr_expect_efsconf
{
    typeset FSECFUNCNAME="cr_expect_efsconf"
    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && set -x
    EXPECT_FILE_FS="${FSEC_LOG_DIR}/powerha_efs.exp.$$"

    #
    :	The following lines go into $EXPECT_FILE_FS
    #
    print -- '#!/usr/bin/expect
#
#   Wait 60 seconds for input
#
set timeout 60

#
#   Pick up the passed initial password
#
set ADMIN_PW [lindex $argv 0]

#
#   Kick off the efsenable command in the background
#
set env(LC_ALL) C
spawn /usr/sbin/efsenable -a 

expect {
        eof {
            catch wait result
            exit [lindex $result 3]
        }
}

#
#   Look for the password prompt, and respond with
#   the given password.  Exit if this does not happen
#   in the timeout period.
#
expect {
        timeout {exit 1}
        "initial keystore:"
}
send "$ADMIN_PW\\r"

#
#   Look for the confirmation prompt, and respond with
#   the given password.  Exit if this does not happen
#   in the timeout period.
#
expect {
        timeout {exit 1}
        "password again:"
}
send "$ADMIN_PW\\r"

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

    #
    :   Check for successfule file creation
    #
    if [[ -s $EXPECT_FILE_FS ]]
    then
	#
	:   $EXPECT_FILE_FS exists and is not empty.  Make it executable
	#
	chmod +x $EXPECT_FILE_FS
	if [[ $VERBOSE_LOGGING == high ]] 
	then
	    #
	    :	Here is the expect file, $EXPECT_FILE_FS
	    #
	    cat -n $EXPECT_FILE_FS | tee -a $EFS_enable_log
	fi
	return 0
    else
	dspmsg -s 129 cspoc.cat 158 "'Expect' script not created in %1$s.\n" $EXPECT_FILE_FS | 
	    tee -a $EFS_enable_log
	return 2		#   Error
    fi
    
}


#######################################################################
#
#   Function:	efs_reset
#
#   Purpose:	AIX provides no function that will turn off EFS 
#		enablement.  This lapse is sorely felt when trying to
#		recover from any problems with configuring PowerHA 
#		support for EFS.  This function cleans up the effects
#		of "efsenable -a", and removes the PowerHA indication
#		of EFS support.
#
#   Input:	Invoked by "cl_enable_efs -R" as root
#
#   Operation:	Remove the 'efsenable -p' rule(s) from Config_Rules
#		Remove all directories and files under /var/efs
#		Remove all 'efs_*' lines from /etc/security/group
#		Remove all 'efs_*' lines from /etc/security/user
#		Remove the EFSKeyStore mode stanza in HACMPLDAP
#
#   Output:	Saves unmodified copy of /etc/security/user in 
#		${FSEC_LOG_DIR}/etc.security.user.save
#		Saves unmodified copy of /etc/security/group in
#		${FSEC_LOG_DIR}/etc.security.group.save
#		Saves unmodified contents of /var/efs in
#		${FSEC_LOG_DIR}/var.efs.tar
#		Configuration should allow retrying enabling EFS 
#		(KeyStore in shared file system)
#
#   Notes:	Not to be used lightly...
#
#		Will not clean up other nodes, or off line shared storage
#		Will not remove resource group/volume group that holds
#		KeyStore files
#		Should only be run with the resource group/volume group
#		that holds KeyStore files offline
#
#		Does not support reset for LDAP configuration 
#
#######################################################################
function efs_reset 
{
    typeset FSECFUNCNAME="efs_reset"
    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && set -x

    #
    :   Check to make sure that the resource group $EFS_KeyStore_RG is
    :   not already running and doing NFS cross mounts.  
    #	That would get in the way of the clean up - only the shared 
    #   storage would be cleaned up.
    #
    if LC_ALL=C clRGinfo -c $EFS_KeyStore_RG 2>&1 | grep -qw ONLINE 
    then
	#
	:   The existing resource group is in the way
	#
	dspmsg -s 129 cspoc.cat 159 "Resource group \"%s\" is already online. \
It must be offline before clean up can proceed.\n" $EFS_KeyStore_RG
	return 1
    fi

    #
    :	Record who made this change
    #
    if me=$(who am i 2>/dev/null)
    then
	#
	:   Find the real user name in case of su or sudo
	#
	print "$me" | read invoker rest
    else
	invoker="root"
    fi
	
    logger -t user.notice "cl_enable_efs[$LINENO]: AIX EFS support reset by $invoker"

    #
    :   Get rid of the keystore files
    #
    if ! cd /var/efs
    then
	#
	:   If /var/efs is not present, EFS support is not configured
	#
	return 0
    fi

    #
    :	Save and remove key files from /var/efs
    #
    tar -cf ${FSEC_LOG_DIR}/var.efs.tar /var/efs
    rm -rf /var/efs/*

    #
    :	Get rid of copies on the shared file system
    #
    if cd /EFS_KS_JFS2
    then
	#
	:   If the shared file system to hold EFS keys is available,
	:   save and remove those keys
	#
	tar -cf ${FSEC_LOG_DIR}/KS.efs.tar /EFS_KS_JFS2
	rm -rf /EFS_KS_JFS2/*
    fi

    #
    :   Undo "efsenable -a"
    :   Remove any Config_Rules entries
    #
    ODMDIR=/etc/objrepos odmdelete -q "rule like '*efsenable*'" -o Config_Rules

    #
    :   Clean up entries in /etc/security/user
    #
    cp /etc/security/user ${FSEC_LOG_DIR}/etc.security.user.save
    if sed '/efs_*/d' /etc/security/user > /tmp/esu && [[ -s /tmp/esu ]]
    then
	mv /tmp/esu /etc/security/user
    fi

    #
    :   Clean up entries in /etc/security/group
    #
    cp /etc/security/group ${FSEC_LOG_DIR}/etc.security.group.save
    if sed '/efs_*/d' /etc/security/group > /tmp/esg && [[ -s /tmp/esg ]]
    then
	mv /tmp/esg /etc/security/group
    fi

    #
    :	Clean up HACMPLDAP ODM
    #
    ODMDIR=/etc/objrepos odmdelete -q "group=EFSKeyStore and name=mode" -o HACMPLDAP

}


#######################################################################
#
#   Function:	efs_query
#
#   Purpose:	Provide an report of how far along configuration of EFS
#		support has proceeded.
#
#		Intended to be used along with "cl_enable_efs -R" in
#		cleaning up after failed configuration attepts, but 
#		could also be used as part of a general display function.
#
#   Input:	Invoked by "cl_enable_efs -Q" as root
#
#		References PowerHA ODMs, /etc/security/usr and 
#		/etc/security group
#
#   Operation:	Checks for the expected output of each of the steps used
#		to configure EFS support.
#
#   Output:	Messages indicate which steps are complete, and which
#		are not.
#
#   Notes:	Checking for LDAP mode is not supported
#
function efs_query 
{
    typeset FSECFUNCNAME="efs_query"
    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && set -x

    integer Fully_Configured=1
    #
    :	Check HACMPLDAP for key store mode
    #
    mode=$(ODMDIR=/etc/objrepos clodmget -q "group = EFSKeyStore and name=mode" -f value -n HACMPLDAP)
    if [[ -z $mode ]]
    then
	#
	:   Key storage not yet configured
	#
	dspmsg -s 129 cspoc.cat 160 "The 'Key Storage' option is not yet configured.\n"
	Fully_Configured=0

    else
	if (( $mode == 2 ))
	then
	    #
	    :   EFS Keystore in shared volume group
	    #
	    dspmsg -s 129 cspoc.cat 161 "Key Storage is configured to use a shared volume group.\n"

	    #
	    :	Check for presence of EFS_KeyStore resource group
	    #
	    if [[ -n $(clodmget -q "group = EFS_KeyStore" HACMPgroup) ]]
	    then
		dspmsg -s 129 cspoc.cat 162 "The resource group 'EFS_KeyStore' is present.\n"

		#
		:   Check for presence of EFS_KeyStore volume group
		#
		EFS_KeyStore_VG=$(clodmget -q "group = EFS_KeyStore and name = VOLUME_GROUP" -f value -n HACMPresource) 
		if [[ -n $EFS_KeyStore_VG ]]
		then
		    if lsvg | grep -qx $EFS_KeyStore_VG
		    then
			dspmsg -s 129 cspoc.cat 163 "EFS KeyStore volume group %s is present.\n" $EFS_KeyStore_VG
		    else
			dspmsg -s 129 cspoc.cat 164 "The volume group '%1$s' has been specified to PowerHA SystemMirror to hold the EFS keys, but has not been defined to AIX.\n" $EFS_KeyStore_VG

			Fully_Configured=0
		    fi
		else
		    dspmsg -s 129 cspoc.cat 165 "EFS Keystore volume group is not defined.\n"
		    Fully_Configured=0
		fi

		#
		:   Check for presence of NFS application server
		#
		if [[ -n $(clodmget -q "group = EFS_KeyStore and name = APPLICATIONS and value = clas_nfsv4" HACMPresource) ]]
		then
		    dspmsg -s 129 cspoc.cat 166 "NFS server defined for resource group EFS_KeyStore.\n"
		else
		    dspmsg -s 129 cspoc.cat 167 "NFS server is not defined for resource group EFS_KeyStore.\n"
		    Fully_Configured=0
		fi

		#
		:   Check for presence of NFS cross mounts
		#
		if [[ -n $(clodmget -q "group = EFS_KeyStore and name = MOUNT_FILESYSTEM and value = /var/efs;/EFS_KS_JFS2" HACMPresource) ]]
		then
		    dspmsg -s 129 cspoc.cat 168 "NFS cross mounts set up for resource group EFS_KeyStore.\n"
		else
		    dspmsg -s 129 cspoc.cat 169 "NFS cross mounts not set up for resource group EFS_KeyStore.\n"
		    Fully_Configured=0
		fi

	    else
		dspmsg -s 129 cspoc.cat 170 "The resource group 'EFS_KeyStore' is not present.\n"
		Fully_Configured=0
	    fi

	elif (( $mode == 1 ))
	then
	    #
	    :	EFS Keystore in LDAP - configuration check not supported
	    #
	    dspmsg -s 129 cspoc.cat 171 "Key Storage is configured to use LDAP.\n"
	fi
    fi

    #
    :	Check /etc/security/group for efs lines in every stanza
    #
    enabled_stanzas=$(grep -p 'efs*' /etc/security/group | grep -c '^[^ ]*:$')
    all_stanzas=$(grep -c '^[^ ]*:$' /etc/security/group)

    if (( $all_stanzas == $enabled_stanzas ))
    then
	dspmsg -s 129 cspoc.cat 172 "EFS is configured for every stanza in /etc/security/group.\n"

    else
	if (( $enabled_stanzas == 0 ))
	then
	    dspmsg -s 129 cspoc.cat 173 "EFS is not configured in /etc/security/group.\n"
	else
	    dspmsg -s 129 cspoc.cat 174 "EFS is not configured for the following stanzas in /etc/security/group.\n"
	    grep -v -p 'efs*' /etc/security/group
	    Fully_Configured=0
	fi

    fi

    #
    :	Check /etc/security/user for efs lines in default stanza
    #
    if grep -p '^default:$' /etc/security/user | grep -q 'efs_*'
    then
	dspmsg -s 129 cspoc.cat 175 "EFS is configured by default in /etc/security/user.\n"
    else
	dspmsg -s 129 cspoc.cat 176 "EFS is not configured in /etc/security/user.\n"
	Fully_Configured=0
    fi

    #
    :	Check for config rule
    #
    if [[ -n $(ODMDIR=/etc/objrepos clodmget -q "rule like '*efsenable*'" Config_Rules) ]]
    then
	dspmsg -s 129 cspoc.cat 177 "EFS is present in the Config_Rules.\n"
    else
	dspmsg -s 129 cspoc.cat 178 "EFS rule is not present in Config_Rules.\n"
	Fully_Configured=0
    fi

    #
    :	Check for EFS enabled flag file
    #
    if [[ -s /var/efs/efsenabled ]]
    then
	dspmsg -s 129 cspoc.cat 179 "The EFS enablement flag, %s, is present in %s.\n" /var/efs/efsenabled /var/efs

    else
	dspmsg -s 129 cspoc.cat 180 "EFS is not enabled in %s.  %s is missing.\n" /var/efs /var/efs/efsenabled
	Fully_Configured=0
    fi

    if (( $Fully_Configured == 1 ))
    then
	dspmsg -s 129 cspoc.cat 181 "EFS support is fully configured.\n"
    fi

}

#######################################################################
#
#   Function:	enable_efs_sharedfs
#
#   Purpose:	Configure both AIX and PowerHA to support EFS cluster
#		wide, with the KeyStore in a shared file system managed
#		by PowerHA.
#
#		Since any EFS in a shared volume group could appear on
#		any node at any time, and since the same set of keys
#		must be used on whatever node it appears, the keys are
#		saved in a shared file system that is NFS exported and
#		mounted on all nodes.  This requires a volume group 
#		and a resource group dedicated to holding the EFS 
#		KeyStore, and a service IP address for making it i
#		accessible on all nodes. 
#
#   Input:	Volume group name, as provided by user
#
#		Service IP address, as provided by user
#
#   Operation:	Validate that the volume group exists and is known on
#		all cluster nodes.  Create the shared file system to
#		hold the EFS KeyStore in that volume group.  Create a
#		resource group to make that volume group accessable
#		via NFS cross mounts on all cluster nodes.
#
#		Run "efsenable -a" on the local node, and save the 
#		results from /var/efs in the shared file system on the
#		given volume group.
#
#		Run "efsenable -a" on all other cluster nodes.
#
#   Output:	RC=1	Input from user unacceptable
#		RC=2	Lower level operation failed
#		Messages to stdout, and saved in 
#		/var/hacmp/log/fsec/$(date +%Y.%m.%d.%Hh%Mm%Ss-FailedConf)/EFS_enable.log.$$
#
#   Notes:	In order to facilitate recovery from prior failed 
#		attempts, and not enforce an obscure & difficult 
#		recovery operation on the user, the logic will attempt
#		to deal with cases such as the given volume group, or
#		file system, or required resource group, already known
#		or partially known.  However, recovery from general
#		failures in file system creation or volume group import
#		is outside the scope of this routine.
#
#######################################################################
function enable_efs_sharedfs
{
    typeset FSECFUNCNAME="sharedfs"
    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && set -x

    #
    :   Constants
    #
    typeset Mount_Pt="/var/efs"		    #   AIX defined location for EFS configuration information
    typeset EFS_KeyStore_FS="/EFS_KS_JFS2"  #   File system to hold EFS configuration information
    typeset KeyStore_NFS_SS="/EFS_NFS_SS"   #   Stable storage used by NFSv4
    typeset Export_dir=$EFS_KeyStore_FS	    #   Will export this same file system
    integer Stabilization_Time=180	    #   Number of 2 second times to wait for EFS Keystore RG
					    #   to come on line

    #
    :   Flags
    #
    integer RG_added_flag=0		    #   created EFS KeyStore resource group
    integer RG_moded_flag=0		    #   modified existing EFS KeyStore resource group

    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && set -x
    #
    :	Enable EFS support using a shared file system for Keystore
    #
	
    #
    :   Check the status of the volume group, and the keystore file 
    :   system across the cluster.  The volume group must be present,
    :   the file system is added if necessary.
    #

    #
    :	Make sure this is not a linked cluster.  
    #
    #	The NFS cross mount structure used to distribute the keys below
    #	is unworkable in a linked cluster.
    if [[ -n $(clodmget -q "multi_site_lc = 1" HACMPcluster) ]]
    then
	dspmsg -s 129 cspoc.cat 182 "EFS file system key store is not supported in a linked cluster.\n" | 
	    tee -a $EFS_enable_log
	return 1
    fi

    #
    :	Make sure this volume group is not already in use
    #
    Current_RG=$(clodmget -q "value = $EFS_KeyStore_VG and group != $EFS_KeyStore_RG" -f group -n HACMPresource)
    if [[ -n $Current_RG ]]
    then
	dspmsg -s 129 cspoc.cat 183 "The given volume group for the EFS KeyStore, \"%s\", is already in use in resource group \"%s\".  \
Please choose an existing volume group that is not in any resource group.\n" $EFS_KeyStore_VG $Current_RG | 
	    tee -a $EFS_enable_log
	return 1
    fi

    #
    :	Make sure this volume group is not currently active on another node
    #
    Local_Node=$(get_local_nodename)
    cli_on_cluster -S clresactive -v $EFS_KeyStore_VG | egrep -w 'active|concurrent' | while IFS=: read node state ; do
	if [[ $node != $Local_Node ]]
	then
	    dspmsg -s 129 cspoc.cat 184 "The given volume group for the EFS KeyStore, \"%s\", is currently active on node \"%s\".  \
Please choose an existing volume group that is not currently active.\n" $EFS_KeyStore_VG $node | 
		tee -a $EFS_enable_log
	    return 1
	fi
    done

    VG_nodes=$(cli_on_cluster -S lsvg | grep -w $EFS_KeyStore_VG | cut -f1 -d: | sort -u)
    if [[ $All_cluster_nodes != $VG_nodes ]]
    then
	#
	:   The EFS KeyStore volume group $EFS_KeyStore_VG does not exist on some cluster nodes.
	:   See if this can be corrected.
	#
	if [[ -z $VG_nodes ]]
	then
	    #
	    :   User is confused - they must give us an existing volume group
	    #
	    dspmsg -s 129 cspoc.cat 185 "The given volume group for the EFS Keystore, \"%s\", does not exist in the cluster.  \
Please either create the volume group, and re-enter the command, or choose an existing volume group.\n"  $EFS_KeyStore_VG |
		tee -a $EFS_enable_log
	    return 1
	else
	    #
	    :   The given volume group $EFS_KeyStore_VG, is not known on some
	    :   nodes.  See if it can be made known on all of them.
	    :	First, find a reference node from amoungst the ones that know
	    :	of $EFS_KeyStore_VG
	    #
	    if ! print "$VG_nodes" | grep -qx $Local_Node
	    then
		print "$VG_nodes" | read ref_node rest
	    else
		ref_node=$Local_Node
	    fi
	    #
	    :	Now, find a disk on node $ref_node to use for importvg on other nodes
	    #
	    cli_on_node -N $ref_node lspv | grep -w $EFS_KeyStore_VG | read skip VG_hdisk rest
	    if [[ -n $ref_node && -n $VG_hdisk ]]
	    then
		#
		:   Try to make the volume group $EFS_KeyStore_VG known 
		:   across the cluster.
		#
		LC_ALL=C _CSPOC_MODE="both" _CSPOC_CALLED_FROM_SMIT="true" cl_importvg -y $EFS_KeyStore_VG -R ${ref_node%:} $VG_hdisk 2>&1 \
		    | tee -a $EFS_enable_log

		#
		:   Look again to see what nodes $EFS_KeyStore_VG is known on
		#
		VG_nodes=$(cli_on_cluster -S lsvg | grep -w $EFS_KeyStore_VG | cut -f1 -d: | sort -u)
		if [[ $All_cluster_nodes != $VG_nodes ]]
		then
		    #
		    :	Still did not work.  User must come up with a better choice of volume group.
		    #
		    dspmsg -s 193 cspoc.cat 186 "The given volume group for a the EFS KeyStore, \"%S\", is not known on nodes %s. \
Please re-enter the command with a volume group that is available cluster wide.\n"  $EFS_KeyStore_VG $bad_nodes \
			| tee -a $EFS_enable_log
		    return 1
		fi
	    fi
	fi
    fi

    #
    :   Now that we know that we have a good volume group, $EFS_KeyStore_VG, 
    :   make sure that there is the appropriate file system, $EFS_KeyStore_FS.  It
    :   is created if necessary.
    #
    FS_nodes=$(cli_on_cluster -S 'lsfs '$EFS_KeyStore_FS' 2>/dev/null | tail -n1' | cut -f1 -d: | sort -u)
    if [[ -z $FS_nodes ]]
    then
	#
	:   The EFS KeyStore FileSystem, $EFS_KeyStore_FS, must be created cluster wide
	#
	dspmsg -s 129 cspoc.cat 187 "Creating the EFS KeyStore FileSystem, \"%s\".\n" $EFS_KeyStore_FS | tee -a $EFS_enable_log
	crfs_out=$(LC_ALL=C cli_crlvfs -v jfs2 -g "$EFS_KeyStore_VG" -a size="$EFS_KeyStore_size" -m "$EFS_KeyStore_FS" -p'rw' -a agblksize='4096' 2>&1)
	RC=$?
	print -- "cli_crlvfs -v jfs2 -g $EFS_KeyStore_VG -a size=$EFS_KeyStore_size -m $EFS_KeyStore_FS -p'rw' -a agblksize='4096' \n\
$crfs_out" | tee -a $EFS_enable_log
	if (( $RC != 0 ))
	then
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 188 "Creation of the EFS KeyStore FileSystem, \"%s\" failed.\n" $EFS_KeyStore_FS | 
		tee -a $EFS_enable_log
	    return 2 
	fi
	#
	:   Check to see if it worked
	#
	FS_nodes=$(cli_on_cluster -S 'lsfs '$EFS_KeyStore_FS' | tail -n1' | cut -f1 -d: | sort -u)
    fi

    #
    :	Allocate a file system to be used as NFSv4 stable storage
    #
    SS_nodes=$(cli_on_cluster -S 'lsfs '$KeyStore_NFS_SS' 2>/dev/null | tail -n1' | cut -f1 -d: | sort -u)
    if [[ -z $SS_nodes ]]
    then
	#
	:   The NFS stable storage, $KeyStore_NFS_SS, must be created cluster wide
	#
	dspmsg -s 129 cspoc.cat 189 "Creating the NFSv4 Stable Storage FileSystem, \"%s\".\n" $KeyStore_NFS_SS | tee -a $EFS_enable_log
	crfs_out=$(LC_ALL=C cli_crlvfs -v jfs2 -g "$EFS_KeyStore_VG" -a size="$EFS_SS_size" -m "$KeyStore_NFS_SS" -p'rw' -a agblksize='4096' 2>&1)
	RC=$?
	print -- "cli_crlvfs -v jfs2 -g $EFS_KeyStore_VG -a size=$EFS_SS_size -m $KeyStore_NFS_SS -p'rw' -a agblksize='4096'\n\
$crfs_out" | tee -a $EFS_enable_log
	if (( $RC != 0 ))
	then
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 190 "Creation of the NFSv4 Stable Storage FileSystem, \"%s\" failed.\n" $KeyStore_NFS_SS | 
		tee -a $EFS_enable_log
	    return 2 
	fi
	#
	:   Check to see if it worked
	#
	SS_nodes=$(cli_on_cluster -S 'lsfs '$KeyStore_NFS_SS' | tail -n1' | cut -f1 -d: | sort -u)
    fi

    if [[ $FS_nodes != $All_cluster_nodes || $SS_nodes != $All_cluster_nodes ]]
    then
	#
	:   The EFS KeyStore FileSystem, $EFS_KeyStore_FS, is known on some nodes, 
	:   but not on all of them.  Try updating the volume group definition
	:   on those nodes.
	#
	cli_updatevg $EFS_KeyStore_VG 2>&1 | tee -a $EFS_enable_log

	#
	:   Check to see if it worked
	#
	FS_nodes=$(cli_on_cluster -S 'lsfs '$EFS_KeyStore_FS' | tail -n1' | cut -f1 -d: | sort -u)
	SS_nodes=$(cli_on_cluster -S 'lsfs '$KeyStore_NFS_SS' | tail -n1' | cut -f1 -d: | sort -u)
    fi

    if [[ $FS_nodes != $All_cluster_nodes ]]
    then
	#
	:   Cannot make the EFS KeyStore Filesystem, $EFS_KeyStore_FS, known on 
	:   all nodes.  Tell the user the bad news, and quit.
	#
	bad_fs_nodes=$(cli_on_cluster -S 'lsfs | grep -qpw '$EFS_KeyStore_FS' || print notfound' |\
			cut -f1 -d: | paste -s -d',' -)
	dspmsg -s 192 cspoc.cat 191 "The EFS KeyStore Filesystem, \"%s\", does not exist on node(s) %s.\n" $EFS_KeyStore_FS $bad_fs_nodes |
	    tee -a $EFS_enable_log
	return 2
    fi

    if [[ $SS_nodes != $All_cluster_nodes ]]
    then
	#
	:   Cannot make the NFSv4 Stable Store Filesystem, $KeyStore_NFS_SS, known on 
	:   all nodes.  Tell the user the bad news, and quit.
	#
	bad_ss_nodes=$(cli_on_cluster -S 'lsfs | grep -qpw '$KeyStore_NFS_SS' || print notfound' |\
			cut -f1 -d: | paste -s -d',' -)
	dspmsg -s 192 cspoc.cat 192 "The NFSv4 Stable Store Filesystem, \"%s\", does not exist on node(s) %s.\n" $KeyStore_NFS_SS $bad_ss_nodes |
	    tee -a $EFS_enable_log
	return 2
    fi

    #
    :   At this point, volume group $EFS_KeyStore_VG holding file system $EFS_KeyStore_FS
    :   should be known on all cluster nodes.  Proceed to set up the resource group to
    :   have $EFS_KeyStore_FS mounted on all cluster nodes.
    #

    #
    :   Create the resource group needed to make the EFS KeyStore file system,
    :   $EFS_KeyStore_FS, available on all nodes through NFS cross mounts.
    #
    if [[ -z $(clodmget -q "group = $EFS_KeyStore_RG" -f group -n HACMPgroup) ]]
    then
	#
	:   Resource group $EFS_KeyStore_RG does not exist, so create it
	#
        node_list=$(print $All_cluster_nodes | paste -s -d' ' -)
        clvt_out=$(claddgrp -g $EFS_KeyStore_RG -n "$node_list" -S 'OHN' -O 'FNPN' -B 'FBHPN' -I)
	RC=$?
        print -- "claddgrp -g $EFS_KeyStore_RG -n \"$node_list\" -S OHN -O FNPN -B FBHPN -I\n$clvt_out" >> $EFS_enable_log
	if (( $RC == 0 ))
	then
	    dspmsg -s 129 cspoc.cat 83 "%s added successfully\n" "$EFS_KeyStore_RG" |
		tee -a $EFS_enable_log
	    RG_added_flag=1

	else
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 193 "Creation of the resource group \"%s\" failed.\n" $EFS_KeyStore_RG |
		tee -a $EFS_enable_log
	    return 2
	fi
    else
	#
	:   The resource group already exists.  It can be used, provided
	:   it matches what we want.
	#
	node_list=$(print $All_cluster_nodes | paste -s -d' ' -)
	if [[ -z $(clodmget -q "group = $EFS_KeyStore_RG and \
				nodes = '$node_list' and \
				startup_pref = OHN and \
				fallback_pref = NFB and \
				fallover_pref = FNPN" \
			    -f group -n HACMPgroup) ]]
	then
	    #
	    :   The existing resource group $EFS_KeyStore_RG does not match
	    :   the needed policies.  We cannot proceed.
	    #
	    dspmsg -s 192 cspoc.cat 194 "Reserved name \"%s\" is already used by an existing resource group, \
and cannot be used as the EFS Filesystem KeyStore.  \
That resource group must be removed before EFS Filesystem Keystore can be configured.\n" $EFS_KeyStore_RG | 
		tee -a $EFS_enable_log
	    return 1
	fi

	#
	:   Check to make sure that the resource group $EFS_KeyStore_RG is
	:   not already running and doing NFS cross mounts.  That would get
	:   in the way of the 'efsenable' we have to do below.
	#
	if LC_ALL=C clRGinfo -c $EFS_KeyStore_RG 2>&1 | grep -qw ONLINE 
	then
	    #
	    :	The existing resource group is in the way
	    #
	    dspmsg -s 129 cspoc.cat 195 "Resource group \"%s\" is already online. \
It must be offline before EFS FileSystem KeyStore can be configured.\n" $EFS_KeyStore_RG | 
		tee -a $EFS_enable_log
	fi
    fi

    #
    :   Add the volume group $EFS_KeyStore_VG to the resource group
    #
    if [[ -z $(clodmget -q "group = $EFS_KeyStore_RG and  \
			    name = VOLUME_GROUP and \
			    value = $EFS_KeyStore_VG" \
			-f group -n HACMPresource) ]]
    then
        clvt_out=$(clchgrp -g $EFS_KeyStore_RG  -S OHN -O FNPN -B FBHPN)
        RC=$?
        print -- "clchgrp -g $EFS_KeyStore_RG  -S OHN -O FNPN -B FBHPN\n$clvt_out" >> $EFS_enable_log

        if (( $RC == 0 )); then
            clvt_out=$(claddres -g $EFS_KeyStore_RG " CONCURRENT_VOLUME_GROUP= DISK= FORCED_VARYON=false NODE_PRIORITY_POLICY= RAW_DISK= SDNP_SCRIPT_PATH= SDNP_SCRIPT_TIMEOUT= VG_AUTO_IMPORT=false VOLUME_GROUP=$EFS_KeyStore_VG USERDEFINED_RESOURCES= FALLBACK_AT= SERVICE_LABEL= APPLICATIONS= FILESYSTEM= FSCHECK_TOOL= RECOVERY_METHOD= FS_BEFORE_IPADDR= EXPORT_FILESYSTEM= EXPORT_FILESYSTEM_V4= MOUNT_FILESYSTEM= STABLE_STORAGE_PATH= WPAR_NAME= NFS_NETWORK= SHARED_TAPE_RESOURCES= AIX_FAST_CONNECT_SERVICES= COMMUNICATION_LINKS= WLM_PRIMARY= WLM_SECONDARY= MISC_DATA= NODE_PRIORITY_POLICY_SCRIPT= NODE_PRIORITY_POLICY_TIMEOUT=")
	    RC=$?
            print -- "claddres -g $EFS_KeyStore_RG CONCURRENT_VOLUME_GROUP= DISK= FORCED_VARYON=false NODE_PRIORITY_POLICY= RAW_DISK= SDNP_SCRIPT_PATH= SDNP_SCRIPT_TIMEOUT= VG_AUTO_IMPORT=false VOLUME_GROUP=$EFS_KeyStore_VG USERDEFINED_RESOURCES= FALLBACK_AT= SERVICE_LABEL= APPLICATIONS= FILESYSTEM= FSCHECK_TOOL= RECOVERY_METHOD= FS_BEFORE_IPADDR= EXPORT_FILESYSTEM= EXPORT_FILESYSTEM_V4= MOUNT_FILESYSTEM= STABLE_STORAGE_PATH= WPAR_NAME= NFS_NETWORK= SHARED_TAPE_RESOURCES= AIX_FAST_CONNECT_SERVICES= COMMUNICATION_LINKS= WLM_PRIMARY= WLM_SECONDARY= MISC_DATA= NODE_PRIORITY_POLICY_SCRIPT= NODE_PRIORITY_POLICY_TIMEOUT= \n$clvt_out" >> $EFS_enable_log
        fi

	if (( $RC != 0 ))
	then
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 196 "Additon of volume group \"%s\" to resource group \"%s\" failed.\n" $EFS_KeyStore_VG $EFS_KeyStore_RG |
		tee -a $EFS_enable_log
	    if (( $RG_added_flag != 0 ))
	    then
		#
		:   Clean up the resource group we added
		#
		clvt delete resource_group $EFS_KeyStore_RG 2>&1 | tee -a $EFS_enable_log
		return 1
	    fi
	fi
	RG_moded_flag=1			#   Will need to do a sync
    fi

    #
    :   Set up NFS cross mounts for the resource group $EFS_KeyStore_RG
    #
    if [[ -z $(clodmget -q "group = $EFS_KeyStore_RG and name = SERVICE_LABEL and value = $Service_IP" -f group -n HACMPresource) ||
	  -z $(clodmget -q "group = $EFS_KeyStore_RG and name = EXPORT_FILESYSTEM_V4 and value = $Export_dir" -f group -n HACMPresource) ||
	  -z $(clodmget -q "group = $EFS_KeyStore_RG and name = MOUNT_FILESYSTEM and value = $Mount_Pt" -f group -n HACMPresource) ||
	  -z $(clodmget -q "group = $EFS_KeyStore_RG and name = STABLE_STORAGE_PATH and value = $KeyStore_NFS_SS" -f group -n HACMPresource) ]]
    then
        clvt_out=$(clchgrp -g $EFS_KeyStore_RG -S OHN -O FNPN -B FBHPN)
        RC=$?
        print -- "clchgrp -g $EFS_KeyStore_RG -S OHN -O FNPN -B FBHPN\n$clvt_out" >> $EFS_enable_log
        if (( $RC == 0 ));then
            clvt_out=$(claddres -g $EFS_KeyStore_RG " DISK= EXPORT_FILESYSTEM_V4=$Export_dir FILESYSTEM= FORCED_VARYON=false FSCHECK_TOOL=fsck FS_BEFORE_IPADDR=true MOUNT_FILESYSTEM=${Mount_Pt};${Export_dir} NODE_PRIORITY_POLICY= RAW_DISK= SDNP_SCRIPT_PATH= SDNP_SCRIPT_TIMEOUT= SERVICE_LABEL=$Service_IP STABLE_STORAGE_PATH=$KeyStore_NFS_SS VG_AUTO_IMPORT=false RECOVERY_METHOD=sequential SSA_DISK_FENCING=false VOLUME_GROUP=$EFS_KeyStore_VG USERDEFINED_RESOURCES= FALLBACK_AT= APPLICATIONS= EXPORT_FILESYSTEM= WPAR_NAME= NFS_NETWORK= SHARED_TAPE_RESOURCES= AIX_FAST_CONNECT_SERVICES= COMMUNICATION_LINKS= WLM_PRIMARY= WLM_SECONDARY= MISC_DATA= NODE_PRIORITY_POLICY_SCRIPT= NODE_PRIORITY_POLICY_TIMEOUT= CONCURRENT_VOLUME_GROUP=")
            RC=$?
            print -- "claddres -g $EFS_KeyStore_RG DISK= EXPORT_FILESYSTEM_V4=$Export_dir FILESYSTEM= FORCED_VARYON=false FSCHECK_TOOL=fsck FS_BEFORE_IPADDR=true MOUNT_FILESYSTEM=${Mount_Pt};${Export_dir} NODE_PRIORITY_POLICY= RAW_DISK= SDNP_SCRIPT_PATH= SDNP_SCRIPT_TIMEOUT= SERVICE_LABEL=$Service_IP STABLE_STORAGE_PATH=$KeyStore_NFS_SS VG_AUTO_IMPORT=false RECOVERY_METHOD=sequential SSA_DISK_FENCING=false VOLUME_GROUP=$EFS_KeyStore_VG USERDEFINED_RESOURCES= FALLBACK_AT= APPLICATIONS= EXPORT_FILESYSTEM= WPAR_NAME= NFS_NETWORK= SHARED_TAPE_RESOURCES= AIX_FAST_CONNECT_SERVICES= COMMUNICATION_LINKS= WLM_PRIMARY= WLM_SECONDARY= MISC_DATA= NODE_PRIORITY_POLICY_SCRIPT= NODE_PRIORITY_POLICY_TIMEOUT= CONCURRENT_VOLUME_GROUP= \n$clvt_out" >> $EFS_enable_log
        fi

	if (( $RC != 0 ))
	then
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 197 "Enabling NFSv4 cross mounts for resource group \"%s\" failed.\n" $EFS_KeyStore_RG |
		tee -a $EFS_enable_log
	    if (( $RG_added_flag != 0 ))
	    then
		clvt delete resource_group $EFS_KeyStore_RG 2>&1 | tee -a $EFS_enable_log
		return 1
	    fi
	fi
	RG_moded_flag=1			#   Will need to do a sync
    fi

    if (( $RG_added_flag == 1 || $RG_moded_flag == 1 ))
    then
	#
	:   Having created or changed the resource group $EFS_KeyStore_RG, 
	:   force a requirement for verify and sync
	#
	Class="HACMPcluster:"
	handle="handle=0"
	if ! printf "%s\n%s\n" $Class $handle | odmchange -o HACMPcluster
	then
	    dspmsg -s 129 cspoc.cat 198 "Failed to update the configuration.  A Verification and Synchronization is required.\n"  | 
		tee -a $EFS_enable_log
	fi
    fi
    
    #
    :   Create an \"expect\" script to run the base AIX \"efsenable\" command 
    :   to turn on EFS support, using the shared file system as a key store.
    #
    cr_expect_efsconf                       #   Create ${EXPECT_FILE} expect script
    RC=$?
    if (( $RC != 0 ))
    then
	return $RC			    #	any diagnostic information from efsconf
    fi

    #
    :	Bring the volume group $EFS_KeyStore_VG on line, and mount
    :	$EFS_KeyStore_FS over /var/efs.  This will allow us to capture
    :	the updated keys for replication to other nodes.
    #
    varyon_flag=$(clresactive -v $EFS_KeyStore_VG)
    if [[ $varyon_flag != 'active' && $varyon_flag != 'concurrent' ]]
    then
	varyonvg_out=$(LC_ALL=C clvaryonvg $EFS_KeyStore_VG 2>&1)
	RC=$?
	print -- "clvaryonvg $EFS_KeyStore_VG\n$varyonvg_out" | tee -a $EFS_enable_log
	if (( $RC != 0 ))
	then
	    #
	    :   Despite all the careful checking above, cannot bring $EFS_KeyStore_VG
	    :   on line locally
	    #
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 199 "Unable to access shared volume group \"%s\".\n" $EFS_KeyStore_VG |
		tee -a $EFS_enable_log
	    return $RC			    #	any diagnostic information from varyonvg
	fi
    fi

    #
    :	Carefully position the file system that will be used for the shared
    :	EFS KeyStore on top of where the AIX 'efsenable' command will place
    :	they keys.  This information can then be made accessible to other 
    :	nodes via NFS cross mount, once $EFS_KeyStore_RG is on line.
    #
    lsvg -l $EFS_KeyStore_VG | grep -w ${EFS_KeyStore_FS} | read lv_name rest
    if [[ -z $lv_name ]]
    then
	#
	:   Despite all the careful work above, $EFS_KeyStore_VG does not 
	:   appear to contain the expected file system $EFS_KeyStore_FS.
	:   Something has gone terribly wrong, and we cannot proceed.
	#
	dspmsg -s 129 cspoc.cat 200 "File system \"%s\" not found in \"%s.\".\n" $EFS_KeyStore_FS $EFS_KeyStore_VG |
	    tee -a $EFS_enable_log
	return 2
    fi

    #
    :	Make sure that every node has a '/var/efs' file system mount point
    #
    missing_nodes=""
    cli_on_cluster -S 'ls -d /var/efs >/dev/null 2>&1 || print "/var/efs missing on node $(get_local_nodename)"' |
    while IFS=: read missing_node rest
    do
	#
	:   $rest
	#
	missing_nodes=${missing_nodes:+"${missing_nodes},"}${missing_node}
    done
    if [[ -n $missing_nodes ]]
    then
	#
	:   Creating /var/efs on nodes $missing_nodes
	#
	cli_on_node -N "$missing_nodes" 'mkdir -p /var/efs'
    fi

    #
    :	If not already present, mount $EFS_KeyStore_FS on top of /var/efs, 
    :	to have AIX initialize it
    #
    if ! mount | grep /dev/${lv_name} | grep -q /var/efs
    then
	#
	:   Clear any spurious annoying mountguard
	#
	stanza=$(grep -p $EFS_KeyStore_FS /etc/filesystems | tr '\t' ' ')
	mountguard=$(print "$stanza" | sed -n '/mountguard/s/^.*= \([^ ]*\).*/\1/p')
	if [[ $mountguard == 'yes' ]]
	then
	    log_lv=$(print "$stanza" | sed -n '/log/s/^.*= \([^ ]*\).*/\1/p')
	    if [[ $log_lv == 'INLINE' ]]
	    then
		log_lv=$lv_name
	    fi
	    if [[ -n $log_lv ]]
	    then
		logredo $log_lv
	    fi
	fi
	mount_out=$(LC_ALL=C mount /dev/${lv_name} /var/efs 2>&1)
	RC=$?
	print -- "mount /dev/${lv_name} /var/efs\n$mount_out" | tee -a $EFS_enable_log
	if (( $RC != 0 ))
	then
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat  201 "Unable to access shared file system \"%s\" in \"%s\".\n" $EFS_KeyStore_FS $EFS_KeyStore_VG |
		tee -a $EFS_enable_log
	    return 2
	fi
	#
	:   Clean up any old files on the shared key store
	#
	#   This is not done in efs_reset, and is easier to do here.
	#   If it is not done, then old files will prevent efsenable -a
	#   will fail, assuming that EFS is already enabled.
	#
	print -- 'rm -rf /var/efs/*' | tee -a $EFS_enable_log
	rm -rf /var/efs/*
    fi

    #
    :	Run the \"expect\" script locally to enable EFS on this node
    #
    dspmsg -s 129 cspoc.cat 202 "Enabling EFS support in AIX.  Please wait...\n"
    expect_out=$(LC_ALL=C ${EXPECT_FILE_FS} ${ADMIN_PW} 2>&1)
    RC=$?
    print -- "${EXPECT_FILE_FS} ${ADMIN_PW}\n$expect_out" | tee -a $EFS_enable_log
    if (( $RC != 0 )) 
    then
	print -- "RC=$RC" | tee -a $EFS_enable_log
	dspmsg -s 129 cspoc.cat 203 "Unable to enable EFS support in AIX.\n" |
	    tee -a $EFS_enable_log
	return $RC
    fi

    #
    :	Get the shared file system out of the way
    #
    umount_out=$(LC_ALL=C umount /dev/${lv_name} 2>&1)
    RC=$?
    print -- "umount /dev/${lv_name}\n$umount_out" | tee -a $EFS_enable_log
    if (( $RC != 0 ))
    then
	print -- "RC=$RC" | tee -a $EFS_enable_log
	dspmsg -s 129 cspoc.cat  204 "Unable to release shared file system \"%s\" in \"%s\".\n" $EFS_KeyStore_FS $EFS_KeyStore_VG |
	    tee -a $EFS_enable_log
	return 2
    fi
    
    #
    :	Put the volume group $EFS_KeyStore_VG back where it was before
    #
    if [[ $varyon_flag == "passive" ]]
    then
	#
	:   Currently on line in active mode
	#
	#   This would be the case if the cluster is up and running,
	#   and $EFS_KeyStore_VG was already present in $EFS_KeyStore_RG
	#
	varyoffvg_cmd="varyonvg -n -c -P $EFS_KeyStore_VG"
	varyoffvg_out=$(LC_ALL=C varyonvg -n -c -P $EFS_KeyStore_VG 2>&1)
	RC=$?
    elif [[ $varyon_flag == 'inactive' ]]
    then
	#
	:   Currently on line
	#
	varyoffvg_cmd="varyoffvg $EFS_KeyStore_VG"
	varyoffvg_out=$(LC_ALL=C varyoffvg $EFS_KeyStore_VG 2>&1)
	RC=$?
    fi
    RC=$?
    #
    :	Set fence height and correct saved volume group time stamps,
    :	if running on a level that supports that.
    #
    if [[ $varyon_flag == "passive" ]] && (( $RC == 0 ))
    then
	cl_set_vg_fence_height -c $EFS_KeyStore_VG ro
    fi
    [[ -x $(whence -p cl_update_vg_odm_ts) ]] && cl_update_vg_odm_ts $EFS_KeyStore_VG
    print -- "$varyoffvg_cmd\n$varyoffvg_out" | tee -a $EFS_enable_log
    if (( $RC != 0 ))
    then
	#
	:   Despite all the careful checking above, cannot release $EFS_KeyStore_VG
	#
	print -- "RC=$RC" | tee -a $EFS_enable_log
	dspmsg -s 129 cspoc.cat 205 "Unable to release shared volume group \"%s\".\n" $EFS_KeyStore_VG |
	    tee -a $EFS_enable_log
	return $RC			    #	any diagnostic information from varyonvg/varyoffvg
    fi

    #
    :	Get a copy of that expect script to every other node in location ${EXPECT_FILE}
    #
    All_other_nodes=$(print "$All_cluster_nodes" | grep -vx $Local_Node)
    for node in $All_other_nodes
    do
	dspmsg -s 129 cspoc.cat 206 "Enabling EFS support in AIX on node \"%s\".  Please wait...\n" $node |
	    tee -a $EFS_enable_log
	#
	:   Copy $EXPECT_FILE to $node
	#
	clrcp_out=$(LC_ALL=C cl_rcp ${EXPECT_FILE_FS} ${node}:${EXPECT_FILE_FS} 2>&1)
	RC=$?
	print -- "cl_rcp ${EXPECT_FILE_FS} $node:${EXPECT_FILE_FS}\n$clrcp_out" |
	    tee -a $EFS_enable_log
	if (( $RC != 0 ))
	then
	    #
	    :   Copy to $node failed.  Operation halts.
	    #
	    print -- "RC=$RC" | tee -a $EFS_enable_log
	    dspmsg -s 129 cspoc.cat 207 "Copy of efsenable expect script to node \"%s\" failed.\n" $node |
		tee -a $EFS_enable_log
	    return 2
	fi

	#
	:   Run the expect script to run the base AIX \"efsenable\" command to enable EFS 
	:   on node $node using shared file system as a key store.
	#
	runexpect_out=$(LC_ALL=C cli_on_node -N $node ${EXPECT_FILE_FS} $ADMIN_PW 2>&1)
	RC=$?
	print -- "cli_on_node -N $node ${EXPECT_FILE_FS} $ADMIN_PW\n$runexepect_out" |
	    tee -a $EFS_enable_log
	if (( $RC != 0 ))
	then
	    #
	    :	Setting up EFS failed on node $node
	    #
	    dspmsg -s 129 cspoc.cat 208 "Unable to enable EFS support in AIX on node \"%s\".\n" |
		tee -a $EFS_enable_log
	    return $RC
	fi
    done
    
    return 0				#   success
}


#######################################################################
#
#   Function:	cr_expect_efsldapconf
#
#   Purpose:	Build an expect script (that is, input for the "expect"
#		command) that will invoke the "efsenable" command for
#		LDAP keystore and set up the initial keystore password.
#
#   Input:	None
#
#   Output:	An expect script is created in 
#		/var/hacmp/log/fsec/$(date +%Y.%m.%d.%Hh%Mm%Ss-FailedConf)/powerha_efsldap.exp.$$
#
#   Notes:	An arbitrary time out of 60 seconds is used.  This is
#		based on experience alone.
#
#######################################################################
function cr_expect_efsldapconf
{

    typeset FSECFUNCNAME="cr_expect_efsldapconf"
    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && set -x
    EXPECT_FILE_LDAP="${FSEC_LOG_DIR}/powerha_efsldap.exp.$$"

    #
    :	The following lines go into $EXPECT_FILE_LDAP
    #
    print -- '#!/usr/bin/expect

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

set env(LC_ALL) C
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_LDAP

    #
    :   Check for successfule file creation
    #
    if [[ -s $EXPECT_FILE_LDAP ]]
    then
	#
	:   $EXPECT_FILE_LDAP exists and is not empty.  Make it executable
	#
	chmod +x $EXPECT_FILE_LDAP
	if [[ $VERBOSE_LOGGING == high ]] 
	then
	    #
	    :	Here is the expect file, $EXPECT_FILE_LDAP
	    #
	    cat -n $EXPECT_FILE_LDAP | tee -a $EFS_enable_log
	fi
	return 0
    else
	dspmsg -s 129 cspoc.cat 158 "'Expect' script not created in %1$s.\n" $EXPECT_FILE_LDAP |
	    tee -a $EFS_enable_log
	return 2		#   game over, man, game over!
    fi
}


#######################################################################
#
#   Function:	efs_ldap_conf
#
#   Purpose:	Enable LDAP KeyStore support for EFS
#
#######################################################################
function efs_ldap_conf
{
    typeset FSECFUNCNAME="efs_ldap_conf"
    [[ -n $FSECDEBUG || $VERBOSE_LOGGING == "high" ]] && 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 

    for i in $All_cluster_nodes
    do
	cl_rsh -n $i "LC_ALL=C 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 != 0 && $ret_code != 20 && $ret_code != 68 ))
	then
	    ret_fail "ldapadd failed." $ret_code
	fi
    done
    cr_expect_efsldapconf
    for i in $All_cluster_nodes
    do
	cl_rcp $EXPECT_FILE_LDAP ${i}:${EXPECT_FILE_LDAP} >/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." $?
}


###############################################################################
#
#   Main
#
while getopts ':s:v:m:A:Rk:p:Q' option
do
    case $option in
        s)  :	Service IP	;   Service_IP=$OPTARG
	    ;;

        v)  :	VG Name		;   EFS_KeyStore_VG=$OPTARG
	    ;;

        m)  :	mode LDAP or FS	;   MODE=$OPTARG
	    ;;

	A)  :	password	;   ADMIN_PW=$OPTARG
	    ;;

	R)  :	reset efsenable	;   Reset="yes"
	    ;;

	Q)  :	query efsenable	;   Query="yes"
	    ;;

        k)  :   KeyStore file system size override
            :   passed to mkfs unchecked
            EFS_KeyStore_size=$OPTARG
            ;;
 
        p)  :   KeyStore stable storage file system size override
            :   passed to mkfs unchecked
            EFS_SS_size=$OPTARG
            ;;

        *)  :	Anything else is invalid 
	    print -u2
            dspmsg -s 4 utilities.cat 50 '%1$s: unknown option "%2$s"\n' "$(/usr/bin/basename $0)" "-$OPTARG" 1>&2
	    dspmsg -s 129 cspoc.cat 115 "Usage: %s {-m 1 -A <password>} {-m 2 -A <password> -v <volume group> -s <service IP>}\n" "$0" 1>&2
            return 1
	    ;;
    esac
done

#
:   Check for sufficient authority to run the various commands below
#
if [[ $(whoami) != "root" ]] && ! ckauth PowerHASM.admin
then
    dspmsg -s 129 cspoc.cat 52 \
	"%s: All C-SPOC commands require the user to either be root, or have PowerHASM.admin authorization\n" "$_CMD"
    exit 2
fi

#
:   Record invocation
#
print "$(LC_ALL=C date +%Y.%m.%d.%Hh%Mm%Ss) $0 version=${version} $*" >> $EFS_enable_log

if [[ $Reset == "yes" ]]
then
    if [[ -n $Service_IP || -n $EFS_KeyStore_VG || -n $MODE || -n $ADMIN_PS ]]
    then
	#
	:   '-R' cannot be mixed with any other option
	#
	print -u2
	dspmsg -s 4 utilities.cat 50 '%1$s: unknown option "%2$s"\n' "$(/usr/bin/basename $0)" "-$OPTARG" 1>&2
	dspmsg -s 129 cspoc.cat 115 "Usage: %s {-m 1 -A <password>} {-m 2 -A <password> -v <volume group> -s <service IP>}\n" "$0" 1>&2
	return 1
    fi
    #
    :	Reset the configuration to where cl_enable_efs can be run again
    #
    efs_reset
    RC=$?
    return $RC
fi

if [[ $Query == "yes" ]]
then
    if [[ -n $Service_IP || -n $EFS_KeyStore_VG || -n $MODE || -n $ADMIN_PS ]]
    then
	#
	:   '-Q' cannot be mixed with any other option
	#
	print -u2
	dspmsg -s 4 utilities.cat 50 '%1$s: unknown option "%2$s"\n' "$(/usr/bin/basename $0)" "-$OPTARG" 1>&2
	dspmsg -s 129 cspoc.cat 115 "Usage: %s {-m 1 -A <password>} {-m 2 -A <password> -v <volume group> -s <service IP>}\n" "$0" 1>&2
	return 1
    fi
    #
    :	Check to see how far along we are
    #
    efs_query
    RC=$?
    return $RC
fi

#
:   Check for required parameters, mode and initial password
#
if [[ -z $MODE ]]
then
    dspmsg -s 129 cspoc.cat 210 "The mode (the \"-m\" parameter) must be suppied. \
The mode must be \"%s\" for LDAP KeyStore or \"%s\" for filesystem KeyStore.\n" $LDAP $FILE_SYSTEM |
	tee -a $EFS_enable_log
	return 1
    return 1
fi	

if [[ -z $ADMIN_PW ]]
then
    dspmsg -s 129 cspoc.cat 211 "The initial password (the \"-A\" parameter) must be supplied.\n" |
	tee -a $EFS_enable_log
    return 1
fi

#
:   Check for required operands based on mode
#
case $MODE in
    $LDAP )	    :   Checks specific to LDAP mode
	if [[ -n $Service_IP || -n $EFS_KeyStore_VG ]]
	then
	    dspmsg -s 129 cspoc.cat 116 "INFORMATION: Volume group and Service IP are not required, and will be ignored in LDAP mode.\n" |
		tee -a $EFS_enable_log
	fi
	;;
	
    $FILE_SYSTEM )  :   Checks specific to file system mode
	if [[ -z $Service_IP ]]
	then
	    #
	    :	We were not given a service IP address.  Check and see if one is present in the resource group
	    :	that we will use.
	    #
	    Service_IP=$(clodmget -q "name = SERVICE_LABEL and group = $EFS_KeyStore_RG" -f value -n HACMPresource)
	    Service_IP=$(clodmget -q "ip_label = $Service_IP and function = shared" -f ip_label -n HACMPadapter)
	    if [[ -z $Service_IP ]]
	    then
		dspmsg -s 129 cspoc.cat 212 "A Service IP address is required for shared filesystem KeyStore.\n" |
		    tee -a $EFS_enable_log
		return 1
	    fi
	fi
	if [[ -z $EFS_KeyStore_VG ]]
	then
	    #
	    :	We were not given a volume group.  Check and see if one is present in the resource group
	    :	that we will use.
	    #
	    EFS_KeyStore_VG=$(clodmget -q "name = VOLUME_GROUP and group = $EFS_KeyStore_RG" -f value -n HACMPresource)
	    if [[ -z $EFS_KeyStore_VG ]]
	    then
		dspmsg -s 129 cspoc.cat 213 "A volume group is required for shared filesystem KeyStore.\n" |
		    tee -a $EFS_enable_log
		return 1
	    fi
        fi
	;;

    * )		    :   Anything else is invalid
	dspmsg -s 129 cspoc.cat 214 "The given mode, \"%s\", is not valid.  \
The mode must be \"%s\" for LDAP KeyStore or \"%s\" for filesystem KeyStore.\n" $MODE $LDAP $FILE_SYSTEM |
	    tee -a $EFS_enable_log
	return 1
	;;
esac

#
:   Check to ensure that keystore is not already defined
#
if [[ -n $(clodmget -n -q "group=EFSKeyStore AND name=mode" -f value HACMPLDAP) ]] 
then
    dspmsg -s 129 cspoc.cat 155 "EFS Keystore is already configured for PowerHA SystemMirror.\n" |
	tee -a $EFS_enable_log
    return 1
fi
	
if (( $MODE == $FILE_SYSTEM )) && [[ -n $(clodmget -n -q "group=LDAPServer AND name=ServerList" HACMPLDAP) ]]
then
    dspmsg -s 129 cspoc.cat 63 "LDAP is already configured in Cluster, Use LDAP mode.\n" |
	tee -a $EFS_enable_log
    return 1								  
fi

#
:   Pick up the list of current nodes.  Because operations must be performed on 
:   remote nodes, the cluster membership must be complete at this point.
#
All_cluster_nodes=$(cllsnode -c | tail +2 | cut -f1 -d: | sort -u)
if [[ -z $All_cluster_nodes ]]
then
    dspmsg -s 129 cspoc.cat 215 "Nodes are not yet configured to PowerHA SystemMirror.  \
The cluster must be configured, and the definition synchronized, before EFS can be enabled.\n" |
	tee -a $EFS_enable_log
    return 1
fi
	
#
:   Check cluster for ODM cluster wide consistency
#
#   Operations below can update HACMPLDAP, HACMPgroup, HACMPcluster and HACMPresource,
#   so the local ODMs must be in a consistent state.
#
odm_check

#
:   Check to make sure expect is present on all nodes
#
missing_expect_nodes=$(/usr/es/sbin/cluster/cspoc/cli_on_cluster -S "lslpp -lcqOu expect.base >/dev/null || print 'not found'" | 
			cut -f1 -d: | paste -s -d',' -)
if [[ -n $missing_expect_nodes ]]
then
    dspmsg -s 129 cspoc.cat 208 "The 'Expect' package is not present on node(s) \"%s\".\
This package must be present on all cluster nodes in order to configure EFS support.\
It can be downloaded from ftp.software.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/ppc/tcltk\n" $missing_expect_nodes |
	tee -a $EFS_enable_log
fi

#
:   End of input validation
:   Processing based on key storage type
#
if (( $MODE == $LDAP ))
then 
    #
    :	Enable EFS support using LDAP for Keystore
    #
    efs_ldap_conf
    RC=$?
else
    #
    :	Enable EFS support using a shared file system for Keystore
    #
    enable_efs_sharedfs
    RC=$?
fi
if (( $RC != 0 ))
then
    #
    :	Tell the user the bad news
    #
    dspmsg -s 129 cspoc.cat 216 "Configuration of EFS KeyStore was not successful. \
See %s for more information.\n" $EFS_enable_log | \
	tee -a $EFS_enable_log
    return $RC		    #	See messages from enable_efs_sharedfs/ldap for cause
fi

if [[ $VERBOSE_LOGGING != "high" && -z $FSECDEBUG ]]
then
    #
    #	If not tracing, and need them for debug
    :   Clean up work files on success
    #
    cli_on_cluster -S "rm -f $TMP_EFS_LDIF $EXPECT_FILE_FS $EXPECT_FILE_LDAP" |
        tee -a $EFS_enable_log

fi

#
:   Create the stanza in HACMPLDAP that indicates the mode of operation
#
Class="HACMPLDAP:"
group="group=EFSKeyStore"
type="type=EFS"
name="name=mode"
value="value=$MODE"
if ! printf "%s\n%s\n%s\n%s\n%s\n" $Class $group $type $name $value | odmadd
then
    dspmsg -s 129 cspoc.cat 71 "Could not create a stanza for the EFS KeyStore resource group in ODM class HACMPLDAP.\n" |
	tee -a $EFS_enable_log
    #
    :	EFS is left enabled...
    #
    return 1
else
    if [[ -z $(clodmget -q "handle = 0" HACMPcluster) ]]
    then
	#
	:   Having updated the security configuration, force a requirement for synchronization
	#
	Class="HACMPcluster:"
	handle="handle=0"
	if ! printf "%s\n%s\n" $Class $handle | odmchange -o HACMPcluster
	then
	    dspmsg -s 129 cspoc.cat 198 "Failed to update the configuration.  A Verification and Synchronization is required.\n"
		tee -a $EFS_enable_log
	    return 2
	fi
    fi
fi 

#
:   Tell the user the good news
#
dspmsg -s 129 cspoc.cat 73 "EFS Keystore is enabled.\n" | tee -a $EFS_enable_log

#
:   Inform the user of the need for a synchronization operation
#
if [[ -n $(clodmget -q "handle = 0" HACMPcluster) ]]
then
    dspmsg -s 129 cspoc.cat 81 "The PowerHA SystemMirror configuration has been changed - the EFS KeyStore configuration has been changed. \
The configuration must be synchronized to make this change effective across the cluster.\n" |
	tee -a $EFS_enable_log
    if [[ $MODE == $FILE_SYSTEM ]] &&
	! LC_ALL=C clRGinfo $EFS_KeyStore_RG 2>&1 | grep -qw ONLINE
    then
	dspmsg -s 129 cspoc.cat 217 "The resource group \"%s\" must be online prior to creating any EFS file systems.\n" $EFS_KeyStore_RG |
	    tee -a $EFS_enable_log
    fi
fi

return 0
