#!/bin/ksh

export try_out try_err cspoc_tmp_log
export FPATH=/usr/es/sbin/cluster/cspoc

cspoc_tmp_log=/var/hacmp/log/cel$$_tmplog
log_cmd $cspoc_tmp_log $0 $*

trap 'cexit $cspoc_tmp_log $?' EXIT
function cel_f1
{
    cel_s1=/tmp/cel$$_s1
    try_err=${cel_s1}.err
    try_out=${cel_s1}.out
    trap "log_output $cspoc_tmp_log ${cel_s1} 	    eval $LSLPP_CMD" EXIT
    cdsh $cel_s1 $Check_nodes -q1 	    eval $LSLPP_CMD
    IFS=,$IFS
    for node in $Check_nodes; do
	cel_rc=$(get_rc ${cel_s1} $node)
	case $cel_rc in
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
function cel_f2
{
    cel_s2=/tmp/cel$$_s2
    try_err=${cel_s2}.err
    try_out=${cel_s2}.out
    trap "log_output $cspoc_tmp_log ${cel_s2} 	lsdev -l $lsdev_name" EXIT
    IFS=,$IFS
    for node in $Check_nodes; do
	cdsh $cel_s2 $node -q 	lsdev -l $lsdev_name
	cel_rc=$(get_rc ${cel_s2} $node)
	case $cel_rc in
	    0)
			    #
			    :	lsdev always returns success, so we have to check
			    :	the output to see if there is anything there
			    #
			    if grep '^'${node}':' $try_out | egrep -qw -e "${Check_name}|r${Check_name}"
			    then
				bad_nodes=${bad_nodes:+$bad_nodes","}${node}
				try_rc=1
			    fi
		;;
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
function cel_f3
{
    cel_s3=/tmp/cel$$_s3
    try_err=${cel_s3}.err
    try_out=${cel_s3}.out
    trap "log_output $cspoc_tmp_log ${cel_s3} 	ls $slashdev" EXIT
    IFS=,$IFS
    for node in $Check_nodes; do
	cdsh $cel_s3 $node -q 	ls $slashdev
	cel_rc=$(get_rc ${cel_s3} $node)
	case $cel_rc in
	    0)
			    #
			    :	The ls command should always return success.  This 
			    :	formulation chosen to avoid filling up the log with
			    :	spurious remote command failure messages.  Now, see
			    :	if the name we are checking for is there.
			    #
			    if grep '^'${node}':' $try_out | egrep -qw -e "${Check_name}|r${Check_name}"
			    then
				bad_nodes=${bad_nodes:+$bad_nodes","}${node}
				try_rc=1
			    fi
		;;
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
function cel_f4
{
    cel_s4=/tmp/cel$$_s4
    try_err=${cel_s4}.err
    try_out=${cel_s4}.out
    trap "log_output $cspoc_tmp_log ${cel_s4} 		    eval $ECMD" EXIT
    IFS=,$IFS
    for node in $Cluster_node; do
	cdsh $cel_s4 $node -q1 		    eval $ECMD
	cel_rc=$(get_rc ${cel_s4} $node)
	case $cel_rc in
	    0)
					#
					:   Comma separated list of nodes on which the disk
					:   appears that are not in \$_TARGET_NODES
					#
					Disk_nodes=${Disk_nodes:+$Disk_nodes","}${node}
					#
					:   Corresponding comma separated list of names that
					:   the disk appears under on those nodes
					#
					Disk_names=${Disk_names:+$Disk_names","},$(grep -w ^${node} $try_out | cut -f2 -d: | cut -f2 -d' ')
		;;
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
function cel_f5
{
    cel_s5=/tmp/cel$$_s5
    try_err=${cel_s5}.err
    try_out=${cel_s5}.out
    trap "log_output $cspoc_tmp_log ${cel_s5}     eval $rename_cmd" EXIT
    cdsh $cel_s5 $_TARGET_NODES -q1     eval $rename_cmd
    IFS=,$IFS
    for node in $_TARGET_NODES; do
	cel_rc=$(get_rc ${cel_s5} $node)
	case $cel_rc in
	    *)
		if [ $cel_rc != 0 ]; then
		    	ran_cmd="$(print $rename_cmd | cldecodearg)"
		    	nls_msg -2 -l $cspoc_tmp_log $_MSET 82 "cl_rendisk: rename of $DOld_disk to $DNewName ($ran_cmd) failed on node $node\n" $DOld_name $DNewName "$ran_cmd" $node
		    	try_rc=1
		fi
		;;
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
function cel_f6
{
    cel_s6=/tmp/cel$$_s6
    try_err=${cel_s6}.err
    try_out=${cel_s6}.out
    trap "log_output $cspoc_tmp_log ${cel_s6} 		eval $rename_cmd" EXIT
    IFS=,$IFS
    for node in $disk_node; do
	cdsh $cel_s6 $node -q1 		eval $rename_cmd
	cel_rc=$(get_rc ${cel_s6} $node)
	case $cel_rc in
	    *)
		if [ $cel_rc != 0 ]; then
		    		    ran_cmd="$(print $rename_cmd | cldecodearg)"
		    		    nls_msg -2 -l $cspoc_tmp_log $_MSET 82 "cl_rendisk: rename of $disk_name to $DNewName ($ran_cmd) failed on node $node\n" $disk_name $DNewName "$ran_cmd" $node
		    		    try_rc=1
		    IFS=${IFS#,}
		    return
		fi
		;;
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/usr/sbin/cluster/cspoc/plans/cl_rendisk.cel 1.3 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2010,2011 
# 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 
# $Id$
###############################################################################
#
# Name:
#   cl_rendisk.cel
#
# Description:
#   The cl_rendisk command renames a physical volume on all nodes of the cluster
#
#   Usage: cl_rmmp -cspoc "[-f] [-g ResourceGroup | -n NodeList ]" \
#          -N NewDiskName [-Y PVID ] CurrentDiskName
#
# Arguments:
#   Current disk name on the given list of nodes
#   Proposed new disk name
#   Disk PVID, indicating that the disk with that PVID is to be renamed on 
#   all cluster nodes
#
#   The C-SPOC specific arguments are as follows:
#       -f                      C-SPOC force flag
#       -g ResourceGroup        Resource group on which to execute cl_chvg
#       -n NodeList             Cluster nodes on which to execute cl_chvg
#
# Return Values:
#       0       success
#       1       failure
#
################################################################################
######################################################################
#
#   Function:	Check to make sure that the 'rendev' command is 
#		available on all nodes on which the disk is going
#		to be changed
#
#   Input:	Current Device name
#		Proposed new device name
#		List of nodes to check in $Check_nodes
#
#   Output:	return code 
#		0 = command is available
#
######################################################################
can_rendev()
{
    [[ -n $_DEBUG ]] && {
        print "DEBUG: Entering can_rendev version $Source: 61haes_r711 43haes/usr/sbin/cluster/cspoc/plans/cl_rendisk.cel 1$2"
	(( $_DEBUG >= 8 )) && {
	    typeset PROGNAME=can_rendev
	    set -x
	}
    }
    integer V R M F
    typeset -Z2 R                       # two digit release
    typeset -Z3 M                       # three digit modification
    typeset -Z3 F                       # three digit fix
    integer VRMF=0
    typeset do_check=false		# need to check each node
    typeset LSLPP_CMD
    typeset NODE_LIST
    typeset bad_nodes
    integer rc=0			# return code
    #
    :   Pick up passed parameters.  Used for error messages
    #
    Orig_name=$1	    # current disk name, unencoded
    Check_name=$2	    # proposed new disk name, unencoded
    bad_nodes=""	    # nodes on which there is a name collision
    #
    :	First, check the already collected level of PowerHA across the
    :	cluster.  If its 7.1 or greater, the known AIX pre-req means 
    :	that mirror pools are supported
    #
    if [[ -s /usr/es/sbin/cluster/etc/config/haver.info ]]
    then
	tail +2 /usr/es/sbin/cluster/etc/config/haver.info | \
	    while read node ha_level 
		do
		    if (( $ha_level <= 7100 ))
		    then
			#
			:   PowerHA is at level $ha_level on node $node
			#
			do_check=true
			break
		    fi
		done
    else
	do_check=true
    fi
    #
    :	The check of the collected PowerHA levels shows some earlier than 7.1
    :	So, have to check the AIX level on each node
    #
    if [[ $do_check == true ]]
    then
	#
	:   The device rename command 'rendev' is only available on nodes
	:   running bos.rte.methods 6.1.6 or later.
	:   Check to see what is installed.
	#
	LSLPP_CMD=$(print -- 'lslpp -lcqOr bos.rte.methods | cut -f3 -d:' | clencodearg)
cel_f1
	#
	:   Process the output from that check - is any node at lower
	:   than 6.1.6?
	#
	if [[ ! -s $try_out ]]
	then
	    bad_nodes=$Check_nodes
	else
	    while IFS=: read node version_info 
	    do
		print -- "$version_info" | IFS=. read V R M F
		VRMF=$V$R$M$F
		if (( $VRMF < 601006000 ))
		then
		    #
		    :   This node is not at a level that supports 
		    :   the 'rendev' command
		    #
		    bad_nodes=${bad_nodes:+$bad_nodes","}${node}
		fi
	    done < $try_out
	fi
    fi
    #
    :	Print an informative error message if the operation is not possible
    #
    if [[ -n $bad_nodes ]]
    then
	nls_msg -2 -l $cspoc_tmp_log $_MSET 106 "cl_rendisk: $Orig_name cannot be renamed to $Check_name on nodes $bad_nodes because those nodes do not support the device rename command.  The device rename command is part of AIX 6.1.6\n" $Orig_name $Check_name $bad_nodes
	return 1
    else
	return 0
    fi
}
######################################################################
#
#   Function:	Check to make sure that a device name - or its raw name
#		equivalent - is not already in use in the cluster
#
#   Input:	Current Device name
#		Proposed new device name
#
#   Output:	return code 
#		0 = no name conflict
#
######################################################################
name_use_check()
{
    [[ -n $_DEBUG ]] && {
        print "DEBUG: Entering name_use_check version $Source: 61haes_r711 43haes/usr/sbin/cluster/cspoc/plans/cl_rendisk.cel 1$2"
	(( $_DEBUG >= 8 )) && {
	    typeset PROGNAME=name_use_check
	    set -x
	}
    }
    Orig_name=$1	    # current disk name, unencoded
    Check_name=$2	    # proposed new disk name, unencoded
    bad_nodes=""	    # nodes on which there is a name collision
    #
    :	Check to see if there is already a device with the given name
    :	on any of the nodes
    #
    try_rc=0
    lsdev_name=$(print '*'${Check_name} | clencodearg)
cel_f2
    if (( $try_rc != 0 ))
    then
	nls_msg -2 -l $cspoc_tmp_log $_MSET 79 "cl_rendisk: $Orig_name cannot be renamed to $dev_name on node $bad_nodes because that name is already in use by another device\n" $Orig_name $dev_name $bad_nodes
	return $try_rc
    fi
    #
    :	Check to see if there is already a device with the given
    :	raw device name on any of the nodes
    #
    bad_nodes=""
    try_rc=0
    slashdev=$(print -- '/dev' | clencodearg)
cel_f3
    if (( $try_rc != 0 ))
    then
	nls_msg -2 -l $cspoc_tmp_log $_MSET 80 "cl_rendisk: $Orig_name cannot be renamed to $Check_name on node $bad_nodes because /dev/$Check_name already exists\n" $Orig_name $Check_name $bad_nodes $Check_name
    fi
    return $try_rc
}
#############################################################################
#
:   Include the PATH and PROGNAME initialization stuff
#
# @(#)69        1.8  src/43haes/usr/sbin/cluster/cspoc/plans/cl_path.cel, hacmp.cspoc, 61haes_r720, 1539B_hacmp720 9/10/15 13:28:25
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r720 src/43haes/usr/sbin/cluster/cspoc/plans/cl_path.cel 1.8 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1999,2015 
# 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 
 ################################################################################
#   COMPONENT_NAME: CSPOC
#
# Name:
#       cl_path.cel
#
# Description:
#       C-SPOC Path Initialization Routine.  This routine is to be included
#       in all C-SPOC Execution Plans (e.g. '%include cl_path.cel').
#       it sets up the PATH environment variable to prevent hardcoding of 
#       path names in the CSPOC code.
#
# Arguments:
#       None.
#
# Return Values:
#	None.
#
# Environment Variables Defined:
#
#   PUBLIC:
#	PROGNAME Represents the name of the program 
#	HA_DIR Represents the directory the HA product is shipped under.
#
################################################################################
PROGNAME=${0##*/}
PATH="$(/usr/es/sbin/cluster/utilities/cl_get_path all)"
# set the HA_DIR env variable to the HA directory
HA_DIR="es"
# Set up useful prompt for when 'set -x' is turned on through _DEBUG
if [[ -n $_DEBUG ]] && (( $_DEBUG == 9 ))
then
    PS4='${PROGNAME:-$_CMD}[$LINENO]: '
    set -x
fi
[[ -n $_DEBUG ]] &&
    print "DEBUG $PROGNAME version $Source: 61haes_r711 43haes/usr/sbin/cluster/cspoc/plans/cl_rendisk.cel 1$"
#
:   Initialize variables needed to parse input
#
_CMD_NAME=${0##*/}
_CSPOC_OPT_STR="d:f?[g:n:]"
_OPT_STR="+1N^Y:"
_USAGE="$(dspmsg -s 21 cspoc.cat 81 'Usage: cl_rendisk -cspoc \"[-f] [-g ResourceGroup | -n NodeList]\" -N new_disk_name [-Y PVID] hdisk_name\n')"
_MSET=127
#
:   Include CELPP init code and verification routines.
#
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2017,2018,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/plans/cl_init.cel 1.16.7.9 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1996,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/plans/cl_init.cel, 726, 2147A_aha726, Feb 05 2021 09:50 PM
################################################################################
#
# COMPONENT_NAME: CSPOC
#
# Name:
#       cl_init.cel
#
# Description:
#       C-SPOC Initialization Routine.  This routine is to be included
#       in all C-SPOC Execution Plans (e.g. '%include cl_init.cel').
#       It defines the ksh functions required to implement C-SPOC commands.
#
# Arguments:
#       None.
#
# Return Values:
#       None.
#
# Environment Variables Defined:
#
#   PUBLIC:
#       _OPT_STR            Specifies the list of valid command flags.
#                           Must be specified in the execution plan.
#
#       _CSPOC_OPT_STR      Specifies the list of valid CSPOC flags.
#                           Must be specified in the execution plan.
#
#       cspoc_tmp_log       Full path of the cspoc log file
#                           (/var/hacmp/log/cspoc.log).
#
#       _CLUSTER_NODES      A comma separated list of all nodes in the cluster.
#
#       _NODE_LIST          A comma separated list of nodes from the command
#                           line (i.e. Those specified by -n or implied by -g).
#
#       _TARGET_NODES       A comma separated list that specify the target
#                           nodes for a generated C-SPOC script.
#
#       BADNODES            A space-separated list that specifies the nodes
#                           that are either not defined in the cluster or not
#                           reachable for a generated C-SPOC script.
#
#       _RES_GRP            The resource group specified by -g on the
#                           command line
#
#       _SPOC_FORCE         Set to "Y" when -f specified.  Otherwise not set.
#
#       _DEBUG              Set to <debug_level> when -d specified.
#                           Otherwise not set.
#
#       _CMD_ARGS           The AIX Command Options and arguments from the
#                           C-SPOC command
#
#       _NUM_CMD_ARGS       The number of AIX Command Options and arguments
#                           from the C-SPOC command
#
#       _NON_FLG_ARGS       The non-flag arguments from the C-SPOC command.
#
#       _OF_NA              A list of the optional command flags specified
#                           that do NOT require an option argument.
#
#       _MF_NA              A list of the mandatory command flags specified
#                           that do NOT require an option argument.
#
#       _OF_WA              A list of the optional command flags specified
#                           that require an option argument.
#
#       _MF_WA              A list of the mandatory command flags specified
#                           that require an option argument.
#
#       _VALID_FLGS         A list of valid command flags.
#
#       _CSPOC_OPTS         The CSPOC Options specified on the command line
#                           following the '-cspoc' flag.
#
#       _CSPOC_OF_NA        A list of the optional CSPOC flags specified that
#                           do NOT require an option argument.
#
#       _CSPOC_MF_NA        A list of the mandatory CSPOC flags specified that
#                           do NOT require an option argument.
#
#       _CSPOC_OF_WA        A list of the optional CSPOC flags specified that
#                           require an option argument.
#
#       _CSPOC_MF_WA        A list of the mandatory CSPOC flags specified that
#                           require an option argument.
#
#       _CSPOC_VALID_FLGS   A list of valid CSPOC flags for this CSPOC command.
#
#       CLUSTER_OVERRIDE    Flag to Cluster Aware AIX Commands to signal that
#                           base AIX commands should be allowed to operate.
#                           Applies to 7.1.0 and later.
#
################################################################################
################################################################################
#
# _get_node_list
#
# DESCRIPTION:
#   Generates two lists _CLUSTER_NODES is a list of all nodes in the cluster.
#
################################################################################
function _get_node_list
{
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: Entering _get_node_list version 1.16.7.9"
        if (( $_DEBUG >= 8 )); then
            typeset PROGNAME="_get_node_list"
            set -x
        fi
    fi
    unset _CLUSTER_NODES
    typeset NODE IP_ADDR
    #
    : GET A comma separated LIST OF ALL NODES IN THE CLUSTER
    #
    _CLUSTER_NODES=$(IFS=, set -- $(clodmget -q "object = COMMUNICATION_PATH" -f name -n HACMPnode) ; print "$*")
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: CLUSTER NODES [${_CLUSTER_NODES}]"
        print "DEBUG: Leaving _get_node_list"
    fi
    #
    : ENSURE THAT NODES FOUND FOR THE CLUSTER
    #
    if [[ -z ${_CLUSTER_NODES} ]]; then
        nls_msg -2 21 6 \
            "${_CMD}: The cluster does not appear to be configured - no nodes are defined.  \n  Configure the cluster, nodes and networks then try this operation again.\n" $_CMD
        return 1
    fi
    return 0
} # End of "_get_node_list()"
################################################################################
#
# _get_target_nodes
#
# DESCRIPTION
#   Sets environment variable $_TARGET_NODES to the list of cluster
#   on which the C-SPOC command is to be executed.
#
#	1 - If a node list was specified $_TARGET_NODES is set to
#	    the nodes listed.
#
#	2 - If a resource group was specified $_TARGET_NODES is set
#	    to the list of nodes that are participating in that
#	    resource group.
#
#	3 - If neither a node list or resource group has been specified
#	    then $_TARGET_NODES is set to a list of all nodes in the cluster.
#
################################################################################
function _get_target_nodes
{
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: Entering _get_target_nodes version 1.16.7.9"
        if (( $_DEBUG >= 8 ))
        then
            typeset PROGNAME="_get_target_nodes"
            set -x
        fi
    fi
    typeset NODE=""
    integer GTN_RC=-1
    #
    : If given a node list, or the nodes in a resource group, use those
    #
    if [[ -n $_NODE_LIST || -n $_RG_NODE_LIST ]]
    then
        _TARGET_NODES=$(IFS=, set -- $_NODE_LIST $_RG_NODE_LIST ; print "$*")
        GTN_RC=0
    #
    : If no node list given, assume all cluster nodes, if we can find them
    #
    elif [[ -n $_CLUSTER_NODES ]]
    then
        _TARGET_NODES="$_CLUSTER_NODES"
        GTN_RC=0
    #
    : Else cannot figure out where to run this
    #
    else
        nls_msg -2 -l ${cspoc_tmp_log} 4 6 \
        "%s: Unable to determine target node list!\n" "$_CMD"
        GTN_RC=1
    fi
    return $GTN_RC
} # End of "_get_target_nodes()"
################################################################################
#
# _get_rgnodes
#
# DESCRIPTION
#   Gets a list of nodes associated with the resource group specified.
#
################################################################################
function _get_rgnodes
{
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: Entering _get_rgnodes version 1.16.7.9"
        if (( $_DEBUG >= 8 ))
        then
            typeset PROGNAME="_get_rgnodes"
            set -x
        fi
    fi
    if [[ -z $1 ]]
    then
        nls_msg -2 -l ${cspoc_tmp_log} 4 9 \
            "%s: _get_rgnodes: A resource group must be specified.\n" "$_CMD"
        return 1
    fi
    _RG_NODE_LIST=$(clodmget -q "group = $1" -f nodes -n HACMPgroup)
    if [[ -z $_RG_NODE_LIST ]]
    then
        nls_msg -2 -l ${cspoc_tmp_log} 4 50 \
            "%s: Resource group %s not found.\n" "$_CMD" "$1"
        return 1
    fi
    return 0
} # End of "_get_rgnodes()"
#######################################################################
#
# _getopts
#
# DESCRIPTION
#   Parses comand line options for C-SPOC commands.
#
#######################################################################
#
# OPTION STRING
#   The _getopts() routine requires the execution plan to define the
#   environment variable $_OPT_STR which is refered to as the option
#   string.  The option string is used to define valid and/or required
#   flags, the required number of non-flag arguments, and what flags
#   may or may not be specified together.
#
#    Operator   Description                                  Example
#    --------   ------------------------------------------   ---------
#	()	Groups mutually required flags               (c!d:)
#	[]	Groups mutually exclusive flags              [f,b,]
#
#	?	Optional flag (default)                      b?
#	!	Mandatory flag                               c!
#
#	:	Optional flag that requires an argument      d:
#	^	Mandatory flag that requires an argument     e^
#
#	.	Optional multi-byte flag
#	,	Mandatory multi-byte flag                    f,
#
#	+N	Indicates that N non-flag arguments are.     +2
#               required. It must be at the beginning of
#               the option string.
#
#   Notes:
#	1 - A flag that can be specified with or without an argument
#           would be specified twice as follows: _OPT_STR="a?a:"
#
#	2 - A flag that requires an argument cannot also be the first
#           letter of a multi-byte flag.  (i.e. -b arg -boot ) as there
#           is no way to differentiate between the two.
#
#  Example:
#    The following option string would correspond to the usage below
#    In the usage '[]' indicates optional flags and '()' indicates
#    grouping.
#
#	_OPT_STR="+2ab?(c!d:)e^[f,b,]g."
#
#    Usage:
#     cmd [-a] [-b] -c [-d arg] -e arg ( -foo | -bar ) [-go] arg1 arg2 [arg3]
#
#
#######################################################################
function _getopts
{
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: Entering _getopts 1.16.7.9"
        if (( $_DEBUG >= 8 ))
        then
            typeset PROGNAME="_get_opts"
            set -x
        fi
    fi
    typeset CMD=${0##*/}
    # unset the following variables to avoid these variables being
    # influenced implicitly by external environment. Note that we will
    # not unset/touch _DEBUG since it is being checked even before hitting
    # this part of the code. i.e. depending upon the _DEBUG flag we set
    # set -x option initially itself.
    unset _NODE_LIST
    unset _RES_GRP
    unset _CSPOC_QUIET
    # LOCAL VARIABLES
    typeset _OPT_STR _CSPOC_OPT_STR OPT X Y
    typeset _VALID_FLGS _CSPOC_VALID_FLGS
    typeset _OF_NA _MF_NA _OF_WA _MF_WA
    typeset _CSPOC_OF_NA _CSPOC_MF_NA _CSPOC_OF_WA _CSPOC_MF_WA
    typeset _GOPT=no _NOPT=no
    # THE FIRST TWO ARGS MUST BE OPTION STRINGS
    _CSPOC_OPT_STR=$1
    _OPT_STR=$2
    shift 2
    # CHECK CSPOC OPT STRING SPECIFIED IN THE EXECUTION PLAN
    # FOR OPTIONAL OR REQUIRED FLAGS
    [[ $_CSPOC_OPT_STR == *g^* ]] && _GOPT=req
    [[ $_CSPOC_OPT_STR == *g:* ]] && _GOPT=opt
    [[ $_CSPOC_OPT_STR == *n^* ]] && _NOPT=req
    [[ $_CSPOC_OPT_STR == *n:* ]] && _NOPT=opt
    # CHECK IF THE OPTION STRINGS SPECIFY A REQUIRED NUMBER OF NON-FLAG ARGS
    if [[ $_OPT_STR == +* ]]
    then
        X=${_OPT_STR#??}
        Y=${_OPT_STR%"$X"}
        _OPT_STR=$X
        _NUM_ARGS_REQ=${Y#?}
    fi
    # PARSE THE OPTION STRING ($_OPT_STR) INTO FIVE LISTS
    #  ${_OF_NA} is a list of optional flags that DO NOT take an option arg.
    #  ${_MF_NA} is a list of mandatory flags that DO NOT take an option arg.
    #  ${_OF_WA} is a list of mandatory flags that DO take an option argument
    #  ${_MF_WA} is a list of optional flags that DO take an option argument
    #  ${_VALID_FLGS} is a list of all valid flags.
    # Note that both strings start and end with a space (to facilitate grepping)
    # and contain a list of space separated options each of which is preceded
    # by a minus sign.
    # THE FOLLOWING WHILE LOOP SIMPLY ORGANIZES THE VALID FLAGS INTO
    # FOUR LISTS THAT CORRESPOND TO THE FOUR FLAG TYPES LISTED ABOVE
    # AND A FIFTH LIST THAT INCLUDES ALL VALID FLAGS.
    X=${_OPT_STR}
    [[ $X == '-' ]] && X=""
    while [[ -n ${X} ]]
    do
        # GET THE NEXT LETTER OF THE OPTION STRING
        Y=${X#?}
        OPT=${X%"$Y"}
        X=${Y}
        # CHECK FOR AND PROCESS MUTALLY REQUIRED OR MUTUALLY EXCLUSIVE FLAGS
        case $OPT in
            '(') # STARTS A GROUP OF MUTUALLY REQUIRED FLAGS
                 if [[ -n $MUTREQ ]]
                 then
                     print '$_CMD: _getopts: Invlid format for $_OPT_STR'
                     print '$_CMD: _getopts: Unexpected character "("'
                     return 1
                 fi
                 MUTREQ=Y
                 continue
            ;;
            ')') # ENDS A GROUP OF MUTUALLY REQUIRED FLAGS
                 if [[ -z $MUTREQ ]]
                 then
                     print '$_CMD: _getopts: Invlid format for $_OPT_STR'
                     print '$_CMD: _getopts: Unexpected character ")"'
                     return 1
                 fi
                 MUTREQ=""
                 MUTREQ_FLAGS=$MUTREQ_FLAGS" "
                 continue
            ;;
            '[') # STARTS A GROUP OF MUTUALLY EXCLUSIVE FLAGS
                 if [[ -n $MUTEX ]]
                 then
                     print '$_CMD: _getopts: Invlid format for $_OPT_STR'
                     print '$_CMD: _getopts: Unexpected character "["'
                     return 1
                 fi
                 MUTEX=Y
                 continue
            ;;
            ']') # ENDS A GROUP OF MUTUALLY EXCLUSIVE FLAGS
                 if [[ -z $MUTEX ]]
                 then
                     print '$_CMD: _getopts: Invlid format for $_OPT_STR'
                     print '$_CMD: _getopts: Unexpected character "]"'
                     return 1
                 fi
                 MUTEX=""
                 MUTEX_FLAGS=$MUTEX_FLAGS" "
                 continue
            ;;
        esac
        # KEEP A LIST OF MUTUALLY EXCLUSIVE FLAGS
        if [[ -n $MUTEX && $MUTEX_FLAGS != *${OPT}* ]]; then
            MUTEX_FLAGS=${MUTEX_FLAGS}${OPT}
        fi
        # KEEP A LIST OF MUTUALLY REQUIRED FLAGS
        if [[ -n $MUTREQ && $MUTREQ_FLAGS != *${OPT}* ]]; then
            MUTREQ_FLAGS=${MUTREQ_FLAGS}${OPT}
        fi
        # KEEP A LIST OF ALL VALID FLAGS
        _VALID_FLGS="${_VALID_FLGS} -$OPT"
        # DETERMINE THE FLAG TYPE AS DESCRIBED ABOVE
        # ADD THE FLAG TO THE APPROPRIATE LIST AND
        # STRIP OFF THE FLAG TYPE IDENTIFIER FROM
        # THE OPTION STRING '${_OPT_STR}'.
        case $X in
            '.'*) # OPTIONAL MULTI-BYTE FLAG
                  X=${X#.}
                  _OF_MB="${_OF_MB} -$OPT"
            ;;
            ','*) # MANDATORY MULTI-BYTE FLAG
                  X=${X#,}
                  _MF_MB="${_MF_MB} -$OPT"
            ;;
            ':'*) # OPTIONAL FLAG THAT REQUIRES AN ARGUMENT
                  X=${X#:}
                  _OF_WA="${_OF_WA} -$OPT"
            ;;
            '^'*) # MANDATORY FLAG THAT REQUIRES AN ARGUMENT
                  X=${X#^}
                  _MF_WA="${_MF_WA} -$OPT"
            ;;
            '!'*) # MANDATORY FLAG
                  X=${X#!}
                  _MF_NA="${_MF_NA} -$OPT"
            ;;
            '?'*) # OPTIONAL FLAG
                  X=${X#?}
                  _OF_NA="${_OF_NA} -$OPT"
            ;;
            *)    # OPTIONAL FLAG
                  _OF_NA="${_OF_NA} -$OPT"
            ;;
        esac
    done # End of the option "while" loop
    # TACK A SPACE ONTO THE END OF EACH LIST TO MAKE OPTION GREPPING SIMPLE
    _VALID_FLGS=$_VALID_FLGS" "
    _OF_NA=$_OF_NA" " ; _OF_WA=$_OF_WA" " ; _OF_MB=$_OF_MB" "
    _MF_NA=$_MF_NA" " ; _MF_WA=$_MF_WA" " ; _MF_MB=$_MF_MB" "
    if [[ -n $_DEBUG ]] && (( $_DEBUG >= 3 )) 
    then
        print "DEBUG(3): _OF_NA=$_OF_NA"
        print "DEBUG(3): _MF_NA=$_MF_NA"
        print "DEBUG(3): _OF_WA=$_OF_WA"
        print "DEBUG(3): _MF_WA=$_MF_WA"
        print "DEBUG(3): _OF_MB=$_OF_MB"
        print "DEBUG(3): _MF_MB=$_MF_MB"
        print "DEBUG(3): _VALID_FLGS=$_VALID_FLGS"
    fi
    # PARSE THE COMMAND LINE ARGS
    let _NUM_CMD_ARGS=0
    while [[ -n $* ]]
    do
        THIS_FLAG=$1
        THIS_ARG=${THIS_FLAG#??}
        THIS_FLAG=${THIS_FLAG%"$THIS_ARG"}
        if [[ -n $_DEBUG ]]
        then
            print "THIS_FLAG=\"$THIS_FLAG\""
            print "THIS_ARG=\"$THIS_ARG\""
        fi
        if [[ $1 == '-cspoc' ]]
        then
            #
            :   Check for and process any CSPOC flags
            #
		_CSPOC_OPTS=$2
            if [[ -z $_CSPOC_OPTS || $_CSPOC_OPTS == *([[:space:]]) ]]
            then
                SHIFT=1
            else
                SHIFT=2
                while getopts ':fd#n:?g:q' _CSPOC_OPTION $_CSPOC_OPTS 
                do
                    case $_CSPOC_OPTION in
                        f ) :   Force option
                            export _SPOC_FORCE=Y
                        ;;
                        d ) :   Debug level
                            export _DEBUG=$OPTARG
                        ;;
                        n ) :   Target node list
                            export _NODE_LIST=$(print $OPTARG | sed -e"s/['\"]//g")
                        ;;
                        g ) :   Target resource group 
                            export _RES_GRP=$(print $OPTARG | sed -e"s/['\"]//g")
                        ;;
                        q ) :   Suppress output to stdout
                            export _CSPOC_QUIET=YES
                        ;;
                        : ) :   Missing operand - ignored
                        ;;
                        * ) :   Invalid flag specified
                            nls_msg -2 -l ${cspoc_tmp_log} 4 13 \
                                "%s: Invalid C-SPOC flag [%s] specified.\n" \
                                "$_CMD" "$_CSPOC_OPTION"
                            print "$_USAGE"
                            exit 2
                        ;;
                    esac
                done
            fi
            #
            :   Validate required and mutually exclusive CSPOC operands
            #
            if [[ $_GOPT == "no" && -n $_RES_GRP ]]
            then
                #
                :   Is "-g" allowed
                #
                nls_msg -2 -l ${cspoc_tmp_log} 4 60 \
                    "%s: C-SPOC -g flag is not allowed for this command.\n" \
                    "$_CMD"
                print "$_USAGE"
                return 2
            elif [[ $_NOPT == "no" && -n $_NODE_LIST ]]
            then
                #
                :   Is "-n" allowed
                #
                nls_msg -2 -l ${cspoc_tmp_log} 4 61 \
                    "%s: C-SPOC -n flag is not allowed for this command.\n" \
                    "$_CMD"
                print "$_USAGE"
                return 2
            elif [[ $_GOPT == "req" && $_NOPT == "req" ]] && \
                 [[ -z $_RES_GRP && -z $_NODE_LIST ]]
            then    
                #
                :   Check for "-g" or "-n" present when one
                :   or the other is required
                #
                nls_msg -2 -l ${cspoc_tmp_log} 4 62 \
                    "%s: Either the '-g' or the '-n' C-SPOC flag must be specified.\n" "$_CMD"
                print "$_USAGE"
                return 2
            elif [[ -n $_RES_GRP && -n $_NODE_LIST ]]
            then
                #
                :   Check that both "-g" and "-n" are not specified together
                #
                nls_msg -2 -l ${cspoc_tmp_log} 4 63 \
                    "%s: C-SPOC -g and -n flags are mutually exclusive.\n" \
                    "$_CMD"
                print "$_USAGE"
                return 2
            elif [[ $_NOPT != "req" && $_GOPT == "req" && -z $_RES_GRP ]]
            then
                #
                :   Is only "-g" allowed
                #
                nls_msg -2 -l ${cspoc_tmp_log} 4 64 \
                    "%s: C-SPOC -g flag is required.\n" "$_CMD"
                print "$_USAGE"
                return 2
            elif [[ $_GOPT != "req" && $_NOPT == "req" && -z $_NODE_LIST ]]
            then
                #
                :   Is only "-n" required
                #
                nls_msg -2 -l ${cspoc_tmp_log} 4 65 \
                    "%s: C-SPOC -n flag is required.\n" "$_CMD"
                print "$_USAGE"
                return 2
            fi
            shift $SHIFT
        elif [[ "$THIS_FLAG" != -* ]]
        then
            #  AIX COMMAND ARGUMENT THAT IS NOT AN OPTION FLAG
            #  NEED TO ACCOMODATE OPTIONS THAT MAY OR MAY NOT HAVE AN ARGUMENT.
            #  IF OPT_ARG DOESN'T START WITH A '-' ITS AN ARGUMENT OTHERWISE
            #  CONSIDER IT TO BE THE NEXT OPTION
            let _NUM_CMD_ARGS=$_NUM_CMD_ARGS+$#
            TMP_FLAG=""
            while (( $# > 0 ))
            do
                case "$1" in
                    -*) TMP_FLAG=$(echo $1 | cut -c1-2)
                        _CMD_ARGS=${_CMD_ARGS:+"${_CMD_ARGS} "}"$TMP_FLAG"
                        TMP_ARG1=$(echo $1 | cut -c3-)
                        if [[ -n $TMP_ARG1 ]] 
                        then
                            TMP_ARG1="$(print -- $TMP_ARG1 |\
                                        clencodearg $_ENCODE_ARGS)"
                            _CMD_ARGS=${_CMD_ARGS:+"${_CMD_ARGS} "}"$TMP_ARG1"
                            TMP_FLAG=""
                        fi
                    ;;
                    *) TMP_ARG2="$(print -- $1 | clencodearg $_ENCODE_ARGS)"
                       _CMD_ARGS=${_CMD_ARGS:+"${_CMD_ARGS} "}${TMP_ARG2}
                       if [[ -z $TMP_FLAG ]]
                       then
                           _NON_FLG_ARGS=${_NON_FLG_ARGS:+"${_NON_FLG_ARGS} "}"${TMP_ARG2}"
                       fi
                       TMP_FLAG=""
                esac
                shift
            done
            break
        else	# COME INTO HERE WITH $THIS_FLAG and $THIS_ARG SET
            ARG_CHECK=Y
            ARG_NEXT=""
            while [[ -n $ARG_CHECK ]]
            do
                # NOW CHECK IF WE STILL HAVE MORE FLAGS TO PROCESS
                [[ -z $THIS_ARG ]] && ARG_CHECK=""
                if print -- "$_OF_MB $_MF_MB" | grep -- "$THIS_FLAG" > /dev/null
                then
                    # THIS IS A MULTI-BYTE FLAG
                    if [[ -z $THIS_ARG ]]
                    then
                        ( print -- "$_OF_NA $_MF_NA" | grep -- "$THIS_FLAG" > /dev/null ) || \
                        {
                            # THIS FLAG REQUIRES AN ARGUMENT
                            nls_msg -2 -l ${cspoc_tmp_log} 4 19 \
                                "%s: Invalid option [%s].\n" "$_CMD" "$1"
                            print "$_USAGE"
                            exit 2
                        }
                    fi
                    # VALID AIX COMMAND MULTI-BYTE OPTION (WITHOUT AN ARGUMENT)
                    _CMD_ARGS=${_CMD_ARGS:+"${_CMD_ARGS} "}"$THIS_FLAG$THIS_ARG"
                    shift
                    ARG_CHECK=""	# Disable further processing of $THIS_ARG as flags
                elif print -- "$_OF_WA $_MF_WA" | grep -- "$THIS_FLAG" > /dev/null
                then
                    # THIS IS A FLAG THAT REQUIRES AN ARGUMWENT
                    # HANDLE OPTIONAL SPACE BETWEEN FLAG AND ITS ARG
                    if [[ -z $THIS_ARG && -z $ARG_NEXT ]]
                    then
                        THIS_ARG=$2		# THERE WAS A SPACE
                        SHIFT=2
                    else
                        SHIFT=1		# THERE WAS NO SPACE
                    fi
                    # NOW VALIDATE THAT WE HAVE AN ARG AND THAT IT IS VALID
                    if [[ -z $THIS_ARG || $THIS_ARG == -* ]]
                    then
                        # IF THERE IS NO ARG THEN CHECK IF FLAG MAY BE SPECFIED WITHOUT ONE
                        print -- "$_OF_NA $_MF_NA" | grep -q -- "$THIS_FLAG" ||\
                        {
                            # THIS FLAG REQUIRES AN ARGUMENT
                            nls_msg -2 -l ${cspoc_tmp_log} 4 19 \
                            "%s: Option [%s] requires an argument.\n" "$_CMD" "$1"
                            print "$_USAGE"
                            exit 2
                        }
                    fi
                    # VALID AIX COMMAND OPTION WITH AN ARGUMENT
                    _CMD_ARGS=${_CMD_ARGS:+"${_CMD_ARGS} "}"$THIS_FLAG $(print -- $THIS_ARG | clencodearg $_ENCODE_ARGS)"
                    shift $SHIFT
                    # Disable further processing of $THIS_ARG as flags
                    ARG_CHECK=""
                elif print -- "$_OF_NA $_MF_NA" | grep -q -- "$THIS_FLAG"
                then
                    # THIS IS A FLAG THAT DOES NOT TAKE AN ARGUMENT
                    _CMD_ARGS=${_CMD_ARGS:+"${_CMD_ARGS} "}"$THIS_FLAG"
                    # IF THIS FLAG WAS OBTAINED FROM $THIS_FLAG THEN WE WANT TO
                    # SHIFT. IF IT WAS OBTAINED FROM $THIS_ARG THEN WE DONT
                    [[ -z $ARG_CHECK ]] && shift
                    # THIS FLAG DOES NOT TAKE AN OPTION ARGUMENT SO ASSUME
                    # THAT "$THIS_ARG" SPECIFIES MORE FLAGS TO PROCESS.
                    if [[ -n $THIS_ARG ]]
                    then
                        # GET THE NEXT FLAG, ADJUST $THIS_ARG,
                        # AND KEEP PROCESSING.
                        X=${THIS_ARG#?}
                        THIS_FLAG="-${THIS_ARG%$X}"
                        THIS_ARG=$X
                        ARG_NEXT=Y
                    fi
                else
                    nls_msg -2 -l ${cspoc_tmp_log} 4 26 \
                    "%s: Invalid option [%s].\n" "$_CMD" "$1"
                    print "$_USAGE"
                    exit 2
                fi
            done
        fi
    done
    ##
    # PERFORM CHECKING OF THE AIX COMMAND FLAGS
    ##
    # CHECK FOR REQUIRED NUMBER OF NON-FLAG ARGUMENTS
    if (( ${_NUM_CMD_ARGS:-0} < ${_NUM_ARGS_REQ:-0} ))
    then
        nls_msg -2 -l ${cspoc_tmp_log} 4 27 \
            "%s: Missing command line arguments.\n" "$_CMD"
        print "$_USAGE"
        return 2
    fi
    # THIS IS WHERE WE CHECK FOR MANDATORY FLAGS, MUTUALLY EXCLUSIVE FLAGS,
    # AND MUTUALLY REQUIRED FLAGS
    # CHECK FOR MUTUALLY REQUIRED FLAGS
    # FOR EACH GROUP OF FLAGS SPECIFIED IN $MUTREQ_FLAGS WE WILL COUNT HOW
    # MANY WE NEED AND HOW MANY ARE GIVEN ON CMD LINE.  IF THESE VALUES ARE
    # NOT EQUAL PRINT AN ERROR AND RETURN NON-ZERO
    typeset -i CNT=0 N=0
    for GROUP in $MUTREQ_FLAGS
    do
        # GET A COUNT OF HOW MANY FLAGS IN THIS GROUP
        print -n $GROUP | wc -c | read N
        integer CNT=0
        F=""
        while [[ -n $GROUP ]]
        do
            # GET THE NEXT FLAG IN THE GROUP
            A=${GROUP#?}
            B=${GROUP%"$A"}
            GROUP=$A
            # IF THIS FLAG IS USED INCREMENT THE COUNTER
            if [[ "$(print -- $_CMD_ARGS | grep -- '-'${B})"' ' != ' ' ]]
            then
                (( CNT = CNT + 1 ))
            fi
            F=${F:+"$F, "}"-"$B
        done
        # VERIFY THAT THE COUNTER EQUALS THE TOTAL NUMBER OF FLAGS IN THE GROUP
        if (( $CNT != $N ))
        then
            print "$_CMD: One or more flags [$F] were not specified."
            print "$_CMD: Specifying any one of these flags requires the others."
            return 2
        fi
    done
    # CHECK FOR MUTUALLY EXCLUSIVE FLAGS
    # FOR EACH GROUP OF FLAGS SPECIFIED IN $MUTEX_FLAGS WE WILL COUNT HOW
    # MANY ARE GIVEN ON CMD LINE.  IF MORE THAN ONE IS GIVEN THEN PRINT
    # AN ERROR AND RETURN NON-ZERO
    for GROUP in $MUTEX_FLAGS
    do
        # GET A COUNT OF HOW MANY FLAGS IN THIS GROUP
        integer CNT=0
        F=""
        while [[ -n $GROUP ]]
        do
            # GET THE NEXT FLAG IN THE GROUP
            A=${GROUP#?}
            B=${GROUP%"$A"}
            GROUP=$A
            # IF THIS FLAG IS USED INCREMENT THE COUNTER
            if [[ -n "$(print -- $_CMD_ARGS | grep -- '-'${B})" ]]
            then
                (( CNT = CNT + 1 ))
            fi
            F=${F:+"$F, "}"-"$B
        done
        # VERIFY THAT THE COUNTER EQUALS THE TOTAL NUMBER OF FLAGS IN THE GROUP
        if (( $CNT > 1 ))
        then
            print "$_CMD: The flags [$F] are mutually exclusive."
            print "$_CMD: Only one of these flags may be specified."
            return 2
        fi
    done
    # CHECK FOR ALL MANDATORY FLAGS
    for X in $_MF_NA $_MF_WA
    do
        # CHECK THAT MANDATORY FLAG IS ON COMMAND LINE
        if [[ -z "$(print -- $_CMD_ARGS | grep -- ${X})" ]]
        then
            # THE FLAG WAS NOT SPECIFIED SO WE MUST FIRST CHECK IF ANOTHER
            # FLAG WAS SPECIFIED THAT IS MUTUALLY EXCLUSIVE WITH THIS ONE.
            for GROUP in $MUTEX_FLAGS
            do
                OK=""
                while [[ -n $GROUP ]]
                do
                    Y=${GROUP#?}
                    Z=${GROUP%"$Y"}
                    GROUP=$Y
                    print -- " $_CMD_ARGS " |\
                        grep -- "-${Z} " > /dev/null && OK=Y
                done
                [[ -n $OK ]] && break
            done
            # "$OK" IS NULL IF NO FLAG IN THIS MUTEX GROUP WAS GIVEN
            if [[ -z $OK ]]
            then
                nls_msg -2 -l ${cspoc_tmp_log} 4 29 \
                "%s: Mandatory option [%s] not specified.\n" "$_CMD" "$X"
                print "$_USAGE"
                return 2
            fi
        fi
    done
    if [[ -n $_DEBUG ]] && (( $_DEBUG >= 3 )) 
    then
        print -- "DEBUG(3): _CMD_ARGS=$_CMD_ARGS"
    fi
    return 0
} # End of "_getopts()"
################################################################################
#
# DESCRIPTION:
#   Updates the C-SPOC logfile
#
################################################################################
function cexit
{
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: Entering cexit version 1.16.7.9"
        if (( $_DEBUG >= 8 ))
        then
            typeset PROGNAME=cexit
            set -x
        fi
    fi
    typeset USAGE="USAGE: cexit <temp_log_file> <return_code>"
    # CHECK USAGE
    (( $# != 2 )) && print "$_CMD: $USAGE"
    typeset TEMP_LOG=$1
    typeset RC=$2
    #
    : Read the HACMPlogs ODM for the pathname of the cspoc.log log file
    : If the ODM is empty or corrupted, use /var/hacmp/log/cspoc.log
    #
    DESTDIR=$(clodmget -q "name = cspoc.log" -f value -n HACMPlogs)
    if [[ -n $DESTDIR ]]
    then
        CSPOC_LOG="$DESTDIR/cspoc.log"
    else
        dspmsg scripts.cat 463 "The cluster log entry for %s could not be found in the HACMPlogs ODM.\n" "cspoc.log"
        dspmsg scripts.cat 464 "Defaulting to log directory %s for log file %s.\n" "/var/hacmp/log" "cspoc.log"
        CSPOC_LOG="/var/hacmp/log/cspoc.log"
    fi
    #
    : CHECK ARGS
    #
    if [[ ! -f ${TEMP_LOG} ]]
    then
        nls_msg -2 -l ${CSPOC_LOG} 4 39 \
            "%s: Unable to open file: %s\n" "${TEMP_LOG}" "$_CMD"
        return 1
    fi
    #
    :  If the log file does not exist, create it.
    #
    if [[ ! -f ${CSPOC_LOG} ]]; then
        touch ${CSPOC_LOG}
    fi
    #
    :  Keep the information in the log file if we have write permission
    #
    if [[ -w $CSPOC_LOG ]]
    then
        cat ${TEMP_LOG} >> $CSPOC_LOG
    fi
    if (( $RC == 0 )) && ( [[ -z $_DEBUG ]] || (( $_DEBUG <= 8 )) ) then
        rm -f ${TEMP_LOG%_*}*
        rm -f /tmp/cel$$_s*.err
        rm -f /tmp/cel$$_s*.out
        rm -f /tmp/cel$$.cache
    fi   
} # End of "cexit()"
################################################################################
#
# _cspoc_verify - Performs verification of a number of CSPOC requirments.
#                 Certain requirements, if not met, produce a hard error
#                 and the routine produces an immediate exit of the script.
#                 Other requirements, if not met, produce soft errors that
#                 result in the routine returning a value of '1'.  The
#                 calling script will then exit unless the CSPOC force flag
#                 has been set.
#
################################################################################
function _cspoc_verify
{
    if [[ -n $_DEBUG ]]
    then
        print "DEBUG: Entering _cspoc_verify version 1.16.7.9 + 20527,842,758"
        if (( $_DEBUG >= 8 ))
        then
            typeset PROGNAME="_cspoc_verify"
            set -x
        fi
    fi
    typeset NODE 
    typeset bad_targets		#   space separated list of unreachable nodes
    typeset CAA_down_nodes	#   target hosts CAA says are down
    typeset CAA_node_name	#   CAA host node name
    integer _RETCODE=0		#   Assume OK until proven otherwise
    typeset BADNODES		#   Space separated list of invalid nodes
    typeset down_ha_nodes	#   target HA nodes CAA says are down
    typeset good_targets	#   target HA nodes that should work
    typeset bad_level_nodes	#   target HA nodes below minimum release level
    if [[ $_CSPOC_CALLED_FROM_SMIT != 'true' ]]
    then
	#
	:   If not called from SMIT, which will surely set things
	:   up correctly, check to make sure target nodes are valid.
	#
        for NODE in $(IFS=, set -- $_TARGET_NODES ; print $*)	
	do
	    #
	    :   Collect a list of given nodes that do not
	    :   show up in the local cluster definition.
	    #
	    if [[ $_CLUSTER_NODES != @(?(*,)$NODE?(,*)) ]]
	    then
		BADNODES=${BADNODES:+$BADNODES" "}$NODE
		nls_msg -2 -l ${cspoc_tmp_log} 4 44 \
		"%s: The node [%s] is not a part of this cluster.\n" "$_CMD" "$NODE"
	    fi
	done
	if [[ -n $BADNODES ]]
	then
	    #
	    :	Remove any invalid node names from the node list
	    #
	    save_targets=""
	    for ha_node in $(IFS=, set -- $_TARGET_NODES ; print $*)
	    do
		if [[ $BADNODES != @(?(* )${ha_node}?( *)) ]]
		then
		    save_targets=${save_targets:+"${save_targets},"}${ha_node}
		fi
	    done
	    _TARGET_NODES=$save_targets
	    if [[ -z $_TARGET_NODES ]]
	    then
		nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		"%s[%d]: The command will not be run because all of the target nodes, %s, are not part of this cluster\n" "$_CMD" $LINENO "$BADNODES"
		exit 1	    #	No valid nodes found
	    else
		_RETCODE=1  #	Continue if 'forced' specified
	    fi
	fi
    fi
    cluster_version=$(clodmget -f cluster_version -n HACMPcluster)
    if [[ -x /usr/lib/cluster/incluster ]] && /usr/lib/cluster/incluster || \
       (( $cluster_version >= 15 )) 
    then
	#
	:   If at a level where CAA is in place, check to see if
	:   CAA can provide information on the state of nodes.
	#
	LC_ALL=C lscluster -m 2>/dev/null | \
	egrep 'Node name:|State of node:' | \
	cut -f2 -d: | \
	paste -d' ' - - | \
	while read CAA_node_name state
	do
	    if [[ -n $CAA_node_name ]]
	    then
		if [[ $state != 'UP' && \
		    $state != @(?(* )NODE_LOCAL?( *)) && \
		    $state != @(?(* )REACHABLE THROUGH REPOS DISK ONLY?( *)) &&  \
		    $state != 'DOWN  STOPPED' ]]
		then
		    #
		    #	The purpose of this check is to avoid long timeouts
		    #	trying to talk to a node known to be dead.
		    #	- The local node is always reachable
		    #	- A stopped node may be reachable; halevel checks below
		    #	- A node reachable only through the repository disk
		    #	  may be reachable: just because CAA declares the 
		    #	  network to be down doesn't mean clcomd can't get 
		    #	  through; hlevel checks below
		    #
		    :   Node $CAA_node_name is 'DOWN' 
		    #
		    CAA_down_nodes=${CAA_down_nodes:+"${CAA_down_nodes} "}${CAA_node_name}
		    #
		    :   Find the PowerHA node name corresponding to the
		    :   $CAA_node_name - the name must be a label on an
		    :   interface on some node.
		    #
		    host_ip=$(LC_ALL=C host $CAA_node_name | cut -f3 -d' ')
		    host_ip=${host_ip%,}
		    if [[ -n $host_ip && $host_ip == @(+([0-9.])|+([0-9:])) ]]
		    then
			down_ha_node=$(clodmget -q "identifier = ${host_ip}" -f nodename -n HACMPadapter)
			if [[ -n $down_ha_node ]] 
			then
			    down_ha_nodes=${down_ha_nodes:+"$down_ha_nodes "}${down_ha_node}
			    nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
			    "%s[%d]: The CAA lscluster command indicates that node %s[%s] is \"%s\" and not active.\n" "$_CMD" $LINENO $down_ha_node $CAA_node_name "$state"
			fi
		    fi
		fi
	    fi
	done
    fi
    if [[ -n $down_ha_nodes ]]
    then
	#
	:   CAA says that nodes $down_ha_nodes are not active
	:   Construct a list of the remaining nodes, to use to
	:   check to see if clcomd is running.
	#
	for ha_node in $(IFS=, set -- $_TARGET_NODES ; echo $* )
	do
	    if [[ $down_ha_nodes != @(?(* )${ha_node}?( *)) ]]
	    then
		good_targets=${good_targets:+"${good_targets} "}${ha_node}
	    fi
	done
    else
	#
	:   CAA gives no reason to suspect nodes are not reachable
	#
        good_targets=$(IFS=, set -- $_TARGET_NODES ; echo $* )
    fi
    #
    :   CAA has not ruled out talking to node $good_targets
    #
    if [[ -n $_SPOC_FORCE ]] && /usr/lib/cluster/incluster
    then
	#
	:   It is possible that the target node list contains names
	:   that do not correspond to CAA host names after the CAA
	:   cluster is created.  
	#   Before the CAA cluster is created, all target nodes are
	#   naturally not in a CAA cluster.  Ordinarily, this can be
	#   left to clhaver to find, though it does not distinguish
	#   between nodes it cannot connect to, and nodes that are
	#   that are not in the CAA cluster.  If the force flag was
	#   specified, and we are already in a CAA cluster, 
	:   Silently elide names in the target list that do not 
	:   correspond to CAA host names.
	#
	save_targets=$good_targets
	good_targets=""
	for given_node in $save_targets
	do
	    if cl_query_hn_id -q -i $given_node >/dev/null 2>&1
	    then
		good_targets=${good_targets:+"${good_targets} "}${given_node}
	    else
		print "$(date) ${_CMD}._cspoc_verify[$LINENO]: Given target \"$given_node\" cannot be converted to a CAA host name.  It will be skipped." >> $clutilslog
	    fi
	done
    fi 
    if [[ -n $good_targets ]]
    then
	#
	:	CAA thinks that nodes \"$good_targets\"
	:	are active.  See if clcomd can talk to them, 
	:	and what level of PowerHA is present.
	#
	clhaver -c $_VER $good_targets | \
	while IFS=: read ha_node caa_host VRMF
	do
	    if [[ -z $caa_host ]]
	    then
		#
		:   Add $ha_node, which clhaver cannot communicate to 
		:   through clcomd, to the list of nodes not to try 
		:   to run the command on.
		#
		down_ha_nodes=${down_ha_nodes:+"${down_ha_nodes} "}${ha_node}
	    elif (( $VRMF < $_VER ))
	    then
		#
		:   Add $ha_node to the list of nodes below the minimum
		:   HA release level.
		#
		bad_level_nodes=${bad_level_nodes:+"${bad_level_nodes} "}${ha_node}
	    fi
	done
	if [[ -n $bad_level_nodes ]]
	then
	    #
	    :   Nodes \"$bad_level_nodes\" report that they are running a
	    :   version of PowerHA below the required level $_VERSION
	    #
	    if [[ -z $_SPOC_FORCE ]]
	    then
		nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		"%s[%d]: The command will not be run because the following nodes are below the required level %s: %s\n" "$_CMD" $LINENO $_VERSION "$bad_level_nodes"
	    elif [[ $bad_level_nodes == $good_targets ]]
	    then
		nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		"%s[%d]: The command will not be run because all nodes are below the required level %s: %s\n" "$_CMD" $LINENO $_VERSION "$bad_level_nodes"
	    else
		#
		:   If force was specified, command processing continues
		:   but skips nodes \"$bad_level_nodes\"
		#
		nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		"%s[%d]: The command will be run, but not on the following nodes, which are below the required level %s: %s\n" "$_CMD" $LINENO $_VERSION "$bad_level_nodes" 
	    fi
	    down_ha_nodes=${down_ha_nodes:+"${down_ha_nodes} "}${bad_level_nodes}
	    _RETCODE=1
	fi 
    fi
    if [[ -n $down_ha_nodes ]]
    then
	#
	:   The nodes in \$down_ha_nodes, \"$down_ha_nodes\", are not acceptable
	:   targets for this command, either because CAA says they are down,
	:   or clcomd cannot talk to them, or they are running too far a back
	:   level of PowerHA.  Remove them from the list of C-SPOC target nodes.
	#
	save_targets=""
	for ha_node in $good_targets
	do
	    if [[ $down_ha_nodes != @(?(* )${ha_node}?( *)) ]]
	    then
		save_targets=${save_targets:+"${save_targets} "}${ha_node}
	    fi
	done
	good_targets=$save_targets
	bad_targets=$(IFS=, set -- $down_ha_nodes ; print "$*" )
	if [[ -z $good_targets ]]
	then
	    nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
	    "%s[%d]: The command will not be run because all of the target nodes, %s, are not reachable\n" "$_CMD" $LINENO "$bad_targets"
	    exit 1
	elif [[ -n $bad_targets ]]
	then
	    if [[ -z $_SPOC_FORCE ]]
	    then
		if [[ $bad_targets == @(*,*) ]]
		then
		    nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		    "%s[%d]: The command will not be run because the target nodes, %s, are not reachable\n" "$_CMD" $LINENO "$bad_targets"
		else
		    nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		    "%s[%d]: The command will not be run because the target node, %s, is not reachable\n" "$_CMD" $LINENO "$bad_targets"
		fi
		_RETCODE=1
	    else
		if [[ $bad_targets == @(*,*) ]]
		then
		    nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		    "%s[%d]: The command will be run, but not on the unreachable nodes %s\n" "$_CMD" $LINENO "$bad_targets"
		else
		    nls_msg -2 -l ${cspoc_tmp_log} 4 9999 \
		    "%s[%d]: The command will be run, but not on the unreachable node %s\n" "$_CMD" $LINENO "$bad_targets"
		fi
	    fi
	fi
    fi
    _TARGET_NODES=$(IFS=, set -- $good_targets ; print "$*" )
    #
    :   \$_TARGET_NODES, \"$_TARGET_NODES\", is a list of nodes that are 
    :   up, contactable by clcomd, and running a reasonably up to date
    :   level of PowerHA.
    #
    return $_RETCODE
} # End of "_cspoc_verify()"
################################################################################
#
#   Start of main, Main, MAIN
#
################################################################################
if [[ -n $_DEBUG ]]
then
    print "\n[C-SPOC Initialization Started version 1.16.7.9"
fi
_VER=${_VER:-"6100"}
_VERSION=${_VERSION:-"6.1.0.0"}
export CLUSTER_OVERRIDE="yes"   # Allow CAAC commands to run...      710
_CMD=${0##*/}
integer TRY_RC=0
#
: since root is needed to determine node lists and what not - clgetaddr
: we may as well disable everything right here right now.  By putting
: in an explicit check we can provide a more intuitive message rather
: than something about not being able to execute some command later on.
#
if [[ $(whoami) != "root" ]] && ! ckauth PowerHASM.admin
then
    nls_msg -2 -l ${cspoc_tmp_log} 4 52 \
    "%s: All C-SPOC commands require the user to either be root, or have PowerHASM.admin authorization\n" "$_CMD"
    exit 2
fi
#
: Set a default value, unless this script is called from SMIT, in which
: case _CSPOC_MODE will already be defined.  By default, this should determine
: what the request mode type.
#
export _CSPOC_MODE=${_CSPOC_MODE:-"both"}
#
: By default, assume that we are being called from the command line
#
export _CSPOC_CALLED_FROM_SMIT=${_CSPOC_CALLED_FROM_SMIT:-"false"}
#
: Make sure that the _CMD_ARGS variable is visible everywhere
#
export _CMD_ARGS=""
[[ -n $_DEBUG ]] && print "\n[Parsing Command Line Options ... ]"
#
:   Tell clencodearg to skip the special escape processing for '='
#
if [[ $SKIP_EQ_ESC == true ]]
then
    export _ENCODE_ARGS="-e"
else
    export _ENCODE_ARGS=""
fi
_CSPOC_OPT_STR=${_CSPOC_OPT_STR:--}
_OPT_STR=${_OPT_STR:--}
_getopts "$_CSPOC_OPT_STR" "$_OPT_STR" "$@" || exit 1
if [[ -n $_DEBUG ]]
then
    print "_CMD_ARGS=${_CMD_ARGS}"
    print "_NUM_CMD_ARGS=${_NUM_CMD_ARGS}"
    print "_NON_FLG_ARGS=${_NON_FLG_ARGS}"
    print "\n[Getting Cluster Node List ... ]"
fi
#
:   Determine the nodes in the cluster, and the nodes to which this operation
:   aplies.
#
export ODMDIR=/etc/objrepos
_get_node_list || exit 1
_get_target_nodes || exit 1
if [[ -n $_DEBUG ]]
then
    print "_CLUSTER_NODES=${_CLUSTER_NODES}"
    print "\n[Verifying C-SPOC Requirements ... ]"
fi
if [[ -z $clutilslog ]]
then
   clutilslog=$(clodmget -q 'name = clutils.log' -f value -n HACMPlogs)"/clutils.log"
fi
#
:   If not all nodes are reachable, stop now, unless the "force" flag was
:   specified, implying continue despite unreachable nodes
#
_cspoc_verify || {
    [[ -z $_SPOC_FORCE ]] && exit 1
}
if [[ -n $_DEBUG ]]
then
    print "\n[C-SPOC Initialization Completed.]"
    print "DEBUG: Entering ${0##*/}"
    (( $_DEBUG >= 8 )) && set -x
fi
#
:   Parse operands
#
NewName=""
PVID=""
while getopts ":N:Y:" opt $_CMD_ARGS
    do
	case $opt in
	    N ) : New disk name		; NewName=$OPTARG   ;;
	    Y ) : PVID			; PVID=$OPTARG	    ;;
	    * )	print $_USAGE
		return -1
		;;
	esac
    done
Old_disk=$_NON_FLG_ARGS
DOld_disk=$(print $Old_disk | cldecodearg)
DNewName=$(print $NewName | cldecodearg)
#
:   The disk must be renamed at least on the nodes given in the
:   node list.  However, if the user specified that all instances
:   of this PVID are to be renamed, then if the disk has a different
:   name on some node, it must be renamed there, too.  So, if that 
:   option was selected, find out what extra nodes the rename must
:   be done on.
#
Disk_nodes=""
if [[ -n $PVID ]]
then
    D_PVID=$(print $PVID | cldecodearg)
    ECMD=$(print -- "lspv | grep -w " | clencodearg -e) 
    ECMD="${ECMD}${PVID}"
    Disk_names=""
    for Cluster_node in $(IFS=, set -- $_CLUSTER_NODES ; print $*)
	do
	    if [[ $_TARGET_NODES != @(?(*,)$Cluster_node?(,*)) ]]
	    then
cel_f4
	    fi
	done
fi
#
:   Get a comma separated list of the nodes on which the new
:   disk name will appear, so we can check for a collision
#
Check_nodes=$_TARGET_NODES
if [[ -n $Disk_nodes ]]
then
    Check_nodes="${Check_nodes},${Disk_nodes}"
fi
#
:   Check to make sure that the new disk name is not in use
:   and that the rename disk function is available 
#
if ! name_use_check $DOld_disk $DNewName ||
   ! can_rendev $DOld_disk $DNewName
then
    return 1
fi
#
:   Rename the disk on the list of nodes specified on
:   the command
#
rename_cmd="$(print -- 'rendev -l '${DOld_disk}' -n ' | clencodearg -e )${NewName}"
try_rc=0
cel_f5
    if (( $try_rc != 0 ))
then 
    return $try_rc
fi
if [[ -n $Disk_nodes ]]
then
    #
    :	Also need to rename the disk on other nodes, where
    :	it is not currently named $DOld_name
    #
    for disk_node in $(IFS=, set -- $Disk_nodes ; print $*)
	do
	    #
	    :	Construct the appropriate rename command for $disk_node
	    :	using the list of the current value of the disk name
	    #
	    print $Disk_names | IFS=, read disk_name Disk_names
	    rename_cmd="$(print -- 'rendev -l $disk_name -n ' | clencodearg -e )${NewName}"
cel_f6
	done
fi
if (( $try_rc == 0 ))
then
    #
    :	Success message on completion of rename on all appropriate nodes
    #
    dspmsg -s $_MSET cspoc.cat 83 "cl_rendisk: Physical volume $DOld_disk renamed to $DNewName on $Check_nodes\n" $DOld_disk $DNewName $Check_nodes
fi