Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package resource-agents for openSUSE:Factory
checked in at 2026-02-27 17:03:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/resource-agents (Old)
and /work/SRC/openSUSE:Factory/.resource-agents.new.29461 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "resource-agents"
Fri Feb 27 17:03:21 2026 rev:147 rq:1335169 version:4.17.0+git42.a607c299
Changes:
--------
--- /work/SRC/openSUSE:Factory/resource-agents/resource-agents.changes
2026-01-28 15:08:50.434223749 +0100
+++
/work/SRC/openSUSE:Factory/.resource-agents.new.29461/resource-agents.changes
2026-02-27 17:07:49.342923240 +0100
@@ -1,0 +2,12 @@
+Wed Feb 25 10:46:27 UTC 2026 - Peter Varkoly <[email protected]>
+
+- Update to version 4.17.0+git42.a607c299:
+ * IPaddr2: fix find_interface output
+ * IPsrcaddr: fix grep expression, so it doesnt log "stray \ before white
space" with newer versions of grep
+ * podman-etcd: fix learner node attribute not set after etcdctl failure
+ * docker: improve image existence check (#2121)
+ * portblock: check correct binary during validate-all
+ * send_arp.linux/tickle_tcp: better alpine compatibility (#2119)
+ * podman-etcd: enhance etcd data backup with snapshots and retention
+
+-------------------------------------------------------------------
Old:
----
resource-agents-4.17.0+git30.b33c378d.tar.xz
New:
----
resource-agents-4.17.0+git42.a607c299.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ resource-agents.spec ++++++
--- /var/tmp/diff_new_pack.i2lgEv/_old 2026-02-27 17:07:50.166957391 +0100
+++ /var/tmp/diff_new_pack.i2lgEv/_new 2026-02-27 17:07:50.170957557 +0100
@@ -17,7 +17,7 @@
Name: resource-agents
-Version: 4.17.0+git30.b33c378d
+Version: 4.17.0+git42.a607c299
Release: 0
Summary: HA Reusable Cluster Resource Scripts
License: GPL-2.0-only AND LGPL-2.1-or-later AND GPL-3.0-or-later
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.i2lgEv/_old 2026-02-27 17:07:50.266961536 +0100
+++ /var/tmp/diff_new_pack.i2lgEv/_new 2026-02-27 17:07:50.270961701 +0100
@@ -1,7 +1,7 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://github.com/ClusterLabs/resource-agents.git</param>
-<param name="changesrevision">b33c378db3a04709a276a436606105e52a946116</param>
+<param name="changesrevision">a607c299ba7784ab30511da0b0445a99396a2e3e</param>
</service>
</servicedata>
(No newline at EOF)
++++++ resource-agents-4.17.0+git30.b33c378d.tar.xz ->
resource-agents-4.17.0+git42.a607c299.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/heartbeat/IPaddr2
new/resource-agents-4.17.0+git42.a607c299/heartbeat/IPaddr2
--- old/resource-agents-4.17.0+git30.b33c378d/heartbeat/IPaddr2 2026-01-22
08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/heartbeat/IPaddr2 2026-02-24
09:59:15.000000000 +0100
@@ -660,9 +660,10 @@
| grep " $ipaddr/$netmask" \
| cut -d ' ' -f2 \
| grep -v '^ipsec[0-9][0-9]*$'`"
- local iface_altname="`$IP2UTIL -f inet link show dev $iface | grep
"altname" | sed 's/^[[:space:]]*//; s/altname //g' | tr '\n' ' '`"
-
- echo "$iface $iface_altname"
+ if [ -n "$iface" ]; then
+ local iface_altname="`$IP2UTIL -f inet link show dev $iface |
grep "altname" | sed 's/^[[:space:]]*//; s/altname //g' | tr '\n' ' '`"
+ echo "$iface $iface_altname"
+ fi
return 0
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/heartbeat/IPsrcaddr
new/resource-agents-4.17.0+git42.a607c299/heartbeat/IPsrcaddr
--- old/resource-agents-4.17.0+git30.b33c378d/heartbeat/IPsrcaddr
2026-01-22 08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/heartbeat/IPsrcaddr
2026-02-24 09:59:15.000000000 +0100
@@ -434,7 +434,7 @@
# is an (aliased) interface name (e.g., "eth0" and "eth0:0").
#
find_interface_generic() {
- local iface=`$IP2UTIL -o -f $FAMILY addr show | grep "\ $BASEIP" \
+ local iface=`$IP2UTIL -o -f $FAMILY addr show | grep " $BASEIP" \
| cut -d ' ' -f2 | grep -v '^ipsec[0-9][0-9]*$'`
if [ -z "$iface" ]; then
return $OCF_ERR_GENERIC
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/heartbeat/docker
new/resource-agents-4.17.0+git42.a607c299/heartbeat/docker
--- old/resource-agents-4.17.0+git30.b33c378d/heartbeat/docker 2026-01-22
08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/heartbeat/docker 2026-02-24
09:59:15.000000000 +0100
@@ -495,36 +495,38 @@
local IMAGE_NAME="${OCF_RESKEY_image}"
local IMAGE_TAG="latest"
+ # try to extract server name before tag, as it might also contain a
colon (server:port/image:tag)
SLASH_FOUND="$(echo "${OCF_RESKEY_image}" | grep -o '/' | grep -c .)"
-
if [ ${SLASH_FOUND} -ge 1 ]; then
SERVER_NAME="$(echo ${IMAGE_NAME} | cut -d / -f
1-${SLASH_FOUND})"
IMAGE_NAME="$(echo ${IMAGE_NAME} | awk -F'/' '{print $NF}')"
fi
+ # extract image tag if specified
COLON_FOUND="$(echo "${IMAGE_NAME}" | grep -o ':' | grep -c .)"
if [ ${COLON_FOUND} -ge 1 ]; then
IMAGE_TAG="$(echo ${IMAGE_NAME} | awk -F':' '{print $NF}')"
IMAGE_NAME="$(echo ${IMAGE_NAME} | cut -d : -f
1-${COLON_FOUND})"
fi
- # IMAGE_NAME might be following formats:
+ # Check for existence of image, which might be in following formats:
# - image
- # - repository:port/image
+ # - server_name/image (as extracted above)
# - docker.io/image (some distro will display "docker.io/" as prefix)
- docker images | awk '{print $1 ":" $2}' | $EGREP -q -s
"^(docker.io\/|${SERVER_NAME}\/)?${IMAGE_NAME}:${IMAGE_TAG}\$"
+ docker image ls --all --format '{{.Repository}}:{{.Tag}}' | $EGREP -q
-s "^(docker.io\/|${SERVER_NAME}\/)?${IMAGE_NAME}:${IMAGE_TAG}\$"
if [ $? -eq 0 ]; then
# image found
- return 0
+ return $OCF_SUCCESS
fi
if ocf_is_true "$OCF_RESKEY_allow_pull"; then
REQUIRE_IMAGE_PULL=1
ocf_log notice "Image (${OCF_RESKEY_image}) does not exist
locally but will be pulled during start"
- return 0
+ return $OCF_SUCCESS
fi
+
# image not found.
- return 1
+ return $OCF_ERR_ARGS
}
docker_validate()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/heartbeat/podman-etcd
new/resource-agents-4.17.0+git42.a607c299/heartbeat/podman-etcd
--- old/resource-agents-4.17.0+git30.b33c378d/heartbeat/podman-etcd
2026-01-22 08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/heartbeat/podman-etcd
2026-02-24 09:59:15.000000000 +0100
@@ -49,6 +49,7 @@
OCF_RESKEY_oom_default="-997"
OCF_RESKEY_config_location_default="/var/lib/etcd"
OCF_RESKEY_backup_location_default="/var/lib/etcd"
+OCF_RESKEY_max_backup_snapshots_default="3"
: ${OCF_RESKEY_image=${OCF_RESKEY_image_default}}
: ${OCF_RESKEY_pod_manifest=${OCF_RESKEY_pod_manifest_default}}
@@ -61,6 +62,7 @@
: ${OCF_RESKEY_oom=${OCF_RESKEY_oom_default}}
: ${OCF_RESKEY_config_location=${OCF_RESKEY_config_location_default}}
: ${OCF_RESKEY_backup_location=${OCF_RESKEY_backup_location_default}}
+: ${OCF_RESKEY_max_backup_snapshots=${OCF_RESKEY_max_backup_snapshots_default}}
#######################################################################
@@ -275,6 +277,17 @@
<content type="string" default="${OCF_RESKEY_backup_location_default}"/>
</parameter>
+<parameter name="max_backup_snapshots" required="0" unique="0">
+<longdesc lang="en">
+Maximum number of etcd database snapshots to retain. When a new snapshot is
created,
+older snapshots will be automatically removed to maintain this limit. This
helps
+control storage usage while ensuring recent backups are available for recovery.
+Set max_backup_snapshots=0 to disable backups.
+</longdesc>
+<shortdesc lang="en">Maximum number of backup snapshots to retain</shortdesc>
+<content type="integer" default="${OCF_RESKEY_max_backup_snapshots_default}"/>
+</parameter>
+
</parameters>
<actions>
@@ -720,20 +733,190 @@
return $OCF_SUCCESS
}
+# Remove etcd member directory to allow the node to rejoin the cluster as a
learner.
+#
+# When a node rejoins an etcd cluster, it must start fresh as a learner to
prevent
+# data inconsistencies. This function removes the member directory and syncs
to disk.
+#
+# Returns:
+# OCF_SUCCESS - Member directory successfully removed
+# OCF_ERR_GENERIC - Failed to remove member directory (critical error)
+wipe_data_folder_for_learner()
+{
+ ocf_log info "deleting etcd member directory ($ETCD_MEMBER_DIR) to
enable learner rejoin"
+ if ! rm -rf "$ETCD_MEMBER_DIR"; then
+ ocf_log err "could not delete etcd member directory
($ETCD_MEMBER_DIR), error code: $?"
+ return $OCF_ERR_GENERIC
+ fi
+ sync
+ return $OCF_SUCCESS
+}
+
+
+# Calculate available disk space in bytes for a given directory.
+#
+# This function queries the filesystem and returns available space in bytes.
+# It converts df output (KB) to bytes for consistent size comparisons.
+#
+# Arguments:
+# $1 - Target directory path to check
+#
+# Returns:
+# OCF_SUCCESS - Available space in bytes (via stdout)
+# OCF_ERR_GENERIC - Failed to determine available space (error message via
stdout)
+get_available_space_in_directory()
+{
+ local target_dir=$1
+ local available_space_kb
+ local available_space_bytes
+
+ available_space_kb=$(df -P "$target_dir" | awk 'NR==2 {print $4}' 2>&1)
+
+ # Validate output is numeric
+ if ! echo "$available_space_kb" | grep -q '^[0-9]\+$'; then
+ echo "df command failed or returned invalid value:
$available_space_kb"
+ return $OCF_ERR_GENERIC
+ fi
+
+ available_space_bytes=$((available_space_kb*1024))
+ echo "$available_space_bytes"
+ return $OCF_SUCCESS
+}
+
+# Archive etcd database with backup and cleanup
+#
+# This function creates a backup copy of the etcd database, validates it, and
+# removes old backups according to the retention policy. Backups are optional
+# and can be disabled by setting max_backup_snapshots=0.
+#
+# Error handling strategy:
+# All backup failures return OCF_SUCCESS to prevent blocking cluster
recovery.
+# Backups are beneficial but not critical for recovery operations.
+#
+# NOTE: This function cannot use etcdctl/etcdutl utilities because the etcd
+# server is not running when this backup is performed.
archive_data_folder()
{
- # TODO: use etcd snapshots
- local dest_dir_name
- local data_dir="/var/lib/etcd/member"
-
- dest_dir_name="members-snapshot-$(date +%Y%M%d%H%M%S)"
- if [ ! -d $data_dir ]; then
- ocf_log info "no data dir to backup"
+ local backup_dir="$OCF_RESKEY_backup_location"
+ local etcd_db_path="$ETCD_MEMBER_DIR/snap/db"
+
+ if [ "$OCF_RESKEY_max_backup_snapshots" -eq 0 ]; then
+ ocf_log debug "etcd backup disabled (max_backup_snapshots=0)"
return $OCF_SUCCESS
fi
- ocf_log info "backing up $data_dir under $HA_RSCTMP/$dest_dir_name"
- mv "$data_dir" "$HA_RSCTMP/$dest_dir_name"
- sync
+
+ # Check if the etcd database file exists
+ if [ ! -f "$etcd_db_path" ]; then
+ ocf_log warn "backup skipped: etcd database file not found at
'$etcd_db_path'"
+ return $OCF_SUCCESS
+ fi
+
+ # Ensure backup directory exists
+ if [ ! -d "$backup_dir" ]; then
+ ocf_log debug "creating backup directory: '$backup_dir'"
+ if ! mkdir -p "$backup_dir"; then
+ ocf_log warn "backup skipped: failed to create backup
directory '$backup_dir'"
+ return $OCF_SUCCESS
+ fi
+ fi
+
+ ocf_log debug "checking disk space: backup_dir=$backup_dir"
+ local available_space_bytes
+ if ! available_space_bytes=$(get_available_space_in_directory
"$backup_dir"); then
+ ocf_log warn "backup skipped: could not compute available disk
space in '$backup_dir', error msg: $available_space_bytes"
+ return $OCF_SUCCESS
+ fi
+
+ local required_space_bytes
+ required_space_bytes=$(stat -c %s "$etcd_db_path" 2>&1)
+ if ! echo "$required_space_bytes" | grep -q '^[0-9]\+$'; then
+ ocf_log warn "backup skipped: could not compute etcd database
size at '$etcd_db_path', error msg: $required_space_bytes"
+ return $OCF_SUCCESS
+ fi
+
+ if [ "$required_space_bytes" -gt "$available_space_bytes" ]; then
+ ocf_log warn "backup skipped: insufficient disk space
(required: ${required_space_bytes}B, available: ${available_space_bytes}B)"
+ return $OCF_SUCCESS
+ fi
+
+ # Generate timestamp and backup filename
+ local timestamp
+ timestamp=$(date +%Y%m%d-%H%M%S)
+
+ local backup_file
+ backup_file="$backup_dir/snapshot-$timestamp.db"
+
+ ocf_log info "creating etcd database backup: '$backup_file'"
+
+ # Create the backup by copying the database file (enable Copy-on-Write
copy)
+ if ! cp --reflink=auto "$etcd_db_path" "$backup_file"; then
+ ocf_log warn "backup creation failed: could not copy
'$etcd_db_path' to '$backup_file', error code: $?"
+ return $OCF_SUCCESS
+ fi
+
+ # Validate the backup file exists and has the expected size
+ if [ ! -f "$backup_file" ]; then
+ ocf_log warn "backup validation failed: snapshot file
'$backup_file' does not exist"
+ return $OCF_SUCCESS
+ fi
+
+ local backup_size_bytes
+ backup_size_bytes=$(stat -c %s "$backup_file" 2>/dev/null || echo "0")
+ if [ "$backup_size_bytes" -ne "$required_space_bytes" ]; then
+ ocf_log warn "backup validation failed: size mismatch
(expected: ${required_space_bytes}B, got: ${backup_size_bytes}B)"
+ rm -f "$backup_file"
+ return $OCF_SUCCESS
+ fi
+
+ ocf_log info "backup created successfully: $backup_file
(${backup_size_bytes}B)"
+
+ # Cleanup old backups based on retention policy
+ cleanup_old_backups "$backup_dir"
+
+ return $OCF_SUCCESS
+}
+
+cleanup_old_backups()
+{
+ local backup_dir="$1"
+ local max_snapshots="$OCF_RESKEY_max_backup_snapshots"
+ local backup_count
+ local backups_to_remove
+ local old_backups
+
+ # Validate max_snapshots is a positive integer
+ if ! echo "$max_snapshots" | grep -q '^[1-9][0-9]*$'; then
+ ocf_log warn "invalid max_backup_snapshots value. Positive
integer expected, got '$max_snapshots' instead, skipping cleanup"
+ return $OCF_SUCCESS
+ fi
+
+ # Count existing backup files
+ backup_count=$(find "$backup_dir" -maxdepth 1 -name "snapshot-*.db"
-type f 2>/dev/null | wc -l)
+
+ if [ "$backup_count" -le "$max_snapshots" ]; then
+ ocf_log info "backup count ($backup_count) is within retention
limit ($max_snapshots), no cleanup needed"
+ return $OCF_SUCCESS
+ fi
+
+ # Calculate how many backups to remove
+ backups_to_remove=$((backup_count - max_snapshots))
+ ocf_log info "removing $backups_to_remove old backup(s) to maintain
retention limit of $max_snapshots"
+
+ # Find oldest backups sorted by modification time
+ # -t sorts by modification time, -r reverses (oldest first)
+ # -print0 and -0 handle filenames with spaces/special characters
+ old_backups=$(find "$backup_dir" -maxdepth 1 -name "snapshot-*.db"
-type f -print0 2>/dev/null | \
+ xargs -0 -r ls -tr | \
+ head -n "$backups_to_remove")
+
+ if [ -n "$old_backups" ]; then
+ ocf_log info "removing old backups: $old_backups"
+ if ! echo "$old_backups" | xargs -r rm -f; then
+ ocf_log warn "failed to remove some old backups, error
code: $?"
+ fi
+ fi
+
+ return $OCF_SUCCESS
}
etcd_pod_container_exists() {
@@ -899,7 +1082,7 @@
local peer_url=$(ip_url $member_ip)
ocf_log info "add $member_name ($member_ip) to the member list as
learner"
- out=$(podman exec "${CONTAINER}" etcdctl
--endpoints="$endpoint_url:2379" member add "$member_name"
--peer-urls="$peer_url:2380" --learner)
+ out=$(podman exec "${CONTAINER}" etcdctl
--endpoints="$endpoint_url:2379" member add "$member_name"
--peer-urls="$peer_url:2380" --learner 2>&1)
rc=$?
if [ $rc -ne 0 ]; then
ocf_log err "could not add $member_name as learner, error code
$rc, etcdctl output: $out"
@@ -1246,10 +1429,22 @@
manage_peer_membership()
{
local member_list_json="$1"
+ local peer_ip_map_entry
+ local peer_member_name
+ local peer_member_ip
+ local peer_member_id
+
+ # Get peer node name and IP
+ peer_ip_map_entry=$(echo "$OCF_RESKEY_node_ip_map" | tr ';' '\n' | grep
-vF "$NODENAME")
+ if [ -z "$peer_ip_map_entry" ]; then
+ ocf_exit_reason "manage_peer_membership: could not parse
node_ip_map: '$OCF_RESKEY_node_ip_map'"
+ exit $OCF_ERR_CONFIGURED
+ fi
+ peer_member_name=$(echo "$peer_ip_map_entry" | cut -d: -f1)
+ peer_member_ip=$(echo "$peer_ip_map_entry" | cut -d: -f2-)
- # Example of .members[] instance fields in member list json format:
- # NOTE that "name" is present in voting members only, while "isLearner"
in learner members only
- # and the value is always true (not a string) in that case.
+ # Parsing the member list's json output to find a "learner" member.
+ # Example of .members[] instance fields in member list json format:
# {
# "ID": <member ID>,
# "name": "<node hostname>",
@@ -1260,26 +1455,28 @@
# "https://<node IP>:2379"
# ]
# }
- for node in $(echo "$OCF_RESKEY_node_ip_map" | sed "s/\s//g;s/;/ /g");
do
- name=$(echo "$node" | cut -d: -f1)
- # do not check itself
- if [ "$name" = "$NODENAME" ]; then
- continue
- fi
+ # NOTE that the "name" field is present in voting members only, while
"isLearner"
+ # field in learner members only and the value is always true (not a
string) in that case.
+ peer_member_id=$(printf "%s" "$member_list_json" | jq -r ".members[] |
select( .peerURLs | map(test(\"$peer_member_ip\")) | any).ID")
+ if [ -z "$peer_member_id" ]; then
+ ocf_log info "$peer_member_name is not in the members list"
+ add_member_as_learner "$peer_member_name" "$peer_member_ip"
+ set_standalone_node
+ return
+ fi
- # Check by IP instead of Name since "learner" members appear
only in peerURLs, not by Name.
- ip=$(echo "$node" | cut -d: -f2-) # Grab everything after the
first : this covers ipv4/ipv6
- peer_member_id=$(printf "%s" "$member_list_json" | jq -r
".members[] | select( .peerURLs | map(test(\"$ip\")) | any).ID")
- if [ -z "$peer_member_id" ]; then
- ocf_log info "$name is not in the members list"
- add_member_as_learner "$name" "$ip"
- set_standalone_node
- else
- ocf_log debug "$name is in the members list by IP: $ip"
- # Errors from reconcile_member_state are logged
internally. Ignoring them here prevents stopping a healthy voter agent;
critical local failures are caught by detect_cluster_leadership_loss.
- reconcile_member_state "$member_list_json"
- fi
- done
+ # Ensure learner_node attribute is always set when we have a learner
member
+ local learner_member_id=$(printf "%s" "$member_list_json" | jq -r
".members[] | select( .isLearner==true ).ID")
+ local current_learner_node=$(attribute_learner_node get)
+ if [ -n "$learner_member_id" ] && [ -z "$current_learner_node" ]; then
+ ocf_log debug "$peer_member_name found as learner in member
list, but learner_node attribute was not set. Updating"
+ attribute_learner_node update "$peer_member_name"
+ return
+ fi
+
+ ocf_log debug "$peer_member_name is in the members list by IP:
$peer_member_ip"
+ # Errors from reconcile_member_state are logged internally. Ignoring
them here prevents stopping a healthy voter agent; critical local failures are
caught by detect_cluster_leadership_loss.
+ reconcile_member_state "$member_list_json"
}
check_peer()
@@ -1902,6 +2099,9 @@
fi
archive_data_folder
+ if ! wipe_data_folder_for_learner; then
+ return "$OCF_ERR_GENERIC"
+ fi
fi
ocf_log info "check for changes in pod manifest to decide if the
container should be reused or replaced"
@@ -2023,6 +2223,7 @@
peer_node_ip="$(attribute_node_ip_peer)"
if [ -n "$peer_node_name" ] && [ -n
"$peer_node_ip" ]; then
add_member_as_learner "$peer_node_name"
"$peer_node_ip"
+ set_standalone_node
else
ocf_log err "could not add peer as
learner (peer node name: ${peer_node_name:-unknown}, peer ip:
${peer_node_ip:-unknown})"
fi
@@ -2251,6 +2452,7 @@
POD_MANIFEST_COPY="${OCF_RESKEY_config_location}/pod.yaml"
ETCD_CONFIGURATION_FILE="${OCF_RESKEY_config_location}/config.yaml"
ETCD_BACKUP_FILE="${OCF_RESKEY_backup_location}/config-previous.tar.gz"
+ETCD_MEMBER_DIR="/var/lib/etcd/member"
ETCD_REVISION_JSON="/var/lib/etcd/revision.json"
ETCD_REVISION_BUMP_PERCENTAGE=0.2
ETCD_BUMP_REV_DEFAULT=1000000000
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/heartbeat/portblock
new/resource-agents-4.17.0+git42.a607c299/heartbeat/portblock
--- old/resource-agents-4.17.0+git30.b33c378d/heartbeat/portblock
2026-01-22 08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/heartbeat/portblock
2026-02-24 09:59:15.000000000 +0100
@@ -761,9 +761,9 @@
{
case $FIREWALL in
nft)
- check_binary $IPTABLES ;;
- iptables)
check_binary $NFTABLES ;;
+ iptables)
+ check_binary $IPTABLES ;;
esac
case $protocol in
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/tools/send_arp.linux.c
new/resource-agents-4.17.0+git42.a607c299/tools/send_arp.linux.c
--- old/resource-agents-4.17.0+git30.b33c378d/tools/send_arp.linux.c
2026-01-22 08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/tools/send_arp.linux.c
2026-02-24 09:59:15.000000000 +0100
@@ -32,7 +32,6 @@
#include <linux/sockios.h>
#include <sys/file.h>
#include <sys/time.h>
-#include <sys/signal.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <net/if.h>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resource-agents-4.17.0+git30.b33c378d/tools/tickle_tcp.c
new/resource-agents-4.17.0+git42.a607c299/tools/tickle_tcp.c
--- old/resource-agents-4.17.0+git30.b33c378d/tools/tickle_tcp.c
2026-01-22 08:54:44.000000000 +0100
+++ new/resource-agents-4.17.0+git42.a607c299/tools/tickle_tcp.c
2026-02-24 09:59:15.000000000 +0100
@@ -235,16 +235,21 @@
ip4pkt.ip.daddr = dst->ip.sin_addr.s_addr;
ip4pkt.ip.check = 0;
- ip4pkt.tcp.source = src->ip.sin_port;
- ip4pkt.tcp.dest = dst->ip.sin_port;
- ip4pkt.tcp.seq = seq;
- ip4pkt.tcp.ack_seq = ack;
- ip4pkt.tcp.ack = 1;
- if (rst)
- ip4pkt.tcp.rst = 1;
- ip4pkt.tcp.doff = sizeof(ip4pkt.tcp)/4;
- ip4pkt.tcp.window = htons(1234);
- ip4pkt.tcp.check = tcp_checksum((uint16_t *)&ip4pkt.tcp,
sizeof(ip4pkt.tcp), &ip4pkt.ip);
+ // musl define only one of the two struct for tcphdr in
+ // /usr/include/netinet/tcp.h so we must use it to ensure
compatibility
+ ip4pkt.tcp.th_sport = src->ip.sin_port;
+ ip4pkt.tcp.th_dport = dst->ip.sin_port;
+ ip4pkt.tcp.th_seq = seq;
+ ip4pkt.tcp.th_ack = ack;
+
+ ip4pkt.tcp.th_flags = 0;
+ ip4pkt.tcp.th_flags |= TH_ACK;
+ if (rst) {
+ ip4pkt.tcp.th_flags |= TH_RST;
+ }
+ ip4pkt.tcp.th_off = sizeof(ip4pkt.tcp)/4;
+ ip4pkt.tcp.th_win = htons(1234);
+ ip4pkt.tcp.th_sum = tcp_checksum((uint16_t *)&ip4pkt.tcp,
sizeof(ip4pkt.tcp), &ip4pkt.ip);
s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
@@ -280,16 +285,20 @@
ip6pkt.ip6.ip6_src = src->ip6.sin6_addr;
ip6pkt.ip6.ip6_dst = dst->ip6.sin6_addr;
- ip6pkt.tcp.source = src->ip6.sin6_port;
- ip6pkt.tcp.dest = dst->ip6.sin6_port;
- ip6pkt.tcp.seq = seq;
- ip6pkt.tcp.ack_seq = ack;
- ip6pkt.tcp.ack = 1;
- if (rst)
- ip6pkt.tcp.rst = 1;
- ip6pkt.tcp.doff = sizeof(ip6pkt.tcp)/4;
- ip6pkt.tcp.window = htons(1234);
- ip6pkt.tcp.check = tcp_checksum6((uint16_t *)&ip6pkt.tcp,
sizeof(ip6pkt.tcp), &ip6pkt.ip6);
+ // musl define only one of the two struct for tcphdr in
+ // /usr/include/netinet/tcp.h so we must use it to ensure
compatibility
+ ip6pkt.tcp.th_sport = src->ip6.sin6_port;
+ ip6pkt.tcp.th_dport = dst->ip6.sin6_port;
+ ip6pkt.tcp.th_seq = seq;
+ ip6pkt.tcp.th_ack = ack;
+ ip6pkt.tcp.th_flags = 0;
+ ip6pkt.tcp.th_flags |= TH_ACK;
+ if (rst) {
+ ip6pkt.tcp.th_flags |= TH_RST;
+ }
+ ip6pkt.tcp.th_off = sizeof(ip6pkt.tcp)/4;
+ ip6pkt.tcp.th_win = htons(1234);
+ ip6pkt.tcp.th_sum = tcp_checksum6((uint16_t *)&ip6pkt.tcp,
sizeof(ip6pkt.tcp), &ip6pkt.ip6);
s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {