#!/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} ${CLXD_SWAP_MG} -n $mg_encode -s $from_site_name_encode -d $to_site_name_encode" EXIT IFS=,$IFS for each_node in $node; do cdsh $cel_s1 $each_node -q ${CLXD_SWAP_MG} -n $mg_encode -s $from_site_name_encode -d $to_site_name_encode cel_rc=$(get_rc ${cel_s1} $each_node) case $cel_rc in 0) TRY_RC=0 IFS=${IFS#,} return ;; *) if [ $cel_rc != 0 ]; then TRY_RC=1 fi ;; esac done IFS=${IFS#,} return $cel_rc } function cel_f2 { cel_s2=/tmp/cel$$_s2 try_err=${cel_s2}.err try_out=${cel_s2}.out trap "log_output $cspoc_tmp_log ${cel_s2} ${CLXD_SWAP_MG} -n $mg_encode -s $from_site_name_encode -d $to_site_name_encode" EXIT IFS=,$IFS for each_node in $node; do cdsh $cel_s2 $each_node -q1 ${CLXD_SWAP_MG} -n $mg_encode -s $from_site_name_encode -d $to_site_name_encode cel_rc=$(get_rc ${cel_s2} $each_node) case $cel_rc in 0) TRY_RC=0 IFS=${IFS#,} return ;; *) if [ $cel_rc != 0 ]; then TRY_RC=1 fi ;; esac done IFS=${IFS#,} return $cel_rc } function cel_f3 { cel_s3=/tmp/cel$$_s3 try_err=${cel_s3}.err try_out=${cel_s3}.out trap "log_output $cspoc_tmp_log ${cel_s3} ${CLXD_SWAP_MG} -n $mg_encode -s $from_site_name_encode -d $to_site_name_encode" EXIT IFS=,$IFS for each_node in $node; do cdsh $cel_s3 $each_node -q ${CLXD_SWAP_MG} -n $mg_encode -s $from_site_name_encode -d $to_site_name_encode cel_rc=$(get_rc ${cel_s3} $each_node) case $cel_rc in 0) TRY_RC=0 IFS=${IFS#,} return ;; *) if [ $cel_rc != 0 ]; then TRY_RC=1 fi ;; esac done IFS=${IFS#,} return $cel_rc } # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # 61haes_r721 src/43haes/usr/sbin/cluster/cspoc/plans/cl_clxd_swap_mg.cel 1.18.1.1 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 2012,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 ############################################################################### # COMPONENT_NAME: CSPOC # # Name: # cl_clxd_swap_mg.cel # # Description # Initiates planned hyperswap for user MG, system MG and repository disk MG # # # Function name : cspoc_swap_user_mgs # # Description : Invokes swap on the node where the MG is active. # if mg_list is "all", it finds all the mgs from ODMS and do the swap # # returns # cspoc_swap_user_mgs() { [[ -n $_DEBUG ]] && { typeset PS4_FUNC=cspoc_swap_user_mgs set -x } RETCODE=0 try_out="" # Get the mg list if [[ "$MG_LIST_GLOBAL" == "all" ]] then mg_list="" # Re-init so the list can be reconstructed, below ${CLXD_LIST_MG} -s "ds8k_inband_mm" "user" | while read LINE do mg_list="$mg_list $LINE" done fi # For each mg in mg_list for mg in $mg_list do TRY_RC=0 MG_DEP_RG=$(${HA_UTILSDIR}/clodmget -n -q "name=GENXD_REP_RESOURCE \ and value=${mg}" -f group HACMPresource) if [[ -z $MG_DEP_RG ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 1 \ "Failed to find a Resource group for Mirror group with name $mg \n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi # Find the affiliated node list for this RG. node="" ${CLRGINFO} ${MG_DEP_RG}|while read LINE do tmp_node=`echo $LINE | awk -F: '($2 == "ONLINE") {print $3}'` node="$node $tmp_node" done for X in $node do RG_STATUS=`/usr/es/sbin/cluster/utilities/clRGinfo -s |grep -w $X |grep -w $MG_DEP_RG|cut -d':' -f2` if [[ $RG_STATUS == UNMANAGED* ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to perform swap for Mirror group: $mg.\nThe affiliated node $X is in UNMANAGED state.\n"$mg $X 1>&2 continue fi pprc_det=`/usr/es/sbin/cluster/utilities/cl_rsh -n $X ${CLXD_PPRC_DETAILS} -n $mg 2>/dev/null` if [[ -z $pprc_det ]] then continue else from_site_name=`echo $pprc_det |/usr/bin/awk -F':' '{print $5}'` to_site_name=`echo $pprc_det |/usr/bin/awk -F':' '{print $6}'` if [[ "$type" == "site" ]] then is_site_valid=$(echo $site_list|sed -n "/$from_site_name/ s/.*\($from_site_name\).*/\1/p") if [[ -z $is_site_valid ]] then continue else break fi elif [[ "$type" == "node" ]] then is_node_valid=$(echo $node_list|sed -n "/$X/ s/.*\($X\).*/\1/p") if [[ -z $is_node_valid ]] then continue else break fi else break fi fi done # Store site details mg_encode=$(print $mg | clencodearg) [[ -n $from_site_name ]] && from_site_name_encode=$(print $from_site_name | clencodearg) [[ -n $to_site_name ]] && to_site_name_encode=$(print $to_site_name | clencodearg) [[ -z $from_site_name_encode || -z $to_site_name_encode ]] && { let RETCODE=RETCODE+1 nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to perform swap for Mirror group: $mg.\nSource or Target site name retrieval failed from PPRC information.\n" $mg 1>&2 continue } if [[ "$type" == "site" ]] then for X in $node do is_node_valid=$(/usr/es/sbin/cluster/utilities/cllssite -c |grep -w $X|awk -F: '{print $1}') if [[ -z $is_node_valid ]]; then is_node_valid=$(/usr/es/sbin/cluster/utilities/cllssite -cx |grep -w $X|awk -F: '{print $1}') fi is_site_valid="" [[ -n $is_node_valid ]] && is_site_valid=$(echo $site_list|sed -n "/$is_node_valid/ s/.*\($is_node_valid\).*/\1/p") [[ -z $is_site_valid ]] && node=$(echo $node|sed "s/$X//g") done fi if [[ "$type" == "node" ]] then for X in $node do is_node_valid=$(echo $node_list|sed -n "/$X/ s/.*\($X\).*/\1/p") [[ -z $is_node_valid ]] && node=$(echo $node|sed "s/$X//g") done fi if [[ -z $node ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Cannot find node to run swap.\nUnable to swap Mirror group $mg\n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi # try to run serially on affiliated node and exit on success cel_f1 if [[ $TRY_RC -ne 0 ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 10 \ "Failed to perform swap for Mirror group: $mg\n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi done [[ -f $try_out ]] && cat $try_out if [[ $RETCODE == 0 ]] then return 0 else return 1 fi } # # Function name : cspoc_swap_sys_mgs # # Description : Invokes swap on all the mgs of type system on a given node. # if mg_list is "all", it finds all the mgs from ODMS and do the swap # # returns # cspoc_swap_sys_mgs() { [[ -n $_DEBUG ]] && { typeset PS4_FUNC=cspoc_swap_sys_mgs set -x } RETCODE=0 try_out="" # Get the mg list if [[ "$MG_LIST_GLOBAL" == "all" ]] then mg_list="" ${CLXD_LIST_MG} -s "ds8k_inband_mm" "system" | while read LINE do mg_list="$mg_list $LINE" done fi if [[ "$type" == "site" ]] then #Getting nodes list for sites selected. node_list="" for site in $site_list do tmp_node=$(cllssite -c|grep -w "^$site"|awk -F: '{print $2}') if [[ -z $tmp_node ]]; then tmp_node=$(cllssite -cx|grep -w "^$site"|awk -F: '{print $2}') fi for node1 in $tmp_node do NODE_STATUS=$(${CLRGINFO} |grep -w $node1 |head -1 |cut -d':' -f2 2>/dev/null) if [[ $NODE_STATUS == UNMANAGED* ]] then continue fi node_list="$node_list $node1" done done fi # For each node in node list for node in $node_list do # For each mg in mg list for mg in $mg_list do TRY_RC=0 aff_node=$(${HA_UTILSDIR}/clodmget -n -q "identifier=$mg and field_type=NODE" -f \ value HACMPxd_ext_attr 2>/dev/null) if [[ -z $aff_node ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 3 \ "Failed to find affiliated nodes for the mirrror group: $mg\n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi if [[ "$node" != $aff_node ]] then continue else NODE_STATUS=`/usr/es/sbin/cluster/utilities/clRGinfo -s |grep -w $aff_node |head -1 |cut -d':' -f2` if [[ $NODE_STATUS == UNMANAGED* ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to perform swap for Mirror group: $mg.\nThe affiliated node $node is in UNMANAGED state.\n"$mg $node 1>&2 continue fi fi pprc_det=`/usr/es/sbin/cluster/utilities/cl_rsh -n $aff_node ${CLXD_PPRC_DETAILS} -n $mg 2>/dev/null` from_site_name=`echo $pprc_det |/usr/bin/awk -F':' '{print $5}'` to_site_name=`echo $pprc_det |/usr/bin/awk -F':' '{print $6}'` # In case of swap mirror group by site site name supplied must be same # as current source site read from clxd if [[ "$type" == "site" ]] then is_site_valid=$(echo $site_list|sed -n "/$from_site_name/ s/.*\($from_site_name\).*/\1/p") if [[ -z $is_site_valid ]] then continue fi fi if [[ "$node" == "$aff_node" ]] then mg_encode=$(print $mg | clencodearg) from_site_name_encode=$(print $from_site_name | clencodearg) to_site_name_encode=$(print $to_site_name | clencodearg) [[ -z $from_site_name_encode || -z $to_site_name_encode ]] && { let RETCODE=RETCODE+1 nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to perform swap for Mirror group: $mg.\nSource/Target site name retrieval failed from PPRC info.\n" $mg 1>&2 continue } cel_f2 if [[ $TRY_RC -ne 0 ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 10 \ "Failed to perform swap for Mirror group: $mg\n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi fi done done [[ -f $try_out ]] && cat $try_out if [[ $RETCODE == 0 ]] then return 0 else return 1 fi } # # Function name : cspoc_swap_repo_mgs # # Description : Invokes swap on the repository mirror groups. # # returns # cspoc_swap_repo_mgs() { [[ -n $_DEBUG ]] && { typeset PS4_FUNC=cspoc_swap_repo_mgs set -x } RETCODE=0 try_out="" # Get the mg list if [[ "$MG_LIST_GLOBAL" == "all" ]] then mg_list="" ${CLXD_LIST_MG} -s "ds8k_inband_mm" "repository" | while read LINE do mg_list="$mg_list $LINE" done fi # For each mg in mg list for mg in $mg_list do TRY_RC=0 aff_sites=$(${HA_UTILSDIR}/clodmget -n -q "identifier=$mg and field_type=site" -f \ value HACMPxd_ext_attr 2>/dev/null) node="" for site in $aff_sites do tmp_node=`/usr/es/sbin/cluster/utilities/cllssite -c|grep -w "^$site"|awk -F: '{print $2}'` if [[ -z $tmp_node ]]; then tmp_node=`/usr/es/sbin/cluster/utilities/cllssite -cx|grep -w "^$site"|awk -F: '{print $2}'` fi for node1 in $tmp_node do NODE_STATUS=`/usr/es/sbin/cluster/utilities/clRGinfo -s |grep -w $node1 |head -1 |cut -d':' -f2` if [[ $NODE_STATUS == UNMANAGED* ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to perform swap for Mirror group: $mg.\nThe affiliated node $node1 is in UNMANAGED state.\n"$mg $node1 1>&2 continue fi node="$node $node1" done done for X in $node do pprc_det=`/usr/es/sbin/cluster/utilities/cl_rsh -n $X ${CLXD_PPRC_DETAILS} -n $mg 2>/dev/null` if [[ -z $pprc_det ]] then continue else from_site_name=`echo $pprc_det |/usr/bin/awk -F':' '{print $5}'` to_site_name=`echo $pprc_det |/usr/bin/awk -F':' '{print $6}'` if [[ "$type" == "site" ]] then is_site_valid=$(echo $site_list|sed -n "/$from_site_name/ s/.*\($from_site_name\).*/\1/p") if [[ -z $is_site_valid ]] then continue else break fi elif [[ "$type" == "node" ]] then is_node_valid=$(echo $node_list|sed -n "/$X/ s/.*\($X\).*/\1/p") if [[ -z $is_node_valid ]] then continue else break fi else break fi fi done mg_encode=$(print $mg | clencodearg) [[ -n $from_site_name ]] && from_site_name_encode=$(print $from_site_name | clencodearg) [[ -n $to_site_name ]] && to_site_name_encode=$(print $to_site_name | clencodearg) [[ -z $from_site_name_encode || -z $to_site_name_encode ]] && { let RETCODE=RETCODE+1 nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to perform swap for Mirror group: $mg.\nSource/Target site name retrieval failed from PPRC info.\n" $mg 1>&2 continue } if [[ "$type" == "site" ]] then for X in $node do is_node_valid=$(/usr/es/sbin/cluster/utilities/cllssite -c |grep -w $X|awk -F: '{print $1}') if [[ -z $is_node_valid ]]; then is_node_valid=$(/usr/es/sbin/cluster/utilities/cllssite -cx |grep -w $X|awk -F: '{print $1}') fi is_site_valid="" [[ -n $is_node_valid ]] && is_site_valid=$(echo $site_list|sed -n "/$is_node_valid/ s/.*\($is_node_valid\).*/\1/p") [[ -z $is_site_valid ]] && node=$(echo $node|sed "s/$X//g") done fi if [[ "$type" == "node" ]] then for X in $node do is_node_valid=$(echo $node_list|sed -n "/$X/ s/.*\($X\).*/\1/p") [[ -z $is_node_valid ]] && node=$(echo $node|sed "s/$X//g") done fi if [[ -z $node ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Cannot find node to run swap.\nUnable to swap Mirror group $mg\n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi cel_f3 if [[ $TRY_RC -ne 0 ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 10 \ "Failed to perform swap for Mirror group: $mg\n" $mg 1>&2 let RETCODE=RETCODE+1 continue fi done [[ -f $try_out ]] && cat $try_out if [[ $RETCODE == 0 ]] then return 0 else return 1 fi } #### MAIN STARTS HERE ####### _CMD_NAME=${0##*/} #_CSPOC_OPT_STR="t:n:i:m:r:s:" _CSPOC_OPT_STR="f" _OPT_STR=":t:n:i:m:r:s:" HA_UTILSDIR="/usr/es/sbin/cluster/utilities" CLXD_SWAP_MG="/usr/es/sbin/cluster/xd_generic/xd_cli/clxd_swap_mg" CLXD_LIST_MG="/usr/es/sbin/cluster/xd_generic/xd_cli/clxd_list_mg_smit" CLXD_PPRC_DETAILS="/usr/es/sbin/cluster/xd_generic/xd_cli/clxd_pprc_details_mg" CLLSNODE="/usr/es/sbin/cluster/utilities/cllsnode" CLRGINFO="/usr/es/sbin/cluster/utilities/clRGinfo -s" # This script requires HA 7.1.2.0 or higher _VER="7120" _VERSION="7.1.2.0" # @(#)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 # 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 # Initialize all the variables MG_FLAG=0 ALL_MGS=0 REPODISK_FLAG=0 REPODISK_SWAP= ROOTVG_FLAG=0 ALL_ROOTVGS=0 MG_LIST= MGS_PASSED= MG_NAME= NODE= RETCODE=0 _MSET=141 MG_LIST_GLOBAL="" NODE=$(${HA_UTILSDIR}/get_local_nodename) NODE_STATE=$(${CLRGINFO} |grep -w $NODE |head -1 |cut -d':' -f2) if [[ "$NODE_STATE" == UNMANAGED* ]] then nls_msg -l ${cspoc_tmp_log} ${_MSET} 999 \ "Failed to initiate swap operation.\nThe current node $NODE is in UNMANAGED state.\n" $NODE 1>&2 exit 1 fi #option m can have the values (site/node/each) OPTSTRING="t:r:s:m:n:i:" while getopts $OPTSTRING opt $_CMD_ARGS do case $opt in t) #values can be (user/sys/repo/node/site) type=$(print $OPTARG | cldecodearg) ;; r) #(yes/no) repo_mg_flag=$(print $OPTARG | cldecodearg) ;; s) #(yes/no) sys_mg_flag=$(print $OPTARG | cldecodearg) ;; m) #value can be mg list or 'all' in case of -t being 'node' or 'site' mg_list=$(print $OPTARG | cldecodearg) ;; n) #value can be single node in case of type being sys or node list or 'all' in case of -t being 'node' node_list=$(print $OPTARG | cldecodearg) ;; i) #value can be site list or 'all' in case of -t being 'site' site_list=$(print $OPTARG | cldecodearg) ;; *) nls_msg -l ${cspoc_tmp_log} ${_MSET} 4 \ "Invalid flag" 1>&2 exit 1 ;; esac done if [[ "$type" == "site" ]] then MG_LIST_GLOBAL="all" cspoc_swap_user_mgs if [[ "$sys_mg_flag" == "yes" ]] then cspoc_swap_sys_mgs fi if [[ "$repo_mg_flag" == "yes" ]] then cspoc_swap_repo_mgs fi elif [[ "$type" == "node" ]] then MG_LIST_GLOBAL="all" cspoc_swap_user_mgs cspoc_swap_repo_mgs if [[ "$sys_mg_flag" == "yes" ]] then cspoc_swap_sys_mgs fi elif [[ "$type" == "user" ]] then cspoc_swap_user_mgs elif [[ "$type" == "sys" ]] then cspoc_swap_sys_mgs elif [[ "$type" == "repository" ]] then cspoc_swap_repo_mgs fi exit 0