#!/bin/ksh93 # ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2017,2019,2020,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # # @(#) 03a409f 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_cluster.sh, 726, 2147A_aha726, May 19 2021 03:11 PM #====================================================================== #If signature of properties for modify cluster need to be changed,make #sure that same changes are done in KLIB_HACMP_add_cluster, #resource_modify. #====================================================================== #============================================================================ # # 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_modify_cluster =head1 SYNOPSIS clmgr modify cluster \ [ NAME= ] \ [ NODES=[,,...] ] \ [ TYPE={NSC|SC} ] \ [ HEARTBEAT_TYPE={unicast|multicast} ] \ [ CLUSTER_IP= ] \ [ REPOSITORIES=[,,...] ] \ [ FC_SYNC_INTERVAL=## ] \ [ RG_SETTLING_TIME=## ] \ [ MAX_EVENT_TIME=### ] \ [ MAX_RG_PROCESSING_TIME=### ] \ [ DAILY_VERIFICATION={Enabled|Disabled} ] \ [ VERIFICATION_NODE={Default|} ] \ [ VERIFICATION_HOUR=<00..23> ] \ [ VERIFICATION_DEBUGGING={Enabled|Disabled} ] \ [ HEARTBEAT_FREQUENCY= ] \ [ GRACE_PERIOD= ] \ [ SITE_POLICY_FAILURE_ACTION={fallover|notify} ] \ [ SITE_POLICY_NOTIFY_METHOD="" ] [ SITE_HEARTBEAT_CYCLE= ] \ [ SITE_GRACE_PERIOD=### ] \ [ TEMP_HOSTNAME={disallow|allow} ] \ [ LPM_POLICY={manage|unmanage} ] \ [ HEARTBEAT_FREQUENCY_DURING_LPM=### ] \ [ NETWORK_FAILURE_DETECTION_TIME=<0,5...590> ] \ [ CAA_AUTO_START_DR={Enabled|Disabled} ] \ [ CAA_REPOS_MODE={assert|event} ] \ [ CAA_CONFIG_TIMEOUT=<0..2147483647> ] \ [ LVM_PREFERRED_READ= ] \ [ CRIT_DAEMON_RESTART_GRACE_PERIOD=<0..240> ] \ [ SKIP_EVENT_PROCESSING_MANAGE_MODE={true|false} ] clmgr modify cluster \ [ NAME= ] \ [ NODES=[,,...] ] \ [ TYPE="LC" ] \ [ HEARTBEAT_TYPE={unicast|multicast} ] \ [ FC_SYNC_INTERVAL=## ] \ [ RG_SETTLING_TIME=## ] \ [ MAX_EVENT_TIME=### ] \ [ MAX_RG_PROCESSING_TIME=### ] \ [ DAILY_VERIFICATION={Enabled|Disabled} ] \ [ VERIFICATION_NODE={Default|} ] \ [ VERIFICATION_HOUR=<00..23> ] \ [ VERIFICATION_DEBUGGING={Enabled|Disabled} ] \ [ HEARTBEAT_FREQUENCY= ] \ [ GRACE_PERIOD= ] \ [ SITE_POLICY_FAILURE_ACTION={fallover|notify} ] \ [ SITE_POLICY_NOTIFY_METHOD="" ] [ SITE_HEARTBEAT_CYCLE= ] \ [ SITE_GRACE_PERIOD=### ] \ [ TEMP_HOSTNAME={disallow|allow} ] \ [ LPM_POLICY={manage|unmanage} ] \ [ HEARTBEAT_FREQUENCY_DURING_LPM=### ] \ [ NETWORK_FAILURE_DETECTION_TIME=<0,5...590> ] \ [ CAA_REPOS_MODE={assert|event} ] \ [ CAA_CONFIG_TIMEOUT=<0..2147483647> ] \ [ LVM_PREFERRED_READ= ] \ [ CRIT_DAEMON_RESTART_GRACE_PERIOD=<0..240> ] \ [ SKIP_EVENT_PROCESSING_MANAGE_MODE={true|false} ] NOTE: "NSC": "Non-Site Cluster"; no sites will be defined. "SC": "Stretched Cluster"; simplified infrastructure, ideal for limited distance data replication. Sites *must* be defined. "LC": "Linked Cluster"; full-featured infrastructure, ideal for long distance data replication. Sites *must* be defined. NOTE: the cluster name cannot be modified once the cluster is fully defined and synchronized. NOTE: the cluster type cannot be modified once the cluster is fully defined and synchronized if sites are already in use. NOTE: "CLUSTER_IP" may only be used with a cluster type of "NSC" or "SC". NOTE: "REPOSITORIES" may only be used with a cluster type of "NSC" or "SC". No more than MAX_NB_OF_BACKUP_REPOSITORIES backup repository disks may be defined per "NSC" or "SC" cluster. NOTE: the "RG_SETTLING_TIME" attribute only affects resource groups with a startup policy of "Online On First Available Node". : Split-merge support for linked clusters only clmgr modify cluster \ [ SPLIT_POLICY={none|tiebreaker|manual|NFS|Cloud} ] \ [ TIEBREAKER= ] \ [ CLOUD_SERVICE={ibm|aws} ] \ [ BUCKET_NAME={} ] \ [ USE_EXISTING_BUCKET={yes|no} ] \ [ MERGE_POLICY={none|majority|tiebreaker|manual|NFS|Cloud} ] \ [ NFS_QUORUM_SERVER= ] \ [ LOCAL_QUORUM_DIRECTORY=] \ [ REMOTE_QUORUM_DIRECTORY=] \ [ QUARANTINE_POLICY=] \ [ CRITICAL_RG= ] \ [ NOTIFY_METHOD= ] \ [ NOTIFY_INTERVAL=### ] \ [ MAXIMUM_NOTIFICATIONS=### ] \ [ DEFAULT_SURVIVING_SITE= ] \ [ APPLY_TO_PPRC_TAKEOVER={yes|no} ] \ [ ACTION_PLAN={reboot|disable_rgs_autostart|disable_cluster_services_autostart} ] NOTE: the alias for "cluster" is "cl". =head1 DESCRIPTION Attempts to modify the cluster configuration to conform to the provided specifications. =head1 ARGUMENTS 1. properties [REQUIRED] [hash ref] An associative array within which data about the modified object can be returned to the caller. 2. new_name [OPTIONAL] [string] The new label to attempt to apply to the cluster. 3. fc_sync_interval [OPTIONAL] [integer] A new file collection propagation interval to apply to the cluster. 4. rg_settling_time [OPTIONAL] [integer] A new resource group settling time to apply to the cluster. 5. rg_dist_policy [OPTIONAL] [set] A new resource group distribution policy to apply to the cluster, from the set {node|network}. 6. max_event_time [OPTIONAL] [integer] The maximum number of seconds to allot for an event to complete its processing. If this limit is exceeded, a CONFIG_TOO_LONG error will occur. 7. max_rg_processing_time [OPTIONAL] [integer] The maximum number of seconds to allot for a resource group-related event to complete its processing (this value is added to the max_event_time to arrive at the total time limit). If this limit is exceeded, a CONFIG_TOO_LONG error will occur. 8. faction [OPTIONAL] [set] A new site policy failure action to apply to the cluster (if sites are configured within the cluster), from the set {fallover|notify}. 9. nmethod [OPTIONAL] [string] A new site policy notify method to use within the cluster (if sites are configured within the cluster). 10. autover [OPTIONAL] [string] A Boolean-like toggle to indicate if automatic, daily verification should be performed. 11. autover_node [OPTIONAL] [string] An indicator of which node to initiate the automatic verification on. 12. autover_hour [OPTIONAL] [string] The hour when the automatic verification should be launched. 13. autover_debug [OPTIONAL] [string] A Boolean-like toggle to indicate if the automatic verification should be run with debugging enabled. 14. repositories [OPTIONAL] [string] One or more disks that will be added as repository disks within the cluster. First disk is the active repository, and following ones are backup repositories. Nor more than MAX_NB_OF_BACKUP_REPOSITORIES backup repositories are accepted. If a CAA cluster is detected, then the disks will be treated as backup repositories. 15. cluster_ip [OPTIONAL] [string] A multicast IP address that will be used for CAA communications within the cluster. 16. heartbeat [OPTIONAL] [posint] This attribute controls the frequency with which the node heartbeats across the various enabled heart beating sources. It is stated in terms of the number of milliseconds that another node may consider node X to be DOWN if it receives no incoming heartbeats from node X. CAA uses this attribute to control the frequency of Gossip Packets, the aggregated heartbeat message sent by gateway servers in linked clusters as well as the interval based heartbeat algorithms that tick over SAN and DISK. The default value is 20. The valid range differs depending on AIX version. Hence the value is directly taken from AIX. 17. node_down_delay [OPTIONAL] [posint] This attribute controls the behavior of the node monitor which periodically evaluates the set of activated heart beating sources to determine whether a node is UP or DOWN. This attribute specifies the amount of time in milliseconds that the node monitor must wait after it makes the determination that another node is DOWN before posting it as DOWN. The default value is 10. The valid range differs depending on AIX version. Hence the value is directly taken from AIX. 18. site_heartbeat_cycle [OPTIONAL] [posint] The remote_HB_factor defines how infrequently CAA would be periodically unreliable message to remote site. This factor is a scaling factor, it would be set to 10 by default with a range of 1 to 100. This means a periodic message would be sent to the remote site once for every 10 same type of message sent locally. 19. site_grace_period [OPTIONAL] [posint] This refers to link_timeout in CAA design. This attribute is applied as a delta to the node timeout for nodes that are in remote sites. That is, the node monitor will wait "node_timeout + link_timeout" seconds before determining that a remote node is DOWN. Then, it will wait an additional node_down_delay seconds before posting that the remote node is DOWN. 20. type [OPTIONAL] [set] "NSC": "Non-Site Cluster"; no sites will be defined. "SC": "Stretched Cluster"; simplified infrastructure, ideal for limited distance data replication. Sites *must* be defined. "LC": "Linked Cluster"; full-featured infrastructure, ideal for long distance data replication. Sites *must* be defined. NOTE: the cluster type cannot be modified once the cluster is fully defined and synchronized if sites are already in use. 21. heartbeat_type [OPTIONAL] [set] This determines whether CAA will use unicast or multicast heartbeat on the cluster. If unicast is chosen, then the cluster IP address is not used. Valid values: unicast, multicast 22. temp_hostname Toggles the honorTempHostNameChanges setting in HACMPcluster, indicating if temporary hostname changes (i.e. via the "hostname" command) should be allowed. ====================== Split-Merge Inputs ====================== 23. split_policy [OPTIONAL] [set] The split handling policy specifies the response when a split has been detected in a cluster. A choice of "None" takes no action; the other choices select a mechanism to identify which portion of the cluster will continue. Valid values include: none, tiebreaker, manual Defaults to "none". 24. merge_policy The merge handling policy specifies the mechanism to identify which part of a split cluster will continue after the merge. Valid values include: majority, none, tiebreaker, nfs, manual Defaults to "majority". 25. quaratine_policy Cluster wide Quarantine policy informs PowerHA SystemMirror about the method it should use to isolate a unresponsive node that was hosting the Critical Resource Group previously. 26. critical_rg A Resource Group for which the selected Quarantine Policy would be applicable. All the resources assosciated with this Resource Group would be handled by the Quarantine Policy that was configured. 27. action_plan The action plan describes the action taken on the nodes in the portion of a cluster that has split, or has merged after a split, and which has not been selected to continue. Valid values include: reboot,disable_rgs_autostart,disable_cluster_services_autostart 1.reboot - Nodes on the loosing partition will be rebooted. 2.disable_rgs_autostart - Nodes on the loosing partition will be rebooted, the Resource Groups can not be brought online until merge is finished. 3. disable_cluster_services_autostart - Nodes on the loosing partition will be rebooted, manual intervention is needed to bring the cluster back to stable state. Defaults to "Disable_cluster_services_autostart". Defaults to "Reboot" for AIX level less than 7210. 28. tiebreaker [OPTIONAL] [set] In the event of a split or merge for which the "tiebreaker" policy is selected, the portion of the cluster that can first access the tie breaker disk will continue. Select the "None" option to have the tie breaker specification removed. If a tie breaker is selected, but neither split nor merge policy uses as tie breaker, the specification is accepted, but unused. Once a disk has been specified to be a tie breaker, it is not available for use in a volume group, or for any other purpose. 29. nfs_quorum_server The hostname of the used NFSv4 server. Enter the Fully Qualified Domain Name. Example : NodeA.in.ibm.com. 30. local_quorum_directory Enter the Absolute Path of the Local node directory, which is use by the NFS TieBreaker Server as a Local Mount Point. 31. remote_quorum_directory Enter the Absolute Path of the NFS TieBreaker Server directory, which is exported by the nfsQuorumServer. 32. notify_method A script to run that will notify whomever needs to know that the cluster has been split. 33. notify_interval The amount of time to wait before running the notify method again. If maximum notifications is set to one, then this input is not used. 34. maximum_notifications The maximum number of times to run the notify method before giving up. 35. typeset default_surviving_site The site that is to be given preferential treatment when a winner when the merge policy is set to "priority". This user- provided input indicates which site survives. 36. apply_to_pprc_takeover 37. nodes [OPTIONAL] [string] A full-membership node list for the cluster. Must contain the local node. 38. lpm_policy [OPTIONAL] [set] The LPM policy specifies the action to be taken on the node during a Live Partition Mobility operation. If "unmanage" is selected, the cluster services are stopped with the 'Unmanage Resource Groups' option during the duration of the LPM operation. Otherwise PowerHA SystemMirror will continue to monitor the resource group(s) and application availablity. Valid values include: manage, unmanage Defaults to "manage". 39. lpm_heartbeat [OPTIONAL] [posint] This attribute supersedes the value of the heartbeat attribute during the time of a Live Partition Mobility processing. Default value is 600 and range is 10-600. Unit is second. 40. Node Failure Detection Time This attribute determines the amount of time CAA would wait to give a network failure notification.It is stated in terms of milliseconds.The default value is 10.The valid range differs depending on AIX version. Hence the value is directly taken from AIX. 41. caa_auto_start_dr [OPTIONAL] [string] Sets a CAA tunable to enable/disable PVID based identification of repository disk(s) during disaster recovery. 42. caa_repos_mode [OPTIONAL] [string] This attribute controls node behavior when cluster repository access is lost. Default value is "event" and valid values are assert and event. 43. caa_config_timeout [OPTIONAL] [integer] This attribute controls the timeout for coordinated configuration changes. Default value is 240 and range is 0-2147483647. Unit is second. 44. lvm_preferred_read [OPTIONAL] [string] This attribute controls LVM read operations when there are mirror pools. This option decides which copy should be used for reading the data. Supported options are roundrobin, favorcopy or siteaffinity. favorcopy - Choose if you would like to read from Flash storage. siteaffinity - Choose if you would like to read from local storage path always based on the resource group location. siteaffinity option is available only for site based clusters. 45. crit_daemon_restart_grace_period [OPTIONAL] [integer] Sets the RSCT resource attribute IBM.PeerNode.CritDaemonRestartGracePeriod for tuning the response to loss of critical daemons in heavily loaded systems. Value is in seconds and the recommended value is less than 120 seconds. Default value is 0 and range is 0-240. 46. skip_events_on_manage [OPTIONAL] [boolean] Set this flag to true to skip any event processing when cluster services are started after stopping with the unmanaged option. 47. bucket_name [OPTIONAL] [string] Provide bucket_name when split merge policy is configured as Cloud-Cloud. During split and merge scenario, PowerHA tries to upload the Cloud tiebreaker file in to provided bucket. 48. cloud_service [OPTIONAL] [string] Provide cloud_service when split merge policy is configured as Cloud-Cloud. This is the cloud service provider. It can be either ibm or aws. 49. use_existing_bucket [OPTIONAL] [boolean] Provide this option when split merge policy is configured as Cloud-Cloud. Supported values are yes or no. If this is set to yes, then the cloud tiebreaker file will upload to existing bucket which is provided. If this is set to no, then new bucket name will be created with the provided bucket name. =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 POD-formatted documentation. #============================================================================== # # Name: list_tie_breaker_disks # # Description: Borrows the logic (and a great deal of code!) from the SMIT # panel "command to list" for the Tie Breaker pick list. Lists # all potential tie breaker disks on STDOUT. # # Inputs: None. # # Outputs: All potential tie breaker disks are displayed on STDOUT in # the following format: # # hdisk0 (00caed8c11314304) on node r8r4m11 at site austin # # Returns: Zero if the disks (if any) were listed successfully. # Otherwise a non-zero value is returned. # #============================================================================== function list_tie_breaker_disks { . $HALIBROOT/log_entry "$0()" "$CL" typeset -i rc=$RC_UNKNOWN # : Check for hyperswap present in the environment # typeset hs_check="" if whence lspprc > /dev/null 2>&1 then hs_check=TRUE fi # : List free disks that can function as a repository # typeset nodelist=$(clnodename) typeset last_good_disk="" LC_ALL=C cllspvids -P $nodelist >$TMPDIR/clmgr.KHmc.ltbd.$$ rc=$? (( rc != RC_SUCCESS )) && rm -f $TMPDIR/clmgr.KHmc.ltbd.$$ while read line; do # : For each line from cllspvids, pick up the PVID # typeset pvid="" print "$line" | read skip pvid skip pvid=${pvid#\(} pvid=${pvid%\)} # : Get the local disk name. : Display a line if its the same disk as a previously displayed disk, : or its a new disk that supports a reserve policy of PR_exclusive # if [[ $last_good_disk == $pvid ]] then print -- "\t$line" # same disk, different name else typeset local_hdisk_name=$(clodmget -q "attribute = pvid and value like ${pvid}*" -f name -n CuAt) if [[ -n $hs_check ]] && lspprc -p $local_hdisk_name >/dev/null 2>&1 then # : Skip hyperswap enabled disks # continue elif LC_ALL=C lsattr -R -l $local_hdisk_name -a reserve_policy | grep -qw PR_exclusive then # : Only if this device supports a reserve_policy : of PR_exclusive is it displayed # print -- "\t$line" last_good_disk=$pvid fi fi done <$TMPDIR/clmgr.KHmc.ltbd.$$ rm -f $TMPDIR/clmgr.KHmc.ltbd.$$ log_return_msg "$rc" "$0()" "$LINENO" return $? } # End of "list_tie_breaker_disks()" #============================================================================== # # Name: handle_split_merge # # Description: If any split-merge manipulations are requested, this # function is invoked to handle them. It attempts to # perform any input validations the the "cl_sm" does # not (because SMIT does it automatically). # # Inputs: split_policy One of {none|tiebreaker|nfs|manual}. # merge_policy One of {none|majority|manual|tiebreaker|nfs}. # action_plan One of {reboot|disable_rgs_autostart|disable_cluster_services_autostart}. # nfs_quorum_server hostname of the used NFSv4 server # local_quorum_directory Absolute Path of the Local node directory # remote_quorum_directory Absolute Path of the NFS TieBreaker Server # directory # quarantine_policy Cluster wide Quarantine policy # critical_rg Resource Group for which the selected Quarantine # Policy would be applicable. # tiebreaker An available disk shared by all nodes in the # cluster. # notify_method An executable to invoke when a split occurs, # ostensibly to notify one or more admins that # something very bad has happened. # notify_interval Number of seconds between each repeated # invocation of the notify method. # maximum_notifications Maximum number of times to invoke the # notify method before going silent. # default_surviving_site The default surviving site. # apply_to_pprc_takeover One of {yes|no}. # bucket_name Cloud bucket to which the cloud tie breaker file # should upload. # cloud_service Cloud service provider name # use_existing_bucket if yes, use provided bucket # if no, create a new bucket with bucket_name # # Outputs: Any errors are written to STDERR. Otherwise, cl_sm displays # results of the operation on STDOUT. # # Returns: Zero if operation succeeded; non-zero otherwise. # #============================================================================== function handle_split_merge { . $HALIBROOT/log_entry "$0()" "$CL" typeset split_policy=$1 typeset merge_policy=$2 typeset nfs_quorum_server=$3 typeset local_quorum_directory=$4 typeset remote_quorum_directory=$5 typeset quarantine_policy=$6 typeset critical_rg=$7 typeset action_plan=$8 typeset tiebreaker=$9 typeset notify_method=${10} typeset notify_interval=${11} typeset maximum_notifications=${12} typeset default_surviving_site=${13} typeset apply_to_pprc_takeover=${14} typeset bucket_name=${15} typeset cloud_service=${16} typeset use_existing_bucket=${17} typeset -i rc=$RC_UNKNOWN cmd_rc=$RC_UNKNOWN if [[ $split_policy != *([[:space:]]) ]]; then CL=$LINENO verify_in_set SPLIT_POLICY "$split_policy" "None, TieBreaker, Manual, NFS, Cloud" split_policy (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ $merge_policy != *([[:space:]]) ]]; then CL=$LINENO verify_in_set MERGE_POLICY "$merge_policy" "None, Majority, Manual, TieBreaker, NFS, Cloud" merge_policy (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ $action_plan != *([[:space:]]) ]]; then CL=$LINENO verify_in_set ACTION_PLAN "$action_plan" "Reboot,Disable_rgs_autostart,Disable_cluster_services_autostart" action_plan (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ $tiebreaker != *([[:space:]]) ]]; then if [[ $split_policy != "TieBreaker" || $merge_policy != "TieBreaker" ]]; then /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 1447 "\nERROR: TieBreaker disk option is supported only for split policy 'TieBreaker' and merge policy 'TieBreaker'.\n\n" 1>&2 rc=$RC_INCORRECT_INPUT else if [[ $tiebreaker == *\(* ]]; then # The tie breaker is in "" format typeset PVID=${tiebreaker##*\(} PVID=${PVID%%\)*} if [[ -n $PVID ]] && \ lspv | grep -qw $PVID then tiebreaker=$PVID fi unset PVID fi #================================================= : Get the list of all possible tie breaker disks #================================================= typeset TIEBREAKERS=$(list_tie_breaker_disks | grep -we $LOCAL_NODE -e "on all nodes" -e "on all cluster nodes") typeset IDENTIFIERS="" CL=$LINENO KLIB_HACMP_is_known_physical_volume "$tiebreaker" "$LOCAL_NODE" IDENTIFIERS if (( $? != RC_SUCCESS )) || [[ -z $IDENTIFIERS ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 '\nERROR: "%1$s" does not appear to exist!\n\n' "$tiebreaker" 1>&2 rc=$RC_NOT_FOUND else typeset -i FOUND=0 typeset NODE="" DISK_LABEL="" DISK_PVID="" DISK_UUID="" REST="" print -- "$IDENTIFIERS" |\ IFS=: read NODE DISK_LABEL DISK_PVID DISK_UUID REST typeset LINE="" print -- "$TIEBREAKERS" |\ while read LINE; do print -- "$LINE" | read TB_NAME TB_PVID REST if [[ $DISK_PVID == ${TB_PVID//[\(\)]/} ]]; then tiebreaker="${TB_PVID//[\(\)]/}" FOUND=1 break fi done if (( ! FOUND )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 434 '\nERROR: "%1$s" appears to be unavailable.\n\n' "$tiebreaker" 1>&2 rc=$RC_INCORRECT_INPUT fi fi if (( rc != RC_UNKNOWN )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 153 "Available Physical Volumes:\n\n" 1>&2 print -u2 -- "$TIEBREAKERS\n" fi fi fi if [[ -n $notify_interval ]]; then CL=$LINENO verify_is_numeric "$notify_interval" 2 "NOTIFY_INTERVAL" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $maximum_notifications ]]; then CL=$LINENO verify_is_numeric "$maximum_notifications" 2 "MAXIMUM_NOTIFICATIONS" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $default_surviving_site ]]; then CL=$LINENO KLIB_HACMP_is_known_site "$default_surviving_site" >/dev/null cmd_rc=$? if (( cmd_rc != RC_SUCCESS )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 '\nERROR: "%1$s" does not appear to exist!\n\n' "$default_surviving_site" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 157 "Available Sites:\n\n" 1>&2 typeset available CL=$LINENO KLIB_HACMP_list_sites available for (( i=0; i<${#available[*]}; i++ )); do if [[ ${available[$i]} != *([[:space:]]) ]]; then print -u2 "\t${available[$i]}" fi done print -u2 "" rc=$RC_NOT_FOUND fi fi if [[ -n $apply_to_pprc_takeover ]]; then CL=$LINENO verify_in_set APPLY_TO_PPRC_TAKEOVER "$apply_to_pprc_takeover" "Yes, No" apply_to_pprc_takeover (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $quarantine_policy ]];then CL=$LINENO verify_in_set QUARANTINE_POLICY "$quarantine_policy" "disable, node_halt, fencing , halt_with_fencing" quarantine_policy (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $cloud_service ]];then CL=$LINENO verify_in_set CLOUD_SERVICE "$cloud_service" "ibm,aws" cloud_service (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $use_existing_bucket ]];then CL=$LINENO verify_in_set USE_EXISTING_BUCKET "$use_existing_bucket" "yes,no" use_existing_bucket (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi typeset anhp="" scsi="" disable_policy="" if [[ -n $quarantine_policy ]];then if [[ $quarantine_policy == "node_halt" ]];then anhp="Yes" scsi="No" elif [[ $quarantine_policy == "fencing" ]];then scsi="Yes" anhp="No" elif [[ $quarantine_policy == "halt_with_fencing" ]];then anhp="Yes" scsi="Yes" elif [[ $quarantine_policy == "disable" ]];then disable_policy="Yes" fi fi if (( rc == RC_UNKNOWN )); then #================================================================ : No obvious input errors were detected. Attempt the operation. #================================================================ typeset aOpt="" iOpt="" mOpt="" nOpt="" sOpt="" typeset tOpt="" vOpt="" wOpt="" xOpt="" rOpt="" typeset kOpt="" gOpt="" pOpt="" bOpt="" dOpt="" typeset eOpt="" NOpt="" BOpt="" COpt="" uOpt="" [[ -n $merge_policy ]] && mOpt=" -m $merge_policy" [[ -n $split_policy ]] && sOpt=" -s $split_policy" [[ -n $nfs_quorum_server ]] && kOpt=" -k $nfs_quorum_server" [[ -n $local_quorum_directory ]] && gOpt=" -g $local_quorum_directory" [[ -n $remote_quorum_directory ]] && pOpt=" -p $remote_quorum_directory" [[ -n $anhp ]] && eOpt=" -e $anhp" [[ -n $scsi ]] && dOpt=" -d $scsi" [[ -n $critical_rg ]] && bOpt=" -b $critical_rg" [[ -n $action_plan ]] && aOpt=" -a $action_plan" [[ -n $tiebreaker ]] && tOpt=" -t $tiebreaker" [[ -n $notify_method ]] && nOpt=" -n $notify_method" [[ -n $notify_interval ]] && iOpt=" -i $notify_interval" [[ -n $maximum_notifications ]] && xOpt=" -x $maximum_notifications" [[ -n $default_surviving_site ]] && vOpt=" -v $default_surviving_site" [[ -n $apply_to_pprc_takeover ]] && rOpt=" -r $apply_to_pprc_takeover" [[ -n $disable_policy ]] && NOpt=" -N" [[ -n $bucket_name ]] && BOpt=" -B $bucket_name" [[ -n $cloud_service ]] && COpt=" -C $cloud_service" [[ -n $use_existing_bucket ]] && uOpt=" -u $use_existing_bucket" print -- "$0()[$LINENO]($SECONDS): cl_sm $wOpt$sOpt$mOpt$kOpt$gOpt$pOpt$eOpt$dOpt$bOpt$aOpt$tOpt$nOpt$iOpt$xOpt$vOpt$rOpt$NOpt$BOpt$COpt$uOpt" >>$CLMGR_TMPLOG cl_sm $wOpt$sOpt$mOpt$kOpt$gOpt$pOpt$eOpt$dOpt$bOpt$aOpt$tOpt$nOpt$iOpt$xOpt$vOpt$rOpt$NOpt$BOpt$COpt$uOpt rc=$? (( $rc == 255 )) && rc=1 print -- "$0()[$LINENO]($SECONDS): cl_sm RC: $rc" >>$CLMGR_TMPLOG fi log_return_msg "$rc" "$0()" "$LINENO" return $? } # End of "handle_split_merge()" #============================================================================ # # Name: KLIB_HACMP_modify_cluster # # Description: This is the main, FPATH function that is invoked by clmgr # to modify a cluster's properties. # # Inputs: Too many to list! Please refer to the detailed listing, and # associated descriptions, in the "ARGUMENTS" section of the # "devDoc()" function, above. # # Outputs: The properties hash is populated. The only other outputs are # any error messages that might be needed. # # Returns: Zero if no errors are detected. Otherwise, an appropriate # non-zero value is returned. Refer to the "RETURN" section # of the "devDoc()" function, above, for the standard return\ # code values/meanings for clmgr. # #============================================================================ function KLIB_HACMP_modify_cluster { . $HALIBROOT/log_entry "$0()" "$CL" : version=@(#) 03a409f 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_cluster.sh, 726, 2147A_aha726, May 19 2021 03:11 PM : INPUTS: $* typeset -n properties=$1 # Remove the properties from the list of arguments shift typeset new_name=${1//\"/} typeset fc_sync_interval=${2//\"/} typeset rg_settling_time=${3//\"/} typeset -l rg_dist_policy=${4//\"/} typeset max_event_time=${5//\"/} typeset max_rg_processing_time=${6//\"/} typeset -l faction=${7//\"/} typeset nmethod=${8//\"/} typeset -l autover=${9//\"/} typeset autover_node=${10//\"/} typeset autover_hour=${11//\"/} typeset -l autover_debug=${12//\"/} typeset repositories=${13//\"/} repositories=${repositories//,/ } typeset cluster_ip=${14//\"/} typeset heartbeat=${15//\"/} typeset node_down_delay=${16//\"/} typeset site_heartbeat_cycle=${17//\"/} typeset site_grace_period=${18//\"/} typeset -u type=${19//\"/} typeset -l heartbeat_type=${20//\"/} typeset -l temp_hostname=${21//\"/} : Split-merge inputs typeset -l split_policy=${22//\"/} typeset -l merge_policy=${23//\"/} typeset nfs_quorum_server=${24//\"/} typeset local_quorum_directory=${25//\"/} typeset remote_quorum_directory=${26//\"/} typeset quarantine_policy=${27//\"/} typeset critical_rg=${28//\"/} typeset -l action_plan=${29//\"/} typeset tiebreaker=${30//\"/} typeset notify_method=${31//\"/} typeset notify_interval=${32//\"/} typeset maximum_notifications=${33//\"/} typeset default_surviving_site=${34//\"/} typeset -l apply_to_pprc_takeover=${35//\"/} typeset nodes=${36//\"/} nodes=${nodes//,/ } typeset -l lpm_policy=${37//\"/} typeset lpm_heartbeat=${38//\"/} typeset network_fdt=${39//\"/} typeset caa_auto_start_dr=${40//\"/} typeset caa_repos_mode=${41//\"/} typeset -l caa_config_timeout=${42//\"/} typeset lvm_preferred_read=${43//\"/} typeset crit_daemon_restart_grace_period=${44//\"/} typeset skip_events_on_manage=${45//\"/} typeset bucket_name=${46//\"/} typeset cloud_service=${47//\"/} typeset use_existing_bucket=${48//\"/} [[ $CLMGR_LOGGING == 'med' ]] && set +x # Only trace param values #================================================================ : Check for a defined cluster. No need to continue without one. #================================================================ CL=$LINENO isClusterDefined if (( $? != RC_SUCCESS )); then log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO" return $? fi #=================================== : Declare and initialize variables #=================================== typeset -i rc=$RC_UNKNOWN cmd_rc=$RC_UNKNOWN typeset OUTPUT= name= typeset -A clattrs typeset -i caa_cluster_exists=0 typeset skip="" typeset -i HeartbeatLowValue=0 HeartbeatHighValue=0 typeset -i NodeDownDelayLowValue=0 NodeDownDelayHighValue=0 typeset -i NetworkLowValue=0 NetworkHighValue=0 #==================================== : Check for a split-merge operation #==================================== if [[ "$split_policy$merge_policy$nfs_quorum_server$local_quorum_directory$remote_quorum_directory$quarantine_policy$critical_rg$action_plan\ $tiebreaker$notify_method$notify_interval$maximum_notifications$default_surviving_site$apply_to_pprc_takeover$bucket_name$cloud_service$use_existing_bucket" != *([[:space:]]) ]] then handle_split_merge "$split_policy" \ "$merge_policy" \ "$nfs_quorum_server" \ "$local_quorum_directory" \ "$remote_quorum_directory" \ "$quarantine_policy" \ "$critical_rg" \ "$action_plan" \ "$tiebreaker" \ "$notify_method" \ "$notify_interval" \ "$maximum_notifications" \ "$default_surviving_site" \ "$apply_to_pprc_takeover" \ "$bucket_name" \ "$cloud_service" \ "$use_existing_bucket" rc=$? fi # get some general cluster attributes for later checks CL=$LINENO isEnterprise typeset -i ENTERPRISE_EDITION=$? CL=$LINENO CLMGR_VERBOSE=0 KLIB_HACMP_get_cluster_attributes clattrs # Check for AIX 71 TL4 or later versions of AIX to see if we can set # the network_fdt tunable typeset -i FV FR FM FF VR typeset -i network_fdt_capable=0 lslpp -lcqOr bos.cluster.rte | cut -f3 -d':' | IFS=. read FV FR FM FF VR=$FV$FR if (( $VR > 71 )) || (( $VR == 71 && $FM > 3 )) then # CAA is capable network_fdt_capable=1; fi #================= : Validate inputs #================= if [[ "$*" == *([[:space:]]) ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 401 "\nERROR: no valid modifications were specified for \"%1\$s\".\n\n" "$(cllsclstr -cS | cut -d: -f2)" 1>&2 rc=$RC_MISSING_INPUT elif [[ -n $new_name && -n "${new_name//[a-zA-Z0-9_]/}" ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 188 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid characters include letters, numbers, underscores, and dashes only.\n\n" "$new_name" "${new_name//[a-zA-Z0-9_]/}" 1>&2 rc=$RC_INCORRECT_INPUT fi if [[ -n $heartbeat_type ]]; then if [[ -z $LANG || $LANG=@(C|en|En|EN)* ]]; then CL=$LINENO verify_in_set HEARTBEAT_TYPE "$heartbeat_type" "unicast, uc, multicast, mc" heartbeat_type if (( $? != RC_SUCCESS )); then rc=RC_INCORRECT_INPUT else [[ $heartbeat_type == u* ]] && heartbeat_type="unicast" \ || heartbeat_type="multicast" fi else # Convert other languages to English, for internal processing typeset -l UC=$(dspmsg -s 64 cluster.cat 4 "Unicast") typeset -l MC=$(dspmsg -s 64 cluster.cat 5 "Multicast") if [[ $UC == $heartbeat_type* ]]; then heartbeat_type="unicast" elif [[ $MC == $heartbeat_type* ]]; then heartbeat_type="multicast" fi fi elif [[ $CLMGR_STACK == *KLIB_HACMP_add_cluster* ]]; then # Only need to set a default heartbeating # type during an "add cluster" operation. heartbeat_type="unicast" fi typeset -u HBT="" if [[ $heartbeat_type == "unicast" ]]; then HBT="U" if ! cl_migcheck ANY 2>>$CLMGR_TMPLOG then print "\nERROR: one or more nodes in the cluster is not reachable through a tcpip connection,\nand cannot be reconfigured for unicast capability. Please perform the necessary updates\non all nodes to allow a unicast-based cluster.\n\n" 1>&2 rc=$RC_INCORRECT_INPUT fi if [[ -n $cluster_ip ]]; then # : If both unicast was selected, and an IP address provided, : the user is confused. Unicast takes precedence. # cl_dspmsg -s 64 cluster.cat 1 'A cluster IP address for heartbeat is not required with unicast heartbeating. The entered cluster IP address will be ignored.\n' cluster_ip="" fi elif [[ $heartbeat_type == "multicast" ]]; then [[ -n $cluster_ip ]] && HBT="C" || HBT="M" if [[ $CLMGR_STACK == *KLIB_HACMP_add_cluster* && \ $HBT == "M" ]] then # Only need to display this during an "add cluster" operation cl_dspmsg -s 64 cluster.cat 8 'A default multicast IP address will be assigned during synchronization\n' fi fi if [[ -n $rg_dist_policy ]]; then CL=$LINENO verify_in_set RG_DIST_POLICY "$rg_dist_policy" "node, network" rg_dist_policy (( $? != RC_SUCCESS )) && rc=RC_INCORRECT_INPUT fi if [[ -n $faction ]]; then CL=$LINENO verify_in_set SITE_POLICY_FAILURE_ACTION "$faction" "fallover, notify" faction (( $? != RC_SUCCESS )) && rc=RC_INCORRECT_INPUT fi # Check whether CAA cluster exists /usr/lib/cluster/incluster 2>/dev/null (( $? == RC_SUCCESS )) && caa_cluster_exists=1 #============================================================================================= : The default value of lpm_heartbeat should be set to 600 only during "add cluster" operation #============================================================================================= if [[ -z $lpm_heartbeat && $CLMGR_STACK == *KLIB_HACMP_add_cluster* ]]; then lpm_heartbeat=600 fi if [[ -n $heartbeat || -n $lpm_heartbeat ]]; then typeset DESC="HEARTBEAT_FREQUENCY" if (( caa_cluster_exists )); then print "$0()[$LINENO]($SECONDS): LC_ALL=C clctrl -tune -L node_timeout" >>$CLMGR_TMPLOG LC_ALL=C clctrl -tune -L node_timeout | grep node_timeout | read skip skip HeartbeatLowValue HeartbeatHighValue skip cmd_rc=$? print "$0()[$LINENO]($SECONDS): clctrl RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc == 0 )); then (( HeartbeatLowValue /= 1000 )) (( HeartbeatHighValue /= 1000 )) if [[ -n $heartbeat ]]; then typeset DESC="HEARTBEAT_FREQUENCY" [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 33 "Node Failure Detection Timeout") CL=$LINENO verify_numeric_range "$heartbeat" $HeartbeatLowValue $HeartbeatHighValue "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $lpm_heartbeat ]]; then # Set a default value if 0 has been given if (( $lpm_heartbeat == 0 )); then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1181 "\nWARNING: The value passed for Node Failure Detection Timeout during LPM is 0, updating it to default value 600\n" 1>&2 lpm_heartbeat=600 fi typeset DESC="HEARTBEAT_FREQUENCY_DURING_LPM" [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 56 "Node Failure Detection Timeout during LPM") CL=$LINENO verify_numeric_range "$lpm_heartbeat" $HeartbeatLowValue $HeartbeatHighValue "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi fi fi fi if [[ -n $node_down_delay ]]; then typeset DESC="GRACE_PERIOD" if (( caa_cluster_exists )); then [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 34 "Failure Indication Grace Time") print "$0()[$LINENO]($SECONDS): LC_ALL=C clctrl -tune -L node_down_delay" >>$CLMGR_TMPLOG LC_ALL=C clctrl -tune -L node_down_delay | grep node_down_delay | read skip skip NodeDownDelayLowValue NodeDownDelayHighValue skip cmd_rc=$? print "$0()[$LINENO]($SECONDS): clctrl RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc == 0 )); then (( NodeDownDelayLowValue /= 1000)) (( NodeDownDelayHighValue /= 1000)) CL=$LINENO verify_numeric_range "$node_down_delay" $NodeDownDelayLowValue $NodeDownDelayHighValue "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi fi fi # validate network fdt input if (( $network_fdt_capable == 1 ));then if [[ -n $network_fdt ]];then typeset DESC="NETWORK_FAILURE_DETECTION_TIME" if (( caa_cluster_exists )); then [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 61 "Network Failure Detection Time") if [[ -n $heartbeat ]];then typeset -i network_max_value=($heartbeat-10) if (( $network_fdt < 5 && $network_fdt > 0 ));then print "$0()[$LINENO]($SECONDS): Network Failure Detection value should be at least 5 seconds or 0 (unset)." >> $CLMGR_TMPLOG cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1141 'ERROR: Network Failure Detection value should be at least 5 seconds or 0 (unset).\n\n' 1>&2 rc=$RC_INCORRECT_INPUT fi if (( $network_fdt > $network_max_value ));then print "$0()[$LINENO]($SECONDS): Given Network Failure Detection TimeOut is not at least 10 seconds less than Node Failure Detection Time(Heartbeat frequency)$heartbeat sec" >>$CLMGR_TMPLOG cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1140 'ERROR: The Given Network Failure Detection TimeOut is not at least 10 seconds less than the Node Failure Detection Time(Heartbeat frequency)%1$s seconds.\nThe Network Failure Detection TimeOut value can be set within the range 5 to %2$s seconds based on the current Node Failure Detection Time value.\n\n' "$heartbeat" "$network_max_value" 1>&2 rc=$RC_INCORRECT_INPUT fi else typeset -i caa_heartbeat=$(clctrl -tune -o node_timeout | awk -F "=" '{print $2}') (( caa_heartbeat /=1000 )) typeset -i network_max=($caa_heartbeat-10) if (( $network_fdt < 5 && $network_fdt > 0 ));then print "$0()[$LINENO]($SECONDS): Network Failure Detection value should be at least 5 seconds or 0 (unset)" >> $CLMGR_TMPLOG cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1141 'ERROR: Network Failure Detection value should be at least 5 seconds or 0 (unset).\n\n' 1>&2 rc=$RC_INCORRECT_INPUT fi if (( $network_fdt > $network_max ));then print "$0()[$LINENO]($SECONDS): Given Network Failure Detection TimeOut is not at least 10 seconds less than Node Failure Detection Time(Heartbeat frequency)$caa_heartbeat sec" >>$CLMGR_TMPLOG cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1140 'ERROR: The Given Network Failure Detection TimeOut is not at least 10 seconds less than the Node Failure Detection Time(Heartbeat frequency)%1$s seconds.\nThe Network Failure Detection TimeOut value can be set within the range 5 to %2$s seconds based on the current Node Failure Detection Time value.\n\n' "$caa_heartbeat" "$network_max" 1>&2 rc=$RC_INCORRECT_INPUT fi fi print "$0()[$LINENO]($SECONDS): LC_ALL=C clctrl -tune -L network_fdt" >>$CLMGR_TMPLOG LC_ALL=C clctrl -tune -L network_fdt | grep network_fdt | read skip skip NetworkLowValue NetworkHighValue skip cmd_rc=$? print "$0()[$LINENO]($SECONDS): clctrl RC: $cmd_rc" >>$CLMGR_TMPLOG if (( $cmd_rc == 0 )); then (( NetworkLowValue /=1000 )) (( NetworkHighValue /=1000 )) CL=$LINENO verify_numeric_range "$network_fdt" $NetworkLowValue $NetworkHighValue "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi fi fi else # network_fdt_capable is 0 - AIX level does not support network fdt if [[ -n $network_fdt ]] then cl_dspmsg -s 63 cluster.cat 72 '\nNetwork failure detection time is not modified as PowerHA supports this tunable only from AIX 71 TL4 version.\n' rc=$RC_INCORRECT_INPUT fi fi if [[ -n $site_heartbeat_cycle ]]; then typeset DESC="SITE_HEARTBEAT_CYCLE" [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 10 "Site Heartbeat Cycle") CL=$LINENO verify_numeric_range "$site_heartbeat_cycle" 1 10 "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi if [[ -n $site_grace_period ]]; then typeset DESC="SITE_GRACE_PERIOD" [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 35 "Link Failure Detection Timeout") CL=$LINENO verify_numeric_range "$site_grace_period" 5 30 "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi # : Before validating critical daemon restart grace period, verifing the installed RSCT version : supports crit_daemon_restart_grace_period attribute or not. # if [[ -n $crit_daemon_restart_grace_period ]]; then typeset RSCT_SUPPORTED_VERSION="3.2.5.0" typeset RSCT_VERSION RSCT_VERSION=$(ctversion | cut -s -f 2 -d ' ') echo $RSCT_VERSION | IFS="." read V R M F if (( $V$R$M$F < 3250 ));then dspmsg -s 63 cluster.cat 80 "\nERROR: Installed RSCT verion \"%1\$s\" is not supported for CRIT_DAEMON_RESTART_GRACE_PERIOD attribute.\n\ Minimum RSCT version required to support CRIT_DAEMON_RESTART_GRACE_PERIOD is \"%2\$s\"" $RSCT_VERSION $RSCT_SUPPORTED_VERSION 1>&2 rc=$RC_INCORRECT_INPUT else typeset DESC="CRIT_DAEMON_RESTART_GRACE_PERIOD" [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 78 "Critical Daemon Restart Grace Period") CL=$LINENO verify_numeric_range "$crit_daemon_restart_grace_period" 0 240 "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi fi typeset -i skip_events_flag if [[ -n $skip_events_on_manage ]]; then CL=$LINENO verify_in_set SKIP_EVENT_PROCESSING_MANAGE_MODE "$skip_events_on_manage" "true, false" skip_events_on_manage if (( $? == RC_SUCCESS )); then [[ $skip_events_on_manage == @(t)* ]] && skip_events_flag=1 [[ $skip_events_on_manage == @(f)* ]] && skip_events_flag=0 else rc=$RC_INCORRECT_INPUT fi fi if [[ $temp_hostname != *([[:space:]]) ]]; then CL=$LINENO verify_in_set TEMP_HOSTNAME "$temp_hostname" "allow, yes, true, 1, disallow, no, false, 0" temp_hostname if (( $? == RC_SUCCESS )); then value=0 [[ $temp_hostname == @(a|y|t|1)* ]] && value=1 print "HACMPcluster: honorTempHostNameChanges = $value" | odmchange -o HACMPcluster if (( $(clodmget -n -f honorTempHostNameChanges HACMPcluster) != $value )); then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 435 '\nERROR: unable to update the non-persistent hostname change support on node "%1$s".\n\n' "$LOCAL_NODE" 1>&2 rc=$RC_ERROR else cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 189 'This change will go into effect on all nodes after the cluster is synchronized.\n' print "HACMPcluster: handle = 0" | odmchange -o HACMPcluster fi else rc=$RC_INCORRECT_INPUT fi fi #============================================================================================= : The default value of lpm_policy should be set to "manage" only during "add cluster" operation #============================================================================================= if [[ -z $lpm_policy && $CLMGR_STACK == *KLIB_HACMP_add_cluster* ]]; then lpm_policy="manage" fi if [[ -n $lpm_policy ]]; then CL=$LINENO verify_in_set LPM_POLICY "$lpm_policy" "manage, unmanage" lpm_policy (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi typeset -i dr_enable if [[ -n $caa_auto_start_dr ]]; then CL=$LINENO verify_in_set CAA_AUTO_START_DR "$caa_auto_start_dr" "enabled, disabled" caa_auto_start_dr if (( $? == RC_SUCCESS )); then [[ $caa_auto_start_dr == @(e)* ]] && dr_enable=1 [[ $caa_auto_start_dr == @(d)* ]] && dr_enable=0 else rc=$RC_INCORRECT_INPUT fi fi #============================================================================================= : The default value of repos_mode should be set to "event" only during "add cluster" operation #============================================================================================= if [[ -z $caa_repos_mode && $CLMGR_STACK == *KLIB_HACMP_add_cluster* ]]; then caa_repos_mode="event" fi typeset -i repos if [[ -n $caa_repos_mode ]]; then CL=$LINENO verify_in_set CAA_REPOS_MODE "$caa_repos_mode" "assert, event" caa_repos_mode if (( $? == RC_SUCCESS )); then [[ $caa_repos_mode == @(a)* ]] && repos=0 [[ $caa_repos_mode == @(e)* ]] && repos=1 else rc=$RC_INCORRECT_INPUT fi fi #============================================================================================= : The default value of lvm_preferred_read should be set to "roundrobin" #============================================================================================= if [[ -n "$lvm_preferred_read" ]]; then if [[ $CLUSTER_TYPE != "NSC" ]]; then # siteaffinity option is available only for site based cluster. CL=$LINENO verify_in_set LVM_PREFERRED_READ "$lvm_preferred_read" "roundrobin, favorcopy, siteaffinity" lvm_preferred_read else CL=$LINENO verify_in_set LVM_PREFERRED_READ "$lvm_preferred_read" "roundrobin, favorcopy" lvm_preferred_read fi if (( $? != RC_SUCCESS )); then rc=$RC_INCORRECT_INPUT fi else lvm_preferred_read="roundrobin" fi #============================================================================================= : The default value of config_timeout should be set to 240 only during "add cluster" operation #============================================================================================= if [[ -z $caa_config_timeout && $CLMGR_STACK == *KLIB_HACMP_add_cluster* ]]; then caa_config_timeout=240 fi if [[ -n $caa_config_timeout ]]; then typeset DESC="CONFIG_TIMEOUT" [[ -n $CLMGR_GUI ]] && DESC=$(dspmsg -s 63 cluster.cat 73 "Config timeout") CL=$LINENO verify_numeric_range "$caa_config_timeout" 0 2147483647 "$DESC" (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT fi #================================================================== # Verify the cluster type to set the site grace period #================================================================== if [[ $CLUSTER_TYPE == "NSC" || $CLUSTER_TYPE == "SC" ]] && [[ -n $site_grace_period ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1484 'ERROR: Site grace period can only be changed in linked cluster.\n\n' 1>&2 rc=$RC_INCORRECT_INPUT fi #================================= # Tune the cluster, if requested #================================= if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $heartbeat ]]; then #========================================= : Setting node heartbeat to "$heartbeat" #========================================= print "HACMPcluster: node_timeout=$heartbeat" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f node_timeout HACMPcluster) (( $VAL == $heartbeat )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $node_down_delay ]]; then #================================================== : Setting node grace period to "$node_down_delay" #================================================== print "HACMPcluster: node_down_delay=$node_down_delay" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f node_down_delay HACMPcluster) (( $VAL == $node_down_delay )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if (( $network_fdt_capable == 1 ));then if [[ -n $network_fdt ]]; then #================================================== : Setting network failure detection time to "$network_fdt" #================================================== print "HACMPcluster: network_fdt=$network_fdt" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f network_fdt HACMPcluster) (( $VAL == $network_fdt )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $site_grace_period ]]; then #==================================================== : Setting site grace period to "$site_grace_period" #==================================================== print "HACMPcluster: link_timeout=$site_grace_period" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f link_timeout HACMPcluster) (( $VAL == $site_grace_period )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $site_heartbeat_cycle ]]; then #========================================================== : Setting site heartbeat cycle to "$site_heartbeat_cycle" #========================================================== print "$0()[$LINENO]($SECONDS): odmchange -o HACMPcluster ==> remote_HB_factor=$site_heartbeat_cycle" >>$CLMGR_TMPLOG print "HACMPcluster: remote_HB_factor=$site_heartbeat_cycle" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f remote_HB_factor HACMPcluster) (( $VAL == $site_heartbeat_cycle )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $HBT ]]; then #============================================================ : Update the heartbeat type to "$HBT", for "$hearbeat_type" #============================================================ print "$0()[$LINENO]($SECONDS): odmchange -o HACMPcluster ==> handle=0, heartbeattype=$HBT" >>$CLMGR_TMPLOG print "HACMPcluster: handle=0 heartbeattype=$HBT" | odmchange -o HACMPcluster if [[ "$(clodmget -n -f handle HACMPcluster)" == "0" && \ "$(clodmget -n -f heartbeattype HACMPcluster)" == "$HBT" ]] then rc=$RC_SUCCESS else rc=$RC_ERROR fi print "$0()[$LINENO]($SECONDS): odmchange RC: $rc" >>$CLMGR_TMPLOG fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if (( caa_cluster_exists )) && [[ -n $new_name ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 439 '\nERROR: the CAA cluster already exists, so the cluster name (%1$s) cannot be changed.\n\n' "${clattrs[CLUSTER_NAME]}" 1>&2 rc=$RC_INCORRECT_INPUT elif [[ -n $new_name ]]; then #============================================== : Establish the new cluster name, "$new_name" #============================================== print "$0()[$LINENO]($SECONDS): clmodclstr -n $new_name" >>$CLMGR_TMPLOG # Always log commands OUTPUT=$(clmodclstr -n $new_name 2>&1) rc=$? print "$0()[$LINENO]($SECONDS): clmodclstr RC: $rc; OUTPUT == \"$OUTPUT\"" >>$CLMGR_TMPLOG # Always log command result if (( $rc != RC_SUCCESS )); then print -- "$OUTPUT" 1>&2 rc=$RC_ERROR fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $fc_sync_interval ]]; then if [[ $fc_sync_interval == +([[:digit:]]) ]]; then #======================================================= : File collection automatic propagation check interval #======================================================= print "$0()[$LINENO]($SECONDS): clfilecollection -o time -c $fc_sync_interval" >>$CLMGR_TMPLOG # Always log commands clfilecollection -o time -c $fc_sync_interval rc=$? print "$0()[$LINENO]($SECONDS): clfilecollection RC: $rc" >>$CLMGR_TMPLOG # Always log command result (( $rc != RC_SUCCESS )) && rc=$RC_ERROR print "$0()[$LINENO]($SECONDS): clodmget -q 'name=file_collections_auto_prop' -f period HACMPtimersvc" >>$CLMGR_TMPLOG # Always log commands typeset 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 == +([[:digit:]]) ]]; then typeset -i PERIOD (( PERIOD = PERIOD_STR / 60 )) # Convert to minutes print "fc_sync_interval = $PERIOD" fi else dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" FC_SYNC_INTERVAL 1>&2 rc=$RC_INCORRECT_INPUT fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $rg_settling_time ]]; then if [[ $rg_settling_time == +([[:digit:]]) ]]; then #======================================================= : Adjust the cluster-wide resource group settling time #======================================================= print "$0()[$LINENO]($SECONDS): clsettlingtime change $rg_settling_time" >>$CLMGR_TMPLOG # Always log commands clsettlingtime change $rg_settling_time rc=$? print "$0()[$LINENO]($SECONDS): clsettlingtime RC: $rc" >>$CLMGR_TMPLOG # Always log command result (( $rc != RC_SUCCESS )) && rc=$RC_ERROR else dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" RG_SETTLING_TIME 1>&2 rc=$RC_INCORRECT_INPUT fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $rg_dist_policy ]]; then #============================================================= : Adjust the cluster-wide resource group distribution policy #============================================================= print "$0()[$LINENO]($SECONDS): clsetdistpolicy change $rg_dist_policy" >>$CLMGR_TMPLOG # Always log commands clsetdistpolicy change $rg_dist_policy rc=$? print "$0()[$LINENO]($SECONDS): clsetdistpolicy RC: $rc" >>$CLMGR_TMPLOG # Always log command result (( $rc != RC_SUCCESS )) && rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $max_event_time || -n $max_rg_processing_time ]]; then #======================================= : Timers controlling "config_too_long" #======================================= if [[ -z $max_event_time ]]; then max_event_time=${clattrs[MAX_EVENT_TIME]} elif [[ -z $max_max_rg_processing_time ]]; then max_rg_processing_time=${clattrs[MAX_RG_PROCESSING_TIME]} fi if [[ $max_event_time == +([[:digit:]]) && $max_rg_processing_time != +([[:digit:]]) ]] then dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" MAX_RG_PROCESSING_TIME 1>&2 rc=$RC_INCORRECT_INPUT elif [[ $max_event_time != +([[:digit:]]) && $max_rg_processing_time == +([[:digit:]]) ]] then dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" MAX_EVENT_TIME 1>&2 rc=$RC_INCORRECT_INPUT elif (( max_event_time <= 0 || max_rg_processing_time <= 0 )) then dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" MAX_EVENT_TIME 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" MAX_RG_PROCESSING_TIME 1>&2 rc=$RC_INCORRECT_INPUT else print "$0()[$LINENO]($SECONDS): clchmsgtimer -e$max_event_time -g$max_rg_processing_time" >>$CLMGR_TMPLOG # Always log commands clchmsgtimer -e$max_event_time \ -g$max_rg_processing_time rc=$? print "$0()[$LINENO]($SECONDS): clchmsgtimer RC: $rc" >>$CLMGR_TMPLOG # Always log command result (( $rc != RC_SUCCESS )) && rc=$RC_ERROR # verify the results if (( rc == RC_SUCCESS )) then if (( $(clodmget -f reserved1 HACMPcluster) != $max_event_time || $(clodmget -f reserved2 HACMPcluster) != $max_rg_processing_time )) then dspmsg -s 4 verify.cat 8186 "An internal error occurred while checking clchmsgtimer.\nPlease report this problem to IBM support.\n" "clchmsgtimer" print "$0()[$LINENO]: clchmsgtimer failed to update the odm with the supplied values." >>$CLMGR_TMPLOG print "max_event_time: $max_event_time reserved1: $(clodmget -f reserved1 HACMPcluster)" >>$CLMGR_TMPLOG print "max_rg_processing_time: $max_rg_processing_time reserved2: $(clodmget -f reserved2 HACMPcluster)" >>$CLMGR_TMPLOG fi fi fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $faction || -n $nmethod ]]; then #============================ : Set the cross-site policy #============================ [[ -z $faction ]] && faction=${clattrs[SITE_POLICY_FAILURE_ACTION]} [[ -z $nmethod ]] && nmethod=${clattrs[SITE_POLICY_NOTIFY_METHOD]} print "$0()[$LINENO]($SECONDS): clchappmon resource_group= name=CROSS_SITE_RG_MOVE FAILURE_ACTION=\"$faction\" NOTIFY_METHOD=\"$nmethod\"" >>$CLMGR_TMPLOG # Always log commands clchappmon resource_group= \ name=CROSS_SITE_RG_MOVE \ FAILURE_ACTION="$faction" \ NOTIFY_METHOD="$nmethod" rc=$? print "$0()[$LINENO]($SECONDS): clchappmon RC: $rc" >>$CLMGR_TMPLOG # Always log command result (( $rc != RC_SUCCESS )) && rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n "$autover$autover_node$autover_hour$autover_debug" ]]; then #=============================================================== : Update the automatic, daily verification settings, if needed #=============================================================== typeset autover_flag= if [[ -n $autover ]]; then [[ $autover == @(d|f|n|0)* ]] && autover_flag="-d" \ || autover_flag="-e" else autover="-e" [[ ${clattrs[DAILY_VERIFICATION]} == @(d|D)* ]] && autover_flag="-d" fi typeset -u autover_node_uc= typeset -u DEFAULT=$(dspmsg -s 1 cluster.cat 860 Default) if [[ -n $autover_node ]]; then autover_node_uc=$autover_node [[ $DEFAULT == $autover_node_uc* ]] && unset autover_node \ || autover_node="-n $autover_node" else autover_node_uc=${clattrs[VERIFICATION_NODE]} autover_node="-n Default" [[ $DEFAULT == $autover_node_uc* ]] && unset autover_node \ || autover_node="-n ${clattrs[VERIFICATION_NODE]}" fi if [[ -n $autover_hour ]]; then autover_hour="-h $autover_hour" else autover_hour="-h ${clattrs[VERIFICATION_HOUR]}" fi typeset autover_debug_flag= if [[ -n $autover_debug ]]; then [[ $autover_debug == @(d|f|n|0)* ]] && autover_debug_flag="" \ || autover_debug_flag="-D" else autover_debug_flag="-D" [[ ${clattrs[DAILY_VERIFICATION]} == @(d|D)* ]] && autover_debug_flag="" fi print "$0()[$LINENO]($SECONDS): clautoconfigmonitor $autover_flag $autover_node $autover_hour $autover_debug_flag" >>$CLMGR_TMPLOG # Always log commands clautoconfigmonitor $autover_flag $autover_node $autover_hour $autover_debug_flag rc=$? print "$0()[$LINENO]($SECONDS): clautoconfigmonitor RC: $rc" >>$CLMGR_TMPLOG # Always log command result fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then #=============================== : Get the current cluster name #=============================== print "$0()[$LINENO]($SECONDS): cllsclstr -cn | awk -F: '(NR==2) {print $2}'" >>$CLMGR_TMPLOG # Always log commands name=$(cllsclstr -cn | awk -F: '(NR==2) {print $2}') print "$0()[$LINENO]($SECONDS): cllsclstr RC: $?; name == \"$name\"" >>$CLMGR_TMPLOG # Always log command result fi if (( caa_cluster_exists )) && [[ -n $type ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1482 'Cluster TYPE changed to %1$s. Proceed with next steps to complete cluster conversion.' "$type" 1>&2 elif [[ -n $type ]]; then typeset SITES=$(clodmget -n -f name HACMPsite) if [[ $type == "NSC" && -n $SITES ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 432 '\nERROR: the current cluster configuration contains sites, so its type cannot be set to "NSC".\n\n' 1>&2 rc=$RC_INCORRECT_INPUT fi fi if [[ -n $repositories && $CLUSTER_TYPE == "LC" ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 436 '\nERROR: repositories must be specified per site in a linked cluster.\n\n' 1>&2 rc=$RC_INCORRECT_INPUT fi # typeset -i NB_NEW_BACKUP_REPOS=$(print $repositories | wc -w) [[ -z $NB_NEW_BACKUP_REPOS ]] && NB_NEW_BACKUP_REPOS=0 || (( NB_NEW_BACKUP_REPOS-=1)) if (( $NB_NEW_BACKUP_REPOS > $MAX_NB_OF_BACKUP_REPOSITORIES )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 1002 "\nERROR: a no-site cluster or a stretched cluster cannot get more than \"%1\$s\" backup repositories (there were \"%2\$s\" backup repositories, and you want to add \"%3\$s\" backup repositories).\n\n" "$MAX_NB_OF_BACKUP_REPOSITORIES" "0" "${NB_NEW_BACKUP_REPOS}" 1>&2 rc=$RC_INCORRECT_INPUT fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $cluster_ip ]]; then #========================================= : Validate the cluster multicast address #========================================= CL=$LINENO verify_is_multicast_address $cluster_ip (( $? != RC_SUCCESS )) && rc=RC_INCORRECT_INPUT if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then #============================================== : Looks like "$cluster_ip" is a valid address #============================================== rm -f $MCIP_ERROR_FILE #=============================================== : If the CAA cluster has not been created yet, : manually clean up any previous IP entry. #=============================================== if (( ! caa_cluster_exists )); then print "$0()[$LINENO]($SECONDS): clodmget -n -f ip_address HACMPsircol" >>$CLMGR_TMPLOG # Always log commands typeset existing_clusterip=$(clodmget -n -f ip_address HACMPsircol 2>/dev/null) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; existing_clusterip == \"$existing_clusterip\"" >>$CLMGR_TMPLOG # Always log command result if [[ $existing_clusterip == [[:digit:]]* ]]; then #=========================================== : We have one defined and should delete it #=========================================== typeset sircolname= print "$0()[$LINENO]($SECONDS): clodmget -n -f name HACMPsircol" >>$CLMGR_TMPLOG # Always log commands sircolname=$(clodmget -n -f name HACMPsircol) print "$0()[$LINENO]($SECONDS): clodmget RC: $?; sircolname == \"$sircolname\"" >>$CLMGR_TMPLOG # Always log command result print "$0()[$LINENO]($SECONDS): odmget -q \"name = $sircolname\" HACMPsircol" >>$CLMGR_TMPLOG # Always log commands odmget -q "name = $sircolname" HACMPsircol >$TMPDIR/clmgr.KHmc.sircol.old.$$ print "$0()[$LINENO]($SECONDS): odmget RC: $?" >>$CLMGR_TMPLOG # Always log command result sed 's/ip_address = .*/ip_address =\"\"/' $TMPDIR/clmgr.KHmc.sircol.old.$$ >$TMPDIR/clmgr.KHmc.sircol.chg.$$ print "$0()[$LINENO]($SECONDS): odmchange -o HACMPsircol -q \"name = $sircolname\"" >>$CLMGR_TMPLOG # Always log commands odmchange -o HACMPsircol -q "name = $sircolname" $TMPDIR/clmgr.KHmc.sircol.chg.$$ print "$0()[$LINENO]($SECONDS): odmchange RC: $?" >>$CLMGR_TMPLOG # Always log command result rm -rf $TMPDIR/clmgr.KHmc.sircol.old.$$ 2>/dev/null rm -rf $TMPDIR/clmgr.KHmc.sircol.chg.$$ 2>/dev/null fi fi #===================================================== : Setting cluster multicast address to "$cluster_ip" #===================================================== print -- "$0()[$LINENO]($SECONDS): odmchange -o HACMPcluster... ip_address=$cluster_ip" >>$CLMGR_TMPLOG print "HACMPsircol: ip_address=$cluster_ip" | odmchange -o HACMPsircol rc=$? print -- "$0()[$LINENO]($SECONDS): odmchange RC: $rc" >>$CLMGR_TMPLOG typeset VAL=$(clodmget -n -f ip_address HACMPsircol) [[ $VAL == $cluster_ip ]] && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then [[ -z $type ]] && type=$CLUSTER_TYPE typeset -i multi_site_lc=-1 case $type in SC) multi_site_lc=0 ;; # Stretched cluster STR*) multi_site_lc=0 ;; # Stretched cluster LC) multi_site_lc=1 ;; # Linked cluster LI*) multi_site_lc=1 ;; # Linked cluster *) multi_site_lc=-1 ;; # Non-site cluster esac #============================================================= : Setting cluster type to "$multi_site_lc", for TYPE="$type" #============================================================= print -- "$0()[$LINENO]($SECONDS): odmchange -o HACMPcluster... multi_site_lc=$multi_site_lc" >>$CLMGR_TMPLOG print "HACMPcluster: multi_site_lc=$multi_site_lc" | odmchange -o HACMPcluster rc=$? print -- "$0()[$LINENO]($SECONDS): odmchange RC: $rc" >>$CLMGR_TMPLOG typeset VAL=$(clodmget -n -f multi_site_lc HACMPcluster) [[ $VAL == $multi_site_lc ]] && rc=$RC_SUCCESS || rc=$RC_ERROR # We are going to convert the cluster to a Linked type. # To change CAA cluster, dr_enabled tunable should be reset to 0. if (( caa_cluster_exists )) && [[ $VAL == 1 ]]; then print -- "$0()[$LINENO]($SECONDS): To enable cluster conversion to Linked type, resetting dr_enabled tunable to 0." >>$CLMGR_TMPLOG print "HACMPcluster: dr_enabled=0" | /usr/bin/odmchange -o HACMPcluster print "$0()[$LINENO]($SECONDS): LC_ALL=C clctrl -tune -o dr_enabled=0" >>$CLMGR_TMPLOG LC_ALL=C clctrl -tune -o dr_enabled=0 cmd_rc=$? print "$0()[$LINENO]($SECONDS): clctrl RC: $cmd_rc" >>$CLMGR_TMPLOG fi fi #=================================================== # This code is to preserve backwards compatibility #=================================================== if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $repositories ]]; then if (( ! caa_cluster_exists )); then typeset -A arprops KLIB_HACMP_add_repository arprops "$repositories" rc=$? elif [[ ${repositories//,/} != *([[:space:]]) ]]; then KLIB_HACMP_replace_repository ${repositories%% *} rc=$? fi fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && \ [[ -n $nodes ]] then #================================================================== : If the NODES input is provided, this list is considered to be : the desired new complete list of nodes for the cluster. So any : nodes specified that are not currently in the cluster are to : be added as new cluster nodes. And any nodes that are currently : in the cluster that are *not* specified in the new list are to : be removed from the cluster. : NOTE: if the local node is not in the node list, the operation : cannot succeed, and an error message will be emitted. #================================================================== typeset current_nodes=$(clnodename) current_nodes=${current_nodes//+([[:space:]])/ } typeset node="" add_nodes="" keepers="" for node in $nodes; do if [[ " $current_nodes " == *\ $node\ * ]]; then [[ -n $keepers ]] && keepers="$keepers " keepers="$keepers$node" else [[ -n $add_nodes ]] && add_nodes="$add_nodes " add_nodes="$add_nodes$node" fi done typeset remove_nodes="" for node in $current_nodes; do if [[ " $nodes " != *\ $node\ * ]]; then [[ -n $remove_nodes ]] && remove_nodes="$remove_nodes " remove_nodes="$remove_nodes$node" fi done if [[ -n $remove_nodes && \ " $remove_nodes " == *\ $LOCAL_NODE\ * && \ -n $keepers ]] then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 444 '\nERROR: the specified node list (%1$s) does not contain the local node, "%2$s". It is not possible to remove "%2$s" from the cluster while actively running a cluster configuration operation on it. Either add "%2$s" to the provided node list, or perform this operation on a different cluster node (%3$s).\n\n' "\"${nodes// /\", \"}\"" "$LOCAL_NODE" "\"${keepers// /\", \"}\"" 1>&2 rc=$RC_INCORRECT_INPUT elif [[ -z $keepers ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 445 '\nERROR: the specified node list (%1$s) does not contain any of the current cluster nodes (%3$s). This operation is not appropriate for deleting the entire cluster. Either add one or more of the current cluster nodes to the provided node list, or perform a standard cluster deletion on "%2$s", followed by a standard cluster creation on one of the new nodes.\n\n' "\"${nodes// /\", \"}\"" "$LOCAL_NODE" "\"${current_nodes// /\", \"}\"" 1>&2 rc=$RC_INCORRECT_INPUT elif [[ -z "$add_nodes$remove_nodes" ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 446 '\nERROR: the specified node list (%1$s) does not contain any changes from the current cluster nodes (%2$s).\n\n' "\"${nodes// /\", \"}\"" "\"${current_nodes// /\", \"}\"" 1>&2 rc=$RC_MISSING_INPUT fi typeset clmgr_cmd="" if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $remove_nodes ]]; then CL=$LINENO KLIB_HACMP_delete_node ${remove_nodes// /,} rc=$? if (( rc == RC_SUCCESS )); then CL=$LINENO isClusterDefined 2>>$CLMGR_TMPLOG 1>&2 if (( $? == RC_SUCCESS )); then : Indicate that the cluster has been changed print "HACMPcluster: handle=0" | odmchange -o HACMPcluster #================================================== : Update the clevents file with formatted event and : send an event upstream to the GUI server, if the : node has a running GUI agent on it #================================================== clmgr_cmd="clmgr delete node" print "$0()[$LINENO]($SECONDS): cl_send_ui_event NODE \"$LOCAL_NODE\" CHANGE \"delete node $remove_nodes\" PASSED \"A cluster configuration change was performed on cluster \\\"\$(CL=$LINENO KLIB_HACMP_get_cluster_name)\\\" : $clmgr_cmd $remove_nodes\"" >>$CLMGR_TMPLOG cl_send_ui_event NODE "$LOCAL_NODE" CHANGE "delete node $remove_nodes" PASSED "A cluster configuration change was performed on cluster \"$(CL=$LINENO KLIB_HACMP_get_cluster_name)\" : $clmgr_cmd $remove_nodes" print "$0()[$LINENO]($SECONDS): cl_send_ui_event RC: $?" >>$CLMGR_TMPLOG fi fi fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then integer added=0 for node in $add_nodes; do CL=$LINENO KLIB_HACMP_add_node null $node "" true rc=$? (( $rc != RC_SUCCESS )) && break (( added++ )) done if (( added )); then CL=$LINENO isClusterDefined 2>>$CLMGR_TMPLOG 1>&2 if (( $? == RC_SUCCESS )); then : Indicate that the cluster has been changed print "HACMPcluster: handle=0" | odmchange -o HACMPcluster #================================================== : Update the clevents file with formatted event and : send an event upstream to the GUI server, if the : node has a running GUI agent on it #================================================== clmgr_cmd="clmgr add node" print "$0()[$LINENO]($SECONDS): cl_send_ui_event NODE \"$LOCAL_NODE\" CHANGE \"add node $add_nodes\" PASSED \"A cluster configuration change was performed on cluster \\\"\$(CL=$LINENO KLIB_HACMP_get_cluster_name)\\\" : $clmgr_cmd $add_nodes\"" >>$CLMGR_TMPLOG cl_send_ui_event NODE "$LOCAL_NODE" CHANGE "add node $add_nodes" PASSED "A cluster configuration change was performed on cluster \"$(CL=$LINENO KLIB_HACMP_get_cluster_name)\" : $clmgr_cmd $add_nodes" print "$0()[$LINENO]($SECONDS): cl_send_ui_event RC: $?" >>$CLMGR_TMPLOG fi fi fi if (( $rc == RC_SUCCESS )) && [[ -n $add_nodes || -n $remove_nodes ]] then cl_dspmsg -s 32 scripts 6 "The configuration must be synchronized to make this change known across the cluster.\n" fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && \ [[ -n $lpm_policy ]] then #======================================================= : Setting LPM policy during LPM to "$lpm_policy" #======================================================= print "$0()[$LINENO]($SECONDS): odmchange -o HACMPcluster ==> lpm_policy=$lpm_policy" >>$CLMGR_TMPLOG print "HACMPcluster: lpm_policy=$lpm_policy" | odmchange -o HACMPcluster rc=$? print "$0()[$LINENO]($SECONDS): odmchange RC: $rc" >>$CLMGR_TMPLOG typeset VAL=$(clodmget -n -f lpm_policy HACMPcluster) [[ $VAL == $lpm_policy ]] && rc=$RC_SUCCESS || rc=$RC_ERROR fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && \ [[ -n $lpm_heartbeat ]] then #======================================================= : Setting node heartbeat during LPM to "$lpm_heartbeat" #======================================================= print "$0()[$LINENO]($SECONDS): odmchange -o HACMPcluster ==> lpm_node_timeout=$lpm_heartbeat" >>$CLMGR_TMPLOG print "HACMPcluster: lpm_node_timeout=$lpm_heartbeat" | odmchange -o HACMPcluster rc=$? print "$0()[$LINENO]($SECONDS): odmchange RC: $rc" >>$CLMGR_TMPLOG typeset VAL=$(clodmget -n -f lpm_node_timeout HACMPcluster) (( $VAL == $lpm_heartbeat )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi typeset -i capability=0 if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && \ [[ -n $caa_auto_start_dr ]] then if [[ $CLUSTER_TYPE != "LC" ]];then if caa_dr_capability=$(LC_ALL=C cl_get_capabilities -i CAA_DR 2>&1) \ && [[ -n $caa_dr_capability ]] then # If CAA DR capability is defined and globally available, then capability is set to 1 capability=${caa_dr_capability#*flag:} fi if (( $capability == 1 ));then print "HACMPcluster: dr_enabled=$dr_enable" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f dr_enabled HACMPcluster) (( $VAL == $dr_enable )) && rc=$RC_SUCCESS || rc=$RC_ERROR else #Just indicating user that current AIX version do not have support for CAA DR capability cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1180 "\nWARNING: CAA DR capability is not currently available in all nodes across the cluster\n" 1>&2 fi else cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1161 "\nERROR:CAA tunable dr_enabled cannot be set in linked cluster\n" 1>&2 rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $caa_repos_mode ]]; then #==================================================== : Setting repos mode to "$repos" #==================================================== print "HACMPcluster: repos_mode=$repos" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f repos_mode HACMPcluster) (( $VAL == $repos )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $caa_config_timeout ]]; then #==================================================== : Setting config timeout to "$caa_config_timeout" #==================================================== print "HACMPcluster: config_timeout=$caa_config_timeout" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f config_timeout HACMPcluster) (( $VAL == $caa_config_timeout )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $lvm_preferred_read ]]; then #==================================================== : Setting lvm_preferred_read to "$lvm_preferred_read" #==================================================== print "HACMPcluster: lvm_preferred_read=$lvm_preferred_read" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f lvm_preferred_read HACMPcluster) [[ $VAL == $lvm_preferred_read ]] && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && [[ -n $crit_daemon_restart_grace_period ]]; then #===================================================================================== : Setting critical daemon restart grace period to "$crit_daemon_restart_grace_period" #===================================================================================== print "HACMPcluster: crit_daemon_restart_grace_period=$crit_daemon_restart_grace_period" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f crit_daemon_restart_grace_period HACMPcluster) (( $VAL == $crit_daemon_restart_grace_period )) && rc=$RC_SUCCESS || rc=$RC_ERROR if (( rc == RC_SUCCESS )); then dspmsg -s 63 cluster.cat 79 "Successfully configured the cluster level RSCT Critical Resource Daemon Grace Period.\n\ Tie Breaker and other RSCT services will not work during this time. \n\ And after waiting for %1\$d seconds if daemons are not restarted, cluster nodes will be halted.\n" $crit_daemon_restart_grace_period fi fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then if [[ -n $skip_events_on_manage ]]; then #==================================================== : Setting skip_events_on_manage to "$skip_events_flag" #==================================================== print "HACMPcluster: skip_events_on_manage=$skip_events_flag" | odmchange -o HACMPcluster typeset VAL=$(clodmget -n -f skip_events_on_manage HACMPcluster) (( $VAL == $skip_events_flag )) && rc=$RC_SUCCESS || rc=$RC_ERROR fi fi #=========================================================== : If output from this operation was requested, retrieve it #=========================================================== if (( $rc == RC_SUCCESS )); then [[ -n $new_name ]] && persistent_ip=$new_name if (( CLMGR_VERBOSE )) || [[ -n $CLMGR_ATTRS ]]; then CL=$LINENO CLMGR_VERBOSE=0 KLIB_HACMP_get_cluster_attributes properties fi fi #======================================================================= : If a user input error was detected, provide some helpful suggestions #======================================================================= if (( $rc == RC_MISSING_INPUT || $rc == RC_INCORRECT_INPUT )) && \ [[ $CLMGR_GUI == *([[:space:]]) ]] then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 104 "For more information about available options and syntax, try\n\"/usr/es/sbin/cluster/utilities/clmgr %1\$s\". As an\nalternative, if the PowerHA SystemMirror man pages have been installed, invoke\n\"/usr/es/sbin/cluster/utilities/clmgr -hv\" (or \"/usr/bin/man clmgr\"),\nsearching for \"%2\$s\" in the displayed text.\n\n" \ "modify cluster -h" "CLUSTER:" "clmgr" 1>&2 fi log_return_msg "$rc" "$0()" "$LINENO" return $? } # End of "KLIB_HACMP_modify_cluster()" #============================================================================== # 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 #==============================================================================