#!/bin/ksh93 # ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2017,2018,2019,2020,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # # @(#) 03d88c7 43haes/lib/ksh93/hacmp/KLIB_HACMP_get_cluster_attributes.sh, 726, 2147A_aha726, Mar 22 2021 04:42 PM #============================================================================ # # Name: KLIB_HACMP_get_cluster_attributes # # Description: This is the main, FPATH function that is invoked by clmgr # to collect cluster-wide information. If invoked in verbose # mode, a comprehensive data collection is done, retrieving # every piece of information known about the cluster. This # is the same as if a verbose query (i.e. clmgr -v query ...) # was done for every known clmgr class. These comprehensive # data pulls are large and slow, but are required for building # the clmgr HTML cluster report. # # Inputs: Refer to the "devDoc()" function at the bottom of this file. # # Outputs: The properties hash is populated for non-verbose queries. # For verbose queries, the collected data is formatted and # displayed directly. # # Returns: Zero if no errors are detected. Otherwise, an appropriate # non-zero value is returned. Refer to the "RETURN" section # of the "devDoc()" function at the bottom of this file for # the standard return code values/meanings for clmgr. # #============================================================================ function KLIB_HACMP_get_cluster_attributes { . $HALIBROOT/log_entry "$0()" "$CL" : version="@(#) 03d88c7 43haes/lib/ksh93/hacmp/KLIB_HACMP_get_cluster_attributes.sh, 726, 2147A_aha726, Mar 22 2021 04:42 PM" : INPUTS: $* typeset -n properties=$1 typeset -l is_cl_defined=${2//\"/} typeset snapshot=${3//\"/} [[ $CLMGR_LOGGING == 'med' ]] && set +x # Only trace param values # : Check to see if this is a normal cluster query, or if instead the : customer really want to view a cluster snapshot instead. If it is : a snapshot query, then extract the given snapshot into a temporary : directory and redirect ODMDIR to that location. # NOTE: if SS_DIR is already set, that means this is the second # invocation of this file (it calls itself) and we should # avoid overwriting the temporary ODMs that we've already # set up. # export SS_DIR # Export to make it visible in the trap function if [[ -n $snapshot && -z $SS_DIR ]] then export CL_SNAPSHOT="$snapshot" # : This is invoked from KLIB_HACMP_view_report, which does all the : needed validations of the snapshot. No need to repeat them here. # SS_DIR="$TMPDIR/clmgr.KHgca.snapshot.$$" mkdir -p "$SS_DIR" if [[ ! -d $SS_DIR ]] then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1350 '\nERROR: Unable to create temporary directory "%1$s" for this operation.\n\n' "$SS_DIR" 1>&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi # : Redirect commands to our private set of constructed ODMs. : We only want to use snapshot data. # export ODMDIR="$SS_DIR" if [[ -z $SNAPSHOTPATH || ! -d $SNAPSHOTPATH ]]; then SNAPSHOTPATH=/usr/es/sbin/cluster/snapshots fi integer ODMSTART=0 ODMEND=0 # Parse snapshot file to obtain ODM data - get the line numbers for # the begining and end tags egrep -nw "&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi # Adjust line numbers to avoid the tags themselves (( ODMSTART++ )) (( ODMEND-- )) (( DIFF = ODMEND - ODMSTART )) if [[ $DIFF == +([0-9]) ]] && (( DIFF > 0 )) then : Get a list of the ODM classes populated within the snapshot print "$0()[$LINENO]($SECONDS): head -n $ODMEND $SNAPSHOTPATH/$CL_SNAPSHOT.odm | tail -n $DIFF | grep '^HACMP[a-z_]*:\$' | sort -u" >>$CLMGR_TMPLOG typeset ODMS=$(head -n $ODMEND $SNAPSHOTPATH/$CL_SNAPSHOT.odm | tail -n $DIFF | grep '^HACMP[a-z_]*:$' | sort -u) print "$0()[$LINENO]($SECONDS): ODMS == ${ODMS//$NL/, }" >>$CLMGR_TMPLOG if [[ -n $ODMS ]] then [[ $ODMS != *HACMPsite* ]] && ODMS=${ODMS:+$ODMS${NL}HACMPsite} # Line is added to get the empty structures for HACMPrgdependency [[ $ODMS != *HACMPrgdependency* ]] && ODMS=${ODMS:+$ODMS${NL}HACMPrgdependency} typeset ODM="" for ODM in $ODMS do cp /etc/es/objrepos/${ODM%:} $SS_DIR/. if (( $? == 0 )) then : Erase the contents. We just need the empty structures. print "$0()[$LINENO]($SECONDS): odmdelete -o ${ODM%:}" >>$CLMGR_TMPLOG odmdelete -o ${ODM%:} >>$CLMGR_TMPLOG 2>&1 else : No need to clean up. The exit trap function will do it. cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1351 '\nERROR: Unable to copy the "%1$s" file to "%2$s".\n\n' "/etc/es/objrepos/${ODM%:}" "$SS_DIR" 1>&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi done print "$0()[$LINENO]($SECONDS): head -n $ODMEND $SNAPSHOTPATH/$CL_SNAPSHOT.odm | tail -n $DIFF | odmadd" >>$CLMGR_TMPLOG # Always log commands head -n $ODMEND $SNAPSHOTPATH/$CL_SNAPSHOT.odm | tail -n $DIFF | odmadd >>$CLMGR_TMPLOG 2>&1 # : Since the return code from the odm commands is not reliable, : run a quick, simple query to see if the population worked. # typeset CNAME=$(clodmget -f name -n HACMPcluster) if [[ -z $CNAME ]] then : No need to clean up. The exit trap function will do it. cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1352 'ERROR: Unable to restore the "%1$s" snapshot to "%2$s".\n\n' "$CL_SNAPSHOT" "$SS_DIR" 1>&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi else cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1353 '\nERROR: Invalid snapshot file (%1$s); invalid format. Verify that the file was created by the cluster snapshot utility.\n\n' "$SNAPSHOTPATH/$CL_SNAPSHOT.odm" 1>&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi else : No need to clean up. The exit trap function will do it. cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1353 '\nERROR: Invalid snapshot file (%1$s); invalid format. Verify that the file was created by the cluster snapshot utility.\n\n' "$SNAPSHOTPATH/$CL_SNAPSHOT" "$SS_DIR" 1>&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi elif [[ -n $snapshot && -n $SS_DIR ]] then : Redirect commands to our private set of constructed ODMs. : We only want to use snapshot data. export ODMDIR="$SS_DIR" fi if [[ -z $CL_SNAPSHOT ]] then #===================================== : See if there is a cluster to query #===================================== CL=$LINENO isClusterDefined if (( $? != RC_SUCCESS )); then log_return_msg "$RC_NOT_FOUND" "$0()" "$LINENO" return $? fi fi #======================================================================= : The need for this function arose *after* the packaging was locked : down for the release. So it was not possible to add a new function! : So this workaround was inserted, and is not documented at this time. #======================================================================= if (( CLMGR_VERBOSE )); then CL=$LINENO getHAData log_return_msg "$?" "$0()" "$LINENO" return $? fi #=================================== : Declare and initialize variables #=================================== for k in ${!properties[*]}; do unset properties[$k]; done typeset key= handle= name= value= DATA= typeset -i matches=0 rc=$RC_UNKNOWN cmd_rc=$RC_UNKNOWN typeset -u attr= uc_key= print "$0()[$LINENO]($SECONDS): odmget HACMPcluster" >>$CLMGR_TMPLOG # Always log commands OUTPUT=$(odmget HACMPcluster) rc=$? print "$0()[$LINENO]($SECONDS): odmget RC: $rc" >>$CLMGR_TMPLOG # Always log command result if (( $rc != RC_SUCCESS )); then rc=$RC_ERROR else print -- "$OUTPUT" |\ while IFS='=' read name value; do name=${name##+([[:space:]])} name=${name%%+([[:space:]])} value=${value##+([[:space:]])} value=${value%%+([[:space:]])} value=${value//\"/} case "$name" in "id") properties[CLUSTER_ID]=$value ;; "name") properties[CLUSTER_NAME]=$value ;; "cluster_version") properties[VERSION_NUMBER]=$value ;; "handle") if [[ $value == 0 ]]; then properties[UNSYNCED_CHANGES]=true else properties[UNSYNCED_CHANGES]=false fi ;; "reserved1") [[ $value == "0" ]] && value=180 properties[MAX_EVENT_TIME]=$value ;; "reserved2") [[ $value == "0" ]] && value=180 properties[MAX_RG_PROCESSING_TIME]=$value ;; "rg_distribution_policy") properties[RG_DIST_POLICY]=$value ;; "node_timeout") properties[HEARTBEAT_FREQUENCY]=$value ;; "node_down_delay") properties[GRACE_PERIOD]=$value ;; "remote_HB_factor") properties[SITE_HEARTBEAT_CYCLE]=$value ;; "link_timeout") properties[SITE_GRACE_PERIOD]=$value ;; "lpm_node_timeout") properties[HEARTBEAT_FREQUENCY_DURING_LPM]=$value ;; "lpm_policy") properties[LPM_POLICY]=$value ;; "network_fdt") properties[NETWORK_FAILURE_DETECTION_TIME]=$value ;; "dr_enabled") if [[ $value == 0 ]]; then properties[CAA_AUTO_START_DR]="Disabled" else properties[CAA_AUTO_START_DR]="Enabled" fi ;; "config_timeout") properties[CAA_CONFIG_TIMEOUT]=$value ;; "repos_mode") if [[ $value == 1 ]]; then properties[CAA_REPOS_MODE]="event" else properties[CAA_REPOS_MODE]="assert" fi ;; "lvm_preferred_read") properties[LVM_PREFERRED_READ]=$value ;; "crit_daemon_restart_grace_period") properties[CRIT_DAEMON_RESTART_GRACE_PERIOD]=$value ;; "skip_events_on_manage") if [[ $value == 1 ]]; then properties[SKIP_EVENT_PROCESSING_MANAGE_MODE]="true" else properties[SKIP_EVENT_PROCESSING_MANAGE_MODE]="false" fi ;; esac done fi #=================================================================== : Check the remainder of the nodes in the cluster to see if *any* : of them have any unsynchronized changes. If any of them do, then : report "UNSYNCED == true" for the whole cluster. #=================================================================== if [[ -z $CLMGR_NO_REMOTE ]]; then if [[ ${properties[UNSYNCED_CHANGES]} == "false" ]]; then print "$0()[$LINENO]($SECONDS): clnodename" >>$CLMGR_TMPLOG # Always log commands typeset NODES="" NODES=$(clnodename 2>>$CLMGR_TMPLOG) print "$0()[$LINENO]($SECONDS): clnodename RC: $?, NODES == \"$NODES\"" >>$CLMGR_TMPLOG # Always log commands for node in $NODES; do [[ $node == $LOCAL_NODE ]] && continue print "$0()[$LINENO]($SECONDS): $CLRSH $node \"$HAUTILS/clodmget -n -f handle HACMPcluster" >>$CLMGR_TMPLOG # Always log commands $CLRSH $node "$HAUTILS/clodmget -n -f handle HACMPcluster" >>$TMPDIR/clmgr.KHgca.uns.$$ 2>>$CLMGR_TMPLOG & done wait if [[ -f $TMPDIR/clmgr.KHgca.uns.$$ ]]; then cat $TMPDIR/clmgr.KHgca.uns.$$ |\ while read unsynced; do if [[ $unsynced == *([[:space:]]) ]] || \ (( $unsynced == 0 )) then properties[UNSYNCED_CHANGES]="true" break fi done rm -f $TMPDIR/clmgr.KHgca.uns.$$ fi fi fi #================================================================= : If the cluster is in the middle of a migration, then it really : does not have a true, single version at the moment. #================================================================= print "$0()[$LINENO]($SECONDS): clmixver" >>$CLMGR_TMPLOG # Always log commands clmixver >/dev/null 2>&1 typeset -i in_migration=$? print "$0()[$LINENO]($SECONDS): clmixver RC: $in_migration" >>$CLMGR_TMPLOG # Always log command result (( in_migration < 0 )) && properties[VERSION_NUMBER]=-1 #=========================================================== : Detect what edition of PowerHA is installed on this node #=========================================================== properties[EDITION]="STANDARD" CL=$LINENO isEnterprise (( $? == 1 )) && properties[EDITION]="ENTERPRISE" if [[ -z ${properties[CLUSTER_NAME]} ]]; then unset properties rc=$RC_SUCCESS # It isn't an error to have no cluster defined! elif [[ -z $is_cl_defined || $is_cl_defined != @(1|y|t)* ]]; then #================================================================= : If the cluster is in the middle of a migration, then it really : does not have a true, single version at the moment. #================================================================= if [[ -z $CL_SNAPSHOT ]] then if (( in_migration < 0 )); then properties[VERSION]=-1 else : Get the user-friendly VRMF string for the cluster server print "$0()[$LINENO]($SECONDS): halevel -esf" >>$CLMGR_TMPLOG # Always log commands properties[VERSION]=$(halevel -esf 2>>$CLMGR_TMPLOG) print "$0()[$LINENO]($SECONDS): halevel RC: $?; VRMF == \"${properties[VERSION]}\"" >>$CLMGR_TMPLOG # Always log command result fi elif [[ -n ${properties[VERSION_NUMBER]} ]] then # : For a snapshot report , all information must be gleaned from the : snapshot itself, not from the current environment. : "properties[VERSION_NUMBER]" was set above, from HACMPcluster. # NOTE: this list mirrors the version info defined in cluster.h. # case ${properties[VERSION_NUMBER]} in 15) properties[VERSION]="7.1.3" ;; 16) properties[VERSION]="7.2.0" ;; 17) properties[VERSION]="7.2.1" ;; 18) properties[VERSION]="7.2.2" ;; 19) properties[VERSION]="7.2.3" ;; 20) properties[VERSION]="7.2.4" ;; *) cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1354 '\nERROR: Unknown or unsupported IBM PowerHA SystemMirror version number detected: "%1$s"\n\n' "${properties[VERSION]}" 1>&2 log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO" return $? ;; esac fi properties[TYPE]=$CLUSTER_TYPE #=================================================================== : Get the current, global file collection "look-for-updated-files" : setting. This setting is stored in seconds, but is displayed to : the user in minutes. #=================================================================== print "$0()[$LINENO]($SECONDS): clodmget -q 'name=file_collections_auto_prop' -f period HACMPtimersvc" >>$CLMGR_TMPLOG # Always log commands typeset PERIOD_STR="" PERIOD_STR=$(clodmget -q 'name=file_collections_auto_prop' -f period HACMPtimersvc) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; PERIOD_STR == \"$PERIOD_STR\"" >>$CLMGR_TMPLOG # Always log command result if [[ $PERIOD_STR == +([0-9]) ]]; then typeset -i PERIOD (( PERIOD = PERIOD_STR / 60 )) # Convert to minutes properties[FC_SYNC_INTERVAL]=$PERIOD fi if [[ -z $CLMGR_NO_REMOTE ]]; then if [[ -z $CL_SNAPSHOT ]] then # : For a snapshot report , all information must be gleaned from : the snapshot itself, not from the current environment. # properties[STATE]=$(CL=$LINENO KLIB_HACMP_get_cluster_state) fi fi #=================================== : The resource group settling time #=================================== print "$0()[$LINENO]($SECONDS): clsettlingtime list | grep -v \"^#\"" >>$CLMGR_TMPLOG # Always log commands typeset STIME="" STIME=$(clsettlingtime list | grep -v "^#") print "$0()[$LINENO]($SECONDS): clsettlingtime RC: $?; STIME == \"$STIME\"" >>$CLMGR_TMPLOG # Always log command result [[ $STIME == +([0-9]) ]] && properties[RG_SETTLING_TIME]=$STIME #=================================== : Cross-site resource group policy #=================================== typeset faction= nmethod= print "$0()[$LINENO]($SECONDS): clodmget -q \"monitor=CROSS_SITE_RG_MOVE and name=FAILURE_ACTION\" -f value HACMPmonitor" >>$CLMGR_TMPLOG # Always log commands faction=$(clodmget -n -q "monitor=CROSS_SITE_RG_MOVE and name=FAILURE_ACTION" -f value HACMPmonitor) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; faction == \"$faction\"" >>$CLMGR_TMPLOG # Always log command result [[ $faction == *([[:space:]]) ]] && faction="fallover" properties[SITE_POLICY_FAILURE_ACTION]=$faction print "$0()[$LINENO]($SECONDS): clodmget -q \"monitor=CROSS_SITE_RG_MOVE and name=NOTIFY_METHOD\" -f value HACMPmonitor" >>$CLMGR_TMPLOG # Always log commands nmethod=$(clodmget -n -q "monitor=CROSS_SITE_RG_MOVE and name=NOTIFY_METHOD" -f value HACMPmonitor) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; nmethod == \"$nmethod\"" >>$CLMGR_TMPLOG # Always log command result properties[SITE_POLICY_NOTIFY_METHOD]=$nmethod #========================================== : Retrieve the auto-verification settings #========================================== typeset data=$(dspmsg -s 1 cluster.cat 862 Enabled,Disabled) typeset ENABLED=${data%%,*} typeset DISABLED=${data##*,} properties[DAILY_VERIFICATION]=$DISABLED print "$0()[$LINENO]($SECONDS): clodmget -f noautoverification HACMPcluster" >>$CLMGR_TMPLOG # Always log commands typeset noautover="" noautover=$(clodmget -f noautoverification HACMPcluster) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; noautover == \"$noautover\"" >>$CLMGR_TMPLOG # Always log command result if [[ $noautover != *([[:space:]]) ]]; then [[ $noautover != "1" ]] && properties[DAILY_VERIFICATION]=$ENABLED fi properties[VERIFICATION_DEBUGGING]="Enabled" if [[ $noautover != *([[:space:]]) && \ ${noautover##*= } != "0" ]] then properties[VERIFICATION_DEBUGGING]="Disabled" fi properties[VERIFICATION_NODE]="Default" print "$0()[$LINENO]($SECONDS): clodmget -f clvernodename HACMPcluster" >>$CLMGR_TMPLOG # Always log commands data=$(clodmget -n -f clvernodename HACMPcluster) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; data == \"$data\"" >>$CLMGR_TMPLOG # Always log command result if [[ $data != *([[:space:]]) ]]; then [[ $data != *([[:space:]]) ]] && properties[VERIFICATION_NODE]=$data fi properties[VERIFICATION_HOUR]="00" print "$0()[$LINENO]($SECONDS): clodmget -f clverhour HACMPcluster" >>$CLMGR_TMPLOG # Always log commands data=$(clodmget -f clverhour HACMPcluster) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; data == \"$data\"" >>$CLMGR_TMPLOG # Always log command result if [[ $data != *([[:space:]]) ]]; then [[ $data == +([0-9]) ]] && properties[VERIFICATION_HOUR]=$data fi # : For a snapshot report , all information must be gleaned from : the snapshot itself, not from the current environment. # if [[ -z $CL_SNAPSHOT ]] then #================================= : Retrieve the security settings #================================= /usr/lib/cluster/incluster typeset -i incluster_rc=$? print "incluster RC: $incluster_rc" >>$CLMGR_TMPLOG if (( $incluster_rc == RC_SUCCESS )); then typeset -u var print "$0()[$LINENO]($SECONDS): LC_ALL=C savesecconf -e ALL" >>$CLMGR_TMPLOG # Always log commands OUTPUT=$(LC_ALL=C savesecconf -e ALL 2>>$CLMGR_TMPLOG) cmd_rc=$? print "$0()[$LINENO]($SECONDS): savesecconf RC: $cmd_rc" >>$CLMGR_TMPLOG if [[ $OUTPUT == *NOT\ ENABLED* ]]; then properties[LEVEL]="DISABLED" else print -- "$OUTPUT" |\ while read LINE; do [[ $LINE != *=* ]] && continue var=${LINE%%*([[:space:]])=*} val=${LINE#*=} [[ -n $val ]] && val=${val##+([[:space:]])} case "$var" in SYMKEYALG) properties[ALGORITHM]="$val" ;; SECLEV) case "$val" in @(1|2|3)) properties[LEVEL]=$(dspmsg -s $CLMGR_SET $CLMGR_MSGS 438 "LOW,MEDIUM,HIGH,DISABLED" |\ cut -d, -f$val) ;; *) properties[LEVEL]=$(dspmsg -s $CLMGR_SET $CLMGR_MSGS 438 "LOW,MEDIUM,HIGH,DISABLED" |\ cut -d, -f4) ;; esac ;; CERTIFICATE_TYPE) properties[MECHANISM]="$val" ;; CERTIFICATE_FILE) properties[CERTIFICATE]="$val" ;; PRVKEY_FILE) properties[PRIVATE_KEY]="$val" ;; esac done fi fi #================================================================= : Get the CAA settings, but only if this is not a linked cluster #================================================================= if [[ $CLUSTER_TYPE != "LC" ]]; then typeset ip= repos= sdisks= print "$0()[$LINENO]($SECONDS): cllsclstr -cS" >>$CLMGR_TMPLOG # Always log commands DATA=$(cllsclstr -cS 2>>$CLMGR_TMPLOG) cmd_rc=$? print -- "$DATA" | IFS=: read cid cname csec persist repos ip print "$0()[$LINENO]($SECONDS): cllsclstr RC: $cmd_rc; $cid:$cname:$csec:$persist:$repos:$ip" >>$CLMGR_TMPLOG # Always log command result if [[ -n $ip ]]; then properties[CLUSTER_IP]=$ip else typeset DATA=$(lscluster -i 2>>$CLMGR_TMPLOG |\ grep "MULTICAST ADDRESS" |\ tail -1 2>/dev/null) DATA=${DATA##*:+([[:space:]])} properties[CLUSTER_IP]=${DATA%%+([[:space:]])*} fi fi fi properties[TEMP_HOSTNAME]="disallow" if [[ $(clodmget -n -f honorTempHostNameChanges HACMPcluster) == 1 ]]; then properties[TEMP_HOSTNAME]="allow" fi # : It is necessary to check for this file being present because at the : the time this was coded, it is NOT present in snapshots. So a lot of : errors erupt when generating a snapshot report. If it is added in : the future, however, this code should "just work". # if [[ -s $ODMDIR/HACMPsplitmerge ]] && \ [[ -z $CL_SNAPSHOT || -n $(grep -w "HACMPsplitmerge:" $CL_SNAPSHOT 2>>$CLMGR_TMPLOG) ]] then # : Retrieve the split-merge properties # typeset -l split="" merge="" action="" pprc="" typeset notify_interval="" max_notify="" survivor="" rest="" print "$0()[$LINENO]($SECONDS): cl_sm -c" >>$CLMGR_TMPLOG DATA=$(VERBOSE_LOGGING="" cl_sm -c) cmd_rc=$? print -- "$DATA" | grep -v '^#' |\ IFS=: read split merge nfs_server local_dir remote_dir quarantine critical_rg action tiebreaker notify_method notify_interval max_notify survivor pprc bucket_name cloud_service use_existing_bucket rest print "$0()[$LINENO]($SECONDS): cl_sm RC: $cmd_rc" >>$CLMGR_TMPLOG properties[SPLIT_POLICY]=$split properties[MERGE_POLICY]=$merge properties[NFS_QUORUM_SERVER]=$nfs_server properties[LOCAL_QUORUM_DIRECTORY]=$local_dir properties[REMOTE_QUORUM_DIRECTORY]=$remote_dir properties[QUARANTINE_POLICY]=$quarantine properties[CRITICAL_RG]=$critical_rg properties[ACTION_PLAN]=$action properties[TIEBREAKER]=$tiebreaker properties[NOTIFY_METHOD]=$notify_method properties[NOTIFY_INTERVAL]=$notify_interval properties[MAXIMUM_NOTIFICATIONS]=$max_notify properties[DEFAULT_SURVIVING_SITE]=$survivor properties[APPLY_TO_PPRC_TAKEOVER]=$pprc properties[BUCKET_NAME]=$bucket_name properties[CLOUD_SERVICE]=$cloud_service properties[USE_EXISTING_BUCKET]=$use_existing_bucket properties[RESPONSE_NEEDED]="" VERBOSE_LOGGING="" cl_smm_check -q 2>>$CLMGR_TMPLOG 1>&2 typeset -i check_rc=$? if (( $check_rc == 1 )); then properties[RESPONSE_NEEDED]="n/a" else typeset none="" reboot="" restart="" rem="" dspmsg -s 58 cluster.cat 47 "None,Tie Breaker,Manual" |\ IFS=, read none rem dspmsg -s 58 cluster.cat 110 \ "Reboot,Disable Applications Auto-Start and Reboot,"\ "Disable Cluster Services Auto-Start and Reboot" |\ IFS=, read Reboot Disable_rgs_autostart Disable_cluster_services_autostart if (( $check_rc == 0 )); then properties[RESPONSE_NEEDED]=$reboot else properties[RESPONSE_NEEDED]=$none fi fi fi # : Check all the nodes Cloud VM or not : Update "Cloud" if all the nodes are Cloud VM : Update "Hybrid" if some of the nodes are Cloud VM and some are not : Update "On-Premise" if none of the nodes are cloud VM # cloud_vmno="" cloud_vmyes="" for node in $(clnodename); do print "$0()[$LINENO]($SECONDS): $CLRSH $node \"LC_ALL=C /usr/es/sbin/cluster/utilities/cl_iscloud_vm\"" >>$CLMGR_TMPLOG # Always log command cloud_flag=$($CLRSH $node /usr/es/sbin/cluster/utilities/cl_iscloud_vm) cmd_rc=$? print "$0()[$LINENO]($SECONDS): $CLRSH $node LC_ALL=C /usr/es/sbin/cluster/utilities/cl_iscloud_vm RC: $cmd_rc" >>$CLMGR_TMPLOG # Always log command result if (( $cmd_rc == 0)); then if [[ "$cloud_flag" == "no" ]];then cloud_vmno="no" else cloud_vmyes="yes" fi fi done if [[ -n "$cloud_vmno" ]] && [[ -n "$cloud_vmyes" ]]; then properties[ONPREM_HYBRID_CLOUD]="Hybrid" elif [[ $cloud_vmno == "no" ]]; then properties[ONPREM_HYBRID_CLOUD]="On_Premise" elif [[ $cloud_vmyes == "yes" ]]; then properties[ONPREM_HYBRID_CLOUD]="Cloud" else properties[ONPREM_HYBRID_CLOUD]="" fi typeset -u HBT=$(clodmget -n -f heartbeattype HACMPcluster) if [[ $HBT != *([[:space:]]) ]]; then [[ $HBT == U* ]] && HBT="UNICAST" || HBT="MULTICAST" elif [[ -z $CL_SNAPSHOT ]] then uc_key=$(LC_ALL=C lscluster -c 2>>$CLMGR_TMPLOG |\ grep "Communication Mode") case $uc_key in *UNI*) HBT=$(dspmsg -s 64 cluster.cat 4 "Unicast\n") ;; *MUL*) HBT=$(dspmsg -s 64 cluster.cat 5 "Multicast\n") ;; esac else HBT="" fi properties[HEARTBEAT_TYPE]=$HBT # : For a snapshot report , all information must be gleaned from : the snapshot itself, not from the current environment. # if [[ -z $CL_SNAPSHOT ]] then # Compute ARR (Automatic Repository Replacement) global indicator on all the nodes of the cluster typeset AUTOMATIC_REPOSITORY_REPLACEMENT="" properties[AUTOMATIC_REPOSITORY_REPLACEMENT]="available" for node in $(clnodename); do # Automatic Repository Replacement capabilities is 4 print "$0()[$LINENO]($SECONDS): $CLRSH $node \"LC_ALL=C /usr/es/sbin/cluster/utilities/cl_get_capabilities -i 4\"" >>$CLMGR_TMPLOG # Always log command $CLRSH $node "LC_ALL=C /usr/es/sbin/cluster/utilities/cl_get_capabilities -i 4" >>$CLMGR_TMPLOG 2>&1 cmd_rc=$? print "$0()[$LINENO]($SECONDS): $CLRSH $node LC_ALL=C cl_get_capabilities RC: $cmd_rc" >>$CLMGR_TMPLOG # Always log command result if (( $cmd_rc != 0)); then properties[AUTOMATIC_REPOSITORY_REPLACEMENT]="unavailable" break fi done fi if [[ $CLUSTER_TYPE != "LC" ]]; then typeset repositories="" CL=$LINENO KLIB_HACMP_list_repositories repositories value=${repositories[*]} properties[REPOSITORIES]="${value//\) /\), }" fi #================================= : Retrieve the hmc settings #================================= print "$0()[$LINENO]($SECONDS): clodmget -n -f default_timeout HACMPhmcparam" >>$CLMGR_TMPLOG # Always log command result typeset -i default_timeout=-1 default_timeout=$(clodmget -n -f default_timeout HACMPhmcparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_timeout == \"$default_timeout\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_timeout ]] ; then properties[DEFAULT_HMC_TIMEOUT]=$default_timeout fi print "$0()[$LINENO]($SECONDS): clodmget -n -f default_retry_count HACMPhmcparam" >>$CLMGR_TMPLOG # Always log command result typeset -i default_retry_count=-1 default_retry_count=$(clodmget -n -f default_retry_count HACMPhmcparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_retry_count == \"$default_retry_count\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_retry_count ]] ; then properties[DEFAULT_HMC_RETRY_COUNT]=$default_retry_count fi print "$0()[$LINENO]($SECONDS): clodmget -n -f default_retry_delay HACMPhmcparam" >>$CLMGR_TMPLOG # Always log command result typeset -i default_retry_delay=-1 default_retry_delay=$(clodmget -n -f default_retry_delay HACMPhmcparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_retry_delay == \"$default_retry_delay\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_retry_delay ]] ; then properties[DEFAULT_HMC_RETRY_DELAY]=$default_retry_delay fi print "$0()[$LINENO]($SECONDS): clodmget -n -f default_hmcs_list HACMPhmcparam" >>$CLMGR_TMPLOG # Always log command result typeset default_hmcs_list="" default_hmcs_list=$(clodmget -n -f default_hmcs_list HACMPhmcparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_hmcs_list == \"$default_hmcs_list\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_hmcs_list ]] ; then properties[DEFAULT_HMCS_LIST]=$default_hmcs_list fi print "$0()[$LINENO]($SECONDS): clodmget -n -f connection_type HACMPhmcparam" >>$CLMGR_TMPLOG # Always log command result typeset -i connectiontype=0 connectiontype=$(clodmget -n -f connection_type HACMPhmcparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, connection_type == \"$connection_type\"" >>$CLMGR_TMPLOG # Always log command result if (( $connectiontype == 1 )); then properties[HMC_CONNECTION_TYPE]=rest else properties[HMC_CONNECTION_TYPE]=ssh fi #================================= : Retrieve the Novalink settings #================================= print "$0()[$LINENO]($SECONDS): clodmget -n -f default_timeout HACMPnovaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i default_timeout=-1 default_timeout=$(clodmget -n -f default_timeout HACMPnovaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_timeout == \"$default_timeout\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_timeout ]] ; then properties[DEFAULT_NOVA_TIMEOUT]=$default_timeout fi print "$0()[$LINENO]($SECONDS): clodmget -n -f default_retry_count HACMPnovaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i default_retry_count=-1 default_retry_count=$(clodmget -n -f default_retry_count HACMPnovaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_retry_count == \"$default_retry_count\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_retry_count ]] ; then properties[DEFAULT_NOVA_RETRY_COUNT]=$default_retry_count fi print "$0()[$LINENO]($SECONDS): clodmget -n -f default_retry_delay HACMPnovaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i default_retry_delay=-1 default_retry_delay=$(clodmget -n -f default_retry_delay HACMPnovaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, default_retry_delay == \"$default_retry_delay\"" >>$CLMGR_TMPLOG # Always log command result if [[ -n $default_retry_delay ]] ; then properties[DEFAULT_NOVA_RETRY_DELAY]=$default_retry_delay fi properties[NOVA_CONNECTION_TYPE]=ssh #============================ : Retrieve the cod settings #============================ print "$0()[$LINENO]($SECONDS): clodmget -n -f always_start_rg HACMProhaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i always_start_rg=-1 always_start_rg=$(clodmget -n -f always_start_rg HACMProhaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, always_start_rg == \"$always_start_rg\"" >>$CLMGR_TMPLOG # Always log command result if [[ $always_start_rg == 0 ]]; then properties[ALWAYS_START_RG]=false else properties[ALWAYS_START_RG]=true fi print "$0()[$LINENO]($SECONDS): clodmget -n -f adjust_spp_size HACMProhaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i adjust_spp_size=-1 adjust_spp_size=$(clodmget -n -f adjust_spp_size HACMProhaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, adjust_spp_size == \"$adjust_spp_size\"" >>$CLMGR_TMPLOG # Always log command result if [[ $adjust_spp_size == 0 ]]; then properties[ADJUST_SPP_SIZE]=false else properties[ADJUST_SPP_SIZE]=true fi print "$0()[$LINENO]($SECONDS): clodmget -n -f force_sync_release HACMProhaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i force_sync_release=-1 force_sync_release=$(clodmget -n -f force_sync_release HACMProhaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, force_sync_release == \"$force_sync_release\"" >>$CLMGR_TMPLOG # Always log command result if [[ $force_sync_release == 0 ]]; then properties[FORCE_SYNC_RELEASE]=false else properties[FORCE_SYNC_RELEASE]=true fi print "$0()[$LINENO]($SECONDS): clodmget -n -f agree_to_cod_costs HACMProhaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i agree_to_cod_costs=-1 agree_to_cod_costs=$(clodmget -n -f agree_to_cod_costs HACMProhaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, agree_to_cod_costs == \"$agree_to_cod_costs\"" >>$CLMGR_TMPLOG # Always log command result if [[ $agree_to_cod_costs == 0 ]]; then properties[AGREE_TO_COD_COSTS]=false else properties[AGREE_TO_COD_COSTS]=true fi print "$0()[$LINENO]($SECONDS): clodmget -n -f onoff_days HACMProhaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i onoff_days=-1 onoff_days=$(clodmget -n -f onoff_days HACMProhaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, onoff_days == \"$onoff_days\"" >>$CLMGR_TMPLOG # Always log command result properties[ONOFF_DAYS]=$onoff_days print "$0()[$LINENO]($SECONDS): clodmget -n -f resource_allocation_order HACMProhaparam" >>$CLMGR_TMPLOG # Always log command result typeset -i resource_allocation_order=-1 resource_allocation_order=$(clodmget -n -f resource_allocation_order HACMProhaparam) print "$0()[$LINENO]($SECONDS): clodmget RC: $?, resource_allocation_order == \"$resource_allocation_order\"" >>$CLMGR_TMPLOG # Always log command result if [[ $resource_allocation_order == 2 ]]; then properties[RESOURCE_ALLOCATION_ORDER]=all_enterprise_pool_before_free_pool elif [[ $resource_allocation_order == 1 ]]; then properties[RESOURCE_ALLOCATION_ORDER]=enterprise_pool_before_free_pool else properties[RESOURCE_ALLOCATION_ORDER]=free_pool_before_enterprise_pool fi #============================================================== : Even if there is no value for a given attribute, we want to : display a placeholder for it, so the customer always sees a : consistent, complete set of attributes. #============================================================== for key in ${_COLON_ATTR_ORDER[cluster]}; do if [[ -z ${properties[$key]} ]]; then properties[$key]="" fi done #================================================================== : If this is a linked cluster, then do not display CAA properties #================================================================== if [[ $CLUSTER_TYPE == "LC" ]]; then unset properties[REPOSITORIES] unset properties[CLUSTER_IP] unset properties[SHARED_DISKS] elif [[ ${properties[HEARTBEAT_TYPE]} == "UNICAST" ]]; then unset properties[CLUSTER_IP] fi #======================================================= # Check for any inputs that limit the requested output #======================================================= typeset -u CMD_ARGS=${_EVENT_SCRIPT_ARGS//[,:\|\"]/ } for ARG in $CMD_ARGS; do typeset DISPLAY="" case $ARG in ALL) CLMGR_ATTRS="" break ;; SEC*) for ARG in LEVEL ALGORITHM MECHANISM CERTIFICATE PRIVATE_KEY do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; @(SPL|MER)*) for ARG in SPLIT_POLICY MERGE_POLICY ACTION_PLAN \ NFS_QUORUM_SERVER LOCAL_QUORUM_DIRECTORY REMOTE_QUORUM_DIRECTORY \ TIEBREAKER NOTIFY_METHOD NOTIFY_INTERVAL \ MAXIMUM_NOTIFICATIONS DEFAULT_SURVIVING_SITE \ APPLY_TO_PPRC_TAKEOVER do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; @(PER|TUN)*) for ARG in HEARTBEAT_FREQUENCY GRACE_PERIOD \ SITE_HEARTBEAT_CYCLE SITE_GRACE_PERIOD \ FC_SYNC_INTERVAL \ NOTIFY_INTERVAL HEARTBEAT_FREQUENCY_DURING_LPM \ NETWORK_FAILURE_DETECTION_TIME \ CAA_AUTO_START_DR CAA_DEADMAN_MODE \ CAA_CONFIG_TIMEOUT CAA_REPOS_MODE do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; HMC) for ARG in DEFAULT_HMC_TIMEOUT DEFAULT_HMC_RETRY_COUNT DEFAULT_HMC_RETRY_DELAY DEFAULT_HMCS_LIST HMC_CONNECTION_TYPE do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; NOV*) for ARG in DEFAULT_NOVA_TIMEOUT DEFAULT_NOVA_RETRY_COUNT DEFAULT_NOVA_RETRY_DELAY NOVA_CONNECTION_TYPE do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; ROH*) for ARG in ALWAYS_START_RG ADJUST_SPP_SIZE \ FORCE_SYNC_RELEASE AGREE_TO_COD_COSTS \ ONOFF_DAYS RESOURCE_ALLOCATION_ORDER do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; COR*) for ARG in CLUSTER_NAME CLUSTER_ID STATE TYPE \ HEARTBEAT_TYPE CLUSTER_IP REPOSITORIES \ VERSION VERSION_NUMBER EDITION \ UNSYNCED_CHANGES FC_SYNC_INTERVAL \ RG_SETTLING_TIME RG_DIST_POLICY \ MAX_EVENT_TIME MAX_RG_PROCESSING_TIME \ DAILY_VERIFICATION VERIFICATION_NODE \ VERIFICATION_HOUR VERIFICATION_DEBUGGING \ HEARTBEAT_FREQUENCY GRACE_PERIOD \ SITE_POLICY_FAILURE_ACTION \ SITE_POLICY_NOTIFY_METHOD \ SITE_HEARTBEAT_CYCLE SITE_GRACE_PERIOD \ TEMP_HOSTNAME LPM_POLICY AUTOMATIC_REPOSITORY_REPLACEMENT \ NETWORK_FAILURE_DETECTION_TIME LVM_PREFERRED_READ \ CRIT_DAEMON_RESTART_GRACE_PERIOD do if [[ " $CLMGR_ATTRS " != *\ $ARG\ * ]]; then CLMGR_ATTRS="$CLMGR_ATTRS $ARG" fi done ;; esac done elif [[ -n $is_cl_defined && $is_cl_defined == @(1|y|t)* ]]; then # : For a request to determine simply if the cluster is defined : or not, return no properties and set the return code to zero : if the cluster is defined, or 1 if it is not. # rc=$RC_SUCCESS if [[ -z ${properties[CLUSTER_NAME]} ]]; then rc=$RC_ERROR fi for attr in ${!properties[*]} do unset properties[$attr] done fi log_return_msg "$rc" "$0()" "$LINENO" return $? } # End of "KLIB_HACMP_get_cluster_attributes()" #============================================================================= # # Name: on_exit_getHAData # # Description: Signal handler for the verbose cluster information retrieval. # When an EXIT signal is detected, any temporary data # directories that have been created, but not removed, are # removed. # # NOTE: A retry loop is used around the recursive removal of # $GHAD_TEMPDIR. This was done due to an intermittent # problem where some processes still writing to that # location had not fully died and released their file # handles yet. This would prevent the removal from # being successful. The retry loop resolved this issue. # # Inputs: None. # # Outputs: None. # # Returns: None. # #============================================================================= function on_exit_getHAData { if [[ -n $GHAD_TEMPDIR && -e $GHAD_TEMPDIR && $GHAD_TEMPDIR == *\.ghd* ]] then cd / typeset -i i for (( i=5; i>0; i-- )); do rm -rf $GHAD_TEMPDIR 2>/dev/null [[ ! -e $GHAD_TEMPDIR ]] && break sleep 1 done fi if [[ -n $SS_DIR && -d $SS_DIR && -n $TMPDIR && $SS_DIR == $TMPDIR/* ]] then rm -rf "$SS_DIR" fi } # End of "on_exit_getHAData()" #============================================================================== # # Name: getHAData # # Description: Collects data for all known SystemMirror object classes, then # displays it in the format requested by the user, defaulting to # a simple XML format. # # Inputs: CLMGR_TIMEOUT # Optional. Externally set in the environment. Sets the # upper limit to wait for the overall operation to complete. # If this limit is reached, an error is displayed and no # results are returned. # # CLMGR_CMD_GROUP_SIZE # Optional. Externally set in the environment. Specifies # how many class data retrieval to group within a given # backgrounded process (they run serially within that # process). This allows the process table impact to be # controlled a bit, and can also be used to tune # performance to some degree. # # Outputs: The collected data is displayed on STDOUT in the appropriate # format. # # Returns: Zero if no errors were detected. Otherwise, a one is returned # to indicate that problems occurred. # #============================================================================== function getHAData { trap 'on_exit_getHAData' EXIT . $HALIBROOT/log_entry "$0()" "$CL" : version="@(#) 03d88c7 43haes/lib/ksh93/hacmp/KLIB_HACMP_get_cluster_attributes.sh, 726, 2147A_aha726, Mar 22 2021 04:42 PM" : INPUTS: $* [[ $CLMGR_LOGGING == 'med' ]] && set +x # Only trace param values typeset -i result=$RC_UNKNOWN [[ $CLMGR_TIMEOUT != +([0-9]) ]] && CLMGR_TIMEOUT=600 (( $CLMGR_TIMEOUT < 60 )) && CLMGR_TIMEOUT=60 [[ $CLMGR_CMD_GROUP_SIZE != +([0-9]) ]] && CLMGR_CMD_GROUP_SIZE=6 (( $CLMGR_CMD_GROUP_SIZE < 1 )) && CLMGR_CMD_GROUP_SIZE=1 export CLMGR_CMD_GROUP_SIZE typeset -i CMD_COUNT=0 typeset GHAD_CHILDREN="" CMDS_DATA="" CLASS="" LOG="" CMD="" MISC="" typeset CLASS_DATA="" DATA="" CMDS_DATA="" if [[ -z $CL_SNAPSHOT ]] then CL=$LINENO isClusterDefined if (( $? != RC_SUCCESS )); then return $RC_MISSING_DEPENDENCY fi fi export GHAD_TEMPDIR="$TMPDIR/clmgr.KHgca.ghd.$$" # Global, for visibility in on_exit_getHAData()! export IF_LOG="$GHAD_TEMPDIR/ifdata" # Global, for visibility in spawn_cmds() export RG_LOG="$GHAD_TEMPDIR/rgdata" # Global, for visibility in spawn_cmds() typeset HOST_LOG="$GHAD_TEMPDIR/hostdata" typeset CLUSTER_LOG="$GHAD_TEMPDIR/cldata" typeset RP_LOG="$GHAD_TEMPDIR/rpdata" typeset SITE_LOG="$GHAD_TEMPDIR/stdata" typeset NODE_LOG="$GHAD_TEMPDIR/nddata" typeset NW_LOG="$GHAD_TEMPDIR/nwdata" typeset FT_LOG="$GHAD_TEMPDIR/ftdata" typeset FC_LOG="$GHAD_TEMPDIR/fcdata" typeset SNAPSHOT_LOG="$GHAD_TEMPDIR/ssdata" typeset AC_LOG="$GHAD_TEMPDIR/acdata" typeset AM_LOG="$GHAD_TEMPDIR/amdata" typeset SI_LOG="$GHAD_TEMPDIR/sidata" typeset PI_LOG="$GHAD_TEMPDIR/pidata" typeset METHOD_LOG="$GHAD_TEMPDIR/mddata" typeset TAPE_LOG="$GHAD_TEMPDIR/tpdata" typeset DEP_LOG="$GHAD_TEMPDIR/dpdata" typeset VG_LOG="$GHAD_TEMPDIR/vgdata" typeset LV_LOG="$GHAD_TEMPDIR/lvdata" typeset PV_LOG="$GHAD_TEMPDIR/pvdata" typeset FS_LOG="$GHAD_TEMPDIR/fsdata" typeset COD_LOG="$GHAD_TEMPDIR/coddata" typeset EV_LOG="$GHAD_TEMPDIR/evdata" typeset HMC_LOG="$GHAD_TEMPDIR/hmcdata" typeset MP_LOG="$GHAD_TEMPDIR/mpdata" typeset STA_LOG="$GHAD_TEMPDIR/stadata" typeset STS_LOG="$GHAD_TEMPDIR/stsdata" typeset MIP_LOG="$GHAD_TEMPDIR/mipdata" typeset MIG_LOG="$GHAD_TEMPDIR/migdata" typeset GHAD_RESULTS_FILE="$GHAD_TEMPDIR/rcs" typeset NODES=$(clnodename 2>/dev/null) NODES=${NODES//+([[:space:]])/,} #=========================================================== : Defined the classes whose information is to be retrieved #=========================================================== CL=$LINENO isEnterprise if (( $? == 1 )); then : Enterprise Edition CLASS_DATA="\ APPLICATION_CONTROLLERS:$AC_LOG:KLIB_HACMP_get_appserver_attributes APPLICATION_MONITORS:$AM_LOG:KLIB_HACMP_get_appmonitor_attributes CLUSTER:$CLUSTER_LOG COD:$COD_LOG DEPENDENCIES:$DEP_LOG EVENTS:$EV_LOG FALLBACK_TIMERS:$FT_LOG FILE_COLLECTIONS:$FC_LOG:KLIB_HACMP_get_filecollection_attributes FILE_SYSTEMS:$FS_LOG HMCS:$HMC_LOG HOSTS:$HOST_LOG:KLIB_HACMP_get_host_info INTERFACES:$IF_LOG LOGICAL_VOLUMES:$LV_LOG METHODS:$METHOD_LOG MIRROR_GROUPS:$MIG_LOG MIRROR_PAIRS:$MIP_LOG MIRROR_POOLS:$MP_LOG NETWORKS:$NW_LOG NODES:$NODE_LOG PERSISTENT_IPS:$PI_LOG PHYSICAL_VOLUMES:$PV_LOG:KLIB_HACMP_get_physical_volume_attributes REPOSITORIES:$RP_LOG RESOURCE_GROUPS:$RG_LOG:KLIB_HACMP_get_rg_attributes SERVICE_IPS:$SI_LOG SITES:$SITE_LOG SNAPSHOTS:$SNAPSHOT_LOG STORAGE_AGENTS:$STA_LOG STORAGE_SYSTEMS:$STS_LOG TAPES:$TAPE_LOG VOLUME_GROUPS:$VG_LOG" else : Standard Edition CLASS_DATA="\ APPLICATION_CONTROLLERS:$AC_LOG:KLIB_HACMP_get_appserver_attributes APPLICATION_MONITORS:$AM_LOG:KLIB_HACMP_get_appmonitor_attributes CLUSTER:$CLUSTER_LOG COD:$COD_LOG DEPENDENCIES:$DEP_LOG EVENTS:$EV_LOG FALLBACK_TIMERS:$FT_LOG FILE_COLLECTIONS:$FC_LOG:KLIB_HACMP_get_filecollection_attributes FILE_SYSTEMS:$FS_LOG HMCS:$HMC_LOG HOSTS:$HOST_LOG:KLIB_HACMP_get_host_info INTERFACES:$IF_LOG LOGICAL_VOLUMES:$LV_LOG METHODS:$METHOD_LOG MIRROR_POOLS:$MP_LOG NETWORKS:$NW_LOG NODES:$NODE_LOG PERSISTENT_IPS:$PI_LOG PHYSICAL_VOLUMES:$PV_LOG:KLIB_HACMP_get_physical_volume_attributes REPOSITORIES:$RP_LOG RESOURCE_GROUPS:$RG_LOG:KLIB_HACMP_get_rg_attributes SERVICE_IPS:$SI_LOG SITES:$SITE_LOG SNAPSHOTS:$SNAPSHOT_LOG TAPES:$TAPE_LOG VOLUME_GROUPS:$VG_LOG" fi if [[ -n $CL_SNAPSHOT ]] then # : Remove classes that are not snapshot-supported. : Since they will not be displayed anyway, there : is no reason to collect their information. It : is a minor performance improvement. # for CLASS in COD HMCS HOSTS LOGICAL_VOLUMES MIRROR_GROUPS MIRROR_PAIRS \ PHYSICAL_VOLUMES STORAGE_AGENTS STORAGE_SYSTEMS do CLASS_DATA=$(print -- "$CLASS_DATA" | grep -vw "$CLASS") done fi #=========================================================== : These classes run slowly enough that they need to be run : on their own, and not as part of a commands group. #=========================================================== typeset -l SLOW_CLASSES="" umask 0077 if [[ -e $GHAD_TEMPDIR && $GHAD_TEMPDIR == *\.ghd* ]]; then cd / typeset -i i for (( i=5; i>0; i-- )); do rm -rf $GHAD_TEMPDIR 2>/dev/null [[ ! -e $GHAD_TEMPDIR ]] && break sleep 1 done fi if [[ -e $GHAD_TEMPDIR ]]; then if [[ $CLMGR_PROGNAME == "clmgr" ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 39 "\nERROR: could not create a temporary storage location in \"%1\$s\".\n\n" "$GHAD_TEMPDIR" 1>&2 fi result=$RC_ERROR else mkdir -p $GHAD_TEMPDIR fi if (( $result == RC_UNKNOWN )); then #========================================================== : A minor regular expression that indicates which classes : require special execution handling, and thus should not : be run via the spawn_cmds function. #========================================================== typeset SPECIAL_HANDLING="logi|volu|file_s|int|res|serv|pers|mp" for DATA in $CLASS_DATA; do typeset -l CLASSNAME=${DATA%%:*} if [[ " $SLOW_CLASSES " == *\ $CLASSNAME\ * && \ $CLASSNAME != @($SPECIAL_HANDLING)* ]] then : The following classes are exempted from normal processing : here in order to enable performance optimization: : logical volumes, file systems, volume groups, interfaces, : resource groups, service IPs, persistent IPs and mirror pools spawn_cmds "$DATA" GHAD_CHILDREN "$GHAD_RESULTS_FILE" fi done for DATA in $CLASS_DATA; do typeset -l CLASSNAME=${DATA%%:*} if [[ " $SLOW_CLASSES " != *\ $CLASSNAME\ * && \ $CLASSNAME != @($SPECIAL_HANDLING)* ]] then : The $CLASSNAME data can be retrieved asynchronously (( CMD_COUNT++ )) CMDS_DATA="$CMDS_DATA $DATA" if (( $CMD_COUNT == CLMGR_CMD_GROUP_SIZE )); then spawn_cmds "${CMDS_DATA# }" GHAD_CHILDREN "$GHAD_RESULTS_FILE" CMD_COUNT=0 # Reset CMDS_DATA="" fi fi done if (( $CMD_COUNT > 0 )) && [[ $CMDS_DATA != *([[:space:]]) ]]; then spawn_cmds "${CMDS_DATA# }" GHAD_CHILDREN "$GHAD_RESULTS_FILE" fi if [[ -n $GHAD_CHILDREN ]]; then ( if [[ -z $CL_SNAPSHOT ]] then #========================================================== : Use the super-fast C-SPOC command to get VG/LV/FS info. : Invoking it globally will allow the LVM FPATH functions : to use the data without each having to invoke the same : command to get the same data. It is a performance : optimization, in other words. #========================================================== typeset TEMPDATAFILE="$TMPDIR/clmgr.cl_ls_vglvfs.data.$$" typeset TEMPERRFILE="$TMPDIR/clmgr.cl_ls_vglvfs.err.$$" integer SLEEP_INTERVAL=5 try=0 for (( try=0; $try<5; try++ )); do print "$0()[$LINENO]($SECONDS): cl_ls_vglvfs -cspoc \"-n $NODES\" -r >$TEMPDATAFILE 2>$TEMPERRFILE" >>$CLMGR_TMPLOG cl_ls_vglvfs -cspoc "-n $NODES" -r >$TEMPDATAFILE 2>$TEMPERRFILE cmd_rc=$? print "$0()[$LINENO]($SECONDS): cl_ls_vglvfs RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc == RC_SUCCESS )) && \ [[ -s $TEMPDATAFILE && ! -s $TEMPERRFILE ]] then [[ -f $TEMPERRFILE ]] && rm -f $TEMPERRFILE break elif (( $try < 4 )); then sleep $SLEEP_INTERVAL # If there is still a problem, then let's # wait a little longer the next time around. (( SLEEP_INTERVAL += 5 )) elif [[ -f $TEMPDATAFILE ]]; then rm -f $TEMPDATAFILE fi done fi typeset LVM_CHILDREN="" typeset LVM_RESULTS_FILE="$GHAD_TEMPDIR/lvm_rcs" spawn_cmds "FILE_SYSTEMS:$FS_LOG LOGICAL_VOLUMES:$LV_LOG VOLUME_GROUPS:$VG_LOG MIRROR_POOLS:$MP_LOG" \ LVM_CHILDREN $LVM_RESULTS_FILE if [[ -n $LVM_CHILDREN ]]; then wait $LVM_CHILDREN typeset LVM_RCS=$(cat $LVM_RESULTS_FILE) print -n -- "$LVM_RCS" >>$GHAD_RESULTS_FILE [[ -f $TEMPDATAFILE ]] && rm -f $TEMPDATAFILE [[ -f $TEMPERRFILE ]] && rm -f $TEMPERRFILE fi )& GHAD_CHILDREN="$GHAD_CHILDREN $!" fi if [[ -n $GHAD_CHILDREN ]]; then ( #=============================================================== : Process the interface classes, along with the resource group : class in a specific sequence in order to enable performance : optimizations: : 1. KLIB_HACMP_get_rg_attributes : 2. KLIB_HACMP_get_interface_attributes : 3. KLIB_HACMP_get_service_ip_attributes, : KLIB_HACMP_get_persistent_ip_attributes : This sequence enables the elimination of some data retrieval : redundancies, resulting in a performance boost. #=============================================================== export CLMGR_VERBOSE=1 # : Process resource groups # typeset ORIG_CLMGR_TMPLOG=$CLMGR_TMPLOG typeset ORIG_CLMGR_ERRLOG=$CLMGR_ERRLOG export CLMGR_TMPLOG=$GHAD_TEMPDIR/clmgr.KHgca.resource_group.$$ export CLMGR_ERRLOG=$GHAD_TEMPDIR/clmgr.KHgca.resource_group.$$ unset props typeset -A props print "\ ### ### RESOURCE GROUPS ### $0()[$(($LINENO+1))]($SECONDS):\tKLIB_HACMP_get_rg_attributes props" >>$CLMGR_TMPLOG CL=$LINENO KLIB_HACMP_get_rg_attributes props cmd_rc=$? print "$0()[$LINENO]($SECONDS): KLIB_HACMP_get_rg_attributes RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc != 0 )); then cat <>$CLMGR_TMPLOG; ERROR: could not collect resource_group information. To debug further, consider querying this class by itself: clmgr -v query resource_group For more detailed information, consider collecting trace ouput: clmgr -v -l high query resource_group EORG dspmsg -s $CLMGR_SET $CLMGR_MSGS 467 '\nERROR: could not collect %1$s information.\n' "resource group" 1>&2 fi print -n $cmd_rc >>$GHAD_RESULTS_FILE CL=$LINENO SerializeAsAssociativeArray props resource_group >$RG_LOG unset props # : Process interfaces # export CLMGR_TMPLOG=$GHAD_TEMPDIR/clmgr.KHgca.interface.$$ export CLMGR_ERRLOG=$GHAD_TEMPDIR/clmgr.KHgca.interface.$$ typeset -A props print "\ ### ### INTERFACES ### $0()[$(($LINENO+1))]($SECONDS):\tKLIB_HACMP_get_interface_attributes props" >>$CLMGR_TMPLOG CL=$LINENO KLIB_HACMP_get_interface_attributes props cmd_rc=$? print "$0()[$LINENO]($SECONDS): KLIB_HACMP_get_interface_attributes RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc != 0 )); then cat <>$CLMGR_TMPLOG; ERROR: could not collect interface information. To debug further, consider querying this class by itself: clmgr -v query interface For more detailed information, consider collecting trace ouput: clmgr -v -l high query interface EOIF dspmsg -s $CLMGR_SET $CLMGR_MSGS 467 '\nERROR: could not collect %1$s information.\n' "interface" 1>&2 fi print -n $cmd_rc >>$GHAD_RESULTS_FILE CL=$LINENO SerializeAsAssociativeArray props interface >$IF_LOG unset props # : Process service and persistent IPs # export CLMGR_TMPLOG=$ORIG_CLMGR_TMPLOG export CLMGR_ERRLOG=$ORIG_CLMGR_ERRLOG typeset IF_CHILDREN="" typeset IF_RESULTS_FILE="$GHAD_TEMPDIR/if_rcs" spawn_cmds "SERVICE_IP:$SI_LOG PERSISTENT_IP:$PI_LOG" \ IF_CHILDREN $IF_RESULTS_FILE if [[ -n $IF_CHILDREN ]]; then wait $IF_CHILDREN typeset IF_RCS=$(cat $IF_RESULTS_FILE) print -n -- "$IF_RCS" >>$GHAD_RESULTS_FILE fi )& GHAD_CHILDREN="$GHAD_CHILDREN $!" fi if [[ -n $GHAD_CHILDREN ]]; then : ############################## : Set an alarm to prevent a hang ( sleep $CLMGR_TIMEOUT & alarmPID=$! print -n $alarmPID >$GHAD_TEMPDIR/ghad.alarm.pid wait $alarmPID cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 462 "Warning: could not collect all IBM PowerHA SystemMirror data in the allotted time ($CLMGR_TIMEOUT seconds).\n" "$CLMGR_TIMEOUT" 1>&2 [[ -n $CLMGR_COMMAND ]] && print -u2 "\n\t${CLMGR_COMMAND/ -T $CLMGR_TRANSACTION_ID}\n" print -n 1 >>$GHAD_RESULTS_FILE cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 470 "Attempting to terminate any remaining, active processes...\n\n" "$CLMGR_TIMEOUT" 1>&2 for pid in $GHAD_CHILDREN; do kill $pid 2>/dev/null 1>&2; done sleep 5 for pid in $GHAD_CHILDREN; do kill -9 $pid 2>/dev/null 1>&2; done )& typeset -i reaperPID=$! : ###################################################### : Wait for all the backgrounded processes to complete... wait $GHAD_CHILDREN typeset ALARM_PIDS="$reaperPID $([[ -f $GHAD_TEMPDIR/ghad.alarm.pid ]] && cat $GHAD_TEMPDIR/ghad.alarm.pid)" ALARM_PIDS=${ALARM_PIDS% } for SIGNAL in INT PIPE KILL do kill -$SIGNAL $ALARM_PIDS 2>/dev/null 1>&2 sleep 1 if [[ "$(ps -eo 'pid,ppid,args' | grep -we ${ALARM_PIDS// / -we } | grep -wv grep)" == *([[:space:]]) ]] then break fi done if [[ -f $GHAD_TEMPDIR/ghad.alarm.pid ]]; then rm -f $GHAD_TEMPDIR/ghad.alarm.pid fi typeset NON_ZERO_RCS=$(cat $GHAD_RESULTS_FILE) NON_ZERO_RCS=${NON_ZERO_RCS//0/} NON_ZERO_RCS=${NON_ZERO_RCS//+([[:space:]])/} if [[ $NON_ZERO_RCS != *([[:space:]]) ]]; then typeset ZERO_RCS=$(cat $GHAD_RESULTS_FILE) if [[ $ZERO_RCS != *0* ]]; then # : If all queries failed, error out # result=$RC_ERROR else # : If at least one query worked, display what you can # result=$RC_SUCCESS fi else result=$RC_SUCCESS fi rm -f $GHAD_RESULTS_FILE typeset -l CLASSNAME="" for CLASSNAME in $CLASS_DATA do CLASSNAME=${CLASSNAME%%:*} case $CLASSNAME in *ies) CLASSNAME="${CLASSNAME%ies}y" ;; *s ) CLASSNAME="${CLASSNAME%s}" ;; esac if [[ -f $GHAD_TEMPDIR/clmgr.KHgca.$CLASSNAME.$$ ]] then print >>$CLMGR_TMPLOG cat $GHAD_TEMPDIR/clmgr.KHgca.$CLASSNAME.$$ >>$CLMGR_TMPLOG rm -f $GHAD_TEMPDIR/clmgr.KHgca.$CLASSNAME.$$ fi done fi if (( $result == RC_SUCCESS )); then #================================= : Display all the data on STDOUT #================================= if (( CLMGR_JSON )) then print "{\n \"clmgr\": {" # Start the tree else print "\n" # Start root element fi integer TOTAL_CLASSES=$(print -- $CLASS_DATA | LC_ALL=C wc -w) integer CLASS_COUNT=0 LAST=0 for DATA in $CLASS_DATA; do (( CLASS_COUNT++ )) print -- "$DATA" | IFS=: read CLASS LOG CMD MISC (( CLASS_COUNT == TOTAL_CLASSES )) && LAST=1 display_data "$CLASS" "$LOG" "$LAST" if [[ -f $LOG.stderr ]]; then [[ -s $LOG.stderr ]] && cat $LOG.stderr 1>&2 rm -f $LOG.stderr fi done if (( CLMGR_JSON )) then print " }\n}" # Close out the tree else print "" # Close root element fi else for DATA in $CLASS_DATA; do print -- "$DATA" | IFS=: read CLASS LOG CMD MISC if [[ -f $LOG.stderr ]]; then [[ -s $LOG.stderr ]] && cat $LOG.stderr 1>&2 rm -f $LOG.stderr fi done fi fi log_return_msg "$result" "$0()" "$LINENO" return $? } # End of "getHAData()" #============================================================================== # # Name: display_data # # Description: Displays collected data in the requested format. # # Inputs: CLASS The class of data that is provided in the # LOG file (e.g. CLUSTER, VOLUME_GROUP, ...). # # LOG The log file containing any collected data # for the indicated CLASS. # # LAST A Boolean indicator of whether or not this is # the last bit of data being displayed. This is # only used for JSON output. # # Outputs: The formatted data from the provided log file is # displayed on STDOUT. # # Returns: None. # #============================================================================== function display_data { typeset CLASS=$1 typeset LOG=$2 integer LAST=$3 typeset DATA="" [[ -f $LOG ]] && DATA=$(cat $LOG 2>>$CLMGR_TMPLOG) DATA=${DATA##+($NL)} if (( CLMGR_COLON )); then [[ -n $DATA ]] && print -- "$DATA" elif (( CLMGR_XML )) && [[ $CLASS != "CLUSTER" ]]; then if [[ ! -s $LOG || -z $(grep "^<$CLASS>" $LOG) ]]; then print " <$CLASS>" if [[ -n $DATA ]]; then print -- "$DATA" | sed "s/^/ /g" 2>>$CLMGR_TMPLOG fi print " " elif [[ -n $DATA ]]; then print -- "$DATA" | sed "s/^/ /g" 2>>$CLMGR_TMPLOG fi elif (( CLMGR_XML && ! CLMGR_JSON )) && [[ ! -s $LOG || -z $(grep "^<$CLASS>" $LOG) ]] then if (( ! CLMGR_VERBOSE )) then print "<$CLASS>" fi [[ -n $DATA ]] && print -- "$DATA" if (( ! CLMGR_VERBOSE )) then print "" fi elif [[ ! -s $LOG || -z $(grep "^<$CLASS>" $LOG) ]] && (( ! CLMGR_JSON )) then print "<$CLASS>" [[ -n $DATA ]] && print -- "$DATA" print "" elif [[ -n $DATA ]]; then typeset COMMA="" (( CLMGR_JSON && ! LAST )) && COMMA="," print -- "$DATA$COMMA" fi (( ! CLMGR_JSON )) && print } # End of "display_data()" #============================================================================== # # Name: spawn_cmds # # Description: Runs the verbose data retrieval commands for the classes # specified in CMDS_DATA in a backgrounded child process. # # Inputs: CMDS_DATA A space-separated list of data pairs, comprised # of ":". # # GHAD_CHILDREN # A reference to a string variable used to return # the process ID of the backgrounded process, # appended to any existing PIDs already contained # in the variable. # # GHAD_RESULTS_FILE A file to store the command return code in. # # Outputs: The GHAD_CHILDREN variable is updated. # # Returns: None. # #============================================================================== function spawn_cmds { typeset CMDS_DATA=$1 typeset -n GHAD_CHILDREN=$2 typeset GHAD_RESULTS_FILE=$3 ( typeset DATA="" LOG="" CMD="" MISC="" typeset -l CLASS="" typeset -u UC_CLASS="" for DATA in $CMDS_DATA; do print -- "$DATA" | IFS=: read CLASS LOG CMD MISC case $CLASS in *ies) CLASS="${CLASS%ies}y" ;; *s ) CLASS="${CLASS%s}" ;; esac UC_CLASS=$CLASS : Store the STDERR for ${CLASS//_/ }s in $LOG.stderr exec 2>>$LOG.stderr CLMGR_VERBOSE=1 case $CLASS in "physical_volume") MISC="'' ALL" ;; "cluster") CLMGR_VERBOSE=0 MISC="'' $CL_SNAPSHOT" ;; esac export CLMGR_VERBOSE #================================================ # Each process must create its own log file, to # avoid interleaved, unreadable information in # clutils.log. #================================================ export CLMGR_TMPLOG=$GHAD_TEMPDIR/clmgr.KHgca.$CLASS.$$ export CLMGR_ERRLOG=$GHAD_TEMPDIR/clmgr.KHgca.$CLASS.$$ typeset -A props [[ -z $CMD ]] && CMD="KLIB_HACMP_get_${CLASS}_attributes" if [[ $MISC == *+([[:space:]])* ]]; then integer LINE=$LINENO (( LINE += 4 )) eval "\ print \"\\ ### ### $UC_CLASS ### $0()[\$LINE](\$SECONDS):\t$CMD props $MISC\" >>$CLMGR_TMPLOG CL=$LINENO $CMD props $MISC >>$CLMGR_TMPLOG 2>&1 typeset -i cmd_rc=\$? print \"$0()[\$((LINE+2))](\$SECONDS):\t$CMD RC: $cmd_rc\" >>$CLMGR_TMPLOG if (( \$cmd_rc != 0 )); then printf \"\\ ERROR: could not collect %1\\\$s information. To debug further, consider querying this class by itself: clmgr -v query %1\\\$s For more detailed information, consider collecting trace ouput: clmgr -v -l high query %1\\\$s\\n\" \"$CLASS\" >>$CLMGR_TMPLOG dspmsg -s $CLMGR_SET $CLMGR_MSGS 467 \"\\nERROR: could not collect ${CLASS//_/ } information.\\n\" \"${CLASS//_/ }\" 1>&2 fi print -n \$cmd_rc >>$GHAD_RESULTS_FILE" else print "\ ### ### $UC_CLASS ### $0()[$(($LINENO+1))]($SECONDS):\t$CMD props $MISC" >>$CLMGR_TMPLOG CL=$LINENO $CMD props $MISC >>$CLMGR_TMPLOG 2>&1 typeset -i cmd_rc=$? print "$0()[$LINENO]($SECONDS):\t$CMD RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc != 0 )); then cat <>$CLMGR_TMPLOG; ERROR: could not collect $CLASS information. To debug further, consider querying this class by itself: clmgr -v query $CLASS For more detailed information, consider collecting trace ouput: clmgr -v -l high query $CLASS EOCLS dspmsg -s $CLMGR_SET $CLMGR_MSGS 467 "\nERROR: could not collect ${CLASS//_/ } information.\n" "${CLASS//_/ }" 1>&2 fi print -n $cmd_rc >>$GHAD_RESULTS_FILE fi CL=$LINENO SerializeAsAssociativeArray props $CLASS >$LOG unset props if [[ $CLASS == "cluster" ]] && (( CLMGR_XML )); then DATA=$(cat $LOG | grep -v CLUSTERS) print -- "${DATA//^$TAB}" >$LOG fi done )& GHAD_CHILDREN="$GHAD_CHILDREN $!" } # End of "spawn_cmds()" #============================================================================ # # Name: devDoc # # Description: This is a never-to-be-called, wrapper function that all the # clmgr FPATH functions implement in order to hide embedded # syntax from trace logging. This information is implemented # in POD format, and can be viewed in a number of ways using # POD tools. Some viewing suggestions for this function's POD- # formatted information are: # # perldoc # pod2text -c # pod2text -c --code # pod2html # # However, the more important use for this information is that # it is parsed by clmgr to display the syntax for this file's # operation. The information in the "SYNOPSIS" section is used # for this purpose. This feature was originally implemented # using the man page information. However, in a code review it # was pointed out that this approach had to be changed because # customers do not have to install the man pages! Therefore, a # built-in dependency on man page information would break the # automatic help feature of clmgr. So the SYNPOSIS section must # be used instead. # # IMPORTANT: As a result of this, it is imperative that the # information in this SYNOPSIS be kept in sync # with the man page information, which is owned # by the IDD team. # # Inputs: None. # # Outputs: None. # # Returns: n/a (not intended to be invoked) # #============================================================================ function devDoc { : <<'=cut' >/dev/null 2>&1 =head1 NAME KLIB_HACMP_get_cluster_attributes =head1 SYNOPSIS clmgr query cluster [ ALL | {CORE,SECURITY,SPLIT-MERGE,HMC,ROHA,TUNING} ] NOTE: defaults to displaying "ALL" known cluster attributes NOTE: the alias for "cluster" is "cl". =head1 DESCRIPTION Retrieves the configuration data for the locally defined cluster (if any). =head1 ARGUMENTS 1. properties [REQUIRED] [hash ref] An associative array within which data about the cluster can be returned to the caller. 2. is_cl_defined [OPTIONAL] [string] A Boolean-like value indicating if this query is simply attempting to determine if a cluster is defined or not. =head1 RETURN 0: no errors were detected; the operation appears to have been successful 1: a general error has occurred 2: a specified resource does not exist, or could not be found 3: some required input was missing 4: some detected input was incorrect in some way 5: a required dependency does not exist 6: a specified search failed to match any data =cut } # End of "devDoc()" #============================================================================== # The following, comment block attempts to enforce coding standards when this # file is edited via emacs or vim. This block _must_ appear at the very end # of the file, or the editor will not find it, and it will be ignored. #============================================================================== # Local Variables: # indent-tabs-mode: nil # tab-width: 4 # End: #============================================================================== # vim: tabstop=4 shiftwidth=4 expandtab #==============================================================================