#!/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}         start_cluster $_START_CLUSTER_ARGS" EXIT
    IFS=,$IFS
    for _NODE in $node; do
	cdsh $cel_s1 $_NODE         start_cluster $_START_CLUSTER_ARGS
	cel_rc=$(get_rc ${cel_s1} $_NODE)
	case $cel_rc in
	    *)
		if [ $cel_rc != 0 ]; then
		                RETCODE=1
		                if [[ -z "$_SPOC_FORCE" ]]
		                then
		                    #
		                    :   Quit on any error
		                    #
		                    #   Unless the original command said to proceed
		                    #
		                    exit ${RETCODE}
		                fi
		fi
		;;
	esac
    done
    IFS=${IFS#,}
    return $cel_rc
}
#  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/plans/cl_rc.cluster.cel 1.35.1.3 
#  
# 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_rc.cluster.cel, 726, 2147A_aha726, Feb 05 2021 09:50 PM
#   COMPONENT_NAME: CSPOC
#
# Name:
#  cl_rc.cluster.cel
#
# Description:
#  The cl_rc.cluster command starts the cluster daemons on some or all cluster
#  nodes using the rc.cluster script.
#
#   Usage: cl_rc.cluster [-cspoc "[-d DebugLevel] [-f] [-n NodeList]"] \
#                        [-boot] [-l] [-i | -I] [-b] [-N | -R | -B] [-M | -A] \
#                        [-r] [-x] [-v] [-C interactive|yes]
#
# Arguments:
#   The cl_clstop command arguments include all options and arguments
#   that are valid for the clstop command as well as C-SPOC specific
#   arguments.  The C-SPOC specific arguments are as follows:
#       -d 1..9     Debug level (not a public flag)
#   -f      C-SPOC force flag
#   -n NodeList Nodes on which to start the cluster daemons
#       -x              NFS crossmounts to be enabled
#
# Return Values:
#       0       success
#       1       failure
#
###############################################################################
# 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 1.35.1.3"
#
:   Initialize variables
#
_CMD_NAME=$PROGNAME
_CSPOC_OPT_STR="d:f?n:g:"
_OPT_STR="l[iI]b?b.[NRB]rC:v[AM]x"
_USAGE="$(dspmsg -s 18 cspoc.cat 7891 'Usage: cl_rc.cluster [-cspoc \"[-f] [-n NodeList | -g ResourceGroup]\"] [-boot] [-l] [-i | -I] [-b] [-N | -R | -B] [-M | -A] [-r] [-x] [-v] [-C interactive|yes]')"
_MSET=18
RETCODE=0
#
:   C-SPOC Initialization and Verification
#
#  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
_START_CLUSTER_ARGS=""          #   arguments passed to start_cluster 
clinfoFLG=""                    #   '-I' specified, clinfo & consistency group 
CORRECTIVE_ACTION=""            #   yes|interactive|no operand for '-C'
CORRECTIVE_ACTION_FLAG=""       #   -C yes|interactive|no
STARTUP_FLAG="auto"             #   auto|manual management of resource groups    #   default is auto
IGNORE_VERIFY_FLAG=""           #   '-v' specified
A_FLAG=""                       #   '-A' explicitly specified
X_FLAG=""                       #   '-x' explicitly specified
#
:   Check if there are any unsynchronized changes on the local node.
#
:   We expect that it is most likely that users will attempt to start
:   the cluster from the same node where changes were made, and so this
:   check should be adequate. if there are unsynchronized changes on one
:   of the other nodes, then cluster start will fail on all nodes,
:   rather than failing here.  This is considered acceptable.
#
if [[ -z $ODMDIR ]]
then
    ODMDIR=/etc/es/objrepos
fi
#
:   local node name and handle must be set, if not, then
:   there are unsynchronized changes
#
LOCALNODENAME=$(clodmget -f nodename -n HACMPcluster)
HANDLE=$(clodmget -f handle HACMPcluster)
if [[ -z $LOCALNODENAME ]] || (( $HANDLE == 0 )) 
then
    nls_msg -l ${cspoc_tmp_log} -c scripts.cat 1 803 "\n$PROGNAME: Error: Changes have been made to the Cluster Topology or Resource \nconfiguration. The Cluster Configuration must be synchronized before\nstarting Cluster Services.\n" $PROGNAME >&2
    exit 1
fi
#
:   Parsing of input operands
#
if [[ $_CMD_ARGS == "-boot"*(?) ]]
then
    #
    :   The first argument is '-boot', which is handled
    :   separately, because getopts cannot.
    #
    _START_CLUSTER_ARGS="-boot"
    _CMD_ARGS=${_CMD_ARGS##-boot}
fi
OPTIONS=":liIbNRBrC:vAMx"
#
:   Most of the potential operands get passed through unchanged,
:   but the ones requiring special processing, or the ones whose
:   presence implies additional procesing, are separated out here.
#
while getopts $OPTIONS opt $_CMD_ARGS
do
    case $opt in
        x )
            _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -x"
            X_FLAG=true
        ;;
        l | i | b | N | B | r )
            _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -${opt}"
        ;;
        I )
            _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -I"
            clinfoFLG="I"
        ;;
        R )
            _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -R"
            RESTART_FLAG="-R"
        ;;
        C )
            _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -C $OPTARG"
            CORRECTIVE_ACTION=$(print $OPTARG | cldecodearg)
            CORRECTIVE_ACTION_FLAG="-C $CORRECTIVE_ACTION"
        ;;
        v )
            _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -v"
            IGNORE_VERIFY_FLAG="-v"
        ;;
        A )
            A_FLAG=true
        ;;
        M )
            STARTUP_FLAG="manual"
        ;; 
        * )
            print "$_USAGE"
            exit 2
        ;;
    esac
