#!/bin/ksh93 # ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2018,2019,2020,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # 61haes_r721 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_verify_and_sync.sh 1.14.1.5 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 2006,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 # @(#) 4ca820e 43haes/lib/ksh93/hacmp/KLIB_HACMP_verify_and_sync.sh, 726, 2147A_aha726, Jun 30 2021 06:42 PM #============================================================================ # # Name: KLIB_HACMP_verify_and_sync # # Description: This is the main, FPATH function that is invoked by clmgr # to synchronize the local cluster configuration across all # nodes in the cluster. Unlike the current SMIT path, this # function invokes verification via clver separately, outside # of cldare. That is to allow more controls over the verify # process then what cldare allows when it invokes clver. # # Inputs: Refer to the "devDoc()" function, below. # # Outputs: This function adds no additional output on top of what the # underlying utilities (clver, cldare) emit, with the exception # of error messages due to input validation failures. # # Returns: Zero if no errors are detected. Otherwise, an appropriate # non-zero value is returned. Refer to the "RETURN" section # of the "devDoc()" function, below, for the standard return # code values/meanings for clmgr. # #============================================================================ function KLIB_HACMP_verify_and_sync { . $HALIBROOT/log_entry "$0()" "$CL" : version=@(#) 4ca820e 43haes/lib/ksh93/hacmp/KLIB_HACMP_verify_and_sync.sh, 726, 2147A_aha726, Jun 30 2021 06:42 PM : INPUTS: $* typeset -l sync=${1//\"/} typeset -l force=${2//\"/} typeset -l verify=${3//\"/} shift; shift; shift typeset -l changes=${1//\"/} typeset -l builtin=${2//\"/} typeset methods=${3//\"/} methods=${methods//,/ } typeset -l autocorrect=${4//\"/} typeset -l logging=${5//\"/} typeset logfile=${6//\"/} typeset -i errors=${7//\"/} typeset CMD_OUTPUT="" [[ $CLMGR_LOGGING == 'med' ]] && set +x # Only trace param values #=================================== : Declare and initialize variables #=================================== typeset -i rc=$RC_UNKNOWN typeset NO_FC_PROP_NEEDED="" [[ $sync != @(1|y|t)* ]] && sync=no || sync=yes [[ $force != @(1|y|t)* ]] && force=no || force=yes if [[ $verify != @(0|n|f)* ]] || [[ -z $verify && -n "$*" ]] then verify=yes else verify=no fi [[ $changes != @(1|y|t)* ]] && changes=no || changes=yes [[ $builtin != @(0|n|f)* ]] && builtin=yes || builtin=no [[ $autocorrect == @(1|y|t)* ]] && autocorrect=yes [[ $autocorrect == @(i)* ]] && autocorrect=interactive [[ $autocorrect != @(i|y|1|t)* ]] && autocorrect=no typeset changesOpt= loggingOpt= autocorrectOpt= typeset forceOpt= methodsOpt= logfileOpt= errorsOpt= [[ $changes == "yes" ]] && changesOpt="-V modified" [[ $logging == v* ]] && loggingOpt="-b" [[ $force == "yes" ]] && forceOpt="-i" [[ -n $methods ]] && methodsOpt="-m $methods" [[ $autocorrect == "yes" ]] && autocorrectOpt="-C $autocorrect" [[ $autocorrect == "interactive" ]] && autocorrectOpt="-C $autocorrect" [[ -n $logfile ]] && logfileOpt="-R $logfile" [[ -n $errors ]] && (( errors >= 0 )) && errorsOpt="-e $errors" CL=$LINENO isClusterDefined if (( $? != RC_SUCCESS )); then log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO" return $? else print "$0()[$LINENO]($SECONDS): clmixver" >>$CLMGR_TMPLOG print -n "clmixver: " >>$CLMGR_TMPLOG clmixver >>$CLMGR_TMPLOG 2>&1 integer in_migration=$? print "$0()[$LINENO]($SECONDS): clmixver RC: $in_migration" >>$CLMGR_TMPLOG if (( in_migration == 1 )); then cl_dspmsg scripts.cat 10608 "\ %1\$s: ERROR: an incomplete cluster migration has been detected.\n\ Cluster verification/synchronization cannot be performed until the\n\ migration is completed and all nodes are running the same version\n\ of the product.\n" \ $CLMGR_PROGNAME 1>&2 log_return_msg "$RC_ERROR" "$0()" "$LINENO" return $? fi print "$0()[$LINENO]($SECONDS): cllsclstr -cS" >>$CLMGR_TMPLOG typeset repository="" cname="" CMD_OUTPUT=$(cllsclstr -cS 2>>$CLMGR_TMPLOG) rc=$? print "$0()[$LINENO]($SECONDS): cllsclstr -cS RC: $rc ($CMD_OUTPUT)" >>$CLMGR_TMPLOG if (( rc == 0 )); then print ${CMD_OUTPUT} | cut -f2,5 -d: | tr ':' ' ' | read cname repository fi if [[ $repository == *([[:space:]]) ||\ $repository == "None" ]] then cl_dspmsg -s 27 scripts.cat 1 "\nERROR: Cannot synchronize cluster changes without a cluster repository defined.\n\n" 1>&2 log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO" return $? fi fi #================= : Validate input #================= if [[ $sync == "no" && $verify == "no" ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 131 '\nERROR: the "SYNC" and "VERIFY" options are both set to "no",\n so nothing to do!\n\n' 1>&2 rc=$RC_INCORRECT_INPUT elif [[ -n $errors && $errors != +([[:digit:]]) ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 '\nERROR: the "%1$s" option requires a positive, integer value.\n\n' ERRORS 1>&2 rc=$RC_INCORRECT_INPUT elif [[ -n $logfile ]]; then logfile=${logfile//\\/\/} typeset logdir=$(dirname "$logfile") if [[ $logdir != /* ]]; then if [[ $logdir == */* ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 106 '\nERROR: the specified path/file does not appear to be in absolute format:\n %1$s\n\n' "$logfile" 1>&2 rc=$RC_INCORRECT_INPUT else logfile="/var/hacmp/log/$logfile" logfileOpt="-R $logfile" fi elif [[ ! -d $logdir ]]; then mkdir -p $logdir if [[ ! -d $logdir ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 107 '\nERROR: the specified path/file does not appear to exist on "%2$s": %1$s\n\n' "$logdir" "$LOCAL_NODE" 1>&2 rc=$RC_ERROR fi fi fi #========================================= : Perform the verification, if requested #========================================= if [[ $verify == "yes" ]]; then #===================================================== : Check the node list and see if there are any newly : added nodes that CAA does not know about yet. #===================================================== integer NEW_NODE=0 typeset SITE="" typeset repos_pvid="" typeset repos_disk="" if /usr/lib/cluster/incluster 2>/dev/null then typeset COMMPATH="" IP="" junk="" typeset CAA_IPS=$(LC_ALL=C lscluster -c | grep "Primary IP address for node" | cut -f2 -d:) for COMMPATH in $(clodmget -q "object=COMMUNICATION_PATH" -f value -n HACMPnode) do host $COMMPATH | read junk junk IP junk IP=${IP%,} if [[ " $CAA_IPS " != *+([[:space:]])$IP+([[:space:]])* ]]; then print "$COMMPATH is not known to CAA. It appears to be a new node." >>$CLMGR_TMPLOG NEW_NODE=1 break else print "$COMMPATH is known to CAA. It appears to be an existing node." >>$CLMGR_TMPLOG fi done fi if (( NEW_NODE )); then #===================================================== : Find whether new node is being added with a new site #===================================================== if [[ $(clodmget -f multi_site_lc HACMPcluster) == 1 ]] && (( $(LC_ALL=C lscluster -c 2>/dev/null | grep "Multicast for site" | wc -l) == 1 )) then # We are here, because cluster type is being changed from standard to linked shortnode=$(clodmget -q "object=COMMUNICATION_PATH and value=$COMMPATH" -n -f name HACMPnode 2>/dev/null) SITE=$(LC_ALL=C cllssite -c 2>/dev/null | grep ":$shortnode:" | cut -d: -f1) repos_pvid=$(clodmget -q "name=${SITE}_sircol" -n -f repository HACMPsircol 2>/dev/null) # For chcluster, we need disk name; get it from clvg_config which was created at add_node phase [[ -n $repos_pvid ]] && repos_disk=$(LC_ALL=C grep -w $repos_pvid /usr/es/sbin/cluster/etc/config/clvg_config | cut -d: -f2) print "Extracted values: $shortnode:$SITE:$repos_pvid:$repos_disk:" >> $CLMGR_TMPLOG fi #============================================== : Temporarily add the node to the CAA cluster : so that the verification can succeed. #============================================== CL=$LINENO add_caa_access $COMMPATH $SITE $repos_disk (( $? != RC_SUCCESS )) && rc=$RC_ERROR fi if (( rc == RC_UNKNOWN || rc == RC_SUCCESS )); then if [[ $sync == "yes" ]]; then #========================================================= : Perform the same test that cldare does, to ensure that : verify will pass if there are unpropagated files. #========================================================= if [[ -n $(odmget -q "prop_sync=1" HACMPfilecollection) ]]; then clfileprop -s rc=$? print #====================================================== : If the propagation was successful, tell cldare that : it does not need to do the propagation again. #====================================================== (( $rc == RC_SUCCESS )) && NO_FC_PROP_NEEDED="-F" fi fi if [[ $autocorrectOpt == *interactive* ]] then # # The clver interactive mode displays its prompts on STDERR. # However, clmgr auto-captures all STDERR traffic in an FFDC # (First Failure Data Capture) file so the prompts are written # there instead of being shown on the terminal as needed. # Therefore, for this one special case, the FFDC capture needs # to be temporarily suspended to allow clver to run # interactively. Once clver completes, FFDC will be restored. # exec 2>&4 # Save a copy of the original STDERR file descriptor fi print "$0()[$LINENO]($SECONDS): $HADIAG/clver -rt $loggingOpt $changesOpt $autocorrectOpt $errorsOpt $logfileOpt $methodsOpt" >>$CLMGR_TMPLOG # Always log commands VERBOSE_LOGGING="" $HADIAG/clver -rt $loggingOpt $changesOpt $autocorrectOpt $errorsOpt $logfileOpt $methodsOpt rc=$? print "$0()[$LINENO]($SECONDS): clver RC: $rc" >>$CLMGR_TMPLOG # Always log command result if [[ $autocorrectOpt == *interactive* ]] then # Restore the First Failure Data Capture (FFDC) exec 2>>$CLMGR_ERRLOG fi fi if (( NEW_NODE )); then #======================================================== : Remove the node from the CAA cluster. If the customer : is also doing a sync, the node will be added to the : CAA cluster permanently by cldare. #======================================================== CL=$LINENO rm_caa_access $COMMPATH $SITE (( $? != RC_SUCCESS )) && rc=$RC_ERROR fi fi #============================================ : Perform the synchronization, if requested #============================================ if [[ $sync == "yes" ]]; then if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) || [[ $force == y* ]]; then print "$0()[$LINENO]($SECONDS): cldare -rtv $forceOpt $loggingOpt $changesOpt $NO_FC_PROP_NEEDED" >>$CLMGR_TMPLOG # Always log commands export CLMGR_TMPLOG # Used inside cldare for logging VERBOSE_LOGGING="" cldare -rtv $forceOpt $loggingOpt $changesOpt $NO_FC_PROP_NEEDED rc=$? print "$0()[$LINENO]($SECONDS): cldare RC: $rc" >>$CLMGR_TMPLOG # Always log command result (( $rc != RC_SUCCESS )) && rc=$RC_ERROR fi #==================================================================== : Make *sure* that the cluster agrees that it has been synchronized #==================================================================== if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then print "$0()[$LINENO]($SECONDS): $HAUTILS/clodmget -f handle HACMPcluster)" >>$CLMGR_TMPLOG # Always log commands typeset UNSYNCED=$($HAUTILS/clodmget -f handle HACMPcluster) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; UNSYNCED == \"$UNSYNCED\"" >>$CLMGR_TMPLOG # Always log command result (( UNSYNCED == 0 )) && rc=$RC_ERROR else rc=$RC_ERROR fi #=============================================== : Make *sure* that the CAA cluster was created #=============================================== if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then print "$0()[$LINENO]($SECONDS): lscluster -c" >>$CLMGR_TMPLOG lscluster -c >>$CLMGR_TMPLOG 2>&1 typeset -i CAA_CL=$? print "$0()[$LINENO]($SECONDS): lscluster RC: $CAA_CL" >>$CLMGR_TMPLOG if (( $CAA_CL != RC_SUCCESS )); then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 259 '\nERROR: failed to create the CAA cluster.\n' 2>&1 rc=$RC_ERROR fi fi fi #=============================================================== : Update the clevents file with formatted event, but only if this : was a verify-only operation. The "sync" operation uses cldare, : which logs its own events. Send an event upstream to the GUI : server, if the node has a running GUI agent on it. #=============================================================== if [[ $sync != "yes" ]]; then if (( $rc == RC_SUCCESS )); then cl_send_ui_event NODE "$LOCAL_NODE" VERIFY PASSED PASSED "A cluster configuration verification operation PASSED on node \"$LOCAL_NODE\". Detailed output can be found in \"${LOGDIR}clverify.log\" on that node." else cl_send_ui_event NODE "$LOCAL_NODE" VERIFY FAILED FAILED "A cluster configuration verification operation FAILED on node \"$LOCAL_NODE\". Detailed output can be found in \"${LOGDIR}clverify.log\" on that node." fi fi log_return_msg "$rc" "$0()" "$LINENO" return $? } # End of "KLIB_HACMP_verify_and_sync()" #============================================================================ # # 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_verify_and_sync =head1 SYNOPSIS_VERIFY clmgr verify cluster [ CHANGES_ONLY={no|yes} ] \ [ DEFAULT_TESTS={yes|no} ] \ [ METHODS=[,,...] ] \ [ FIX={no|yes} ] \ [ LOGGING={standard|verbose} ] \ [ LOGFILE= ] \ [ MAX_ERRORS=## ] [ SYNC={no|yes} ] \ [ FORCE={no|yes} ] NOTE: the "FORCE" option should only be used when "SYNC" is set to "yes". =head1 SYNOPSIS_SYNC clmgr sync cluster [ FORCE={no|yes} ] \ [ VERIFY={yes|no} ] \ [ CHANGES_ONLY={no|yes} ] \ [ DEFAULT_TESTS={yes|no} ] \ [ METHODS=[,,...] ] \ [ FIX={no|yes} ] \ [ LOGGING={standard|verbose} ] \ [ LOGFILE= ] \ [ MAX_ERRORS=## ] NOTE: all options other than "FORCE" should only be used when "VERIFY" is set to "yes". =head1 DESCRIPTION Run verification and/or synchronization according to the provided specifications, or using defaults. =head1 ARGUMENTS 1. sync [OPTIONAL] [string] A Boolean-like indicator of whether or not to attempt a cluster synchronization. DEFAULT: no 2. force [OPTIONAL] [string] A Boolean-like indicator of whether or not to force a cluster synchronization attempt to occur, even if verification errors are encountered. DEFAULT: no 3. verify [OPTIONAL] [string] A Boolean-like indicator of whether or not to perform a verification on the cluster configuration. This option can actually be implied by the setting of the other options, described below. DEFAULT: yes 4. changes [OPTIONAL] [string] A Boolean-like indicator of whether or not to perform only those verification tests that apply to the changes that have been made, versus performing all the available tests. DEFAULT: no (runs all available tests) 5. builtin [OPTIONAL] [string] A Boolean-like indicator of whether or not to run all the available, builtin verification tests. DEFAULT: yes 6. methods [OPTIONAL] [string] A list of verification method labels, indicating that those methods should be run as part of the verification. 7. autocorrect [OPTIONAL] [string] A Boolean-like indicator of whether or not to attempt to automatically correct certain errors found during verification. 8. logging [OPTIONAL] [string] The logging level to use, standard versus verbose. DEFAULT: standard 9. logfile [OPTIONAL] [string] A file to write all standard output from the operation into. If the file already exists, it will be appended to. If the directory path that is specified does not exist, it will be created. 10. errors [OPTIONAL] [integer] The maximum number of errors to allow before aborting the operation. =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 #==============================================================================