#!/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 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 " # 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 # :[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