done
#
:   Filter out some incompatible operand combinations
#
if [[ -n $A_FLAG ]]
then
    if [[ -n $X_FLAG ]]
    then
        #
        :   -A and -x cannot both be specified
        #
        print "$_USAGE"
        exit 2
    elif [[ $STARTUP_FLAG == 'manual' ]]
    then
        #
        :   -A and -M cannot both be specified
        #
        print "$_USAGE"
        exit 2
    fi
fi
#
:   Add the encoded argument -P cl_rc_cluster to indicate to the cluster
:   manager how it was started.
#
_START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -P $(print cl_rc_cluster | clencodearg)"
CGodm=$(odmget HACMPpprcconsistgrp)
if [[ -n $CGodm && $clinfoFLG != "I" ]]
then
    #
    :   Consistency groups are defined, but clinfo is not
    :   starting up with Consistency Group support. 
    :   Log, warn user and continue.
    #
    dspmsg -s 18 cspoc.cat 5 \
"WARNING: PPRC Consistency Groups are configured but the consistency group\n\
support option for the Cluster Information Daemon is not set. Without this\n\
option set HACMP support for consistency groups may not work as expected.\n\
To start up the Cluster Information Daemon with consistency groups, set\n\
\"Startup Cluster Information Daemon?\" in smit to \"true with consistency group support\"\n"
fi
#
:   Update the HACMPdaemons ODM class with the start options
#
for node in $(IFS=, set -- $_TARGET_NODES ; echo $* )
do
    cl_rsh $node /usr/es/sbin/cluster/utilities/clchdaemons -O /etc/es/objrepos -n "$node" -d "clstrmgr" -t "start" -o " manage" -v "$STARTUP_FLAG"
done
#
:   If we have been asked to set cluster services to start at system reboot only, 
:   then do not attempt to verify and sync.
#
if [[ -z $RESTART_FLAG ]]
then
    #
    :   Invoke clverify as a prerequisite for starting cluster services
    #
    dspmsg -s 20 scripts.cat 33 "Verifying cluster configuration prior to starting cluster services\n"
    nodelist=$(print $_TARGET_NODES | tr ',' ':')       #   colon separated list
    autoverify_status=/usr/es/sbin/cluster/etc/config/autoverify.status
    /usr/es/sbin/cluster/utilities/cl_auto_versync -N$nodelist $CORRECTIVE_ACTION_FLAG $IGNORE_VERIFY_FLAG  -w $STARTUP_FLAG
    #
    :   Here reduce the list of nodes on which cluster services are 
    :   started to those that have passed verification above.
    #
    #   The format of autoverify.status is
    #   <node name>:[passed|failed]
    #   with one line for each node
    #
    nodelist=""
    while IFS=: read node status
    do 
        [[ $status == "passed" ]] && nodelist="$nodelist $node"
    done < $autoverify_status
    if [[ -z $nodelist ]]
    then
        #
        :   No node passed verification, so quit now
        #
        exit 1
    fi
        #
    :   cl_auto_versync may have determined that the start up option must
    :   be changed from automatic to manual.  If so, it updated HACMPdaemons.
    :   Pick up that change from one of the target nodes.
    #
    targetnode=$(print $_TARGET_NODES | cut -d',' -f1)
    new_STARTUP_FLAG=$(cl_rsh $targetnode /usr/es/sbin/cluster/utilities/clodmget -q \"nodename = $targetnode and daemon = clstrmgr and type = start and object = manage\" -f value -n HACMPdaemons)
    if [[ -n $new_STARTUP_FLAG && $new_STARTUP_FLAG != $STARTUP_FLAG ]]
    then
        #
        :   Update all other nodes with the modified startup option
        #
        for node in $(print $_TARGET_NODES | tr ',' '\n' | grep -vx $LOCALNODENAME)
        do
            cl_rsh $node /usr/es/sbin/cluster/utilities/clchdaemons -O /etc/es/objrepos -n "$node" -d "clstrmgr" -t "start" -o " manage" -v "$new_STARTUP_FLAG"
        done
        STARTUP_FLAG=$new_STARTUP_FLAG
    fi
else
    #
    :   Cluster services started only on AIX restart
    #
    nodelist=$(IFS=, set -- $_TARGET_NODES ; echo $* )      #   space separated list
    nls_msg -l ${cspoc_tmp_log} -c scripts.cat 1 809 "\n\
Setting /etc/inittab to start HACMP at system reboot for node(s): $nodelist\n" "$nodelist"
    nls_msg -l ${cspoc_tmp_log} -c scripts.cat 1 809 "\n\
Setting /etc/inittab to start HACMP at system reboot for node(s): $nodelist\n" "$nodelist" | logger -t "PowerHA SystemMirror for AIX"
fi
#
:   Set the startup option, as potentially modified by cl_auto_versync
#
if [[ $STARTUP_FLAG == "auto" ]]
then
    if [[ -n $X_FLAG ]]
    then
        _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -M"
    else
        _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -A"
    fi
elif [[ $STARTUP_FLAG == "manual" ]]
then
    _START_CLUSTER_ARGS="$_START_CLUSTER_ARGS -M"
fi
#
:   Run start_cluster on the specified cluster nodes. 
:   The script start_cluster script calls rc.cluster and then returns.
#
for node in $nodelist 
do
    if [[ -z $RESTART_FLAG ]]
    then
        nls_msg -l ${cspoc_tmp_log} -c scripts.cat 1 808 "\nStarting Cluster Services on node: $node\n\
This may take a few minutes.  Please wait...\n" $node >&2
    fi
cel_f1
    rm -f $try_out
done
exit $RETCODE

