diff --git a/RHEL-116150-1-ocf-shellfuncs-add-ocf_promotion_score.patch b/RHEL-116150-1-ocf-shellfuncs-add-ocf_promotion_score.patch new file mode 100644 index 0000000..059d505 --- /dev/null +++ b/RHEL-116150-1-ocf-shellfuncs-add-ocf_promotion_score.patch @@ -0,0 +1,19 @@ +--- a/heartbeat/ocf-shellfuncs.in 2025-09-29 14:01:55.762931795 +0200 ++++ b/heartbeat/ocf-shellfuncs.in 2025-09-29 14:09:28.651731793 +0200 +@@ -1093,6 +1093,16 @@ + echo $1 + } + ++ocf_promotion_score() { ++ ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.10.0" ++ res=$? ++ if [ $res -eq 2 ] || [ $res -eq 1 ] || ! have_binary "crm_master"; then ++ ${HA_SBIN_DIR}/crm_attribute -p ${OCF_RESOURCE_INSTANCE} $@ ++ else ++ ${HA_SBIN_DIR}/crm_master -l reboot $@ ++ fi ++} ++ + __ocf_set_defaults "$@" + + : ${OCF_TRACE_RA:=$OCF_RESKEY_trace_ra} diff --git a/RHEL-116150-2-portblock-add-promotable-support.patch b/RHEL-116150-2-portblock-add-promotable-support.patch new file mode 100644 index 0000000..0ae29e3 --- /dev/null +++ b/RHEL-116150-2-portblock-add-promotable-support.patch @@ -0,0 +1,362 @@ +--- a/heartbeat/portblock 2025-09-30 09:52:13.967530030 +0200 ++++ b/heartbeat/portblock 2025-09-30 09:52:49.018382542 +0200 +@@ -4,6 +4,7 @@ + # + # Author: Sun Jiang Dong (initial version) + # Philipp Reisner (per-IP filtering) ++# Sebastian Baszczyj (nftables code) + # + # License: GNU General Public License (GPL) + # +@@ -43,11 +44,15 @@ + ####################################################################### + CMD=`basename $0` + TICKLETCP=$HA_BIN/tickle_tcp ++TABLE="portblock" ++# Promotion scores ++SCORE_UNPROMOTED=5 ++SCORE_PROMOTED=10 + + usage() + { + cat <&2 +- usage: $CMD {start|stop|status|monitor|meta-data|validate-all} ++ usage: $CMD {start|stop|promote|demote|status|monitor|meta-data|validate-all} + + $CMD is used to temporarily block ports using iptables. + +@@ -86,8 +91,8 @@ + NOTE: iptables is Linux-specific. + + An additional feature in the portblock RA is the tickle ACK function +- enabled by specifying the tickle_dir parameter. The tickle ACK +- triggers the clients to faster reconnect their TCP connections to the ++ enabled by specifying the tickle_dir parameter. The tickle ACK ++ triggers the clients to faster reconnect their TCP connections to the + fail-overed server. + + Please note that this feature is often used for the floating IP fail- +@@ -95,7 +100,7 @@ + It doesn't support the cluster alias IP scenario. + + When using the tickle ACK function, in addition to the normal usage +- of portblock RA, the parameter tickle_dir must be specified in the ++ of portblock RA, the parameter tickle_dir must be specified in the + action=unblock instance of the portblock resources. + For example, you may stack resources like below: + portblock action=block +@@ -103,18 +108,18 @@ + portblock action=unblock tickle_dir=/tickle/state/dir + + If you want to tickle all the TCP connections which connected to _one_ +- floating IP but different ports, no matter how many portblock resources +- you have defined, you should enable tickles for _one_ portblock ++ floating IP but different ports, no matter how many portblock resources ++ you have defined, you should enable tickles for _one_ portblock + resource(action=unblock) only. +- +- The tickle_dir is a location which stores the established TCP +- connections. It can be a shared directory(which is cluster-visible to ++ ++ The tickle_dir is a location which stores the established TCP ++ connections. It can be a shared directory(which is cluster-visible to + all nodes) or a local directory. + If you use the shared directory, you needn't do any other things. + If you use the local directory, you must also specify the sync_script + paramater. We recommend you to use csync2 as the sync_script. +- For example, if you use the local directory /tmp/tickle as tickle_dir, +- you could setup the csync2 as the csync2 documentation says and ++ For example, if you use the local directory /tmp/tickle as tickle_dir, ++ you could setup the csync2 as the csync2 documentation says and + configure your /etc/csync2/csync2.cfg like: + group ticklegroup { + host node1; +@@ -137,15 +142,19 @@ + 1.0 + + +-Resource script for portblock. It is used to temporarily block ports ++Resource script for portblock. It is used to block ports + using iptables. In addition, it may allow for faster TCP reconnects + for clients on failover. Use that if there are long lived TCP + connections to an HA service. This feature is enabled by setting the + tickle_dir parameter and only in concert with action set to unblock. + Note that the tickle ACK function is new as of version 3.0.2 and + hasn't yet seen widespread use. ++ ++In Promotable mode, the promote action unblocks the port(s) on the Promoted node ++and blocks the port(s) on the Unpromoted node(s) when action=unblock, and vice versa ++when action=block. + +-Block and unblocks access to TCP and UDP ports ++Blocks and unblocks access to TCP and UDP ports + + + +@@ -167,6 +176,10 @@ + + + The action (block/unblock) to be done on the protocol::portno. ++ ++In Promotable mode it is the action for the promote action, ++and the opposite action will be used for the start and demote ++actions. + + action + +@@ -202,7 +215,7 @@ + + + +-The shared or local directory (_must_ be absolute path) which ++The shared or local directory (_must_ be absolute path) which + stores the established TCP connections. + + Tickle directory +@@ -236,6 +249,8 @@ + + + ++ ++ + + + +@@ -269,9 +284,9 @@ + # iptables 1.8.9 briefly broke the output format, returning the + # numeric protocol value instead of a string. Support both variants. + if [ "$1" = "tcp" ]; then +- local prot="(tcp|6)" ++ local prot="\(tcp\|6\)" + else +- local prot="(udp|17)" ++ local prot="\(udp\|17\)" + fi + echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$" + } +@@ -281,7 +296,7 @@ + { + [ "$4" = "OUTPUT" ] && ds="s" || ds="d" + PAT=$(active_grep_pat "$1" "$2" "$3" "$ds") +- $IPTABLES $wait -n -L "$4" | grep -qE "$PAT" ++ $IPTABLES $wait -n -L "$4" | grep -q "$PAT" + } + + # netstat -tn and ss -Htn, split on whitespace and colon, +@@ -397,6 +412,17 @@ + rc=$OCF_NOT_RUNNING + ;; + esac ++ elif ocf_is_ms; then ++ case $5 in ++ block) ++ SayInactive $* ++ rc=$OCF_NOT_RUNNING ++ ;; ++ *) ++ SayActive $* ++ rc=$OCF_SUCCESS ++ ;; ++ esac + else + case $5 in + block) +@@ -493,18 +519,21 @@ + { + ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" start + case $5 in +- block) IptablesBLOCK "$@";; ++ block) IptablesBLOCK "$@" ++ rc=$? ++ ;; + unblock) + IptablesUNBLOCK "$@" + rc=$? + tickle_remote + #ignore run_tickle_tcp exit code! +- return $rc + ;; +- *) usage; return 1; ++ *) usage; return $OCF_ERR_CONFIGURED ; + esac + +- return $? ++ ocf_is_ms && ocf_promotion_score -v $SCORE_UNPROMOTED -N $nodename ++ ++ return $rc + } + + #IptablesStop {udp|tcp} portno,portno ip {in|out|both} {block|unblock} +@@ -512,17 +541,73 @@ + { + ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" stop + case $5 in +- block) IptablesUNBLOCK "$@";; ++ block) IptablesUNBLOCK "$@" ++ rc=$? ++ ;; + unblock) + save_tcp_connections + IptablesBLOCK "$@" ++ rc=$? + ;; +- *) usage; return 1;; ++ *) usage; return $OCF_ERR_CONFIGURED ;; + esac + ++ ocf_is_ms && ocf_promotion_score -D -N $nodename ++ ++ return $rc ++} ++ ++IptablesPromote() { ++ IptablesStatus "$@" ++ rc=$? ++ if [ $rc -eq $OCF_SUCCESS ] && [ $promotion_score -eq $SCORE_PROMOTED ]; then ++ ocf_log info "Promote: resource already promoted." ++ return $rc ++ elif [ $rc -ne $OCF_SUCCESS ] && [ $rc -ne $OCF_NOT_RUNNING ]; then ++ ocf_exit_reason "Promote: IptablesStatus failed with rc: $rc." ++ return $rc ++ fi ++ case $5 in ++ block) IptablesBLOCK "$@" ++ rc=$? ++ ;; ++ unblock) ++ IptablesUNBLOCK "$@" ++ rc=$? ++ tickle_remote ++ #ignore run_tickle_tcp exit code! ++ ;; ++ *) usage; return $OCF_ERR_CONFIGURED ; ++ esac ++ ocf_promotion_score -v $SCORE_PROMOTED -N $nodename + return $? + } + ++IptablesDemote() { ++ IptablesStatus "$@" ++ rc=$? ++ if [ $rc -eq $OCF_SUCCESS ] && [ $promotion_score -eq $SCORE_UNPROMOTED ]; then ++ ocf_log info "Demote: resource already demoted." ++ return $rc ++ elif [ $rc -ne $OCF_SUCCESS ] && [ $rc -ne $OCF_NOT_RUNNING ]; then ++ ocf_exit_reason "Demote: IptablesStatus failed with rc: $rc." ++ return $rc ++ fi ++ case $5 in ++ block) ++ save_tcp_connections ++ IptablesBLOCK "$@" ++ rc=$? ++ ;; ++ unblock) IptablesUNBLOCK "$@" ++ rc=$? ++ ;; ++ *) usage; return $OCF_ERR_CONFIGURED ;; ++ esac ++ ocf_promotion_score -v $SCORE_UNPROMOTED -N $nodename ++ return $rc ++} ++ + # + # Check if the port is valid, this function code is not decent, but works + # +@@ -558,17 +643,17 @@ + fi + if [ ! -d "$OCF_RESKEY_tickle_dir" ]; then + ocf_log err "The tickle dir doesn't exist!" +- exit $OCF_ERR_INSTALLED ++ exit $OCF_ERR_INSTALLED + fi + fi + + case $action in +- block|unblock) ++ block|unblock) + ;; +- *) ++ *) + ocf_log err "Invalid action $action!" + exit $OCF_ERR_CONFIGURED +- ;; ++ ;; + esac + + if ocf_is_true $reset_local_on_unblock_stop; then +@@ -591,7 +676,7 @@ + exit $OCF_ERR_ARGS + fi + +-case $1 in ++case $__OCF_ACTION in + meta-data) meta_data + exit $OCF_SUCCESS + ;; +@@ -605,12 +690,12 @@ + if [ -z "$OCF_RESKEY_protocol" ]; then + ocf_log err "Please set OCF_RESKEY_protocol" + exit $OCF_ERR_CONFIGURED +-fi ++fi + + if [ -z "$OCF_RESKEY_portno" ]; then + ocf_log err "Please set OCF_RESKEY_portno" + exit $OCF_ERR_CONFIGURED +-fi ++fi + + if [ -z "$OCF_RESKEY_action" ]; then + ocf_log err "Please set OCF_RESKEY_action" +@@ -632,6 +717,7 @@ + action=$OCF_RESKEY_action + ip=$OCF_RESKEY_ip + reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop ++nodename=$(ocf_local_nodename) + + + # If "tickle" is enabled, we need to record the list of currently established +@@ -647,17 +733,35 @@ + fi + fi + +-case $1 in +- start) +- IptablesStart $protocol $portno $ip $direction $action ++if ocf_is_ms; then ++ promotion_score=$(ocf_promotion_score -G -N $nodename -q 2> /dev/null) ++ if { [ "$__OCF_ACTION" = "monitor" ] && [ "$promotion_score" = "$SCORE_UNPROMOTED" ]; } || [ "$__OCF_ACTION" = "demote" ] || [ "$__OCF_ACTION" = "start" ]; then ++ case $action in ++ block) action="unblock" ;; ++ unblock) action="block" ;; ++ esac ++ fi ++fi ++ ++case $__OCF_ACTION in ++ start) ++ IptablesStart "$protocol" "$portno" "$ip" "$direction" "$action" ++ ;; ++ ++ stop) ++ IptablesStop "$protocol" "$portno" "$ip" "$direction" "$action" ++ ;; ++ ++ promote) ++ IptablesPromote "$protocol" "$portno" "$ip" "$direction" "$action" + ;; + +- stop) +- IptablesStop $protocol $portno $ip $direction $action ++ demote) ++ IptablesDemote "$protocol" "$portno" "$ip" "$direction" "$action" + ;; + +- status|monitor) +- IptablesStatus $protocol $portno $ip $direction $action ++ status|monitor) ++ IptablesStatus "$protocol" "$portno" "$ip" "$direction" "$action" + ;; + + validate-all) diff --git a/RHEL-116150-3-portblock-fixes-add-method-and-status_check-parameters.patch b/RHEL-116150-3-portblock-fixes-add-method-and-status_check-parameters.patch new file mode 100644 index 0000000..39a7da3 --- /dev/null +++ b/RHEL-116150-3-portblock-fixes-add-method-and-status_check-parameters.patch @@ -0,0 +1,180 @@ +--- a/heartbeat/portblock 2025-10-21 09:27:41.753028260 +0200 ++++ b/heartbeat/portblock 2025-10-21 09:28:55.573855995 +0200 +@@ -28,6 +28,8 @@ + OCF_RESKEY_portno_default="" + OCF_RESKEY_direction_default="in" + OCF_RESKEY_action_default="" ++OCF_RESKEY_method_default="drop" ++OCF_RESKEY_status_check_default="rule" + OCF_RESKEY_ip_default="0.0.0.0/0" + OCF_RESKEY_reset_local_on_unblock_stop_default="false" + OCF_RESKEY_tickle_dir_default="" +@@ -37,6 +39,8 @@ + : ${OCF_RESKEY_portno=${OCF_RESKEY_portno_default}} + : ${OCF_RESKEY_direction=${OCF_RESKEY_direction_default}} + : ${OCF_RESKEY_action=${OCF_RESKEY_action_default}} ++: ${OCF_RESKEY_method=${OCF_RESKEY_method_default}} ++: ${OCF_RESKEY_status_check=${OCF_RESKEY_status_check_default}} + : ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}} + : ${OCF_RESKEY_reset_local_on_unblock_stop=${OCF_RESKEY_reset_local_on_unblock_stop_default}} + : ${OCF_RESKEY_tickle_dir=${OCF_RESKEY_tickle_dir_default}} +@@ -185,6 +189,26 @@ + + + ++ ++ ++Block method: ++drop: Use DROP rule. ++reject: Use REJECT rule w/conntrack to clear connections when blocking. ++ ++Block method ++ ++ ++ ++ ++ ++Status check: ++rule: Check rule. ++pseudo: Check pseudo status when rule is absent. ++ ++Status check ++ ++ ++ + + + If for some reason the long lived server side TCP sessions won't be cleaned up +@@ -253,6 +277,7 @@ + + + ++ + + + +@@ -288,7 +313,11 @@ + else + local prot="\(udp\|17\)" + fi +- echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$" ++ if [ "$method" = "DROP" ]; then ++ echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$" ++ else ++ echo "^REJECT${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}${w}ctstate${w}NEW,RELATED,ESTABLISHED${w}reject-with${w}tcp-reset$" ++ fi + } + + #chain_isactive {udp|tcp} portno,portno ip chain +@@ -374,17 +403,17 @@ + + SayActive() + { +- ocf_log debug "$CMD DROP rule [$*] is running (OK)" ++ ocf_log debug "$CMD $method rule [$*] is running (OK)" + } + + SayConsideredActive() + { +- ocf_log debug "$CMD DROP rule [$*] considered to be running (OK)" ++ ocf_log debug "$CMD $method rule [$*] considered to be running (OK)" + } + + SayInactive() + { +- ocf_log debug "$CMD DROP rule [$*] is inactive" ++ ocf_log debug "$CMD $method rule [$*] is inactive" + } + + #IptablesStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock} +@@ -405,14 +434,18 @@ + case $5 in + block) + SayActive $* +- rc=$OCF_SUCCESS ++ if [ "$__OCF_ACTION" = "monitor" ] && [ "$promotion_score" = "$SCORE_PROMOTED" ]; then ++ rc=$OCF_RUNNING_MASTER ++ else ++ rc=$OCF_SUCCESS ++ fi + ;; + *) + SayInactive $* + rc=$OCF_NOT_RUNNING + ;; + esac +- elif ocf_is_ms; then ++ elif [ "$OCF_RESKEY_status_check" = "rule" ]; then + case $5 in + block) + SayInactive $* +@@ -420,7 +453,11 @@ + ;; + *) + SayActive $* +- rc=$OCF_SUCCESS ++ if [ "$__OCF_ACTION" = "monitor" ] && [ "$promotion_score" = "$SCORE_PROMOTED" ]; then ++ rc=$OCF_RUNNING_MASTER ++ else ++ rc=$OCF_SUCCESS ++ fi + ;; + esac + else +@@ -461,7 +498,11 @@ + : Chain already in desired state + else + [ "$chain" = "OUTPUT" ] && ds="s" || ds="d" +- $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -j DROP ++ if [ "$method" = "DROP" ]; then ++ $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -j DROP ++ else ++ $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j REJECT --reject-with tcp-reset ++ fi + fi + } + +@@ -486,7 +527,11 @@ + $IPTABLES $wait -I OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset + tickle_local + fi +- $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP ++ if [ "$method" = "DROP" ]; then ++ $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP ++ else ++ $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j REJECT --reject-with tcp-reset ++ fi + rc_in=$? + if $try_reset ; then + $IPTABLES $wait -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset +@@ -718,6 +763,13 @@ + ip=$OCF_RESKEY_ip + reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop + nodename=$(ocf_local_nodename) ++case "$OCF_RESKEY_method" in ++ drop) method="DROP" ;; ++ reject) method="REJECT" ;; ++ *) ocf_log err "method: $OCF_RESKEY_method not supported" ++ exit $OCF_ERR_CONFIGURED ++ ;; ++esac + + + # If "tickle" is enabled, we need to record the list of currently established +@@ -743,6 +795,8 @@ + fi + fi + ++IptablesValidateAll ++ + case $__OCF_ACTION in + start) + IptablesStart "$protocol" "$portno" "$ip" "$direction" "$action" +@@ -765,7 +819,6 @@ + ;; + + validate-all) +- IptablesValidateAll + ;; + + *) usage diff --git a/resource-agents.spec b/resource-agents.spec index d4138fe..198d555 100644 --- a/resource-agents.spec +++ b/resource-agents.spec @@ -73,7 +73,7 @@ Name: resource-agents Summary: Open Source HA Reusable Cluster Resource Scripts Version: 4.9.0 -Release: 54%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}.19 +Release: 54%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}.20 License: GPLv2+ and LGPLv2+ URL: https://github.com/ClusterLabs/resource-agents %if 0%{?fedora} || 0%{?centos_version} || 0%{?rhel} @@ -175,6 +175,9 @@ Patch78: RHEL-91257-Filesystem-add-support-for-aznfs.patch Patch79: RHEL-102731-ocf-shellfuncs-remove-extra-sleep-from-curl_retry.patch Patch80: RHEL-115783-RHEL-115781-db2-add-skip_basic_sql_health_check-and-monitor-parameters.patch Patch81: RHEL-118625-db2-use-reintegration-flag-to-avoid-race-condition-on-cluster-reintegration.patch +Patch82: RHEL-116150-1-ocf-shellfuncs-add-ocf_promotion_score.patch +Patch83: RHEL-116150-2-portblock-add-promotable-support.patch +Patch84: RHEL-116150-3-portblock-fixes-add-method-and-status_check-parameters.patch # bundle patches Patch1000: 7-gcp-bundled.patch @@ -441,6 +444,9 @@ exit 1 %patch -p1 -P 79 %patch -p1 -P 80 %patch -p1 -P 81 -F2 +%patch -p1 -P 82 +%patch -p1 -P 83 +%patch -p1 -P 84 chmod 755 heartbeat/nova-compute-wait chmod 755 heartbeat/NovaEvacuate @@ -1031,6 +1037,12 @@ ccs_update_schema > /dev/null 2>&1 ||: %{_usr}/lib/ocf/lib/heartbeat/OCF_*.pm %changelog +* Tue Oct 21 2025 Oyvind Albrigtsen - 4.9.0-54.20 +- portblock: add promotable support, and method and status_check + parameters + + Resolves: RHEL-116150 + * Mon Oct 20 2025 Oyvind Albrigtsen - 4.9.0-54.19 - db2: use reintegration flag to avoid race condition on cluster reintegration