Compare commits
No commits in common. "c8" and "c10s" have entirely different histories.
14
.gitignore
vendored
14
.gitignore
vendored
@ -1,12 +1,2 @@
|
||||
SOURCES/ClusterLabs-resource-agents-55a4e2c9.tar.gz
|
||||
SOURCES/aliyun-cli-2.1.10.tar.gz
|
||||
SOURCES/aliyun-python-sdk-core-2.13.1.tar.gz
|
||||
SOURCES/aliyun-python-sdk-ecs-4.9.3.tar.gz
|
||||
SOURCES/aliyun-python-sdk-vpc-3.0.2.tar.gz
|
||||
SOURCES/colorama-0.3.3.tar.gz
|
||||
SOURCES/google-cloud-sdk-360.0.0-linux-x86_64.tar.gz
|
||||
SOURCES/httplib2-0.20.4.tar.gz
|
||||
SOURCES/pycryptodome-3.20.0.tar.gz
|
||||
SOURCES/pyparsing-2.4.7-py2.py3-none-any.whl
|
||||
SOURCES/pyroute2-0.4.13.tar.gz
|
||||
SOURCES/urllib3-1.26.18.tar.gz
|
||||
/*
|
||||
!/*.patch
|
||||
|
@ -1,12 +0,0 @@
|
||||
dfc65f4cac3f95026b2f5674019814a527333004 SOURCES/ClusterLabs-resource-agents-55a4e2c9.tar.gz
|
||||
306e131d8908ca794276bfe3a0b55ccc3bbd482f SOURCES/aliyun-cli-2.1.10.tar.gz
|
||||
0a56f6d9ed2014a363486d33b63eca094379be06 SOURCES/aliyun-python-sdk-core-2.13.1.tar.gz
|
||||
c2a98b9a1562d223a76514f05028488ca000c395 SOURCES/aliyun-python-sdk-ecs-4.9.3.tar.gz
|
||||
f14647a4d37a9a254c4e711b95a7654fc418e41e SOURCES/aliyun-python-sdk-vpc-3.0.2.tar.gz
|
||||
0fe5bd8bca54dd71223778a1e0bcca9af324abb1 SOURCES/colorama-0.3.3.tar.gz
|
||||
81f039cf075e9c8b70d5af99c189296a9e031de3 SOURCES/google-cloud-sdk-360.0.0-linux-x86_64.tar.gz
|
||||
7caf4412d9473bf17352316249a8133fa70b7e37 SOURCES/httplib2-0.20.4.tar.gz
|
||||
c55d177e9484d974c95078d4ae945f89ba2c7251 SOURCES/pycryptodome-3.20.0.tar.gz
|
||||
c8307f47e3b75a2d02af72982a2dfefa3f56e407 SOURCES/pyparsing-2.4.7-py2.py3-none-any.whl
|
||||
147149db11104c06d405fd077dcd2aa1c345f109 SOURCES/pyroute2-0.4.13.tar.gz
|
||||
84e2852d8da1655373f7ce5e7d5d3e256b62b4e4 SOURCES/urllib3-1.26.18.tar.gz
|
1127
RHEL-109013-powervs-move-ip-new-ra.patch
Normal file
1127
RHEL-109013-powervs-move-ip-new-ra.patch
Normal file
File diff suppressed because it is too large
Load Diff
85
RHEL-113104-podman-etcd-add-oom-parameter.patch
Normal file
85
RHEL-113104-podman-etcd-add-oom-parameter.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From d08a7f74427ea2cf7d355a0f7f6d8f583e2d0cba Mon Sep 17 00:00:00 2001
|
||||
From: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
Date: Thu, 3 Jul 2025 12:22:12 +0200
|
||||
Subject: [PATCH] OCPBUGS-58324: podman-etcd Add OOM score adjustment for etcd
|
||||
containers
|
||||
|
||||
This change introduces a new `oom` parameter to the `podman-etcd` OCF
|
||||
agent. This allows tuning the Out-Of-Memory (OOM) score adjustment for
|
||||
the etcd container.
|
||||
|
||||
The `oom` parameter accepts integer values from -1000 to 1000,
|
||||
defaulting to -997 (system-node-critical equivalent).
|
||||
|
||||
see https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/#node-out-of-memory-behavior
|
||||
|
||||
Key changes:
|
||||
- Added `OCF_RESKEY_oom` parameter to agent definition (`content type="integer"`).
|
||||
- Integrated `--oom-score-adj` option into `podman_start()`.
|
||||
- Implemented input validation for `oom` in `podman_validate()`,
|
||||
ensuring values are within the [-1000:1000] range.
|
||||
---
|
||||
heartbeat/podman-etcd | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 6762112ec..884b7c579 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -45,6 +45,7 @@ OCF_RESKEY_nic_default="br-ex"
|
||||
OCF_RESKEY_authfile_default="/var/lib/kubelet/config.json"
|
||||
OCF_RESKEY_allow_pull_default="1"
|
||||
OCF_RESKEY_reuse_default="0"
|
||||
+OCF_RESKEY_oom_default="-997"
|
||||
|
||||
: ${OCF_RESKEY_image=${OCF_RESKEY_image_default}}
|
||||
: ${OCF_RESKEY_pod_manifest=${OCF_RESKEY_pod_manifest_default}}
|
||||
@@ -53,6 +54,7 @@ OCF_RESKEY_reuse_default="0"
|
||||
: ${OCF_RESKEY_authfile=${OCF_RESKEY_authfile_default}}
|
||||
: ${OCF_RESKEY_allow_pull=${OCF_RESKEY_allow_pull_default}}
|
||||
: ${OCF_RESKEY_reuse=${OCF_RESKEY_reuse_default}}
|
||||
+: ${OCF_RESKEY_oom=${OCF_RESKEY_oom_default}}
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -230,6 +232,16 @@ to stop the container before pacemaker.
|
||||
<shortdesc lang="en">drop-in dependency</shortdesc>
|
||||
<content type="boolean"/>
|
||||
</parameter>
|
||||
+
|
||||
+<parameter name="oom" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+Tune the host's Out-Of-Memory (OOM) preferences for containers (accepts values from -1000 to 1000).
|
||||
+Default to same OOM score as system-node-critical
|
||||
+https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/#node-out-of-memory-behavior
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">OOM for container</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_oom_default}"/>
|
||||
+</parameter>
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -1226,7 +1238,10 @@ podman_start()
|
||||
fi
|
||||
|
||||
podman_create_mounts
|
||||
- local run_opts="-d --name=${CONTAINER}"
|
||||
+ local run_opts="--detach --name=${CONTAINER}"
|
||||
+
|
||||
+ run_opts="$run_opts --oom-score-adj=${OCF_RESKEY_oom}"
|
||||
+
|
||||
# check to see if the container has already started
|
||||
podman_simple_status
|
||||
if [ $? -eq $OCF_SUCCESS ]; then
|
||||
@@ -1513,6 +1528,11 @@ podman_validate()
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
+ if [ "$OCF_RESKEY_oom" -lt -1000 ] || [ "$OCF_RESKEY_oom" -gt 1000 ]; then
|
||||
+ ocf_exit_reason "'oom' value ${OCF_RESKEY_oom} is out of range [-1000:1000]"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
686
RHEL-113816-podman-etcd-preserve-containers-for-debugging.patch
Normal file
686
RHEL-113816-podman-etcd-preserve-containers-for-debugging.patch
Normal file
@ -0,0 +1,686 @@
|
||||
From 6e9200dc2ffc89382188794742361985309936b2 Mon Sep 17 00:00:00 2001
|
||||
From: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
Date: Wed, 23 Jul 2025 09:34:13 +0200
|
||||
Subject: [PATCH] podman-etcd: preserve containers for debugging
|
||||
|
||||
This change modifies the agent to keep stopped containers for log
|
||||
inspection and debugging, with supporting changes to enable this
|
||||
behavior.
|
||||
|
||||
* Conditionally reuse existing containers when configuration unchanged
|
||||
* Move etcd inline configuration flags to external file to allow
|
||||
restarts without container recreation (mainly for the
|
||||
force-new-cluster flag)
|
||||
* Archive previous container renaming it into *-previous, and its
|
||||
configuration files into /var/lib/etcd/config-previous.tar.gz archive.
|
||||
The tar.gz archive consists in:
|
||||
* the pod manifest created by CEO, used to generated the Etc
|
||||
configuration file
|
||||
* the Etcd configuration file
|
||||
* the auth json file
|
||||
Only one copy is maintained to limit disk usage.
|
||||
* Both configuration and backup files location is configurable with 2
|
||||
new input arguments.
|
||||
|
||||
Signed-off-by: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
---
|
||||
heartbeat/podman-etcd | 438 ++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 336 insertions(+), 102 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 4969fbaaf..33804414a 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -46,6 +46,8 @@ OCF_RESKEY_authfile_default="/var/lib/kubelet/config.json"
|
||||
OCF_RESKEY_allow_pull_default="1"
|
||||
OCF_RESKEY_reuse_default="0"
|
||||
OCF_RESKEY_oom_default="-997"
|
||||
+OCF_RESKEY_config_location_default="/var/lib/etcd"
|
||||
+OCF_RESKEY_backup_location_default="/var/lib/etcd"
|
||||
|
||||
: ${OCF_RESKEY_image=${OCF_RESKEY_image_default}}
|
||||
: ${OCF_RESKEY_pod_manifest=${OCF_RESKEY_pod_manifest_default}}
|
||||
@@ -55,6 +57,9 @@ OCF_RESKEY_oom_default="-997"
|
||||
: ${OCF_RESKEY_allow_pull=${OCF_RESKEY_allow_pull_default}}
|
||||
: ${OCF_RESKEY_reuse=${OCF_RESKEY_reuse_default}}
|
||||
: ${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}}
|
||||
+
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -242,6 +247,23 @@ https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/#
|
||||
<shortdesc lang="en">OOM for container</shortdesc>
|
||||
<content type="integer" default="${OCF_RESKEY_oom_default}"/>
|
||||
</parameter>
|
||||
+
|
||||
+<parameter name="config_location" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+The directory where the resource agent stores its state files, such as the generated etcd configuration and a copy of the pod manifest.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Resource agent state directory</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_config_location_default}"/>
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="backup_location" required="0" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+The directory where the resource agent stores its backups.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Resource agent backup directory</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_backup_location_default}"/>
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -309,42 +331,52 @@ container_exists()
|
||||
return 1
|
||||
}
|
||||
|
||||
-remove_container()
|
||||
+# archive_current_container archives the current
|
||||
+# podman etcd container and its configuration files.
|
||||
+archive_current_container()
|
||||
{
|
||||
- local rc
|
||||
- local execids
|
||||
+ # don't attempt to archive a container that doesn't exist
|
||||
+ if ! container_exists; then
|
||||
+ return
|
||||
+ fi
|
||||
|
||||
- if ocf_is_true "$OCF_RESKEY_reuse"; then
|
||||
- # never remove the container if we have reuse enabled.
|
||||
- return 0
|
||||
+ # delete any container named "*-previous", or we won't be able to archive the current container.
|
||||
+ if podman inspect "${CONTAINER}-previous" >/dev/null 2>&1; then
|
||||
+ ocf_log info "removing old archived container '$CONTAINER-previous'"
|
||||
+ if ! ocf_run podman rm --volumes --force "$CONTAINER-previous"; then
|
||||
+ ocf_log warn "could not remove old archived container (podman rm failed, error code: $?). Won't be able to archive current container"
|
||||
+ return
|
||||
+ fi
|
||||
fi
|
||||
|
||||
- if ! container_exists; then
|
||||
- # don't attempt to remove a container that doesn't exist
|
||||
- return 0
|
||||
+ ocf_log info "archiving '$CONTAINER' container as '$CONTAINER-previous' for debugging purposes"
|
||||
+ if ! ocf_run podman rename "$CONTAINER" "$CONTAINER-previous"; then
|
||||
+ ocf_log err "could not archive container '$CONTAINER', error code: $?"
|
||||
+ return
|
||||
fi
|
||||
- ocf_log notice "Cleaning up inactive container, ${CONTAINER}."
|
||||
- ocf_run podman rm -v "$CONTAINER"
|
||||
- rc=$?
|
||||
- if [ $rc -ne 0 ]; then
|
||||
- if [ $rc -eq 2 ]; then
|
||||
- if podman inspect --format '{{.State.Status}}' "$CONTAINER" | grep -wq "stopping"; then
|
||||
- ocf_log err "Inactive container ${CONTAINER} is stuck in 'stopping' state. Force-remove it."
|
||||
- ocf_run podman rm -f "$CONTAINER"
|
||||
- rc=$?
|
||||
- fi
|
||||
- fi
|
||||
- # due to a podman bug (rhbz#1841485), sometimes a stopped
|
||||
- # container can still be associated with Exec sessions, in
|
||||
- # which case the "podman rm" has to be forced
|
||||
- execids=$(podman inspect "$CONTAINER" --format '{{len .ExecIDs}}')
|
||||
- if [ "$execids" -ne "0" ]; then
|
||||
- ocf_log warn "Inactive container ${CONTAINER} has lingering exec sessions. Force-remove it."
|
||||
- ocf_run podman rm -f "$CONTAINER"
|
||||
- rc=$?
|
||||
+
|
||||
+ # archive corresponding etcd configuration files
|
||||
+ local files_to_archive=""
|
||||
+ for file in "$OCF_RESKEY_authfile" "$POD_MANIFEST_COPY" "$ETCD_CONFIGURATION_FILE"; do
|
||||
+ if [ -f "$file" ]; then
|
||||
+ files_to_archive="$files_to_archive $file"
|
||||
+ else
|
||||
+ ocf_log warn "file '$file' is missing and won't be archived"
|
||||
fi
|
||||
+ done
|
||||
+
|
||||
+ if [ -z "$files_to_archive" ]; then
|
||||
+ ocf_log warn "could not find any file to archive."
|
||||
+ return
|
||||
+ fi
|
||||
+
|
||||
+ # NOTE: tar will override any existing archive as wanted
|
||||
+ # shellcheck disable=SC2086
|
||||
+ if ! ocf_run tar --create --verbose --gzip --file "$ETCD_BACKUP_FILE" $files_to_archive; then
|
||||
+ ocf_log warn "container archived successfully, but configuration backup failed (error: $?). Container debugging available, but without matching configuration files"
|
||||
+ else
|
||||
+ ocf_log info "container configuration also archived in '$ETCD_BACKUP_FILE'"
|
||||
fi
|
||||
- return $rc
|
||||
}
|
||||
|
||||
# Correctly wraps an ipv6 in [] for url otherwise use return normal ipv4 address.
|
||||
@@ -365,6 +397,7 @@ attribute_node_ip()
|
||||
local attribute="node_ip"
|
||||
local ip_addr name
|
||||
|
||||
+ # TODO: We can retrieve both the local and peer IP addresses from this map, which eliminates the need to use CIB to share them between nodes
|
||||
for node in $(echo "$OCF_RESKEY_node_ip_map" | sed "s/\s//g;s/;/ /g"); do
|
||||
name=$(echo "$node" | cut -d: -f1)
|
||||
# ignore other nodes
|
||||
@@ -375,7 +408,7 @@ attribute_node_ip()
|
||||
done
|
||||
|
||||
if [ -z "$ip_addr" ]; then
|
||||
- ocf_log err "ip address was empty when querying (getent ahosts) for hostname: $(hostname -f)"
|
||||
+ ocf_log err "could not get local ip address from node_ip_map: '$OCF_RESKEY_node_ip_map'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -384,9 +417,9 @@ attribute_node_ip()
|
||||
echo "$ip_addr"
|
||||
;;
|
||||
update)
|
||||
- if ! crm_attribute --type nodes --node "$NODENAME" --name "$attribute" --update "$value"; then
|
||||
+ if ! crm_attribute --type nodes --node "$NODENAME" --name "$attribute" --update "$ip_addr"; then
|
||||
rc="$?"
|
||||
- ocf_log err "could not set $attribute to $value, error code: $rc"
|
||||
+ ocf_log err "could not set $attribute to $ip_addr, error code: $rc"
|
||||
return "$rc"
|
||||
fi
|
||||
;;
|
||||
@@ -428,6 +461,48 @@ get_env_from_manifest() {
|
||||
echo "$env_var_value"
|
||||
}
|
||||
|
||||
+# etcd configuration file expects duration to be expressed in nanoseconds
|
||||
+convert_duration_in_nanoseconds() {
|
||||
+ local duration=$1
|
||||
+ local value unit nanoseconds
|
||||
+
|
||||
+ if [ -z "$duration" ]; then
|
||||
+ ocf_log err "convert_duration_in_nanoseconds: no duration provided"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ if ! echo "$duration" | grep -qE '^[0-9]+[numµ]?s$'; then
|
||||
+ ocf_log err "convert_duration_in_nanoseconds: invalid duration format \"$duration\". Expected format: <number><unit> where unit is one of s, ms, us, µs, ns"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ # Extract numeric value and unit from duration string
|
||||
+ value=$(echo "$duration" | sed 's/[^0-9]*$//')
|
||||
+ unit=$(echo "$duration" | sed 's/^[0-9]*//')
|
||||
+
|
||||
+ case "$unit" in
|
||||
+ ns)
|
||||
+ nanoseconds=$value
|
||||
+ ;;
|
||||
+ us|µs)
|
||||
+ nanoseconds=$((value * 1000))
|
||||
+ ;;
|
||||
+ ms)
|
||||
+ nanoseconds=$((value * 1000000))
|
||||
+ ;;
|
||||
+ s)
|
||||
+ nanoseconds=$((value * 1000000000))
|
||||
+ ;;
|
||||
+ *)
|
||||
+ # this should not happen as the input is already validated
|
||||
+ ocf_log err "convert_duration_in_nanoseconds: unknown duration unit \"$unit\""
|
||||
+ return 1
|
||||
+ ;;
|
||||
+ esac
|
||||
+
|
||||
+ echo "$nanoseconds"
|
||||
+}
|
||||
+
|
||||
prepare_env() {
|
||||
local name ip ipurl standalone_node
|
||||
|
||||
@@ -457,9 +532,14 @@ prepare_env() {
|
||||
ETCDCTL_API=$(get_env_from_manifest "ETCDCTL_API")
|
||||
ETCD_CIPHER_SUITES=$(get_env_from_manifest "ETCD_CIPHER_SUITES")
|
||||
ETCD_DATA_DIR=$(get_env_from_manifest "ETCD_DATA_DIR")
|
||||
+ if [ ! -d "$ETCD_DATA_DIR" ]; then
|
||||
+ ocf_log err "could not find data-dir at path \"$ETCD_DATA_DIR\""
|
||||
+ return "$OCF_ERR_ARGS"
|
||||
+ else
|
||||
+ ocf_log info "using data-dir: $ETCD_DATA_DIR"
|
||||
+ fi
|
||||
ETCD_ELECTION_TIMEOUT=$(get_env_from_manifest "ETCD_ELECTION_TIMEOUT")
|
||||
ETCD_ENABLE_PPROF=$(get_env_from_manifest "ETCD_ENABLE_PPROF")
|
||||
- ETCD_EXPERIMENTAL_MAX_LEARNERS=$(get_env_from_manifest "ETCD_EXPERIMENTAL_MAX_LEARNERS")
|
||||
ETCD_EXPERIMENTAL_WARNING_APPLY_DURATION=$(get_env_from_manifest "ETCD_EXPERIMENTAL_WARNING_APPLY_DURATION")
|
||||
ETCD_EXPERIMENTAL_WATCH_PROGRESS_NOTIFY_INTERVAL=$(get_env_from_manifest "ETCD_EXPERIMENTAL_WATCH_PROGRESS_NOTIFY_INTERVAL")
|
||||
ETCD_HEARTBEAT_INTERVAL=$(get_env_from_manifest "ETCD_HEARTBEAT_INTERVAL")
|
||||
@@ -475,6 +555,62 @@ prepare_env() {
|
||||
LISTEN_METRICS_URLS="0.0.0.0"
|
||||
}
|
||||
|
||||
+
|
||||
+generate_etcd_configuration() {
|
||||
+ if is_force_new_cluster; then
|
||||
+ # The embedded newline is required for correct YAML formatting.
|
||||
+ FORCE_NEW_CLUSTER_CONFIG="force-new-cluster: true
|
||||
+force-new-cluster-bump-amount: 1000000000"
|
||||
+ else
|
||||
+ FORCE_NEW_CLUSTER_CONFIG="force-new-cluster: false"
|
||||
+ fi
|
||||
+
|
||||
+ cat > "$ETCD_CONFIGURATION_FILE" << EOF
|
||||
+logger: zap
|
||||
+log-level: info
|
||||
+snapshot-count: 10000
|
||||
+name: $NODENAME
|
||||
+data-dir: $ETCD_DATA_DIR
|
||||
+$FORCE_NEW_CLUSTER_CONFIG
|
||||
+socket-reuse-address: $ETCD_SOCKET_REUSE_ADDRESS
|
||||
+election-timeout: $ETCD_ELECTION_TIMEOUT
|
||||
+enable-pprof: $ETCD_ENABLE_PPROF
|
||||
+heartbeat-interval: $ETCD_HEARTBEAT_INTERVAL
|
||||
+quota-backend-bytes: $ETCD_QUOTA_BACKEND_BYTES
|
||||
+initial-advertise-peer-urls: "$NODEIPURL:2380"
|
||||
+listen-peer-urls: "$(ip_url ${LISTEN_PEER_URLS}):2380"
|
||||
+listen-client-urls: "$(ip_url ${LISTEN_CLIENT_URLS}):2379,unixs://${NODEIP}:0"
|
||||
+initial-cluster: $ETCD_INITIAL_CLUSTER
|
||||
+initial-cluster-state: $ETCD_INITIAL_CLUSTER_STATE
|
||||
+client-transport-security:
|
||||
+ cert-file: /etc/kubernetes/static-pod-certs/secrets/etcd-all-certs/etcd-serving-${NODENAME}.crt
|
||||
+ key-file: /etc/kubernetes/static-pod-certs/secrets/etcd-all-certs/etcd-serving-${NODENAME}.key
|
||||
+ client-cert-auth: true
|
||||
+ trusted-ca-file: $SERVER_CACERT
|
||||
+peer-transport-security:
|
||||
+ cert-file: $ETCD_PEER_CERT
|
||||
+ key-file: $ETCD_PEER_KEY
|
||||
+ client-cert-auth: true
|
||||
+ trusted-ca-file: $SERVER_CACERT
|
||||
+advertise-client-urls: "$NODEIPURL:2379"
|
||||
+listen-metrics-urls: "$(ip_url ${LISTEN_METRICS_URLS}):9978"
|
||||
+metrics: extensive
|
||||
+experimental-initial-corrupt-check: true
|
||||
+experimental-max-learners: 1
|
||||
+experimental-warning-apply-duration: $(convert_duration_in_nanoseconds "$ETCD_EXPERIMENTAL_WARNING_APPLY_DURATION")
|
||||
+experimental-watch-progress-notify-interval: $(convert_duration_in_nanoseconds "$ETCD_EXPERIMENTAL_WATCH_PROGRESS_NOTIFY_INTERVAL")
|
||||
+EOF
|
||||
+
|
||||
+ {
|
||||
+ if [ -n "$ETCD_CIPHER_SUITES" ]; then
|
||||
+ echo "cipher-suites:"
|
||||
+ echo "$ETCD_CIPHER_SUITES" | tr ',' '\n' | while read -r cipher; do
|
||||
+ echo " - \"$cipher\""
|
||||
+ done
|
||||
+ fi
|
||||
+ } >> "$ETCD_CONFIGURATION_FILE"
|
||||
+}
|
||||
+
|
||||
archive_data_folder()
|
||||
{
|
||||
# TODO: use etcd snapshots
|
||||
@@ -634,7 +770,7 @@ add_member_as_learner()
|
||||
local endpoint_url=$(ip_url $(attribute_node_ip get))
|
||||
local peer_url=$(ip_url $member_ip)
|
||||
|
||||
- ocf_log info "add $member_name ($member_ip) to the member list as learner"
|
||||
+ ocf_log info "add $member_name ($member_ip, $endpoint_url) 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)
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
@@ -1104,18 +1240,18 @@ compare_revision()
|
||||
peer_revision=$(attribute_node_revision_peer)
|
||||
|
||||
if [ "$revision" = "" ] || [ "$revision" = "null" ] || [ "$peer_revision" = "" ] || [ "$peer_revision" = "null" ]; then
|
||||
- ocf_log err "could not compare revisions: $NODENAME local revision: $revision, peer revision: $peer_revision"
|
||||
+ ocf_log err "could not compare revisions: '$NODENAME' local revision='$revision', peer revision='$peer_revision'"
|
||||
return "$OCF_ERR_GENERIC"
|
||||
fi
|
||||
|
||||
if [ "$revision" -gt "$peer_revision" ]; then
|
||||
- ocf_log info "$NODENAME revision: $revision is newer than peer revision: $peer_revision"
|
||||
+ ocf_log info "$NODENAME revision: '$revision' is newer than peer revision: '$peer_revision'"
|
||||
echo "newer"
|
||||
elif [ "$revision" -eq "$peer_revision" ]; then
|
||||
- ocf_log info "$NODENAME revision: $revision is equal to peer revision: $peer_revision"
|
||||
+ ocf_log info "$NODENAME revision: '$revision' is equal to peer revision: '$peer_revision'"
|
||||
echo "equal"
|
||||
else
|
||||
- ocf_log info "$NODENAME revision: $revision is older than peer revision: $peer_revision"
|
||||
+ ocf_log info "$NODENAME revision: '$revision' is older than peer revision: '$peer_revision'"
|
||||
echo "older"
|
||||
fi
|
||||
return "$OCF_SUCCESS"
|
||||
@@ -1144,6 +1280,100 @@ ensure_pod_manifest_exists()
|
||||
return "$OCF_SUCCESS"
|
||||
}
|
||||
|
||||
+filter_pod_manifest() {
|
||||
+ # Remove pod-version related fields from POD manifest
|
||||
+ local pod_manifest="$1"
|
||||
+ local temporary_file
|
||||
+ local jq_filter='del(.metadata.labels.revision) | .spec.containers[] |= ( .env |= map(select( .name != "ETCD_STATIC_POD_VERSION" ))) | .spec.volumes |= map( select( .name != "resource-dir" ))'
|
||||
+
|
||||
+ if ! temporary_file=$(mktemp); then
|
||||
+ ocf_log err "could not create temporary file for '$pod_manifest', error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if ! jq "$jq_filter" "$pod_manifest" > "$temporary_file"; then
|
||||
+ ocf_log err "could not remove pod version related data from '$pod_manifest', error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ echo "$temporary_file"
|
||||
+}
|
||||
+
|
||||
+can_reuse_container() {
|
||||
+ # Decide whether to reuse the existing container or create a new one based on etcd pod manifest changes.
|
||||
+ # NOTE: explicitly ignore POD version and POD version related data, as the content might be the same even if the revision number has changed.
|
||||
+ local cp_rc
|
||||
+ local diff_rc
|
||||
+ local filtered_original_pod_manifest
|
||||
+ local filtered_copy_pod_manifest
|
||||
+
|
||||
+
|
||||
+ # If the container does not exist it cannot be reused
|
||||
+ if ! container_exists; then
|
||||
+ OCF_RESKEY_reuse=0
|
||||
+ return "$OCF_SUCCESS"
|
||||
+ fi
|
||||
+
|
||||
+ # If the manifest copy doesn't exist, we need a new container.
|
||||
+ if [ ! -f "$POD_MANIFEST_COPY" ]; then
|
||||
+ ocf_log info "a working copy of $OCF_RESKEY_pod_manifest was not found. A new etcd container will be created."
|
||||
+ OCF_RESKEY_reuse=0
|
||||
+ return "$OCF_SUCCESS"
|
||||
+ fi
|
||||
+
|
||||
+ if ! filtered_original_pod_manifest=$(filter_pod_manifest "$OCF_RESKEY_pod_manifest"); then
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if ! filtered_copy_pod_manifest=$(filter_pod_manifest "$POD_MANIFEST_COPY"); then
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "comparing $OCF_RESKEY_pod_manifest with local copy $POD_MANIFEST_COPY"
|
||||
+ ocf_run diff -s "$filtered_original_pod_manifest" "$filtered_copy_pod_manifest"
|
||||
+ diff_rc="$?"
|
||||
+ # clean up temporary files
|
||||
+ rm -f "$filtered_original_pod_manifest" "$filtered_copy_pod_manifest"
|
||||
+ case "$diff_rc" in
|
||||
+ 0)
|
||||
+ ocf_log info "Reusing the existing etcd container"
|
||||
+ OCF_RESKEY_reuse=1
|
||||
+ ;;
|
||||
+ 1)
|
||||
+ ocf_log info "Etcd pod manifest changes detected: creating a new etcd container to apply the changes"
|
||||
+ if ! ocf_run cp -p "$OCF_RESKEY_pod_manifest" "$POD_MANIFEST_COPY"; then
|
||||
+ cp_rc="$?"
|
||||
+ ocf_log err "Could not create a working copy of $OCF_RESKEY_pod_manifest, rc: $cp_rc"
|
||||
+ return "$OCF_ERR_GENERIC"
|
||||
+ fi
|
||||
+ ocf_log info "A working copy of $OCF_RESKEY_pod_manifest was created"
|
||||
+ OCF_RESKEY_reuse=0
|
||||
+ ;;
|
||||
+ *)
|
||||
+ ocf_log err "Could not check if etcd pod manifest has changed, diff rc: $diff_rc"
|
||||
+ return "$OCF_ERR_GENERIC"
|
||||
+ ;;
|
||||
+ esac
|
||||
+
|
||||
+ return "$OCF_SUCCESS"
|
||||
+}
|
||||
+
|
||||
+ensure_pod_manifest_copy_exists() {
|
||||
+ local cp_rc
|
||||
+
|
||||
+ if [ -f "$POD_MANIFEST_COPY" ]; then
|
||||
+ return "$OCF_SUCCESS"
|
||||
+ fi
|
||||
+
|
||||
+ # If the manifest copy doesn't exist, create it and ensure a new container.
|
||||
+ if ! ocf_run cp -p "$OCF_RESKEY_pod_manifest" "$POD_MANIFEST_COPY"; then
|
||||
+ cp_rc="$?"
|
||||
+ ocf_log err "Could not create a working copy of $OCF_RESKEY_pod_manifest, rc: $cp_rc"
|
||||
+ return "$OCF_ERR_GENERIC"
|
||||
+ fi
|
||||
+
|
||||
+ ocf_log info "a new working copy of $OCF_RESKEY_pod_manifest was created"
|
||||
+
|
||||
+ return "$OCF_SUCCESS"
|
||||
+}
|
||||
+
|
||||
podman_start()
|
||||
{
|
||||
local cid
|
||||
@@ -1173,6 +1403,13 @@ podman_start()
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
+ # check if the container has already started
|
||||
+ podman_simple_status
|
||||
+ if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ ocf_log info "the '$CONTAINER' has already started. Nothing to do"
|
||||
+ return "$OCF_SUCCESS"
|
||||
+ fi
|
||||
+
|
||||
if ! ensure_pod_manifest_exists; then
|
||||
ocf_exit_reason "could not find etcd pod manifest ($OCF_RESKEY_pod_manifest)"
|
||||
return "$OCF_ERR_GENERIC"
|
||||
@@ -1186,8 +1423,9 @@ podman_start()
|
||||
ocf_log info "static pod was running: start normally"
|
||||
else
|
||||
if is_force_new_cluster; then
|
||||
- ocf_log notice "$NODENAME marked to force-new-cluster"
|
||||
+ ocf_log notice "'$NODENAME' marked to force-new-cluster"
|
||||
else
|
||||
+ ocf_log info "'$NODENAME' is not marked to force-new-cluster"
|
||||
# When the local agent starts, we can infer the cluster state by counting
|
||||
# how many agents are starting or already active:
|
||||
# - 1 active agent: it's the peer (we are just starting)
|
||||
@@ -1195,6 +1433,7 @@ podman_start()
|
||||
# - 0 active agents, 2 starting: both agents are starting simultaneously
|
||||
local active_resources_count
|
||||
active_resources_count=$(echo "$OCF_RESKEY_CRM_meta_notify_active_resource" | wc -w)
|
||||
+ ocf_log info "found '$active_resources_count' active etcd resources (meta notify environment variable: '$OCF_RESKEY_CRM_meta_notify_active_resource')"
|
||||
case "$active_resources_count" in
|
||||
1)
|
||||
if [ "$(attribute_learner_node get)" = "$(get_peer_node_name)" ]; then
|
||||
@@ -1205,17 +1444,17 @@ podman_start()
|
||||
fi
|
||||
;;
|
||||
0)
|
||||
+ # count how many agents are starting now
|
||||
+ local start_resources_count
|
||||
+ start_resources_count=$(echo "$OCF_RESKEY_CRM_meta_notify_start_resource" | wc -w)
|
||||
+ ocf_log info "found '$start_resources_count' starting etcd resources (meta notify environment variable: '$OCF_RESKEY_CRM_meta_notify_start_resource')"
|
||||
+
|
||||
# we need to compare the revisions in any of the following branches
|
||||
# so call the function only once here
|
||||
if ! revision_compare_result=$(compare_revision); then
|
||||
ocf_log err "could not compare revisions, error code: $?"
|
||||
return "$OCF_ERR_GENERIC"
|
||||
fi
|
||||
-
|
||||
- # count how many agents are starting now
|
||||
- local start_resources_count
|
||||
- start_resources_count=$(echo "$OCF_RESKEY_CRM_meta_notify_start_resource" | wc -w)
|
||||
-
|
||||
case "$start_resources_count" in
|
||||
1)
|
||||
ocf_log debug "peer not starting: ensure we can start a new cluster"
|
||||
@@ -1231,6 +1470,7 @@ podman_start()
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
+ # TODO: can we start "normally", regardless the revisions, if the container-id is the same on both nodes?
|
||||
ocf_log info "peer starting"
|
||||
if [ "$revision_compare_result" = "newer" ]; then
|
||||
set_force_new_cluster
|
||||
@@ -1263,7 +1503,7 @@ podman_start()
|
||||
fi
|
||||
|
||||
podman_create_mounts
|
||||
- local run_opts="--detach --name=${CONTAINER}"
|
||||
+ local run_opts="--detach --name=${CONTAINER} --replace"
|
||||
|
||||
run_opts="$run_opts --oom-score-adj=${OCF_RESKEY_oom}"
|
||||
|
||||
@@ -1297,61 +1537,59 @@ podman_start()
|
||||
archive_data_folder
|
||||
fi
|
||||
|
||||
- prepare_env
|
||||
+ ocf_log info "check for changes in pod manifest to decide if the container should be reused or replaced"
|
||||
+ if ! can_reuse_container ; then
|
||||
+ rc="$?"
|
||||
+ ocf_log err "could not determine etcd container reuse strategy, rc: $rc"
|
||||
+ return "$rc"
|
||||
+ fi
|
||||
+
|
||||
+ # Archive current container and its configuration before creating
|
||||
+ # new configuration files.
|
||||
+ if ! ocf_is_true "$OCF_RESKEY_reuse"; then
|
||||
+ # Log archive container failures but don't block, as the priority
|
||||
+ # is ensuring the etcd container starts successfully.
|
||||
+ archive_current_container
|
||||
+ fi
|
||||
+
|
||||
+ if ! ensure_pod_manifest_copy_exists; then
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ if ! prepare_env; then
|
||||
+ ocf_log err "Could not prepare environment for podman, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ if ! generate_etcd_configuration; then
|
||||
+ ocf_log err "Could not generate etcd configuration, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
|
||||
- # add etcd-specific opts
|
||||
run_opts="$run_opts \
|
||||
- --network=host \
|
||||
- -v /etc/kubernetes/static-pod-resources/etcd-certs:/etc/kubernetes/static-pod-certs \
|
||||
- -v /var/lib/etcd:/var/lib/etcd \
|
||||
- --env ALL_ETCD_ENDPOINTS=$ALL_ETCD_ENDPOINTS \
|
||||
- --env ETCD_CIPHER_SUITES=$ETCD_CIPHER_SUITES \
|
||||
- --env ETCD_DATA_DIR=$ETCD_DATA_DIR \
|
||||
- --env ETCD_ELECTION_TIMEOUT=$ETCD_ELECTION_TIMEOUT \
|
||||
- --env ETCD_ENABLE_PPROF=$ETCD_ENABLE_PPROF \
|
||||
- --env ETCD_EXPERIMENTAL_MAX_LEARNERS=$ETCD_EXPERIMENTAL_MAX_LEARNERS \
|
||||
- --env ETCD_EXPERIMENTAL_WARNING_APPLY_DURATION=$ETCD_EXPERIMENTAL_WARNING_APPLY_DURATION \
|
||||
- --env ETCD_EXPERIMENTAL_WATCH_PROGRESS_NOTIFY_INTERVAL=$ETCD_EXPERIMENTAL_WATCH_PROGRESS_NOTIFY_INTERVAL \
|
||||
- --env ETCD_HEARTBEAT_INTERVAL=$ETCD_HEARTBEAT_INTERVAL \
|
||||
- --env ETCD_INITIAL_CLUSTER=$ETCD_INITIAL_CLUSTER \
|
||||
- --env ETCD_INITIAL_CLUSTER_STATE=$ETCD_INITIAL_CLUSTER_STATE \
|
||||
- --env ETCD_NAME=$NODENAME \
|
||||
- --env ETCD_QUOTA_BACKEND_BYTES=$ETCD_QUOTA_BACKEND_BYTES \
|
||||
- --env ETCD_SOCKET_REUSE_ADDRESS=$ETCD_SOCKET_REUSE_ADDRESS \
|
||||
- --env ETCDCTL_API=$ETCDCTL_API \
|
||||
- --env ETCDCTL_CACERT=$SERVER_CACERT \
|
||||
- --env ETCDCTL_CERT=$ETCD_PEER_CERT \
|
||||
- --env ETCDCTL_KEY=$ETCD_PEER_KEY \
|
||||
- --authfile=$OCF_RESKEY_authfile \
|
||||
- --security-opt label=disable"
|
||||
+ --network=host \
|
||||
+ -v /etc/kubernetes/static-pod-resources/etcd-certs:/etc/kubernetes/static-pod-certs \
|
||||
+ -v /var/lib/etcd:/var/lib/etcd \
|
||||
+ --env ETCDCTL_API=$ETCDCTL_API \
|
||||
+ --env ETCDCTL_CACERT=$SERVER_CACERT \
|
||||
+ --env ETCDCTL_CERT=$ETCD_PEER_CERT \
|
||||
+ --env ETCDCTL_KEY=$ETCD_PEER_KEY \
|
||||
+ --authfile=$OCF_RESKEY_authfile \
|
||||
+ --security-opt label=disable"
|
||||
if [ -n "$OCF_RESKEY_run_opts" ]; then
|
||||
run_opts="$run_opts $OCF_RESKEY_run_opts"
|
||||
fi
|
||||
|
||||
- OCF_RESKEY_run_cmd="$OCF_RESKEY_run_cmd --logger=zap \
|
||||
- --log-level=info \
|
||||
- --experimental-initial-corrupt-check=true \
|
||||
- --snapshot-count=10000 \
|
||||
- --initial-advertise-peer-urls=$NODEIPURL:2380 \
|
||||
- --cert-file=/etc/kubernetes/static-pod-certs/secrets/etcd-all-certs/etcd-serving-${NODENAME}.crt \
|
||||
- --key-file=/etc/kubernetes/static-pod-certs/secrets/etcd-all-certs/etcd-serving-${NODENAME}.key \
|
||||
- --trusted-ca-file=$SERVER_CACERT \
|
||||
- --client-cert-auth=true \
|
||||
- --peer-cert-file=$ETCD_PEER_CERT \
|
||||
- --peer-key-file=$ETCD_PEER_KEY \
|
||||
- --peer-trusted-ca-file=$SERVER_CACERT \
|
||||
- --peer-client-cert-auth=true \
|
||||
- --advertise-client-urls=$NODEIPURL:2379 \
|
||||
- --listen-client-urls=$(ip_url ${LISTEN_CLIENT_URLS}):2379,unixs://${NODEIP}:0 \
|
||||
- --listen-peer-urls=$(ip_url ${LISTEN_PEER_URLS}):2380 \
|
||||
- --metrics=extensive \
|
||||
- --listen-metrics-urls=$(ip_url ${LISTEN_METRICS_URLS}):9978"
|
||||
- if [ -n "$OCF_RESKEY_run_cmd_opts" ]; then
|
||||
- OCF_RESKEY_run_cmd="$OCF_RESKEY_run_cmd $OCF_RESKEY_run_cmd_opts"
|
||||
+ if [ -f "$ETCD_CONFIGURATION_FILE" ]; then
|
||||
+ ocf_log info "using etcd configuration file: $ETCD_CONFIGURATION_FILE"
|
||||
+ else
|
||||
+ ocf_log err "could not find $ETCD_CONFIGURATION_FILE"
|
||||
+ return "$OCF_ERR_GENERIC"
|
||||
fi
|
||||
|
||||
- if is_force_new_cluster; then
|
||||
- OCF_RESKEY_run_cmd="$OCF_RESKEY_run_cmd --force-new-cluster"
|
||||
+ OCF_RESKEY_run_cmd="$OCF_RESKEY_run_cmd --config-file=$ETCD_CONFIGURATION_FILE"
|
||||
+ if [ -n "$OCF_RESKEY_run_cmd_opts" ]; then
|
||||
+ OCF_RESKEY_run_cmd="$OCF_RESKEY_run_cmd $OCF_RESKEY_run_cmd_opts"
|
||||
fi
|
||||
|
||||
if [ "$OCF_RESKEY_image" = "$OCF_RESKEY_image_default" ]; then
|
||||
@@ -1377,9 +1615,7 @@ podman_start()
|
||||
ocf_log info "starting existing container $CONTAINER."
|
||||
ocf_run podman start "$CONTAINER"
|
||||
else
|
||||
- # make sure any previous container matching our container name is cleaned up first.
|
||||
- # we already know at this point it wouldn't be running
|
||||
- remove_container
|
||||
+ ocf_log info "starting new container $CONTAINER."
|
||||
run_new_container "$run_opts" "$OCF_RESKEY_image" "$OCF_RESKEY_run_cmd"
|
||||
if [ $? -eq 125 ]; then
|
||||
return $OCF_ERR_GENERIC
|
||||
@@ -1439,7 +1675,6 @@ podman_stop()
|
||||
local rc
|
||||
podman_simple_status
|
||||
if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
- remove_container
|
||||
ocf_log info "could not leave members list: etcd container not running"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
@@ -1475,7 +1710,7 @@ podman_stop()
|
||||
ocf_run podman kill "$CONTAINER"
|
||||
rc=$?
|
||||
else
|
||||
- ocf_log debug "waiting $timeout second[s] before killing container"
|
||||
+ ocf_log info "waiting $timeout second[s] before killing container"
|
||||
ocf_run podman stop -t="$timeout" "$CONTAINER"
|
||||
rc=$?
|
||||
# on stop, systemd will automatically delete any transient
|
||||
@@ -1496,11 +1731,6 @@ podman_stop()
|
||||
fi
|
||||
fi
|
||||
|
||||
- if ! remove_container; then
|
||||
- ocf_exit_reason "Failed to remove stopped container, ${CONTAINER}, based on image, ${OCF_RESKEY_image}."
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
-
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
@@ -1532,6 +1762,7 @@ podman_validate()
|
||||
check_binary oc
|
||||
check_binary podman
|
||||
check_binary jq
|
||||
+ check_binary tar
|
||||
|
||||
if [ -z "$OCF_RESKEY_node_ip_map" ]; then
|
||||
ocf_exit_reason "'node_ip_map' option is required"
|
||||
@@ -1589,6 +1820,9 @@ else
|
||||
fi
|
||||
|
||||
CONTAINER=$OCF_RESKEY_name
|
||||
+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"
|
||||
|
||||
# Note: we currently monitor podman containers by with the "podman exec"
|
||||
# command, so make sure that invocation is always valid by enforcing the
|
193
RHEL-113817-podman-etcd-wrap-ipv6-address-in-brackets.patch
Normal file
193
RHEL-113817-podman-etcd-wrap-ipv6-address-in-brackets.patch
Normal file
@ -0,0 +1,193 @@
|
||||
From 11cdff8c886c72c83c26e48e46a8620c06e4c2f0 Mon Sep 17 00:00:00 2001
|
||||
From: E Hila <ehila@redhat.com>
|
||||
Date: Tue, 9 Sep 2025 06:06:12 -0400
|
||||
Subject: [PATCH] OCPBUGS-60977: podman-etcd: wrap ipv6 address in brackets for
|
||||
attribute_node_ip (#2068)
|
||||
|
||||
When trying to determine the node ip address we need to make sure we account for ipv6 and dualstack deployments, and accordingly wrap ipv6 in brackets so it correctly resolves. Since the node ip mapping is provided by the controller, we parse out the IP address of the node from there and use a helper function for building URLs with ports to correctly use brackets for ipv6 ip addresses.
|
||||
|
||||
Signed-off-by: ehila <ehila@redhat.com>
|
||||
---
|
||||
heartbeat/podman-etcd | 77 ++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 51 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 884b7c579..4969fbaaf 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -347,21 +347,41 @@ remove_container()
|
||||
return $rc
|
||||
}
|
||||
|
||||
+# Correctly wraps an ipv6 in [] for url otherwise use return normal ipv4 address.
|
||||
+ip_url() {
|
||||
+ local ip_addr=$1
|
||||
+ local value
|
||||
+ if echo "$ip_addr" | grep -q ":" ; then
|
||||
+ value="[$ip_addr]"
|
||||
+ else
|
||||
+ value="$ip_addr"
|
||||
+ fi
|
||||
+ echo "https://$value"
|
||||
+}
|
||||
+
|
||||
attribute_node_ip()
|
||||
{
|
||||
local action="$1"
|
||||
local attribute="node_ip"
|
||||
- local value
|
||||
+ local ip_addr name
|
||||
|
||||
- if ! value=$(ip -brief addr show "$OCF_RESKEY_nic" | awk '{gsub("/.*", "", $3); print $3}'); then
|
||||
- rc=$?
|
||||
- ocf_log err "could not get node ip, error code: $rc"
|
||||
- return "$rc"
|
||||
+ for node in $(echo "$OCF_RESKEY_node_ip_map" | sed "s/\s//g;s/;/ /g"); do
|
||||
+ name=$(echo "$node" | cut -d: -f1)
|
||||
+ # ignore other nodes
|
||||
+ if [ "$name" != "$NODENAME" ]; then
|
||||
+ continue
|
||||
+ fi
|
||||
+ ip_addr=$(echo "$node" | cut -d: -f2-) # Grab everything after the first : this covers ipv4/ipv6
|
||||
+ done
|
||||
+
|
||||
+ if [ -z "$ip_addr" ]; then
|
||||
+ ocf_log err "ip address was empty when querying (getent ahosts) for hostname: $(hostname -f)"
|
||||
+ return 1
|
||||
fi
|
||||
|
||||
case "$action" in
|
||||
get)
|
||||
- echo "$value"
|
||||
+ echo "$ip_addr"
|
||||
;;
|
||||
update)
|
||||
if ! crm_attribute --type nodes --node "$NODENAME" --name "$attribute" --update "$value"; then
|
||||
@@ -409,26 +429,28 @@ get_env_from_manifest() {
|
||||
}
|
||||
|
||||
prepare_env() {
|
||||
- local name ip standalone_node
|
||||
+ local name ip ipurl standalone_node
|
||||
|
||||
NODEIP="$(attribute_node_ip get)"
|
||||
+ NODEIPURL=$(ip_url $NODEIP)
|
||||
|
||||
if is_force_new_cluster; then
|
||||
- ALL_ETCD_ENDPOINTS="https://$NODEIP:2379"
|
||||
+ ALL_ETCD_ENDPOINTS="$NODEIPURL:2379"
|
||||
ETCD_INITIAL_CLUSTER_STATE="new"
|
||||
- ETCD_INITIAL_CLUSTER="$NODENAME=https://$NODEIP:2380"
|
||||
+ ETCD_INITIAL_CLUSTER="$NODENAME=$NODEIPURL:2380"
|
||||
else
|
||||
ETCD_INITIAL_CLUSTER_STATE="existing"
|
||||
for node in $(echo "$OCF_RESKEY_node_ip_map" | sed "s/\s//g;s/;/ /g"); do
|
||||
- name=$(echo "$node" | awk -F":" '{print $1}')
|
||||
- ip=$(echo "$node" | awk -F":" '{print $2}')
|
||||
+ name=$(echo "$node" | cut -d: -f1)
|
||||
+ ip=$(echo "$node" | cut -d: -f2-) # Grab everything after the first : this covers ipv4/ipv6
|
||||
+ ipurl="$(ip_url $ip)"
|
||||
if [ -z "$name" ] || [ -z "$ip" ]; then
|
||||
ocf_exit_reason "name or ip missing for 1 or more nodes"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
- [ -z "$ALL_ETCD_ENDPOINTS" ] && ALL_ETCD_ENDPOINTS="https://$ip:2379" || ALL_ETCD_ENDPOINTS="$ALL_ETCD_ENDPOINTS,https://$ip:2379"
|
||||
- [ -z "$ETCD_INITIAL_CLUSTER" ] && ETCD_INITIAL_CLUSTER="$name=https://$ip:2380" || ETCD_INITIAL_CLUSTER="$ETCD_INITIAL_CLUSTER,$name=https://$ip:2380"
|
||||
+ [ -z "$ALL_ETCD_ENDPOINTS" ] && ALL_ETCD_ENDPOINTS="$ipurl:2379" || ALL_ETCD_ENDPOINTS="$ALL_ETCD_ENDPOINTS,$ipurl:2379"
|
||||
+ [ -z "$ETCD_INITIAL_CLUSTER" ] && ETCD_INITIAL_CLUSTER="$name=$ipurl:2380" || ETCD_INITIAL_CLUSTER="$ETCD_INITIAL_CLUSTER,$name=$ipurl:2380"
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -609,9 +631,11 @@ add_member_as_learner()
|
||||
local rc
|
||||
local member_name=$1
|
||||
local member_ip=$2
|
||||
+ local endpoint_url=$(ip_url $(attribute_node_ip get))
|
||||
+ 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="https://$(attribute_node_ip get):2379" member add "$member_name" --peer-urls="https://$member_ip:2380" --learner)
|
||||
+ out=$(podman exec "${CONTAINER}" etcdctl --endpoints="$endpoint_url:2379" member add "$member_name" --peer-urls="$peer_url:2380" --learner)
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
ocf_log err "could not add $member_name as learner, error code: $rc"
|
||||
@@ -806,14 +830,15 @@ get_peer_node_name() {
|
||||
|
||||
get_all_etcd_endpoints() {
|
||||
for node in $(echo "$OCF_RESKEY_node_ip_map" | sed "s/\s//g;s/;/ /g"); do
|
||||
- name=$(echo "$node" | awk -F":" '{print $1}')
|
||||
- ip=$(echo "$node" | awk -F":" '{print $2}')
|
||||
+ name=$(echo "$node" | cut -d: -f1)
|
||||
+ ip=$(echo "$node" | cut -d: -f2-) # Grab everything after the first : this covers ipv4/ipv6
|
||||
+ ipurl="$(ip_url $ip)"
|
||||
if [ -z "$name" ] || [ -z "$ip" ]; then
|
||||
ocf_exit_reason "name or ip missing for 1 or more nodes"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
- [ -z "$ALL_ETCD_ENDPOINTS" ] && ALL_ETCD_ENDPOINTS="https://$ip:2379" || ALL_ETCD_ENDPOINTS="$ALL_ETCD_ENDPOINTS,https://$ip:2379"
|
||||
+ [ -z "$ALL_ETCD_ENDPOINTS" ] && ALL_ETCD_ENDPOINTS="$ipurl:2379" || ALL_ETCD_ENDPOINTS="$ALL_ETCD_ENDPOINTS,$ipurl:2379"
|
||||
done
|
||||
echo "$ALL_ETCD_ENDPOINTS"
|
||||
}
|
||||
@@ -831,7 +856,7 @@ get_member_list_json() {
|
||||
# Get the list of members visible to the current node
|
||||
local this_node_endpoint
|
||||
|
||||
- this_node_endpoint="https://$(attribute_node_ip get):2379"
|
||||
+ this_node_endpoint="$(ip_url $(attribute_node_ip get)):2379"
|
||||
podman exec "${CONTAINER}" etcdctl member list --endpoints="$this_node_endpoint" -w json
|
||||
}
|
||||
|
||||
@@ -886,14 +911,14 @@ check_peers()
|
||||
# ]
|
||||
# }
|
||||
for node in $(echo "$OCF_RESKEY_node_ip_map" | sed "s/\s//g;s/;/ /g"); do
|
||||
- name=$(echo "$node" | awk -F":" '{print $1}')
|
||||
+ name=$(echo "$node" | cut -d: -f1)
|
||||
# do not check itself
|
||||
if [ "$name" = "$NODENAME" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check by IP instead of Name since "learner" members appear only in peerURLs, not by Name.
|
||||
- ip=$(echo "$node" | awk -F":" '{print $2}')
|
||||
+ ip=$(echo "$node" | cut -d: -f2-) # Grab everything after the first : this covers ipv4/ipv6
|
||||
id=$(printf "%s" "$member_list_json" | jq -r ".members[] | select( .peerURLs | map(test(\"$ip\")) | any).ID")
|
||||
if [ -z "$id" ]; then
|
||||
ocf_log info "$name is not in the members list"
|
||||
@@ -1307,7 +1332,7 @@ podman_start()
|
||||
--log-level=info \
|
||||
--experimental-initial-corrupt-check=true \
|
||||
--snapshot-count=10000 \
|
||||
- --initial-advertise-peer-urls=https://${NODEIP}:2380 \
|
||||
+ --initial-advertise-peer-urls=$NODEIPURL:2380 \
|
||||
--cert-file=/etc/kubernetes/static-pod-certs/secrets/etcd-all-certs/etcd-serving-${NODENAME}.crt \
|
||||
--key-file=/etc/kubernetes/static-pod-certs/secrets/etcd-all-certs/etcd-serving-${NODENAME}.key \
|
||||
--trusted-ca-file=$SERVER_CACERT \
|
||||
@@ -1316,11 +1341,11 @@ podman_start()
|
||||
--peer-key-file=$ETCD_PEER_KEY \
|
||||
--peer-trusted-ca-file=$SERVER_CACERT \
|
||||
--peer-client-cert-auth=true \
|
||||
- --advertise-client-urls=https://${NODEIP}:2379 \
|
||||
- --listen-client-urls=https://${LISTEN_CLIENT_URLS}:2379,unixs://${NODEIP}:0 \
|
||||
- --listen-peer-urls=https://${LISTEN_PEER_URLS}:2380 \
|
||||
+ --advertise-client-urls=$NODEIPURL:2379 \
|
||||
+ --listen-client-urls=$(ip_url ${LISTEN_CLIENT_URLS}):2379,unixs://${NODEIP}:0 \
|
||||
+ --listen-peer-urls=$(ip_url ${LISTEN_PEER_URLS}):2380 \
|
||||
--metrics=extensive \
|
||||
- --listen-metrics-urls=https://${LISTEN_METRICS_URLS}:9978"
|
||||
+ --listen-metrics-urls=$(ip_url ${LISTEN_METRICS_URLS}):9978"
|
||||
if [ -n "$OCF_RESKEY_run_cmd_opts" ]; then
|
||||
OCF_RESKEY_run_cmd="$OCF_RESKEY_run_cmd $OCF_RESKEY_run_cmd_opts"
|
||||
fi
|
||||
@@ -1430,7 +1455,7 @@ podman_stop()
|
||||
ocf_log info "last member. Not leaving the member list"
|
||||
else
|
||||
ocf_log info "leaving members list as member with ID $member_id"
|
||||
- endpoint="https://$(attribute_node_ip get):2379"
|
||||
+ endpoint="$(ip_url $(attribute_node_ip get)):2379"
|
||||
if ! ocf_run podman exec "$CONTAINER" etcdctl member remove "$member_id" --endpoints="$endpoint"; then
|
||||
rc=$?
|
||||
ocf_log err "error leaving members list, error code: $rc"
|
@ -0,0 +1,684 @@
|
||||
From 90e4402ee81ee107d9e7b99e6908289b00a39a4c Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 20 May 2025 09:59:54 +0200
|
||||
Subject: [PATCH] portblock: add nftables and multi-state support
|
||||
|
||||
---
|
||||
heartbeat/ocf-binaries.in | 1 +
|
||||
heartbeat/portblock | 389 ++++++++++++++++++++++++++++++--------
|
||||
2 files changed, 307 insertions(+), 83 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-binaries.in b/heartbeat/ocf-binaries.in
|
||||
index e11ae1d6f..aed6eecae 100644
|
||||
--- a/heartbeat/ocf-binaries.in
|
||||
+++ b/heartbeat/ocf-binaries.in
|
||||
@@ -26,6 +26,7 @@ export PATH
|
||||
: ${GETENT:=getent}
|
||||
: ${GREP:=grep}
|
||||
: ${IFCONFIG:=ifconfig}
|
||||
+: ${NFTABLES:=nft}
|
||||
: ${IPTABLES:=iptables}
|
||||
## for cases that are known not to be serviceable with iptables-nft impl.
|
||||
: ${IPTABLES_LEGACY:=iptables-legacy}
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index 9b4f5db39..1eea28a6d 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -1,9 +1,10 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
-# portblock: iptables temporary portblocking control
|
||||
+# portblock: iptables temporary portblocking control
|
||||
#
|
||||
# Author: Sun Jiang Dong (initial version)
|
||||
# Philipp Reisner (per-IP filtering)
|
||||
+# Sebastian Baszczyj (nftables code)
|
||||
#
|
||||
# License: GNU General Public License (GPL)
|
||||
#
|
||||
@@ -23,6 +24,7 @@
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
# Defaults
|
||||
+OCF_RESKEY_firewall_default="auto"
|
||||
OCF_RESKEY_protocol_default=""
|
||||
OCF_RESKEY_portno_default=""
|
||||
OCF_RESKEY_direction_default="in"
|
||||
@@ -32,6 +34,7 @@ OCF_RESKEY_reset_local_on_unblock_stop_default="false"
|
||||
OCF_RESKEY_tickle_dir_default=""
|
||||
OCF_RESKEY_sync_script_default=""
|
||||
|
||||
+: ${OCF_RESKEY_firewall=${OCF_RESKEY_firewall_default}}
|
||||
: ${OCF_RESKEY_protocol=${OCF_RESKEY_protocol_default}}
|
||||
: ${OCF_RESKEY_portno=${OCF_RESKEY_portno_default}}
|
||||
: ${OCF_RESKEY_direction=${OCF_RESKEY_direction_default}}
|
||||
@@ -43,13 +46,17 @@ OCF_RESKEY_sync_script_default=""
|
||||
#######################################################################
|
||||
CMD=`basename $0`
|
||||
TICKLETCP=$HA_BIN/tickle_tcp
|
||||
+TABLE="portblock"
|
||||
+# Promotion scores
|
||||
+SCORE_UNPROMOTED=5
|
||||
+SCORE_PROMOTED=10
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<END >&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.
|
||||
+ $CMD is used to temporarily block ports using nftables or iptables.
|
||||
|
||||
It can be used to blackhole a port before bringing
|
||||
up an IP address, and enable it after a service is started.
|
||||
@@ -86,8 +93,8 @@ usage()
|
||||
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 +102,7 @@ usage()
|
||||
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 +110,18 @@ usage()
|
||||
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,17 +144,29 @@ meta_data() {
|
||||
<version>1.0</version>
|
||||
|
||||
<longdesc lang="en">
|
||||
-Resource script for portblock. It is used to temporarily 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.
|
||||
+Resource script for portblock. It is used to block ports using nftables
|
||||
+or 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 ports on the Promoted node
|
||||
+and blocks the ports on the Unpromoted node(s) when action=block, and vice versa
|
||||
+when action=unblock.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Block and unblocks access to TCP and UDP ports</shortdesc>
|
||||
|
||||
<parameters>
|
||||
+<parameter name="firewall" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Firewall to use, e.g. auto (default), nft, or iptables.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Firewall</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_firewall_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="protocol" unique="0" required="1">
|
||||
<longdesc lang="en">
|
||||
The protocol used to be blocked/unblocked.
|
||||
@@ -167,6 +186,9 @@ The port number used to be blocked/unblocked.
|
||||
<parameter name="action" unique="0" required="1">
|
||||
<longdesc lang="en">
|
||||
The action (block/unblock) to be done on the protocol::portno.
|
||||
+
|
||||
+In Promotable mode it is the initial action for start/demote actions,
|
||||
+and the promote action will change the state to the opposite.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">action</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_action_default}" />
|
||||
@@ -202,7 +224,7 @@ The IP address used to be blocked/unblocked.
|
||||
|
||||
<parameter name="tickle_dir" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
-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.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Tickle directory</shortdesc>
|
||||
@@ -236,6 +258,8 @@ If "both" is used, both the incoming and outgoing ports are blocked.
|
||||
<actions>
|
||||
<action name="start" timeout="20s" />
|
||||
<action name="stop" timeout="20s" />
|
||||
+<action name="promote" timeout="10s"/>
|
||||
+<action name="demote" timeout="10s"/>
|
||||
<action name="status" depth="0" timeout="10s" interval="10s" />
|
||||
<action name="monitor" depth="0" timeout="10s" interval="10s" />
|
||||
<action name="meta-data" timeout="5s" />
|
||||
@@ -269,11 +293,17 @@ active_grep_pat()
|
||||
# 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
|
||||
+ if [ "$FIREWALL" = "nft" ]; then
|
||||
+ local ip
|
||||
+ [ "$4" = "s" ] && ip=$src || ip=$dst
|
||||
+ echo "^\s\+ip $4addr ${ip} $1 $4port $2 ct state { established, related, new } drop$"
|
||||
+ else
|
||||
+ echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$"
|
||||
fi
|
||||
- echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$"
|
||||
}
|
||||
|
||||
#chain_isactive {udp|tcp} portno,portno ip chain
|
||||
@@ -281,7 +311,11 @@ chain_isactive()
|
||||
{
|
||||
[ "$4" = "OUTPUT" ] && ds="s" || ds="d"
|
||||
PAT=$(active_grep_pat "$1" "$2" "$3" "$ds")
|
||||
- $IPTABLES $wait -n -L "$4" | grep -qE "$PAT"
|
||||
+ if [ "$FIREWALL" = "nft" ]; then
|
||||
+ $NFTABLES list chain inet $TABLE $4 2>&1 | grep -q "$PAT"
|
||||
+ else
|
||||
+ $IPTABLES $wait -n -L "$4" | grep -q "$PAT"
|
||||
+ fi
|
||||
}
|
||||
|
||||
# netstat -tn and ss -Htn, split on whitespace and colon,
|
||||
@@ -372,8 +406,8 @@ SayInactive()
|
||||
ocf_log debug "$CMD DROP rule [$*] is inactive"
|
||||
}
|
||||
|
||||
-#IptablesStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
-IptablesStatus() {
|
||||
+#PortStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
+PortStatus() {
|
||||
local rc
|
||||
rc=$OCF_ERR_GENERIC
|
||||
is_active=0
|
||||
@@ -397,6 +431,17 @@ IptablesStatus() {
|
||||
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)
|
||||
@@ -424,29 +469,56 @@ IptablesStatus() {
|
||||
return $rc
|
||||
}
|
||||
|
||||
-#DoIptables {-I|-D} {udp|tcp} portno,portno ip chain
|
||||
-DoIptables()
|
||||
+#NftDelete chain proto {d|s} ip ports
|
||||
+NftDelete()
|
||||
+{
|
||||
+ local chain=$1 proto=$2 ds=$3 ip=$(echo "$4" | sed "s#/#\\\/#") ports=$5
|
||||
+ # Try both single port and multi-port patterns for handle search
|
||||
+ local handles=$($NFTABLES -a list chain inet $TABLE $chain 2>/dev/null | awk "/\s+ip ${ds}addr $ip $proto ${ds}port $ports/"' {printf "%d ", $NF}')
|
||||
+ for handle in $handles; do
|
||||
+ ocf_log debug "NftDelete: Deleting $chain rule with handle $handle"
|
||||
+ nft delete rule inet $TABLE $chain handle $handle || {
|
||||
+ ocf_exit_reason "NftDelete: Failed to delete $chain handle $handle."
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ }
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+#DoPort {-I|-D} {udp|tcp} portno,portno ip chain
|
||||
+DoPort()
|
||||
{
|
||||
op=$1 proto=$2 ports=$3 ip=$4 chain=$5
|
||||
active=0; chain_isactive "$proto" "$ports" "$ip" "$chain" && active=1
|
||||
- want_active=0; [ "$op" = "-I" ] && want_active=1
|
||||
+ want_active=0; { [ "$op" = "insert" ] || [ "$op" = "-I" ] && want_active=1; }
|
||||
ocf_log debug "active: $active want_active: $want_active"
|
||||
if [ $active -eq $want_active ] ; then
|
||||
: 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
|
||||
+ case $FIREWALL in
|
||||
+ nft)
|
||||
+ if [ "$op" = "insert" ]; then
|
||||
+ $NFTABLES $op rule inet $TABLE $chain ip ${ds}addr $ip $proto ${ds}port $ports ct state { established, related, new } drop
|
||||
+ elif [ "$op" = "delete" ]; then
|
||||
+ NftDelete "$chain" "$proto" "$ds" "$ip" "$ports"
|
||||
+ fi
|
||||
+ ;;
|
||||
+ iptables)
|
||||
+ $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -j DROP
|
||||
+ ;;
|
||||
+ esac
|
||||
fi
|
||||
}
|
||||
|
||||
-#IptablesBLOCK {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
-IptablesBLOCK()
|
||||
+#PortBLOCK {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
+PortBLOCK()
|
||||
{
|
||||
local rc_in=0
|
||||
local rc_out=0
|
||||
+ [ "$FIREWALL" = "nft" ] && action="insert" || action="-I"
|
||||
if [ "$4" = "in" ] || [ "$4" = "both" ]; then
|
||||
local try_reset=false
|
||||
- if [ "$1/$5/$__OCF_ACTION" = tcp/unblock/stop ] &&
|
||||
+ if [ "$1/$5/$__OCF_ACTION" = tcp/unblock/stop ] &&
|
||||
ocf_is_true $reset_local_on_unblock_stop
|
||||
then
|
||||
try_reset=true
|
||||
@@ -456,73 +528,168 @@ IptablesBLOCK()
|
||||
then
|
||||
: OK -- chain already active
|
||||
else
|
||||
- if $try_reset ; then
|
||||
- $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
|
||||
- rc_in=$?
|
||||
- if $try_reset ; then
|
||||
- $IPTABLES $wait -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
+ if [ "$FIREWALL" = "nft" ]; then
|
||||
+ if $try_reset ; then
|
||||
+ $NFTABLES insert rule inet $TABLE OUTPUT ip saddr $3 $1 sport $2 ct state { established, related, new } reject with tcp reset
|
||||
+ tickle_local
|
||||
+ fi
|
||||
+ $NFTABLES insert rule inet $TABLE INPUT ip daddr $3 $1 dport $2 ct state { established, related, new } drop
|
||||
+ rc_in=$?
|
||||
+ if $try_reset ; then
|
||||
+ NftDelete "OUTPUT" "$1" "s" "$ports"
|
||||
+ fi
|
||||
+ else
|
||||
+ if $try_reset ; then
|
||||
+ $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
|
||||
+ rc_in=$?
|
||||
+ if $try_reset ; then
|
||||
+ $IPTABLES $wait -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
+ fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ "$4" = "out" ] || [ "$4" = "both" ]; then
|
||||
- DoIptables -I "$1" "$2" "$3" OUTPUT
|
||||
+ DoPort "$action" "$1" "$2" "$3" OUTPUT
|
||||
rc_out=$?
|
||||
fi
|
||||
|
||||
[ $rc_in -gt $rc_out ] && return $rc_in || return $rc_out
|
||||
}
|
||||
|
||||
-#IptablesUNBLOCK {udp|tcp} portno,portno ip {in|out|both}
|
||||
-IptablesUNBLOCK()
|
||||
+#PortUNBLOCK {udp|tcp} portno,portno ip {in|out|both}
|
||||
+PortUNBLOCK()
|
||||
{
|
||||
+ local action
|
||||
+ [ "$FIREWALL" = "nft" ] && action="delete" || action="-D"
|
||||
if [ "$4" = "in" ] || [ "$4" = "both" ]; then
|
||||
- DoIptables -D "$1" "$2" "$3" INPUT
|
||||
+ DoPort "$action" "$1" "$2" "$3" INPUT
|
||||
fi
|
||||
if [ "$4" = "out" ] || [ "$4" = "both" ]; then
|
||||
- DoIptables -D "$1" "$2" "$3" OUTPUT
|
||||
+ DoPort "$action" "$1" "$2" "$3" OUTPUT
|
||||
fi
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
-#IptablesStart {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
-IptablesStart()
|
||||
+#PortStart {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
+PortStart()
|
||||
{
|
||||
ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" start
|
||||
+
|
||||
+ if [ "$FIREWALL" = "nft" ]; then
|
||||
+ $NFTABLES add table inet $TABLE || {
|
||||
+ ocf_exit_reason "Failed to create nftables table $TABLE"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ }
|
||||
+ ocf_log debug "Created nftables table $TABLE"
|
||||
+
|
||||
+ $NFTABLES add chain inet $TABLE INPUT { type filter hook input priority 0\; } || {
|
||||
+ ocf_exit_reason "Failed to create INPUT chain"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ }
|
||||
+ ocf_log debug "Created INPUT chain"
|
||||
+
|
||||
+ $NFTABLES add chain inet $TABLE OUTPUT { type filter hook output priority 0\; } || {
|
||||
+ ocf_exit_reason "Failed to create OUTPUT chain"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ }
|
||||
+ ocf_log debug "Created OUTPUT chain"
|
||||
+ fi
|
||||
+
|
||||
case $5 in
|
||||
- block) IptablesBLOCK "$@";;
|
||||
+ block) PortBLOCK "$@"
|
||||
+ rc=$?
|
||||
+ ;;
|
||||
unblock)
|
||||
- IptablesUNBLOCK "$@"
|
||||
+ PortUNBLOCK "$@"
|
||||
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}
|
||||
-IptablesStop()
|
||||
+#PortStop {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
+PortStop()
|
||||
{
|
||||
ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" stop
|
||||
+
|
||||
case $5 in
|
||||
- block) IptablesUNBLOCK "$@";;
|
||||
+ block) PortUNBLOCK "$@"
|
||||
+ rc=$?
|
||||
+ ;;
|
||||
unblock)
|
||||
save_tcp_connections
|
||||
- IptablesBLOCK "$@"
|
||||
+ PortBLOCK "$@"
|
||||
+ rc=$?
|
||||
;;
|
||||
- *) usage; return 1;;
|
||||
+ *) usage; return $OCF_ERR_CONFIGURED ;;
|
||||
esac
|
||||
|
||||
+ ocf_is_ms && ocf_promotion_score -D -N $nodename
|
||||
+
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
+PortPromote() {
|
||||
+ PortStatus "$@"
|
||||
+ 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: PortStatus failed with rc: $rc."
|
||||
+ return $rc
|
||||
+ fi
|
||||
+ case $5 in
|
||||
+ block) PortBLOCK "$@"
|
||||
+ rc=$?
|
||||
+ ;;
|
||||
+ unblock)
|
||||
+ PortUNBLOCK "$@"
|
||||
+ rc=$?
|
||||
+ tickle_remote
|
||||
+ #ignore run_tickle_tcp exit code!
|
||||
+ ;;
|
||||
+ *) usage; return $OCF_ERR_CONFIGURED ;
|
||||
+ esac
|
||||
+ ocf_promotion_score -v $SCORE_PROMOTED -N $nodename
|
||||
return $?
|
||||
}
|
||||
|
||||
+PortDemote() {
|
||||
+ PortStatus "$@"
|
||||
+ 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: PortStatus failed with rc: $rc."
|
||||
+ return $rc
|
||||
+ fi
|
||||
+ case $5 in
|
||||
+ block)
|
||||
+ save_tcp_connections
|
||||
+ PortBLOCK "$@"
|
||||
+ rc=$?
|
||||
+ ;;
|
||||
+ unblock) PortUNBLOCK "$@"
|
||||
+ 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
|
||||
#
|
||||
@@ -532,9 +699,15 @@ CheckPort() {
|
||||
echo $1 | $EGREP -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*'
|
||||
}
|
||||
|
||||
-IptablesValidateAll()
|
||||
+PortValidateAll()
|
||||
{
|
||||
- check_binary $IPTABLES
|
||||
+ case $FIREWALL in
|
||||
+ nft)
|
||||
+ check_binary $IPTABLES ;;
|
||||
+ iptables)
|
||||
+ check_binary $NFTABLES ;;
|
||||
+ esac
|
||||
+
|
||||
case $protocol in
|
||||
tcp|udp)
|
||||
;;
|
||||
@@ -558,17 +731,17 @@ IptablesValidateAll()
|
||||
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
|
||||
@@ -584,6 +757,20 @@ IptablesValidateAll()
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+# Detect firewall tool
|
||||
+detect_firewall_tool() {
|
||||
+ if have_binary nft; then
|
||||
+ FIREWALL="nft"
|
||||
+ ocf_log debug "Detected nftables"
|
||||
+ elif have_binary iptables; then
|
||||
+ FIREWALL="iptables"
|
||||
+ ocf_log debug "Detected iptables"
|
||||
+ else
|
||||
+ ocf_exit_reason "No firewall tool available"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
if
|
||||
( [ $# -ne 1 ] )
|
||||
then
|
||||
@@ -591,7 +778,7 @@ then
|
||||
exit $OCF_ERR_ARGS
|
||||
fi
|
||||
|
||||
-case $1 in
|
||||
+case $__OCF_ACTION in
|
||||
meta-data) meta_data
|
||||
exit $OCF_SUCCESS
|
||||
;;
|
||||
@@ -605,25 +792,16 @@ esac
|
||||
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"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
-fi
|
||||
-
|
||||
-# iptables v1.4.20+ is required to use -w (wait)
|
||||
-version=$(iptables -V | grep -oE '[0-9]+[\.0-9]+')
|
||||
-ocf_version_cmp "$version" "1.4.19.1"
|
||||
-if [ "$?" -eq "2" ]; then
|
||||
- wait="-w"
|
||||
-else
|
||||
- wait=""
|
||||
fi
|
||||
|
||||
protocol=$OCF_RESKEY_protocol
|
||||
@@ -632,6 +810,7 @@ direction=$OCF_RESKEY_direction
|
||||
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,21 +826,65 @@ if [ -n "$OCF_RESKEY_tickle_dir" ] ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
-case $1 in
|
||||
- start)
|
||||
- IptablesStart $protocol $portno $ip $direction $action
|
||||
+case $OCF_RESKEY_firewall in
|
||||
+ auto)
|
||||
+ detect_firewall_tool
|
||||
+ ;;
|
||||
+ nft|iptables)
|
||||
+ FIREWALL="$OCF_RESKEY_firewall"
|
||||
+ ;;
|
||||
+ *)
|
||||
+ ocf_exit_reason "Firewall '$OCF_RESKEY_firewall' not supported."
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+if [ "$FIREWALL" = "nft" ]; then
|
||||
+ echo "$portno" | grep -q "," && portno="{ $(echo $portno | sed 's/,/, /g') }"
|
||||
+elif [ "$FIREWALL" = "iptables" ]; then
|
||||
+ # iptables v1.4.20+ is required to use -w (wait)
|
||||
+ version=$(iptables -V | grep -oE '[0-9]+[\.0-9]+')
|
||||
+ ocf_version_cmp "$version" "1.4.19.1"
|
||||
+ if [ "$?" -eq "2" ]; then
|
||||
+ wait="-w"
|
||||
+ else
|
||||
+ wait=""
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+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)
|
||||
+ PortStart "$protocol" "$portno" "$ip" "$direction" "$action"
|
||||
+ ;;
|
||||
+
|
||||
+ stop)
|
||||
+ PortStop "$protocol" "$portno" "$ip" "$direction" "$action"
|
||||
+ ;;
|
||||
+
|
||||
+ promote)
|
||||
+ PortPromote $protocol "$portno" "$ip" "$direction" "$action"
|
||||
;;
|
||||
|
||||
- stop)
|
||||
- IptablesStop $protocol $portno $ip $direction $action
|
||||
+ demote)
|
||||
+ PortDemote "$protocol" "$portno" "$ip" "$direction" "$action"
|
||||
;;
|
||||
|
||||
- status|monitor)
|
||||
- IptablesStatus $protocol $portno $ip $direction $action
|
||||
+ status|monitor)
|
||||
+ PortStatus "$protocol" "$portno" "$ip" "$direction" "$action"
|
||||
;;
|
||||
|
||||
validate-all)
|
||||
- IptablesValidateAll
|
||||
+ PortValidateAll
|
||||
;;
|
||||
|
||||
*) usage
|
@ -0,0 +1,50 @@
|
||||
From ed2fdbb58d874d3a331425b360d7358b7a5b195e Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 29 Sep 2025 11:04:40 +0200
|
||||
Subject: [PATCH] portblock: fix incorrect promotable description
|
||||
|
||||
---
|
||||
heartbeat/portblock | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index 1eea28a6d..ff162c955 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -152,11 +152,11 @@ 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 ports on the Promoted node
|
||||
-and blocks the ports on the Unpromoted node(s) when action=block, and vice versa
|
||||
-when action=unblock.
|
||||
+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.
|
||||
</longdesc>
|
||||
-<shortdesc lang="en">Block and unblocks access to TCP and UDP ports</shortdesc>
|
||||
+<shortdesc lang="en">Blocks and unblocks access to TCP and UDP ports</shortdesc>
|
||||
|
||||
<parameters>
|
||||
<parameter name="firewall" unique="0" required="0">
|
||||
@@ -187,8 +187,9 @@ The port number used to be blocked/unblocked.
|
||||
<longdesc lang="en">
|
||||
The action (block/unblock) to be done on the protocol::portno.
|
||||
|
||||
-In Promotable mode it is the initial action for start/demote actions,
|
||||
-and the promote action will change the state to the opposite.
|
||||
+In Promotable mode it is the action for the promote action,
|
||||
+and the opposite action will be used for the start and demote
|
||||
+actions.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">action</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_action_default}" />
|
||||
@@ -872,7 +873,7 @@ case $__OCF_ACTION in
|
||||
;;
|
||||
|
||||
promote)
|
||||
- PortPromote $protocol "$portno" "$ip" "$direction" "$action"
|
||||
+ PortPromote "$protocol" "$portno" "$ip" "$direction" "$action"
|
||||
;;
|
||||
|
||||
demote)
|
@ -0,0 +1,186 @@
|
||||
From 1afdd91b2961061937fc802c575304ede8d79286 Mon Sep 17 00:00:00 2001
|
||||
From: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
Date: Wed, 10 Sep 2025 16:56:56 +0200
|
||||
Subject: [PATCH] podman-etcd: Add cluster-wide force_new_cluster attribute
|
||||
checking
|
||||
|
||||
Implement cluster-wide validation of force_new_cluster attribute to resolve
|
||||
race conditions during automated cluster recovery. The enhancement ensures
|
||||
agents check for the cluster-wide attribute before falling back to local
|
||||
etcd revision comparison.
|
||||
|
||||
Key changes:
|
||||
- Enhanced get_force_new_cluster() to query all cluster nodes
|
||||
- Ensure force_new_cluster is not set in both nodes to prevent
|
||||
conflicting recovery attempts
|
||||
- Updated startup logic to prioritize cluster-wide attribute checking
|
||||
|
||||
fixes OCPBUGS-61117
|
||||
---
|
||||
heartbeat/podman-etcd | 107 ++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 72 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 33804414a..f3a6da5e2 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -794,54 +794,72 @@ set_force_new_cluster()
|
||||
return $rc
|
||||
}
|
||||
|
||||
+# get_force_new_cluster returns a space-separated list of nodes that have the force_new_cluster attribute set.
|
||||
+# Return values:
|
||||
+# - Exit code 0 with non-empty output: One or more nodes have the force_new_cluster attribute set
|
||||
+# - Exit code 0 with empty output: No nodes have the force_new_cluster attribute set
|
||||
+# - Exit code 1 with empty output: Error occurred while querying the cluster nodes
|
||||
get_force_new_cluster()
|
||||
{
|
||||
- crm_attribute --lifetime reboot --query --name "force_new_cluster" | awk -F"value=" '{print $2}'
|
||||
+ local node nodes value
|
||||
+ local holders=""
|
||||
+
|
||||
+ if ! nodes=$(crm_node -l | awk '{print $2}'); then
|
||||
+ ocf_log err "could not get force_new_cluster attribute, crm_node error code: $?"
|
||||
+ return 1
|
||||
+ fi
|
||||
+ if [ -z "$nodes" ]; then
|
||||
+ ocf_log err "could not get force_new_cluster attribute, the list of nodes is empty"
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ for node in $nodes; do
|
||||
+ if ! value=$(crm_attribute --query --lifetime reboot --name "force_new_cluster" --node "$node" 2>/dev/null | awk -F'value=' '{print $2}' | tr -d "'"); then
|
||||
+ ocf_log err "could not get force_new_cluster attribute, crm_attribut error code: $?"
|
||||
+ return 1
|
||||
+ fi
|
||||
+ if [ -n "$value" ]; then
|
||||
+ holders="$holders$node "
|
||||
+ fi
|
||||
+ done
|
||||
+ echo "$holders"
|
||||
}
|
||||
|
||||
+
|
||||
clear_force_new_cluster()
|
||||
{
|
||||
- local force_new_cluster_node
|
||||
-
|
||||
- force_new_cluster_node=$(get_force_new_cluster)
|
||||
- if [ -z "$force_new_cluster_node" ]; then
|
||||
- ocf_log info "$NODENAME: force_new_cluster attribute not set"
|
||||
+ # only the holder of "force_new_cluster" attribute can delete it
|
||||
+ if ! is_force_new_cluster; then
|
||||
+ ocf_log info "force_new_cluster unset or not owned by $NODENAME"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- # only the holder of "force_new_cluster" attribute can delete it
|
||||
- if [ "$NODENAME" = "$force_new_cluster_node" ]; then
|
||||
- crm_attribute --lifetime reboot --name "force_new_cluster" --delete
|
||||
- rc=$?
|
||||
- if [ $rc -ne 0 ]; then
|
||||
- ocf_log err "could not clear force_new_cluster attribute, error code: $rc"
|
||||
- else
|
||||
- ocf_log info "$NODENAME: force_new_cluster attribute cleared"
|
||||
- fi
|
||||
- return $rc
|
||||
- else
|
||||
- ocf_log info "$NODENAME does not hold force_new_cluster ($force_new_cluster_node has it)"
|
||||
- return $OCF_SUCCESS
|
||||
+ if ! crm_attribute --delete --lifetime reboot --node "$NODENAME" --name "force_new_cluster"; then
|
||||
+ ocf_log err "could not clear force_new_cluster attribute, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
+
|
||||
+ ocf_log info "$NODENAME: force_new_cluster attribute cleared"
|
||||
+ return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+
|
||||
is_force_new_cluster()
|
||||
{
|
||||
- # Return 0 if 'force_new_cluster' is set and the value matches the current node name, 1 otherwise.
|
||||
- local value
|
||||
+ # Return 0 if 'force_new_cluster' is set on the current node, 1 otherwise.
|
||||
+ local fnc_holders
|
||||
|
||||
- value=$(get_force_new_cluster)
|
||||
- if [ -z "$value" ]; then
|
||||
- ocf_log debug "force_new_cluster attribute is not set"
|
||||
- return 1
|
||||
+ if ! fnc_holders=$(get_force_new_cluster); then
|
||||
+ ocf_exit_reason "is_force_new_cluster: Failed to get force_new_cluster node holders"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- if [ "$value" = "$NODENAME" ]; then
|
||||
+ if echo "$fnc_holders" | grep -q -w "$NODENAME"; then
|
||||
ocf_log debug "$NODENAME has force_new_cluster set"
|
||||
return 0
|
||||
fi
|
||||
|
||||
- ocf_log info "force_new_cluster attribute set on peer node $value"
|
||||
+ ocf_log debug "force_new_cluster attribute is not set on $NODENAME"
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -1415,17 +1433,34 @@ podman_start()
|
||||
return "$OCF_ERR_GENERIC"
|
||||
fi
|
||||
|
||||
- # force-new-cluster property is a runtime-scoped flag that instructs the agent to force a new cluster-of-1.
|
||||
- # Since this attribute is configured with a reboot-lifetime, it is automatically cleared when the machine reboots.
|
||||
- # If the agent detects during its start that this property is set, it indicates that the flag was explicitly set
|
||||
- # during the current node boot session, implying a deliberate request to recover the cluster.
|
||||
if ocf_is_true "$pod_was_running"; then
|
||||
ocf_log info "static pod was running: start normally"
|
||||
else
|
||||
- if is_force_new_cluster; then
|
||||
- ocf_log notice "'$NODENAME' marked to force-new-cluster"
|
||||
+ local fnc_holders
|
||||
+ if ! fnc_holders=$(get_force_new_cluster); then
|
||||
+ ocf_exit_reason "Failed to get force_new_cluster node holders"
|
||||
+ return "$OCF_ERR_GENERIC"
|
||||
+ fi
|
||||
+
|
||||
+ local fnc_holder_count
|
||||
+ fnc_holder_count=$(echo "$fnc_holders" | wc -w)
|
||||
+ if [ "$fnc_holder_count" -gt 1 ]; then
|
||||
+ ocf_exit_reason "force_new_cluster attribute is set on multiple nodes ($fnc_holders)"
|
||||
+ return "$OCF_ERR_GENERIC"
|
||||
+ fi
|
||||
+
|
||||
+ if [ "$fnc_holder_count" -eq 1 ]; then
|
||||
+ if echo "$fnc_holders" | grep -q -w "$NODENAME"; then
|
||||
+ # Attribute is set on the local node.
|
||||
+ ocf_log notice "$NODENAME marked to force-new-cluster"
|
||||
+ JOIN_AS_LEARNER=false
|
||||
+ else
|
||||
+ # Attribute is set on a peer node.
|
||||
+ ocf_log info "$NODENAME shall join as learner because force_new_cluster is set on peer $fnc_holders"
|
||||
+ JOIN_AS_LEARNER=true
|
||||
+ fi
|
||||
else
|
||||
- ocf_log info "'$NODENAME' is not marked to force-new-cluster"
|
||||
+ ocf_log info "no node is marked to force-new-cluster"
|
||||
# When the local agent starts, we can infer the cluster state by counting
|
||||
# how many agents are starting or already active:
|
||||
# - 1 active agent: it's the peer (we are just starting)
|
||||
@@ -1522,7 +1557,7 @@ podman_start()
|
||||
for try in $(seq $retries); do
|
||||
learner_node=$(attribute_learner_node get)
|
||||
if [ "$NODENAME" != "$learner_node" ]; then
|
||||
- ocf_log info "$learner_node is not in the member list yet. Retry in $poll_interval_sec seconds."
|
||||
+ ocf_log info "$NODENAME is not in the member list yet. Retry in $poll_interval_sec seconds."
|
||||
sleep $poll_interval_sec
|
||||
continue
|
||||
fi
|
||||
@@ -1673,6 +1708,8 @@ podman_stop()
|
||||
{
|
||||
local timeout=60
|
||||
local rc
|
||||
+
|
||||
+ ocf_log notice "podman-etcd stop"
|
||||
podman_simple_status
|
||||
if [ $? -eq $OCF_NOT_RUNNING ]; then
|
||||
ocf_log info "could not leave members list: etcd container not running"
|
@ -0,0 +1,321 @@
|
||||
From a31f15104fc712cd25f8a59d49f1bbcdbbbc5434 Mon Sep 17 00:00:00 2001
|
||||
From: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
Date: Tue, 30 Sep 2025 11:54:44 +0200
|
||||
Subject: [PATCH 1/2] Refactor(podman-etcd): improve peer checking and
|
||||
leadership loss detection
|
||||
|
||||
The check_peers function is broken up into smaller, more manageable
|
||||
functions. This refactoring separates the logic for detecting a loss of
|
||||
cluster leadership from the logic for managing peer membership.
|
||||
|
||||
The main function is renamed to check_peer as there is only 1 peer to
|
||||
check (it was check_peers).
|
||||
---
|
||||
heartbeat/podman-etcd | 78 +++++++++++++++++++++++++------------------
|
||||
1 file changed, 45 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index f3a6da5e2..3d1e4c520 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -1014,42 +1014,35 @@ get_member_list_json() {
|
||||
podman exec "${CONTAINER}" etcdctl member list --endpoints="$this_node_endpoint" -w json
|
||||
}
|
||||
|
||||
-check_peers()
|
||||
+detect_cluster_leadership_loss()
|
||||
{
|
||||
- # Check peers endpoint status and locally accessible member list
|
||||
- local member_list_json
|
||||
-
|
||||
- if ! container_exists; then
|
||||
- # we need a running container to execute etcdctl.
|
||||
- return $OCF_SUCCESS
|
||||
+ endpoint_status_json=$(get_endpoint_status_json)
|
||||
+ ocf_log info "endpoint status: $endpoint_status_json"
|
||||
+
|
||||
+ count_endpoints=$(printf "%s" "$endpoint_status_json" | jq -r ".[].Endpoint" | wc -l)
|
||||
+ if [ "$count_endpoints" -eq 1 ]; then
|
||||
+ ocf_log info "one endpoint only: checking status errors"
|
||||
+ endpoint_status_errors=$(printf "%s" "$endpoint_status_json" | jq -r ".[0].Status.errors")
|
||||
+ if echo "$endpoint_status_errors" | grep -q "no leader"; then
|
||||
+ set_force_new_cluster
|
||||
+ set_standalone_node
|
||||
+ ocf_exit_reason "$NODENAME must force a new cluster"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if [ "$endpoint_status_errors" != "null" ]; then
|
||||
+ ocf_log err "unmanaged endpoint status error: $endpoint_status_errors"
|
||||
+ fi
|
||||
fi
|
||||
|
||||
- member_list_json=$(get_member_list_json)
|
||||
- rc=$?
|
||||
- ocf_log debug "member list: $member_list_json"
|
||||
- if [ $rc -ne 0 ]; then
|
||||
- ocf_log info "podman failed to get member list, error code: $rc"
|
||||
-
|
||||
- endpoint_status_json=$(get_endpoint_status_json)
|
||||
- ocf_log info "endpoint status: $endpoint_status_json"
|
||||
-
|
||||
- count_endpoints=$(printf "%s" "$endpoint_status_json" | jq -r ".[].Endpoint" | wc -l)
|
||||
- if [ "$count_endpoints" -eq 1 ]; then
|
||||
- ocf_log info "one endpoint only: checking status errors"
|
||||
- endpoint_status_errors=$(printf "%s" "$endpoint_status_json" | jq -r ".[0].Status.errors")
|
||||
- if echo "$endpoint_status_errors" | grep -q "no leader"; then
|
||||
- set_force_new_cluster
|
||||
- set_standalone_node
|
||||
- ocf_exit_reason "$NODENAME must force a new cluster"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
- if [ "$endpoint_status_errors" != "null" ]; then
|
||||
- ocf_log err "unmanaged endpoint status error: $endpoint_status_errors"
|
||||
- fi
|
||||
- fi
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
|
||||
- return $OCF_SUCCESS
|
||||
- fi
|
||||
+manage_peer_membership()
|
||||
+{
|
||||
+ # Read etcd member list to detect the status of the peer member.
|
||||
+ # If the peer is missing from the member list, it will be added back as learner
|
||||
+ # If the peer is back in the member list, we ensure that the related CIB attributes (standalone and learner_node) are reset
|
||||
+ local member_list_json="$1"
|
||||
|
||||
# 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
|
||||
@@ -1083,6 +1076,25 @@ check_peers()
|
||||
clear_standalone_and_learner_if_not_learners "$member_list_json"
|
||||
fi
|
||||
done
|
||||
+}
|
||||
+
|
||||
+check_peer()
|
||||
+{
|
||||
+ # Check peers endpoint status and locally accessible member list
|
||||
+ local member_list_json
|
||||
+
|
||||
+ # we need a running container to execute etcdctl.
|
||||
+ if ! container_exists; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+
|
||||
+ if ! member_list_json=$(get_member_list_json); then
|
||||
+ ocf_log info "podman failed to get member list, error code: $?"
|
||||
+ detect_cluster_leadership_loss
|
||||
+ return $?
|
||||
+ fi
|
||||
+
|
||||
+ manage_peer_membership "$member_list_json"
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
@@ -1124,7 +1136,7 @@ podman_monitor()
|
||||
# monitor operation to fail.
|
||||
# TODO: move this inside check_peers where we already query member list json
|
||||
attribute_node_member_id update
|
||||
- if ! check_peers; then
|
||||
+ if ! check_peer; then
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
|
||||
From de7c73a933cefb8f7b9e810bd23c3d12f6d6f29a Mon Sep 17 00:00:00 2001
|
||||
From: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
Date: Tue, 30 Sep 2025 18:38:06 +0200
|
||||
Subject: [PATCH 2/2] OCPBUGS-42808: podman-etcd: add automatic learner member
|
||||
promotion
|
||||
|
||||
Automatically promote etcd learner members to voting members when detected.
|
||||
Includes refactored member management functions and improved validation.
|
||||
---
|
||||
heartbeat/podman-etcd | 108 ++++++++++++++++++++++++++++++------------
|
||||
1 file changed, 79 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 3d1e4c520..e1425ec02 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -712,6 +712,22 @@ attribute_node_revision_peer()
|
||||
crm_attribute --query --type nodes --node "$nodename" --name "revision" | awk -F"value=" '{print $2}'
|
||||
}
|
||||
|
||||
+# Converts a decimal number to hexadecimal format with validation
|
||||
+# Args: $1 - decimal number (test for non-negative integer too)
|
||||
+# Returns: 0 on success, OCF_ERR_GENERIC on invalid input
|
||||
+# Outputs: hexadecimal representation to stdout
|
||||
+decimal_to_hex() {
|
||||
+ local dec=$1
|
||||
+
|
||||
+ if ! echo "$dec" | grep -q "^[1-9][0-9]*$"; then
|
||||
+ ocf_log err "Invalid member ID format: '$dec' (expected decimal number)"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ printf "%x" "$dec"
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
attribute_node_member_id()
|
||||
{
|
||||
local action="$1"
|
||||
@@ -737,7 +753,7 @@ attribute_node_member_id()
|
||||
return "$rc"
|
||||
fi
|
||||
|
||||
- local value
|
||||
+ local value value_hex
|
||||
if ! value=$(echo -n "$member_list_json" | jq -r ".header.member_id"); then
|
||||
rc=$?
|
||||
ocf_log err "could not get $attribute from member list JSON, error code: $rc"
|
||||
@@ -745,8 +761,11 @@ attribute_node_member_id()
|
||||
fi
|
||||
|
||||
# JSON member_id is decimal, while etcdctl command needs the hex version
|
||||
- value=$(printf "%x" "$value")
|
||||
- if ! crm_attribute --type nodes --node "$NODENAME" --name "$attribute" --update "$value"; then
|
||||
+ if ! value_hex=$(decimal_to_hex "$value"); then
|
||||
+ ocf_log err "could not convert decimal member_id '$value' to hex, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if ! crm_attribute --type nodes --node "$NODENAME" --name "$attribute" --update "$value_hex"; then
|
||||
rc=$?
|
||||
ocf_log err "could not update etcd $attribute, error code: $rc"
|
||||
return "$rc"
|
||||
@@ -905,42 +924,70 @@ clear_standalone_node()
|
||||
crm_attribute --name "standalone_node" --delete
|
||||
}
|
||||
|
||||
-clear_standalone_and_learner_if_not_learners()
|
||||
+
|
||||
+# Promotes an etcd learner member to a voting member
|
||||
+# Args: $1 - learner member ID in decimal format
|
||||
+# Returns: OCF_SUCCESS (even on expected promotion failures), OCF_ERR_GENERIC on conversion errors
|
||||
+# Note: Promotion failures are expected and logged as info (peer may not be up-to-date)
|
||||
+promote_learner_member()
|
||||
+{
|
||||
+ local learner_member_id=$1
|
||||
+
|
||||
+ # JSON member_id is decimal, while etcdctl command needs the hex version
|
||||
+ if ! learner_member_id_hex=$(decimal_to_hex "$learner_member_id"); then
|
||||
+ ocf_log err "could not convert decimal member_id '$learner_member_id' to hex, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if ! ocf_run podman exec "${CONTAINER}" etcdctl member promote "$learner_member_id_hex" 2>&1; then
|
||||
+ # promotion is expected to fail if the peer is not yet up-to-date
|
||||
+ ocf_log info "could not promote member $learner_member_id_hex, error code: $?"
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
+ ocf_log info "successfully promoted member '$learner_member_id_hex'"
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+# Reconciles etcd cluster member states
|
||||
+# Promotes learner members or clears standalone/learner attributes as needed
|
||||
+# Args: $1 - member list JSON from etcdctl
|
||||
+# Returns: OCF_SUCCESS on completion, OCF_ERR_GENERIC on errors
|
||||
+# Note: Only operates when exactly 2 started members are present
|
||||
+reconcile_member_state()
|
||||
{
|
||||
local rc
|
||||
local member_list_json="$1"
|
||||
|
||||
- number_of_members=$(printf "%s" "$member_list_json" | jq -r ".members[].ID" | wc -l)
|
||||
- if [ "$number_of_members" -ne 2 ]; then
|
||||
- ocf_log info "could not clear standalone_node, nor learner_node properties: found $number_of_members members, need 2"
|
||||
+ # count only the started members, which have the ".name" JSON field
|
||||
+ number_of_started_members=$(printf "%s" "$member_list_json" | jq -r ".members[].name | select(. != null)" | wc -l)
|
||||
+ if [ "$number_of_started_members" -ne 2 ]; then
|
||||
+ ocf_log info "could not clear standalone_node, nor learner_node properties: found $number_of_started_members members, need 2"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- id=$(printf "%s" "$member_list_json" | jq -r ".members[] | select( .isLearner==true ).ID")
|
||||
+ learner_member_id=$(printf "%s" "$member_list_json" | jq -r ".members[] | select( .isLearner==true ).ID")
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
ocf_log err "could not get isLearner field from member list, error code: $rc"
|
||||
return $rc
|
||||
fi
|
||||
|
||||
- if [ -z "$id" ]; then
|
||||
- clear_standalone_node
|
||||
- rc=$?
|
||||
- if [ $rc -ne 0 ]; then
|
||||
- ocf_og error "could not clear standalone_node attribute, error code: $rc"
|
||||
- return $rc
|
||||
- fi
|
||||
+ if [ -n "$learner_member_id" ]; then
|
||||
+ promote_learner_member "$learner_member_id"
|
||||
+ return $?
|
||||
fi
|
||||
- if [ -z "$id" ]; then
|
||||
- attribute_learner_node clear
|
||||
- rc=$?
|
||||
- if [ $rc -ne 0 ]; then
|
||||
- ocf_og error "could not clear learner_node attribute, error code: $rc"
|
||||
- return $rc
|
||||
+
|
||||
+ if [ -z "$learner_member_id" ]; then
|
||||
+ if ! clear_standalone_node; then
|
||||
+ ocf_log error "could not clear standalone_node attribute, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ if ! attribute_learner_node clear; then
|
||||
+ ocf_log error "could not clear learner_node attribute, error code: $?"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
fi
|
||||
|
||||
- return $rc
|
||||
+ return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
attribute_learner_node()
|
||||
@@ -1019,7 +1066,7 @@ detect_cluster_leadership_loss()
|
||||
endpoint_status_json=$(get_endpoint_status_json)
|
||||
ocf_log info "endpoint status: $endpoint_status_json"
|
||||
|
||||
- count_endpoints=$(printf "%s" "$endpoint_status_json" | jq -r ".[].Endpoint" | wc -l)
|
||||
+ count_endpoints=$(printf "%s" "$endpoint_status_json" | jq -r ".[].Endpoint" | wc -l)
|
||||
if [ "$count_endpoints" -eq 1 ]; then
|
||||
ocf_log info "one endpoint only: checking status errors"
|
||||
endpoint_status_errors=$(printf "%s" "$endpoint_status_json" | jq -r ".[0].Status.errors")
|
||||
@@ -1037,11 +1084,14 @@ detect_cluster_leadership_loss()
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+
|
||||
+# Manages etcd peer membership by detecting and handling missing or rejoining peers
|
||||
+# Adds missing peers as learners and reconciles member states when peers rejoin
|
||||
+# Args: $1 - member list JSON from etcdctl
|
||||
+# Returns: OCF_SUCCESS on completion, OCF_ERR_GENERIC on errors
|
||||
+# Note: Iterates through all peer nodes to ensure proper cluster membership
|
||||
manage_peer_membership()
|
||||
{
|
||||
- # Read etcd member list to detect the status of the peer member.
|
||||
- # If the peer is missing from the member list, it will be added back as learner
|
||||
- # If the peer is back in the member list, we ensure that the related CIB attributes (standalone and learner_node) are reset
|
||||
local member_list_json="$1"
|
||||
|
||||
# Example of .members[] instance fields in member list json format:
|
||||
@@ -1066,14 +1116,14 @@ manage_peer_membership()
|
||||
|
||||
# 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
|
||||
- id=$(printf "%s" "$member_list_json" | jq -r ".members[] | select( .peerURLs | map(test(\"$ip\")) | any).ID")
|
||||
- if [ -z "$id" ]; then
|
||||
+ 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"
|
||||
- clear_standalone_and_learner_if_not_learners "$member_list_json"
|
||||
+ reconcile_member_state "$member_list_json"
|
||||
fi
|
||||
done
|
||||
}
|
317
RHEL-13089-1-crypt-add-tang-clevis-support-and-fix-issues.patch
Normal file
317
RHEL-13089-1-crypt-add-tang-clevis-support-and-fix-issues.patch
Normal file
@ -0,0 +1,317 @@
|
||||
From ba5737a659be55a5e88f2cadcec867b00b8a53be Mon Sep 17 00:00:00 2001
|
||||
From: Lloyd Brown <lloyd_brown@byu.edu>
|
||||
Date: Fri, 4 Jun 2021 08:58:25 -0600
|
||||
Subject: [PATCH 1/3] initial pass on supporting clevis-unlocked volumes
|
||||
|
||||
---
|
||||
heartbeat/crypt | 26 ++++++++++++++++++++++++--
|
||||
1 file changed, 24 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/crypt b/heartbeat/crypt
|
||||
index 56db379666..ab9d686b04 100755
|
||||
--- a/heartbeat/crypt
|
||||
+++ b/heartbeat/crypt
|
||||
@@ -37,12 +37,14 @@ OCF_RESKEY_crypt_dev_default=""
|
||||
OCF_RESKEY_key_file_default=""
|
||||
OCF_RESKEY_crypt_type_default=""
|
||||
OCF_RESKEY_force_stop_default="false"
|
||||
+OCF_RESKEY_use_clevis_default="false"
|
||||
|
||||
: ${OCF_RESKEY_encrypted_dev=${OCF_RESKEY_encrypted_dev_default}}
|
||||
: ${OCF_RESKEY_crypt_dev=${OCF_RESKEY_crypt_dev_default}}
|
||||
: ${OCF_RESKEY_key_file=${OCF_RESKEY_key_file_default}}
|
||||
: ${OCF_RESKEY_crypt_type=${OCF_RESKEY_crypt_type_default}}
|
||||
: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}}
|
||||
+: ${OCF_RESKEY_use_clevis=${OCF_RESKEY_use_clevis_default}}
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -122,6 +124,16 @@ will fail and the node will be fenced.
|
||||
<content type="boolean" default="${OCF_RESKEY_force_stop_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="use_clevis" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+If LUKS volume is set up to unlock automatically using Tang/Clevis,
|
||||
+then set this parameter to "true". This has the side-effect of ignoring
|
||||
+the "key_file", "disable_locks" and "crypt_type" parameters.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">use clevis tools to unlock volume</shortdesc>
|
||||
+<content type="boolean" default="${OCF_RESKEY_use_clevis_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -153,12 +165,17 @@ crypt_dev_path="/dev/mapper/$crypt_dev"
|
||||
key_file="${OCF_RESKEY_key_file}"
|
||||
crypt_type="${OCF_RESKEY_crypt_type}"
|
||||
force_stop="${OCF_RESKEY_force_stop}"
|
||||
+use_clevis="${OCF_RESKEY_use_clevis}"
|
||||
|
||||
crypt_validate_all() {
|
||||
if ! have_binary cryptsetup; then
|
||||
ocf_exit_reason "Please install cryptsetup(8)"
|
||||
return $OCF_ERR_INSTALLED
|
||||
fi
|
||||
+ if ocf_is_true "$use_clevis" && ! have_binary clevis ; then
|
||||
+ ocf_exit_reason "Please install clevis tools"
|
||||
+ return $OCF_ERR_INSTALLED
|
||||
+ fi
|
||||
if [ -z "$encrypted_dev" ]; then
|
||||
ocf_exit_reason "Undefined OCF_RESKEY_encrypted_dev"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
@@ -250,8 +267,13 @@ crypt_stop_one() {
|
||||
crypt_start() {
|
||||
local rc
|
||||
|
||||
- cryptsetup open $encrypted_dev $crypt_dev --type $crypt_type $disable_locks --key-file=$key_file
|
||||
- rc=$?
|
||||
+ if ocf_is_true "$use_clevis"; then
|
||||
+ clevis luks unlock -d $encrypted_dev -n $crypt_dev
|
||||
+ rc=$?
|
||||
+ else
|
||||
+ cryptsetup open $encrypted_dev $crypt_dev --type $crypt_type $disable_locks --key-file=$key_file
|
||||
+ rc=$?
|
||||
+ fi
|
||||
if [ $rc -eq 0 ];then
|
||||
crypt_monitor
|
||||
rc=$?
|
||||
|
||||
From 7419b629429edacd16493a3baaca2c5481467bc5 Mon Sep 17 00:00:00 2001
|
||||
From: Lloyd Brown <lloyd_brown@byu.edu>
|
||||
Date: Mon, 7 Jun 2021 08:40:41 -0600
|
||||
Subject: [PATCH 2/3] Attempting to detect clevis automatically
|
||||
|
||||
---
|
||||
heartbeat/crypt | 16 +++++++++++++++-
|
||||
1 file changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/crypt b/heartbeat/crypt
|
||||
index ab9d686b04..0b184305e8 100755
|
||||
--- a/heartbeat/crypt
|
||||
+++ b/heartbeat/crypt
|
||||
@@ -227,6 +227,19 @@ crypt_validate_all() {
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
+
|
||||
+detect_clevis() {
|
||||
+ if ! have_binary clevis; then
|
||||
+ use_clevis="false" #We can't use clevis, if we don't have it installed
|
||||
+ elif ! ocf_is_true "$use_clevis"; then #if not already specified by user to use clevis
|
||||
+ #Try to detect whether clevis is available
|
||||
+ if clevis luks list -d $encrypted_dev | grep -q '^[[:digit:]]\+:'; then
|
||||
+ use_clevis="true" #if grep finds output that matches, we have clevis, therefore use it
|
||||
+ fi
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+
|
||||
get_users_pids() {
|
||||
ocf_log debug "running lsof to list \"$crypt_dev\" users..."
|
||||
ocf_run -warn 'lsof $crypt_dev_path | tail -n +2 | awk "{print $2}" | sort -u'
|
||||
@@ -266,7 +279,8 @@ crypt_stop_one() {
|
||||
#
|
||||
crypt_start() {
|
||||
local rc
|
||||
-
|
||||
+ detect_clevis
|
||||
+
|
||||
if ocf_is_true "$use_clevis"; then
|
||||
clevis luks unlock -d $encrypted_dev -n $crypt_dev
|
||||
rc=$?
|
||||
|
||||
From c35a3d14656a7c52f32126b7646f4a78f2b33dff Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 27 Feb 2025 15:00:17 +0100
|
||||
Subject: [PATCH 3/3] crypt: fixes to validate-action and to avoid running as a
|
||||
cloned resource
|
||||
|
||||
---
|
||||
heartbeat/crypt | 67 ++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 36 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/crypt b/heartbeat/crypt
|
||||
index 0b184305e8..4d4d6142ba 100755
|
||||
--- a/heartbeat/crypt
|
||||
+++ b/heartbeat/crypt
|
||||
@@ -88,7 +88,7 @@ The resulting block device path is /dev/mapper/name.
|
||||
<content type="string" default="${OCF_RESKEY_crypt_dev_default}" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="key_file" unique="0" required="1">
|
||||
+<parameter name="key_file" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
Key file path containing the encryption passphrase
|
||||
(aka key; see cryptsetup(8)). For LUKS, the passphrase as of the key_file
|
||||
@@ -98,7 +98,7 @@ parameter is used to decrypt a randomly selected key when the device was created
|
||||
<content type="string" default="${OCF_RESKEY_key_file_default}" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="crypt_type" unique="0" required="1">
|
||||
+<parameter name="crypt_type" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
Encryption (device) type (e.g. "luks" or "luks2").
|
||||
|
||||
@@ -128,7 +128,7 @@ will fail and the node will be fenced.
|
||||
<longdesc lang="en">
|
||||
If LUKS volume is set up to unlock automatically using Tang/Clevis,
|
||||
then set this parameter to "true". This has the side-effect of ignoring
|
||||
-the "key_file", "disable_locks" and "crypt_type" parameters.
|
||||
+the "key_file" and "crypt_type" parameters.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">use clevis tools to unlock volume</shortdesc>
|
||||
<content type="boolean" default="${OCF_RESKEY_use_clevis_default}" />
|
||||
@@ -147,10 +147,6 @@ the "key_file", "disable_locks" and "crypt_type" parameters.
|
||||
END
|
||||
}
|
||||
|
||||
-# Disable cryptsetup auto-recovery if cloned.
|
||||
-disable_locks=""
|
||||
-ocf_is_clone && disable_locks="--disable-locks"
|
||||
-
|
||||
crypt_usage() {
|
||||
cat <<END
|
||||
usage: $0 {start|stop|monitor|usage|meta-data|validate-all}
|
||||
@@ -168,6 +164,10 @@ force_stop="${OCF_RESKEY_force_stop}"
|
||||
use_clevis="${OCF_RESKEY_use_clevis}"
|
||||
|
||||
crypt_validate_all() {
|
||||
+ if ocf_is_clone; then
|
||||
+ ocf_exit_reason "crypt cannot run as a cloned resource"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
if ! have_binary cryptsetup; then
|
||||
ocf_exit_reason "Please install cryptsetup(8)"
|
||||
return $OCF_ERR_INSTALLED
|
||||
@@ -184,35 +184,32 @@ crypt_validate_all() {
|
||||
case "$encrypted_dev" in
|
||||
*-*-*-*) if [ `echo "$encrypted_dev" | wc -c` -ne 37 ]; then
|
||||
ocf_exit_reason "Bogus encrypted device UUID \"$encrypted_dev\""
|
||||
- return $OCF_ERR_ARGS
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
encrypted_dev=/dev/disk/by-uuid/"$encrypted_dev";;
|
||||
*) case "$encrypted_dev" in
|
||||
/dev/*) ;;
|
||||
*) ocf_exit_reason "Bogus encrypted device path"
|
||||
- return $OCF_ERR_ARGS;;
|
||||
+ return $OCF_ERR_CONFIGURED;;
|
||||
esac
|
||||
esac
|
||||
fi
|
||||
-
|
||||
- # return early for probes where device might not be available yet
|
||||
- # e.g. LVM exclusive volumes
|
||||
- if ocf_is_probe; then
|
||||
- return $OCF_SUCCESS
|
||||
- fi
|
||||
-
|
||||
if [ ! -b "$encrypted_dev" ] && [ ! -L "$encrypted_dev" ]; then
|
||||
ocf_exit_reason "Encrypted device $encrypted_dev not accessible"
|
||||
- return $OCF_ERR_ARGS
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
echo "$crypt_dev" | grep "/" >/dev/null
|
||||
if [ $? -eq 0 ] && [ -z "$crypt_dev" ]; then
|
||||
ocf_exit_reason "Crypt device \"$crypt_dev\" name has to at least 1 character long and without path"
|
||||
- return $OCF_ERR_ARGS
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
- if [ ! -r "$key_file" ]; then
|
||||
+ if ! ocf_is_true "$use_clevis" && [ ! -r "$key_file" ]; then
|
||||
ocf_exit_reason "Hash key file $key_file not accessible"
|
||||
- return $OCF_ERR_ARGS
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if ! ocf_is_true "$use_clevis" && [ ! -r "$crypt_type" ]; then
|
||||
+ ocf_exit_reason "crypt_type not set"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
if ocf_is_true "$force_stop" && ! have_binary lsof; then
|
||||
ocf_exit_reason "Force stop requested, please install lsof(8)"
|
||||
@@ -270,7 +267,7 @@ show_users() {
|
||||
}
|
||||
|
||||
crypt_stop_one() {
|
||||
- cryptsetup close $crypt_dev $disable_locks
|
||||
+ cryptsetup close $crypt_dev
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
@@ -278,21 +275,22 @@ crypt_stop_one() {
|
||||
# Action: START an encrypted resource
|
||||
#
|
||||
crypt_start() {
|
||||
- local rc
|
||||
+ local out rc
|
||||
detect_clevis
|
||||
-
|
||||
+
|
||||
if ocf_is_true "$use_clevis"; then
|
||||
- clevis luks unlock -d $encrypted_dev -n $crypt_dev
|
||||
+ out=$(clevis luks unlock -d $encrypted_dev -n $crypt_dev 2>&1)
|
||||
rc=$?
|
||||
else
|
||||
- cryptsetup open $encrypted_dev $crypt_dev --type $crypt_type $disable_locks --key-file=$key_file
|
||||
+ out=$(cryptsetup open $encrypted_dev $crypt_dev --type $crypt_type --key-file=$key_file 2>&1)
|
||||
rc=$?
|
||||
fi
|
||||
if [ $rc -eq 0 ];then
|
||||
crypt_monitor
|
||||
rc=$?
|
||||
else
|
||||
- rc=$OCF_ERR_GERNERIC
|
||||
+ ocf_exit_reason "Failed to start encrypted device \"$crypt_dev\": $out"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
[ $rc -ne $OCF_SUCCESS ] && ocf_exit_reason "Failed to start encrypted device \"$crypt_dev\""
|
||||
|
||||
@@ -315,7 +313,8 @@ crypt_stop() {
|
||||
if [ $rc -ne $OCF_NOT_RUNNING ] && ocf_is_true $force_stop; then
|
||||
stop_crypt_users
|
||||
case $? in
|
||||
- 2) rc=$OCF_SUCCESS;;
|
||||
+ 2) crypt_monitor
|
||||
+ rc=$?;;
|
||||
*) crypt_stop_one
|
||||
crypt_monitor
|
||||
rc=$?;;
|
||||
@@ -335,7 +334,7 @@ crypt_stop() {
|
||||
# Action: MONITOR an encrypted resource
|
||||
#
|
||||
crypt_monitor() {
|
||||
- cryptsetup status $crypt_dev $disable_locks >/dev/null 2>&1
|
||||
+ cryptsetup status $crypt_dev >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
if [ -b "$encrypted_dev" ] || [ -L $crypt_dev_path ]; then
|
||||
return $OCF_SUCCESS
|
||||
@@ -347,10 +346,10 @@ crypt_monitor() {
|
||||
return $OCF_NOT_RUNNING
|
||||
}
|
||||
|
||||
-# Check for stange argument count.
|
||||
+# Check for strange argument count.
|
||||
if [ $# -ne 1 ]; then
|
||||
usage
|
||||
- exit $OCF_ERR_ARGS
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
case "$__OCF_ACTION" in
|
||||
@@ -363,7 +362,13 @@ esac
|
||||
# XME: remove once pacemaker is fixed and calls this action
|
||||
crypt_validate_all
|
||||
rc=$?
|
||||
-[ $rc -ne $OCF_SUCCESS ] && exit $rc
|
||||
+if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
+ if ! ocf_is_probe && [ "$__OCF_ACTION" != "stop" ]; then
|
||||
+ exit $rc
|
||||
+ else
|
||||
+ $OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+fi
|
||||
|
||||
case "$__OCF_ACTION" in
|
||||
start) crypt_start; rc=$?;;
|
32
RHEL-13089-2-crypt-fix-crypt_type-check-and-usage.patch
Normal file
32
RHEL-13089-2-crypt-fix-crypt_type-check-and-usage.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From fa45156e8b22d477ea8cbbfe48151e4e0b173320 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 24 Apr 2025 14:45:52 +0200
|
||||
Subject: [PATCH] crypt: fix crypt_type check, and usage when action has not
|
||||
been specified
|
||||
|
||||
---
|
||||
heartbeat/crypt | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/crypt b/heartbeat/crypt
|
||||
index 4d4d6142b..1dbf8c33f 100755
|
||||
--- a/heartbeat/crypt
|
||||
+++ b/heartbeat/crypt
|
||||
@@ -207,7 +207,7 @@ crypt_validate_all() {
|
||||
ocf_exit_reason "Hash key file $key_file not accessible"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
- if ! ocf_is_true "$use_clevis" && [ ! -r "$crypt_type" ]; then
|
||||
+ if ! ocf_is_true "$use_clevis" && [ -z "$crypt_type" ]; then
|
||||
ocf_exit_reason "crypt_type not set"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -348,7 +348,7 @@ crypt_monitor() {
|
||||
|
||||
# Check for strange argument count.
|
||||
if [ $# -ne 1 ]; then
|
||||
- usage
|
||||
+ crypt_usage
|
||||
exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
@ -450,6 +450,6 @@ index ef7639bff..447f5cba3 100644
|
||||
ocf-distro ocf.py ocf-rarun ocf-returncodes \
|
||||
- findif.sh apache-conf.sh http-mon.sh mysql-common.sh \
|
||||
+ findif.sh apache-conf.sh aws.sh http-mon.sh mysql-common.sh \
|
||||
nfsserver-redhat.sh ora-common.sh
|
||||
nfsserver-redhat.sh openstack-common.sh ora-common.sh
|
||||
|
||||
preptree:
|
184
RHEL-68740-awsvip-add-interface-parameter.patch
Normal file
184
RHEL-68740-awsvip-add-interface-parameter.patch
Normal file
@ -0,0 +1,184 @@
|
||||
From 392d40048a25d7cb73ec5b5e9f7a5862f7a3fd48 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 11 Nov 2024 12:22:27 +0100
|
||||
Subject: [PATCH 1/2] aws.sh: add get_interface_mac()
|
||||
|
||||
---
|
||||
heartbeat/aws.sh | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh
|
||||
index 64f2e13a7..ebb4eb1f4 100644
|
||||
--- a/heartbeat/aws.sh
|
||||
+++ b/heartbeat/aws.sh
|
||||
@@ -69,3 +69,24 @@ get_instance_id() {
|
||||
echo "$INSTANCE_ID"
|
||||
return "$OCF_SUCCESS"
|
||||
}
|
||||
+
|
||||
+get_interface_mac() {
|
||||
+ local MAC_FILE MAC_ADDR rc
|
||||
+ MAC_FILE="/sys/class/net/${OCF_RESKEY_interface}/address"
|
||||
+ if [ -f "$MAC_FILE" ]; then
|
||||
+ cmd="cat ${MAC_FILE}"
|
||||
+ else
|
||||
+ cmd="ip -br link show dev ${OCF_RESKEY_interface} | tr -s ' ' | cut -d' ' -f3"
|
||||
+ fi
|
||||
+ ocf_log debug "executing command: $cmd"
|
||||
+ MAC_ADDR="$(eval $cmd)"
|
||||
+ rc=$?
|
||||
+ if [ $rc != 0 ]; then
|
||||
+ ocf_log warn "command failed, rc: $rc"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+ ocf_log debug "MAC address associated with interface ${OCF_RESKEY_interface}: ${MAC_ADDR}"
|
||||
+
|
||||
+ echo $MAC_ADDR
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
|
||||
From 87337ac4da931d5a53c83d53d4bab17ee123ba9f Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 11 Nov 2024 12:26:38 +0100
|
||||
Subject: [PATCH 2/2] awsvip: let user specify which interface to use, and make
|
||||
the parameter optional in aws-vpc-move-ip
|
||||
|
||||
---
|
||||
heartbeat/aws-vpc-move-ip | 20 ++++----------------
|
||||
heartbeat/aws.sh | 4 +++-
|
||||
heartbeat/awsvip | 24 +++++++++++++++++-------
|
||||
3 files changed, 24 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip
|
||||
index 09ae68b57..2afc0ba53 100755
|
||||
--- a/heartbeat/aws-vpc-move-ip
|
||||
+++ b/heartbeat/aws-vpc-move-ip
|
||||
@@ -157,7 +157,7 @@ Role to use to query/update the route table
|
||||
<content type="string" default="${OCF_RESKEY_routing_table_role_default}" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="interface" required="1">
|
||||
+<parameter name="interface" required="0">
|
||||
<longdesc lang="en">
|
||||
Name of the network interface, i.e. eth0
|
||||
</longdesc>
|
||||
@@ -321,7 +321,7 @@ ec2ip_monitor() {
|
||||
ocf_log debug "monitor: Enhanced Monitoring disabled - omitting API call"
|
||||
fi
|
||||
|
||||
- cmd="ip addr show to $OCF_RESKEY_ip up"
|
||||
+ cmd="ip addr show dev $OCF_RESKEY_interface to $OCF_RESKEY_ip up"
|
||||
ocf_log debug "executing command: $cmd"
|
||||
RESULT=$($cmd | grep "$OCF_RESKEY_ip")
|
||||
if [ -z "$RESULT" ]; then
|
||||
@@ -331,7 +331,7 @@ ec2ip_monitor() {
|
||||
level="info"
|
||||
fi
|
||||
|
||||
- ocf_log "$level" "IP $OCF_RESKEY_ip not assigned to running interface"
|
||||
+ ocf_log "$level" "IP $OCF_RESKEY_ip not assigned to interface $OCF_RESKEY_interface"
|
||||
return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
@@ -369,19 +369,7 @@ ec2ip_drop() {
|
||||
}
|
||||
|
||||
ec2ip_get_instance_eni() {
|
||||
- MAC_FILE="/sys/class/net/${OCF_RESKEY_interface}/address"
|
||||
- if [ -f $MAC_FILE ]; then
|
||||
- cmd="cat ${MAC_FILE}"
|
||||
- else
|
||||
- cmd="ip -br link show dev ${OCF_RESKEY_interface} | tr -s ' ' | cut -d' ' -f3"
|
||||
- fi
|
||||
- ocf_log debug "executing command: $cmd"
|
||||
- MAC_ADDR="$(eval $cmd)"
|
||||
- rc=$?
|
||||
- if [ $rc != 0 ]; then
|
||||
- ocf_log warn "command failed, rc: $rc"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
+ MAC_ADDR=$(get_interface_mac)
|
||||
ocf_log debug "MAC address associated with interface ${OCF_RESKEY_interface}: ${MAC_ADDR}"
|
||||
|
||||
cmd="curl_retry \"$OCF_RESKEY_curl_retries\" \"$OCF_RESKEY_curl_sleep\" \"--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'\" \"http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC_ADDR}/interface-id\""
|
||||
diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh
|
||||
index ebb4eb1f4..216033afe 100644
|
||||
--- a/heartbeat/aws.sh
|
||||
+++ b/heartbeat/aws.sh
|
||||
@@ -73,7 +73,9 @@ get_instance_id() {
|
||||
get_interface_mac() {
|
||||
local MAC_FILE MAC_ADDR rc
|
||||
MAC_FILE="/sys/class/net/${OCF_RESKEY_interface}/address"
|
||||
- if [ -f "$MAC_FILE" ]; then
|
||||
+ if [ -z "$OCF_RESKEY_interface" ]; then
|
||||
+ cmd="curl_retry \"$OCF_RESKEY_curl_retries\" \"$OCF_RESKEY_curl_sleep\" \"--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'\" \"http://169.254.169.254/latest/meta-data/mac\""
|
||||
+ elif [ -f "$MAC_FILE" ]; then
|
||||
cmd="cat ${MAC_FILE}"
|
||||
else
|
||||
cmd="ip -br link show dev ${OCF_RESKEY_interface} | tr -s ' ' | cut -d' ' -f3"
|
||||
diff --git a/heartbeat/awsvip b/heartbeat/awsvip
|
||||
index 0856ac5e4..015180d5a 100755
|
||||
--- a/heartbeat/awsvip
|
||||
+++ b/heartbeat/awsvip
|
||||
@@ -49,12 +49,14 @@ OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_api_delay_default="3"
|
||||
+OCF_RESKEY_interface_default=""
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}}
|
||||
+: ${OCF_RESKEY_interface=${OCF_RESKEY_interface_default}}
|
||||
|
||||
meta_data() {
|
||||
cat <<END
|
||||
@@ -125,6 +127,14 @@ a short delay between API calls, to avoid sending API too quick
|
||||
<content type="integer" default="${OCF_RESKEY_api_delay_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="interface" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Name of the network interface, i.e. eth0
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">network interface name</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_interface_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="curl_retries" unique="0">
|
||||
<longdesc lang="en">
|
||||
curl retries before failing
|
||||
@@ -207,16 +217,16 @@ awsvip_stop() {
|
||||
}
|
||||
|
||||
awsvip_monitor() {
|
||||
- $AWSCLI_CMD ec2 describe-instances \
|
||||
- --instance-id "${INSTANCE_ID}" \
|
||||
- --query 'Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddresses[].PrivateIpAddress[]' \
|
||||
+ $AWSCLI_CMD ec2 describe-network-interfaces \
|
||||
+ --network-interface-ids "${NETWORK_ID}" \
|
||||
+ --query 'NetworkInterfaces[].PrivateIpAddresses[].PrivateIpAddress[]' \
|
||||
--output text | \
|
||||
grep -qE "(^|\s)${SECONDARY_PRIVATE_IP}(\s|$)"
|
||||
- RET=$?
|
||||
-
|
||||
- if [ $RET -ne 0 ]; then
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe && ocf_log error "IP $SECONDARY_PRIVATE_IP not assigned to interface ${NETWORK_ID}"
|
||||
return $OCF_NOT_RUNNING
|
||||
fi
|
||||
+
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
@@ -267,7 +277,7 @@ TOKEN=$(get_token)
|
||||
[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
INSTANCE_ID=$(get_instance_id)
|
||||
[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
-MAC_ADDRESS=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/mac")
|
||||
+MAC_ADDRESS=$(get_interface_mac)
|
||||
[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
NETWORK_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC_ADDRESS}/interface-id")
|
||||
[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
@ -0,0 +1,23 @@
|
||||
From 17bf880b110c59a69e677b3961b0ebe4e9a483d9 Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Safarov <s.safarov@anycast-lb.net>
|
||||
Date: Sun, 12 Jan 2025 20:02:53 +0200
|
||||
Subject: [PATCH] ocf-shellfuncs: fixed bash systax error added at
|
||||
a25f08cf98d784894df9c52960eff5ccef059393
|
||||
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index 8e51fa3c8..6b35b89c7 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -742,7 +742,7 @@ crm_mon_no_validation()
|
||||
# The subshell prevents parsing error with incompatible shells
|
||||
ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.19.7"
|
||||
if [ $res -eq 2 ] || [ $res -eq 1 ]; then
|
||||
- "$SHELL" -c "CIB_file=<(${HA_SBIN_DIR}/cibadmin -Q \
|
||||
+ "$SHELL" -c "CIB_file=<(${HA_SBIN_DIR}/cibadmin -Q) \
|
||||
${HA_SBIN_DIR}/crm_mon \$*" -- $*
|
||||
else
|
||||
"$SHELL" -c "CIB_file=<(${HA_SBIN_DIR}/cibadmin -Q | sed 's/validate-with=\"[^\"]*\"/validate-with=\"none\"/') \
|
@ -0,0 +1,22 @@
|
||||
From 9bb30d743d04905dec474bd71e31553e5189a570 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 11 Feb 2025 10:38:59 +0100
|
||||
Subject: [PATCH] ocf-shellfuncs: add missing variable in
|
||||
crm_mon_no_validation()
|
||||
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index 6b35b89c7..e834ded95 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -741,6 +741,7 @@ crm_mon_no_validation()
|
||||
{
|
||||
# The subshell prevents parsing error with incompatible shells
|
||||
ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.19.7"
|
||||
+ res=$?
|
||||
if [ $res -eq 2 ] || [ $res -eq 1 ]; then
|
||||
"$SHELL" -c "CIB_file=<(${HA_SBIN_DIR}/cibadmin -Q) \
|
||||
${HA_SBIN_DIR}/crm_mon \$*" -- $*
|
243
RHEL-75574-1-all-agents-use-grep-E-F.patch
Normal file
243
RHEL-75574-1-all-agents-use-grep-E-F.patch
Normal file
@ -0,0 +1,243 @@
|
||||
From 618ee5d013b6f4caeb703ffee6d2d696db887a1f Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 21 Jan 2025 10:07:46 +0100
|
||||
Subject: [PATCH] All agents: use detected grep -E/-F instead of egrep/fgrep
|
||||
when detected
|
||||
|
||||
---
|
||||
configure.ac | 4 ++--
|
||||
heartbeat/IPaddr2 | 2 +-
|
||||
heartbeat/ManageVE.in | 2 +-
|
||||
heartbeat/SAPInstance | 2 +-
|
||||
heartbeat/VirtualDomain | 4 ++--
|
||||
heartbeat/WAS | 2 +-
|
||||
heartbeat/WAS6 | 2 +-
|
||||
heartbeat/docker | 2 +-
|
||||
heartbeat/eDir88.in | 2 +-
|
||||
heartbeat/mysql-proxy | 2 +-
|
||||
heartbeat/portblock | 2 +-
|
||||
heartbeat/rabbitmq-server-ha | 2 +-
|
||||
heartbeat/sapdb.sh | 2 +-
|
||||
heartbeat/smb-share.in | 4 ++--
|
||||
heartbeat/symlink | 2 +-
|
||||
15 files changed, 18 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 951a05430f..bb2bbaded2 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -492,12 +492,12 @@ AC_PATH_PROGS(TEST, test)
|
||||
AC_PATH_PROGS(PING, ping, /bin/ping)
|
||||
AC_PATH_PROGS(IFCONFIG, ifconfig, /sbin/ifconfig)
|
||||
AC_PATH_PROGS(MAILCMD, mailx mail, mail)
|
||||
-AC_PATH_PROGS(EGREP, egrep)
|
||||
AC_PATH_PROGS(RM, rm)
|
||||
+AC_PROG_EGREP
|
||||
+AC_PROG_FGREP
|
||||
|
||||
AC_SUBST(BASH_SHELL)
|
||||
AC_SUBST(MAILCMD)
|
||||
-AC_SUBST(EGREP)
|
||||
AC_SUBST(SHELL)
|
||||
AC_SUBST(PING)
|
||||
AC_SUBST(RM)
|
||||
diff --git a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
|
||||
index 27cae2d11a..489826b814 100755
|
||||
--- a/heartbeat/IPaddr2
|
||||
+++ b/heartbeat/IPaddr2
|
||||
@@ -1028,7 +1028,7 @@ ip_served() {
|
||||
echo "partial2"
|
||||
return 0
|
||||
fi
|
||||
- if egrep -q "(^|,)${IP_INC_NO}(,|$)" $IP_CIP_FILE ; then
|
||||
+ if $EGREP -q "(^|,)${IP_INC_NO}(,|$)" $IP_CIP_FILE ; then
|
||||
echo "ok"
|
||||
return 0
|
||||
else
|
||||
diff --git a/heartbeat/ManageVE.in b/heartbeat/ManageVE.in
|
||||
index f07ca5bdc6..540addd946 100644
|
||||
--- a/heartbeat/ManageVE.in
|
||||
+++ b/heartbeat/ManageVE.in
|
||||
@@ -273,7 +273,7 @@ esac
|
||||
declare -i veidtest1=$?
|
||||
|
||||
# really a number?
|
||||
-`echo "$OCF_RESKEY_veid" | egrep -q '^[[:digit:]]+$'`
|
||||
+`echo "$OCF_RESKEY_veid" | $EGREP -q '^[[:digit:]]+$'`
|
||||
|
||||
if [[ $veidtest1 != 1 || $? != 0 ]]; then
|
||||
ocf_log err "OCF_RESKEY_veid not set or not a number."
|
||||
diff --git a/heartbeat/SAPInstance b/heartbeat/SAPInstance
|
||||
index 26fd541361..95140e9c45 100755
|
||||
--- a/heartbeat/SAPInstance
|
||||
+++ b/heartbeat/SAPInstance
|
||||
@@ -795,7 +795,7 @@ sapinstance_monitor() {
|
||||
esac
|
||||
|
||||
SEARCH=`echo "$OCF_RESKEY_MONITOR_SERVICES" | sed 's/\+/\\\+/g' | sed 's/\./\\\./g'`
|
||||
- if [ `echo "$SERVICE" | egrep -c "$SEARCH"` -eq 1 ]
|
||||
+ if [ `echo "$SERVICE" | $EGREP -c "$SEARCH"` -eq 1 ]
|
||||
then
|
||||
if [ $STATE -eq $OCF_NOT_RUNNING ]
|
||||
then
|
||||
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
|
||||
index 3905695ae1..7db42bd12e 100755
|
||||
--- a/heartbeat/VirtualDomain
|
||||
+++ b/heartbeat/VirtualDomain
|
||||
@@ -975,7 +975,7 @@ VirtualDomain_migrate_to() {
|
||||
sed "s/%n/$target_node/g"`
|
||||
|
||||
# extract migrationuri from options
|
||||
- elif echo "$migrate_opts" | fgrep -qs -- "--migrateuri="; then
|
||||
+ elif echo "$migrate_opts" | $FGREP -qs -- "--migrateuri="; then
|
||||
migrateuri=`echo "$migrate_opts" |
|
||||
sed "s/.*--migrateuri=\([^ ]*\).*/\1/;s/%n/$target_node/g"`
|
||||
|
||||
@@ -1148,7 +1148,7 @@ VirtualDomain_getconfig() {
|
||||
VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet"
|
||||
|
||||
# Retrieve the domain name from the xml file.
|
||||
- DOMAIN_NAME=`egrep '[[:space:]]*<name>.*</name>[[:space:]]*$' ${OCF_RESKEY_config} 2>/dev/null | sed -e 's/[[:space:]]*<name>\(.*\)<\/name>[[:space:]]*$/\1/'`
|
||||
+ DOMAIN_NAME=`$EGREP '[[:space:]]*<name>.*</name>[[:space:]]*$' ${OCF_RESKEY_config} 2>/dev/null | sed -e 's/[[:space:]]*<name>\(.*\)<\/name>[[:space:]]*$/\1/'`
|
||||
|
||||
EMULATOR_STATE="${HA_RSCTMP}/VirtualDomain-${DOMAIN_NAME}-emu.state"
|
||||
}
|
||||
diff --git a/heartbeat/WAS b/heartbeat/WAS
|
||||
index 15b56e99e0..44aa83e20a 100755
|
||||
--- a/heartbeat/WAS
|
||||
+++ b/heartbeat/WAS
|
||||
@@ -227,7 +227,7 @@ WASPortInfo() {
|
||||
esac
|
||||
PortCount=`expr $PortCount + 1`
|
||||
done
|
||||
- netstat -ltnp 2>/dev/null| egrep -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
|
||||
+ netstat -ltnp 2>/dev/null| $EGREP -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
|
||||
}
|
||||
|
||||
#
|
||||
diff --git a/heartbeat/WAS6 b/heartbeat/WAS6
|
||||
index 9e18cd682d..e71eec9305 100755
|
||||
--- a/heartbeat/WAS6
|
||||
+++ b/heartbeat/WAS6
|
||||
@@ -196,7 +196,7 @@ WASPortInfo() {
|
||||
esac
|
||||
PortCount=`expr $PortCount + 1`
|
||||
done
|
||||
- netstat -ltnp 2>/dev/null| egrep -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
|
||||
+ netstat -ltnp 2>/dev/null| $EGREP -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
|
||||
}
|
||||
|
||||
#
|
||||
diff --git a/heartbeat/docker b/heartbeat/docker
|
||||
index 50523db934..d51c468977 100755
|
||||
--- a/heartbeat/docker
|
||||
+++ b/heartbeat/docker
|
||||
@@ -512,7 +512,7 @@ image_exists()
|
||||
# - image
|
||||
# - repository:port/image
|
||||
# - 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 images | awk '{print $1 ":" $2}' | $EGREP -q -s "^(docker.io\/|${SERVER_NAME}\/)?${IMAGE_NAME}:${IMAGE_TAG}\$"
|
||||
if [ $? -eq 0 ]; then
|
||||
# image found
|
||||
return 0
|
||||
diff --git a/heartbeat/eDir88.in b/heartbeat/eDir88.in
|
||||
index cd945d2c31..9a21ff852d 100644
|
||||
--- a/heartbeat/eDir88.in
|
||||
+++ b/heartbeat/eDir88.in
|
||||
@@ -331,7 +331,7 @@ eDir_monitor() {
|
||||
|
||||
# Monitor IDM first, as it will start before LDAP
|
||||
if [ $MONITOR_IDM -eq 1 ]; then
|
||||
- RET=$($NDSTRACE --config-file "$NDSCONF" -c modules | egrep -i '^vrdim.*Running' | awk '{print $1}')
|
||||
+ RET=$($NDSTRACE --config-file "$NDSCONF" -c modules | $EGREP -i '^vrdim.*Running' | awk '{print $1}')
|
||||
if [ "$RET" != "vrdim" ]; then
|
||||
ocf_log err "eDirectory IDM engine isn't running ($NDSCONF)."
|
||||
return $OCF_ERR_GENERIC
|
||||
diff --git a/heartbeat/mysql-proxy b/heartbeat/mysql-proxy
|
||||
index 013c5e4ec3..2815860d72 100755
|
||||
--- a/heartbeat/mysql-proxy
|
||||
+++ b/heartbeat/mysql-proxy
|
||||
@@ -572,7 +572,7 @@ mysqlproxy_validate_all()
|
||||
fi
|
||||
|
||||
# check for valid log-level
|
||||
- echo $log_level | egrep -q "^(error|warning|info|message|debug|)$"
|
||||
+ echo $log_level | $EGREP -q "^(error|warning|info|message|debug|)$"
|
||||
if [ $? -ne 0 ]; then
|
||||
ocf_log err "MySQL Proxy log level '$log_level' not in valid range error|warning|info|message|debug"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index e88ecc2a13..450e372081 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -529,7 +529,7 @@ IptablesStop()
|
||||
CheckPort() {
|
||||
# Examples of valid port: "1080", "1", "0080"
|
||||
# Examples of invalid port: "1080bad", "0", "0000", ""
|
||||
- echo $1 |egrep -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*'
|
||||
+ echo $1 | $EGREP -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*'
|
||||
}
|
||||
|
||||
IptablesValidateAll()
|
||||
diff --git a/heartbeat/rabbitmq-server-ha b/heartbeat/rabbitmq-server-ha
|
||||
index 8b3cd9ee90..f483380359 100755
|
||||
--- a/heartbeat/rabbitmq-server-ha
|
||||
+++ b/heartbeat/rabbitmq-server-ha
|
||||
@@ -529,7 +529,7 @@ proc_stop()
|
||||
pid="none"
|
||||
else
|
||||
# check if provide just a number
|
||||
- echo "${pid_param}" | egrep -q '^[0-9]+$'
|
||||
+ echo "${pid_param}" | $EGREP -q '^[0-9]+$'
|
||||
if [ $? -eq 0 ]; then
|
||||
pid="${pid_param}"
|
||||
elif [ -e "${pid_param}" ]; then # check if passed in a pid file
|
||||
diff --git a/heartbeat/sapdb.sh b/heartbeat/sapdb.sh
|
||||
index 66e9854b6c..dccd36e172 100755
|
||||
--- a/heartbeat/sapdb.sh
|
||||
+++ b/heartbeat/sapdb.sh
|
||||
@@ -238,7 +238,7 @@ sapdatabase_monitor() {
|
||||
esac
|
||||
|
||||
SEARCH=`echo "$OCF_RESKEY_MONITOR_SERVICES" | sed 's/\+/\\\+/g' | sed 's/\./\\\./g'`
|
||||
- if [ `echo "$SERVICE" | egrep -c "$SEARCH"` -eq 1 ]
|
||||
+ if [ `echo "$SERVICE" | $EGREP -c "$SEARCH"` -eq 1 ]
|
||||
then
|
||||
if [ $STATE -eq $OCF_NOT_RUNNING ]
|
||||
then
|
||||
diff --git a/heartbeat/smb-share.in b/heartbeat/smb-share.in
|
||||
index 8a1a0a8604..3e5bf60bf1 100755
|
||||
--- a/heartbeat/smb-share.in
|
||||
+++ b/heartbeat/smb-share.in
|
||||
@@ -435,7 +435,7 @@ smb_share_stop() {
|
||||
smb_share_monitor() {
|
||||
RES=$(smbcontrol smbd ping > /dev/null 2>&1)
|
||||
if [ $? -eq 0 ];then
|
||||
- if [ $(testparm -s 2>/dev/null| egrep -c \\[$OCF_RESKEY_share\\]) -eq 1 ];then
|
||||
+ if [ $(testparm -s 2>/dev/null| $EGREP -c \\[$OCF_RESKEY_share\\]) -eq 1 ];then
|
||||
return $OCF_SUCCESS
|
||||
else
|
||||
return $OCF_NOT_RUNNING
|
||||
@@ -449,7 +449,7 @@ smb_share_state() {
|
||||
smb_share_checktmpmount
|
||||
RES=$(smbcontrol smbd ping > /dev/null 2>&1)
|
||||
if [ $? -eq 0 ];then
|
||||
- if [ $(testparm -s 2>/dev/null| egrep -c \\[$OCF_RESKEY_share\\]) -eq 1 ];then
|
||||
+ if [ $(testparm -s 2>/dev/null| $EGREP -c \\[$OCF_RESKEY_share\\]) -eq 1 ];then
|
||||
ocf_log info "Samba share $OCF_RESKEY_share is active"
|
||||
return $OCF_SUCCESS
|
||||
else
|
||||
diff --git a/heartbeat/symlink b/heartbeat/symlink
|
||||
index decd9f74e5..82a667a01f 100755
|
||||
--- a/heartbeat/symlink
|
||||
+++ b/heartbeat/symlink
|
||||
@@ -123,7 +123,7 @@ symlink_monitor() {
|
||||
ocf_log debug "$OCF_RESKEY_link exists but is not a symbolic link, will be moved to ${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix} on start"
|
||||
rc=$OCF_NOT_RUNNING
|
||||
fi
|
||||
- elif readlink -m "$OCF_RESKEY_link" | egrep -q "^$(readlink -m ${OCF_RESKEY_target})$"; then
|
||||
+ elif readlink -m "$OCF_RESKEY_link" | $EGREP -q "^$(readlink -m ${OCF_RESKEY_target})$"; then
|
||||
ocf_log debug "$OCF_RESKEY_link exists and is a symbolic link to ${OCF_RESKEY_target}."
|
||||
rc=$OCF_SUCCESS
|
||||
else
|
21
RHEL-75574-2-ocf-binaries-add-FGREP.patch
Normal file
21
RHEL-75574-2-ocf-binaries-add-FGREP.patch
Normal file
@ -0,0 +1,21 @@
|
||||
From 990d37a7209774f91b73ec9cc06e936a96db0f70 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 23 Jan 2025 16:04:39 +0100
|
||||
Subject: [PATCH] ocf-binaries: add FGREP
|
||||
|
||||
---
|
||||
heartbeat/ocf-binaries.in | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/heartbeat/ocf-binaries.in b/heartbeat/ocf-binaries.in
|
||||
index e9bf95fc28..e11ae1d6fb 100644
|
||||
--- a/heartbeat/ocf-binaries.in
|
||||
+++ b/heartbeat/ocf-binaries.in
|
||||
@@ -9,6 +9,7 @@ export PATH
|
||||
# Binaries and binary options for use in Resource Agents
|
||||
: ${AWK:=@AWK@}
|
||||
: ${EGREP:="@EGREP@"}
|
||||
+: ${FGREP:="@FGREP@"}
|
||||
: ${IFCONFIG_A_OPT:="@IFCONFIG_A_OPT@"}
|
||||
: ${MAILCMD:=@MAILCMD@}
|
||||
: ${PING:=@PING@}
|
@ -0,0 +1,23 @@
|
||||
From 2ba4b0c05902da4520a8931b9417b74c5659b5d1 Mon Sep 17 00:00:00 2001
|
||||
From: Satomi OSAWA <satomi.t.osawa@gmail.com>
|
||||
Date: Thu, 23 Jan 2025 10:55:28 +0900
|
||||
Subject: [PATCH] To avoid the Warning when executing the pcs resource create
|
||||
command, the INFO log message in validate-all operation will be suppressed.
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index b48bee142..0c43220df 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -1145,7 +1145,7 @@ check_binary $FSCK
|
||||
check_binary $MOUNT
|
||||
check_binary $UMOUNT
|
||||
|
||||
-if [ "$OP" != "monitor" ]; then
|
||||
+if [ "$OP" != "monitor" ] && [ "$OP" != "validate-all" ]; then
|
||||
ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT"
|
||||
fi
|
||||
|
23
RHEL-76037-1-storage-mon-remove-unused-variables.patch
Normal file
23
RHEL-76037-1-storage-mon-remove-unused-variables.patch
Normal file
@ -0,0 +1,23 @@
|
||||
From a1e22c5c612f369bac0830588642560dcea92e7c Mon Sep 17 00:00:00 2001
|
||||
From: Fujii Masao <fujii@postgresql.org>
|
||||
Date: Sat, 9 Nov 2024 02:33:37 +0900
|
||||
Subject: [PATCH] Remove unused macro variables from storage_mon.c.
|
||||
|
||||
---
|
||||
tools/storage_mon.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/tools/storage_mon.c b/tools/storage_mon.c
|
||||
index f94268f6f..2519a9e72 100644
|
||||
--- a/tools/storage_mon.c
|
||||
+++ b/tools/storage_mon.c
|
||||
@@ -33,9 +33,6 @@
|
||||
#define DEFAULT_PIDFILE HA_VARRUNDIR "storage_mon.pid"
|
||||
#define DEFAULT_ATTRNAME "#health-storage_mon"
|
||||
#define SMON_GET_RESULT_COMMAND "get_check_value"
|
||||
-#define SMON_RESULT_OK "green"
|
||||
-#define SMON_RESULT_NG "red"
|
||||
-#define SMON_RESULT_COMMAND_ERROR "unknown command"
|
||||
#define SMON_BUFF_1MEG 1048576
|
||||
#define SMON_MAX_IPCSNAME 256
|
||||
#define SMON_MAX_MSGSIZE 128
|
@ -0,0 +1,79 @@
|
||||
From 46715c638829598d949dffab0898fe4c07074895 Mon Sep 17 00:00:00 2001
|
||||
From: Hideo Yamauchi <renayama19661014@ybb.ne.jp>
|
||||
Date: Thu, 21 Nov 2024 15:21:19 +0900
|
||||
Subject: [PATCH 1/2] High: storage-mon: Correct the timing of setting
|
||||
notification values to storage-mon(RA) clients.
|
||||
|
||||
---
|
||||
tools/storage_mon.c | 17 ++++++++---------
|
||||
1 file changed, 8 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/tools/storage_mon.c b/tools/storage_mon.c
|
||||
index 2519a9e72..27d2ff1d1 100644
|
||||
--- a/tools/storage_mon.c
|
||||
+++ b/tools/storage_mon.c
|
||||
@@ -320,7 +320,14 @@ static int32_t sigchld_handler(int32_t sig, void *data)
|
||||
|
||||
finished_count++;
|
||||
test_forks[index] = 0;
|
||||
-
|
||||
+
|
||||
+ /* Update the result value for the client response once all checks have completed. */
|
||||
+ if (device_count == finished_count) {
|
||||
+ response_final_score = final_score;
|
||||
+ if (!daemon_check_first_all_devices) {
|
||||
+ daemon_check_first_all_devices = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -441,15 +448,7 @@ static int test_device_main(gpointer data)
|
||||
if (is_child_runnning()) {
|
||||
device_check = FALSE;
|
||||
}
|
||||
-
|
||||
- if (device_count == finished_count && device_check) {
|
||||
- /* Update the result value for the client response once all checks have completed. */
|
||||
- response_final_score = final_score;
|
||||
|
||||
- if (!daemon_check_first_all_devices) {
|
||||
- daemon_check_first_all_devices = TRUE;
|
||||
- }
|
||||
- }
|
||||
}
|
||||
|
||||
if (device_check) {
|
||||
|
||||
From 1201390fb219d1b566c5d31463daacef60c31ab4 Mon Sep 17 00:00:00 2001
|
||||
From: Hideo Yamauchi <renayama19661014@ybb.ne.jp>
|
||||
Date: Thu, 21 Nov 2024 15:43:33 +0900
|
||||
Subject: [PATCH 2/2] Mid: storage-mon RA: Wait until monitor confirms the
|
||||
startup pid according to the OCF resource specification.
|
||||
|
||||
---
|
||||
heartbeat/storage-mon.in | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/storage-mon.in b/heartbeat/storage-mon.in
|
||||
index 284dec30f..7c9943d4f 100644
|
||||
--- a/heartbeat/storage-mon.in
|
||||
+++ b/heartbeat/storage-mon.in
|
||||
@@ -325,6 +325,17 @@ storage-mon_start() {
|
||||
if [ "$?" -ne 0 ]; then
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
+
|
||||
+ #Wait until monitor confirms the startup pid according to the ocf resource specification.
|
||||
+ while true; do
|
||||
+ storage-mon_monitor pid_check_only
|
||||
+ rc="$?"
|
||||
+ if [ $rc -eq $OCF_SUCCESS ]; then
|
||||
+ break
|
||||
+ fi
|
||||
+ sleep 1
|
||||
+ ocf_log debug "storage-mon daemon still hasn't started yet. Waiting..."
|
||||
+ done
|
||||
fi
|
||||
}
|
||||
|
148
RHEL-76037-3-storage-mon-only-use-underscores-in-functions.patch
Normal file
148
RHEL-76037-3-storage-mon-only-use-underscores-in-functions.patch
Normal file
@ -0,0 +1,148 @@
|
||||
From b72b329a45c058fda720c6739f881b9597fc8b30 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 23 Jan 2025 16:18:20 +0100
|
||||
Subject: [PATCH] storage-mon: replace dashes with underscores in functions
|
||||
|
||||
Dashes in function names produce "`storage-mon_usage': not a valid identifier"
|
||||
error when run with sh -x.
|
||||
---
|
||||
heartbeat/storage-mon.in | 44 ++++++++++++++++++++--------------------
|
||||
1 file changed, 22 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/storage-mon.in b/heartbeat/storage-mon.in
|
||||
index 7c9943d4f..5edb96979 100644
|
||||
--- a/heartbeat/storage-mon.in
|
||||
+++ b/heartbeat/storage-mon.in
|
||||
@@ -152,7 +152,7 @@ END
|
||||
|
||||
#######################################################################
|
||||
|
||||
-storage-mon_usage() {
|
||||
+storage_mon_usage() {
|
||||
cat <<END
|
||||
usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
|
||||
@@ -161,7 +161,7 @@ END
|
||||
return $1
|
||||
}
|
||||
|
||||
-storage-mon_init() {
|
||||
+storage_mon_init() {
|
||||
#Test for presence of storage_mon helper
|
||||
if [ ! -x "$STORAGEMON" ] ; then
|
||||
ocf_log err "${STORAGEMON} not installed."
|
||||
@@ -205,7 +205,7 @@ storage-mon_init() {
|
||||
fi
|
||||
}
|
||||
|
||||
-storage-mon_update_attribute() {
|
||||
+storage_mon_update_attribute() {
|
||||
|
||||
while :
|
||||
do
|
||||
@@ -224,9 +224,9 @@ storage-mon_update_attribute() {
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
-storage-mon_monitor() {
|
||||
+storage_mon_monitor() {
|
||||
if ! ocf_is_true "$OCF_RESKEY_daemonize"; then
|
||||
- storage-mon_init
|
||||
+ storage_mon_init
|
||||
|
||||
# Monitor _MUST!_ differentiate correctly between running
|
||||
# (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING).
|
||||
@@ -252,7 +252,7 @@ storage-mon_monitor() {
|
||||
status="green"
|
||||
fi
|
||||
|
||||
- storage-mon_update_attribute $status
|
||||
+ storage_mon_update_attribute $status
|
||||
return "$?"
|
||||
else
|
||||
ocf_pidfile_status "${PIDFILE}" > /dev/null 2>&1
|
||||
@@ -298,20 +298,20 @@ storage-mon_monitor() {
|
||||
esac
|
||||
done
|
||||
|
||||
- storage-mon_update_attribute $status
|
||||
+ storage_mon_update_attribute $status
|
||||
return "$?"
|
||||
fi
|
||||
}
|
||||
|
||||
-storage-mon_start() {
|
||||
+storage_mon_start() {
|
||||
if ! ocf_is_true "$OCF_RESKEY_daemonize"; then
|
||||
- storage-mon_monitor
|
||||
+ storage_mon_monitor
|
||||
if [ $? -eq $OCF_SUCCESS ]; then
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
touch "${OCF_RESKEY_state_file}"
|
||||
else
|
||||
- storage-mon_init
|
||||
+ storage_mon_init
|
||||
# generate command line
|
||||
cmdline=""
|
||||
for DRIVE in ${OCF_RESKEY_drives}; do
|
||||
@@ -328,7 +328,7 @@ storage-mon_start() {
|
||||
|
||||
#Wait until monitor confirms the startup pid according to the ocf resource specification.
|
||||
while true; do
|
||||
- storage-mon_monitor pid_check_only
|
||||
+ storage_mon_monitor pid_check_only
|
||||
rc="$?"
|
||||
if [ $rc -eq $OCF_SUCCESS ]; then
|
||||
break
|
||||
@@ -339,8 +339,8 @@ storage-mon_start() {
|
||||
fi
|
||||
}
|
||||
|
||||
-storage-mon_stop() {
|
||||
- storage-mon_monitor
|
||||
+storage_mon_stop() {
|
||||
+ storage_mon_monitor
|
||||
rc=$?
|
||||
|
||||
if ! ocf_is_true "$OCF_RESKEY_daemonize"; then
|
||||
@@ -363,7 +363,7 @@ storage-mon_stop() {
|
||||
fi
|
||||
|
||||
while true; do
|
||||
- storage-mon_monitor pid_check_only
|
||||
+ storage_mon_monitor pid_check_only
|
||||
rc="$?"
|
||||
case "$rc" in
|
||||
$OCF_SUCCESS)
|
||||
@@ -379,8 +379,8 @@ storage-mon_stop() {
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
-storage-mon_validate() {
|
||||
- storage-mon_init
|
||||
+storage_mon_validate() {
|
||||
+ storage_mon_init
|
||||
|
||||
if ! ocf_is_true "$OCF_RESKEY_daemonize"; then
|
||||
# Is the state directory writable?
|
||||
@@ -396,13 +396,13 @@ storage-mon_validate() {
|
||||
}
|
||||
|
||||
case "$__OCF_ACTION" in
|
||||
- start) storage-mon_start;;
|
||||
- stop) storage-mon_stop;;
|
||||
- monitor) storage-mon_monitor;;
|
||||
- validate-all) storage-mon_validate;;
|
||||
+ start) storage_mon_start;;
|
||||
+ stop) storage_mon_stop;;
|
||||
+ monitor) storage_mon_monitor;;
|
||||
+ validate-all) storage_mon_validate;;
|
||||
meta-data) meta_data;;
|
||||
- usage|help) storage-mon_usage $OCF_SUCCESS;;
|
||||
- *) storage-mon_usage $OCF_ERR_UNIMPLEMENTED;;
|
||||
+ usage|help) storage_mon_usage $OCF_SUCCESS;;
|
||||
+ *) storage_mon_usage $OCF_ERR_UNIMPLEMENTED;;
|
||||
esac
|
||||
rc=$?
|
||||
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
@ -0,0 +1,25 @@
|
||||
From c6f520344e830a7c946b2222f9f251be038b1b28 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 24 Jan 2025 10:01:30 +0100
|
||||
Subject: [PATCH] storage-mon: check if daemon is already running during
|
||||
start-action
|
||||
|
||||
---
|
||||
heartbeat/storage-mon.in | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/storage-mon.in b/heartbeat/storage-mon.in
|
||||
index 5edb96979..00e42f68d 100644
|
||||
--- a/heartbeat/storage-mon.in
|
||||
+++ b/heartbeat/storage-mon.in
|
||||
@@ -311,6 +311,10 @@ storage_mon_start() {
|
||||
fi
|
||||
touch "${OCF_RESKEY_state_file}"
|
||||
else
|
||||
+ storage_mon_monitor pid_check_only
|
||||
+ if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ return $OCF_SUCCESS
|
||||
+ fi
|
||||
storage_mon_init
|
||||
# generate command line
|
||||
cmdline=""
|
@ -0,0 +1,22 @@
|
||||
From de51a1705ce761f1fb5f1b2294cfc1153af70c1c Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 27 Jan 2025 09:54:06 +0100
|
||||
Subject: [PATCH] storage-mon: log "storage_mon is already running" in
|
||||
start-action
|
||||
|
||||
---
|
||||
heartbeat/storage-mon.in | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/heartbeat/storage-mon.in b/heartbeat/storage-mon.in
|
||||
index 00e42f68d..d60db4ad4 100644
|
||||
--- a/heartbeat/storage-mon.in
|
||||
+++ b/heartbeat/storage-mon.in
|
||||
@@ -313,6 +313,7 @@ storage_mon_start() {
|
||||
else
|
||||
storage_mon_monitor pid_check_only
|
||||
if [ $? -eq $OCF_SUCCESS ]; then
|
||||
+ ocf_log info "storage_mon is already running. PID=`cat $PIDFILE`"
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
storage_mon_init
|
46
RHEL-79822-1-portblock-fix-version-detection.patch
Normal file
46
RHEL-79822-1-portblock-fix-version-detection.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 575dcec0cd97af26623975cbc43564d25b91b346 Mon Sep 17 00:00:00 2001
|
||||
From: abrychcy <abrychcy@users.noreply.github.com>
|
||||
Date: Wed, 12 Feb 2025 19:49:22 +0100
|
||||
Subject: [PATCH 1/2] Update portblock: improve version detection of iptables
|
||||
|
||||
The awk script does not remove suffixes after the version string. ocf_version_cmp fails to compare this string. wait option will never be added if (nf_tables) or (legacy) is present after vX.Y.Z
|
||||
---
|
||||
heartbeat/portblock | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index 450e37208..ea22f76a6 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -618,7 +618,7 @@ if [ -z "$OCF_RESKEY_action" ]; then
|
||||
fi
|
||||
|
||||
# iptables v1.4.20+ is required to use -w (wait)
|
||||
-version=$(iptables -V | awk -F ' v' '{print $NF}')
|
||||
+version=$(iptables -V | grep -oE '[0-9]+(\.[0-9]+)+')
|
||||
ocf_version_cmp "$version" "1.4.19.1"
|
||||
if [ "$?" -eq "2" ]; then
|
||||
wait="-w"
|
||||
|
||||
From 938867b0c4a77448403961b94aa04f9a34c72b11 Mon Sep 17 00:00:00 2001
|
||||
From: abrychcy <abrychcy@users.noreply.github.com>
|
||||
Date: Thu, 13 Feb 2025 19:16:26 +0100
|
||||
Subject: [PATCH 2/2] simplify iptables version string regex
|
||||
|
||||
---
|
||||
heartbeat/portblock | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index ea22f76a6..2fca0f893 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -618,7 +618,7 @@ if [ -z "$OCF_RESKEY_action" ]; then
|
||||
fi
|
||||
|
||||
# iptables v1.4.20+ is required to use -w (wait)
|
||||
-version=$(iptables -V | grep -oE '[0-9]+(\.[0-9]+)+')
|
||||
+version=$(iptables -V | grep -oE '[0-9]+[\.0-9]+')
|
||||
ocf_version_cmp "$version" "1.4.19.1"
|
||||
if [ "$?" -eq "2" ]; then
|
||||
wait="-w"
|
43
RHEL-79822-2-portblock-use-ocf_log-for-logging.patch
Normal file
43
RHEL-79822-2-portblock-use-ocf_log-for-logging.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 8a3328c07d8e8f1cfe34dd37afaa5707dcafce9b Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 20 Feb 2025 14:24:34 +0100
|
||||
Subject: [PATCH] portblock: use ocf_log() for logging
|
||||
|
||||
---
|
||||
heartbeat/portblock | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index 2fca0f893..9b4f5db39 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -359,17 +359,17 @@ tickle_local()
|
||||
|
||||
SayActive()
|
||||
{
|
||||
- echo "$CMD DROP rule [$*] is running (OK)"
|
||||
+ ocf_log debug "$CMD DROP rule [$*] is running (OK)"
|
||||
}
|
||||
|
||||
SayConsideredActive()
|
||||
{
|
||||
- echo "$CMD DROP rule [$*] considered to be running (OK)"
|
||||
+ ocf_log debug "$CMD DROP rule [$*] considered to be running (OK)"
|
||||
}
|
||||
|
||||
SayInactive()
|
||||
{
|
||||
- echo "$CMD DROP rule [$*] is inactive"
|
||||
+ ocf_log debug "$CMD DROP rule [$*] is inactive"
|
||||
}
|
||||
|
||||
#IptablesStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
@@ -430,7 +430,7 @@ DoIptables()
|
||||
op=$1 proto=$2 ports=$3 ip=$4 chain=$5
|
||||
active=0; chain_isactive "$proto" "$ports" "$ip" "$chain" && active=1
|
||||
want_active=0; [ "$op" = "-I" ] && want_active=1
|
||||
- echo "active: $active want_active: $want_active"
|
||||
+ ocf_log debug "active: $active want_active: $want_active"
|
||||
if [ $active -eq $want_active ] ; then
|
||||
: Chain already in desired state
|
||||
else
|
@ -0,0 +1,118 @@
|
||||
From 4a228f3d8212368124134c01f958ac43e32cec08 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 7 Apr 2025 09:19:37 +0200
|
||||
Subject: [PATCH] IPaddr2: add link status DOWN/LOWERLAYERDOWN check
|
||||
|
||||
---
|
||||
heartbeat/IPaddr2 | 42 +++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 41 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
|
||||
index cf03e4426..230ac853c 100755
|
||||
--- a/heartbeat/IPaddr2
|
||||
+++ b/heartbeat/IPaddr2
|
||||
@@ -92,6 +92,19 @@ OCF_RESKEY_nodad_default=false
|
||||
OCF_RESKEY_noprefixroute_default="false"
|
||||
OCF_RESKEY_preferred_lft_default="forever"
|
||||
OCF_RESKEY_network_namespace_default=""
|
||||
+OCF_RESKEY_check_link_status_default="true"
|
||||
+
|
||||
+# RHEL specific defaults
|
||||
+if is_redhat_based; then
|
||||
+ get_os_ver
|
||||
+ ocf_version_cmp "$VER" "10.1" 2>/dev/null
|
||||
+
|
||||
+ case "$?" in
|
||||
+ # RHEL < 10.1
|
||||
+ 0)
|
||||
+ OCF_RESKEY_check_link_status_default="false";;
|
||||
+ esac
|
||||
+fi
|
||||
|
||||
: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
|
||||
: ${OCF_RESKEY_cidr_netmask=${OCF_RESKEY_cidr_netmask_default}}
|
||||
@@ -116,6 +129,7 @@ OCF_RESKEY_network_namespace_default=""
|
||||
: ${OCF_RESKEY_noprefixroute=${OCF_RESKEY_noprefixroute_default}}
|
||||
: ${OCF_RESKEY_preferred_lft=${OCF_RESKEY_preferred_lft_default}}
|
||||
: ${OCF_RESKEY_network_namespace=${OCF_RESKEY_network_namespace_default}}
|
||||
+: ${OCF_RESKEY_check_link_status=${OCF_RESKEY_check_link_status_default}}
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -449,6 +463,14 @@ the namespace.
|
||||
<shortdesc lang="en">Network namespace to use</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_network_namespace_default}"/>
|
||||
</parameter>
|
||||
+
|
||||
+<parameter name="check_link_status">
|
||||
+<longdesc lang="en">
|
||||
+Consider the resource failed if the interface has status DOWN or LOWERLAYERDOWN.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Consider the resource failed if the interface has status DOWN or LOWERLAYERDOWN</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_check_link_status_default}"/>
|
||||
+</parameter>
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -581,6 +603,9 @@ ip_init() {
|
||||
elif [ "$__OCF_ACTION" = stop ]; then
|
||||
ocf_log warn "[$FINDIF] failed"
|
||||
exit $OCF_SUCCESS
|
||||
+ elif [ "$__OCF_ACTION" = start ]; then
|
||||
+ ocf_exit_reason "[$FINDIF] failed"
|
||||
+ exit $OCF_ERR_INSTALLED
|
||||
else
|
||||
ocf_exit_reason "[$FINDIF] failed"
|
||||
exit $rc
|
||||
@@ -1002,6 +1027,12 @@ ip_served() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
+ if ocf_is_true "$OCF_RESKEY_check_link_status" && $IP2UTIL -f $FAMILY addr show $cur_nic | \
|
||||
+ grep -q "[[:space:]]\(DOWN\|LOWERLAYERDOWN\)[[:space:]]"; then
|
||||
+ echo "down"
|
||||
+ return 0
|
||||
+ fi
|
||||
+
|
||||
if [ -z "$IP_CIP" ]; then
|
||||
for i in $cur_nic; do
|
||||
# check address label
|
||||
@@ -1073,6 +1104,11 @@ ip_start() {
|
||||
exit $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
+ if [ "$ip_status" = "down" ]; then
|
||||
+ ocf_exit_reason "IP $OCF_RESKEY_ip available, but device has status $ip_status"
|
||||
+ exit $OCF_ERR_INSTALLED
|
||||
+ fi
|
||||
+
|
||||
if [ "$ip_status" = "partial3" ]; then
|
||||
ocf_exit_reason "IP $OCF_RESKEY_ip available, but label missing"
|
||||
exit $OCF_ERR_GENERIC
|
||||
@@ -1096,7 +1132,7 @@ ip_start() {
|
||||
echo "+$IP_INC_NO" >$IP_CIP_FILE
|
||||
fi
|
||||
|
||||
- if [ "$ip_status" = "no" ]; then
|
||||
+ if [ "$ip_status" != "ok" ]; then
|
||||
if ocf_is_true ${OCF_RESKEY_lvs_support}; then
|
||||
for i in `find_interface $OCF_RESKEY_ip 32`; do
|
||||
case $i in
|
||||
@@ -1213,6 +1249,7 @@ ip_monitor() {
|
||||
# interface health maybe via a daemon like FailSafe etc...
|
||||
|
||||
local ip_status=`ip_served`
|
||||
+ ocf_log debug "monitor: $ip_status"
|
||||
case $ip_status in
|
||||
ok)
|
||||
run_arp_sender refresh
|
||||
@@ -1221,6 +1258,9 @@ ip_monitor() {
|
||||
no)
|
||||
exit $OCF_NOT_RUNNING
|
||||
;;
|
||||
+ down)
|
||||
+ exit $OCF_ERR_INSTALLED
|
||||
+ ;;
|
||||
*)
|
||||
# Errors on this interface?
|
||||
return $OCF_ERR_GENERIC
|
23
RHEL-85057-2-tomcat-log-validate-all-on-debug-level.patch
Normal file
23
RHEL-85057-2-tomcat-log-validate-all-on-debug-level.patch
Normal file
@ -0,0 +1,23 @@
|
||||
From fbefa52578c5b803e986466e0b9930316a779adb Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Wed, 9 Apr 2025 12:30:36 +0200
|
||||
Subject: [PATCH] tomcat: only log "validate_all_tomcat[$TOMCAT_NAME]" on
|
||||
debug-level
|
||||
|
||||
---
|
||||
heartbeat/tomcat | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/tomcat b/heartbeat/tomcat
|
||||
index 1e8f21638..540cb733e 100755
|
||||
--- a/heartbeat/tomcat
|
||||
+++ b/heartbeat/tomcat
|
||||
@@ -560,7 +560,7 @@ validate_all_tomcat()
|
||||
{
|
||||
local port
|
||||
local rc=$OCF_SUCCESS
|
||||
- ocf_log info "validate_all_tomcat[$TOMCAT_NAME]"
|
||||
+ ocf_log debug "validate_all_tomcat[$TOMCAT_NAME]"
|
||||
|
||||
check_binary $WGET
|
||||
|
1643
RHEL-88431-1-podman-etcd-new-ra.patch
Normal file
1643
RHEL-88431-1-podman-etcd-new-ra.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@
|
||||
From 6a3249aae260c081ccbcfd09444d5d85ebc4e3b3 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 28 Apr 2025 15:48:29 +0200
|
||||
Subject: [PATCH] podman-etcd: remove unused actions from metadata
|
||||
|
||||
---
|
||||
heartbeat/podman-etcd | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 514dd2e5b..3a2323260 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -236,8 +236,6 @@ to stop the container before pacemaker.
|
||||
<action name="start" timeout="600s" />
|
||||
<action name="stop" timeout="90s" />
|
||||
<action name="monitor" timeout="25s" interval="30s" depth="0" />
|
||||
-<action name="promote" timeout="300s" />
|
||||
-<action name="demote" timeout="120s" />
|
||||
<action name="meta-data" timeout="5s" />
|
||||
<action name="validate-all" timeout="30s" />
|
||||
</actions>
|
||||
@@ -251,7 +249,7 @@ REQUIRE_IMAGE_PULL=0
|
||||
podman_usage()
|
||||
{
|
||||
cat <<END
|
||||
-usage: $0 {start|stop|monitor|promote|demote|validate-all|meta-data}
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
|
||||
Expects to have a fully populated OCF RA-compliant environment set.
|
||||
END
|
36
RHEL-88431-3-podman-etcd-fix-listen-peer-urls-binding.patch
Normal file
36
RHEL-88431-3-podman-etcd-fix-listen-peer-urls-binding.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 5f7b9b045d4713e8ff27a4fc8b2799669c1b823a Mon Sep 17 00:00:00 2001
|
||||
From: Carlo Lobrano <c.lobrano@gmail.com>
|
||||
Date: Tue, 20 May 2025 09:34:03 +0200
|
||||
Subject: [PATCH] podman-etcd: fix listen-peer-urls binding (#2049)
|
||||
|
||||
This change ensures learner etcd listens on all interfaces for peer
|
||||
connections, resolving accessibility issues.
|
||||
|
||||
Fix: OCPBUGS-56447
|
||||
---
|
||||
heartbeat/podman-etcd | 12 +++---------
|
||||
1 file changed, 3 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/podman-etcd b/heartbeat/podman-etcd
|
||||
index 3a2323260..6762112ec 100755
|
||||
--- a/heartbeat/podman-etcd
|
||||
+++ b/heartbeat/podman-etcd
|
||||
@@ -436,15 +436,9 @@ prepare_env() {
|
||||
ETCD_PEER_CERT=$(get_env_from_manifest "ETCDCTL_CERT")
|
||||
ETCD_PEER_KEY=$(get_env_from_manifest "ETCDCTL_KEY")
|
||||
|
||||
- if is_learner; then
|
||||
- LISTEN_CLIENT_URLS="$NODEIP"
|
||||
- LISTEN_PEER_URLS="$NODEIP"
|
||||
- LISTEN_METRICS_URLS="$NODEIP"
|
||||
- else
|
||||
- LISTEN_CLIENT_URLS="0.0.0.0"
|
||||
- LISTEN_PEER_URLS="0.0.0.0"
|
||||
- LISTEN_METRICS_URLS="0.0.0.0"
|
||||
- fi
|
||||
+ LISTEN_CLIENT_URLS="0.0.0.0"
|
||||
+ LISTEN_PEER_URLS="0.0.0.0"
|
||||
+ LISTEN_METRICS_URLS="0.0.0.0"
|
||||
}
|
||||
|
||||
archive_data_folder()
|
@ -0,0 +1,32 @@
|
||||
From 843c3b6f3bc4d2d60fd2c4dccbf00c10f29c5894 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Zhong <lidong.zhong@suse.com>
|
||||
Date: Fri, 25 Apr 2025 14:24:41 +0800
|
||||
Subject: [PATCH] Filesystem: fix getting the wrong block device when doing
|
||||
grep
|
||||
|
||||
If we have such a filesystem structure mounted in our cluster
|
||||
/dev/drbd50 /export/prq/upgrade_emspq xfs
|
||||
/dev/drbd55 /export/prq/upgrade_sharedmsb xfs
|
||||
/dev/drbd1 /export/devAGN/share xfs
|
||||
/dev/drbd5 /export/dev/archivesn1agn xfs
|
||||
|
||||
When we want to stop the filesystem mounted on
|
||||
/export/dev/archivesn1agn, we probably will get the wrong entry returned
|
||||
here and thus will try to stop the wrong target.
|
||||
---
|
||||
heartbeat/Filesystem | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 0c43220df..d10e5a714 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -408,7 +408,7 @@ list_bindmounts() {
|
||||
fi
|
||||
|
||||
if [ -b "$mount_disk" ]; then
|
||||
- list_mounts | grep "$mount_disk" | grep -v "$match_string" | cut -d"$TAB" -f2 | sort -r
|
||||
+ list_mounts | grep -w "$mount_disk" | grep -v "$match_string" | cut -d"$TAB" -f2 | sort -r
|
||||
fi
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
From d0d2a0ff92dd23ee36cb57324c1eeaa3daed65bc Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 4 Feb 2025 16:13:27 +0100
|
||||
Subject: [PATCH] findif.sh: fix to avoid duplicate route issues
|
||||
|
||||
---
|
||||
heartbeat/findif.sh | 14 +++++---------
|
||||
1 file changed, 5 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/findif.sh b/heartbeat/findif.sh
|
||||
index 2ae91e958..6fb47110c 100644
|
||||
--- a/heartbeat/findif.sh
|
||||
+++ b/heartbeat/findif.sh
|
||||
@@ -217,18 +217,14 @@ findif()
|
||||
fi
|
||||
if [ -n "$nic" ] ; then
|
||||
# NIC supports more than two.
|
||||
- routematch=$(ip -o -f $family route list match $match $proto $scope | grep -v "^\(unreachable\|prohibit\|blackhole\)" | grep "dev $nic " | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
|
||||
+ routematch=$(ip -o -f $family route list match $match $proto $scope | grep "dev $nic " | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
|
||||
else
|
||||
- routematch=$(ip -o -f $family route list match $match $proto $scope | grep -v "^\(unreachable\|prohibit\|blackhole\)" | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
|
||||
- fi
|
||||
- if [ "$family" = "inet6" ]; then
|
||||
- routematch=$(echo "$routematch" | grep -v "^default")
|
||||
+ routematch=$(ip -o -f $family route list match $match $proto $scope | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
|
||||
fi
|
||||
|
||||
- if [ $(echo "$routematch" | wc -l) -gt 1 ]; then
|
||||
- ocf_exit_reason "More than 1 routes match $match. Unable to decide which route to use."
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
+ # ignore matches from unrelated tables, and sort by metric to get the route with the lowest metric
|
||||
+ routematch=$(echo "$routematch" | awk '!/^(default|unreachable|prohibit|blackhole)/{match($0, /metric ([^ ]+)/, arr); print arr[1], $0}' | sort -k 1n -u | cut -d" " -f 2- | head -1)
|
||||
+
|
||||
set -- $routematch
|
||||
if [ $# = 0 ] ; then
|
||||
case $OCF_RESKEY_ip in
|
24
RHEL-97216-Filesystem-fix-issue-with-Vormetric-mounts.patch
Normal file
24
RHEL-97216-Filesystem-fix-issue-with-Vormetric-mounts.patch
Normal file
@ -0,0 +1,24 @@
|
||||
From 9127148e15fc200356df2571c7c9e5a716854c24 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 26 Jun 2025 09:39:31 +0200
|
||||
Subject: [PATCH] Filesystem: fix issue with Vormetric mounts
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index d10e5a714..515a3919d 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -361,8 +361,8 @@ list_mounts() {
|
||||
fi
|
||||
done
|
||||
|
||||
- # Convert octal \040 to space characters
|
||||
- printf "$mount_list"
|
||||
+ # Convert octal \040 to space characters and ignore Vormetric mounts
|
||||
+ printf "$mount_list" | grep -v "secfs2$"
|
||||
}
|
||||
|
||||
determine_blockdevice() {
|
45
RHEL-99743-Filesystem-remove-validate-all-fstype-check.patch
Normal file
45
RHEL-99743-Filesystem-remove-validate-all-fstype-check.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 08c5b856a671b1583d3547dd76faf8a907485a12 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 19 Jun 2025 13:11:29 +0200
|
||||
Subject: [PATCH] Filesystem: remove validate-all fstype check, as there isnt a
|
||||
reliable and portable way to check
|
||||
|
||||
This check cause Warnings and might cause errors in future pcs versions
|
||||
when running "pcs resource create".
|
||||
|
||||
Example:
|
||||
Warning: Validating resource options using the resource agent itself is enabled by default and produces warnings. In a future version, this might be changed to errors. Specify --agent-validation to switch to the future behavior.
|
||||
Warning: Validation result from agent:
|
||||
Jun 19 06:13:45 INFO: It seems we do not have ext3 support
|
||||
---
|
||||
heartbeat/Filesystem | 17 -----------------
|
||||
1 file changed, 17 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index d10e5a714..6d3960162 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -978,23 +978,6 @@ Filesystem_monitor()
|
||||
#
|
||||
Filesystem_validate_all()
|
||||
{
|
||||
- # Check if the $FSTYPE is workable
|
||||
- # NOTE: Without inserting the $FSTYPE module, this step may be imprecise
|
||||
- # TODO: This is Linux specific crap.
|
||||
- if [ ! -z "$FSTYPE" -a "$FSTYPE" != none ]; then
|
||||
- cut -f2 /proc/filesystems | grep "^${FSTYPE}$" >/dev/null 2>&1
|
||||
- if [ $? -ne 0 ]; then
|
||||
- modpath=/lib/modules/$(uname -r)
|
||||
- moddep=$modpath/modules.dep
|
||||
- # Do we have $FSTYPE in modules.dep?
|
||||
- cut -d' ' -f1 $moddep \
|
||||
- | grep "^${modpath}.*${FSTYPE}\.k\?o:$" >/dev/null 2>&1
|
||||
- if [ $? -ne 0 ]; then
|
||||
- ocf_log info "It seems we do not have $FSTYPE support"
|
||||
- fi
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
# If we are supposed to do monitoring with status files, then
|
||||
# we need a utility to write in O_DIRECT mode.
|
||||
if [ $OCF_CHECK_LEVEL -gt 0 ]; then
|
@ -1,25 +0,0 @@
|
||||
diff -uNr a/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/calliope/usage_text.py b/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/calliope/usage_text.py
|
||||
--- a/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/calliope/usage_text.py 1980-01-01 09:00:00.000000000 +0100
|
||||
+++ b/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/calliope/usage_text.py 2019-04-04 11:59:47.592768577 +0200
|
||||
@@ -900,6 +900,9 @@
|
||||
return """\
|
||||
For detailed information on this command and its flags, run:
|
||||
{command_path} --help
|
||||
+
|
||||
+WARNING: {command_path} is only supported for "{command_path} init" and for use
|
||||
+with the agents in resource-agents.
|
||||
""".format(command_path=' '.join(command.GetPath()))
|
||||
|
||||
|
||||
diff -uNr a/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/gcloud_main.py b/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/gcloud_main.py
|
||||
--- a/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/gcloud_main.py 1980-01-01 09:00:00.000000000 +0100
|
||||
+++ b/bundled/gcp/google-cloud-sdk/lib/googlecloudsdk/gcloud_main.py 2019-04-04 12:00:23.991142694 +0200
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
pkg_root = os.path.dirname(os.path.dirname(surface.__file__))
|
||||
loader = cli.CLILoader(
|
||||
- name='gcloud',
|
||||
+ name='gcloud-ra',
|
||||
command_root_directory=os.path.join(pkg_root, 'surface'),
|
||||
allow_non_existing_modules=True,
|
||||
version_func=VersionFunc,
|
@ -1,45 +0,0 @@
|
||||
diff --color -uNr a/heartbeat/gcp-pd-move.in b/heartbeat/gcp-pd-move.in
|
||||
--- a/heartbeat/gcp-pd-move.in 2024-07-22 10:59:42.170483160 +0200
|
||||
+++ b/heartbeat/gcp-pd-move.in 2024-07-22 11:01:51.455543850 +0200
|
||||
@@ -32,6 +32,7 @@
|
||||
from ocf import logger
|
||||
|
||||
try:
|
||||
+ sys.path.insert(0, '/usr/lib/resource-agents/bundled/gcp')
|
||||
import googleapiclient.discovery
|
||||
except ImportError:
|
||||
pass
|
||||
diff --color -uNr a/heartbeat/gcp-vpc-move-ip.in b/heartbeat/gcp-vpc-move-ip.in
|
||||
--- a/heartbeat/gcp-vpc-move-ip.in 2024-07-22 10:59:42.170483160 +0200
|
||||
+++ b/heartbeat/gcp-vpc-move-ip.in 2024-07-22 11:01:18.010752081 +0200
|
||||
@@ -36,7 +36,7 @@
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
# Defaults
|
||||
-OCF_RESKEY_gcloud_default="/usr/bin/gcloud"
|
||||
+OCF_RESKEY_gcloud_default="/usr/bin/gcloud-ra"
|
||||
OCF_RESKEY_configuration_default="default"
|
||||
OCF_RESKEY_vpc_network_default="default"
|
||||
OCF_RESKEY_interface_default="eth0"
|
||||
diff --color -uNr a/heartbeat/gcp-vpc-move-route.in b/heartbeat/gcp-vpc-move-route.in
|
||||
--- a/heartbeat/gcp-vpc-move-route.in 2024-07-22 10:59:42.170483160 +0200
|
||||
+++ b/heartbeat/gcp-vpc-move-route.in 2024-07-22 11:01:18.011752105 +0200
|
||||
@@ -45,6 +45,7 @@
|
||||
from ocf import *
|
||||
|
||||
try:
|
||||
+ sys.path.insert(0, '/usr/lib/resource-agents/bundled/gcp')
|
||||
import googleapiclient.discovery
|
||||
import pyroute2
|
||||
try:
|
||||
diff --color -uNr a/heartbeat/gcp-vpc-move-vip.in b/heartbeat/gcp-vpc-move-vip.in
|
||||
--- a/heartbeat/gcp-vpc-move-vip.in 2024-07-22 10:59:42.170483160 +0200
|
||||
+++ b/heartbeat/gcp-vpc-move-vip.in 2024-07-22 11:01:18.012752128 +0200
|
||||
@@ -29,6 +29,7 @@
|
||||
from ocf import *
|
||||
|
||||
try:
|
||||
+ sys.path.insert(0, '/usr/lib/resource-agents/bundled/gcp')
|
||||
import googleapiclient.discovery
|
||||
try:
|
||||
from google.oauth2.service_account import Credentials as ServiceAccountCredentials
|
@ -1,129 +0,0 @@
|
||||
diff -uNr a/bundled/gcp/google-cloud-sdk/lib/third_party/oauth2client/_pure_python_crypt.py b/bundled/gcp/google-cloud-sdk/lib/third_party/oauth2client/_pure_python_crypt.py
|
||||
--- a/bundled/gcp/google-cloud-sdk/lib/third_party/oauth2client/_pure_python_crypt.py 1980-01-01 09:00:00.000000000 +0100
|
||||
+++ b/bundled/gcp/google-cloud-sdk/lib/third_party/oauth2client/_pure_python_crypt.py 2019-04-04 11:56:00.292677044 +0200
|
||||
@@ -19,8 +19,14 @@
|
||||
certificates.
|
||||
"""
|
||||
|
||||
+from pyasn1.codec.der import decoder
|
||||
from pyasn1_modules import pem
|
||||
-import rsa
|
||||
+from pyasn1_modules.rfc2459 import Certificate
|
||||
+from pyasn1_modules.rfc5208 import PrivateKeyInfo
|
||||
+from cryptography.hazmat.primitives import serialization, hashes
|
||||
+from cryptography.hazmat.primitives.asymmetric import padding
|
||||
+from cryptography import x509
|
||||
+from cryptography.hazmat.backends import default_backend
|
||||
import six
|
||||
|
||||
from oauth2client import _helpers
|
||||
@@ -40,7 +46,7 @@
|
||||
'-----END RSA PRIVATE KEY-----')
|
||||
_PKCS8_MARKER = ('-----BEGIN PRIVATE KEY-----',
|
||||
'-----END PRIVATE KEY-----')
|
||||
-_PKCS8_SPEC = None
|
||||
+_PKCS8_SPEC = PrivateKeyInfo()
|
||||
|
||||
|
||||
def _bit_list_to_bytes(bit_list):
|
||||
@@ -67,7 +73,8 @@
|
||||
"""
|
||||
|
||||
def __init__(self, pubkey):
|
||||
- self._pubkey = pubkey
|
||||
+ self._pubkey = serialization.load_pem_public_key(pubkey,
|
||||
+ backend=default_backend())
|
||||
|
||||
def verify(self, message, signature):
|
||||
"""Verifies a message against a signature.
|
||||
@@ -84,8 +91,9 @@
|
||||
"""
|
||||
message = _helpers._to_bytes(message, encoding='utf-8')
|
||||
try:
|
||||
- return rsa.pkcs1.verify(message, signature, self._pubkey)
|
||||
- except (ValueError, rsa.pkcs1.VerificationError):
|
||||
+ return self._pubkey.verify(signature, message, padding.PKCS1v15(),
|
||||
+ hashes.SHA256())
|
||||
+ except (ValueError, TypeError, InvalidSignature):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
@@ -109,19 +117,18 @@
|
||||
"""
|
||||
key_pem = _helpers._to_bytes(key_pem)
|
||||
if is_x509_cert:
|
||||
- from pyasn1.codec.der import decoder
|
||||
- from pyasn1_modules import rfc2459
|
||||
-
|
||||
- der = rsa.pem.load_pem(key_pem, 'CERTIFICATE')
|
||||
- asn1_cert, remaining = decoder.decode(der, asn1Spec=rfc2459.Certificate())
|
||||
+ der = x509.load_pem_x509_certificate(pem_data, default_backend())
|
||||
+ asn1_cert, remaining = decoder.decode(der, asn1Spec=Certificate())
|
||||
if remaining != b'':
|
||||
raise ValueError('Unused bytes', remaining)
|
||||
|
||||
cert_info = asn1_cert['tbsCertificate']['subjectPublicKeyInfo']
|
||||
key_bytes = _bit_list_to_bytes(cert_info['subjectPublicKey'])
|
||||
- pubkey = rsa.PublicKey.load_pkcs1(key_bytes, 'DER')
|
||||
+ pubkey = serialization.load_der_public_key(decoded_key,
|
||||
+ backend=default_backend())
|
||||
else:
|
||||
- pubkey = rsa.PublicKey.load_pkcs1(key_pem, 'PEM')
|
||||
+ pubkey = serialization.load_pem_public_key(decoded_key,
|
||||
+ backend=default_backend())
|
||||
return cls(pubkey)
|
||||
|
||||
|
||||
@@ -134,6 +141,8 @@
|
||||
|
||||
def __init__(self, pkey):
|
||||
self._key = pkey
|
||||
+ self._pubkey = serialization.load_pem_private_key(pkey,
|
||||
+ backend=default_backend())
|
||||
|
||||
def sign(self, message):
|
||||
"""Signs a message.
|
||||
@@ -145,7 +154,7 @@
|
||||
string, The signature of the message for the given key.
|
||||
"""
|
||||
message = _helpers._to_bytes(message, encoding='utf-8')
|
||||
- return rsa.pkcs1.sign(message, self._key, 'SHA-256')
|
||||
+ return self._key.sign(message, padding.PKCS1v15(), hashes.SHA256())
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, key, password='notasecret'):
|
||||
@@ -163,27 +172,24 @@
|
||||
ValueError if the key cannot be parsed as PKCS#1 or PKCS#8 in
|
||||
PEM format.
|
||||
"""
|
||||
- global _PKCS8_SPEC
|
||||
key = _helpers._from_bytes(key) # pem expects str in Py3
|
||||
marker_id, key_bytes = pem.readPemBlocksFromFile(
|
||||
six.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER)
|
||||
|
||||
if marker_id == 0:
|
||||
- pkey = rsa.key.PrivateKey.load_pkcs1(key_bytes,
|
||||
- format='DER')
|
||||
- elif marker_id == 1:
|
||||
- from pyasn1.codec.der import decoder
|
||||
- from pyasn1_modules import rfc5208
|
||||
+ pkey = serialization.load_der_private_key(
|
||||
+ key_bytes, password=None,
|
||||
+ backend=default_backend())
|
||||
|
||||
- if _PKCS8_SPEC is None:
|
||||
- _PKCS8_SPEC = rfc5208.PrivateKeyInfo()
|
||||
+ elif marker_id == 1:
|
||||
key_info, remaining = decoder.decode(
|
||||
key_bytes, asn1Spec=_PKCS8_SPEC)
|
||||
if remaining != b'':
|
||||
raise ValueError('Unused bytes', remaining)
|
||||
pkey_info = key_info.getComponentByName('privateKey')
|
||||
- pkey = rsa.key.PrivateKey.load_pkcs1(pkey_info.asOctets(),
|
||||
- format='DER')
|
||||
+ pkey = serialization.load_der_private_key(
|
||||
+ pkey_info.asOctets(), password=None,
|
||||
+ backend=default_backend())
|
||||
else:
|
||||
raise ValueError('No key could be detected.')
|
||||
|
@ -1,47 +0,0 @@
|
||||
From 57acb7c26d809cf864ec439b8bcd6364702022d5 Mon Sep 17 00:00:00 2001
|
||||
From: Nate Prewitt <nate.prewitt@gmail.com>
|
||||
Date: Wed, 25 Sep 2024 08:03:20 -0700
|
||||
Subject: [PATCH] Only use hostname to do netrc lookup instead of netloc
|
||||
|
||||
---
|
||||
src/requests/utils.py | 8 +-------
|
||||
1 file changed, 1 insertion(+), 7 deletions(-)
|
||||
|
||||
diff --git a/aliyun/aliyunsdkcore/vendored/requests/utils.py b/aliyun/aliyunsdkcore/vendored/requests/utils.py
|
||||
index 699683e5d9..8a307ca8a0 100644
|
||||
--- a/aliyun/aliyunsdkcore/vendored/requests/utils.py
|
||||
+++ b/aliyun/aliyunsdkcore/vendored/requests/utils.py
|
||||
@@ -182,13 +182,7 @@
|
||||
return
|
||||
|
||||
ri = urlparse(url)
|
||||
-
|
||||
- # Strip port numbers from netloc. This weird `if...encode`` dance is
|
||||
- # used for Python 3.2, which doesn't support unicode literals.
|
||||
- splitstr = b':'
|
||||
- if isinstance(url, str):
|
||||
- splitstr = splitstr.decode('ascii')
|
||||
- host = ri.netloc.split(splitstr)[0]
|
||||
+ host = ri.hostname
|
||||
|
||||
try:
|
||||
_netrc = netrc(netrc_path).authenticators(host)
|
||||
diff --git a/gcp/google-cloud-sdk/lib/third_party/requests/utils.py b/gcp/google-cloud-sdk/lib/third_party/requests/utils.py
|
||||
index 699683e5d9..8a307ca8a0 100644
|
||||
--- a/gcp/google-cloud-sdk/lib/third_party/requests/utils.py
|
||||
+++ b/gcp/google-cloud-sdk/lib/third_party/requests/utils.py
|
||||
@@ -236,13 +236,7 @@ def get_netrc_auth(url, raise_errors=False):
|
||||
return
|
||||
|
||||
ri = urlparse(url)
|
||||
-
|
||||
- # Strip port numbers from netloc. This weird `if...encode`` dance is
|
||||
- # used for Python 3.2, which doesn't support unicode literals.
|
||||
- splitstr = b':'
|
||||
- if isinstance(url, str):
|
||||
- splitstr = splitstr.decode('ascii')
|
||||
- host = ri.netloc.split(splitstr)[0]
|
||||
+ host = ri.hostname
|
||||
|
||||
try:
|
||||
_netrc = netrc(netrc_path).authenticators(host)
|
@ -1,75 +0,0 @@
|
||||
From b806487ca758fce838c988767556007ecf66a6e3 Mon Sep 17 00:00:00 2001
|
||||
From: Roger Zhou <zzhou@suse.com>
|
||||
Date: Mon, 10 Apr 2023 18:08:56 +0800
|
||||
Subject: [PATCH] exportfs: make the "fsid=" parameter optional
|
||||
|
||||
Based on feedback [1] from the kernel developer @neilbrown regarding the
|
||||
NFS clustering use case, it has been determined that the fsid= parameter
|
||||
is now considered optional and safe to omit.
|
||||
|
||||
[1] https://bugzilla.suse.com/show_bug.cgi?id=1201271#c49
|
||||
"""
|
||||
Since some time in 2007 NFS has used the UUID of a filesystem as the
|
||||
primary identifier for that filesystem, rather than using the device
|
||||
number. So from that time there should have been reduced need for the
|
||||
"fsid=" option. Probably there are some filesystems that this didn't
|
||||
work for. btrfs has been problematic at time, particularly when subvols
|
||||
are exported. But for quite some years this has all "just worked" at
|
||||
least for the major filesystems (ext4 xfs btrfs). [...] I would suggest
|
||||
getting rid of the use of fsid= altogether. [...] I'm confident that it
|
||||
was no longer an issue in SLE-12 and similarly not in SLE-15.
|
||||
"""
|
||||
---
|
||||
heartbeat/exportfs | 12 +++++++-----
|
||||
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/exportfs b/heartbeat/exportfs
|
||||
index 2307a9e67b..435a19646b 100755
|
||||
--- a/heartbeat/exportfs
|
||||
+++ b/heartbeat/exportfs
|
||||
@@ -82,7 +82,7 @@ The directory or directories to export.
|
||||
<content type="string" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="fsid" unique="0" required="1">
|
||||
+<parameter name="fsid" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
The fsid option to pass to exportfs. This can be a unique positive
|
||||
integer, a UUID (assuredly sans comma characters), or the special string
|
||||
@@ -185,6 +185,8 @@ exportfs_methods() {
|
||||
|
||||
reset_fsid() {
|
||||
CURRENT_FSID=$OCF_RESKEY_fsid
|
||||
+ [ -z "$CURRENT_FSID" ] && CURRENT_FSID=`echo "$OCF_RESKEY_options" | sed -n 's/.*fsid=\([^,]*\).*/\1/p'`
|
||||
+ echo $CURRENT_FSID
|
||||
}
|
||||
bump_fsid() {
|
||||
CURRENT_FSID=$((CURRENT_FSID+1))
|
||||
@@ -322,7 +324,7 @@ export_one() {
|
||||
if echo "$opts" | grep fsid >/dev/null; then
|
||||
#replace fsid in options list
|
||||
opts=`echo "$opts" | sed "s,fsid=[^,]*,fsid=$(get_fsid),g"`
|
||||
- else
|
||||
+ elif [ -n "$OCF_RESKEY_fsid" ]; then
|
||||
#tack the fsid option onto our options list.
|
||||
opts="${opts}${sep}fsid=$(get_fsid)"
|
||||
fi
|
||||
@@ -448,8 +450,8 @@ exportfs_validate_all ()
|
||||
ocf_exit_reason "$OCF_RESKEY_fsid cannot contain a comma"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
- if [ $NUMDIRS -gt 1 ] &&
|
||||
- ! ocf_is_decimal "$OCF_RESKEY_fsid"; then
|
||||
+ if [ $NUMDIRS -gt 1 ] && [ -n "$(reset_fsid)" ] &&
|
||||
+ ! ocf_is_decimal "$(reset_fsid)"; then
|
||||
ocf_exit_reason "use integer fsid when exporting multiple directories"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -485,6 +487,6 @@ done
|
||||
OCF_RESKEY_directory="${directories%% }"
|
||||
|
||||
NUMDIRS=`echo "$OCF_RESKEY_directory" | wc -w`
|
||||
-OCF_REQUIRED_PARAMS="directory fsid clientspec"
|
||||
+OCF_REQUIRED_PARAMS="directory clientspec"
|
||||
OCF_REQUIRED_BINARIES="exportfs"
|
||||
ocf_rarun $*
|
@ -1,43 +0,0 @@
|
||||
From 1d1481aa6d848efab4d398ad6e74d80b5b32549f Mon Sep 17 00:00:00 2001
|
||||
From: Valentin Vidic <vvidic@debian.org>
|
||||
Date: Wed, 1 Nov 2023 18:25:45 +0100
|
||||
Subject: [PATCH] exportfs: remove test for "fsid=" parameter
|
||||
|
||||
fsid parameter is now considered optional.
|
||||
---
|
||||
tools/ocft/exportfs | 5 -----
|
||||
tools/ocft/exportfs-multidir | 5 -----
|
||||
2 files changed, 10 deletions(-)
|
||||
|
||||
diff --git a/tools/ocft/exportfs b/tools/ocft/exportfs
|
||||
index 285a4b8ea0..1ec3d4c364 100644
|
||||
--- a/tools/ocft/exportfs
|
||||
+++ b/tools/ocft/exportfs
|
||||
@@ -28,11 +28,6 @@ CASE "check base env"
|
||||
Include prepare
|
||||
AgentRun start OCF_SUCCESS
|
||||
|
||||
-CASE "check base env: no 'OCF_RESKEY_fsid'"
|
||||
- Include prepare
|
||||
- Env OCF_RESKEY_fsid=
|
||||
- AgentRun start OCF_ERR_CONFIGURED
|
||||
-
|
||||
CASE "check base env: invalid 'OCF_RESKEY_directory'"
|
||||
Include prepare
|
||||
Env OCF_RESKEY_directory=/no_such
|
||||
diff --git a/tools/ocft/exportfs-multidir b/tools/ocft/exportfs-multidir
|
||||
index 00e41f0859..ac6d5c7f6a 100644
|
||||
--- a/tools/ocft/exportfs-multidir
|
||||
+++ b/tools/ocft/exportfs-multidir
|
||||
@@ -28,11 +28,6 @@ CASE "check base env"
|
||||
Include prepare
|
||||
AgentRun start OCF_SUCCESS
|
||||
|
||||
-CASE "check base env: no 'OCF_RESKEY_fsid'"
|
||||
- Include prepare
|
||||
- Env OCF_RESKEY_fsid=
|
||||
- AgentRun start OCF_ERR_CONFIGURED
|
||||
-
|
||||
CASE "check base env: invalid 'OCF_RESKEY_directory'"
|
||||
Include prepare
|
||||
Env OCF_RESKEY_directory=/no_such
|
@ -1,45 +0,0 @@
|
||||
From e4f84ae185b6943d1ff461d53c7f1b5295783086 Mon Sep 17 00:00:00 2001
|
||||
From: Valentin Vidic <vvidic@valentin-vidic.from.hr>
|
||||
Date: Wed, 1 Nov 2023 19:35:21 +0100
|
||||
Subject: [PATCH] findif.sh: fix loopback handling
|
||||
|
||||
tools/ocft/IPaddr2 fails the loopback test because of the missing
|
||||
table local parameter:
|
||||
|
||||
$ ip -o -f inet route list match 127.0.0.3 scope host
|
||||
|
||||
$ ip -o -f inet route list match 127.0.0.3 table local scope host
|
||||
local 127.0.0.0/8 dev lo proto kernel src 127.0.0.1
|
||||
|
||||
Also rename the function because it is called only in for the special
|
||||
loopback address case.
|
||||
---
|
||||
heartbeat/findif.sh | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/findif.sh b/heartbeat/findif.sh
|
||||
index 5f1c19ec3..7c766e6e0 100644
|
||||
--- a/heartbeat/findif.sh
|
||||
+++ b/heartbeat/findif.sh
|
||||
@@ -29,10 +29,10 @@ prefixcheck() {
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
-getnetworkinfo()
|
||||
+getloopbackinfo()
|
||||
{
|
||||
local line netinfo
|
||||
- ip -o -f inet route list match $OCF_RESKEY_ip table "${OCF_RESKEY_table:=main}" scope host | (while read line;
|
||||
+ ip -o -f inet route list match $OCF_RESKEY_ip table local scope host | (while read line;
|
||||
do
|
||||
netinfo=`echo $line | awk '{print $2}'`
|
||||
case $netinfo in
|
||||
@@ -222,7 +222,7 @@ findif()
|
||||
if [ $# = 0 ] ; then
|
||||
case $OCF_RESKEY_ip in
|
||||
127.*)
|
||||
- set -- `getnetworkinfo`
|
||||
+ set -- `getloopbackinfo`
|
||||
shift;;
|
||||
esac
|
||||
fi
|
@ -1,20 +0,0 @@
|
||||
--- a/heartbeat/findif.sh 2024-02-08 11:31:53.414257686 +0100
|
||||
+++ b/heartbeat/findif.sh 2023-11-02 10:20:12.150853167 +0100
|
||||
@@ -210,14 +210,14 @@
|
||||
fi
|
||||
findif_check_params $family || return $?
|
||||
|
||||
- if [ -n "$netmask" ] ; then
|
||||
+ if [ -n "$netmask" ]; then
|
||||
match=$match/$netmask
|
||||
fi
|
||||
if [ -n "$nic" ] ; then
|
||||
# NIC supports more than two.
|
||||
- set -- $(ip -o -f $family route list match $match $scope table "${OCF_RESKEY_table:=main}" | grep "dev $nic " | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
+ set -- $(ip -o -f $family route list match $match $scope | grep "dev $nic " | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
else
|
||||
- set -- $(ip -o -f $family route list match $match $scope table "${OCF_RESKEY_table:=main}" | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
+ set -- $(ip -o -f $family route list match $match $scope | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
fi
|
||||
if [ $# = 0 ] ; then
|
||||
case $OCF_RESKEY_ip in
|
@ -1,555 +0,0 @@
|
||||
From f45f76600a7e02c860566db7d1350dc3b09449c2 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 6 Nov 2023 15:49:44 +0100
|
||||
Subject: [PATCH] aws-vpc-move-ip/aws-vpc-route53/awseip/awsvip: add auth_type
|
||||
parameter and AWS Policy based authentication type
|
||||
|
||||
---
|
||||
heartbeat/aws-vpc-move-ip | 43 +++++++++++++++++++----
|
||||
heartbeat/aws-vpc-route53.in | 47 ++++++++++++++++++++-----
|
||||
heartbeat/awseip | 68 +++++++++++++++++++++++++++---------
|
||||
heartbeat/awsvip | 60 ++++++++++++++++++++++++-------
|
||||
4 files changed, 173 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip
|
||||
index dee040300f..54806f6eaa 100755
|
||||
--- a/heartbeat/aws-vpc-move-ip
|
||||
+++ b/heartbeat/aws-vpc-move-ip
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
# Defaults
|
||||
OCF_RESKEY_awscli_default="/usr/bin/aws"
|
||||
+OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_ip_default=""
|
||||
@@ -48,6 +49,7 @@ OCF_RESKEY_monapi_default="false"
|
||||
OCF_RESKEY_lookup_type_default="InstanceId"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
+: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
|
||||
@@ -58,8 +60,6 @@ OCF_RESKEY_lookup_type_default="InstanceId"
|
||||
: ${OCF_RESKEY_iflabel=${OCF_RESKEY_iflabel_default}}
|
||||
: ${OCF_RESKEY_monapi=${OCF_RESKEY_monapi_default}}
|
||||
: ${OCF_RESKEY_lookup_type=${OCF_RESKEY_lookup_type_default}}
|
||||
-
|
||||
-[ -n "$OCF_RESKEY_region" ] && region_opt="--region $OCF_RESKEY_region"
|
||||
#######################################################################
|
||||
|
||||
|
||||
@@ -83,6 +83,10 @@ cat <<END
|
||||
<longdesc lang="en">
|
||||
Resource Agent to move IP addresses within a VPC of the Amazon Webservices EC2
|
||||
by changing an entry in an specific routing table
|
||||
+
|
||||
+Credentials needs to be setup by running "aws configure", or by using AWS Policies.
|
||||
+
|
||||
+See https://aws.amazon.com/cli/ for more information about awscli.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Move IP within a VPC of the AWS EC2</shortdesc>
|
||||
|
||||
@@ -95,6 +99,15 @@ Path to command line tools for AWS
|
||||
<content type="string" default="${OCF_RESKEY_awscli_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="auth_type">
|
||||
+<longdesc lang="en">
|
||||
+Authentication type "key" for AccessKey and SecretAccessKey set via "aws configure",
|
||||
+or "role" to use AWS Policies.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authentication type</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_auth_type_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="profile">
|
||||
<longdesc lang="en">
|
||||
Valid AWS CLI profile name (see ~/.aws/config and 'aws configure')
|
||||
@@ -198,7 +211,7 @@ END
|
||||
execute_cmd_as_role(){
|
||||
cmd=$1
|
||||
role=$2
|
||||
- output="$($OCF_RESKEY_awscli sts assume-role --role-arn $role --role-session-name AWSCLI-RouteTableUpdate --profile $OCF_RESKEY_profile $region_opt --output=text)"
|
||||
+ output="$($AWSCLI_CMD sts assume-role --role-arn $role --role-session-name AWSCLI-RouteTableUpdate --output=text)"
|
||||
export AWS_ACCESS_KEY_ID="$(echo $output | awk -F" " '$4=="CREDENTIALS" {print $5}')"
|
||||
export AWS_SECRET_ACCESS_KEY="$(echo $output | awk -F" " '$4=="CREDENTIALS" {print $7}')"
|
||||
export AWS_SESSION_TOKEN="$(echo $output | awk -F" " '$4=="CREDENTIALS" {print $8}')"
|
||||
@@ -220,11 +233,11 @@ ec2ip_set_address_param_compat(){
|
||||
}
|
||||
|
||||
ec2ip_validate() {
|
||||
- for cmd in $OCF_RESKEY_awscli ip curl; do
|
||||
+ for cmd in "$OCF_RESKEY_awscli" ip curl; do
|
||||
check_binary "$cmd"
|
||||
done
|
||||
|
||||
- if [ -z "$OCF_RESKEY_profile" ]; then
|
||||
+ if [ "x${OCF_RESKEY_auth_type}" = "xkey" ] && [ -z "$OCF_RESKEY_profile" ]; then
|
||||
ocf_exit_reason "profile parameter not set"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -262,7 +275,7 @@ ec2ip_monitor() {
|
||||
for rtb in $(echo $OCF_RESKEY_routing_table | sed -e 's/,/ /g'); do
|
||||
ocf_log info "monitor: check routing table (API call) - $rtb"
|
||||
if [ -z "${OCF_RESKEY_routing_table_role}" ]; then
|
||||
- cmd="$OCF_RESKEY_awscli --profile $OCF_RESKEY_profile $region_opt --output text ec2 describe-route-tables --route-table-ids $rtb --query RouteTables[*].Routes[?DestinationCidrBlock=='$OCF_RESKEY_ip/32'].$OCF_RESKEY_lookup_type"
|
||||
+ cmd="$AWSCLI_CMD --output text ec2 describe-route-tables --route-table-ids $rtb --query RouteTables[*].Routes[?DestinationCidrBlock=='$OCF_RESKEY_ip/32'].$OCF_RESKEY_lookup_type"
|
||||
ocf_log debug "executing command: $cmd"
|
||||
ROUTE_TO_INSTANCE="$($cmd)"
|
||||
else
|
||||
@@ -368,7 +381,7 @@ ec2ip_get_and_configure() {
|
||||
EC2_NETWORK_INTERFACE_ID="$(ec2ip_get_instance_eni)"
|
||||
for rtb in $(echo $OCF_RESKEY_routing_table | sed -e 's/,/ /g'); do
|
||||
if [ -z "${OCF_RESKEY_routing_table_role}" ]; then
|
||||
- cmd="$OCF_RESKEY_awscli --profile $OCF_RESKEY_profile $region_opt --output text ec2 replace-route --route-table-id $rtb --destination-cidr-block ${OCF_RESKEY_ip}/32 --network-interface-id $EC2_NETWORK_INTERFACE_ID"
|
||||
+ cmd="$AWSCLI_CMD --output text ec2 replace-route --route-table-id $rtb --destination-cidr-block ${OCF_RESKEY_ip}/32 --network-interface-id $EC2_NETWORK_INTERFACE_ID"
|
||||
ocf_log debug "executing command: $cmd"
|
||||
$cmd
|
||||
else
|
||||
@@ -475,6 +488,22 @@ if ! ocf_is_root; then
|
||||
exit $OCF_ERR_PERM
|
||||
fi
|
||||
|
||||
+AWSCLI_CMD="${OCF_RESKEY_awscli}"
|
||||
+if [ "x${OCF_RESKEY_auth_type}" = "xkey" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --profile ${OCF_RESKEY_profile}"
|
||||
+elif [ "x${OCF_RESKEY_auth_type}" = "xrole" ]; then
|
||||
+ if [ -z "${OCF_RESKEY_region}" ]; then
|
||||
+ ocf_exit_reason "region needs to be set when using role-based authentication"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+else
|
||||
+ ocf_exit_reason "Incorrect auth_type: ${OCF_RESKEY_auth_type}"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+fi
|
||||
+if [ -n "${OCF_RESKEY_region}" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --region ${OCF_RESKEY_region}"
|
||||
+fi
|
||||
+
|
||||
ec2ip_set_address_param_compat
|
||||
|
||||
ec2ip_validate
|
||||
diff --git a/heartbeat/aws-vpc-route53.in b/heartbeat/aws-vpc-route53.in
|
||||
index 22cbb35833..18ab157e8a 100644
|
||||
--- a/heartbeat/aws-vpc-route53.in
|
||||
+++ b/heartbeat/aws-vpc-route53.in
|
||||
@@ -46,24 +46,22 @@
|
||||
|
||||
# Defaults
|
||||
OCF_RESKEY_awscli_default="/usr/bin/aws"
|
||||
+OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
+OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_hostedzoneid_default=""
|
||||
OCF_RESKEY_fullname_default=""
|
||||
OCF_RESKEY_ip_default="local"
|
||||
OCF_RESKEY_ttl_default=10
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
+: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
+: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_hostedzoneid:=${OCF_RESKEY_hostedzoneid_default}}
|
||||
: ${OCF_RESKEY_fullname:=${OCF_RESKEY_fullname_default}}
|
||||
: ${OCF_RESKEY_ip:=${OCF_RESKEY_ip_default}}
|
||||
: ${OCF_RESKEY_ttl:=${OCF_RESKEY_ttl_default}}
|
||||
-#######################################################################
|
||||
-
|
||||
-
|
||||
-AWS_PROFILE_OPT="--profile $OCF_RESKEY_profile --cli-connect-timeout 10"
|
||||
-#######################################################################
|
||||
-
|
||||
|
||||
usage() {
|
||||
cat <<-EOT
|
||||
@@ -123,6 +121,15 @@ Path to command line tools for AWS
|
||||
<content type="string" default="${OCF_RESKEY_awscli_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="auth_type">
|
||||
+<longdesc lang="en">
|
||||
+Authentication type "key" for AccessKey and SecretAccessKey set via "aws configure",
|
||||
+or "role" to use AWS Policies.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authentication type</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_auth_type_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="profile">
|
||||
<longdesc lang="en">
|
||||
The name of the AWS CLI profile of the root account. This
|
||||
@@ -196,7 +203,7 @@ r53_validate() {
|
||||
|
||||
# Check for required binaries
|
||||
ocf_log debug "Checking for required binaries"
|
||||
- for command in curl dig; do
|
||||
+ for command in "${OCF_RESKEY_awscli}" curl dig; do
|
||||
check_binary "$command"
|
||||
done
|
||||
|
||||
@@ -216,7 +223,10 @@ r53_validate() {
|
||||
esac
|
||||
|
||||
# profile
|
||||
- [[ -z "$OCF_RESKEY_profile" ]] && ocf_log error "AWS CLI profile not set $OCF_RESKEY_profile!" && exit $OCF_ERR_CONFIGURED
|
||||
+ if [ "x${OCF_RESKEY_auth_type}" = "xkey" ] && [ -z "$OCF_RESKEY_profile" ]; then
|
||||
+ ocf_exit_reason "profile parameter not set"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
|
||||
# TTL
|
||||
[[ -z "$OCF_RESKEY_ttl" ]] && ocf_log error "TTL not set $OCF_RESKEY_ttl!" && exit $OCF_ERR_CONFIGURED
|
||||
@@ -417,7 +427,6 @@ _update_record() {
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
-
|
||||
case $__OCF_ACTION in
|
||||
usage|help)
|
||||
usage
|
||||
@@ -427,6 +436,26 @@ case $__OCF_ACTION in
|
||||
metadata
|
||||
exit $OCF_SUCCESS
|
||||
;;
|
||||
+esac
|
||||
+
|
||||
+AWSCLI_CMD="${OCF_RESKEY_awscli}"
|
||||
+if [ "x${OCF_RESKEY_auth_type}" = "xkey" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --profile ${OCF_RESKEY_profile}"
|
||||
+elif [ "x${OCF_RESKEY_auth_type}" = "xrole" ]; then
|
||||
+ if [ -z "${OCF_RESKEY_region}" ]; then
|
||||
+ ocf_exit_reason "region needs to be set when using role-based authentication"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+else
|
||||
+ ocf_exit_reason "Incorrect auth_type: ${OCF_RESKEY_auth_type}"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+fi
|
||||
+if [ -n "${OCF_RESKEY_region}" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --region ${OCF_RESKEY_region}"
|
||||
+fi
|
||||
+AWSCLI_CMD="$AWSCLI_CMD --cli-connect-timeout 10"
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
start)
|
||||
r53_validate || exit $?
|
||||
r53_start
|
||||
diff --git a/heartbeat/awseip b/heartbeat/awseip
|
||||
index dc48460c85..49b0ca6155 100755
|
||||
--- a/heartbeat/awseip
|
||||
+++ b/heartbeat/awseip
|
||||
@@ -23,7 +23,8 @@
|
||||
#
|
||||
# Prerequisites:
|
||||
#
|
||||
-# - preconfigured AWS CLI running environment (AccessKey, SecretAccessKey, etc.)
|
||||
+# - preconfigured AWS CLI running environment (AccessKey, SecretAccessKey, etc.) or
|
||||
+# (AWSRole) Setup up relevant AWS Policies to allow agent related functions to be executed.
|
||||
# - a reserved secondary private IP address for EC2 instances high availability
|
||||
# - IAM user role with the following permissions:
|
||||
# * DescribeInstances
|
||||
@@ -44,11 +45,15 @@
|
||||
# Defaults
|
||||
#
|
||||
OCF_RESKEY_awscli_default="/usr/bin/aws"
|
||||
+OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
+OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_api_delay_default="3"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
+: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
+: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}}
|
||||
|
||||
meta_data() {
|
||||
@@ -63,7 +68,7 @@ Resource Agent for Amazon AWS Elastic IP Addresses.
|
||||
|
||||
It manages AWS Elastic IP Addresses with awscli.
|
||||
|
||||
-Credentials needs to be setup by running "aws configure".
|
||||
+Credentials needs to be setup by running "aws configure", or by using AWS Policies.
|
||||
|
||||
See https://aws.amazon.com/cli/ for more information about awscli.
|
||||
</longdesc>
|
||||
@@ -79,6 +84,15 @@ command line tools for aws services
|
||||
<content type="string" default="${OCF_RESKEY_awscli_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="auth_type">
|
||||
+<longdesc lang="en">
|
||||
+Authentication type "key" for AccessKey and SecretAccessKey set via "aws configure",
|
||||
+or "role" to use AWS Policies.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authentication type</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_auth_type_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="profile">
|
||||
<longdesc lang="en">
|
||||
Valid AWS CLI profile name (see ~/.aws/config and 'aws configure')
|
||||
@@ -111,6 +125,14 @@ predefined private ip address for ec2 instance
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="region" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Region for AWS resource (required for role-based authentication)
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Region</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_region_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="api_delay" unique="0">
|
||||
<longdesc lang="en">
|
||||
a short delay between API calls, to avoid sending API too quick
|
||||
@@ -157,13 +179,13 @@ awseip_start() {
|
||||
NETWORK_ID=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/interface-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
fi
|
||||
done
|
||||
- $AWSCLI --profile $OCF_RESKEY_profile ec2 associate-address \
|
||||
+ $AWSCLI_CMD ec2 associate-address \
|
||||
--network-interface-id ${NETWORK_ID} \
|
||||
--allocation-id ${ALLOCATION_ID} \
|
||||
--private-ip-address ${PRIVATE_IP_ADDRESS}
|
||||
RET=$?
|
||||
else
|
||||
- $AWSCLI --profile $OCF_RESKEY_profile ec2 associate-address \
|
||||
+ $AWSCLI_CMD ec2 associate-address \
|
||||
--instance-id ${INSTANCE_ID} \
|
||||
--allocation-id ${ALLOCATION_ID}
|
||||
RET=$?
|
||||
@@ -183,7 +205,7 @@ awseip_start() {
|
||||
awseip_stop() {
|
||||
awseip_monitor || return $OCF_SUCCESS
|
||||
|
||||
- ASSOCIATION_ID=$($AWSCLI --profile $OCF_RESKEY_profile --output json ec2 describe-addresses \
|
||||
+ ASSOCIATION_ID=$($AWSCLI_CMD --output json ec2 describe-addresses \
|
||||
--allocation-id ${ALLOCATION_ID} | grep -m 1 "AssociationId" | awk -F'"' '{print$4}')
|
||||
|
||||
if [ -z "${ASSOCIATION_ID}" ]; then
|
||||
@@ -191,9 +213,7 @@ awseip_stop() {
|
||||
return $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
- $AWSCLI --profile ${OCF_RESKEY_profile} \
|
||||
- ec2 disassociate-address \
|
||||
- --association-id ${ASSOCIATION_ID}
|
||||
+ $AWSCLI_CMD ec2 disassociate-address --association-id ${ASSOCIATION_ID}
|
||||
RET=$?
|
||||
|
||||
# delay to avoid sending request too fast
|
||||
@@ -208,7 +228,7 @@ awseip_stop() {
|
||||
}
|
||||
|
||||
awseip_monitor() {
|
||||
- $AWSCLI --profile $OCF_RESKEY_profile ec2 describe-instances --instance-id "${INSTANCE_ID}" | grep -q "${ELASTIC_IP}"
|
||||
+ $AWSCLI_CMD ec2 describe-instances --instance-id "${INSTANCE_ID}" | grep -q "${ELASTIC_IP}"
|
||||
RET=$?
|
||||
|
||||
if [ $RET -ne 0 ]; then
|
||||
@@ -218,9 +238,9 @@ awseip_monitor() {
|
||||
}
|
||||
|
||||
awseip_validate() {
|
||||
- check_binary ${AWSCLI}
|
||||
+ check_binary "${OCF_RESKEY_awscli}"
|
||||
|
||||
- if [ -z "$OCF_RESKEY_profile" ]; then
|
||||
+ if [ "x${OCF_RESKEY_auth_type}" = "xkey" ] && [ -z "$OCF_RESKEY_profile" ]; then
|
||||
ocf_exit_reason "profile parameter not set"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -238,9 +258,27 @@ case $__OCF_ACTION in
|
||||
meta_data
|
||||
exit $OCF_SUCCESS
|
||||
;;
|
||||
-esac
|
||||
+ usage|help)
|
||||
+ awseip_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+esac
|
||||
|
||||
-AWSCLI="${OCF_RESKEY_awscli}"
|
||||
+AWSCLI_CMD="${OCF_RESKEY_awscli}"
|
||||
+if [ "x${OCF_RESKEY_auth_type}" = "xkey" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --profile ${OCF_RESKEY_profile}"
|
||||
+elif [ "x${OCF_RESKEY_auth_type}" = "xrole" ]; then
|
||||
+ if [ -z "${OCF_RESKEY_region}" ]; then
|
||||
+ ocf_exit_reason "region needs to be set when using role-based authentication"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+else
|
||||
+ ocf_exit_reason "Incorrect auth_type: ${OCF_RESKEY_auth_type}"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+fi
|
||||
+if [ -n "${OCF_RESKEY_region}" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --region ${OCF_RESKEY_region}"
|
||||
+fi
|
||||
ELASTIC_IP="${OCF_RESKEY_elastic_ip}"
|
||||
ALLOCATION_ID="${OCF_RESKEY_allocation_id}"
|
||||
PRIVATE_IP_ADDRESS="${OCF_RESKEY_private_ip_address}"
|
||||
@@ -272,10 +310,6 @@ case $__OCF_ACTION in
|
||||
validate|validate-all)
|
||||
awseip_validate
|
||||
;;
|
||||
- usage|help)
|
||||
- awseip_usage
|
||||
- exit $OCF_SUCCESS
|
||||
- ;;
|
||||
*)
|
||||
awseip_usage
|
||||
exit $OCF_ERR_UNIMPLEMENTED
|
||||
diff --git a/heartbeat/awsvip b/heartbeat/awsvip
|
||||
index 037278e296..bdb4d68dd0 100755
|
||||
--- a/heartbeat/awsvip
|
||||
+++ b/heartbeat/awsvip
|
||||
@@ -23,7 +23,8 @@
|
||||
#
|
||||
# Prerequisites:
|
||||
#
|
||||
-# - preconfigured AWS CLI running environment (AccessKey, SecretAccessKey, etc.)
|
||||
+# - preconfigured AWS CLI running environment (AccessKey, SecretAccessKey, etc.) or
|
||||
+# (AWSRole) Setup up relevant AWS Policies to allow agent related functions to be executed.
|
||||
# - a reserved secondary private IP address for EC2 instances high availablity
|
||||
# - IAM user role with the following permissions:
|
||||
# * DescribeInstances
|
||||
@@ -43,11 +44,15 @@
|
||||
# Defaults
|
||||
#
|
||||
OCF_RESKEY_awscli_default="/usr/bin/aws"
|
||||
+OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
+OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_api_delay_default="3"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
+: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
+: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}}
|
||||
|
||||
meta_data() {
|
||||
@@ -62,7 +67,7 @@ Resource Agent for Amazon AWS Secondary Private IP Addresses.
|
||||
|
||||
It manages AWS Secondary Private IP Addresses with awscli.
|
||||
|
||||
-Credentials needs to be setup by running "aws configure".
|
||||
+Credentials needs to be setup by running "aws configure", or by using AWS Policies.
|
||||
|
||||
See https://aws.amazon.com/cli/ for more information about awscli.
|
||||
</longdesc>
|
||||
@@ -78,6 +83,15 @@ command line tools for aws services
|
||||
<content type="string" default="${OCF_RESKEY_awscli_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="auth_type">
|
||||
+<longdesc lang="en">
|
||||
+Authentication type "key" for AccessKey and SecretAccessKey set via "aws configure",
|
||||
+or "role" to use AWS Policies.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Authentication type</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_auth_type_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="profile">
|
||||
<longdesc lang="en">
|
||||
Valid AWS CLI profile name (see ~/.aws/config and 'aws configure')
|
||||
@@ -94,6 +108,14 @@ reserved secondary private ip for ec2 instance
|
||||
<content type="string" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="region" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Region for AWS resource (required for role-based authentication)
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Region</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_region_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="api_delay" unique="0">
|
||||
<longdesc lang="en">
|
||||
a short delay between API calls, to avoid sending API too quick
|
||||
@@ -131,7 +153,7 @@ END
|
||||
awsvip_start() {
|
||||
awsvip_monitor && return $OCF_SUCCESS
|
||||
|
||||
- $AWSCLI --profile $OCF_RESKEY_profile ec2 assign-private-ip-addresses \
|
||||
+ $AWSCLI_CMD ec2 assign-private-ip-addresses \
|
||||
--network-interface-id ${NETWORK_ID} \
|
||||
--private-ip-addresses ${SECONDARY_PRIVATE_IP} \
|
||||
--allow-reassignment
|
||||
@@ -151,7 +173,7 @@ awsvip_start() {
|
||||
awsvip_stop() {
|
||||
awsvip_monitor || return $OCF_SUCCESS
|
||||
|
||||
- $AWSCLI --profile $OCF_RESKEY_profile ec2 unassign-private-ip-addresses \
|
||||
+ $AWSCLI_CMD ec2 unassign-private-ip-addresses \
|
||||
--network-interface-id ${NETWORK_ID} \
|
||||
--private-ip-addresses ${SECONDARY_PRIVATE_IP}
|
||||
RET=$?
|
||||
@@ -168,7 +190,7 @@ awsvip_stop() {
|
||||
}
|
||||
|
||||
awsvip_monitor() {
|
||||
- $AWSCLI --profile ${OCF_RESKEY_profile} ec2 describe-instances \
|
||||
+ $AWSCLI_CMD ec2 describe-instances \
|
||||
--instance-id "${INSTANCE_ID}" \
|
||||
--query 'Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddresses[].PrivateIpAddress[]' \
|
||||
--output text | \
|
||||
@@ -182,9 +204,9 @@ awsvip_monitor() {
|
||||
}
|
||||
|
||||
awsvip_validate() {
|
||||
- check_binary ${AWSCLI}
|
||||
+ check_binary "${OCF_RESKEY_awscli}"
|
||||
|
||||
- if [ -z "$OCF_RESKEY_profile" ]; then
|
||||
+ if [ "x${OCF_RESKEY_auth_type}" = "xkey" ] && [ -z "$OCF_RESKEY_profile" ]; then
|
||||
ocf_exit_reason "profile parameter not set"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -202,9 +224,27 @@ case $__OCF_ACTION in
|
||||
meta_data
|
||||
exit $OCF_SUCCESS
|
||||
;;
|
||||
+ usage|help)
|
||||
+ awsvip_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
esac
|
||||
|
||||
-AWSCLI="${OCF_RESKEY_awscli}"
|
||||
+AWSCLI_CMD="${OCF_RESKEY_awscli}"
|
||||
+if [ "x${OCF_RESKEY_auth_type}" = "xkey" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --profile ${OCF_RESKEY_profile}"
|
||||
+elif [ "x${OCF_RESKEY_auth_type}" = "xrole" ]; then
|
||||
+ if [ -z "${OCF_RESKEY_region}" ]; then
|
||||
+ ocf_exit_reason "region needs to be set when using role-based authentication"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+else
|
||||
+ ocf_exit_reason "Incorrect auth_type: ${OCF_RESKEY_auth_type}"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+fi
|
||||
+if [ -n "${OCF_RESKEY_region}" ]; then
|
||||
+ AWSCLI_CMD="$AWSCLI_CMD --region ${OCF_RESKEY_region}"
|
||||
+fi
|
||||
SECONDARY_PRIVATE_IP="${OCF_RESKEY_secondary_private_ip}"
|
||||
TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
@@ -236,10 +276,6 @@ case $__OCF_ACTION in
|
||||
validate|validate-all)
|
||||
awsvip_validate
|
||||
;;
|
||||
- usage|help)
|
||||
- awsvip_usage
|
||||
- exit $OCF_SUCCESS
|
||||
- ;;
|
||||
*)
|
||||
awsvip_usage
|
||||
exit $OCF_ERR_UNIMPLEMENTED
|
@ -1,22 +0,0 @@
|
||||
From b23ba4eaefb500199c4845751f4c5545c81f42f1 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 20 Nov 2023 16:37:37 +0100
|
||||
Subject: [PATCH 2/2] findif: also check that netmaskbits != EOS
|
||||
|
||||
---
|
||||
tools/findif.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/findif.c b/tools/findif.c
|
||||
index a25395fec..ab108a3c4 100644
|
||||
--- a/tools/findif.c
|
||||
+++ b/tools/findif.c
|
||||
@@ -669,7 +669,7 @@ main(int argc, char ** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
- if (netmaskbits) {
|
||||
+ if (netmaskbits != NULL && *netmaskbits != EOS) {
|
||||
best_netmask = netmask;
|
||||
}else if (best_netmask == 0L) {
|
||||
/*
|
@ -1,23 +0,0 @@
|
||||
From a9c4aeb971e9f4963345d0e215b729def62dd27c Mon Sep 17 00:00:00 2001
|
||||
From: pepadelic <162310096+pepadelic@users.noreply.github.com>
|
||||
Date: Mon, 15 Apr 2024 13:52:54 +0200
|
||||
Subject: [PATCH] Update db2: fix OCF_SUCESS name in db2_notify
|
||||
|
||||
fix OCF_SUCESS to OCF_SUCCESS in db2_notify
|
||||
---
|
||||
heartbeat/db2 | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/db2 b/heartbeat/db2
|
||||
index 95447ab6cb..1cd66f15af 100755
|
||||
--- a/heartbeat/db2
|
||||
+++ b/heartbeat/db2
|
||||
@@ -848,7 +848,7 @@ db2_notify() {
|
||||
|
||||
# only interested in pre-start
|
||||
[ $OCF_RESKEY_CRM_meta_notify_type = pre \
|
||||
- -a $OCF_RESKEY_CRM_meta_notify_operation = start ] || return $OCF_SUCESS
|
||||
+ -a $OCF_RESKEY_CRM_meta_notify_operation = start ] || return $OCF_SUCCESS
|
||||
|
||||
# gets FIRST_ACTIVE_LOG
|
||||
db2_get_cfg $dblist || return $?
|
@ -1,343 +0,0 @@
|
||||
From fc0657b936f6a58f741e33f851b22f82bc68bffa Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 6 Feb 2024 13:28:12 +0100
|
||||
Subject: [PATCH 1/2] ocf-shellfuncs: add curl_retry()
|
||||
|
||||
---
|
||||
heartbeat/ocf-shellfuncs.in | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index c5edb6f57..a69a9743d 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -672,6 +672,40 @@ EOF
|
||||
systemctl daemon-reload
|
||||
}
|
||||
|
||||
+# usage: curl_retry RETRIES SLEEP ARGS URL
|
||||
+#
|
||||
+# Use --show-error in ARGS to log HTTP error code
|
||||
+#
|
||||
+# returns:
|
||||
+# 0 success
|
||||
+# exit:
|
||||
+# 1 fail
|
||||
+curl_retry()
|
||||
+{
|
||||
+ local retries=$1 sleep=$2 opts=$3 url=$4
|
||||
+ local tries=$(($retries + 1))
|
||||
+ local args="--fail $opts $url"
|
||||
+ local result rc
|
||||
+
|
||||
+ for try in $(seq $tries); do
|
||||
+ ocf_log debug "curl $args try $try of $tries"
|
||||
+ result=$(echo "$args" | xargs curl 2>&1)
|
||||
+ rc=$?
|
||||
+
|
||||
+ ocf_log debug "result: $result"
|
||||
+ [ $rc -eq 0 ] && break
|
||||
+ sleep $sleep
|
||||
+ done
|
||||
+
|
||||
+ if [ $rc -ne 0 ]; then
|
||||
+ ocf_exit_reason "curl $args failed $tries tries"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ echo "$result"
|
||||
+ return $rc
|
||||
+}
|
||||
+
|
||||
# usage: crm_mon_no_validation args...
|
||||
# run crm_mon without any cib schema validation
|
||||
# This is useful when an agent runs in a bundle to avoid potential
|
||||
|
||||
From 80d330557319bdae9e45aad1279e435fc481d4e7 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 6 Feb 2024 13:28:25 +0100
|
||||
Subject: [PATCH 2/2] AWS agents: use curl_retry()
|
||||
|
||||
---
|
||||
heartbeat/aws-vpc-move-ip | 35 ++++++++++++++++++++++++++---------
|
||||
heartbeat/aws-vpc-route53.in | 27 +++++++++++++++++++++++++--
|
||||
heartbeat/awseip | 36 +++++++++++++++++++++++++++++++-----
|
||||
heartbeat/awsvip | 32 ++++++++++++++++++++++++++++----
|
||||
4 files changed, 110 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip
|
||||
index 54806f6ea..6115e5ba8 100755
|
||||
--- a/heartbeat/aws-vpc-move-ip
|
||||
+++ b/heartbeat/aws-vpc-move-ip
|
||||
@@ -47,6 +47,8 @@ OCF_RESKEY_interface_default="eth0"
|
||||
OCF_RESKEY_iflabel_default=""
|
||||
OCF_RESKEY_monapi_default="false"
|
||||
OCF_RESKEY_lookup_type_default="InstanceId"
|
||||
+OCF_RESKEY_curl_retries_default="3"
|
||||
+OCF_RESKEY_curl_sleep_default="1"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
@@ -60,6 +62,8 @@ OCF_RESKEY_lookup_type_default="InstanceId"
|
||||
: ${OCF_RESKEY_iflabel=${OCF_RESKEY_iflabel_default}}
|
||||
: ${OCF_RESKEY_monapi=${OCF_RESKEY_monapi_default}}
|
||||
: ${OCF_RESKEY_lookup_type=${OCF_RESKEY_lookup_type_default}}
|
||||
+: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}}
|
||||
+: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}}
|
||||
#######################################################################
|
||||
|
||||
|
||||
@@ -194,6 +198,22 @@ Name of resource type to lookup in route table.
|
||||
<content type="string" default="${OCF_RESKEY_lookup_type_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="curl_retries" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl retries before failing
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl retries</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_retries_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="curl_sleep" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl sleep between tries
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl sleep</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_sleep_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -250,8 +270,10 @@ ec2ip_validate() {
|
||||
fi
|
||||
fi
|
||||
|
||||
- TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
- EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
+ TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token")
|
||||
+ [ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+ EC2_INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id")
|
||||
+ [ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
|
||||
if [ -z "${EC2_INSTANCE_ID}" ]; then
|
||||
ocf_exit_reason "Instance ID not found. Is this a EC2 instance?"
|
||||
@@ -365,14 +387,9 @@ ec2ip_get_instance_eni() {
|
||||
fi
|
||||
ocf_log debug "MAC address associated with interface ${OCF_RESKEY_interface}: ${MAC_ADDR}"
|
||||
|
||||
- cmd="curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC_ADDR}/interface-id -H \"X-aws-ec2-metadata-token: $TOKEN\""
|
||||
- ocf_log debug "executing command: $cmd"
|
||||
+ cmd="curl_retry \"$OCF_RESKEY_curl_retries\" \"$OCF_RESKEY_curl_sleep\" \"--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'\" \"http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC_ADDR}/interface-id\""
|
||||
EC2_NETWORK_INTERFACE_ID="$(eval $cmd)"
|
||||
- rc=$?
|
||||
- if [ $rc != 0 ]; then
|
||||
- ocf_log warn "command failed, rc: $rc"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
+ [ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
ocf_log debug "network interface id associated MAC address ${MAC_ADDR}: ${EC2_NETWORK_INTERFACE_ID}"
|
||||
echo $EC2_NETWORK_INTERFACE_ID
|
||||
}
|
||||
diff --git a/heartbeat/aws-vpc-route53.in b/heartbeat/aws-vpc-route53.in
|
||||
index 18ab157e8..eba2ed95c 100644
|
||||
--- a/heartbeat/aws-vpc-route53.in
|
||||
+++ b/heartbeat/aws-vpc-route53.in
|
||||
@@ -53,6 +53,8 @@ OCF_RESKEY_hostedzoneid_default=""
|
||||
OCF_RESKEY_fullname_default=""
|
||||
OCF_RESKEY_ip_default="local"
|
||||
OCF_RESKEY_ttl_default=10
|
||||
+OCF_RESKEY_curl_retries_default="3"
|
||||
+OCF_RESKEY_curl_sleep_default="1"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
@@ -62,6 +64,8 @@ OCF_RESKEY_ttl_default=10
|
||||
: ${OCF_RESKEY_fullname:=${OCF_RESKEY_fullname_default}}
|
||||
: ${OCF_RESKEY_ip:=${OCF_RESKEY_ip_default}}
|
||||
: ${OCF_RESKEY_ttl:=${OCF_RESKEY_ttl_default}}
|
||||
+: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}}
|
||||
+: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}}
|
||||
|
||||
usage() {
|
||||
cat <<-EOT
|
||||
@@ -185,6 +189,22 @@ Time to live for Route53 ARECORD
|
||||
<shortdesc lang="en">ARECORD TTL</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_ttl_default}" />
|
||||
</parameter>
|
||||
+
|
||||
+<parameter name="curl_retries" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl retries before failing
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl retries</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_retries_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="curl_sleep" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl sleep between tries
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl sleep</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_sleep_default}" />
|
||||
+</parameter>
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -357,8 +377,11 @@ r53_monitor() {
|
||||
_get_ip() {
|
||||
case $OCF_RESKEY_ip in
|
||||
local|public)
|
||||
- TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
- IPADDRESS=$(curl -s http://169.254.169.254/latest/meta-data/${OCF_RESKEY_ip}-ipv4 -H "X-aws-ec2-metadata-token: $TOKEN");;
|
||||
+ TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token")
|
||||
+ [ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+ IPADDRESS=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/${OCF_RESKEY_ip}-ipv4")
|
||||
+ [ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+ ;;
|
||||
*.*.*.*)
|
||||
IPADDRESS="${OCF_RESKEY_ip}";;
|
||||
esac
|
||||
diff --git a/heartbeat/awseip b/heartbeat/awseip
|
||||
index 49b0ca615..ffb6223a1 100755
|
||||
--- a/heartbeat/awseip
|
||||
+++ b/heartbeat/awseip
|
||||
@@ -49,12 +49,16 @@ OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_api_delay_default="3"
|
||||
+OCF_RESKEY_curl_retries_default="3"
|
||||
+OCF_RESKEY_curl_sleep_default="1"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}}
|
||||
+: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}}
|
||||
+: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}}
|
||||
|
||||
meta_data() {
|
||||
cat <<END
|
||||
@@ -141,6 +145,22 @@ a short delay between API calls, to avoid sending API too quick
|
||||
<content type="integer" default="${OCF_RESKEY_api_delay_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="curl_retries" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl retries before failing
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl retries</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_retries_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="curl_sleep" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl sleep between tries
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl sleep</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_sleep_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -171,14 +191,18 @@ awseip_start() {
|
||||
awseip_monitor && return $OCF_SUCCESS
|
||||
|
||||
if [ -n "${PRIVATE_IP_ADDRESS}" ]; then
|
||||
- NETWORK_INTERFACES_MACS=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/ -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
+ NETWORK_INTERFACES_MACS=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "-s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/network/interfaces/macs/")
|
||||
for MAC in ${NETWORK_INTERFACES_MACS}; do
|
||||
- curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/local-ipv4s -H "X-aws-ec2-metadata-token: $TOKEN" |
|
||||
+ curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "-s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC%/*}/local-ipv4s" |
|
||||
grep -q "^${PRIVATE_IP_ADDRESS}$"
|
||||
if [ $? -eq 0 ]; then
|
||||
- NETWORK_ID=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/interface-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
+ NETWORK_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "-s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC%/*}/interface-id")
|
||||
fi
|
||||
done
|
||||
+ if [ -z "$NETWORK_ID" ]; then
|
||||
+ ocf_exit_reason "Could not find network interface for private_ip_address: $PRIVATE_IP_ADDRESS"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
$AWSCLI_CMD ec2 associate-address \
|
||||
--network-interface-id ${NETWORK_ID} \
|
||||
--allocation-id ${ALLOCATION_ID} \
|
||||
@@ -282,8 +306,10 @@ fi
|
||||
ELASTIC_IP="${OCF_RESKEY_elastic_ip}"
|
||||
ALLOCATION_ID="${OCF_RESKEY_allocation_id}"
|
||||
PRIVATE_IP_ADDRESS="${OCF_RESKEY_private_ip_address}"
|
||||
-TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
-INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
+TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token")
|
||||
+[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id")
|
||||
+[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
|
||||
case $__OCF_ACTION in
|
||||
start)
|
||||
diff --git a/heartbeat/awsvip b/heartbeat/awsvip
|
||||
index bdb4d68dd..f2b238a0f 100755
|
||||
--- a/heartbeat/awsvip
|
||||
+++ b/heartbeat/awsvip
|
||||
@@ -48,12 +48,16 @@ OCF_RESKEY_auth_type_default="key"
|
||||
OCF_RESKEY_profile_default="default"
|
||||
OCF_RESKEY_region_default=""
|
||||
OCF_RESKEY_api_delay_default="3"
|
||||
+OCF_RESKEY_curl_retries_default="3"
|
||||
+OCF_RESKEY_curl_sleep_default="1"
|
||||
|
||||
: ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}}
|
||||
: ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}}
|
||||
: ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}}
|
||||
: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}}
|
||||
: ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}}
|
||||
+: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}}
|
||||
+: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}}
|
||||
|
||||
meta_data() {
|
||||
cat <<END
|
||||
@@ -124,6 +128,22 @@ a short delay between API calls, to avoid sending API too quick
|
||||
<content type="integer" default="${OCF_RESKEY_api_delay_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="curl_retries" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl retries before failing
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl retries</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_retries_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="curl_sleep" unique="0">
|
||||
+<longdesc lang="en">
|
||||
+curl sleep between tries
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">curl sleep</shortdesc>
|
||||
+<content type="integer" default="${OCF_RESKEY_curl_sleep_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -246,10 +266,14 @@ if [ -n "${OCF_RESKEY_region}" ]; then
|
||||
AWSCLI_CMD="$AWSCLI_CMD --region ${OCF_RESKEY_region}"
|
||||
fi
|
||||
SECONDARY_PRIVATE_IP="${OCF_RESKEY_secondary_private_ip}"
|
||||
-TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
-INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
-MAC_ADDRESS=$(curl -s http://169.254.169.254/latest/meta-data/mac -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
-NETWORK_ID=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC_ADDRESS}/interface-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
+TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token")
|
||||
+[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id")
|
||||
+[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+MAC_ADDRESS=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/mac")
|
||||
+[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
+NETWORK_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC_ADDRESS}/interface-id")
|
||||
+[ $? -ne 0 ] && exit $OCF_ERR_GENERIC
|
||||
|
||||
case $__OCF_ACTION in
|
||||
start)
|
@ -1,48 +0,0 @@
|
||||
From accff72ecc2f6cf5a76d9570198a93ac7c90270e Mon Sep 17 00:00:00 2001
|
||||
From: Quentin Pradet <quentin.pradet@gmail.com>
|
||||
Date: Mon, 17 Jun 2024 11:09:06 +0400
|
||||
Subject: [PATCH] Merge pull request from GHSA-34jh-p97f-mpxf
|
||||
|
||||
* Strip Proxy-Authorization header on redirects
|
||||
|
||||
* Fix test_retry_default_remove_headers_on_redirect
|
||||
|
||||
* Set release date
|
||||
---
|
||||
CHANGES.rst | 5 +++++
|
||||
src/urllib3/util/retry.py | 4 +++-
|
||||
test/test_retry.py | 6 ++++-
|
||||
test/with_dummyserver/test_poolmanager.py | 27 ++++++++++++++++++++---
|
||||
4 files changed, 37 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/aliyun/aliyunsdkcore/vendored/requests/packages/urllib3/util/retry.py b/aliyun/aliyunsdkcore/vendored/requests/packages/urllib3/util/retry.py
|
||||
index 7a76a4a6ad..0456cceba4 100644
|
||||
--- a/aliyun/aliyunsdkcore/vendored/requests/packages/urllib3/util/retry.py
|
||||
+++ b/aliyun/aliyunsdkcore/vendored/requests/packages/urllib3/util/retry.py
|
||||
@@ -189,7 +189,9 @@ class Retry:
|
||||
RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503])
|
||||
|
||||
#: Default headers to be used for ``remove_headers_on_redirect``
|
||||
- DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Cookie", "Authorization"])
|
||||
+ DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(
|
||||
+ ["Cookie", "Authorization", "Proxy-Authorization"]
|
||||
+ )
|
||||
|
||||
#: Default maximum backoff time.
|
||||
DEFAULT_BACKOFF_MAX = 120
|
||||
|
||||
diff --git a/gcp/google-cloud-sdk/lib/third_party/urllib3/util/retry.py b/gcp/google-cloud-sdk/lib/third_party/urllib3/util/retry.py
|
||||
index 7a76a4a6ad..0456cceba4 100644
|
||||
--- a/gcp/google-cloud-sdk/lib/third_party/urllib3/util/retry.py
|
||||
+++ b/gcp/google-cloud-sdk/lib/third_party/urllib3/util/retry.py
|
||||
@@ -189,7 +189,9 @@ class Retry:
|
||||
RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503])
|
||||
|
||||
#: Default headers to be used for ``remove_headers_on_redirect``
|
||||
- DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Cookie", "Authorization"])
|
||||
+ DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(
|
||||
+ ["Cookie", "Authorization", "Proxy-Authorization"]
|
||||
+ )
|
||||
|
||||
#: Default maximum backoff time.
|
||||
DEFAULT_BACKOFF_MAX = 120
|
@ -1,201 +0,0 @@
|
||||
--- a/setuptools/package_index.py 1980-01-01 09:00:00.000000000 +0100
|
||||
+++ b/setuptools/package_index.py 2024-07-25 10:11:40.537307665 +0200
|
||||
@@ -1,5 +1,6 @@
|
||||
"""PyPI and direct package downloading"""
|
||||
import sys
|
||||
+import subprocess
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
@@ -563,7 +564,7 @@
|
||||
scheme = URL_SCHEME(spec)
|
||||
if scheme:
|
||||
# It's a url, download it to tmpdir
|
||||
- found = self._download_url(scheme.group(1), spec, tmpdir)
|
||||
+ found = self._download_url(spec, tmpdir)
|
||||
base, fragment = egg_info_for_url(spec)
|
||||
if base.endswith('.py'):
|
||||
found = self.gen_setup(found, fragment, tmpdir)
|
||||
@@ -775,7 +776,7 @@
|
||||
raise DistutilsError("Download error for %s: %s"
|
||||
% (url, v))
|
||||
|
||||
- def _download_url(self, scheme, url, tmpdir):
|
||||
+ def _download_url(self, url, tmpdir):
|
||||
# Determine download filename
|
||||
#
|
||||
name, fragment = egg_info_for_url(url)
|
||||
@@ -790,19 +791,59 @@
|
||||
|
||||
filename = os.path.join(tmpdir, name)
|
||||
|
||||
- # Download the file
|
||||
- #
|
||||
- if scheme == 'svn' or scheme.startswith('svn+'):
|
||||
- return self._download_svn(url, filename)
|
||||
- elif scheme == 'git' or scheme.startswith('git+'):
|
||||
- return self._download_git(url, filename)
|
||||
- elif scheme.startswith('hg+'):
|
||||
- return self._download_hg(url, filename)
|
||||
- elif scheme == 'file':
|
||||
- return urllib.request.url2pathname(urllib.parse.urlparse(url)[2])
|
||||
- else:
|
||||
- self.url_ok(url, True) # raises error if not allowed
|
||||
- return self._attempt_download(url, filename)
|
||||
+ return self._download_vcs(url, filename) or self._download_other(url, filename)
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def _resolve_vcs(url):
|
||||
+ """
|
||||
+ >>> rvcs = PackageIndex._resolve_vcs
|
||||
+ >>> rvcs('git+http://foo/bar')
|
||||
+ 'git'
|
||||
+ >>> rvcs('hg+https://foo/bar')
|
||||
+ 'hg'
|
||||
+ >>> rvcs('git:myhost')
|
||||
+ 'git'
|
||||
+ >>> rvcs('hg:myhost')
|
||||
+ >>> rvcs('http://foo/bar')
|
||||
+ """
|
||||
+ scheme = urllib.parse.urlsplit(url).scheme
|
||||
+ pre, sep, post = scheme.partition('+')
|
||||
+ # svn and git have their own protocol; hg does not
|
||||
+ allowed = set(['svn', 'git'] + ['hg'] * bool(sep))
|
||||
+ return next(iter({pre} & allowed), None)
|
||||
+
|
||||
+ def _download_vcs(self, url, spec_filename):
|
||||
+ vcs = self._resolve_vcs(url)
|
||||
+ if not vcs:
|
||||
+ return
|
||||
+ if vcs == 'svn':
|
||||
+ raise DistutilsError(
|
||||
+ f"Invalid config, SVN download is not supported: {url}"
|
||||
+ )
|
||||
+
|
||||
+ filename, _, _ = spec_filename.partition('#')
|
||||
+ url, rev = self._vcs_split_rev_from_url(url)
|
||||
+
|
||||
+ self.info(f"Doing {vcs} clone from {url} to {filename}")
|
||||
+ subprocess.check_call([vcs, 'clone', '--quiet', url, filename])
|
||||
+
|
||||
+ co_commands = dict(
|
||||
+ git=[vcs, '-C', filename, 'checkout', '--quiet', rev],
|
||||
+ hg=[vcs, '--cwd', filename, 'up', '-C', '-r', rev, '-q'],
|
||||
+ )
|
||||
+ if rev is not None:
|
||||
+ self.info(f"Checking out {rev}")
|
||||
+ subprocess.check_call(co_commands[vcs])
|
||||
+
|
||||
+ return filename
|
||||
+
|
||||
+ def _download_other(self, url, filename):
|
||||
+ scheme = urllib.parse.urlsplit(url).scheme
|
||||
+ if scheme == 'file': # pragma: no cover
|
||||
+ return urllib.request.url2pathname(urllib.parse.urlparse(url).path)
|
||||
+ # raise error if not allowed
|
||||
+ self.url_ok(url, True)
|
||||
+ return self._attempt_download(url, filename)
|
||||
|
||||
def scan_url(self, url):
|
||||
self.process_url(url, True)
|
||||
@@ -829,76 +870,37 @@
|
||||
os.unlink(filename)
|
||||
raise DistutilsError("Unexpected HTML page found at " + url)
|
||||
|
||||
- def _download_svn(self, url, filename):
|
||||
- url = url.split('#', 1)[0] # remove any fragment for svn's sake
|
||||
- creds = ''
|
||||
- if url.lower().startswith('svn:') and '@' in url:
|
||||
- scheme, netloc, path, p, q, f = urllib.parse.urlparse(url)
|
||||
- if not netloc and path.startswith('//') and '/' in path[2:]:
|
||||
- netloc, path = path[2:].split('/', 1)
|
||||
- auth, host = splituser(netloc)
|
||||
- if auth:
|
||||
- if ':' in auth:
|
||||
- user, pw = auth.split(':', 1)
|
||||
- creds = " --username=%s --password=%s" % (user, pw)
|
||||
- else:
|
||||
- creds = " --username=" + auth
|
||||
- netloc = host
|
||||
- parts = scheme, netloc, url, p, q, f
|
||||
- url = urllib.parse.urlunparse(parts)
|
||||
- self.info("Doing subversion checkout from %s to %s", url, filename)
|
||||
- os.system("svn checkout%s -q %s %s" % (creds, url, filename))
|
||||
- return filename
|
||||
-
|
||||
@staticmethod
|
||||
- def _vcs_split_rev_from_url(url, pop_prefix=False):
|
||||
- scheme, netloc, path, query, frag = urllib.parse.urlsplit(url)
|
||||
-
|
||||
- scheme = scheme.split('+', 1)[-1]
|
||||
-
|
||||
- # Some fragment identification fails
|
||||
- path = path.split('#', 1)[0]
|
||||
-
|
||||
- rev = None
|
||||
- if '@' in path:
|
||||
- path, rev = path.rsplit('@', 1)
|
||||
-
|
||||
- # Also, discard fragment
|
||||
- url = urllib.parse.urlunsplit((scheme, netloc, path, query, ''))
|
||||
-
|
||||
- return url, rev
|
||||
-
|
||||
- def _download_git(self, url, filename):
|
||||
- filename = filename.split('#', 1)[0]
|
||||
- url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
|
||||
-
|
||||
- self.info("Doing git clone from %s to %s", url, filename)
|
||||
- os.system("git clone --quiet %s %s" % (url, filename))
|
||||
+ def _vcs_split_rev_from_url(url):
|
||||
+ """
|
||||
+ Given a possible VCS URL, return a clean URL and resolved revision if any.
|
||||
|
||||
- if rev is not None:
|
||||
- self.info("Checking out %s", rev)
|
||||
- os.system("(cd %s && git checkout --quiet %s)" % (
|
||||
- filename,
|
||||
- rev,
|
||||
- ))
|
||||
+ >>> vsrfu = PackageIndex._vcs_split_rev_from_url
|
||||
+ >>> vsrfu('git+https://github.com/pypa/setuptools@v69.0.0#egg-info=setuptools')
|
||||
+ ('https://github.com/pypa/setuptools', 'v69.0.0')
|
||||
+ >>> vsrfu('git+https://github.com/pypa/setuptools#egg-info=setuptools')
|
||||
+ ('https://github.com/pypa/setuptools', None)
|
||||
+ >>> vsrfu('http://foo/bar')
|
||||
+ ('http://foo/bar', None)
|
||||
+ """
|
||||
+ parts = urllib.parse.urlsplit(url)
|
||||
|
||||
- return filename
|
||||
+ clean_scheme = parts.scheme.split('+', 1)[-1]
|
||||
|
||||
- def _download_hg(self, url, filename):
|
||||
- filename = filename.split('#', 1)[0]
|
||||
- url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
|
||||
+ # Some fragment identification fails
|
||||
+ no_fragment_path, _, _ = parts.path.partition('#')
|
||||
|
||||
- self.info("Doing hg clone from %s to %s", url, filename)
|
||||
- os.system("hg clone --quiet %s %s" % (url, filename))
|
||||
+ pre, sep, post = no_fragment_path.rpartition('@')
|
||||
+ clean_path, rev = (pre, post) if sep else (post, None)
|
||||
|
||||
- if rev is not None:
|
||||
- self.info("Updating to %s", rev)
|
||||
- os.system("(cd %s && hg up -C -r %s >&-)" % (
|
||||
- filename,
|
||||
- rev,
|
||||
- ))
|
||||
+ resolved = parts._replace(
|
||||
+ scheme=clean_scheme,
|
||||
+ path=clean_path,
|
||||
+ # discard the fragment
|
||||
+ fragment='',
|
||||
+ ).geturl()
|
||||
|
||||
- return filename
|
||||
+ return resolved, rev
|
||||
|
||||
def debug(self, msg, *args):
|
||||
log.debug(msg, *args)
|
@ -1,38 +0,0 @@
|
||||
From 38eaf00bc81af7530c56eba282918762a47a9326 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 19 Sep 2024 13:01:53 +0200
|
||||
Subject: [PATCH] nfsserver: also stop rpc-statd for nfsv4_only to avoid stop
|
||||
failing in some cases
|
||||
|
||||
E.g. nfs_no_notify=true nfsv4_only=true nfs_shared_infodir=/nfsmq/nfsinfo would cause a "Failed to unmount a bind mount" error
|
||||
---
|
||||
heartbeat/nfsserver | 16 +++++++---------
|
||||
1 file changed, 7 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 5793d7a70..fd9268afc 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -947,15 +947,13 @@ nfsserver_stop ()
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- if ! ocf_is_true "$OCF_RESKEY_nfsv4_only"; then
|
||||
- nfs_exec stop rpc-statd > /dev/null 2>&1
|
||||
- ocf_log info "Stop: rpc-statd"
|
||||
- rpcinfo -t localhost 100024 > /dev/null 2>&1
|
||||
- rc=$?
|
||||
- if [ "$rc" -eq "0" ]; then
|
||||
- ocf_exit_reason "Failed to stop rpc-statd"
|
||||
- return $OCF_ERR_GENERIC
|
||||
- fi
|
||||
+ nfs_exec stop rpc-statd > /dev/null 2>&1
|
||||
+ ocf_log info "Stop: rpc-statd"
|
||||
+ rpcinfo -t localhost 100024 > /dev/null 2>&1
|
||||
+ rc=$?
|
||||
+ if [ "$rc" -eq "0" ]; then
|
||||
+ ocf_exit_reason "Failed to stop rpc-statd"
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
nfs_exec stop nfs-idmapd > /dev/null 2>&1
|
@ -1,22 +0,0 @@
|
||||
From 4b09b3e467a7f8076bbf20f5b027efecf16303e7 Mon Sep 17 00:00:00 2001
|
||||
From: Gianluca Piccolo <gianluca.piccolo@wuerth-phoenix.com>
|
||||
Date: Thu, 6 Jun 2024 17:34:41 +0200
|
||||
Subject: [PATCH] Fix #1944
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index a445349b9..59b6c1b51 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -664,7 +664,7 @@ get_pids()
|
||||
if [ "X${HOSTOS}" = "XOpenBSD" ];then
|
||||
fstat | grep $dir | awk '{print $3}'
|
||||
else
|
||||
- $FUSER -m $dir 2>/dev/null
|
||||
+ $FUSER -Mm $dir 2>/dev/null
|
||||
fi
|
||||
elif [ "$FORCE_UNMOUNT" = "safe" ]; then
|
||||
procs=$(find /proc/[0-9]*/ -type l -lname "${dir}/*" -or -lname "${dir}" 2>/dev/null | awk -F/ '{print $3}')
|
@ -1,26 +0,0 @@
|
||||
From c9ba6ac66ee27a70c69e1156f17aa6beac277bc5 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 7 Jun 2024 14:23:28 +0200
|
||||
Subject: [PATCH] Filesystem: use fuser -c on FreeBSD, as -m and -M are used
|
||||
for other functionality
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 59b6c1b51..88fe2e2eb 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -661,8 +661,10 @@ get_pids()
|
||||
fi
|
||||
|
||||
if ocf_is_true "$FORCE_UNMOUNT"; then
|
||||
- if [ "X${HOSTOS}" = "XOpenBSD" ];then
|
||||
+ if [ "X${HOSTOS}" = "XOpenBSD" ]; then
|
||||
fstat | grep $dir | awk '{print $3}'
|
||||
+ elif [ "X${HOSTOS}" = "XFreeBSD" ]; then
|
||||
+ $FUSER -c $dir 2>/dev/null
|
||||
else
|
||||
$FUSER -Mm $dir 2>/dev/null
|
||||
fi
|
@ -1,448 +0,0 @@
|
||||
--- a/heartbeat/portblock 2025-02-20 14:54:18.047134471 +0100
|
||||
+++ b/heartbeat/portblock 2025-02-20 14:09:44.546869740 +0100
|
||||
@@ -25,6 +25,7 @@
|
||||
# Defaults
|
||||
OCF_RESKEY_protocol_default=""
|
||||
OCF_RESKEY_portno_default=""
|
||||
+OCF_RESKEY_direction_default="in"
|
||||
OCF_RESKEY_action_default=""
|
||||
OCF_RESKEY_ip_default="0.0.0.0/0"
|
||||
OCF_RESKEY_reset_local_on_unblock_stop_default="false"
|
||||
@@ -33,6 +34,7 @@
|
||||
|
||||
: ${OCF_RESKEY_protocol=${OCF_RESKEY_protocol_default}}
|
||||
: ${OCF_RESKEY_portno=${OCF_RESKEY_portno_default}}
|
||||
+: ${OCF_RESKEY_direction=${OCF_RESKEY_direction_default}}
|
||||
: ${OCF_RESKEY_action=${OCF_RESKEY_action_default}}
|
||||
: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
|
||||
: ${OCF_RESKEY_reset_local_on_unblock_stop=${OCF_RESKEY_reset_local_on_unblock_stop_default}}
|
||||
@@ -217,6 +219,18 @@
|
||||
<shortdesc lang="en">Connection state file synchronization script</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_sync_script_default}" />
|
||||
</parameter>
|
||||
+
|
||||
+<parameter name="direction" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Whether to block incoming or outgoing traffic. Can be either "in",
|
||||
+"out", or "both".
|
||||
+If "in" is used, the incoming ports are blocked on the INPUT chain.
|
||||
+If "out" is used, the outgoing ports are blocked on the OUTPUT chain.
|
||||
+If "both" is used, both the incoming and outgoing ports are blocked.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Whether to block incoming or outgoing traffic, or both</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_direction_default}" />
|
||||
+</parameter>
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
@@ -240,36 +254,73 @@
|
||||
# and disable us -- but we're still in some sense active...
|
||||
#
|
||||
|
||||
-#active_grep_pat {udp|tcp} portno,portno
|
||||
+#active_grep_pat {udp|tcp} portno,portno ip {d|s}
|
||||
+# d = look for destination ports
|
||||
+# s = look for source ports
|
||||
active_grep_pat()
|
||||
{
|
||||
w="[ ][ ]*"
|
||||
any="0\\.0\\.0\\.0/0"
|
||||
- echo "^DROP${w}${1}${w}--${w}${any}${w}${3}${w}multiport${w}dports${w}${2}\>"
|
||||
+ src=$any dst=$3
|
||||
+ if [ "$4" = "s" ]; then
|
||||
+ local src=$3
|
||||
+ local dst=$any
|
||||
+ fi
|
||||
+ # 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)"
|
||||
+ else
|
||||
+ local prot="(udp|17)"
|
||||
+ fi
|
||||
+ echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$"
|
||||
}
|
||||
|
||||
-#chain_isactive {udp|tcp} portno,portno ip
|
||||
+#chain_isactive {udp|tcp} portno,portno ip chain
|
||||
chain_isactive()
|
||||
{
|
||||
- PAT=`active_grep_pat "$1" "$2" "$3"`
|
||||
- $IPTABLES $wait -n -L INPUT | grep "$PAT" >/dev/null
|
||||
+ [ "$4" = "OUTPUT" ] && ds="s" || ds="d"
|
||||
+ PAT=$(active_grep_pat "$1" "$2" "$3" "$ds")
|
||||
+ $IPTABLES $wait -n -L "$4" | grep -qE "$PAT"
|
||||
+}
|
||||
+
|
||||
+# netstat -tn and ss -Htn, split on whitespace and colon,
|
||||
+# look very similar:
|
||||
+# tcp 0 0 10.43.55.1 675 10.43.9.8 2049 ESTABLISHED
|
||||
+# ESTAB 0 0 10.43.55.1 675 10.43.9.8 2049
|
||||
+# so we can write one awk script for both
|
||||
+get_established_tcp_connections()
|
||||
+{
|
||||
+ local columns
|
||||
+ if [ -z "$1" ] ; then
|
||||
+ columns='$4,$5, $6,$7'
|
||||
+ else
|
||||
+ # swap local and remote for "tickle_local"
|
||||
+ columns='$6,$7, $4,$5'
|
||||
+ fi
|
||||
+ $ss_or_netstat | awk -F '[:[:space:]]+' '
|
||||
+ ( $8 == "ESTABLISHED" || $1 == "ESTAB" ) && $4 == "'$OCF_RESKEY_ip'" \
|
||||
+ {printf "%s:%s\t%s:%s\n", '"$columns"'}'
|
||||
}
|
||||
|
||||
save_tcp_connections()
|
||||
{
|
||||
[ -z "$OCF_RESKEY_tickle_dir" ] && return
|
||||
statefile=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
||||
+ # If we have _no_ sync script, we probably have a shared
|
||||
+ # (or replicated) directory, and need to fsync, or we might
|
||||
+ # end up with the just truncated file after failover, exactly
|
||||
+ # when we need it.
|
||||
+ #
|
||||
+ # If we _do_ have a sync script, it is not that important whether
|
||||
+ # the local state file is fsync'ed or not, the sync script is
|
||||
+ # responsible to "atomically" communicate the state to the peer(s).
|
||||
if [ -z "$OCF_RESKEY_sync_script" ]; then
|
||||
- netstat -tn |awk -F '[:[:space:]]+' '
|
||||
- $8 == "ESTABLISHED" && $4 == "'$OCF_RESKEY_ip'" \
|
||||
- {printf "%s:%s\t%s:%s\n", $4,$5, $6,$7}' |
|
||||
- dd of="$statefile".new conv=fsync status=none &&
|
||||
- mv "$statefile".new "$statefile"
|
||||
+ get_established_tcp_connections |
|
||||
+ dd of="$statefile".new conv=fsync status=none &&
|
||||
+ mv "$statefile".new "$statefile"
|
||||
else
|
||||
- netstat -tn |awk -F '[:[:space:]]+' '
|
||||
- $8 == "ESTABLISHED" && $4 == "'$OCF_RESKEY_ip'" \
|
||||
- {printf "%s:%s\t%s:%s\n", $4,$5, $6,$7}' \
|
||||
- > $statefile
|
||||
+ get_established_tcp_connections > $statefile
|
||||
$OCF_RESKEY_sync_script $statefile > /dev/null 2>&1 &
|
||||
fi
|
||||
}
|
||||
@@ -277,7 +328,6 @@
|
||||
tickle_remote()
|
||||
{
|
||||
[ -z "$OCF_RESKEY_tickle_dir" ] && return
|
||||
- echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
|
||||
f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
||||
[ -r $f ] || return
|
||||
$TICKLETCP -n 3 < $f
|
||||
@@ -289,11 +339,6 @@
|
||||
f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
|
||||
[ -r $f ] || return
|
||||
|
||||
- checkcmd="netstat -tn"
|
||||
- if ! have_binary "netstat"; then
|
||||
- checkcmd="ss -Htn"
|
||||
- fi
|
||||
-
|
||||
# swap "local" and "remote" address,
|
||||
# so we tickle ourselves.
|
||||
# We set up a REJECT with tcp-reset before we do so, so we get rid of
|
||||
@@ -302,122 +347,152 @@
|
||||
# the way if we switch-over and then switch-back in quick succession.
|
||||
local i
|
||||
awk '{ print $2, $1; }' $f | $TICKLETCP
|
||||
- $checkcmd | grep -Fw $OCF_RESKEY_ip || return
|
||||
+ $ss_or_netstat | grep -Fw $OCF_RESKEY_ip || return
|
||||
for i in 0.1 0.5 1 2 4 ; do
|
||||
sleep $i
|
||||
- awk '{ print $2, $1; }' $f | $TICKLETCP
|
||||
- $checkcmd | grep -Fw $OCF_RESKEY_ip || break
|
||||
+ # now kill what is currently in the list,
|
||||
+ # not what was recorded during last monitor
|
||||
+ get_established_tcp_connections swap | $TICKLETCP
|
||||
+ $ss_or_netstat | grep -Fw $OCF_RESKEY_ip || break
|
||||
done
|
||||
}
|
||||
|
||||
SayActive()
|
||||
{
|
||||
- echo "$CMD DROP rule for INPUT chain [$*] is running (OK)"
|
||||
+ ocf_log debug "$CMD DROP rule [$*] is running (OK)"
|
||||
}
|
||||
|
||||
SayConsideredActive()
|
||||
{
|
||||
- echo "$CMD DROP rule for INPUT chain [$*] considered to be running (OK)"
|
||||
+ ocf_log debug "$CMD DROP rule [$*] considered to be running (OK)"
|
||||
}
|
||||
|
||||
SayInactive()
|
||||
{
|
||||
- echo "$CMD DROP rule for INPUT chain [$*] is inactive"
|
||||
+ ocf_log debug "$CMD DROP rule [$*] is inactive"
|
||||
}
|
||||
|
||||
-#IptablesStatus {udp|tcp} portno,portno ip {block|unblock}
|
||||
+#IptablesStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
IptablesStatus() {
|
||||
- local rc
|
||||
- rc=$OCF_ERR_GENERIC
|
||||
- activewords="$CMD $1 $2 is running (OK)"
|
||||
- if chain_isactive "$1" "$2" "$3"; then
|
||||
- case $4 in
|
||||
- block)
|
||||
- SayActive $*
|
||||
- rc=$OCF_SUCCESS
|
||||
- ;;
|
||||
- *)
|
||||
- SayInactive $*
|
||||
- rc=$OCF_NOT_RUNNING
|
||||
- ;;
|
||||
- esac
|
||||
- else
|
||||
- case $4 in
|
||||
- block)
|
||||
- if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then
|
||||
- SayConsideredActive $*
|
||||
- rc=$OCF_SUCCESS
|
||||
- else
|
||||
- SayInactive $*
|
||||
- rc=$OCF_NOT_RUNNING
|
||||
- fi
|
||||
- ;;
|
||||
-
|
||||
- *)
|
||||
- if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then
|
||||
- SayActive $*
|
||||
- #This is only run on real monitor events.
|
||||
- save_tcp_connections
|
||||
- rc=$OCF_SUCCESS
|
||||
- else
|
||||
- SayInactive $*
|
||||
- rc=$OCF_NOT_RUNNING
|
||||
- fi
|
||||
- ;;
|
||||
- esac
|
||||
- fi
|
||||
-
|
||||
- return $rc
|
||||
+ local rc
|
||||
+ rc=$OCF_ERR_GENERIC
|
||||
+ is_active=0
|
||||
+ if [ "$4" = "in" ] || [ "$4" = "both" ]; then
|
||||
+ chain_isactive "$1" "$2" "$3" INPUT
|
||||
+ is_active=$?
|
||||
+ fi
|
||||
+ if [ "$4" = "out" ] || [ "$4" = "both" ]; then
|
||||
+ chain_isactive "$1" "$2" "$3" OUTPUT
|
||||
+ r=$?
|
||||
+ [ $r -gt $is_active ] && is_active=$r
|
||||
+ fi
|
||||
+ if [ $is_active -eq 0 ]; then
|
||||
+ case $5 in
|
||||
+ block)
|
||||
+ SayActive $*
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ ;;
|
||||
+ *)
|
||||
+ SayInactive $*
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ ;;
|
||||
+ esac
|
||||
+ else
|
||||
+ case $5 in
|
||||
+ block)
|
||||
+ if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then
|
||||
+ SayConsideredActive $*
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ else
|
||||
+ SayInactive $*
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ ;;
|
||||
+ *)
|
||||
+ if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then
|
||||
+ SayActive $*
|
||||
+ #This is only run on real monitor events.
|
||||
+ save_tcp_connections
|
||||
+ rc=$OCF_SUCCESS
|
||||
+ else
|
||||
+ SayInactive $*
|
||||
+ rc=$OCF_NOT_RUNNING
|
||||
+ fi
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fi
|
||||
+ return $rc
|
||||
}
|
||||
|
||||
-#IptablesBLOCK {udp|tcp} portno,portno ip
|
||||
-IptablesBLOCK()
|
||||
+#DoIptables {-I|-D} {udp|tcp} portno,portno ip chain
|
||||
+DoIptables()
|
||||
{
|
||||
- local rc=0
|
||||
- local try_reset=false
|
||||
- if [ "$1/$4/$__OCF_ACTION" = tcp/unblock/stop ] &&
|
||||
- ocf_is_true $reset_local_on_unblock_stop
|
||||
- then
|
||||
- try_reset=true
|
||||
- fi
|
||||
- if
|
||||
- chain_isactive "$1" "$2" "$3"
|
||||
- then
|
||||
- : OK -- chain already active
|
||||
+ op=$1 proto=$2 ports=$3 ip=$4 chain=$5
|
||||
+ active=0; chain_isactive "$proto" "$ports" "$ip" "$chain" && active=1
|
||||
+ want_active=0; [ "$op" = "-I" ] && want_active=1
|
||||
+ ocf_log debug "active: $active want_active: $want_active"
|
||||
+ if [ $active -eq $want_active ] ; then
|
||||
+ : Chain already in desired state
|
||||
else
|
||||
- if $try_reset ; then
|
||||
- $IPTABLES $wait -I OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
- tickle_local
|
||||
+ [ "$chain" = "OUTPUT" ] && ds="s" || ds="d"
|
||||
+ $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -j DROP
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+#IptablesBLOCK {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
+IptablesBLOCK()
|
||||
+{
|
||||
+ local rc_in=0
|
||||
+ local rc_out=0
|
||||
+ if [ "$4" = "in" ] || [ "$4" = "both" ]; then
|
||||
+ local try_reset=false
|
||||
+ if [ "$1/$5/$__OCF_ACTION" = tcp/unblock/stop ] &&
|
||||
+ ocf_is_true $reset_local_on_unblock_stop
|
||||
+ then
|
||||
+ try_reset=true
|
||||
fi
|
||||
- $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP
|
||||
- rc=$?
|
||||
- if $try_reset ; then
|
||||
- $IPTABLES $wait -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
+ if
|
||||
+ chain_isactive "$1" "$2" "$3" INPUT
|
||||
+ then
|
||||
+ : OK -- chain already active
|
||||
+ else
|
||||
+ if $try_reset ; then
|
||||
+ $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
|
||||
+ rc_in=$?
|
||||
+ if $try_reset ; then
|
||||
+ $IPTABLES $wait -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset
|
||||
+ fi
|
||||
fi
|
||||
fi
|
||||
+ if [ "$4" = "out" ] || [ "$4" = "both" ]; then
|
||||
+ DoIptables -I "$1" "$2" "$3" OUTPUT
|
||||
+ rc_out=$?
|
||||
+ fi
|
||||
|
||||
- return $rc
|
||||
+ [ $rc_in -gt $rc_out ] && return $rc_in || return $rc_out
|
||||
}
|
||||
|
||||
-#IptablesUNBLOCK {udp|tcp} portno,portno ip
|
||||
+#IptablesUNBLOCK {udp|tcp} portno,portno ip {in|out|both}
|
||||
IptablesUNBLOCK()
|
||||
{
|
||||
- if
|
||||
- chain_isactive "$1" "$2" "$3"
|
||||
- then
|
||||
- $IPTABLES $wait -D INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP
|
||||
- else
|
||||
- : Chain Not active
|
||||
+ if [ "$4" = "in" ] || [ "$4" = "both" ]; then
|
||||
+ DoIptables -D "$1" "$2" "$3" INPUT
|
||||
+ fi
|
||||
+ if [ "$4" = "out" ] || [ "$4" = "both" ]; then
|
||||
+ DoIptables -D "$1" "$2" "$3" OUTPUT
|
||||
fi
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
-#IptablesStart {udp|tcp} portno,portno ip {block|unblock}
|
||||
+#IptablesStart {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
IptablesStart()
|
||||
{
|
||||
ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" start
|
||||
- case $4 in
|
||||
+ case $5 in
|
||||
block) IptablesBLOCK "$@";;
|
||||
unblock)
|
||||
IptablesUNBLOCK "$@"
|
||||
@@ -432,11 +507,11 @@
|
||||
return $?
|
||||
}
|
||||
|
||||
-#IptablesStop {udp|tcp} portno,portno ip {block|unblock}
|
||||
+#IptablesStop {udp|tcp} portno,portno ip {in|out|both} {block|unblock}
|
||||
IptablesStop()
|
||||
{
|
||||
ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" stop
|
||||
- case $4 in
|
||||
+ case $5 in
|
||||
block) IptablesUNBLOCK "$@";;
|
||||
unblock)
|
||||
save_tcp_connections
|
||||
@@ -454,7 +529,7 @@
|
||||
CheckPort() {
|
||||
# Examples of valid port: "1080", "1", "0080"
|
||||
# Examples of invalid port: "1080bad", "0", "0000", ""
|
||||
- echo $1 |egrep -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*'
|
||||
+ echo $1 | $EGREP -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*'
|
||||
}
|
||||
|
||||
IptablesValidateAll()
|
||||
@@ -543,7 +618,7 @@
|
||||
fi
|
||||
|
||||
# iptables v1.4.20+ is required to use -w (wait)
|
||||
-version=$(iptables -V | awk -F ' v' '{print $NF}')
|
||||
+version=$(iptables -V | grep -oE '[0-9]+[\.0-9]+')
|
||||
ocf_version_cmp "$version" "1.4.19.1"
|
||||
if [ "$?" -eq "2" ]; then
|
||||
wait="-w"
|
||||
@@ -553,21 +628,36 @@
|
||||
|
||||
protocol=$OCF_RESKEY_protocol
|
||||
portno=$OCF_RESKEY_portno
|
||||
+direction=$OCF_RESKEY_direction
|
||||
action=$OCF_RESKEY_action
|
||||
ip=$OCF_RESKEY_ip
|
||||
reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop
|
||||
|
||||
+
|
||||
+# If "tickle" is enabled, we need to record the list of currently established
|
||||
+# connections during monitor. Use ss where available, and netstat otherwise.
|
||||
+if [ -n "$OCF_RESKEY_tickle_dir" ] ; then
|
||||
+ if have_binary ss ; then
|
||||
+ ss_or_netstat="ss -Htn"
|
||||
+ elif have_binary netstat ; then
|
||||
+ ss_or_netstat="netstat -tn"
|
||||
+ else
|
||||
+ ocf_log err "Neither ss nor netstat found, but needed to record estblished connections."
|
||||
+ exit $OCF_ERR_INSTALLED
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
case $1 in
|
||||
start)
|
||||
- IptablesStart $protocol $portno $ip $action
|
||||
+ IptablesStart $protocol $portno $ip $direction $action
|
||||
;;
|
||||
|
||||
stop)
|
||||
- IptablesStop $protocol $portno $ip $action
|
||||
+ IptablesStop $protocol $portno $ip $direction $action
|
||||
;;
|
||||
|
||||
status|monitor)
|
||||
- IptablesStatus $protocol $portno $ip $action
|
||||
+ IptablesStatus $protocol $portno $ip $direction $action
|
||||
;;
|
||||
|
||||
validate-all)
|
@ -1,171 +0,0 @@
|
||||
From 3bffa541f7bf66e143f14e51551fc91dfebec86c Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Schug <happytobi@tscoding.de>
|
||||
Date: Mon, 28 Oct 2024 09:14:41 +0100
|
||||
Subject: [PATCH] Add azure aznfs filesystem support
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 37 ++++++++++++++++++++-----------------
|
||||
1 file changed, 20 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 3405e2c26..b48bee142 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Support: users@clusterlabs.org
|
||||
# License: GNU General Public License (GPL)
|
||||
-#
|
||||
+#
|
||||
# Filesystem
|
||||
# Description: Manages a Filesystem on a shared storage medium.
|
||||
# Original Author: Eric Z. Ayers (eric.ayers@compgen.com)
|
||||
@@ -142,7 +142,7 @@ meta_data() {
|
||||
|
||||
<longdesc lang="en">
|
||||
Resource script for Filesystem. It manages a Filesystem on a
|
||||
-shared storage medium.
|
||||
+shared storage medium.
|
||||
|
||||
The standard monitor operation of depth 0 (also known as probe)
|
||||
checks if the filesystem is mounted. If you want deeper tests,
|
||||
@@ -260,7 +260,7 @@ currently accessing the mount directory.
|
||||
"true" : Kill processes accessing mount point
|
||||
"safe" : Kill processes accessing mount point using methods that
|
||||
avoid functions that could potentially block during process
|
||||
- detection
|
||||
+ detection
|
||||
"false" : Do not kill any processes.
|
||||
|
||||
The 'safe' option uses shell logic to walk the /procs/ directory
|
||||
@@ -373,7 +373,7 @@ determine_blockdevice() {
|
||||
# Get the current real device name, if possible.
|
||||
# (specified devname could be -L or -U...)
|
||||
case "$FSTYPE" in
|
||||
- nfs4|nfs|efs|smbfs|cifs|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|none|lustre)
|
||||
+ nfs4|nfs|aznfs|efs|smbfs|cifs|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|none|lustre)
|
||||
: ;;
|
||||
*)
|
||||
match_string="${TAB}${CANONICALIZED_MOUNTPOINT}${TAB}"
|
||||
@@ -455,7 +455,7 @@ is_fsck_needed() {
|
||||
no) false;;
|
||||
""|auto)
|
||||
case "$FSTYPE" in
|
||||
- ext4|ext4dev|ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs4|nfs|efs|cifs|smbfs|ocfs2|gfs2|none|lustre|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs)
|
||||
+ ext4|ext4dev|ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs4|nfs|aznfs|efs|cifs|smbfs|ocfs2|gfs2|none|lustre|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs)
|
||||
false;;
|
||||
*)
|
||||
true;;
|
||||
@@ -478,7 +478,7 @@ fstype_supported()
|
||||
fi
|
||||
|
||||
if [ -z "$FSTYPE" -o "$FSTYPE" = none ]; then
|
||||
- : No FSTYPE specified, rely on the system has the right file-system support already
|
||||
+ : No FSTYPE specified, rely on the system has the right file-system support already
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
@@ -487,6 +487,7 @@ fstype_supported()
|
||||
case "$FSTYPE" in
|
||||
fuse.*|glusterfs|rozofs) support="fuse";;
|
||||
efs) check_binary "mount.efs"; support="nfs4";;
|
||||
+ aznfs) check_binary "mount.aznfs"; support="nfs4";;
|
||||
esac
|
||||
|
||||
if [ "$support" != "$FSTYPE" ]; then
|
||||
@@ -530,7 +531,7 @@ fstype_supported()
|
||||
# node on the shared storage, and is not visible yet. Then try
|
||||
# partprobe to refresh /dev/disk/by-{label,uuid}/* up to date.
|
||||
#
|
||||
-# DEVICE can be /dev/xxx, -U, -L
|
||||
+# DEVICE can be /dev/xxx, -U, -L
|
||||
#
|
||||
trigger_udev_rules_if_needed()
|
||||
{
|
||||
@@ -545,12 +546,12 @@ trigger_udev_rules_if_needed()
|
||||
fi
|
||||
else
|
||||
tmp="$(echo $DEVICE|awk '{$1=""; print substr($0,2)}')"
|
||||
- case "$DEVICE" in
|
||||
- -U*|--uuid*)
|
||||
- tmp="/dev/disk/by-uuid/$tmp"
|
||||
+ case "$DEVICE" in
|
||||
+ -U*|--uuid*)
|
||||
+ tmp="/dev/disk/by-uuid/$tmp"
|
||||
;;
|
||||
-L*|--label*)
|
||||
- tmp="/dev/disk/by-label/$tmp"
|
||||
+ tmp="/dev/disk/by-label/$tmp"
|
||||
;;
|
||||
*)
|
||||
# bind mount?
|
||||
@@ -595,7 +596,7 @@ Filesystem_start()
|
||||
|
||||
fstype_supported || exit $OCF_ERR_INSTALLED
|
||||
|
||||
- # Check the filesystem & auto repair.
|
||||
+ # Check the filesystem & auto repair.
|
||||
# NOTE: Some filesystem types don't need this step... Please modify
|
||||
# accordingly
|
||||
|
||||
@@ -697,7 +698,7 @@ signal_processes() {
|
||||
local sig=$2
|
||||
local pids pid
|
||||
# fuser returns a non-zero return code if none of the
|
||||
- # specified files is accessed or in case of a fatal
|
||||
+ # specified files is accessed or in case of a fatal
|
||||
# error.
|
||||
pids=$(get_pids "$dir")
|
||||
if [ -z "$pids" ]; then
|
||||
@@ -745,6 +746,7 @@ fs_stop_loop() {
|
||||
try_umount "$force_arg" "$SUB" && return $OCF_SUCCESS
|
||||
done
|
||||
}
|
||||
+
|
||||
fs_stop() {
|
||||
local SUB="$1" timeout=$2 grace_time ret
|
||||
grace_time=$((timeout/2))
|
||||
@@ -797,7 +799,7 @@ Filesystem_stop()
|
||||
|
||||
# For networked filesystems, there's merit in trying -f:
|
||||
case "$FSTYPE" in
|
||||
- nfs4|nfs|efs|cifs|smbfs) umount_force="-f" ;;
|
||||
+ nfs4|nfs|aznfs|efs|cifs|smbfs) umount_force="-f" ;;
|
||||
esac
|
||||
|
||||
# Umount all sub-filesystems mounted under $MOUNTPOINT/ too.
|
||||
@@ -942,6 +944,7 @@ Filesystem_monitor_20()
|
||||
fi
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
+
|
||||
Filesystem_monitor()
|
||||
{
|
||||
Filesystem_status
|
||||
@@ -1016,7 +1019,7 @@ set_blockdevice_var() {
|
||||
|
||||
# these are definitely not block devices
|
||||
case "$FSTYPE" in
|
||||
- nfs4|nfs|efs|smbfs|cifs|none|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|lustre) return;;
|
||||
+ nfs4|nfs|aznfs|efs|smbfs|cifs|none|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|lustre) return;;
|
||||
esac
|
||||
|
||||
if $(is_option "loop"); then
|
||||
@@ -1098,7 +1101,7 @@ set_blockdevice_var
|
||||
if [ -z "$OCF_RESKEY_directory" ]; then
|
||||
if [ X$OP = "Xstart" -o $blockdevice = "no" ]; then
|
||||
ocf_exit_reason "Please specify the directory"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
else
|
||||
MOUNTPOINT="$(echo "$OCF_RESKEY_directory" | sed 's/\/*$//')"
|
||||
@@ -1166,7 +1169,7 @@ is_option "ro" &&
|
||||
CLUSTERSAFE=2
|
||||
|
||||
case "$FSTYPE" in
|
||||
-nfs4|nfs|efs|smbfs|cifs|none|gfs2|glusterfs|ceph|ocfs2|overlay|overlayfs|tmpfs|cvfs|lustre)
|
||||
+nfs4|nfs|aznfs|efs|smbfs|cifs|none|gfs2|glusterfs|ceph|ocfs2|overlay|overlayfs|tmpfs|cvfs|lustre)
|
||||
CLUSTERSAFE=1 # this is kind of safe too
|
||||
systemd_drop_in "99-Filesystem-remote" "After" "remote-fs.target"
|
||||
;;
|
@ -1,15 +0,0 @@
|
||||
--- a/heartbeat/aliyun-vpc-move-ip 2020-06-09 13:45:38.432860930 +0200
|
||||
+++ b/heartbeat/aliyun-vpc-move-ip 2020-06-09 13:51:06.341211557 +0200
|
||||
@@ -35,10 +35,10 @@
|
||||
USAGE="usage: $0 {start|stop|status|meta-data}";
|
||||
|
||||
if [ "${OCF_RESKEY_aliyuncli}" = "detect" ]; then
|
||||
- OCF_RESKEY_aliyuncli="$(which aliyuncli 2> /dev/null || which aliyun 2> /dev/null)"
|
||||
+ OCF_RESKEY_aliyuncli="$(which aliyuncli-ra 2> /dev/null || which aliyuncli 2> /dev/null || which aliyun 2> /dev/null)"
|
||||
fi
|
||||
|
||||
-if [ "${OCF_RESKEY_aliyuncli##*/}" = 'aliyuncli' ]; then
|
||||
+if [ "${OCF_RESKEY_aliyuncli##*/}" = 'aliyuncli-ra' ] || [ "${OCF_RESKEY_aliyuncli##*/}" = 'aliyuncli' ]; then
|
||||
OUTPUT="text"
|
||||
EXECUTING='{ print $3 }'
|
||||
IFS_=" "
|
@ -1,398 +0,0 @@
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsExportHandler.py b/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsExportHandler.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsExportHandler.py 2019-02-19 12:08:17.331785393 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsExportHandler.py 2019-02-19 14:40:39.656330971 +0100
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
def getFileName(self,keyValues):
|
||||
filename = None
|
||||
- if keyValues.has_key('--filename') and len(keyValues['--filename']) > 0:
|
||||
+ if '--filename' in keyValues and len(keyValues['--filename']) > 0:
|
||||
filename = keyValues['--filename'][0]
|
||||
else:
|
||||
return filename, "A file name is needed! please use \'--filename\' and add the file name."
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsImportHandler.py b/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsImportHandler.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsImportHandler.py 2019-02-19 12:08:17.331785393 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/advance/ecsImportHandler.py 2019-02-19 14:41:48.927128430 +0100
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
def getFileName(self,keyValues):
|
||||
filename = None
|
||||
- if keyValues.has_key('--filename') and len(keyValues['--filename']) > 0:
|
||||
+ if '--filename' in keyValues and len(keyValues['--filename']) > 0:
|
||||
filename = keyValues['--filename'][0]
|
||||
else:
|
||||
print("A profile is needed! please use \'--filename\' and add the profile name.")
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
def getInstanceCount(self,keyValues):
|
||||
count = 1
|
||||
- if keyValues.has_key('--instancecount') and len(keyValues['--instancecount']) > 0:
|
||||
+ if '--instancecount' in keyValues and len(keyValues['--instancecount']) > 0:
|
||||
if keyValues['--instancecount'][0].isdigit() and int(keyValues['--instancecount'][0]) >= 0:
|
||||
count = keyValues['--instancecount'][0]
|
||||
else:
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
def isAllocatePublicIpAddress(self,keyValues):
|
||||
_publicIp = False
|
||||
- if keyValues.has_key('--allocatepublicip') and len(keyValues['--allocatepublicip']) > 0:
|
||||
+ if '--allocatepublicip' in keyValues and len(keyValues['--allocatepublicip']) > 0:
|
||||
if keyValues['--allocatepublicip'][0] == "yes":
|
||||
_publicIp = True
|
||||
return _publicIp
|
||||
@@ -125,7 +125,7 @@
|
||||
'''
|
||||
data = json.loads(jsonbody)
|
||||
'''
|
||||
- if data.has_key('InstanceId') and len(data['InstanceId']) > 0:
|
||||
+ if 'InstanceId' in data and len(data['InstanceId']) > 0:
|
||||
instanceId = data['InstanceId']
|
||||
except Exception as e:
|
||||
pass
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsExportHandler.py b/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsExportHandler.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsExportHandler.py 2019-02-19 12:08:17.331785393 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsExportHandler.py 2019-02-19 14:42:11.772731833 +0100
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
def getFileName(self,keyValues):
|
||||
filename = None
|
||||
- if keyValues.has_key('--filename') and len(keyValues['--filename']) > 0:
|
||||
+ if '--filename' in keyValues and len(keyValues['--filename']) > 0:
|
||||
filename = keyValues['--filename'][0]
|
||||
else:
|
||||
return filename, "A file name is needed! please use \'--filename\' and add the file name."
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsImportHandler.py b/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsImportHandler.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsImportHandler.py 2019-02-19 12:08:17.331785393 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/advance/rdsImportHandler.py 2019-02-19 14:39:09.247900469 +0100
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
def getFileName(self,keyValues):
|
||||
filename = None
|
||||
- if keyValues.has_key('--filename') and len(keyValues['--filename']) > 0:
|
||||
+ if '--filename' in keyValues and len(keyValues['--filename']) > 0:
|
||||
filename = keyValues['--filename'][0]
|
||||
else:
|
||||
return filename, "A filename is needed! please use \'--filename\' and add the file name."
|
||||
@@ -21,7 +21,7 @@
|
||||
def getInstanceCount(self,keyValues):
|
||||
count = 1
|
||||
import_count = "--count"
|
||||
- if keyValues.has_key(import_count) and len(keyValues[import_count]) > 0:
|
||||
+ if import_count in keyValues and len(keyValues[import_count]) > 0:
|
||||
if keyValues[import_count][0].isdigit() and int(keyValues[import_count][0]) >= 0:
|
||||
count = keyValues[import_count][0]
|
||||
else:
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/advance/userConfigHandler.py b/bundled/aliyun/aliyun-cli/aliyuncli/advance/userConfigHandler.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/advance/userConfigHandler.py 2018-01-24 04:08:33.000000000 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/advance/userConfigHandler.py 2019-02-19 11:01:46.116653274 +0100
|
||||
@@ -17,37 +17,37 @@
|
||||
|
||||
def getConfigHandlerOptions(self):
|
||||
return [ConfigCmd.name]
|
||||
-
|
||||
+
|
||||
def showConfig(self):
|
||||
_credentialsPath = os.path.join(self.extensionCliHandler.aliyunConfigurePath,self.extensionCliHandler.credentials)
|
||||
_configurePath = os.path.join(self.extensionCliHandler.aliyunConfigurePath,self.extensionCliHandler.configure)
|
||||
config = dict()
|
||||
configContent = dict()
|
||||
- credentialsContent = dict ()
|
||||
- if os.path.exists(_configurePath):
|
||||
+ credentialsContent = dict ()
|
||||
+ if os.path.exists(_configurePath):
|
||||
for line in open(_configurePath):
|
||||
line = line.strip('\n')
|
||||
if line.find('=') > 0:
|
||||
list = line.split("=",1)
|
||||
- configContent[list[0]] = list[1]
|
||||
- else:
|
||||
- pass
|
||||
- config['configure'] = configContent
|
||||
- if os.path.exists(_credentialsPath):
|
||||
- for line in open(_credentialsPath):
|
||||
+ configContent[list[0]] = list[1]
|
||||
+ else:
|
||||
+ pass
|
||||
+ config['configure'] = configContent
|
||||
+ if os.path.exists(_credentialsPath):
|
||||
+ for line in open(_credentialsPath):
|
||||
line = line.strip('\n')
|
||||
if line.find('=') > 0:
|
||||
list = line.split("=",1)
|
||||
- credentialsContent[list[0]] = list[1]
|
||||
- else:
|
||||
- pass
|
||||
- config ['credentials'] = credentialsContent
|
||||
- response.display_response("showConfigure",config,'table')
|
||||
+ credentialsContent[list[0]] = list[1]
|
||||
+ else:
|
||||
+ pass
|
||||
+ config ['credentials'] = credentialsContent
|
||||
+ response.display_response("showConfigure",config,'table')
|
||||
def importConfig():
|
||||
pass
|
||||
def exportConfig():
|
||||
pass
|
||||
-
|
||||
+
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/advance/userProfileHandler.py b/bundled/aliyun/aliyun-cli/aliyuncli/advance/userProfileHandler.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/advance/userProfileHandler.py 2019-02-19 12:08:17.332785376 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/advance/userProfileHandler.py 2019-02-19 14:40:12.267806439 +0100
|
||||
@@ -20,7 +20,7 @@
|
||||
def handleProfileCmd(self, cmd, keyValues):
|
||||
if cmd.lower() == ProfileCmd.useProfile.lower(): # confirm command is right
|
||||
#check --name is valid
|
||||
- if keyValues.has_key(ProfileCmd.name) and len(keyValues[ProfileCmd.name]) > 0:
|
||||
+ if ProfileCmd.name in keyValues and len(keyValues[ProfileCmd.name]) > 0:
|
||||
_value = keyValues[ProfileCmd.name][0] # use the first value
|
||||
self.extensionCliHandler.setUserProfile(_value)
|
||||
else:
|
||||
@@ -34,7 +34,7 @@
|
||||
newProfileName = ''
|
||||
if cmd.lower() == ProfileCmd.addProfile.lower(): # confirm command is right
|
||||
#check --name is valid
|
||||
- if keyValues.has_key(ProfileCmd.name) and len(keyValues[ProfileCmd.name]) > 0:
|
||||
+ if ProfileCmd.name in keyValues and len(keyValues[ProfileCmd.name]) > 0:
|
||||
_value = keyValues[ProfileCmd.name][0] # check the first value
|
||||
# only input key and secret
|
||||
newProfileName = _value
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliParser.py b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliParser.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliParser.py 2019-02-19 12:08:17.332785376 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliParser.py 2019-02-19 14:35:32.009660989 +0100
|
||||
@@ -137,9 +137,9 @@
|
||||
values.append(self.args[index])
|
||||
index = index + 1
|
||||
keyValues[currentValue] = values
|
||||
- if keyValues.has_key(keystr) and keyValues[keystr].__len__() > 0:
|
||||
+ if keystr in keyValues and keyValues[keystr].__len__() > 0:
|
||||
_key = keyValues[keystr][0]
|
||||
- if keyValues.has_key(secretstr) and keyValues[secretstr].__len__() > 0:
|
||||
+ if secretstr in keyValues and keyValues[secretstr].__len__() > 0:
|
||||
_secret = keyValues[secretstr][0]
|
||||
#print("accesskeyid: ", _key , "accesskeysecret: ",_secret)
|
||||
return _key, _secret
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/aliyuncli.py b/bundled/aliyun/aliyun-cli/aliyuncli/aliyuncli.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/aliyuncli.py 2018-01-24 04:08:33.000000000 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/aliyuncli.py 2019-02-19 13:35:35.738680413 +0100
|
||||
@@ -19,8 +19,9 @@
|
||||
'''
|
||||
|
||||
import sys
|
||||
-reload(sys)
|
||||
-sys.setdefaultencoding('utf-8')
|
||||
+if sys.version_info[0] < 3:
|
||||
+ reload(sys)
|
||||
+ sys.setdefaultencoding('utf-8')
|
||||
__author__ = 'xixi.xxx'
|
||||
import aliyunCliMain
|
||||
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliUpgrade.py b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliUpgrade.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliUpgrade.py 2019-02-19 12:08:17.332785376 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunCliUpgrade.py 2019-02-19 11:15:19.920089641 +0100
|
||||
@@ -18,7 +18,7 @@
|
||||
'''
|
||||
|
||||
import aliyunCliConfiugre
|
||||
-import urllib2
|
||||
+import urllib3
|
||||
import re
|
||||
import os
|
||||
import platform
|
||||
@@ -151,7 +151,7 @@
|
||||
# this functino will get the latest version
|
||||
def _getLatestTimeFromServer(self):
|
||||
try:
|
||||
- f = urllib2.urlopen(self.configure.server_url,data=None,timeout=5)
|
||||
+ f = urllib3.urlopen(self.configure.server_url,data=None,timeout=5)
|
||||
s = f.read()
|
||||
return s
|
||||
except Exception as e:
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunOpenApiData.py b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunOpenApiData.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunOpenApiData.py 2019-02-19 12:08:17.332785376 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunOpenApiData.py 2019-02-19 14:37:28.221649497 +0100
|
||||
@@ -26,7 +26,7 @@
|
||||
import aliyunSdkConfigure
|
||||
import json
|
||||
import cliError
|
||||
-import urllib2
|
||||
+import urllib3
|
||||
import handleEndPoint
|
||||
|
||||
from __init__ import __version__
|
||||
@@ -259,7 +259,7 @@
|
||||
def changeEndPoint(self, classname, keyValues):
|
||||
endpoint = "Endpoint"
|
||||
try:
|
||||
- if keyValues.has_key(endpoint) and keyValues[endpoint].__len__() > 0:
|
||||
+ if endpoint in keyValues and keyValues[endpoint].__len__() > 0:
|
||||
classname._RestApi__domain = keyValues[endpoint][0]
|
||||
except Exception as e:
|
||||
pass
|
||||
@@ -444,10 +444,10 @@
|
||||
|
||||
def getTempVersion(self,keyValues):
|
||||
key='--version'
|
||||
- if keyValues is not None and keyValues.has_key(key):
|
||||
+ if keyValues is not None and key in keyValues:
|
||||
return keyValues.get(key)
|
||||
key = 'version'
|
||||
- if keyValues is not None and keyValues.has_key(key):
|
||||
+ if keyValues is not None and key in keyValues:
|
||||
return keyValues.get(key)
|
||||
|
||||
def getVersionFromFile(self,cmd):
|
||||
@@ -513,7 +513,7 @@
|
||||
self.checkForServer(response,cmd,operation)
|
||||
def getRequestId(self,response):
|
||||
try:
|
||||
- if response.has_key('RequestId') and len(response['RequestId']) > 0:
|
||||
+ if 'RequestId' in response and len(response['RequestId']) > 0:
|
||||
requestId = response['RequestId']
|
||||
return requestId
|
||||
except Exception:
|
||||
@@ -532,7 +532,7 @@
|
||||
ua = ""
|
||||
url = configure.server_url + "?requesId=" + requestId + "&ak=" + ak +"&ua="+ua+"&cmd="+cmd+"&operation="+operation
|
||||
try:
|
||||
- f = urllib2.urlopen(url,data=None,timeout=5)
|
||||
+ f = urllib3.urlopen(url,data=None,timeout=5)
|
||||
s = f.read()
|
||||
return s
|
||||
except Exception :
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunSdkConfigure.py b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunSdkConfigure.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/aliyunSdkConfigure.py 2019-02-19 12:08:17.333785359 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/aliyunSdkConfigure.py 2019-02-19 14:38:04.032029661 +0100
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
def sdkConfigure(self,cmd,operation):
|
||||
keyValues = self.parser._getKeyValues()
|
||||
- if keyValues.has_key('--version') and len(keyValues['--version']) > 0:
|
||||
+ if '--version' in keyValues and len(keyValues['--version']) > 0:
|
||||
version=keyValues['--version'][0]
|
||||
filename=self.fileName
|
||||
self.writeCmdVersionToFile(cmd,version,filename)
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/configure.py b/bundled/aliyun/aliyun-cli/aliyuncli/configure.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/configure.py 2019-02-19 12:08:17.333785359 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/configure.py 2019-02-19 11:12:58.670708353 +0100
|
||||
@@ -23,6 +23,8 @@
|
||||
import aliyunCliParser
|
||||
import platform
|
||||
|
||||
+if sys.version_info[0] > 2:
|
||||
+ raw_input = input
|
||||
|
||||
OSS_CREDS_FILENAME = "%s/.aliyuncli/osscredentials" % os.path.expanduser('~')
|
||||
OSS_CONFIG_SECTION = 'OSSCredentials'
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/paramOptimize.py b/bundled/aliyun/aliyun-cli/aliyuncli/paramOptimize.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/paramOptimize.py 2019-02-19 12:08:17.333785359 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/paramOptimize.py 2019-02-19 11:14:58.926181598 +0100
|
||||
@@ -19,7 +19,7 @@
|
||||
#/usr/bin/env python
|
||||
#!-*- coding:utf-8 -*-
|
||||
import os
|
||||
-import urllib2
|
||||
+import urllib3
|
||||
import cliError
|
||||
|
||||
|
||||
@@ -64,9 +64,9 @@
|
||||
print(e)
|
||||
def _getParamFromUrl(prefix,value,mode):
|
||||
|
||||
- req = urllib2.Request(value)
|
||||
+ req = urllib3.Request(value)
|
||||
try:
|
||||
- response=urllib2.urlopen(req)
|
||||
+ response=urllib3.urlopen(req)
|
||||
if response.getcode() == 200:
|
||||
return response.read()
|
||||
else:
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/aliyuncli/six.py b/bundled/aliyun/aliyun-cli/aliyuncli/six.py
|
||||
--- a/bundled/aliyun/aliyun-cli/aliyuncli/six.py 2018-01-24 04:08:33.000000000 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/aliyuncli/six.py 2019-02-19 11:14:40.505262286 +0100
|
||||
@@ -340,8 +340,8 @@
|
||||
|
||||
|
||||
_urllib_error_moved_attributes = [
|
||||
- MovedAttribute("URLError", "urllib2", "urllib.error"),
|
||||
- MovedAttribute("HTTPError", "urllib2", "urllib.error"),
|
||||
+ MovedAttribute("URLError", "urllib3", "urllib.error"),
|
||||
+ MovedAttribute("HTTPError", "urllib3", "urllib.error"),
|
||||
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
|
||||
]
|
||||
for attr in _urllib_error_moved_attributes:
|
||||
@@ -359,34 +359,34 @@
|
||||
|
||||
|
||||
_urllib_request_moved_attributes = [
|
||||
- MovedAttribute("urlopen", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("install_opener", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("build_opener", "urllib2", "urllib.request"),
|
||||
+ MovedAttribute("urlopen", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("install_opener", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("build_opener", "urllib3", "urllib.request"),
|
||||
MovedAttribute("pathname2url", "urllib", "urllib.request"),
|
||||
MovedAttribute("url2pathname", "urllib", "urllib.request"),
|
||||
MovedAttribute("getproxies", "urllib", "urllib.request"),
|
||||
- MovedAttribute("Request", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("FileHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
|
||||
- MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
||||
+ MovedAttribute("Request", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("OpenerDirector", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPDefaultErrorHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPRedirectHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPCookieProcessor", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("ProxyHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("BaseHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPPasswordMgr", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("AbstractBasicAuthHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPBasicAuthHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("ProxyBasicAuthHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("AbstractDigestAuthHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPDigestAuthHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("ProxyDigestAuthHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPSHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("FileHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("FTPHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("CacheFTPHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("UnknownHandler", "urllib3", "urllib.request"),
|
||||
+ MovedAttribute("HTTPErrorProcessor", "urllib3", "urllib.request"),
|
||||
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
||||
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
||||
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
||||
diff -uNr a/bundled/aliyun/aliyun-cli/setup.py b/bundled/aliyun/aliyun-cli/setup.py
|
||||
--- a/bundled/aliyun/aliyun-cli/setup.py 2018-01-24 04:08:33.000000000 +0100
|
||||
+++ b/bundled/aliyun/aliyun-cli/setup.py 2019-02-19 13:33:29.069848394 +0100
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
install_requires = [
|
||||
'colorama>=0.2.5,<=0.3.3',
|
||||
- 'jmespath>=0.7.0,<=0.7.1',
|
||||
+ 'jmespath>=0.7.0',
|
||||
]
|
||||
def main():
|
||||
setup(
|
@ -1,14 +0,0 @@
|
||||
--- a/bundled/gcp/google-cloud-sdk/bin/gcloud 1980-01-01 09:00:00.000000000 +0100
|
||||
+++ b/bundled/gcp/google-cloud-sdk/bin/gcloud 2021-10-14 11:30:17.726138166 +0200
|
||||
@@ -128,6 +128,11 @@
|
||||
fi
|
||||
}
|
||||
|
||||
+if [ -z "$CLOUDSDK_PYTHON" ]; then
|
||||
+ CLOUDSDK_PYTHON="/usr/libexec/platform-python"
|
||||
+ CLOUDSDK_PYTHON_SITEPACKAGES=1
|
||||
+fi
|
||||
+
|
||||
setup_cloudsdk_python
|
||||
|
||||
# $PYTHONHOME can interfere with gcloud. Users should use
|
@ -1,68 +0,0 @@
|
||||
From fcceb714085836de9db4493b527e94d85dd72626 Mon Sep 17 00:00:00 2001
|
||||
From: ut002970 <liuxingwei@uniontech.com>
|
||||
Date: Wed, 6 Sep 2023 15:27:05 +0800
|
||||
Subject: [PATCH 1/3] modify error message
|
||||
|
||||
---
|
||||
heartbeat/mysql-common.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/mysql-common.sh b/heartbeat/mysql-common.sh
|
||||
index 8104019b03..a93acc4c60 100755
|
||||
--- a/heartbeat/mysql-common.sh
|
||||
+++ b/heartbeat/mysql-common.sh
|
||||
@@ -254,7 +254,7 @@ mysql_common_start()
|
||||
while [ $start_wait = 1 ]; do
|
||||
if ! ps $pid > /dev/null 2>&1; then
|
||||
wait $pid
|
||||
- ocf_exit_reason "MySQL server failed to start (pid=$pid) (rc=$?), please check your installation"
|
||||
+ ocf_exit_reason "MySQL server failed to start (pid=$pid) (rc=$?), please check your installation, log message you can check $OCF_RESKEY_log"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
mysql_common_status info
|
||||
|
||||
From 8f9b344cd5b3cb96ea0f94b7ab0306da2234ac00 Mon Sep 17 00:00:00 2001
|
||||
From: ut002970 <liuxingwei@uniontech.com>
|
||||
Date: Wed, 6 Sep 2023 15:56:24 +0800
|
||||
Subject: [PATCH 2/3] modify error message
|
||||
|
||||
---
|
||||
heartbeat/mysql-common.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/mysql-common.sh b/heartbeat/mysql-common.sh
|
||||
index a93acc4c60..d5b2286737 100755
|
||||
--- a/heartbeat/mysql-common.sh
|
||||
+++ b/heartbeat/mysql-common.sh
|
||||
@@ -254,7 +254,7 @@ mysql_common_start()
|
||||
while [ $start_wait = 1 ]; do
|
||||
if ! ps $pid > /dev/null 2>&1; then
|
||||
wait $pid
|
||||
- ocf_exit_reason "MySQL server failed to start (pid=$pid) (rc=$?), please check your installation, log message you can check $OCF_RESKEY_log"
|
||||
+ ocf_exit_reason "MySQL server failed to start (pid=$pid) (rc=$?), Check $OCF_RESKEY_log for details"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
mysql_common_status info
|
||||
|
||||
From a292b3c552bf3f2beea5f73e0d171546c0a1273c Mon Sep 17 00:00:00 2001
|
||||
From: ut002970 <liuxingwei@uniontech.com>
|
||||
Date: Wed, 6 Sep 2023 16:10:48 +0800
|
||||
Subject: [PATCH 3/3] modify error message
|
||||
|
||||
---
|
||||
heartbeat/mysql-common.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/mysql-common.sh b/heartbeat/mysql-common.sh
|
||||
index d5b2286737..d6b4e3cdf4 100755
|
||||
--- a/heartbeat/mysql-common.sh
|
||||
+++ b/heartbeat/mysql-common.sh
|
||||
@@ -254,7 +254,7 @@ mysql_common_start()
|
||||
while [ $start_wait = 1 ]; do
|
||||
if ! ps $pid > /dev/null 2>&1; then
|
||||
wait $pid
|
||||
- ocf_exit_reason "MySQL server failed to start (pid=$pid) (rc=$?), Check $OCF_RESKEY_log for details"
|
||||
+ ocf_exit_reason "MySQL server failed to start (pid=$pid) (rc=$?). Check $OCF_RESKEY_log for details"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
mysql_common_status info
|
@ -1,195 +0,0 @@
|
||||
From 640c2b57f0f3e7256d587ddd5960341cb38b1982 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Sun, 13 Dec 2020 14:58:34 -0800
|
||||
Subject: [PATCH] LVM-activate: Fix return codes
|
||||
|
||||
OCF_ERR_ARGS should be used when the configuration isn't valid for the
|
||||
**local** node, and so the resource should not attempt to start again
|
||||
locally until the issue is corrected.
|
||||
|
||||
OCF_ERR_CONFIGURED should be used when the configuration isn't valid on
|
||||
**any** node, and so the resource should not attempt to start again
|
||||
anywhere until the issue is corrected.
|
||||
|
||||
One remaining gray area: Should lvmlockd/lvmetad/clvmd improperly
|
||||
running (or improperly not running) be an OCF_ERR_GENERIC or
|
||||
OCF_ERR_ARGS? The fact that it's a state issue rather than a config
|
||||
issue suggests OCF_ERR_GENERIC. The fact that it won't be fixed without
|
||||
user intervention suggests OCF_ERR_ARGS. The approach here is to use
|
||||
GENERIC for all of these. One can make the case that "improperly
|
||||
running" should use ARGS, since a process must be manually stopped to
|
||||
fix the issue, and that "improperly not running" should use GENERIC,
|
||||
since there's a small chance the process died and will be recovered in
|
||||
some way.
|
||||
|
||||
More info about return code meanings:
|
||||
- https://clusterlabs.org/pacemaker/doc/2.1/Pacemaker_Administration/html/agents.html#how-are-ocf-return-codes-interpreted
|
||||
|
||||
Resolves: RHBZ#1905820
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
heartbeat/LVM-activate | 47 +++++++++++++++++++++---------------------
|
||||
1 file changed, 23 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/LVM-activate b/heartbeat/LVM-activate
|
||||
index c86606637..e951a08e9 100755
|
||||
--- a/heartbeat/LVM-activate
|
||||
+++ b/heartbeat/LVM-activate
|
||||
@@ -333,8 +333,7 @@ config_verify()
|
||||
real=$(lvmconfig "$name" | cut -d'=' -f2)
|
||||
if [ "$real" != "$expect" ]; then
|
||||
ocf_exit_reason "config item $name: expect=$expect but real=$real"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
-
|
||||
+ exit $OCF_ERR_ARGS
|
||||
fi
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -366,12 +365,12 @@ lvmlockd_check()
|
||||
fi
|
||||
|
||||
ocf_exit_reason "lvmlockd daemon is not running!"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
if pgrep clvmd >/dev/null 2>&1 ; then
|
||||
ocf_exit_reason "clvmd daemon is running unexpectedly."
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -402,17 +401,17 @@ clvmd_check()
|
||||
# Good: clvmd is running, and lvmlockd is not running
|
||||
if ! pgrep clvmd >/dev/null 2>&1 ; then
|
||||
ocf_exit_reason "clvmd daemon is not running!"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
if pgrep lvmetad >/dev/null 2>&1 ; then
|
||||
ocf_exit_reason "Please stop lvmetad daemon when clvmd is running."
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
if pgrep lvmlockd >/dev/null 2>&1 ; then
|
||||
ocf_exit_reason "lvmlockd daemon is running unexpectedly."
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -424,12 +423,12 @@ systemid_check()
|
||||
source=$(lvmconfig 'global/system_id_source' 2>/dev/null | cut -d"=" -f2)
|
||||
if [ "$source" = "" ] || [ "$source" = "none" ]; then
|
||||
ocf_exit_reason "system_id_source in lvm.conf is not set correctly!"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_ARGS
|
||||
fi
|
||||
|
||||
if [ -z ${SYSTEM_ID} ]; then
|
||||
ocf_exit_reason "local/system_id is not set!"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_ARGS
|
||||
fi
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -441,18 +440,18 @@ tagging_check()
|
||||
# The volume_list must be initialized to something in order to
|
||||
# guarantee our tag will be filtered on startup
|
||||
if ! lvm dumpconfig activation/volume_list; then
|
||||
- ocf_log err "LVM: Improper setup detected"
|
||||
+ ocf_log err "LVM: Improper setup detected"
|
||||
ocf_exit_reason "The volume_list filter must be initialized in lvm.conf for exclusive activation without clvmd"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_ARGS
|
||||
fi
|
||||
|
||||
# Our tag must _NOT_ be in the volume_list. This agent
|
||||
# overrides the volume_list during activation using the
|
||||
# special tag reserved for cluster activation
|
||||
if lvm dumpconfig activation/volume_list | grep -e "\"@${OUR_TAG}\"" -e "\"${VG}\""; then
|
||||
- ocf_log err "LVM: Improper setup detected"
|
||||
+ ocf_log err "LVM: Improper setup detected"
|
||||
ocf_exit_reason "The volume_list in lvm.conf must not contain the cluster tag, \"${OUR_TAG}\", or volume group, ${VG}"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_ARGS
|
||||
fi
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -463,13 +462,13 @@ read_parameters()
|
||||
if [ -z "$VG" ]
|
||||
then
|
||||
ocf_exit_reason "You must identify the volume group name!"
|
||||
- exit $OCF_ERR_ARGS
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
if [ "$LV_activation_mode" != "shared" ] && [ "$LV_activation_mode" != "exclusive" ]
|
||||
then
|
||||
ocf_exit_reason "Invalid value for activation_mode: $LV_activation_mode"
|
||||
- exit $OCF_ERR_ARGS
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
# Convert VG_access_mode from string to index
|
||||
@@ -519,8 +518,10 @@ lvm_validate() {
|
||||
exit $OCF_NOT_RUNNING
|
||||
fi
|
||||
|
||||
+ # Could be a transient error (e.g., iSCSI connection
|
||||
+ # issue) so use OCF_ERR_GENERIC
|
||||
ocf_exit_reason "Volume group[${VG}] doesn't exist, or not visible on this node!"
|
||||
- exit $OCF_ERR_CONFIGURED
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
# Inconsistency might be due to missing physical volumes, which doesn't
|
||||
@@ -549,7 +550,7 @@ lvm_validate() {
|
||||
mode=$?
|
||||
if [ $VG_access_mode_num -ne 4 ] && [ $mode -ne $VG_access_mode_num ]; then
|
||||
ocf_exit_reason "The specified vg_access_mode doesn't match the lock_type on VG metadata!"
|
||||
- exit $OCF_ERR_ARGS
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
# Nothing to do if the VG has no logical volume
|
||||
@@ -561,11 +562,11 @@ lvm_validate() {
|
||||
|
||||
# Check if the given $LV is in the $VG
|
||||
if [ -n "$LV" ]; then
|
||||
- OUT=$(lvs --foreign --noheadings ${VG}/${LV} 2>&1)
|
||||
+ output=$(lvs --foreign --noheadings ${VG}/${LV} 2>&1)
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_log err "lvs: ${OUT}"
|
||||
+ ocf_log err "lvs: ${output}"
|
||||
ocf_exit_reason "LV ($LV) is not in the given VG ($VG)."
|
||||
- exit $OCF_ERR_ARGS
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -580,7 +581,6 @@ lvm_validate() {
|
||||
3)
|
||||
systemid_check
|
||||
;;
|
||||
-
|
||||
4)
|
||||
tagging_check
|
||||
;;
|
||||
@@ -808,10 +808,9 @@ lvm_status() {
|
||||
dd if=${dm_name} of=/dev/null bs=1 count=1 >/dev/null \
|
||||
2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
- return $OCF_NOT_RUNNING
|
||||
- else
|
||||
- return $OCF_SUCCESS
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
+ return $OCF_SUCCESS
|
||||
;;
|
||||
*)
|
||||
ocf_exit_reason "unsupported monitor level $OCF_CHECK_LEVEL"
|
@ -1,55 +0,0 @@
|
||||
From bb5cfa172ca58cd8adcedcaca92bde54d0645661 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 14 Jul 2022 10:55:19 +0200
|
||||
Subject: [PATCH] openstack-agents: set domain parameter's default to Default
|
||||
and fix missing parameter name in ocf_exit_reason
|
||||
|
||||
---
|
||||
heartbeat/openstack-common.sh | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/openstack-common.sh b/heartbeat/openstack-common.sh
|
||||
index b6eec09c..14d290bd 100644
|
||||
--- a/heartbeat/openstack-common.sh
|
||||
+++ b/heartbeat/openstack-common.sh
|
||||
@@ -1,6 +1,10 @@
|
||||
+OCF_RESKEY_user_domain_name_default="Default"
|
||||
+OCF_RESKEY_project_domain_name_default="Default"
|
||||
OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
|
||||
OCF_RESKEY_insecure_default="false"
|
||||
|
||||
+: ${OCF_RESKEY_user_domain_name=${OCF_RESKEY_user_domain_name_default}}
|
||||
+: ${OCF_RESKEY_project_domain_name=${OCF_RESKEY_project_domain_name_default}}
|
||||
: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
|
||||
: ${OCF_RESKEY_insecure=${OCF_RESKEY_insecure_default}}
|
||||
|
||||
@@ -64,7 +68,7 @@ Keystone Project.
|
||||
Keystone User Domain Name.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Keystone User Domain Name</shortdesc>
|
||||
-<content type="string" />
|
||||
+<content type="string" default="${OCF_RESKEY_user_domain_name_default}" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="project_domain_name" required="0">
|
||||
@@ -72,7 +76,7 @@ Keystone User Domain Name.
|
||||
Keystone Project Domain Name.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Keystone Project Domain Name</shortdesc>
|
||||
-<content type="string" />
|
||||
+<content type="string" default="${OCF_RESKEY_project_domain_name_default}" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="openstackcli">
|
||||
@@ -133,7 +137,7 @@ get_config() {
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
if [ -z "$OCF_RESKEY_project_domain_name" ]; then
|
||||
- ocf_exit_reason " not set"
|
||||
+ ocf_exit_reason "project_domain_name not set"
|
||||
exit $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
--
|
||||
2.36.1
|
||||
|
@ -1,282 +0,0 @@
|
||||
From ebea4c3620261c529cad908c0e52064df84b0c61 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 11 Jul 2022 10:28:11 +0200
|
||||
Subject: [PATCH] openstack-agents: warn when openstackcli is slow
|
||||
|
||||
---
|
||||
heartbeat/openstack-cinder-volume | 19 +++++++++++--------
|
||||
heartbeat/openstack-common.sh | 22 ++++++++++++++++++++++
|
||||
heartbeat/openstack-floating-ip | 17 ++++++++++-------
|
||||
heartbeat/openstack-info.in | 20 ++++++++++----------
|
||||
heartbeat/openstack-virtual-ip | 20 ++++++++++----------
|
||||
5 files changed, 63 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/openstack-cinder-volume b/heartbeat/openstack-cinder-volume
|
||||
index 19bf04faf..116442c41 100755
|
||||
--- a/heartbeat/openstack-cinder-volume
|
||||
+++ b/heartbeat/openstack-cinder-volume
|
||||
@@ -113,11 +113,14 @@ _get_node_id() {
|
||||
}
|
||||
|
||||
osvol_validate() {
|
||||
+ local result
|
||||
+
|
||||
check_binary "$OCF_RESKEY_openstackcli"
|
||||
|
||||
get_config
|
||||
|
||||
- if ! $OCF_RESKEY_openstackcli volume list|grep -q $OCF_RESKEY_volume_id ; then
|
||||
+ result=$(run_openstackcli "volume list")
|
||||
+ if ! echo "$result" | grep -q $OCF_RESKEY_volume_id; then
|
||||
ocf_exit_reason "volume-id $OCF_RESKEY_volume_id not found"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -156,17 +159,17 @@ osvol_monitor() {
|
||||
# Is the volue attached?
|
||||
# We use the API
|
||||
#
|
||||
- result=$($OCF_RESKEY_openstackcli volume show \
|
||||
+ result=$(run_openstackcli "volume show \
|
||||
--column status \
|
||||
--column attachments \
|
||||
--format value \
|
||||
- $OCF_RESKEY_volume_id)
|
||||
+ $OCF_RESKEY_volume_id")
|
||||
|
||||
- if echo "$result" | grep -q available ; then
|
||||
+ if echo "$result" | grep -q available; then
|
||||
ocf_log warn "$OCF_RESKEY_volume_id is not attached to any instance"
|
||||
return $OCF_NOT_RUNNING
|
||||
else
|
||||
- export attached_server_id=$(echo $result|head -n1|
|
||||
+ export attached_server_id=$(echo "$result"|head -n1|
|
||||
grep -P -o "'server_id': '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}'"|
|
||||
grep -P -o "[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}")
|
||||
ocf_log info "$OCF_RESKEY_volume_id is attached to instance $attached_server_id"
|
||||
@@ -199,7 +202,7 @@ osvol_stop() {
|
||||
#
|
||||
# Detach the volume
|
||||
#
|
||||
- if ! $OCF_RESKEY_openstackcli server remove volume $node_id $OCF_RESKEY_volume_id ; then
|
||||
+ if ! run_openstackcli "server remove volume $node_id $OCF_RESKEY_volume_id"; then
|
||||
ocf_log error "Couldn't remove volume $OCF_RESKEY_volume_id from instance $node_id"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
@@ -225,7 +228,7 @@ osvol_start() {
|
||||
# TODO: make it optional in case multi-attachment is allowed by Cinder
|
||||
#
|
||||
if [ ! -z $attached_server_id ] ; then
|
||||
- if ! $OCF_RESKEY_openstackcli server remove volume $attached_server_id $OCF_RESKEY_volume_id ; then
|
||||
+ if ! run_openstackcli "server remove volume $attached_server_id $OCF_RESKEY_volume_id"; then
|
||||
ocf_log error "Couldn't remove volume $OCF_RESKEY_volume_id from instance $attached_server_id"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
@@ -238,7 +241,7 @@ osvol_start() {
|
||||
#
|
||||
# Attach the volume
|
||||
#
|
||||
- $OCF_RESKEY_openstackcli server add volume $node_id $OCF_RESKEY_volume_id
|
||||
+ run_openstackcli "server add volume $node_id $OCF_RESKEY_volume_id"
|
||||
if [ $? != $OCF_SUCCESS ]; then
|
||||
ocf_log error "Couldn't add volume $OCF_RESKEY_volume_id to instance $node_id"
|
||||
return $OCF_ERR_GENERIC
|
||||
diff --git a/heartbeat/openstack-common.sh b/heartbeat/openstack-common.sh
|
||||
index 4763c90db..b6eec09c2 100644
|
||||
--- a/heartbeat/openstack-common.sh
|
||||
+++ b/heartbeat/openstack-common.sh
|
||||
@@ -145,3 +145,25 @@ get_config() {
|
||||
OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-project-domain-name $OCF_RESKEY_project_domain_name"
|
||||
fi
|
||||
}
|
||||
+
|
||||
+run_openstackcli() {
|
||||
+ local cmd="${OCF_RESKEY_openstackcli} $1"
|
||||
+ local result
|
||||
+ local rc
|
||||
+ local start_time=$(date +%s)
|
||||
+ local end_time
|
||||
+ local elapsed_time
|
||||
+
|
||||
+ result=$($cmd)
|
||||
+ rc=$?
|
||||
+ end_time=$(date +%s)
|
||||
+ elapsed_time=$(expr $end_time - $start_time)
|
||||
+
|
||||
+ if [ $elapsed_time -gt 20 ]; then
|
||||
+ ocf_log warn "$cmd took ${elapsed_time}s to complete"
|
||||
+ fi
|
||||
+
|
||||
+ echo "$result"
|
||||
+
|
||||
+ return $rc
|
||||
+}
|
||||
diff --git a/heartbeat/openstack-floating-ip b/heartbeat/openstack-floating-ip
|
||||
index 6e2895654..7317f19a8 100755
|
||||
--- a/heartbeat/openstack-floating-ip
|
||||
+++ b/heartbeat/openstack-floating-ip
|
||||
@@ -101,11 +101,14 @@ END
|
||||
}
|
||||
|
||||
osflip_validate() {
|
||||
+ local result
|
||||
+
|
||||
check_binary "$OCF_RESKEY_openstackcli"
|
||||
|
||||
get_config
|
||||
|
||||
- if ! $OCF_RESKEY_openstackcli floating ip list|grep -q $OCF_RESKEY_ip_id ; then
|
||||
+ result=$(run_openstackcli "floating ip list")
|
||||
+ if ! echo "$result" | grep -q $OCF_RESKEY_ip_id; then
|
||||
ocf_exit_reason "ip-id $OCF_RESKEY_ip_id not found"
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
@@ -132,14 +135,14 @@ osflip_monitor() {
|
||||
| awk '{gsub("[^ ]*:", "");print}')
|
||||
|
||||
# Is the IP active and attached?
|
||||
- result=$($OCF_RESKEY_openstackcli floating ip show \
|
||||
+ result=$(run_openstackcli "floating ip show \
|
||||
--column port_id --column floating_ip_address \
|
||||
--format yaml \
|
||||
- $OCF_RESKEY_ip_id)
|
||||
+ $OCF_RESKEY_ip_id")
|
||||
|
||||
for port in $node_port_ids ; do
|
||||
- if echo $result | grep -q $port ; then
|
||||
- floating_ip=$(echo $result | awk '/floating_ip_address/ {print $2}')
|
||||
+ if echo "$result" | grep -q $port ; then
|
||||
+ floating_ip=$(echo "$result" | awk '/floating_ip_address/ {print $2}')
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n openstack_floating_ip -v $floating_ip
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -160,7 +163,7 @@ osflip_stop() {
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- if ! $OCF_RESKEY_openstackcli floating ip unset --port $OCF_RESKEY_ip_id ; then
|
||||
+ if ! run_openstackcli "floating ip unset --port $OCF_RESKEY_ip_id"; then
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -194,7 +197,7 @@ osflip_start() {
|
||||
|
||||
ocf_log info "Moving IP address $OCF_RESKEY_ip_id to port ID $node_port_id"
|
||||
|
||||
- $OCF_RESKEY_openstackcli floating ip set --port $node_port_id $OCF_RESKEY_ip_id
|
||||
+ run_openstackcli "floating ip set --port $node_port_id $OCF_RESKEY_ip_id"
|
||||
if [ $? != $OCF_SUCCESS ]; then
|
||||
ocf_log error "$OCF_RESKEY_ip_id Cannot be set to port $node_port_id"
|
||||
return $OCF_ERR_GENERIC
|
||||
diff --git a/heartbeat/openstack-info.in b/heartbeat/openstack-info.in
|
||||
index f3a59fc7a..6502f1df1 100755
|
||||
--- a/heartbeat/openstack-info.in
|
||||
+++ b/heartbeat/openstack-info.in
|
||||
@@ -119,9 +119,7 @@ END
|
||||
#######################################################################
|
||||
|
||||
OSInfoStats() {
|
||||
- local result
|
||||
local value
|
||||
- local node
|
||||
local node_id
|
||||
|
||||
get_config
|
||||
@@ -141,31 +139,33 @@ OSInfoStats() {
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_id -v "$node_id"
|
||||
|
||||
# Nova data: flavor
|
||||
- value=$($OCF_RESKEY_openstackcli server show \
|
||||
+ value=$(run_openstackcli "server show \
|
||||
--format value \
|
||||
--column flavor \
|
||||
- $node_id)
|
||||
+ $node_id")
|
||||
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_flavor -v "$value"
|
||||
|
||||
# Nova data: availability zone
|
||||
- value=$($OCF_RESKEY_openstackcli server show \
|
||||
+ value=$(run_openstackcli "server show \
|
||||
--format value \
|
||||
--column OS-EXT-AZ:availability_zone \
|
||||
- $node_id)
|
||||
+ $node_id")
|
||||
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_az -v "$value"
|
||||
|
||||
# Network data: ports
|
||||
value=""
|
||||
- for port_id in $($OCF_RESKEY_openstackcli port list \
|
||||
+ for port_id in $(run_openstackcli "port list \
|
||||
--format value \
|
||||
--column id \
|
||||
- --server $node_id); do
|
||||
- subnet_id=$($OCF_RESKEY_openstackcli port show \
|
||||
+ --server $node_id"); do
|
||||
+ subnet_result=$(run_openstackcli "port show \
|
||||
--format json \
|
||||
--column fixed_ips \
|
||||
- ${port_id} | grep -P '\"subnet_id\": \".*\",$' |
|
||||
+ ${port_id}")
|
||||
+ subnet_id=$(echo "$subnet_result" |
|
||||
+ grep -P '\"subnet_id\": \".*\",$' |
|
||||
grep -P -o '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}')
|
||||
value="${value}${subnet_id}:${port_id},"
|
||||
done
|
||||
diff --git a/heartbeat/openstack-virtual-ip b/heartbeat/openstack-virtual-ip
|
||||
index c654d980a..361357d55 100755
|
||||
--- a/heartbeat/openstack-virtual-ip
|
||||
+++ b/heartbeat/openstack-virtual-ip
|
||||
@@ -132,11 +132,11 @@ osvip_monitor() {
|
||||
|
||||
node_port_id=$(osvip_port_id)
|
||||
|
||||
- result=$($OCF_RESKEY_openstackcli port show \
|
||||
+ result=$(run_openstackcli "port show \
|
||||
--format value \
|
||||
--column allowed_address_pairs \
|
||||
- ${node_port_id})
|
||||
- if echo $result | grep -q "$OCF_RESKEY_ip"; then
|
||||
+ ${node_port_id}")
|
||||
+ if echo "$result" | grep -q "$OCF_RESKEY_ip"; then
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n openstack_virtual_ip -v $OCF_RESKEY_ip
|
||||
|
||||
return $OCF_SUCCESS
|
||||
@@ -158,20 +158,20 @@ osvip_stop() {
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- mac_address=$($OCF_RESKEY_openstackcli port show \
|
||||
+ mac_address=$(run_openstackcli "port show \
|
||||
--format value \
|
||||
--column mac_address \
|
||||
- $node_port_id)
|
||||
- echo ${mac_address} | grep -q -P "^([0-9a-f]{2}:){5}[0-9a-f]{2}$"
|
||||
+ $node_port_id")
|
||||
+ echo "${mac_address}" | grep -q -P "^([0-9a-f]{2}:){5}[0-9a-f]{2}$"
|
||||
if [ $? -ne 0 ]; then
|
||||
ocf_log error "MAC address '${mac_address}' is not valid."
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
- if ! $OCF_RESKEY_openstackcli port unset \
|
||||
+ if ! run_openstackcli "port unset \
|
||||
--allowed-address \
|
||||
ip-address=$OCF_RESKEY_ip,mac-address=${mac_address} \
|
||||
- $node_port_id; then
|
||||
+ $node_port_id"; then
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
@@ -196,9 +196,9 @@ osvip_start() {
|
||||
|
||||
ocf_log info "Moving IP address $OCF_RESKEY_ip to port ID $node_port_id"
|
||||
|
||||
- $OCF_RESKEY_openstackcli port set \
|
||||
+ run_openstackcli "port set \
|
||||
--allowed-address ip-address=$OCF_RESKEY_ip \
|
||||
- $node_port_id
|
||||
+ $node_port_id"
|
||||
if [ $? != $OCF_SUCCESS ]; then
|
||||
ocf_log error "$OCF_RESKEY_ip Cannot be set to port $node_port_id"
|
||||
return $OCF_ERR_GENERIC
|
@ -1,770 +0,0 @@
|
||||
diff --color -uNr a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
--- a/heartbeat/Makefile.am 2022-03-15 16:14:29.355209012 +0100
|
||||
+++ b/heartbeat/Makefile.am 2022-03-15 16:18:35.917048467 +0100
|
||||
@@ -217,6 +217,7 @@
|
||||
lvm-clvm.sh \
|
||||
lvm-plain.sh \
|
||||
lvm-tag.sh \
|
||||
+ openstack-common.sh \
|
||||
ora-common.sh \
|
||||
mysql-common.sh \
|
||||
nfsserver-redhat.sh \
|
||||
diff --color -uNr a/heartbeat/openstack-cinder-volume b/heartbeat/openstack-cinder-volume
|
||||
--- a/heartbeat/openstack-cinder-volume 2022-03-15 16:14:29.370209063 +0100
|
||||
+++ b/heartbeat/openstack-cinder-volume 2022-03-15 16:17:36.231840008 +0100
|
||||
@@ -34,11 +34,11 @@
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
+. ${OCF_FUNCTIONS_DIR}/openstack-common.sh
|
||||
+
|
||||
# Defaults
|
||||
-OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
|
||||
OCF_RESKEY_volume_local_check_default="true"
|
||||
|
||||
-: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
|
||||
: ${OCF_RESKEY_volume_local_check=${OCF_RESKEY_volume_local_check_default}}
|
||||
|
||||
#######################################################################
|
||||
@@ -68,14 +68,11 @@
|
||||
<shortdesc lang="en">Attach a cinder volume</shortdesc>
|
||||
|
||||
<parameters>
|
||||
-<parameter name="openstackcli">
|
||||
-<longdesc lang="en">
|
||||
-Path to command line tools for openstack.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Path to Openstack CLI tool</shortdesc>
|
||||
-<content type="string" default="${OCF_RESKEY_openstackcli_default}" />
|
||||
-</parameter>
|
||||
+END
|
||||
|
||||
+common_meta_data
|
||||
+
|
||||
+cat <<END
|
||||
<parameter name="volume_local_check">
|
||||
<longdesc lang="en">
|
||||
This option allows the cluster to monitor the cinder volume presence without
|
||||
@@ -85,28 +82,19 @@
|
||||
<content type="boolean" default="${OCF_RESKEY_volume_local_check_default}" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="openrc" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Valid Openstack credentials as openrc file from api_access/openrc.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">openrc file</shortdesc>
|
||||
-<content type="string" />
|
||||
-</parameter>
|
||||
-
|
||||
<parameter name="volume_id" required="1">
|
||||
<longdesc lang="en">
|
||||
-Cinder volume identifier to use to attach the bloc storage.
|
||||
+Cinder volume identifier to use to attach the block storage.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Volume ID</shortdesc>
|
||||
<content type="string" />
|
||||
</parameter>
|
||||
-
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
<action name="start" timeout="180s" />
|
||||
<action name="stop" timeout="180s" />
|
||||
-<action name="monitor" depth="0" timeout="30s" interval="60s" />
|
||||
+<action name="monitor" depth="0" timeout="180s" interval="60s" />
|
||||
<action name="validate-all" timeout="5s" />
|
||||
<action name="meta-data" timeout="5s" />
|
||||
</actions>
|
||||
@@ -127,17 +115,7 @@
|
||||
osvol_validate() {
|
||||
check_binary "$OCF_RESKEY_openstackcli"
|
||||
|
||||
- if [ -z "$OCF_RESKEY_openrc" ]; then
|
||||
- ocf_exit_reason "openrc parameter not set"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- if [ ! -f "$OCF_RESKEY_openrc" ] ; then
|
||||
- ocf_exit_reason "openrc file not found"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- . $OCF_RESKEY_openrc
|
||||
+ get_config
|
||||
|
||||
if ! $OCF_RESKEY_openstackcli volume list|grep -q $OCF_RESKEY_volume_id ; then
|
||||
ocf_exit_reason "volume-id $OCF_RESKEY_volume_id not found"
|
||||
diff --color -uNr a/heartbeat/openstack-common.sh b/heartbeat/openstack-common.sh
|
||||
--- a/heartbeat/openstack-common.sh 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/heartbeat/openstack-common.sh 2022-03-15 16:17:36.232840011 +0100
|
||||
@@ -0,0 +1,147 @@
|
||||
+OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
|
||||
+OCF_RESKEY_insecure_default="false"
|
||||
+
|
||||
+: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
|
||||
+: ${OCF_RESKEY_insecure=${OCF_RESKEY_insecure_default}}
|
||||
+
|
||||
+if ocf_is_true "${OCF_RESKEY_insecure}"; then
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --insecure"
|
||||
+fi
|
||||
+
|
||||
+common_meta_data() {
|
||||
+ cat <<END
|
||||
+
|
||||
+<parameter name="cloud" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Openstack cloud (from ~/.config/openstack/clouds.yaml or /etc/openstack/clouds.yaml).
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Cloud from clouds.yaml</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="openrc" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Openstack credentials as openrc file from api_access/openrc.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">openrc file</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="auth_url" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Keystone Auth URL
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Keystone Auth URL</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="username" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Username.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Username</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="password" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Password.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Password</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="project_name" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Keystone Project.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Keystone Project</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="user_domain_name" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Keystone User Domain Name.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Keystone User Domain Name</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="project_domain_name" required="0">
|
||||
+<longdesc lang="en">
|
||||
+Keystone Project Domain Name.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Keystone Project Domain Name</shortdesc>
|
||||
+<content type="string" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="openstackcli">
|
||||
+<longdesc lang="en">
|
||||
+Path to command line tools for openstack.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Path to Openstack CLI tool</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_openstackcli_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="insecure">
|
||||
+<longdesc lang="en">
|
||||
+Allow insecure connections
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Allow insecure connections</shortdesc>
|
||||
+<content type="boolean" default="${OCF_RESKEY_insecure_default}" />
|
||||
+</parameter>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+get_config() {
|
||||
+ if [ -n "$OCF_RESKEY_cloud" ]; then
|
||||
+ TILDE=$(echo ~)
|
||||
+ clouds_yaml="$TILDE/.config/openstack/clouds.yaml"
|
||||
+ if [ ! -f "$clouds_yaml" ]; then
|
||||
+ clouds_yaml="/etc/openstack/clouds.yaml"
|
||||
+ fi
|
||||
+ if [ ! -f "$clouds_yaml" ]; then
|
||||
+ ocf_exit_reason "~/.config/openstack/clouds.yaml and /etc/openstack/clouds.yaml does not exist"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-cloud $OCF_RESKEY_cloud"
|
||||
+ elif [ -n "$OCF_RESKEY_openrc" ]; then
|
||||
+ if [ ! -f "$OCF_RESKEY_openrc" ]; then
|
||||
+ ocf_exit_reason "$OCF_RESKEY_openrc does not exist"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ . $OCF_RESKEY_openrc
|
||||
+ else
|
||||
+ if [ -z "$OCF_RESKEY_auth_url" ]; then
|
||||
+ ocf_exit_reason "auth_url not set"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if [ -z "$OCF_RESKEY_username" ]; then
|
||||
+ ocf_exit_reason "username not set"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if [ -z "$OCF_RESKEY_password" ]; then
|
||||
+ ocf_exit_reason "password not set"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if [ -z "$OCF_RESKEY_project_name" ]; then
|
||||
+ ocf_exit_reason "project_name not set"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if [ -z "$OCF_RESKEY_user_domain_name" ]; then
|
||||
+ ocf_exit_reason "user_domain_name not set"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ if [ -z "$OCF_RESKEY_project_domain_name" ]; then
|
||||
+ ocf_exit_reason " not set"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-auth-url $OCF_RESKEY_auth_url"
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-username $OCF_RESKEY_username"
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-password $OCF_RESKEY_password"
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-project-name $OCF_RESKEY_project_name"
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-user-domain-name $OCF_RESKEY_user_domain_name"
|
||||
+ OCF_RESKEY_openstackcli="${OCF_RESKEY_openstackcli} --os-project-domain-name $OCF_RESKEY_project_domain_name"
|
||||
+ fi
|
||||
+}
|
||||
diff --color -uNr a/heartbeat/openstack-floating-ip b/heartbeat/openstack-floating-ip
|
||||
--- a/heartbeat/openstack-floating-ip 2022-03-15 16:14:29.370209063 +0100
|
||||
+++ b/heartbeat/openstack-floating-ip 2022-03-15 16:17:36.233840014 +0100
|
||||
@@ -34,10 +34,9 @@
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
-# Defaults
|
||||
-OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
|
||||
+. ${OCF_FUNCTIONS_DIR}/openstack-common.sh
|
||||
|
||||
-: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
|
||||
+# Defaults
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -67,22 +66,11 @@
|
||||
<shortdesc lang="en">Move a floating IP</shortdesc>
|
||||
|
||||
<parameters>
|
||||
-<parameter name="openstackcli">
|
||||
-<longdesc lang="en">
|
||||
-Path to command line tools for openstack.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Path to Openstack CLI tool</shortdesc>
|
||||
-<content type="string" default="${OCF_RESKEY_openstackcli_default}" />
|
||||
-</parameter>
|
||||
+END
|
||||
|
||||
-<parameter name="openrc" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Valid Openstack credentials as openrc file from api_access/openrc.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">openrc file</shortdesc>
|
||||
-<content type="string" />
|
||||
-</parameter>
|
||||
+common_meta_data
|
||||
|
||||
+cat <<END
|
||||
<parameter name="ip_id" required="1">
|
||||
<longdesc lang="en">
|
||||
Floating IP Identifier.
|
||||
@@ -104,7 +92,7 @@
|
||||
<actions>
|
||||
<action name="start" timeout="180s" />
|
||||
<action name="stop" timeout="180s" />
|
||||
-<action name="monitor" depth="0" timeout="30s" interval="60s" />
|
||||
+<action name="monitor" depth="0" timeout="180s" interval="60s" />
|
||||
<action name="validate-all" timeout="5s" />
|
||||
<action name="meta-data" timeout="5s" />
|
||||
</actions>
|
||||
@@ -115,17 +103,7 @@
|
||||
osflip_validate() {
|
||||
check_binary "$OCF_RESKEY_openstackcli"
|
||||
|
||||
- if [ -z "$OCF_RESKEY_openrc" ]; then
|
||||
- ocf_exit_reason "openrc parameter not set"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- if [ ! -f "$OCF_RESKEY_openrc" ] ; then
|
||||
- ocf_exit_reason "openrc file not found"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- . $OCF_RESKEY_openrc
|
||||
+ get_config
|
||||
|
||||
if ! $OCF_RESKEY_openstackcli floating ip list|grep -q $OCF_RESKEY_ip_id ; then
|
||||
ocf_exit_reason "ip-id $OCF_RESKEY_ip_id not found"
|
||||
diff --color -uNr a/heartbeat/openstack-info b/heartbeat/openstack-info
|
||||
--- a/heartbeat/openstack-info 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/heartbeat/openstack-info 2022-03-15 16:17:36.234840018 +0100
|
||||
@@ -0,0 +1,270 @@
|
||||
+#!/bin/sh
|
||||
+#
|
||||
+#
|
||||
+# OCF resource agent to set attributes from Openstack instance details.
|
||||
+# It records (in the CIB) various attributes of a node
|
||||
+#
|
||||
+# Copyright (c) 2018 Mathieu Grzybek
|
||||
+# All Rights Reserved.
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of version 2 of the GNU General Public License as
|
||||
+# published by the Free Software Foundation.
|
||||
+#
|
||||
+# This program is distributed in the hope that it would be useful, but
|
||||
+# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
+#
|
||||
+# Further, this software is distributed without any warranty that it is
|
||||
+# free of the rightful claim of any third person regarding infringement
|
||||
+# or the like. Any license provided herein, whether implied or
|
||||
+# otherwise, applies only to this software file. Patent licenses, if
|
||||
+# any, provided herein do not apply to combinations of this program with
|
||||
+# other software, or any other product whatsoever.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write the Free Software Foundation,
|
||||
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
+#
|
||||
+#######################################################################
|
||||
+# Initialization:
|
||||
+
|
||||
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+
|
||||
+. ${OCF_FUNCTIONS_DIR}/openstack-common.sh
|
||||
+
|
||||
+# Defaults
|
||||
+OCF_RESKEY_pidfile_default="$HA_RSCTMP/OSInfo-${OCF_RESOURCE_HOSTNAME}"
|
||||
+OCF_RESKEY_delay_default="0"
|
||||
+OCF_RESKEY_clone_default="0"
|
||||
+OCF_RESKEY_curlcli_default="/usr/bin/curl"
|
||||
+OCF_RESKEY_pythoncli_default="/usr/bin/python"
|
||||
+
|
||||
+: ${OCF_RESKEY_curlcli=${OCF_RESKEY_curlcli_default}}
|
||||
+: ${OCF_RESKEY_pythoncli=${OCF_RESKEY_pythoncli_default}}
|
||||
+: ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}}
|
||||
+: ${OCF_RESKEY_delay=${OCF_RESKEY_delay_default}}
|
||||
+: ${OCF_RESKEY_clone=${OCF_RESKEY_clone_default}}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+meta_data() {
|
||||
+ cat <<END
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
||||
+<resource-agent name="openstack-info" version="1.0">
|
||||
+<version>1.0</version>
|
||||
+
|
||||
+<longdesc lang="en">
|
||||
+OCF resource agent to set attributes from Openstack instance details.
|
||||
+It records (in the CIB) various attributes of a node.
|
||||
+Sample output:
|
||||
+ openstack_az : nova
|
||||
+ openstack_flavor : c1.small
|
||||
+ openstack_id : 60ac4343-5828-49b1-8aac-7c69b1417f31
|
||||
+ openstack_ports : 7960d889-9750-4160-bf41-c69a41ad72d9:96530d18-57a3-4718-af32-30f2a74c22a2,b0e55a06-bd75-468d-8baa-22cfeb65799f:a55ae917-8016-4b1e-8ffa-04311b9dc7d6
|
||||
+
|
||||
+The layout of openstack_ports is a comma-separated list of tuples "subnet_id:port_id".
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Records various node attributes in the CIB</shortdesc>
|
||||
+
|
||||
+<parameters>
|
||||
+END
|
||||
+
|
||||
+common_meta_data
|
||||
+
|
||||
+ cat <<END
|
||||
+<parameter name="pidfile" unique="0">
|
||||
+<longdesc lang="en">PID file</longdesc>
|
||||
+<shortdesc lang="en">PID file</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_pidfile_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="delay" unique="0">
|
||||
+<longdesc lang="en">Interval to allow values to stabilize</longdesc>
|
||||
+<shortdesc lang="en">Dampening Delay</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_delay_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="curlcli">
|
||||
+<longdesc lang="en">
|
||||
+Path to command line cURL binary.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Path to cURL binary</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_curlcli_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+<parameter name="pythoncli">
|
||||
+<longdesc lang="en">
|
||||
+Path to command line Python interpreter.
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Path to Python interpreter</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_pythoncli_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
+</parameters>
|
||||
+
|
||||
+<actions>
|
||||
+<action name="start" timeout="180s" />
|
||||
+<action name="stop" timeout="180s" />
|
||||
+<action name="monitor" timeout="30s" interval="60s"/>
|
||||
+<action name="meta-data" timeout="5s" />
|
||||
+<action name="validate-all" timeout="20s" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+#######################################################################
|
||||
+
|
||||
+OSInfoStats() {
|
||||
+ local result
|
||||
+ local value
|
||||
+ local node
|
||||
+ local node_id
|
||||
+
|
||||
+ get_config
|
||||
+
|
||||
+ # Nova data: server ID
|
||||
+ node_id=$($OCF_RESKEY_curlcli \
|
||||
+ -s http://169.254.169.254/openstack/latest/meta_data.json |
|
||||
+ $OCF_RESKEY_pythoncli -m json.tool |
|
||||
+ grep -P '\"uuid\": \".*\",$' |
|
||||
+ grep -P -o '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}')
|
||||
+
|
||||
+ if [ $? -ne 0 ] ; then
|
||||
+ ocf_exit_reason "Cannot find server ID"
|
||||
+ exit $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
+
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_id -v "$node_id"
|
||||
+
|
||||
+ # Nova data: flavor
|
||||
+ value=$($OCF_RESKEY_openstackcli server show \
|
||||
+ --format value \
|
||||
+ --column flavor \
|
||||
+ $node_id)
|
||||
+
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_flavor -v "$value"
|
||||
+
|
||||
+ # Nova data: availability zone
|
||||
+ value=$($OCF_RESKEY_openstackcli server show \
|
||||
+ --format value \
|
||||
+ --column OS-EXT-AZ:availability_zone \
|
||||
+ $node_id)
|
||||
+
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_az -v "$value"
|
||||
+
|
||||
+ # Network data: ports
|
||||
+ value=""
|
||||
+ for port_id in $($OCF_RESKEY_openstackcli port list \
|
||||
+ --format value \
|
||||
+ --column id \
|
||||
+ --server $node_id); do
|
||||
+ subnet_id=$($OCF_RESKEY_openstackcli port show \
|
||||
+ --format json \
|
||||
+ --column fixed_ips \
|
||||
+ ${port_id} | grep -P '\"subnet_id\": \".*\",$' |
|
||||
+ grep -P -o '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}')
|
||||
+ value+="${subnet_id}:${port_id},"
|
||||
+ done
|
||||
+ value=$(echo ${value} | sed -e 's/,$//g')
|
||||
+
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_ports -v "$value"
|
||||
+
|
||||
+ if [ ! -z "$OS_REGION_NAME" ] ; then
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_region -v "$OS_REGION_NAME"
|
||||
+ fi
|
||||
+
|
||||
+ if [ ! -z "$OS_TENANT_ID" ] ; then
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_tenant_id -v "$OS_TENANT_ID"
|
||||
+
|
||||
+ if [ ! -z "$OS_TENANT_NAME" ] ; then
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_tenant_name -v "$OS_TENANT_NAME"
|
||||
+ fi
|
||||
+ else
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_project_id -v "$OS_PROJECT_ID"
|
||||
+
|
||||
+ if [ ! -z "$OS_PROJECT_NAME" ] ; then
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_project_name -v "$OS_PROJECT_NAME"
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+}
|
||||
+
|
||||
+OSInfo_usage() {
|
||||
+ cat <<END
|
||||
+usage: $0 {start|stop|monitor|validate-all|meta-data}
|
||||
+
|
||||
+Expects to have a fully populated OCF RA-compliant environment set.
|
||||
+END
|
||||
+}
|
||||
+
|
||||
+OSInfo_start() {
|
||||
+ echo $OCF_RESKEY_clone > $OCF_RESKEY_pidfile
|
||||
+ OSInfoStats
|
||||
+ exit $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+OSInfo_stop() {
|
||||
+ rm -f $OCF_RESKEY_pidfile
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_id
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_flavor
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_az
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_ports
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_region
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_tenant_id
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_tenant_name
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_project_id
|
||||
+ ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_project_name
|
||||
+ exit $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+OSInfo_monitor() {
|
||||
+ if [ -f "$OCF_RESKEY_pidfile" ] ; then
|
||||
+ OSInfoStats
|
||||
+ exit $OCF_RUNNING
|
||||
+ fi
|
||||
+ exit $OCF_NOT_RUNNING
|
||||
+}
|
||||
+
|
||||
+OSInfo_validate() {
|
||||
+ check_binary "$OCF_RESKEY_curlcli"
|
||||
+ check_binary "$OCF_RESKEY_openstackcli"
|
||||
+ check_binary "$OCF_RESKEY_pythoncli"
|
||||
+
|
||||
+ return $OCF_SUCCESS
|
||||
+}
|
||||
+
|
||||
+if [ $# -ne 1 ]; then
|
||||
+ OSInfo_usage
|
||||
+ exit $OCF_ERR_ARGS
|
||||
+fi
|
||||
+
|
||||
+if [ x != x${OCF_RESKEY_delay} ]; then
|
||||
+ OCF_RESKEY_delay="-d ${OCF_RESKEY_delay}"
|
||||
+fi
|
||||
+
|
||||
+case $__OCF_ACTION in
|
||||
+meta-data) meta_data
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+start) OSInfo_validate || exit $?
|
||||
+ OSInfo_start
|
||||
+ ;;
|
||||
+stop) OSInfo_stop
|
||||
+ ;;
|
||||
+monitor) OSInfo_monitor
|
||||
+ ;;
|
||||
+validate-all) OSInfo_validate
|
||||
+ ;;
|
||||
+usage|help) OSInfo_usage
|
||||
+ exit $OCF_SUCCESS
|
||||
+ ;;
|
||||
+*) OSInfo_usage
|
||||
+ exit $OCF_ERR_UNIMPLEMENTED
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+exit $?
|
||||
diff --color -uNr a/heartbeat/openstack-info.in b/heartbeat/openstack-info.in
|
||||
--- a/heartbeat/openstack-info.in 2022-03-15 16:14:29.370209063 +0100
|
||||
+++ b/heartbeat/openstack-info.in 2022-03-15 16:17:36.234840018 +0100
|
||||
@@ -32,16 +32,16 @@
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
+. ${OCF_FUNCTIONS_DIR}/openstack-common.sh
|
||||
+
|
||||
# Defaults
|
||||
OCF_RESKEY_pidfile_default="$HA_RSCTMP/OSInfo-${OCF_RESOURCE_HOSTNAME}"
|
||||
OCF_RESKEY_delay_default="0"
|
||||
OCF_RESKEY_clone_default="0"
|
||||
OCF_RESKEY_curlcli_default="/usr/bin/curl"
|
||||
-OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
|
||||
OCF_RESKEY_pythoncli_default="@PYTHON@"
|
||||
|
||||
: ${OCF_RESKEY_curlcli=${OCF_RESKEY_curlcli_default}}
|
||||
-: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
|
||||
: ${OCF_RESKEY_pythoncli=${OCF_RESKEY_pythoncli_default}}
|
||||
: ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}}
|
||||
: ${OCF_RESKEY_delay=${OCF_RESKEY_delay_default}}
|
||||
@@ -70,25 +70,23 @@
|
||||
<shortdesc lang="en">Records various node attributes in the CIB</shortdesc>
|
||||
|
||||
<parameters>
|
||||
+END
|
||||
+
|
||||
+common_meta_data
|
||||
+
|
||||
+ cat <<END
|
||||
<parameter name="pidfile" unique="0">
|
||||
<longdesc lang="en">PID file</longdesc>
|
||||
<shortdesc lang="en">PID file</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_pidfile_default}" />
|
||||
</parameter>
|
||||
+
|
||||
<parameter name="delay" unique="0">
|
||||
<longdesc lang="en">Interval to allow values to stabilize</longdesc>
|
||||
<shortdesc lang="en">Dampening Delay</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_delay_default}" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="openrc" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Valid Openstack credentials as openrc file from api_access/openrc.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">openrc file</shortdesc>
|
||||
-<content type="string" />
|
||||
-</parameter>
|
||||
-
|
||||
<parameter name="curlcli">
|
||||
<longdesc lang="en">
|
||||
Path to command line cURL binary.
|
||||
@@ -97,14 +95,6 @@
|
||||
<content type="string" default="${OCF_RESKEY_curlcli_default}" />
|
||||
</parameter>
|
||||
|
||||
-<parameter name="openstackcli">
|
||||
-<longdesc lang="en">
|
||||
-Path to command line tools for openstack.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Path to Openstack CLI tool</shortdesc>
|
||||
-<content type="string" default="${OCF_RESKEY_openstackcli_default}" />
|
||||
-</parameter>
|
||||
-
|
||||
<parameter name="pythoncli">
|
||||
<longdesc lang="en">
|
||||
Path to command line Python interpreter.
|
||||
@@ -116,9 +106,9 @@
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
-<action name="start" timeout="20s" />
|
||||
-<action name="stop" timeout="20s" />
|
||||
-<action name="monitor" timeout="20s" interval="60s"/>
|
||||
+<action name="start" timeout="180s" />
|
||||
+<action name="stop" timeout="180s" />
|
||||
+<action name="monitor" timeout="180s" interval="60s"/>
|
||||
<action name="meta-data" timeout="5s" />
|
||||
<action name="validate-all" timeout="20s" />
|
||||
</actions>
|
||||
@@ -134,7 +124,7 @@
|
||||
local node
|
||||
local node_id
|
||||
|
||||
- . $OCF_RESKEY_openrc
|
||||
+ get_config
|
||||
|
||||
# Nova data: server ID
|
||||
node_id=$($OCF_RESKEY_curlcli \
|
||||
@@ -244,16 +234,6 @@
|
||||
check_binary "$OCF_RESKEY_openstackcli"
|
||||
check_binary "$OCF_RESKEY_pythoncli"
|
||||
|
||||
- if [ -z "$OCF_RESKEY_openrc" ]; then
|
||||
- ocf_exit_reason "openrc parameter not set"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- if [ ! -f "$OCF_RESKEY_openrc" ] ; then
|
||||
- ocf_exit_reason "openrc file not found"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
return $OCF_SUCCESS
|
||||
}
|
||||
|
||||
diff --color -uNr a/heartbeat/openstack-virtual-ip b/heartbeat/openstack-virtual-ip
|
||||
--- a/heartbeat/openstack-virtual-ip 2022-03-15 16:14:29.370209063 +0100
|
||||
+++ b/heartbeat/openstack-virtual-ip 2022-03-15 16:17:36.235840021 +0100
|
||||
@@ -34,10 +34,9 @@
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
|
||||
-# Defaults
|
||||
-OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
|
||||
+. ${OCF_FUNCTIONS_DIR}/openstack-common.sh
|
||||
|
||||
-: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
|
||||
+# Defaults
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -68,22 +67,11 @@
|
||||
<shortdesc lang="en">Move a virtual IP</shortdesc>
|
||||
|
||||
<parameters>
|
||||
-<parameter name="openstackcli">
|
||||
-<longdesc lang="en">
|
||||
-Path to command line tools for openstack.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">Path to Openstack CLI tool</shortdesc>
|
||||
-<content type="string" default="${OCF_RESKEY_openstackcli_default}" />
|
||||
-</parameter>
|
||||
+END
|
||||
|
||||
-<parameter name="openrc" required="1">
|
||||
-<longdesc lang="en">
|
||||
-Valid Openstack credentials as openrc file from api_access/openrc.
|
||||
-</longdesc>
|
||||
-<shortdesc lang="en">openrc file</shortdesc>
|
||||
-<content type="string" />
|
||||
-</parameter>
|
||||
+common_meta_data
|
||||
|
||||
+cat <<END
|
||||
<parameter name="ip" required="1">
|
||||
<longdesc lang="en">
|
||||
Virtual IP Address.
|
||||
@@ -105,7 +93,7 @@
|
||||
<actions>
|
||||
<action name="start" timeout="180s" />
|
||||
<action name="stop" timeout="180s" />
|
||||
-<action name="monitor" depth="0" timeout="30s" interval="60s" />
|
||||
+<action name="monitor" depth="0" timeout="180s" interval="60s" />
|
||||
<action name="validate-all" timeout="5s" />
|
||||
<action name="meta-data" timeout="5s" />
|
||||
</actions>
|
||||
@@ -128,17 +116,7 @@
|
||||
osvip_validate() {
|
||||
check_binary "$OCF_RESKEY_openstackcli"
|
||||
|
||||
- if [ -z "$OCF_RESKEY_openrc" ]; then
|
||||
- ocf_exit_reason "openrc parameter not set"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- if [ ! -f "$OCF_RESKEY_openrc" ] ; then
|
||||
- ocf_exit_reason "openrc file not found"
|
||||
- return $OCF_ERR_CONFIGURED
|
||||
- fi
|
||||
-
|
||||
- . $OCF_RESKEY_openrc
|
||||
+ get_config
|
||||
|
||||
${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) > /dev/null 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
@ -1,72 +0,0 @@
|
||||
From 64f434014bc198055478a139532c7cc133967c5d Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 8 Jul 2022 15:41:34 +0200
|
||||
Subject: [PATCH] openstack-agents: fixes
|
||||
|
||||
- openstack-cinder-volume: dont do volume_local_check during start/stop-action
|
||||
- openstack-floating-ip/openstack-virtual-ip: dont fail in validate()
|
||||
during probe-calls
|
||||
- openstack-floating-ip: fix awk only catching last id for node_port_ids
|
||||
---
|
||||
heartbeat/openstack-cinder-volume | 2 +-
|
||||
heartbeat/openstack-floating-ip | 4 ++--
|
||||
heartbeat/openstack-virtual-ip | 4 ++--
|
||||
3 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/openstack-cinder-volume b/heartbeat/openstack-cinder-volume
|
||||
index cc12e58ae..19bf04faf 100755
|
||||
--- a/heartbeat/openstack-cinder-volume
|
||||
+++ b/heartbeat/openstack-cinder-volume
|
||||
@@ -138,7 +138,7 @@ osvol_monitor() {
|
||||
|
||||
node_id=$(_get_node_id)
|
||||
|
||||
- if ocf_is_true $OCF_RESKEY_volume_local_check ; then
|
||||
+ if [ "$__OCF_ACTION" = "monitor" ] && ocf_is_true $OCF_RESKEY_volume_local_check ; then
|
||||
#
|
||||
# Is the volue attached?
|
||||
# We check the local devices
|
||||
diff --git a/heartbeat/openstack-floating-ip b/heartbeat/openstack-floating-ip
|
||||
index 8c135cc24..6e2895654 100755
|
||||
--- a/heartbeat/openstack-floating-ip
|
||||
+++ b/heartbeat/openstack-floating-ip
|
||||
@@ -111,7 +111,7 @@ osflip_validate() {
|
||||
fi
|
||||
|
||||
${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) > /dev/null 2>&1
|
||||
- if [ $? -ne 0 ] ; then
|
||||
+ if [ $? -ne 0 ] && ! ocf_is_probe; then
|
||||
ocf_log warn "attr_updater failed to get openstack_ports attribute of node $OCF_RESOURCE_INSTANCE"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
@@ -129,7 +129,7 @@ osflip_monitor() {
|
||||
node_port_ids=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) \
|
||||
| awk -F= '{gsub("\"","");print $NF}' \
|
||||
| tr ',' ' ' \
|
||||
- | awk -F: '{print $NF}')
|
||||
+ | awk '{gsub("[^ ]*:", "");print}')
|
||||
|
||||
# Is the IP active and attached?
|
||||
result=$($OCF_RESKEY_openstackcli floating ip show \
|
||||
diff --git a/heartbeat/openstack-virtual-ip b/heartbeat/openstack-virtual-ip
|
||||
index a1084c420..c654d980a 100755
|
||||
--- a/heartbeat/openstack-virtual-ip
|
||||
+++ b/heartbeat/openstack-virtual-ip
|
||||
@@ -119,7 +119,7 @@ osvip_validate() {
|
||||
get_config
|
||||
|
||||
${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) > /dev/null 2>&1
|
||||
- if [ $? -ne 0 ] ; then
|
||||
+ if [ $? -ne 0 ] && ! ocf_is_probe; then
|
||||
ocf_log warn "attr_updater failed to get openstack_ports attribute of node $OCF_RESOURCE_INSTANCE"
|
||||
return $OCF_ERR_GENERIC
|
||||
fi
|
||||
@@ -136,7 +136,7 @@ osvip_monitor() {
|
||||
--format value \
|
||||
--column allowed_address_pairs \
|
||||
${node_port_id})
|
||||
- if echo $result | grep -q $OCF_RESKEY_ip ; then
|
||||
+ if echo $result | grep -q "$OCF_RESKEY_ip"; then
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n openstack_virtual_ip -v $OCF_RESKEY_ip
|
||||
|
||||
return $OCF_SUCCESS
|
@ -1,26 +0,0 @@
|
||||
From 8b1d3257e5176a2f50a843a21888c4b4f51f370b Mon Sep 17 00:00:00 2001
|
||||
From: Valentin Vidic <vvidic@valentin-vidic.from.hr>
|
||||
Date: Sun, 3 Apr 2022 20:31:50 +0200
|
||||
Subject: [PATCH] openstack-info: fix bashism
|
||||
|
||||
Also simplify striping of trailing comma.
|
||||
---
|
||||
heartbeat/openstack-info.in | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/openstack-info.in b/heartbeat/openstack-info.in
|
||||
index f6dc1ee4d..f3a59fc7a 100755
|
||||
--- a/heartbeat/openstack-info.in
|
||||
+++ b/heartbeat/openstack-info.in
|
||||
@@ -167,9 +167,9 @@ OSInfoStats() {
|
||||
--column fixed_ips \
|
||||
${port_id} | grep -P '\"subnet_id\": \".*\",$' |
|
||||
grep -P -o '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}')
|
||||
- value+="${subnet_id}:${port_id},"
|
||||
+ value="${value}${subnet_id}:${port_id},"
|
||||
done
|
||||
- value=$(echo ${value} | sed -e 's/,$//g')
|
||||
+ value=${value%,}
|
||||
|
||||
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_ports -v "$value"
|
||||
|
@ -1,52 +0,0 @@
|
||||
From f91804ff4772e3ab41f46e28d370f57898700333 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Brandl <georg@python.org>
|
||||
Date: Thu, 10 Dec 2020 08:19:21 +0100
|
||||
Subject: [PATCH] fixes #1625: infinite loop in SML lexer
|
||||
|
||||
Reason was a lookahead-only pattern which was included in the state
|
||||
where the lookahead was transitioning to.
|
||||
---
|
||||
pygments/lexers/ml.py | 12 ++++++------
|
||||
2 files changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/pygments/lexers/ml.py b/pygments/lexers/ml.py
|
||||
index 8ca8ce3eb..f2ac367c5 100644
|
||||
--- a/pygments/lexers/ml.py
|
||||
+++ b/pygments/lexers/ml.py
|
||||
@@ -142,7 +142,7 @@ def id_callback(self, match):
|
||||
(r'#\s+(%s)' % symbolicid_re, Name.Label),
|
||||
# Some reserved words trigger a special, local lexer state change
|
||||
(r'\b(datatype|abstype)\b(?!\')', Keyword.Reserved, 'dname'),
|
||||
- (r'(?=\b(exception)\b(?!\'))', Text, ('ename')),
|
||||
+ (r'\b(exception)\b(?!\')', Keyword.Reserved, 'ename'),
|
||||
(r'\b(functor|include|open|signature|structure)\b(?!\')',
|
||||
Keyword.Reserved, 'sname'),
|
||||
(r'\b(type|eqtype)\b(?!\')', Keyword.Reserved, 'tname'),
|
||||
@@ -315,15 +315,14 @@ def id_callback(self, match):
|
||||
'ename': [
|
||||
include('whitespace'),
|
||||
|
||||
- (r'(exception|and)\b(\s+)(%s)' % alphanumid_re,
|
||||
+ (r'(and\b)(\s+)(%s)' % alphanumid_re,
|
||||
bygroups(Keyword.Reserved, Text, Name.Class)),
|
||||
- (r'(exception|and)\b(\s*)(%s)' % symbolicid_re,
|
||||
+ (r'(and\b)(\s*)(%s)' % symbolicid_re,
|
||||
bygroups(Keyword.Reserved, Text, Name.Class)),
|
||||
(r'\b(of)\b(?!\')', Keyword.Reserved),
|
||||
+ (r'(%s)|(%s)' % (alphanumid_re, symbolicid_re), Name.Class),
|
||||
|
||||
- include('breakout'),
|
||||
- include('core'),
|
||||
- (r'\S+', Error),
|
||||
+ default('#pop'),
|
||||
],
|
||||
|
||||
'datcon': [
|
||||
@@ -445,6 +444,7 @@ class OcamlLexer(RegexLexer):
|
||||
],
|
||||
}
|
||||
|
||||
+
|
||||
class OpaLexer(RegexLexer):
|
||||
"""
|
||||
Lexer for the Opa language (http://opalang.org).
|
@ -1,138 +0,0 @@
|
||||
From 2e7e8c4a7b318f4032493773732754e418279a14 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Brandl <georg@python.org>
|
||||
Date: Mon, 11 Jan 2021 09:46:34 +0100
|
||||
Subject: [PATCH] Fix several exponential/cubic complexity regexes found by Ben
|
||||
Caller/Doyensec
|
||||
|
||||
---
|
||||
pygments/lexers/archetype.py | 2 +-
|
||||
pygments/lexers/factor.py | 4 ++--
|
||||
pygments/lexers/jvm.py | 1 -
|
||||
pygments/lexers/matlab.py | 6 +++---
|
||||
pygments/lexers/objective.py | 4 ++--
|
||||
pygments/lexers/templates.py | 2 +-
|
||||
pygments/lexers/varnish.py | 2 +-
|
||||
8 files changed, 14 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/pygments/lexers/archetype.py b/pygments/lexers/archetype.py
|
||||
index 65046613d..26f5ea8c9 100644
|
||||
--- a/pygments/lexers/archetype.py
|
||||
+++ b/pygments/lexers/archetype.py
|
||||
@@ -58,7 +58,7 @@ class AtomsLexer(RegexLexer):
|
||||
(r'P((\d*(\.\d+)?[YyMmWwDd]){1,3}(T(\d*(\.\d+)?[HhMmSs]){,3})?|'
|
||||
r'T(\d*(\.\d+)?[HhMmSs]){,3})', Literal.Date),
|
||||
(r'[+-]?(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+', Number.Float),
|
||||
- (r'[+-]?(\d+)*\.\d+%?', Number.Float),
|
||||
+ (r'[+-]?\d*\.\d+%?', Number.Float),
|
||||
(r'0x[0-9a-fA-F]+', Number.Hex),
|
||||
(r'[+-]?\d+%?', Number.Integer),
|
||||
],
|
||||
diff --git a/pygments/lexers/factor.py b/pygments/lexers/factor.py
|
||||
index be7b30dff..9200547f9 100644
|
||||
--- a/pygments/lexers/factor.py
|
||||
+++ b/pygments/lexers/factor.py
|
||||
@@ -265,7 +265,7 @@ class FactorLexer(RegexLexer):
|
||||
(r'(?:<PRIVATE|PRIVATE>)\s', Keyword.Namespace),
|
||||
|
||||
# strings
|
||||
- (r'"""\s+(?:.|\n)*?\s+"""', String),
|
||||
+ (r'"""\s(?:.|\n)*?\s"""', String),
|
||||
(r'"(?:\\\\|\\"|[^"])*"', String),
|
||||
(r'\S+"\s+(?:\\\\|\\"|[^"])*"', String),
|
||||
(r'CHAR:\s+(?:\\[\\abfnrstv]|[^\\]\S*)\s', String.Char),
|
||||
@@ -322,7 +322,7 @@ class FactorLexer(RegexLexer):
|
||||
'slots': [
|
||||
(r'\s+', Text),
|
||||
(r';\s', Keyword, '#pop'),
|
||||
- (r'(\{\s+)(\S+)(\s+[^}]+\s+\}\s)',
|
||||
+ (r'(\{\s+)(\S+)(\s[^}]+\s\}\s)',
|
||||
bygroups(Text, Name.Variable, Text)),
|
||||
(r'\S+', Name.Variable),
|
||||
],
|
||||
diff --git a/pygments/lexers/jvm.py b/pygments/lexers/jvm.py
|
||||
index 62dfd45e5..9a9397c2d 100644
|
||||
--- a/pygments/lexers/jvm.py
|
||||
+++ b/pygments/lexers/jvm.py
|
||||
@@ -981,7 +981,6 @@ class CeylonLexer(RegexLexer):
|
||||
(r'(import)(\s+)', bygroups(Keyword.Namespace, Text), 'import'),
|
||||
(r'"(\\\\|\\[^\\]|[^"\\])*"', String),
|
||||
(r"'\\.'|'[^\\]'|'\\\{#[0-9a-fA-F]{4}\}'", String.Char),
|
||||
- (r'".*``.*``.*"', String.Interpol),
|
||||
(r'(\.)([a-z_]\w*)',
|
||||
bygroups(Operator, Name.Attribute)),
|
||||
(r'[a-zA-Z_]\w*:', Name.Label),
|
||||
diff --git a/pygments/lexers/matlab.py b/pygments/lexers/matlab.py
|
||||
index 4823c6a7e..578848623 100644
|
||||
--- a/pygments/lexers/matlab.py
|
||||
+++ b/pygments/lexers/matlab.py
|
||||
@@ -137,7 +137,7 @@ class MatlabLexer(RegexLexer):
|
||||
(r'.', Comment.Multiline),
|
||||
],
|
||||
'deffunc': [
|
||||
- (r'(\s*)(?:(.+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)',
|
||||
+ (r'(\s*)(?:(\S+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)',
|
||||
bygroups(Whitespace, Text, Whitespace, Punctuation,
|
||||
Whitespace, Name.Function, Punctuation, Text,
|
||||
Punctuation, Whitespace), '#pop'),
|
||||
@@ -638,7 +638,7 @@ class OctaveLexer(RegexLexer):
|
||||
(r"[^']*'", String, '#pop'),
|
||||
],
|
||||
'deffunc': [
|
||||
- (r'(\s*)(?:(.+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)',
|
||||
+ (r'(\s*)(?:(\S+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)',
|
||||
bygroups(Whitespace, Text, Whitespace, Punctuation,
|
||||
Whitespace, Name.Function, Punctuation, Text,
|
||||
Punctuation, Whitespace), '#pop'),
|
||||
@@ -710,7 +710,7 @@ class ScilabLexer(RegexLexer):
|
||||
(r'.', String, '#pop'),
|
||||
],
|
||||
'deffunc': [
|
||||
- (r'(\s*)(?:(.+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)',
|
||||
+ (r'(\s*)(?:(\S+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)',
|
||||
bygroups(Whitespace, Text, Whitespace, Punctuation,
|
||||
Whitespace, Name.Function, Punctuation, Text,
|
||||
Punctuation, Whitespace), '#pop'),
|
||||
diff --git a/pygments/lexers/objective.py b/pygments/lexers/objective.py
|
||||
index 34e4062f6..38ac9bb05 100644
|
||||
--- a/pygments/lexers/objective.py
|
||||
+++ b/pygments/lexers/objective.py
|
||||
@@ -261,11 +261,11 @@ class LogosLexer(ObjectiveCppLexer):
|
||||
'logos_classname'),
|
||||
(r'(%hook|%group)(\s+)([a-zA-Z$_][\w$]+)',
|
||||
bygroups(Keyword, Text, Name.Class)),
|
||||
- (r'(%config)(\s*\(\s*)(\w+)(\s*=\s*)(.*?)(\s*\)\s*)',
|
||||
+ (r'(%config)(\s*\(\s*)(\w+)(\s*=)(.*?)(\)\s*)',
|
||||
bygroups(Keyword, Text, Name.Variable, Text, String, Text)),
|
||||
(r'(%ctor)(\s*)(\{)', bygroups(Keyword, Text, Punctuation),
|
||||
'function'),
|
||||
- (r'(%new)(\s*)(\()(\s*.*?\s*)(\))',
|
||||
+ (r'(%new)(\s*)(\()(.*?)(\))',
|
||||
bygroups(Keyword, Text, Keyword, String, Keyword)),
|
||||
(r'(\s*)(%end)(\s*)', bygroups(Text, Keyword, Text)),
|
||||
inherit,
|
||||
diff --git a/pygments/lexers/templates.py b/pygments/lexers/templates.py
|
||||
index 33c06c4c4..5c3346b4c 100644
|
||||
--- a/pygments/lexers/templates.py
|
||||
+++ b/pygments/lexers/templates.py
|
||||
@@ -1405,7 +1405,7 @@ class EvoqueLexer(RegexLexer):
|
||||
# see doc for handling first name arg: /directives/evoque/
|
||||
# + minor inconsistency: the "name" in e.g. $overlay{name=site_base}
|
||||
# should be using(PythonLexer), not passed out as String
|
||||
- (r'(\$)(evoque|overlay)(\{(%)?)(\s*[#\w\-"\'.]+[^=,%}]+?)?'
|
||||
+ (r'(\$)(evoque|overlay)(\{(%)?)(\s*[#\w\-"\'.]+)?'
|
||||
r'(.*?)((?(4)%)\})',
|
||||
bygroups(Punctuation, Name.Builtin, Punctuation, None,
|
||||
String, using(PythonLexer), Punctuation)),
|
||||
diff --git a/pygments/lexers/varnish.py b/pygments/lexers/varnish.py
|
||||
index 23653f7a1..9d358bd7c 100644
|
||||
--- a/pygments/lexers/varnish.py
|
||||
+++ b/pygments/lexers/varnish.py
|
||||
@@ -61,7 +61,7 @@ def analyse_text(text):
|
||||
bygroups(Name.Attribute, Operator, Name.Variable.Global, Punctuation)),
|
||||
(r'(\.probe)(\s*=\s*)(\{)',
|
||||
bygroups(Name.Attribute, Operator, Punctuation), 'probe'),
|
||||
- (r'(\.\w+\b)(\s*=\s*)([^;]*)(\s*;)',
|
||||
+ (r'(\.\w+\b)(\s*=\s*)([^;\s]*)(\s*;)',
|
||||
bygroups(Name.Attribute, Operator, using(this), Punctuation)),
|
||||
(r'\{', Punctuation, '#push'),
|
||||
(r'\}', Punctuation, '#pop'),
|
@ -1,903 +0,0 @@
|
||||
From 5dcd5153f0318e4766f7f4d3e61dfdb4b352c39c Mon Sep 17 00:00:00 2001
|
||||
From: MSSedusch <sedusch@microsoft.com>
|
||||
Date: Mon, 30 May 2022 15:08:10 +0200
|
||||
Subject: [PATCH 1/2] add new Azure Events AZ resource agent
|
||||
|
||||
---
|
||||
.gitignore | 1 +
|
||||
configure.ac | 8 +
|
||||
doc/man/Makefile.am | 4 +
|
||||
heartbeat/Makefile.am | 4 +
|
||||
heartbeat/azure-events-az.in | 782 +++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 799 insertions(+)
|
||||
create mode 100644 heartbeat/azure-events-az.in
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index 0c259b5cf..e2b7c039c 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -54,6 +54,7 @@ heartbeat/Squid
|
||||
heartbeat/SysInfo
|
||||
heartbeat/aws-vpc-route53
|
||||
heartbeat/azure-events
|
||||
+heartbeat/azure-events-az
|
||||
heartbeat/clvm
|
||||
heartbeat/conntrackd
|
||||
heartbeat/dnsupdate
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index eeecfad0e..5716a2be2 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -523,6 +523,13 @@ if test -z "$PYTHON" || test $BUILD_OCF_PY -eq 0; then
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_AZURE_EVENTS, test $BUILD_AZURE_EVENTS -eq 1)
|
||||
|
||||
+BUILD_AZURE_EVENTS_AZ=1
|
||||
+if test -z "$PYTHON" || test $BUILD_OCF_PY -eq 0; then
|
||||
+ BUILD_AZURE_EVENTS_AZ=0
|
||||
+ AC_MSG_WARN("Not building azure-events-az")
|
||||
+fi
|
||||
+AM_CONDITIONAL(BUILD_AZURE_EVENTS_AZ, test $BUILD_AZURE_EVENTS_AZ -eq 1)
|
||||
+
|
||||
BUILD_GCP_PD_MOVE=1
|
||||
if test -z "$PYTHON" || test "x${HAVE_PYMOD_GOOGLEAPICLIENT}" != xyes || test $BUILD_OCF_PY -eq 0; then
|
||||
BUILD_GCP_PD_MOVE=0
|
||||
@@ -976,6 +983,7 @@ rgmanager/Makefile \
|
||||
|
||||
dnl Files we output that need to be executable
|
||||
AC_CONFIG_FILES([heartbeat/azure-events], [chmod +x heartbeat/azure-events])
|
||||
+AC_CONFIG_FILES([heartbeat/azure-events-az], [chmod +x heartbeat/azure-events-az])
|
||||
AC_CONFIG_FILES([heartbeat/AoEtarget], [chmod +x heartbeat/AoEtarget])
|
||||
AC_CONFIG_FILES([heartbeat/ManageRAID], [chmod +x heartbeat/ManageRAID])
|
||||
AC_CONFIG_FILES([heartbeat/ManageVE], [chmod +x heartbeat/ManageVE])
|
||||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||||
index cd8fd16bf..658c700ac 100644
|
||||
--- a/doc/man/Makefile.am
|
||||
+++ b/doc/man/Makefile.am
|
||||
@@ -219,6 +219,10 @@ if BUILD_AZURE_EVENTS
|
||||
man_MANS += ocf_heartbeat_azure-events.7
|
||||
endif
|
||||
|
||||
+if BUILD_AZURE_EVENTS_AZ
|
||||
+man_MANS += ocf_heartbeat_azure-events-az.7
|
||||
+endif
|
||||
+
|
||||
if BUILD_GCP_PD_MOVE
|
||||
man_MANS += ocf_heartbeat_gcp-pd-move.7
|
||||
endif
|
||||
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
|
||||
index 20d41e36a..1133dc13e 100644
|
||||
--- a/heartbeat/Makefile.am
|
||||
+++ b/heartbeat/Makefile.am
|
||||
@@ -188,6 +188,10 @@ if BUILD_AZURE_EVENTS
|
||||
ocf_SCRIPTS += azure-events
|
||||
endif
|
||||
|
||||
+if BUILD_AZURE_EVENTS_AZ
|
||||
+ocf_SCRIPTS += azure-events-az
|
||||
+endif
|
||||
+
|
||||
if BUILD_GCP_PD_MOVE
|
||||
ocf_SCRIPTS += gcp-pd-move
|
||||
endif
|
||||
diff --git a/heartbeat/azure-events-az.in b/heartbeat/azure-events-az.in
|
||||
new file mode 100644
|
||||
index 000000000..616fc8d9e
|
||||
--- /dev/null
|
||||
+++ b/heartbeat/azure-events-az.in
|
||||
@@ -0,0 +1,782 @@
|
||||
+#!@PYTHON@ -tt
|
||||
+#
|
||||
+# Resource agent for monitoring Azure Scheduled Events
|
||||
+#
|
||||
+# License: GNU General Public License (GPL)
|
||||
+# (c) 2018 Tobias Niekamp, Microsoft Corp.
|
||||
+# and Linux-HA contributors
|
||||
+
|
||||
+import os
|
||||
+import sys
|
||||
+import time
|
||||
+import subprocess
|
||||
+import json
|
||||
+try:
|
||||
+ import urllib2
|
||||
+ from urllib2 import URLError
|
||||
+except ImportError:
|
||||
+ import urllib.request as urllib2
|
||||
+ from urllib.error import URLError
|
||||
+import socket
|
||||
+from collections import defaultdict
|
||||
+
|
||||
+OCF_FUNCTIONS_DIR = os.environ.get("OCF_FUNCTIONS_DIR", "%s/lib/heartbeat" % os.environ.get("OCF_ROOT"))
|
||||
+sys.path.append(OCF_FUNCTIONS_DIR)
|
||||
+import ocf
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+
|
||||
+VERSION = "0.10"
|
||||
+USER_AGENT = "Pacemaker-ResourceAgent/%s %s" % (VERSION, ocf.distro())
|
||||
+
|
||||
+attr_globalPullState = "azure-events-az_globalPullState"
|
||||
+attr_lastDocVersion = "azure-events-az_lastDocVersion"
|
||||
+attr_curNodeState = "azure-events-az_curNodeState"
|
||||
+attr_pendingEventIDs = "azure-events-az_pendingEventIDs"
|
||||
+attr_healthstate = "#health-azure"
|
||||
+
|
||||
+default_loglevel = ocf.logging.INFO
|
||||
+default_relevantEventTypes = set(["Reboot", "Redeploy"])
|
||||
+
|
||||
+global_pullMaxAttempts = 3
|
||||
+global_pullDelaySecs = 1
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+class attrDict(defaultdict):
|
||||
+ """
|
||||
+ A wrapper for accessing dict keys like an attribute
|
||||
+ """
|
||||
+ def __init__(self, data):
|
||||
+ super(attrDict, self).__init__(attrDict)
|
||||
+ for d in data.keys():
|
||||
+ self.__setattr__(d, data[d])
|
||||
+
|
||||
+ def __getattr__(self, key):
|
||||
+ try:
|
||||
+ return self[key]
|
||||
+ except KeyError:
|
||||
+ raise AttributeError(key)
|
||||
+
|
||||
+ def __setattr__(self, key, value):
|
||||
+ self[key] = value
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+class azHelper:
|
||||
+ """
|
||||
+ Helper class for Azure's metadata API (including Scheduled Events)
|
||||
+ """
|
||||
+ metadata_host = "http://169.254.169.254/metadata"
|
||||
+ instance_api = "instance"
|
||||
+ events_api = "scheduledevents"
|
||||
+ api_version = "2019-08-01"
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def _sendMetadataRequest(endpoint, postData=None):
|
||||
+ """
|
||||
+ Send a request to Azure's Azure Metadata Service API
|
||||
+ """
|
||||
+ url = "%s/%s?api-version=%s" % (azHelper.metadata_host, endpoint, azHelper.api_version)
|
||||
+ data = ""
|
||||
+ ocf.logger.debug("_sendMetadataRequest: begin; endpoint = %s, postData = %s" % (endpoint, postData))
|
||||
+ ocf.logger.debug("_sendMetadataRequest: url = %s" % url)
|
||||
+
|
||||
+ if postData and type(postData) != bytes:
|
||||
+ postData = postData.encode()
|
||||
+
|
||||
+ req = urllib2.Request(url, postData)
|
||||
+ req.add_header("Metadata", "true")
|
||||
+ req.add_header("User-Agent", USER_AGENT)
|
||||
+ try:
|
||||
+ resp = urllib2.urlopen(req)
|
||||
+ except URLError as e:
|
||||
+ if hasattr(e, 'reason'):
|
||||
+ ocf.logger.warning("Failed to reach the server: %s" % e.reason)
|
||||
+ clusterHelper.setAttr(attr_globalPullState, "IDLE")
|
||||
+ elif hasattr(e, 'code'):
|
||||
+ ocf.logger.warning("The server couldn\'t fulfill the request. Error code: %s" % e.code)
|
||||
+ clusterHelper.setAttr(attr_globalPullState, "IDLE")
|
||||
+ else:
|
||||
+ data = resp.read()
|
||||
+ ocf.logger.debug("_sendMetadataRequest: response = %s" % data)
|
||||
+
|
||||
+ if data:
|
||||
+ data = json.loads(data)
|
||||
+
|
||||
+ ocf.logger.debug("_sendMetadataRequest: finished")
|
||||
+ return data
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def getInstanceInfo():
|
||||
+ """
|
||||
+ Fetch details about the current VM from Azure's Azure Metadata Service API
|
||||
+ """
|
||||
+ ocf.logger.debug("getInstanceInfo: begin")
|
||||
+
|
||||
+ jsondata = azHelper._sendMetadataRequest(azHelper.instance_api)
|
||||
+ ocf.logger.debug("getInstanceInfo: json = %s" % jsondata)
|
||||
+
|
||||
+ if jsondata:
|
||||
+ ocf.logger.debug("getInstanceInfo: finished, returning {}".format(jsondata["compute"]))
|
||||
+ return attrDict(jsondata["compute"])
|
||||
+ else:
|
||||
+ ocf.ocf_exit_reason("getInstanceInfo: Unable to get instance info")
|
||||
+ sys.exit(ocf.OCF_ERR_GENERIC)
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def pullScheduledEvents():
|
||||
+ """
|
||||
+ Retrieve all currently scheduled events via Azure Metadata Service API
|
||||
+ """
|
||||
+ ocf.logger.debug("pullScheduledEvents: begin")
|
||||
+
|
||||
+ jsondata = azHelper._sendMetadataRequest(azHelper.events_api)
|
||||
+ ocf.logger.debug("pullScheduledEvents: json = %s" % jsondata)
|
||||
+
|
||||
+ ocf.logger.debug("pullScheduledEvents: finished")
|
||||
+ return attrDict(jsondata)
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def forceEvents(eventIDs):
|
||||
+ """
|
||||
+ Force a set of events to start immediately
|
||||
+ """
|
||||
+ ocf.logger.debug("forceEvents: begin")
|
||||
+
|
||||
+ events = []
|
||||
+ for e in eventIDs:
|
||||
+ events.append({
|
||||
+ "EventId": e,
|
||||
+ })
|
||||
+ postData = {
|
||||
+ "StartRequests" : events
|
||||
+ }
|
||||
+ ocf.logger.info("forceEvents: postData = %s" % postData)
|
||||
+ resp = azHelper._sendMetadataRequest(azHelper.events_api, postData=json.dumps(postData))
|
||||
+
|
||||
+ ocf.logger.debug("forceEvents: finished")
|
||||
+ return
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+class clusterHelper:
|
||||
+ """
|
||||
+ Helper functions for Pacemaker control via crm
|
||||
+ """
|
||||
+ @staticmethod
|
||||
+ def _getLocation(node):
|
||||
+ """
|
||||
+ Helper function to retrieve local/global attributes
|
||||
+ """
|
||||
+ if node:
|
||||
+ return ["--node", node]
|
||||
+ else:
|
||||
+ return ["--type", "crm_config"]
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def _exec(command, *args):
|
||||
+ """
|
||||
+ Helper function to execute a UNIX command
|
||||
+ """
|
||||
+ args = list(args)
|
||||
+ ocf.logger.debug("_exec: begin; command = %s, args = %s" % (command, str(args)))
|
||||
+
|
||||
+ def flatten(*n):
|
||||
+ return (str(e) for a in n
|
||||
+ for e in (flatten(*a) if isinstance(a, (tuple, list)) else (str(a),)))
|
||||
+ command = list(flatten([command] + args))
|
||||
+ ocf.logger.debug("_exec: cmd = %s" % " ".join(command))
|
||||
+ try:
|
||||
+ ret = subprocess.check_output(command)
|
||||
+ if type(ret) != str:
|
||||
+ ret = ret.decode()
|
||||
+ ocf.logger.debug("_exec: return = %s" % ret)
|
||||
+ return ret.rstrip()
|
||||
+ except Exception as err:
|
||||
+ ocf.logger.exception(err)
|
||||
+ return None
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def setAttr(key, value, node=None):
|
||||
+ """
|
||||
+ Set the value of a specific global/local attribute in the Pacemaker cluster
|
||||
+ """
|
||||
+ ocf.logger.debug("setAttr: begin; key = %s, value = %s, node = %s" % (key, value, node))
|
||||
+
|
||||
+ if value:
|
||||
+ ret = clusterHelper._exec("crm_attribute",
|
||||
+ "--name", key,
|
||||
+ "--update", value,
|
||||
+ clusterHelper._getLocation(node))
|
||||
+ else:
|
||||
+ ret = clusterHelper._exec("crm_attribute",
|
||||
+ "--name", key,
|
||||
+ "--delete",
|
||||
+ clusterHelper._getLocation(node))
|
||||
+
|
||||
+ ocf.logger.debug("setAttr: finished")
|
||||
+ return len(ret) == 0
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def getAttr(key, node=None):
|
||||
+ """
|
||||
+ Retrieve a global/local attribute from the Pacemaker cluster
|
||||
+ """
|
||||
+ ocf.logger.debug("getAttr: begin; key = %s, node = %s" % (key, node))
|
||||
+
|
||||
+ val = clusterHelper._exec("crm_attribute",
|
||||
+ "--name", key,
|
||||
+ "--query", "--quiet",
|
||||
+ "--default", "",
|
||||
+ clusterHelper._getLocation(node))
|
||||
+ ocf.logger.debug("getAttr: finished")
|
||||
+ if not val:
|
||||
+ return None
|
||||
+ return val if not val.isdigit() else int(val)
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def getAllNodes():
|
||||
+ """
|
||||
+ Get a list of hostnames for all nodes in the Pacemaker cluster
|
||||
+ """
|
||||
+ ocf.logger.debug("getAllNodes: begin")
|
||||
+
|
||||
+ nodes = []
|
||||
+ nodeList = clusterHelper._exec("crm_node", "--list")
|
||||
+ for n in nodeList.split("\n"):
|
||||
+ nodes.append(n.split()[1])
|
||||
+ ocf.logger.debug("getAllNodes: finished; return %s" % str(nodes))
|
||||
+
|
||||
+ return nodes
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def getHostNameFromAzName(azName):
|
||||
+ """
|
||||
+ Helper function to get the actual host name from an Azure node name
|
||||
+ """
|
||||
+ return clusterHelper.getAttr("hostName_%s" % azName)
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def removeHoldFromNodes():
|
||||
+ """
|
||||
+ Remove the ON_HOLD state from all nodes in the Pacemaker cluster
|
||||
+ """
|
||||
+ ocf.logger.debug("removeHoldFromNodes: begin")
|
||||
+
|
||||
+ for n in clusterHelper.getAllNodes():
|
||||
+ if clusterHelper.getAttr(attr_curNodeState, node=n) == "ON_HOLD":
|
||||
+ clusterHelper.setAttr(attr_curNodeState, "AVAILABLE", node=n)
|
||||
+ ocf.logger.info("removeHoldFromNodes: removed ON_HOLD from node %s" % n)
|
||||
+
|
||||
+ ocf.logger.debug("removeHoldFromNodes: finished")
|
||||
+ return False
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def otherNodesAvailable(exceptNode):
|
||||
+ """
|
||||
+ Check if there are any nodes (except a given node) in the Pacemaker cluster that have state AVAILABLE
|
||||
+ """
|
||||
+ ocf.logger.debug("otherNodesAvailable: begin; exceptNode = %s" % exceptNode)
|
||||
+
|
||||
+ for n in clusterHelper.getAllNodes():
|
||||
+ state = clusterHelper.getAttr(attr_curNodeState, node=n)
|
||||
+ state = stringToNodeState(state) if state else AVAILABLE
|
||||
+ if state == AVAILABLE and n != exceptNode.hostName:
|
||||
+ ocf.logger.info("otherNodesAvailable: at least %s is available" % n)
|
||||
+ ocf.logger.debug("otherNodesAvailable: finished")
|
||||
+ return True
|
||||
+ ocf.logger.info("otherNodesAvailable: no other nodes are available")
|
||||
+ ocf.logger.debug("otherNodesAvailable: finished")
|
||||
+
|
||||
+ return False
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def transitionSummary():
|
||||
+ """
|
||||
+ Get the current Pacemaker transition summary (used to check if all resources are stopped when putting a node standby)
|
||||
+ """
|
||||
+ # <tniek> Is a global crm_simulate "too much"? Or would it be sufficient it there are no planned transitions for a particular node?
|
||||
+ # # crm_simulate -Ls
|
||||
+ # Transition Summary:
|
||||
+ # * Promote rsc_SAPHana_HN1_HDB03:0 (Slave -> Master hsr3-db1)
|
||||
+ # * Stop rsc_SAPHana_HN1_HDB03:1 (hsr3-db0)
|
||||
+ # * Move rsc_ip_HN1_HDB03 (Started hsr3-db0 -> hsr3-db1)
|
||||
+ # * Start rsc_nc_HN1_HDB03 (hsr3-db1)
|
||||
+ # # Excepted result when there are no pending actions:
|
||||
+ # Transition Summary:
|
||||
+ ocf.logger.debug("transitionSummary: begin")
|
||||
+
|
||||
+ summary = clusterHelper._exec("crm_simulate", "-Ls")
|
||||
+ if not summary:
|
||||
+ ocf.logger.warning("transitionSummary: could not load transition summary")
|
||||
+ return False
|
||||
+ if summary.find("Transition Summary:") < 0:
|
||||
+ ocf.logger.warning("transitionSummary: received unexpected transition summary: %s" % summary)
|
||||
+ return False
|
||||
+ summary = summary.split("Transition Summary:")[1]
|
||||
+ ret = summary.split("\n").pop(0)
|
||||
+
|
||||
+ ocf.logger.debug("transitionSummary: finished; return = %s" % str(ret))
|
||||
+ return ret
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def listOperationsOnNode(node):
|
||||
+ """
|
||||
+ Get a list of all current operations for a given node (used to check if any resources are pending)
|
||||
+ """
|
||||
+ # hsr3-db1:/home/tniek # crm_resource --list-operations -N hsr3-db0
|
||||
+ # rsc_azure-events-az (ocf::heartbeat:azure-events-az): Started: rsc_azure-events-az_start_0 (node=hsr3-db0, call=91, rc=0, last-rc-change=Fri Jun 8 22:37:46 2018, exec=115ms): complete
|
||||
+ # rsc_azure-events-az (ocf::heartbeat:azure-events-az): Started: rsc_azure-events-az_monitor_10000 (node=hsr3-db0, call=93, rc=0, last-rc-change=Fri Jun 8 22:37:47 2018, exec=197ms): complete
|
||||
+ # rsc_SAPHana_HN1_HDB03 (ocf::suse:SAPHana): Master: rsc_SAPHana_HN1_HDB03_start_0 (node=hsr3-db0, call=-1, rc=193, last-rc-change=Fri Jun 8 22:37:46 2018, exec=0ms): pending
|
||||
+ # rsc_SAPHanaTopology_HN1_HDB03 (ocf::suse:SAPHanaTopology): Started: rsc_SAPHanaTopology_HN1_HDB03_start_0 (node=hsr3-db0, call=90, rc=0, last-rc-change=Fri Jun 8 22:37:46 2018, exec=3214ms): complete
|
||||
+ ocf.logger.debug("listOperationsOnNode: begin; node = %s" % node)
|
||||
+
|
||||
+ resources = clusterHelper._exec("crm_resource", "--list-operations", "-N", node)
|
||||
+ if len(resources) == 0:
|
||||
+ ret = []
|
||||
+ else:
|
||||
+ ret = resources.split("\n")
|
||||
+
|
||||
+ ocf.logger.debug("listOperationsOnNode: finished; return = %s" % str(ret))
|
||||
+ return ret
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def noPendingResourcesOnNode(node):
|
||||
+ """
|
||||
+ Check that there are no pending resources on a given node
|
||||
+ """
|
||||
+ ocf.logger.debug("noPendingResourcesOnNode: begin; node = %s" % node)
|
||||
+
|
||||
+ for r in clusterHelper.listOperationsOnNode(node):
|
||||
+ ocf.logger.debug("noPendingResourcesOnNode: * %s" % r)
|
||||
+ resource = r.split()[-1]
|
||||
+ if resource == "pending":
|
||||
+ ocf.logger.info("noPendingResourcesOnNode: found resource %s that is still pending" % resource)
|
||||
+ ocf.logger.debug("noPendingResourcesOnNode: finished; return = False")
|
||||
+ return False
|
||||
+ ocf.logger.info("noPendingResourcesOnNode: no pending resources on node %s" % node)
|
||||
+ ocf.logger.debug("noPendingResourcesOnNode: finished; return = True")
|
||||
+
|
||||
+ return True
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def allResourcesStoppedOnNode(node):
|
||||
+ """
|
||||
+ Check that all resources on a given node are stopped
|
||||
+ """
|
||||
+ ocf.logger.debug("allResourcesStoppedOnNode: begin; node = %s" % node)
|
||||
+
|
||||
+ if clusterHelper.noPendingResourcesOnNode(node):
|
||||
+ if len(clusterHelper.transitionSummary()) == 0:
|
||||
+ ocf.logger.info("allResourcesStoppedOnNode: no pending resources on node %s and empty transition summary" % node)
|
||||
+ ocf.logger.debug("allResourcesStoppedOnNode: finished; return = True")
|
||||
+ return True
|
||||
+ ocf.logger.info("allResourcesStoppedOnNode: transition summary is not empty")
|
||||
+ ocf.logger.debug("allResourcesStoppedOnNode: finished; return = False")
|
||||
+ return False
|
||||
+
|
||||
+ ocf.logger.info("allResourcesStoppedOnNode: still pending resources on node %s" % node)
|
||||
+ ocf.logger.debug("allResourcesStoppedOnNode: finished; return = False")
|
||||
+ return False
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+AVAILABLE = 0 # Node is online and ready to handle events
|
||||
+STOPPING = 1 # Standby has been triggered, but some resources are still running
|
||||
+IN_EVENT = 2 # All resources are stopped, and event has been initiated via Azure Metadata Service
|
||||
+ON_HOLD = 3 # Node has a pending event that cannot be started there are no other nodes available
|
||||
+
|
||||
+def stringToNodeState(name):
|
||||
+ if type(name) == int: return name
|
||||
+ if name == "STOPPING": return STOPPING
|
||||
+ if name == "IN_EVENT": return IN_EVENT
|
||||
+ if name == "ON_HOLD": return ON_HOLD
|
||||
+ return AVAILABLE
|
||||
+
|
||||
+def nodeStateToString(state):
|
||||
+ if state == STOPPING: return "STOPPING"
|
||||
+ if state == IN_EVENT: return "IN_EVENT"
|
||||
+ if state == ON_HOLD: return "ON_HOLD"
|
||||
+ return "AVAILABLE"
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+class Node:
|
||||
+ """
|
||||
+ Core class implementing logic for a cluster node
|
||||
+ """
|
||||
+ def __init__(self, ra):
|
||||
+ self.raOwner = ra
|
||||
+ self.azInfo = azHelper.getInstanceInfo()
|
||||
+ self.azName = self.azInfo.name
|
||||
+ self.hostName = socket.gethostname()
|
||||
+ self.setAttr("azName", self.azName)
|
||||
+ clusterHelper.setAttr("hostName_%s" % self.azName, self.hostName)
|
||||
+
|
||||
+ def getAttr(self, key):
|
||||
+ """
|
||||
+ Get a local attribute
|
||||
+ """
|
||||
+ return clusterHelper.getAttr(key, node=self.hostName)
|
||||
+
|
||||
+ def setAttr(self, key, value):
|
||||
+ """
|
||||
+ Set a local attribute
|
||||
+ """
|
||||
+ return clusterHelper.setAttr(key, value, node=self.hostName)
|
||||
+
|
||||
+ def selfOrOtherNode(self, node):
|
||||
+ """
|
||||
+ Helper function to distinguish self/other node
|
||||
+ """
|
||||
+ return node if node else self.hostName
|
||||
+
|
||||
+ def setState(self, state, node=None):
|
||||
+ """
|
||||
+ Set the state for a given node (or self)
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("setState: begin; node = %s, state = %s" % (node, nodeStateToString(state)))
|
||||
+
|
||||
+ clusterHelper.setAttr(attr_curNodeState, nodeStateToString(state), node=node)
|
||||
+
|
||||
+ ocf.logger.debug("setState: finished")
|
||||
+
|
||||
+ def getState(self, node=None):
|
||||
+ """
|
||||
+ Get the state for a given node (or self)
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("getState: begin; node = %s" % node)
|
||||
+
|
||||
+ state = clusterHelper.getAttr(attr_curNodeState, node=node)
|
||||
+ ocf.logger.debug("getState: state = %s" % state)
|
||||
+ ocf.logger.debug("getState: finished")
|
||||
+ if not state:
|
||||
+ return AVAILABLE
|
||||
+ return stringToNodeState(state)
|
||||
+
|
||||
+ def setEventIDs(self, eventIDs, node=None):
|
||||
+ """
|
||||
+ Set pending EventIDs for a given node (or self)
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("setEventIDs: begin; node = %s, eventIDs = %s" % (node, str(eventIDs)))
|
||||
+
|
||||
+ if eventIDs:
|
||||
+ eventIDStr = ",".join(eventIDs)
|
||||
+ else:
|
||||
+ eventIDStr = None
|
||||
+ clusterHelper.setAttr(attr_pendingEventIDs, eventIDStr, node=node)
|
||||
+
|
||||
+ ocf.logger.debug("setEventIDs: finished")
|
||||
+ return
|
||||
+
|
||||
+ def getEventIDs(self, node=None):
|
||||
+ """
|
||||
+ Get pending EventIDs for a given node (or self)
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("getEventIDs: begin; node = %s" % node)
|
||||
+
|
||||
+ eventIDStr = clusterHelper.getAttr(attr_pendingEventIDs, node=node)
|
||||
+ if eventIDStr:
|
||||
+ eventIDs = eventIDStr.split(",")
|
||||
+ else:
|
||||
+ eventIDs = None
|
||||
+
|
||||
+ ocf.logger.debug("getEventIDs: finished; eventIDs = %s" % str(eventIDs))
|
||||
+ return eventIDs
|
||||
+
|
||||
+ def updateNodeStateAndEvents(self, state, eventIDs, node=None):
|
||||
+ """
|
||||
+ Set the state and pending EventIDs for a given node (or self)
|
||||
+ """
|
||||
+ ocf.logger.debug("updateNodeStateAndEvents: begin; node = %s, state = %s, eventIDs = %s" % (node, nodeStateToString(state), str(eventIDs)))
|
||||
+
|
||||
+ self.setState(state, node=node)
|
||||
+ self.setEventIDs(eventIDs, node=node)
|
||||
+
|
||||
+ ocf.logger.debug("updateNodeStateAndEvents: finished")
|
||||
+ return state
|
||||
+
|
||||
+ def putNodeStandby(self, node=None):
|
||||
+ """
|
||||
+ Put self to standby
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("putNodeStandby: begin; node = %s" % node)
|
||||
+
|
||||
+ clusterHelper._exec("crm_attribute",
|
||||
+ "--node", node,
|
||||
+ "--name", attr_healthstate,
|
||||
+ "--update", "-1000000",
|
||||
+ "--lifetime=forever")
|
||||
+
|
||||
+ ocf.logger.debug("putNodeStandby: finished")
|
||||
+
|
||||
+ def isNodeInStandby(self, node=None):
|
||||
+ """
|
||||
+ check if node is in standby
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("isNodeInStandby: begin; node = %s" % node)
|
||||
+ isInStandy = False
|
||||
+
|
||||
+ healthAttributeStr = clusterHelper.getAttr(attr_healthstate, node)
|
||||
+ if healthAttributeStr is not None:
|
||||
+ try:
|
||||
+ healthAttribute = int(healthAttributeStr)
|
||||
+ isInStandy = healthAttribute < 0
|
||||
+ except ValueError:
|
||||
+ # Handle the exception
|
||||
+ ocf.logger.warn("Health attribute %s on node %s cannot be converted to an integer value" % (healthAttributeStr, node))
|
||||
+
|
||||
+ ocf.logger.debug("isNodeInStandby: finished - result %s" % isInStandy)
|
||||
+ return isInStandy
|
||||
+
|
||||
+ def putNodeOnline(self, node=None):
|
||||
+ """
|
||||
+ Put self back online
|
||||
+ """
|
||||
+ node = self.selfOrOtherNode(node)
|
||||
+ ocf.logger.debug("putNodeOnline: begin; node = %s" % node)
|
||||
+
|
||||
+ clusterHelper._exec("crm_attribute",
|
||||
+ "--node", node,
|
||||
+ "--name", "#health-azure",
|
||||
+ "--update", "0",
|
||||
+ "--lifetime=forever")
|
||||
+
|
||||
+ ocf.logger.debug("putNodeOnline: finished")
|
||||
+
|
||||
+ def separateEvents(self, events):
|
||||
+ """
|
||||
+ Split own/other nodes' events
|
||||
+ """
|
||||
+ ocf.logger.debug("separateEvents: begin; events = %s" % str(events))
|
||||
+
|
||||
+ localEvents = []
|
||||
+ remoteEvents = []
|
||||
+ for e in events:
|
||||
+ e = attrDict(e)
|
||||
+ if e.EventType not in self.raOwner.relevantEventTypes:
|
||||
+ continue
|
||||
+ if self.azName in e.Resources:
|
||||
+ localEvents.append(e)
|
||||
+ else:
|
||||
+ remoteEvents.append(e)
|
||||
+ ocf.logger.debug("separateEvents: finished; localEvents = %s, remoteEvents = %s" % (str(localEvents), str(remoteEvents)))
|
||||
+ return (localEvents, remoteEvents)
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+class raAzEvents:
|
||||
+ """
|
||||
+ Main class for resource agent
|
||||
+ """
|
||||
+ def __init__(self, relevantEventTypes):
|
||||
+ self.node = Node(self)
|
||||
+ self.relevantEventTypes = relevantEventTypes
|
||||
+
|
||||
+ def monitor(self):
|
||||
+ ocf.logger.debug("monitor: begin")
|
||||
+
|
||||
+ events = azHelper.pullScheduledEvents()
|
||||
+
|
||||
+ # get current document version
|
||||
+ curDocVersion = events.DocumentIncarnation
|
||||
+ lastDocVersion = self.node.getAttr(attr_lastDocVersion)
|
||||
+ ocf.logger.debug("monitor: lastDocVersion = %s; curDocVersion = %s" % (lastDocVersion, curDocVersion))
|
||||
+
|
||||
+ # split events local/remote
|
||||
+ (localEvents, remoteEvents) = self.node.separateEvents(events.Events)
|
||||
+
|
||||
+ # ensure local events are only executing once
|
||||
+ if curDocVersion == lastDocVersion:
|
||||
+ ocf.logger.info("monitor: already handled curDocVersion, skip")
|
||||
+ return ocf.OCF_SUCCESS
|
||||
+
|
||||
+ localAzEventIDs = set()
|
||||
+ for e in localEvents:
|
||||
+ localAzEventIDs.add(e.EventId)
|
||||
+
|
||||
+ curState = self.node.getState()
|
||||
+ clusterEventIDs = self.node.getEventIDs()
|
||||
+
|
||||
+ ocf.logger.debug("monitor: curDocVersion has not been handled yet")
|
||||
+
|
||||
+ if clusterEventIDs:
|
||||
+ # there are pending events set, so our state must be STOPPING or IN_EVENT
|
||||
+ i = 0; touchedEventIDs = False
|
||||
+ while i < len(clusterEventIDs):
|
||||
+ # clean up pending events that are already finished according to AZ
|
||||
+ if clusterEventIDs[i] not in localAzEventIDs:
|
||||
+ ocf.logger.info("monitor: remove finished local clusterEvent %s" % (clusterEventIDs[i]))
|
||||
+ clusterEventIDs.pop(i)
|
||||
+ touchedEventIDs = True
|
||||
+ else:
|
||||
+ i += 1
|
||||
+ if len(clusterEventIDs) > 0:
|
||||
+ # there are still pending events (either because we're still stopping, or because the event is still in place)
|
||||
+ # either way, we need to wait
|
||||
+ if touchedEventIDs:
|
||||
+ ocf.logger.info("monitor: added new local clusterEvent %s" % str(clusterEventIDs))
|
||||
+ self.node.setEventIDs(clusterEventIDs)
|
||||
+ else:
|
||||
+ ocf.logger.info("monitor: no local clusterEvents were updated")
|
||||
+ else:
|
||||
+ # there are no more pending events left after cleanup
|
||||
+ if clusterHelper.noPendingResourcesOnNode(self.node.hostName):
|
||||
+ # and no pending resources on the node -> set it back online
|
||||
+ ocf.logger.info("monitor: all local events finished -> clean up, put node online and AVAILABLE")
|
||||
+ curState = self.node.updateNodeStateAndEvents(AVAILABLE, None)
|
||||
+ self.node.putNodeOnline()
|
||||
+ clusterHelper.removeHoldFromNodes()
|
||||
+ # If Azure Scheduled Events are not used for 24 hours (e.g. because the cluster was asleep), it will be disabled for a VM.
|
||||
+ # When the cluster wakes up and starts using it again, the DocumentIncarnation is reset.
|
||||
+ # We need to remove it during cleanup, otherwise azure-events-az will not process the event after wakeup
|
||||
+ self.node.setAttr(attr_lastDocVersion, None)
|
||||
+ else:
|
||||
+ ocf.logger.info("monitor: all local events finished, but some resources have not completed startup yet -> wait")
|
||||
+ else:
|
||||
+ if curState == AVAILABLE:
|
||||
+ if len(localAzEventIDs) > 0:
|
||||
+ if clusterHelper.otherNodesAvailable(self.node):
|
||||
+ ocf.logger.info("monitor: can handle local events %s -> set state STOPPING" % (str(localAzEventIDs)))
|
||||
+ curState = self.node.updateNodeStateAndEvents(STOPPING, localAzEventIDs)
|
||||
+ else:
|
||||
+ ocf.logger.info("monitor: cannot handle azEvents %s (only node available) -> set state ON_HOLD" % str(localAzEventIDs))
|
||||
+ self.node.setState(ON_HOLD)
|
||||
+ else:
|
||||
+ ocf.logger.debug("monitor: no local azEvents to handle")
|
||||
+
|
||||
+ if curState == STOPPING:
|
||||
+ eventIDsForNode = {}
|
||||
+ if clusterHelper.noPendingResourcesOnNode(self.node.hostName):
|
||||
+ if not self.node.isNodeInStandby():
|
||||
+ ocf.logger.info("monitor: all local resources are started properly -> put node standby and exit")
|
||||
+ self.node.putNodeStandby()
|
||||
+ return ocf.OCF_SUCCESS
|
||||
+
|
||||
+ for e in localEvents:
|
||||
+ ocf.logger.info("monitor: handling remote event %s (%s; nodes = %s)" % (e.EventId, e.EventType, str(e.Resources)))
|
||||
+ # before we can force an event to start, we need to ensure all nodes involved have stopped their resources
|
||||
+ if e.EventStatus == "Scheduled":
|
||||
+ allNodesStopped = True
|
||||
+ for azName in e.Resources:
|
||||
+ hostName = clusterHelper.getHostNameFromAzName(azName)
|
||||
+ state = self.node.getState(node=hostName)
|
||||
+ if state == STOPPING:
|
||||
+ # the only way we can continue is when node state is STOPPING, but all resources have been stopped
|
||||
+ if not clusterHelper.allResourcesStoppedOnNode(hostName):
|
||||
+ ocf.logger.info("monitor: (at least) node %s has still resources running -> wait" % hostName)
|
||||
+ allNodesStopped = False
|
||||
+ break
|
||||
+ elif state in (AVAILABLE, IN_EVENT, ON_HOLD):
|
||||
+ ocf.logger.info("monitor: node %s is still %s -> remote event needs to be picked up locally" % (hostName, nodeStateToString(state)))
|
||||
+ allNodesStopped = False
|
||||
+ break
|
||||
+ if allNodesStopped:
|
||||
+ ocf.logger.info("monitor: nodes %s are stopped -> add remote event %s to force list" % (str(e.Resources), e.EventId))
|
||||
+ for n in e.Resources:
|
||||
+ hostName = clusterHelper.getHostNameFromAzName(n)
|
||||
+ if hostName in eventIDsForNode:
|
||||
+ eventIDsForNode[hostName].append(e.EventId)
|
||||
+ else:
|
||||
+ eventIDsForNode[hostName] = [e.EventId]
|
||||
+ elif e.EventStatus == "Started":
|
||||
+ ocf.logger.info("monitor: remote event already started")
|
||||
+
|
||||
+ # force the start of all events whose nodes are ready (i.e. have no more resources running)
|
||||
+ if len(eventIDsForNode.keys()) > 0:
|
||||
+ eventIDsToForce = set([item for sublist in eventIDsForNode.values() for item in sublist])
|
||||
+ ocf.logger.info("monitor: set nodes %s to IN_EVENT; force remote events %s" % (str(eventIDsForNode.keys()), str(eventIDsToForce)))
|
||||
+ for node, eventId in eventIDsForNode.items():
|
||||
+ self.node.updateNodeStateAndEvents(IN_EVENT, eventId, node=node)
|
||||
+ azHelper.forceEvents(eventIDsToForce)
|
||||
+ self.node.setAttr(attr_lastDocVersion, curDocVersion)
|
||||
+ else:
|
||||
+ ocf.logger.info("monitor: some local resources are not clean yet -> wait")
|
||||
+
|
||||
+ ocf.logger.debug("monitor: finished")
|
||||
+ return ocf.OCF_SUCCESS
|
||||
+
|
||||
+##############################################################################
|
||||
+
|
||||
+def setLoglevel(verbose):
|
||||
+ # set up writing into syslog
|
||||
+ loglevel = default_loglevel
|
||||
+ if verbose:
|
||||
+ opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1))
|
||||
+ urllib2.install_opener(opener)
|
||||
+ loglevel = ocf.logging.DEBUG
|
||||
+ ocf.log.setLevel(loglevel)
|
||||
+
|
||||
+description = (
|
||||
+ "Microsoft Azure Scheduled Events monitoring agent",
|
||||
+ """This resource agent implements a monitor for scheduled
|
||||
+(maintenance) events for a Microsoft Azure VM.
|
||||
+
|
||||
+If any relevant events are found, it moves all Pacemaker resources
|
||||
+away from the affected node to allow for a graceful shutdown.
|
||||
+
|
||||
+ Usage:
|
||||
+ [OCF_RESKEY_eventTypes=VAL] [OCF_RESKEY_verbose=VAL] azure-events-az ACTION
|
||||
+
|
||||
+ action (required): Supported values: monitor, help, meta-data
|
||||
+ eventTypes (optional): List of event types to be considered
|
||||
+ relevant by the resource agent (comma-separated).
|
||||
+ Supported values: Freeze,Reboot,Redeploy
|
||||
+ Default = Reboot,Redeploy
|
||||
+/ verbose (optional): If set to true, displays debug info.
|
||||
+ Default = false
|
||||
+
|
||||
+ Deployment:
|
||||
+ crm configure primitive rsc_azure-events-az ocf:heartbeat:azure-events-az \
|
||||
+ op monitor interval=10s
|
||||
+ crm configure clone cln_azure-events-az rsc_azure-events-az
|
||||
+
|
||||
+For further information on Microsoft Azure Scheduled Events, please
|
||||
+refer to the following documentation:
|
||||
+https://docs.microsoft.com/en-us/azure/virtual-machines/linux/scheduled-events
|
||||
+""")
|
||||
+
|
||||
+def monitor_action(eventTypes):
|
||||
+ relevantEventTypes = set(eventTypes.split(",") if eventTypes else [])
|
||||
+ ra = raAzEvents(relevantEventTypes)
|
||||
+ return ra.monitor()
|
||||
+
|
||||
+def validate_action(eventTypes):
|
||||
+ if eventTypes:
|
||||
+ for event in eventTypes.split(","):
|
||||
+ if event not in ("Freeze", "Reboot", "Redeploy"):
|
||||
+ ocf.ocf_exit_reason("Event type not one of Freeze, Reboot, Redeploy: " + eventTypes)
|
||||
+ return ocf.OCF_ERR_CONFIGURED
|
||||
+ return ocf.OCF_SUCCESS
|
||||
+
|
||||
+def main():
|
||||
+ agent = ocf.Agent("azure-events-az", shortdesc=description[0], longdesc=description[1])
|
||||
+ agent.add_parameter(
|
||||
+ "eventTypes",
|
||||
+ shortdesc="List of resources to be considered",
|
||||
+ longdesc="A comma-separated list of event types that will be handled by this resource agent. (Possible values: Freeze,Reboot,Redeploy)",
|
||||
+ content_type="string",
|
||||
+ default="Reboot,Redeploy")
|
||||
+ agent.add_parameter(
|
||||
+ "verbose",
|
||||
+ shortdesc="Enable verbose agent logging",
|
||||
+ longdesc="Set to true to enable verbose logging",
|
||||
+ content_type="boolean",
|
||||
+ default="false")
|
||||
+ agent.add_action("start", timeout=10, handler=lambda: ocf.OCF_SUCCESS)
|
||||
+ agent.add_action("stop", timeout=10, handler=lambda: ocf.OCF_SUCCESS)
|
||||
+ agent.add_action("validate-all", timeout=20, handler=validate_action)
|
||||
+ agent.add_action("monitor", timeout=240, interval=10, handler=monitor_action)
|
||||
+ setLoglevel(ocf.is_true(ocf.get_parameter("verbose", "false")))
|
||||
+ agent.run()
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ main()
|
||||
\ No newline at end of file
|
||||
|
||||
From a95337d882c7cc69d604b050159ad50b679f18be Mon Sep 17 00:00:00 2001
|
||||
From: MSSedusch <sedusch@microsoft.com>
|
||||
Date: Thu, 2 Jun 2022 14:10:33 +0200
|
||||
Subject: [PATCH 2/2] Remove developer documentation
|
||||
|
||||
---
|
||||
heartbeat/azure-events-az.in | 11 -----------
|
||||
1 file changed, 11 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/azure-events-az.in b/heartbeat/azure-events-az.in
|
||||
index 616fc8d9e..59d095306 100644
|
||||
--- a/heartbeat/azure-events-az.in
|
||||
+++ b/heartbeat/azure-events-az.in
|
||||
@@ -723,17 +723,6 @@ description = (
|
||||
If any relevant events are found, it moves all Pacemaker resources
|
||||
away from the affected node to allow for a graceful shutdown.
|
||||
|
||||
- Usage:
|
||||
- [OCF_RESKEY_eventTypes=VAL] [OCF_RESKEY_verbose=VAL] azure-events-az ACTION
|
||||
-
|
||||
- action (required): Supported values: monitor, help, meta-data
|
||||
- eventTypes (optional): List of event types to be considered
|
||||
- relevant by the resource agent (comma-separated).
|
||||
- Supported values: Freeze,Reboot,Redeploy
|
||||
- Default = Reboot,Redeploy
|
||||
-/ verbose (optional): If set to true, displays debug info.
|
||||
- Default = false
|
||||
-
|
||||
Deployment:
|
||||
crm configure primitive rsc_azure-events-az ocf:heartbeat:azure-events-az \
|
||||
op monitor interval=10s
|
@ -1,24 +0,0 @@
|
||||
From ed5bc606a4db5108995df9297698cf9dc14cccb2 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 18 Jan 2022 11:32:05 +0100
|
||||
Subject: [PATCH] mysql-common: fix local SSL connection by using
|
||||
--ssl-mode=REQUIRED which is available on 5.7+ (--ssl is not available in
|
||||
8.0)
|
||||
|
||||
---
|
||||
heartbeat/mysql-common.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/mysql-common.sh b/heartbeat/mysql-common.sh
|
||||
index 459948b10..de8763544 100755
|
||||
--- a/heartbeat/mysql-common.sh
|
||||
+++ b/heartbeat/mysql-common.sh
|
||||
@@ -97,7 +97,7 @@ MYSQL_BINDIR=`dirname ${OCF_RESKEY_binary}`
|
||||
|
||||
MYSQL=$OCF_RESKEY_client_binary
|
||||
if ocf_is_true "$OCF_RESKEY_replication_require_ssl"; then
|
||||
- MYSQL_OPTIONS_LOCAL_SSL_OPTIONS="--ssl"
|
||||
+ MYSQL_OPTIONS_LOCAL_SSL_OPTIONS="--ssl-mode=REQUIRED"
|
||||
else
|
||||
MYSQL_OPTIONS_LOCAL_SSL_OPTIONS=""
|
||||
fi
|
@ -1,23 +0,0 @@
|
||||
From 09cde6531a87fd6a04568eaae94d5c489f36a8b6 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 6 Sep 2021 15:07:41 +0200
|
||||
Subject: [PATCH] storage-mon: update metadata to suggest usage in combination
|
||||
with HealthSMART agent
|
||||
|
||||
---
|
||||
heartbeat/storage-mon.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/storage-mon.in b/heartbeat/storage-mon.in
|
||||
index 5b289fe55..875095670 100644
|
||||
--- a/heartbeat/storage-mon.in
|
||||
+++ b/heartbeat/storage-mon.in
|
||||
@@ -75,7 +75,7 @@ meta_data() {
|
||||
<longdesc lang="en">
|
||||
System health agent that checks the storage I/O status of the given drives and
|
||||
updates the #health-storage attribute. Usage is highly recommended in combination
|
||||
-with storage-mon monitoring agent. The agent currently support a maximum of 25
|
||||
+with the HealthSMART monitoring agent. The agent currently support a maximum of 25
|
||||
devices per instance.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">storage I/O health status</shortdesc>
|
File diff suppressed because it is too large
Load Diff
@ -1,64 +0,0 @@
|
||||
From fcd2565602146c0b9317d159cecb8935e304c7ce Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 30 Sep 2021 10:23:17 +0200
|
||||
Subject: [PATCH] gcp-pd-move/gcp-vpc-move-route: dont fail failed resources
|
||||
instantly (caused by OCF_ERR_CONFIGURED)
|
||||
|
||||
---
|
||||
heartbeat/gcp-pd-move.in | 4 ++--
|
||||
heartbeat/gcp-vpc-move-route.in | 6 +++---
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/gcp-pd-move.in b/heartbeat/gcp-pd-move.in
|
||||
index e99cc71f88..cbe703c3c5 100644
|
||||
--- a/heartbeat/gcp-pd-move.in
|
||||
+++ b/heartbeat/gcp-pd-move.in
|
||||
@@ -157,7 +157,7 @@ def populate_vars():
|
||||
CONN = googleapiclient.discovery.build('compute', 'v1')
|
||||
except Exception as e:
|
||||
logger.error('Couldn\'t connect with google api: ' + str(e))
|
||||
- sys.exit(ocf.OCF_ERR_CONFIGURED)
|
||||
+ sys.exit(ocf.OCF_ERR_GENERIC)
|
||||
|
||||
for param in PARAMETERS:
|
||||
value = os.environ.get('OCF_RESKEY_%s' % param, PARAMETERS[param])
|
||||
@@ -172,7 +172,7 @@ def populate_vars():
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
'Couldn\'t get instance name, is this running inside GCE?: ' + str(e))
|
||||
- sys.exit(ocf.OCF_ERR_CONFIGURED)
|
||||
+ sys.exit(ocf.OCF_ERR_GENERIC)
|
||||
|
||||
PROJECT = get_metadata('project/project-id')
|
||||
if PARAMETERS['disk_scope'] in ['detect', 'regional']:
|
||||
diff --git a/heartbeat/gcp-vpc-move-route.in b/heartbeat/gcp-vpc-move-route.in
|
||||
index dac6e4ea8c..6b240c04d0 100644
|
||||
--- a/heartbeat/gcp-vpc-move-route.in
|
||||
+++ b/heartbeat/gcp-vpc-move-route.in
|
||||
@@ -243,7 +243,7 @@ def validate(ctx):
|
||||
ctx.conn = googleapiclient.discovery.build('compute', 'v1', credentials=credentials, cache_discovery=False)
|
||||
except Exception as e:
|
||||
logger.error('Couldn\'t connect with google api: ' + str(e))
|
||||
- sys.exit(OCF_ERR_CONFIGURED)
|
||||
+ sys.exit(OCF_ERR_GENERIC)
|
||||
|
||||
ctx.ip = os.environ.get('OCF_RESKEY_ip')
|
||||
if not ctx.ip:
|
||||
@@ -258,7 +258,7 @@ def validate(ctx):
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
'Instance information not found. Is this a GCE instance ?: %s', str(e))
|
||||
- sys.exit(OCF_ERR_CONFIGURED)
|
||||
+ sys.exit(OCF_ERR_GENERIC)
|
||||
|
||||
ctx.instance_url = '%s/projects/%s/zones/%s/instances/%s' % (
|
||||
GCP_API_URL_PREFIX, ctx.project, ctx.zone, ctx.instance)
|
||||
@@ -273,7 +273,7 @@ def validate(ctx):
|
||||
idxs = ctx.iproute.link_lookup(ifname=ctx.interface)
|
||||
if not idxs:
|
||||
logger.error('Network interface not found')
|
||||
- sys.exit(OCF_ERR_CONFIGURED)
|
||||
+ sys.exit(OCF_ERR_GENERIC)
|
||||
ctx.iface_idx = idxs[0]
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
From 7c54e4ecda33c90a1046c0688774f5b847ab10fe Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 7 Dec 2021 10:37:24 +0100
|
||||
Subject: [PATCH] Route: return OCF_NOT_RUNNING for probe action when interface
|
||||
or route doesnt exist
|
||||
|
||||
---
|
||||
heartbeat/Route | 15 +++++----------
|
||||
1 file changed, 5 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Route b/heartbeat/Route
|
||||
index 8b390615a..7db41d0ae 100755
|
||||
--- a/heartbeat/Route
|
||||
+++ b/heartbeat/Route
|
||||
@@ -227,15 +227,6 @@ route_stop() {
|
||||
}
|
||||
|
||||
route_status() {
|
||||
- if [ -n "${OCF_RESKEY_device}" ]; then
|
||||
- # Must check if device exists or is gone.
|
||||
- # If device is gone, route is also unconfigured.
|
||||
- ip link show dev ${OCF_RESKEY_device} >/dev/null 2>&1
|
||||
- if [ $? -ne 0 ]; then
|
||||
- # Assume device does not exist, and short-circuit here.
|
||||
- return $OCF_NOT_RUNNING
|
||||
- fi
|
||||
- fi
|
||||
show_output="$(ip $addr_family route show $(create_route_spec) 2>/dev/null)"
|
||||
if [ $? -eq 0 ]; then
|
||||
if [ -n "$show_output" ]; then
|
||||
@@ -251,7 +242,11 @@ route_status() {
|
||||
else
|
||||
# "ip route show" returned an error code. Assume something
|
||||
# went wrong.
|
||||
- return $OCF_ERR_GENERIC
|
||||
+ if ocf_is_probe; then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ else
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
fi
|
||||
}
|
||||
|
@ -1,366 +0,0 @@
|
||||
From 764dacb6195f8940f13b9c322b1bc8189c5619fc Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Mon, 6 Sep 2021 12:13:42 +0200
|
||||
Subject: [PATCH 1/6] Fix NFSv4 lock failover: set NFS Server Scope
|
||||
|
||||
Problem: https://github.com/ClusterLabs/resource-agents/issues/1644
|
||||
RFC8881, 8.4.2.1 State Reclaim:
|
||||
|
||||
| If the server scope is different, the client should not attempt to
|
||||
| reclaim locks. In this situation, no lock reclaim is possible.
|
||||
| Any attempt to re-obtain the locks with non-reclaim operations is
|
||||
| problematic since there is no guarantee that the existing
|
||||
| filehandles will be recognized by the new server, or that if
|
||||
| recognized, they denote the same objects. It is best to treat the
|
||||
| locks as having been revoked by the reconfiguration event.
|
||||
|
||||
That's why for lock reclaim to even be attempted, we have to define and set
|
||||
the same server scope for NFSD on all cluster nodes in the NFS failover
|
||||
cluster. And in linux, that is done by setting the uts nodename for the
|
||||
command that starts the nfsd kernel threads.
|
||||
|
||||
For "init scripts", just set it directly using unshare --uts.
|
||||
For systemd units, add NFS_SERVER_SCOPE to some environment files
|
||||
and inject the "unshare --uts" into the ExecStart command lines
|
||||
using override drop-in files.
|
||||
---
|
||||
heartbeat/nfsserver | 120 +++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 119 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 96b19abe36..0888378645 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -5,6 +5,18 @@
|
||||
# by hxinwei@gmail.com
|
||||
# License: GNU General Public License v2 (GPLv2) and later
|
||||
|
||||
+
|
||||
+# I don't know for certain whether all services actuall _need_ this,
|
||||
+# I know that at least nfs-server needs it.
|
||||
+# The rgmanager resource agent in rgmanager/src/resources/nfsserver.sh.in
|
||||
+# did the unshare for gssd and idmapd as well, even though it seems unclear why.
|
||||
+# Let's start with just the nfs-server, and add others if/when we have clear
|
||||
+# indication they need it.
|
||||
+#NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-idmapd.service nfs-mountd.service nfs-server.service nfsdcld.service rpc-gssd.service rpc-statd.service rpcbind.service"
|
||||
+NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-server.service"
|
||||
+SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE=/run/sysconfig/nfs-server-scope
|
||||
+SYSTEMD_UNSHARE_UTS_DROPIN=51-resource-agents-unshare-uts.conf
|
||||
+
|
||||
if [ -n "$OCF_DEBUG_LIBRARY" ]; then
|
||||
. $OCF_DEBUG_LIBRARY
|
||||
else
|
||||
@@ -99,6 +111,31 @@ Specifies the length of sm-notify retry time (minutes).
|
||||
<content type="integer" default="" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="nfs_server_scope" unique="0" required="0">
|
||||
+<longdesc lang="en">
|
||||
+RFC8881, 8.4.2.1 State Reclaim:
|
||||
+
|
||||
+If the server scope is different, the client should not attempt to
|
||||
+reclaim locks. In this situation, no lock reclaim is possible.
|
||||
+Any attempt to re-obtain the locks with non-reclaim operations is
|
||||
+problematic since there is no guarantee that the existing
|
||||
+filehandles will be recognized by the new server, or that if
|
||||
+recognized, they denote the same objects. It is best to treat the
|
||||
+locks as having been revoked by the reconfiguration event.
|
||||
+
|
||||
+For lock reclaim to even be attempted, we have to define and set the same
|
||||
+server scope for NFSD on all cluster nodes in the NFS failover cluster.
|
||||
+
|
||||
+This agent won't "guess" a suitable server scope name for you, you need to
|
||||
+explicitly specify this. But without it, NFSv4 lock reclaim after failover
|
||||
+won't work properly. Suggested value: the failover "service IP".
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">
|
||||
+RFC8881 NFS server scope for (lock) state reclaim after failover.
|
||||
+</shortdesc>
|
||||
+<content type="string"/>
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="nfs_ip" unique="0" required="0">
|
||||
<longdesc lang="en">
|
||||
Comma separated list of floating IP addresses used to access the nfs service
|
||||
@@ -269,7 +306,11 @@ nfs_exec()
|
||||
set_exec_mode
|
||||
|
||||
case $EXEC_MODE in
|
||||
- 1) ${OCF_RESKEY_nfs_init_script} $cmd;;
|
||||
+ 1) if [ -z "$OCF_RESKEY_nfs_server_scope" ] ; then
|
||||
+ ${OCF_RESKEY_nfs_init_script} $cmd
|
||||
+ else
|
||||
+ unshare -u /bin/sh -c "hostname ${OCF_RESKEY_nfs_server_scope}; exec ${OCF_RESKEY_nfs_init_script} $cmd"
|
||||
+ fi ;;
|
||||
2) if ! echo $svc | grep -q "\."; then
|
||||
svc="${svc}.service"
|
||||
fi
|
||||
@@ -623,6 +664,74 @@ notify_locks()
|
||||
fi
|
||||
}
|
||||
|
||||
+# Problem: https://github.com/ClusterLabs/resource-agents/issues/1644
|
||||
+# RFC8881, 8.4.2.1 State Reclaim:
|
||||
+#
|
||||
+# | If the server scope is different, the client should not attempt to
|
||||
+# | reclaim locks. In this situation, no lock reclaim is possible.
|
||||
+# | Any attempt to re-obtain the locks with non-reclaim operations is
|
||||
+# | problematic since there is no guarantee that the existing
|
||||
+# | filehandles will be recognized by the new server, or that if
|
||||
+# | recognized, they denote the same objects. It is best to treat the
|
||||
+# | locks as having been revoked by the reconfiguration event.
|
||||
+#
|
||||
+# That's why for lock reclaim to even be attempted, we have to define and set
|
||||
+# the same server scope for NFSD on all cluster nodes in the NFS failover
|
||||
+# cluster. And in linux, that is done by setting the uts nodename for the
|
||||
+# command that starts the nfsd kernel threads.
|
||||
+#
|
||||
+inject_unshare_uts_name_into_systemd_units ()
|
||||
+{
|
||||
+ local END_TAG="# END OF DROP-IN FOR NFS SERVER SCOPE"
|
||||
+ local services
|
||||
+ services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE | cut -d ' ' -f1)
|
||||
+
|
||||
+ local svc dir dropin edited_exec_start do_reload=false
|
||||
+ for svc in $services ; do
|
||||
+ dir=/run/systemd/system/$svc.d
|
||||
+ dropin=$dir/$SYSTEMD_UNSHARE_UTS_DROPIN
|
||||
+ grep -sqF "$END_TAG" "$dropin" && continue
|
||||
+
|
||||
+ test -d "$dir" || mkdir -p "$dir"
|
||||
+ test -e "$dropin" && rm -f "$dropin"
|
||||
+
|
||||
+ edited_exec_start=$(systemctl cat $svc | sed -ne "s#^ExecStart=\\(.*\\)#ExecStart=/usr/bin/unshare --uts /bin/sh -ec 'hostname \${NFS_SERVER_SCOPE}; exec \"\$@\"' -- \\1#p")
|
||||
+ cat > "$dropin" <<___
|
||||
+[Service]
|
||||
+EnvironmentFile=$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE
|
||||
+# reset list of exec start, then re-populate with unshared uts namespace
|
||||
+ExecStart=
|
||||
+$edited_exec_start
|
||||
+$END_TAG
|
||||
+___
|
||||
+ do_reload=true
|
||||
+ ocf_log debug "injected unshare --uts into $dropin"
|
||||
+ done
|
||||
+
|
||||
+ mkdir -p "${SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE%/*}"
|
||||
+ echo "NFS_SERVER_SCOPE=$OCF_RESKEY_nfs_server_scope" > "$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE"
|
||||
+
|
||||
+ $do_reload && systemctl daemon-reload
|
||||
+}
|
||||
+
|
||||
+remove_unshare_uts_dropins ()
|
||||
+{
|
||||
+ local services
|
||||
+ services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE)
|
||||
+
|
||||
+ local svc dir dropin do_reload=false
|
||||
+ for svc in $services ; do
|
||||
+ dir=/run/systemd/system/$svc.d
|
||||
+ dropin=$dir/$SYSTEMD_UNSHARE_UTS_DROPIN
|
||||
+ test -e "$dropin" || continue
|
||||
+ rm -f "$dropin"
|
||||
+ do_reload=true
|
||||
+ ocf_log debug "removed unshare --uts from $svc"
|
||||
+ done
|
||||
+ rm -f "${SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE}"
|
||||
+ $do_reload && systemctl daemon-reload
|
||||
+}
|
||||
+
|
||||
nfsserver_start ()
|
||||
{
|
||||
local rc;
|
||||
@@ -636,6 +745,13 @@ nfsserver_start ()
|
||||
is_redhat_based && set_env_args
|
||||
bind_tree
|
||||
prepare_directory
|
||||
+ case $EXEC_MODE in [23])
|
||||
+ if [ -z "$OCF_RESKEY_nfs_server_scope" ] ; then
|
||||
+ remove_unshare_uts_dropins
|
||||
+ else
|
||||
+ inject_unshare_uts_name_into_systemd_units
|
||||
+ fi ;;
|
||||
+ esac
|
||||
|
||||
if ! `mount | grep -q " on $OCF_RESKEY_rpcpipefs_dir "`; then
|
||||
mount -t rpc_pipefs sunrpc $OCF_RESKEY_rpcpipefs_dir
|
||||
@@ -854,6 +970,8 @@ nfsserver_stop ()
|
||||
ocf_log info "NFS server stopped"
|
||||
fi
|
||||
|
||||
+ case $EXEC_MODE in [23]) remove_unshare_uts_dropins;; esac
|
||||
+
|
||||
return $rc
|
||||
}
|
||||
|
||||
|
||||
From 515697b53c1614d05d39491c9af83e8d8b844b17 Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Fri, 8 Oct 2021 12:01:41 +0200
|
||||
Subject: [PATCH 2/6] Fix NFSv4 lock failover: set NFS Server Scope, regardless
|
||||
of EXEC_MODE
|
||||
|
||||
Debian (and other systems) may provide "init scripts",
|
||||
which will only redirect back to systemd.
|
||||
|
||||
If we just unshare --uts the init script invocation,
|
||||
the uts namespace is useless in that case.
|
||||
|
||||
If systemd is running, mangle the nfs-server.service unit,
|
||||
independent of the "EXEC_MODE".
|
||||
---
|
||||
heartbeat/nfsserver | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 0888378645..054aabbaf6 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -745,13 +745,20 @@ nfsserver_start ()
|
||||
is_redhat_based && set_env_args
|
||||
bind_tree
|
||||
prepare_directory
|
||||
- case $EXEC_MODE in [23])
|
||||
+
|
||||
+ # Debian (and other systems) may provide "init scripts",
|
||||
+ # which will only redirect back to systemd.
|
||||
+ # If we just unshare --uts the init script invocation,
|
||||
+ # the uts namespace is useless in that case.
|
||||
+ # If systemd is running, mangle the nfs-server.service unit,
|
||||
+ # independent of the "EXEC_MODE" we detected.
|
||||
+ if $systemd_is_running ; then
|
||||
if [ -z "$OCF_RESKEY_nfs_server_scope" ] ; then
|
||||
remove_unshare_uts_dropins
|
||||
else
|
||||
inject_unshare_uts_name_into_systemd_units
|
||||
- fi ;;
|
||||
- esac
|
||||
+ fi
|
||||
+ fi
|
||||
|
||||
if ! `mount | grep -q " on $OCF_RESKEY_rpcpipefs_dir "`; then
|
||||
mount -t rpc_pipefs sunrpc $OCF_RESKEY_rpcpipefs_dir
|
||||
@@ -970,7 +977,9 @@ nfsserver_stop ()
|
||||
ocf_log info "NFS server stopped"
|
||||
fi
|
||||
|
||||
- case $EXEC_MODE in [23]) remove_unshare_uts_dropins;; esac
|
||||
+ if $systemd_is_running; then
|
||||
+ remove_unshare_uts_dropins
|
||||
+ fi
|
||||
|
||||
return $rc
|
||||
}
|
||||
@@ -1008,6 +1017,7 @@ nfsserver_validate ()
|
||||
}
|
||||
|
||||
nfsserver_validate
|
||||
+systemd_is_running && systemd_is_running=true || systemd_is_running=false
|
||||
|
||||
case $__OCF_ACTION in
|
||||
start) nfsserver_start
|
||||
|
||||
From e83c20d88f404f9f9d829c654883d60eb6cc9ff3 Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Fri, 8 Oct 2021 17:06:18 +0200
|
||||
Subject: [PATCH 3/6] Fix NFSv4 lock failover: add missing "|cut -f1" in
|
||||
remove_unshare_uts_dropins
|
||||
|
||||
---
|
||||
heartbeat/nfsserver | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 054aabbaf6..d3db89a537 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -717,7 +717,7 @@ ___
|
||||
remove_unshare_uts_dropins ()
|
||||
{
|
||||
local services
|
||||
- services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE)
|
||||
+ services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE | cut -d ' ' -f1)
|
||||
|
||||
local svc dir dropin do_reload=false
|
||||
for svc in $services ; do
|
||||
|
||||
From b5b0e4a0b60d285af576b2d8ecfbe95e5a177a87 Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Fri, 8 Oct 2021 17:07:13 +0200
|
||||
Subject: [PATCH 4/6] Fix NFSv4 lock failover: get rid of "world-inaccessible"
|
||||
warning
|
||||
|
||||
by temporarily changing the umask before generating the dropins
|
||||
---
|
||||
heartbeat/nfsserver | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index d3db89a537..447e0302b2 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -687,6 +687,8 @@ inject_unshare_uts_name_into_systemd_units ()
|
||||
services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE | cut -d ' ' -f1)
|
||||
|
||||
local svc dir dropin edited_exec_start do_reload=false
|
||||
+ local old_umask=$(umask)
|
||||
+ umask 0022
|
||||
for svc in $services ; do
|
||||
dir=/run/systemd/system/$svc.d
|
||||
dropin=$dir/$SYSTEMD_UNSHARE_UTS_DROPIN
|
||||
@@ -710,6 +712,7 @@ ___
|
||||
|
||||
mkdir -p "${SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE%/*}"
|
||||
echo "NFS_SERVER_SCOPE=$OCF_RESKEY_nfs_server_scope" > "$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE"
|
||||
+ umask $old_umask
|
||||
|
||||
$do_reload && systemctl daemon-reload
|
||||
}
|
||||
|
||||
From 3c6c91ce5a00eeef9cd766389d73a0b42580a1e6 Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Fri, 8 Oct 2021 17:08:09 +0200
|
||||
Subject: [PATCH 5/6] Fix NFSv4 lock failover: deal with "special executable
|
||||
prefix" chars in ExecStart
|
||||
|
||||
---
|
||||
heartbeat/nfsserver | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 447e0302b2..5326bd2c6e 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -697,7 +697,7 @@ inject_unshare_uts_name_into_systemd_units ()
|
||||
test -d "$dir" || mkdir -p "$dir"
|
||||
test -e "$dropin" && rm -f "$dropin"
|
||||
|
||||
- edited_exec_start=$(systemctl cat $svc | sed -ne "s#^ExecStart=\\(.*\\)#ExecStart=/usr/bin/unshare --uts /bin/sh -ec 'hostname \${NFS_SERVER_SCOPE}; exec \"\$@\"' -- \\1#p")
|
||||
+ edited_exec_start=$(systemctl cat $svc | sed -ne "s#^ExecStart=\\([-+:!@]*\\)\\(.*\\)#ExecStart=\\1/usr/bin/unshare --uts /bin/sh -c 'hostname \${NFS_SERVER_SCOPE}; exec \"\$@\"' -- \\2#p")
|
||||
cat > "$dropin" <<___
|
||||
[Service]
|
||||
EnvironmentFile=$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE
|
||||
|
||||
From 512fbaf61e6d24a1236ef50e323ea17a62485c36 Mon Sep 17 00:00:00 2001
|
||||
From: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
Date: Fri, 8 Oct 2021 17:08:59 +0200
|
||||
Subject: [PATCH 6/6] Fix NFSv4 lock failover: add rpc-statd-notify to the
|
||||
comment list of potentially interesting services
|
||||
|
||||
---
|
||||
heartbeat/nfsserver | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
|
||||
index 5326bd2c6e..240dd1a76c 100755
|
||||
--- a/heartbeat/nfsserver
|
||||
+++ b/heartbeat/nfsserver
|
||||
@@ -12,7 +12,7 @@
|
||||
# did the unshare for gssd and idmapd as well, even though it seems unclear why.
|
||||
# Let's start with just the nfs-server, and add others if/when we have clear
|
||||
# indication they need it.
|
||||
-#NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-idmapd.service nfs-mountd.service nfs-server.service nfsdcld.service rpc-gssd.service rpc-statd.service rpcbind.service"
|
||||
+#NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-idmapd.service nfs-mountd.service nfs-server.service nfsdcld.service rpc-gssd.service rpc-statd.service rpc-statd-notify.service rpcbind.service"
|
||||
NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-server.service"
|
||||
SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE=/run/sysconfig/nfs-server-scope
|
||||
SYSTEMD_UNSHARE_UTS_DROPIN=51-resource-agents-unshare-uts.conf
|
@ -1,29 +0,0 @@
|
||||
From 9a7b47f1838e9d6e3c807e9db5312097adb5c499 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Fri, 5 Nov 2021 10:30:49 +0100
|
||||
Subject: [PATCH] gcp-ilb/Squid: fix issues detected by CI
|
||||
|
||||
---
|
||||
heartbeat/Squid.in | 2 +-
|
||||
heartbeat/gcp-ilb | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/gcp-ilb b/heartbeat/gcp-ilb
|
||||
index 28484b241..48dc3ac4e 100755
|
||||
--- a/heartbeat/gcp-ilb
|
||||
+++ b/heartbeat/gcp-ilb
|
||||
@@ -53,12 +53,12 @@ pidfile="/var/run/$OCF_RESOURCE_INSTANCE.pid"
|
||||
|
||||
|
||||
#Validate command for logging
|
||||
-if $OCF_RESKEY_log_enable = "true"; then
|
||||
+if [ $OCF_RESKEY_log_enable = "true" ]; then
|
||||
if type $OCF_RESKEY_log_cmd > /dev/null 2>&1; then
|
||||
logging_cmd="$OCF_RESKEY_log_cmd $OCF_RESKEY_log_params"
|
||||
ocf_log debug "Logging command is: \'$logging_cmd\' "
|
||||
else
|
||||
- $OCF_RESKEY_log_enable = "false"
|
||||
+ OCF_RESKEY_log_enable="false"
|
||||
ocf_log err "\'$logging_cmd\' is invalid. External logging disabled."
|
||||
|
||||
fi;
|
@ -1,51 +0,0 @@
|
||||
From 14576f7ca02fb0abff188238ac019e88ab06e878 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 9 Nov 2021 11:49:36 +0100
|
||||
Subject: [PATCH] gcp-ilb: only check if log_cmd binary is available if
|
||||
log_enable is true
|
||||
|
||||
---
|
||||
heartbeat/gcp-ilb | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/gcp-ilb b/heartbeat/gcp-ilb
|
||||
index 48dc3ac4e..f84f373b7 100755
|
||||
--- a/heartbeat/gcp-ilb
|
||||
+++ b/heartbeat/gcp-ilb
|
||||
@@ -37,7 +37,7 @@ if type "socat" > /dev/null 2>&1; then
|
||||
OCF_RESKEY_cat_default="socat"
|
||||
else
|
||||
OCF_RESKEY_cat_default="nc"
|
||||
-fi;
|
||||
+fi
|
||||
|
||||
|
||||
: ${OCF_RESKEY_cat=${OCF_RESKEY_cat_default}}
|
||||
@@ -53,7 +53,7 @@ pidfile="/var/run/$OCF_RESOURCE_INSTANCE.pid"
|
||||
|
||||
|
||||
#Validate command for logging
|
||||
-if [ $OCF_RESKEY_log_enable = "true" ]; then
|
||||
+if ocf_is_true "$OCF_RESKEY_log_enable"; then
|
||||
if type $OCF_RESKEY_log_cmd > /dev/null 2>&1; then
|
||||
logging_cmd="$OCF_RESKEY_log_cmd $OCF_RESKEY_log_params"
|
||||
ocf_log debug "Logging command is: \'$logging_cmd\' "
|
||||
@@ -61,7 +61,7 @@ if [ $OCF_RESKEY_log_enable = "true" ]; then
|
||||
OCF_RESKEY_log_enable="false"
|
||||
ocf_log err "\'$logging_cmd\' is invalid. External logging disabled."
|
||||
|
||||
- fi;
|
||||
+ fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -285,7 +285,8 @@ ilb_stop() {
|
||||
|
||||
ilb_validate() {
|
||||
check_binary "$OCF_RESKEY_cat"
|
||||
- check_binary "$OCF_RESKEY_log_cmd"
|
||||
+
|
||||
+ ocf_is_true "$OCF_RESKEY_log_enable" && check_binary "$OCF_RESKEY_log_cmd"
|
||||
|
||||
if ! ocf_is_decimal "$OCF_RESKEY_port"; then
|
||||
ocf_exit_reason "$OCF_RESKEY_port is not a valid port"
|
@ -1,11 +0,0 @@
|
||||
--- a/heartbeat/gcp-ilb 2021-11-09 14:13:20.311243373 +0100
|
||||
+++ b/heartbeat/gcp-ilb 2021-11-09 14:13:50.269329165 +0100
|
||||
@@ -28,7 +28,7 @@
|
||||
OCF_RESKEY_cat_default="socat"
|
||||
OCF_RESKEY_port_default="60000"
|
||||
OCF_RESKEY_log_enable_default="false"
|
||||
-OCF_RESKEY_log_cmd_default="gcloud"
|
||||
+OCF_RESKEY_log_cmd_default="gcloud-ra"
|
||||
OCF_RESKEY_log_params_default="logging write GCPILB"
|
||||
OCF_RESKEY_log_end_params_default=""
|
||||
|
@ -1,22 +0,0 @@
|
||||
From 1c037b3ac0288509fb2b74fb4a661a504155da15 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 26 Aug 2021 12:27:50 +0200
|
||||
Subject: [PATCH] nfsnotify: fix default value for "notify_args"
|
||||
|
||||
---
|
||||
heartbeat/nfsnotify.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/nfsnotify.in b/heartbeat/nfsnotify.in
|
||||
index 851f6ad6b4..fe6d2793ba 100644
|
||||
--- a/heartbeat/nfsnotify.in
|
||||
+++ b/heartbeat/nfsnotify.in
|
||||
@@ -33,7 +33,7 @@
|
||||
# Parameter defaults
|
||||
|
||||
OCF_RESKEY_source_host_default=""
|
||||
-OCF_RESKEY_notify_args_default="false"
|
||||
+OCF_RESKEY_notify_args_default=""
|
||||
|
||||
: ${OCF_RESKEY_source_host=${OCF_RESKEY_source_host_default}}
|
||||
: ${OCF_RESKEY_notify_args=${OCF_RESKEY_notify_args_default}}
|
@ -1,32 +0,0 @@
|
||||
From 925180da2f41feddc5aac3c249563eb179b34029 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 22 Nov 2021 16:44:48 +0100
|
||||
Subject: [PATCH] db2: use -l forever instead of -t nodes -l reboot, as they
|
||||
conflict with eachother
|
||||
|
||||
---
|
||||
heartbeat/db2 | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/db2 b/heartbeat/db2
|
||||
index 03146a957..fa2a45a5d 100755
|
||||
--- a/heartbeat/db2
|
||||
+++ b/heartbeat/db2
|
||||
@@ -274,7 +274,7 @@ db2_fal_attrib() {
|
||||
while read id node member
|
||||
do
|
||||
[ "$member" = member -a "$node" != "$me" ] || continue
|
||||
- crm_attribute -t nodes -l reboot --node=$node -n $attr -v "$3"
|
||||
+ crm_attribute -l forever --node=$node -n $attr -v "$3"
|
||||
rc=$?
|
||||
ocf_log info "DB2 instance $instance($db2node/$db: setting attrib for FAL to $FIRST_ACTIVE_LOG @ $node"
|
||||
[ $rc != 0 ] && break
|
||||
@@ -282,7 +282,7 @@ db2_fal_attrib() {
|
||||
;;
|
||||
|
||||
get)
|
||||
- crm_attribute -t nodes -l reboot -n $attr -G --quiet 2>&1
|
||||
+ crm_attribute -l forever -n $attr -G --quiet 2>&1
|
||||
rc=$?
|
||||
if [ $rc != 0 ]
|
||||
then
|
@ -1,32 +0,0 @@
|
||||
From 75eaf06eea8957aa3941823955d1c8fa7933ab1d Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Wed, 23 Feb 2022 16:32:21 +0100
|
||||
Subject: [PATCH] db2: only warn when notify isnt set, and use
|
||||
ocf_local_nodename() to get node name
|
||||
|
||||
---
|
||||
heartbeat/db2 | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/db2 b/heartbeat/db2
|
||||
index fa2a45a5d..ea24d33fc 100755
|
||||
--- a/heartbeat/db2
|
||||
+++ b/heartbeat/db2
|
||||
@@ -267,7 +267,7 @@ db2_fal_attrib() {
|
||||
|
||||
case "$2" in
|
||||
set)
|
||||
- me=$(uname -n)
|
||||
+ me=$(ocf_local_nodename)
|
||||
|
||||
# loop over all member nodes and set attribute
|
||||
crm_node -l |
|
||||
@@ -284,7 +284,7 @@ db2_fal_attrib() {
|
||||
get)
|
||||
crm_attribute -l forever -n $attr -G --quiet 2>&1
|
||||
rc=$?
|
||||
- if [ $rc != 0 ]
|
||||
+ if ! ocf_is_true "$OCF_RESKEY_CRM_meta_notify" && [ $rc != 0 ]
|
||||
then
|
||||
ocf_log warn "DB2 instance $instance($db2node/$db: can't retrieve attribute $attr, are you sure notifications are enabled ?"
|
||||
fi
|
@ -1,70 +0,0 @@
|
||||
From 706b48fd93a75a582c538013aea1418b6ed69dd0 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Thu, 9 Mar 2023 15:57:59 +0100
|
||||
Subject: [PATCH] mysql: promotable fixes to avoid nodes getting bounced around
|
||||
by setting -v 1/-v 2, and added OCF_CHECK_LEVEL=10 for promotable resources
|
||||
to be able to distinguish between promoted and not
|
||||
|
||||
---
|
||||
heartbeat/mysql | 19 +++++++++++++------
|
||||
1 file changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/mysql b/heartbeat/mysql
|
||||
index 9ab49ab20e..29ed427319 100755
|
||||
--- a/heartbeat/mysql
|
||||
+++ b/heartbeat/mysql
|
||||
@@ -757,6 +757,10 @@ mysql_monitor() {
|
||||
status_loglevel="info"
|
||||
fi
|
||||
|
||||
+ if ocf_is_ms; then
|
||||
+ OCF_CHECK_LEVEL=10
|
||||
+ fi
|
||||
+
|
||||
mysql_common_status $status_loglevel
|
||||
rc=$?
|
||||
|
||||
@@ -777,7 +781,13 @@ mysql_monitor() {
|
||||
return $rc
|
||||
fi
|
||||
|
||||
- if [ $OCF_CHECK_LEVEL -gt 0 -a -n "$OCF_RESKEY_test_table" ]; then
|
||||
+ if [ $OCF_CHECK_LEVEL -eq 10 ]; then
|
||||
+ if [ -z "$OCF_RESKEY_test_table" ]; then
|
||||
+ ocf_exit_reason "test_table not set"
|
||||
+ return $OCF_ERR_CONFIGURED
|
||||
+
|
||||
+ fi
|
||||
+
|
||||
# Check if this instance is configured as a slave, and if so
|
||||
# check slave status
|
||||
if is_slave; then
|
||||
@@ -795,18 +805,16 @@ mysql_monitor() {
|
||||
ocf_exit_reason "Failed to select from $test_table";
|
||||
return $OCF_ERR_GENERIC;
|
||||
fi
|
||||
- else
|
||||
- # In case no exnteded tests are enabled and we are in master/slave mode _always_ set the master score to 1 if we reached this point
|
||||
- ocf_is_ms && $CRM_MASTER -v 1
|
||||
fi
|
||||
|
||||
if ocf_is_ms && ! get_read_only; then
|
||||
ocf_log debug "MySQL monitor succeeded (master)";
|
||||
# Always set master score for the master
|
||||
- $CRM_MASTER -v 2
|
||||
+ $CRM_MASTER -v $((${OCF_RESKEY_max_slave_lag}+1))
|
||||
return $OCF_RUNNING_MASTER
|
||||
else
|
||||
ocf_log debug "MySQL monitor succeeded";
|
||||
+ ocf_is_ms && $CRM_MASTER -v 1
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
}
|
||||
@@ -873,7 +881,6 @@ mysql_start() {
|
||||
# preference set by the administrator. We choose a low
|
||||
# greater-than-zero preference.
|
||||
$CRM_MASTER -v 1
|
||||
-
|
||||
fi
|
||||
|
||||
# Initial monitor action
|
@ -1,32 +0,0 @@
|
||||
From 34483f8029ea9ab25220cfee71d53adaf5aacaa0 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Wed, 14 Jun 2023 14:37:01 +0200
|
||||
Subject: [PATCH] mysql: fix promotion_score bouncing between ~3600 and 1 on
|
||||
demoted nodes
|
||||
|
||||
---
|
||||
heartbeat/mysql | 11 -----------
|
||||
1 file changed, 11 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/mysql b/heartbeat/mysql
|
||||
index 29ed42731..1df2fc0f2 100755
|
||||
--- a/heartbeat/mysql
|
||||
+++ b/heartbeat/mysql
|
||||
@@ -517,17 +517,6 @@ check_slave() {
|
||||
|
||||
exit $OCF_ERR_INSTALLED
|
||||
fi
|
||||
- elif ocf_is_ms; then
|
||||
- # Even if we're not set to evict lagging slaves, we can
|
||||
- # still use the seconds behind master value to set our
|
||||
- # master preference.
|
||||
- local master_pref
|
||||
- master_pref=$((${OCF_RESKEY_max_slave_lag}-${secs_behind}))
|
||||
- if [ $master_pref -lt 0 ]; then
|
||||
- # Sanitize a below-zero preference to just zero
|
||||
- master_pref=0
|
||||
- fi
|
||||
- $CRM_MASTER -v $master_pref
|
||||
fi
|
||||
|
||||
# is the slave ok to have a VIP on it
|
@ -1,84 +0,0 @@
|
||||
From 4d87bcfe5df8a1e40ee945e095ac9e7cca147ec4 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Wed, 29 Jun 2022 10:26:25 +0200
|
||||
Subject: [PATCH] IPaddr2/IPsrcaddr: add/modify table parameter to be able to
|
||||
find interface while using policy based routing
|
||||
|
||||
---
|
||||
heartbeat/IPaddr2 | 12 ++++++++++++
|
||||
heartbeat/IPsrcaddr | 5 ++++-
|
||||
heartbeat/findif.sh | 2 +-
|
||||
3 files changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
|
||||
index 97a7431a2..e8384c586 100755
|
||||
--- a/heartbeat/IPaddr2
|
||||
+++ b/heartbeat/IPaddr2
|
||||
@@ -73,6 +73,7 @@ OCF_RESKEY_ip_default=""
|
||||
OCF_RESKEY_cidr_netmask_default=""
|
||||
OCF_RESKEY_broadcast_default=""
|
||||
OCF_RESKEY_iflabel_default=""
|
||||
+OCF_RESKEY_table_default=""
|
||||
OCF_RESKEY_cidr_netmask_default=""
|
||||
OCF_RESKEY_lvs_support_default=false
|
||||
OCF_RESKEY_lvs_ipv6_addrlabel_default=false
|
||||
@@ -97,6 +98,7 @@ OCF_RESKEY_network_namespace_default=""
|
||||
: ${OCF_RESKEY_cidr_netmask=${OCF_RESKEY_cidr_netmask_default}}
|
||||
: ${OCF_RESKEY_broadcast=${OCF_RESKEY_broadcast_default}}
|
||||
: ${OCF_RESKEY_iflabel=${OCF_RESKEY_iflabel_default}}
|
||||
+: ${OCF_RESKEY_table=${OCF_RESKEY_table_default}}
|
||||
: ${OCF_RESKEY_lvs_support=${OCF_RESKEY_lvs_support_default}}
|
||||
: ${OCF_RESKEY_lvs_ipv6_addrlabel=${OCF_RESKEY_lvs_ipv6_addrlabel_default}}
|
||||
: ${OCF_RESKEY_lvs_ipv6_addrlabel_value=${OCF_RESKEY_lvs_ipv6_addrlabel_value_default}}
|
||||
@@ -239,6 +241,16 @@ If a label is specified in nic name, this parameter has no effect.
|
||||
<content type="string" default="${OCF_RESKEY_iflabel_default}"/>
|
||||
</parameter>
|
||||
|
||||
+<parameter name="table">
|
||||
+<longdesc lang="en">
|
||||
+Table to use to lookup which interface to use for the IP.
|
||||
+
|
||||
+This can be used for policy based routing. See man ip-rule(8).
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Table</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_table_default}" />
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="lvs_support">
|
||||
<longdesc lang="en">
|
||||
Enable support for LVS Direct Routing configurations. In case a IP
|
||||
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
|
||||
index 1bd41a930..cf106cc34 100755
|
||||
--- a/heartbeat/IPsrcaddr
|
||||
+++ b/heartbeat/IPsrcaddr
|
||||
@@ -155,13 +155,16 @@ Metric. Only needed if incorrect metric value is used.
|
||||
|
||||
<parameter name="table">
|
||||
<longdesc lang="en">
|
||||
-Table to modify. E.g. "local".
|
||||
+Table to modify and use for interface lookup. E.g. "local".
|
||||
|
||||
The table has to have a route matching the "destination" parameter.
|
||||
+
|
||||
+This can be used for policy based routing. See man ip-rule(8).
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Table</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_table_default}" />
|
||||
</parameter>
|
||||
+
|
||||
</parameters>
|
||||
|
||||
<actions>
|
||||
diff --git a/heartbeat/findif.sh b/heartbeat/findif.sh
|
||||
index 66bc6d56a..1a40cc9a4 100644
|
||||
--- a/heartbeat/findif.sh
|
||||
+++ b/heartbeat/findif.sh
|
||||
@@ -32,7 +32,7 @@ prefixcheck() {
|
||||
getnetworkinfo()
|
||||
{
|
||||
local line netinfo
|
||||
- ip -o -f inet route list match $OCF_RESKEY_ip table local scope host | (while read line;
|
||||
+ ip -o -f inet route list match $OCF_RESKEY_ip table "${OCF_RESKEY_table=local}" scope host | (while read line;
|
||||
do
|
||||
netinfo=`echo $line | awk '{print $2}'`
|
||||
case $netinfo in
|
@ -1,35 +0,0 @@
|
||||
From da9e8e691f39494e14f8f11173b6ab6433384396 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 20 Jun 2023 14:19:23 +0200
|
||||
Subject: [PATCH] findif.sh: fix table parameter so it uses main table by
|
||||
default
|
||||
|
||||
---
|
||||
heartbeat/findif.sh | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/findif.sh b/heartbeat/findif.sh
|
||||
index 1a40cc9a4b..6c04c98c19 100644
|
||||
--- a/heartbeat/findif.sh
|
||||
+++ b/heartbeat/findif.sh
|
||||
@@ -32,7 +32,7 @@ prefixcheck() {
|
||||
getnetworkinfo()
|
||||
{
|
||||
local line netinfo
|
||||
- ip -o -f inet route list match $OCF_RESKEY_ip table "${OCF_RESKEY_table=local}" scope host | (while read line;
|
||||
+ ip -o -f inet route list match $OCF_RESKEY_ip table "${OCF_RESKEY_table:=main}" scope host | (while read line;
|
||||
do
|
||||
netinfo=`echo $line | awk '{print $2}'`
|
||||
case $netinfo in
|
||||
@@ -215,9 +215,9 @@ findif()
|
||||
fi
|
||||
if [ -n "$nic" ] ; then
|
||||
# NIC supports more than two.
|
||||
- set -- $(ip -o -f $family route list match $match $scope | grep "dev $nic " | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
+ set -- $(ip -o -f $family route list match $match $scope table "${OCF_RESKEY_table:=main}" | grep "dev $nic " | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
else
|
||||
- set -- $(ip -o -f $family route list match $match $scope | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
+ set -- $(ip -o -f $family route list match $match $scope table "${OCF_RESKEY_table:=main}" | awk 'BEGIN{best=0} /\// { mask=$1; sub(".*/", "", mask); if( int(mask)>=best ) { best=int(mask); best_ln=$0; } } END{print best_ln}')
|
||||
fi
|
||||
if [ $# = 0 ] ; then
|
||||
case $OCF_RESKEY_ip in
|
@ -1,175 +0,0 @@
|
||||
From cab190c737fdf58268aa5c009f6089b754862b22 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Tue, 1 Feb 2022 16:32:50 -0800
|
||||
Subject: [PATCH 1/3] Filesystem: Fix OpenBSD check in fstype_supported()
|
||||
|
||||
fstype_supported() is supposed to skip the /proc/filesystems check if
|
||||
the OS is OpenBSD. Instead, it skips the check if the OS is **not**
|
||||
OpenBSD. That means the function has been a no-op for all other distros.
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
heartbeat/Filesystem | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 010c1dcfc..8b4792152 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -440,7 +440,7 @@ fstype_supported()
|
||||
local support="$FSTYPE"
|
||||
local rc
|
||||
|
||||
- if [ "X${HOSTOS}" != "XOpenBSD" ];then
|
||||
+ if [ "X${HOSTOS}" = "XOpenBSD" ];then
|
||||
# skip checking /proc/filesystems for obsd
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
From 5d38b87daa9cfffa89a193df131d6ebd87cd05aa Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Tue, 1 Feb 2022 18:26:32 -0800
|
||||
Subject: [PATCH 2/3] Filesystem: Improve fstype_supported logs for fuse
|
||||
|
||||
Make it more clear when we have to use a different name to check for
|
||||
support of a particular filesystem. Currently only used for fuse-type
|
||||
filesystems.
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
heartbeat/Filesystem | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 8b4792152..4d84846c1 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -455,6 +455,10 @@ fstype_supported()
|
||||
fuse.*|glusterfs|rozofs) support="fuse";;
|
||||
esac
|
||||
|
||||
+ if [ "$support" != "$FSTYPE" ]; then
|
||||
+ ocf_log info "Checking support for $FSTYPE as \"$support\""
|
||||
+ fi
|
||||
+
|
||||
grep -w "$support"'$' /proc/filesystems >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# found the fs type
|
||||
@@ -465,7 +469,7 @@ fstype_supported()
|
||||
# check the if the filesystem support exists again.
|
||||
$MODPROBE $support >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
- ocf_exit_reason "Couldn't find filesystem $FSTYPE in /proc/filesystems and failed to load kernel module"
|
||||
+ ocf_exit_reason "Couldn't find filesystem $support in /proc/filesystems and failed to load kernel module"
|
||||
return $OCF_ERR_INSTALLED
|
||||
fi
|
||||
|
||||
@@ -478,11 +482,11 @@ fstype_supported()
|
||||
# yes. found the filesystem after doing the modprobe
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
- ocf_log debug "Unable to find support for $FSTYPE in /proc/filesystems after modprobe, trying again"
|
||||
+ ocf_log debug "Unable to find support for $support in /proc/filesystems after modprobe, trying again"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- ocf_exit_reason "Couldn't find filesystem $FSTYPE in /proc/filesystems"
|
||||
+ ocf_exit_reason "Couldn't find filesystem $support in /proc/filesystems"
|
||||
return $OCF_ERR_INSTALLED
|
||||
}
|
||||
|
||||
@@ -837,6 +841,9 @@ Filesystem_monitor()
|
||||
# VALIDATE_ALL: Are the instance parameters valid?
|
||||
# FIXME!! The only part that's useful is the return code.
|
||||
# This code always returns $OCF_SUCCESS (!)
|
||||
+# FIXME!! Needs some tuning to match fstype_supported() (e.g., for
|
||||
+# fuse). Can we just call fstype_supported() with a flag like
|
||||
+# "no_modprobe" instead?
|
||||
#
|
||||
Filesystem_validate_all()
|
||||
{
|
||||
|
||||
From e2174244067b02d798e0f12437f0f499c80f91fe Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Tue, 1 Feb 2022 18:55:47 -0800
|
||||
Subject: [PATCH 3/3] Filesystem: Add support for Amazon EFS mount helper
|
||||
|
||||
mount.efs, the mount helper for Amazon Elastic File System (EFS)
|
||||
provided by amazon-efs-utils [1], is a wrapper for mount.nfs4. It offers
|
||||
a number of AWS-specific mount options and some security improvements
|
||||
like encryption of data in transit.
|
||||
|
||||
This commit adds support by treating an fstype=efs like fstype=nfs4 for
|
||||
the most part.
|
||||
|
||||
Resolves: RHBZ#2049319
|
||||
|
||||
[1] https://docs.aws.amazon.com/efs/latest/ug/efs-mount-helper.html
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
heartbeat/Filesystem | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 4d84846c1..1a90d6a42 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -341,7 +341,7 @@ determine_blockdevice() {
|
||||
# Get the current real device name, if possible.
|
||||
# (specified devname could be -L or -U...)
|
||||
case "$FSTYPE" in
|
||||
- nfs4|nfs|smbfs|cifs|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|none|lustre)
|
||||
+ nfs4|nfs|efs|smbfs|cifs|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|none|lustre)
|
||||
: ;;
|
||||
*)
|
||||
match_string="${TAB}${CANONICALIZED_MOUNTPOINT}${TAB}"
|
||||
@@ -423,7 +423,7 @@ is_fsck_needed() {
|
||||
no) false;;
|
||||
""|auto)
|
||||
case "$FSTYPE" in
|
||||
- ext4|ext4dev|ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs4|nfs|cifs|smbfs|ocfs2|gfs2|none|lustre|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs)
|
||||
+ ext4|ext4dev|ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs4|nfs|efs|cifs|smbfs|ocfs2|gfs2|none|lustre|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs)
|
||||
false;;
|
||||
*)
|
||||
true;;
|
||||
@@ -450,9 +450,11 @@ fstype_supported()
|
||||
return $OCF_SUCCESS
|
||||
fi
|
||||
|
||||
- # support fuse-filesystems (e.g. GlusterFS)
|
||||
+ # support fuse-filesystems (e.g. GlusterFS) and Amazon Elastic File
|
||||
+ # System (EFS)
|
||||
case "$FSTYPE" in
|
||||
fuse.*|glusterfs|rozofs) support="fuse";;
|
||||
+ efs) support="nfs4";;
|
||||
esac
|
||||
|
||||
if [ "$support" != "$FSTYPE" ]; then
|
||||
@@ -701,7 +703,7 @@ Filesystem_stop()
|
||||
|
||||
# For networked filesystems, there's merit in trying -f:
|
||||
case "$FSTYPE" in
|
||||
- nfs4|nfs|cifs|smbfs) umount_force="-f" ;;
|
||||
+ nfs4|nfs|efs|cifs|smbfs) umount_force="-f" ;;
|
||||
esac
|
||||
|
||||
# Umount all sub-filesystems mounted under $MOUNTPOINT/ too.
|
||||
@@ -892,7 +894,7 @@ set_blockdevice_var() {
|
||||
|
||||
# these are definitely not block devices
|
||||
case "$FSTYPE" in
|
||||
- nfs4|nfs|smbfs|cifs|none|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|lustre) return;;
|
||||
+ nfs4|nfs|efs|smbfs|cifs|none|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|lustre) return;;
|
||||
esac
|
||||
|
||||
if $(is_option "loop"); then
|
||||
@@ -1013,7 +1015,7 @@ is_option "ro" &&
|
||||
CLUSTERSAFE=2
|
||||
|
||||
case "$FSTYPE" in
|
||||
-nfs4|nfs|smbfs|cifs|none|gfs2|glusterfs|ceph|ocfs2|overlay|overlayfs|tmpfs|cvfs|lustre)
|
||||
+nfs4|nfs|efs|smbfs|cifs|none|gfs2|glusterfs|ceph|ocfs2|overlay|overlayfs|tmpfs|cvfs|lustre)
|
||||
CLUSTERSAFE=1 # this is kind of safe too
|
||||
;;
|
||||
# add here CLUSTERSAFE=0 for all filesystems which are not
|
@ -1,44 +0,0 @@
|
||||
From 26de0ad2f0f975166fe79ef72ab08e2c03519eea Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 28 Mar 2022 13:25:35 +0200
|
||||
Subject: [PATCH] Filesystem: fix logic for UUID/label devices with space
|
||||
between parameter and UUID/label
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 14 ++++++++++----
|
||||
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 1a90d6a42..72a1b8623 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -596,11 +596,11 @@ Filesystem_start()
|
||||
flushbufs "$DEVICE"
|
||||
# Mount the filesystem.
|
||||
case "$FSTYPE" in
|
||||
- none) $MOUNT $options "$DEVICE" "$MOUNTPOINT" &&
|
||||
+ none) $MOUNT $options $device_opt "$DEVICE" "$MOUNTPOINT" &&
|
||||
bind_mount
|
||||
;;
|
||||
- "") $MOUNT $options "$DEVICE" "$MOUNTPOINT" ;;
|
||||
- *) $MOUNT -t "$FSTYPE" $options "$DEVICE" "$MOUNTPOINT" ;;
|
||||
+ "") $MOUNT $options $device_opt "$DEVICE" "$MOUNTPOINT" ;;
|
||||
+ *) $MOUNT -t "$FSTYPE" $options $device_opt "$DEVICE" "$MOUNTPOINT" ;;
|
||||
esac
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
@@ -902,7 +902,13 @@ set_blockdevice_var() {
|
||||
fi
|
||||
|
||||
case "$DEVICE" in
|
||||
- -*) # Oh... An option to mount instead... Typically -U or -L
|
||||
+ --*) # Typically --uuid or --label
|
||||
+ device_opt=$(echo $DEVICE | sed -E "s/([[:blank:]]|=).*//")
|
||||
+ DEVICE=$(echo $DEVICE | sed -E "s/$device_opt([[:blank:]]*|=)//")
|
||||
+ ;;
|
||||
+ -*) # Oh... An option to mount instead... Typically -U or -L
|
||||
+ device_opt=$(echo $DEVICE | cut -c1-2)
|
||||
+ DEVICE=$(echo $DEVICE | sed "s/$device_opt[[:blank:]]*//")
|
||||
;;
|
||||
/dev/null) # Special case for BSC
|
||||
blockdevice=yes
|
@ -1,38 +0,0 @@
|
||||
From d9b46474fc19d9c57e2cfb752d60319017da8410 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Wed, 6 Apr 2022 14:14:19 +0200
|
||||
Subject: [PATCH] Filesystem: improve logic for UUID/label and add note that
|
||||
/dev/disk/by-{uuid,label}/ are preferred on Linux
|
||||
|
||||
---
|
||||
heartbeat/Filesystem | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
|
||||
index 72a1b8623..44270ad98 100755
|
||||
--- a/heartbeat/Filesystem
|
||||
+++ b/heartbeat/Filesystem
|
||||
@@ -163,6 +163,8 @@ directory where the status file is to be placed.
|
||||
<parameter name="device" required="1">
|
||||
<longdesc lang="en">
|
||||
The name of block device for the filesystem, or -U, -L options for mount, or NFS mount specification.
|
||||
+
|
||||
+NOTE: On Linux /dev/disk/by-{uuid,label}/ are preferred to -U/-L.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">block device</shortdesc>
|
||||
<content type="string" default="${OCF_RESKEY_device_default}" />
|
||||
@@ -902,11 +904,11 @@ set_blockdevice_var() {
|
||||
fi
|
||||
|
||||
case "$DEVICE" in
|
||||
- --*) # Typically --uuid or --label
|
||||
- device_opt=$(echo $DEVICE | sed -E "s/([[:blank:]]|=).*//")
|
||||
+ --uuid=*|--uuid\ *|--label=*|--label\ *)
|
||||
+ device_opt=$(echo $DEVICE | sed "s/\([[:blank:]]\|=\).*//")
|
||||
DEVICE=$(echo $DEVICE | sed -E "s/$device_opt([[:blank:]]*|=)//")
|
||||
;;
|
||||
- -*) # Oh... An option to mount instead... Typically -U or -L
|
||||
+ -U*|-L*) # short versions of --uuid/--label
|
||||
device_opt=$(echo $DEVICE | cut -c1-2)
|
||||
DEVICE=$(echo $DEVICE | sed "s/$device_opt[[:blank:]]*//")
|
||||
;;
|
@ -1,41 +0,0 @@
|
||||
From 6d2ed7615614ede093f097189876d0f08553a43e Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Mon, 14 Feb 2022 22:23:39 -0800
|
||||
Subject: [PATCH] IPsrcaddr: Add warning about DHCP
|
||||
|
||||
If DHCP is enabled for the interface that serves OCF_RESKEY_ipaddress,
|
||||
then NetworkManager (and possibly dhclient in systems without NM;
|
||||
unsure) may later re-add a route that the IPsrcaddr resource replaced.
|
||||
This may cause the resource to fail or cause other unexpected behavior.
|
||||
|
||||
So far this has been observed with a default route, albeit with an edge
|
||||
case of a configuration (OCF_RESKEY_ipaddress on a different subnet)
|
||||
that may not be totally valid. There are likely to be other situations
|
||||
as well where DHCP can cause conflicts with IPsrcaddr's manual updates
|
||||
via iproute. The safest option is to use only static configuration for
|
||||
the involved interface.
|
||||
|
||||
Resolves: RHBZ#1654862
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
heartbeat/IPsrcaddr | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
|
||||
index ec868409f..fd7b6f68d 100755
|
||||
--- a/heartbeat/IPsrcaddr
|
||||
+++ b/heartbeat/IPsrcaddr
|
||||
@@ -99,6 +99,12 @@ meta_data() {
|
||||
<longdesc lang="en">
|
||||
Resource script for IPsrcaddr. It manages the preferred source address
|
||||
modification.
|
||||
+
|
||||
+Note: DHCP should not be enabled for the interface serving the preferred
|
||||
+source address. Enabling DHCP may result in unexpected behavior, such as
|
||||
+the automatic addition of duplicate or conflicting routes. This may
|
||||
+cause the IPsrcaddr resource to fail, or it may produce undesired
|
||||
+behavior while the resource continues to run.
|
||||
</longdesc>
|
||||
<shortdesc lang="en">Manages the preferred source address for outgoing IP packets</shortdesc>
|
||||
|
@ -1,49 +0,0 @@
|
||||
From 5a65f66ff803ad7ed15af958cc1efdde4d53dcb7 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Thu, 17 Feb 2022 03:53:21 -0800
|
||||
Subject: [PATCH] IPsrcaddr: Better error message when no matching route found
|
||||
|
||||
If OCF_RESKEY_destination is not explicitly set and `ip route list`
|
||||
can't find a route matching the specifications, the NETWORK variable
|
||||
doesn't get set. This causes a certain failure of the start operation,
|
||||
because there is no PREFIX argument to `ip route replace` (syntax
|
||||
error). It may also cause unexpected behavior for stop operations (but
|
||||
not in all cases). During a monitor, this event can only happen if
|
||||
something has changed outside the cluster's control, and so is cause
|
||||
for warning there.
|
||||
|
||||
Exit OCF_ERR_ARGS for start, log debug for probe, log warning for all
|
||||
other ops.
|
||||
|
||||
Resolves: RHBZ#1654862
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
heartbeat/IPsrcaddr | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
|
||||
index fd7b6f68d..f0216722d 100755
|
||||
--- a/heartbeat/IPsrcaddr
|
||||
+++ b/heartbeat/IPsrcaddr
|
||||
@@ -549,6 +549,20 @@ rc=$?
|
||||
INTERFACE=`echo $findif_out | awk '{print $1}'`
|
||||
if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
|
||||
NETWORK=`$IP2UTIL route list dev $INTERFACE scope link $PROTO match $ipaddress|grep -m 1 -o '^[^ ]*'`
|
||||
+
|
||||
+ if [ -z "$NETWORK" ]; then
|
||||
+ err_str="command '$IP2UTIL route list dev $INTERFACE scope link $PROTO"
|
||||
+ err_str="$err_str match $ipaddress' failed to find a matching route"
|
||||
+
|
||||
+ if [ "$__OCF_ACTION" = "start" ]; then
|
||||
+ ocf_exit_reason "$err_str"
|
||||
+ exit $OCF_ERR_ARGS
|
||||
+ elif ! ocf_is_probe; then
|
||||
+ ocf_log warn "$err_str"
|
||||
+ else
|
||||
+ ocf_log debug "$err_str"
|
||||
+ fi
|
||||
+ fi
|
||||
else
|
||||
NETWORK="$OCF_RESKEY_destination"
|
||||
fi
|
@ -1,56 +0,0 @@
|
||||
From 0a197f1cd227e768837dff778a0c56fc1085d434 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Mon, 21 Feb 2022 13:54:04 +0100
|
||||
Subject: [PATCH] IPsrcaddr: fix indentation in better error message code
|
||||
|
||||
---
|
||||
heartbeat/IPsrcaddr | 30 +++++++++++++++---------------
|
||||
1 file changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
|
||||
index f0216722d..c82adc0e9 100755
|
||||
--- a/heartbeat/IPsrcaddr
|
||||
+++ b/heartbeat/IPsrcaddr
|
||||
@@ -542,27 +542,27 @@ fi
|
||||
findif_out=`$FINDIF -C`
|
||||
rc=$?
|
||||
[ $rc -ne 0 ] && {
|
||||
- ocf_exit_reason "[$FINDIF -C] failed"
|
||||
- exit $rc
|
||||
+ ocf_exit_reason "[$FINDIF -C] failed"
|
||||
+ exit $rc
|
||||
}
|
||||
|
||||
INTERFACE=`echo $findif_out | awk '{print $1}'`
|
||||
if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
|
||||
NETWORK=`$IP2UTIL route list dev $INTERFACE scope link $PROTO match $ipaddress|grep -m 1 -o '^[^ ]*'`
|
||||
|
||||
- if [ -z "$NETWORK" ]; then
|
||||
- err_str="command '$IP2UTIL route list dev $INTERFACE scope link $PROTO"
|
||||
- err_str="$err_str match $ipaddress' failed to find a matching route"
|
||||
-
|
||||
- if [ "$__OCF_ACTION" = "start" ]; then
|
||||
- ocf_exit_reason "$err_str"
|
||||
- exit $OCF_ERR_ARGS
|
||||
- elif ! ocf_is_probe; then
|
||||
- ocf_log warn "$err_str"
|
||||
- else
|
||||
- ocf_log debug "$err_str"
|
||||
- fi
|
||||
- fi
|
||||
+ if [ -z "$NETWORK" ]; then
|
||||
+ err_str="command '$IP2UTIL route list dev $INTERFACE scope link $PROTO"
|
||||
+ err_str="$err_str match $ipaddress' failed to find a matching route"
|
||||
+
|
||||
+ if [ "$__OCF_ACTION" = "start" ]; then
|
||||
+ ocf_exit_reason "$err_str"
|
||||
+ exit $OCF_ERR_ARGS
|
||||
+ elif ! ocf_is_probe; then
|
||||
+ ocf_log warn "$err_str"
|
||||
+ else
|
||||
+ ocf_log debug "$err_str"
|
||||
+ fi
|
||||
+ fi
|
||||
else
|
||||
NETWORK="$OCF_RESKEY_destination"
|
||||
fi
|
@ -1,117 +0,0 @@
|
||||
From 50a596bfb977b18902dc62b99145bbd1a087690a Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 1 Mar 2022 11:06:07 +0100
|
||||
Subject: [PATCH] IPsrcaddr: fixes
|
||||
|
||||
- use findif.sh to detect secondary interfaces
|
||||
- get metric and proto to update the correct route/update it correctly
|
||||
- match route using interface to fail when trying to update secondary
|
||||
interfaces without specifying destination (would update default route
|
||||
before)
|
||||
- also use PRIMARY_IP/OPTS during stop-action for default routes (to get
|
||||
back to the exact routes we started with)
|
||||
- dont fail during stop-action if route doesnt exist
|
||||
- use [[:blank:]] for WS to follow POSIX standard (suggested by nrwahl)
|
||||
---
|
||||
heartbeat/IPsrcaddr | 35 +++++++++++++++++++----------------
|
||||
1 file changed, 19 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
|
||||
index c82adc0e9..7dbf65ff5 100755
|
||||
--- a/heartbeat/IPsrcaddr
|
||||
+++ b/heartbeat/IPsrcaddr
|
||||
@@ -52,6 +52,7 @@
|
||||
# Initialization:
|
||||
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
||||
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
||||
+. ${OCF_FUNCTIONS_DIR}/findif.sh
|
||||
|
||||
# Defaults
|
||||
OCF_RESKEY_ipaddress_default=""
|
||||
@@ -181,19 +182,21 @@ errorexit() {
|
||||
#
|
||||
# where the src clause "src Y.Y.Y.Y" may or may not be present
|
||||
|
||||
-WS="[`echo -en ' \t'`]"
|
||||
+WS="[[:blank:]]"
|
||||
OCTET="[0-9]\{1,3\}"
|
||||
IPADDR="\($OCTET\.\)\{3\}$OCTET"
|
||||
SRCCLAUSE="src$WS$WS*\($IPADDR\)"
|
||||
MATCHROUTE="\(.*${WS}\)\($SRCCLAUSE\)\($WS.*\|$\)"
|
||||
-FINDIF=$HA_BIN/findif
|
||||
+METRICCLAUSE=".*\(metric$WS[^ ]\+\)"
|
||||
+PROTOCLAUSE=".*\(proto$WS[^ ]\+\)"
|
||||
+FINDIF=findif
|
||||
|
||||
# findif needs that to be set
|
||||
export OCF_RESKEY_ip=$OCF_RESKEY_ipaddress
|
||||
|
||||
srca_read() {
|
||||
# Capture matching route - doublequotes prevent word splitting...
|
||||
- ROUTE="`$CMDSHOW 2> /dev/null`" || errorexit "command '$CMDSHOW' failed"
|
||||
+ ROUTE="`$CMDSHOW dev $INTERFACE 2> /dev/null`" || errorexit "command '$CMDSHOW' failed"
|
||||
|
||||
# ... so we can make sure there is only 1 matching route
|
||||
[ 1 -eq `echo "$ROUTE" | wc -l` ] || \
|
||||
@@ -201,7 +204,7 @@ srca_read() {
|
||||
|
||||
# But there might still be no matching route
|
||||
[ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] && [ -z "$ROUTE" ] && \
|
||||
- ! ocf_is_probe && errorexit "no matching route exists"
|
||||
+ ! ocf_is_probe && [ "$__OCF_ACTION" != stop ] && errorexit "no matching route exists"
|
||||
|
||||
# Sed out the source ip address if it exists
|
||||
SRCIP=`echo $ROUTE | sed -n "s/$MATCHROUTE/\3/p"`
|
||||
@@ -232,8 +235,8 @@ srca_start() {
|
||||
rc=$OCF_SUCCESS
|
||||
ocf_log info "The ip route has been already set.($NETWORK, $INTERFACE, $ROUTE_WO_SRC)"
|
||||
else
|
||||
- $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE src $1 || \
|
||||
- errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE src $1' failed"
|
||||
+ $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $PROTO src $1 $METRIC || \
|
||||
+ errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $PROTO src $1 $METRIC' failed"
|
||||
|
||||
if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
|
||||
$CMDCHANGE $ROUTE_WO_SRC src $1 || \
|
||||
@@ -266,14 +269,11 @@ srca_stop() {
|
||||
|
||||
[ $rc = 2 ] && errorexit "The address you specified to stop does not match the preferred source address"
|
||||
|
||||
- OPTS=""
|
||||
- if [ "$OCF_RESKEY_destination" != "0.0.0.0/0" ] ;then
|
||||
- PRIMARY_IP="$($IP2UTIL -4 -o addr show dev $INTERFACE primary | awk '{split($4,a,"/");print a[1]}')"
|
||||
- OPTS="proto kernel scope host src $PRIMARY_IP"
|
||||
- fi
|
||||
+ PRIMARY_IP="$($IP2UTIL -4 -o addr show dev $INTERFACE primary | awk '{split($4,a,"/");print a[1]}')"
|
||||
+ OPTS="proto kernel scope link src $PRIMARY_IP"
|
||||
|
||||
- $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $OPTS || \
|
||||
- errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $OPTS' failed"
|
||||
+ $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $OPTS $METRIC || \
|
||||
+ errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $OPTS $METRIC' failed"
|
||||
|
||||
if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
|
||||
$CMDCHANGE $ROUTE_WO_SRC || \
|
||||
@@ -539,16 +539,19 @@ if [ $rc -ne $OCF_SUCCESS ]; then
|
||||
esac
|
||||
fi
|
||||
|
||||
-findif_out=`$FINDIF -C`
|
||||
+findif_out=`$FINDIF`
|
||||
rc=$?
|
||||
[ $rc -ne 0 ] && {
|
||||
- ocf_exit_reason "[$FINDIF -C] failed"
|
||||
+ ocf_exit_reason "[$FINDIF] failed"
|
||||
exit $rc
|
||||
}
|
||||
|
||||
INTERFACE=`echo $findif_out | awk '{print $1}'`
|
||||
+LISTROUTE=`$IP2UTIL route list dev $INTERFACE scope link $PROTO match $ipaddress`
|
||||
+METRIC=`echo $LISTROUTE | sed -n "s/$METRICCLAUSE/\1/p"`
|
||||
+[ -z "$PROTO" ] && PROTO=`echo $LISTROUTE | sed -n "s/$PROTOCLAUSE/\1/p"`
|
||||
if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
|
||||
- NETWORK=`$IP2UTIL route list dev $INTERFACE scope link $PROTO match $ipaddress|grep -m 1 -o '^[^ ]*'`
|
||||
+ NETWORK=`echo $LISTROUTE | grep -m 1 -o '^[^ ]*'`
|
||||
|
||||
if [ -z "$NETWORK" ]; then
|
||||
err_str="command '$IP2UTIL route list dev $INTERFACE scope link $PROTO"
|
@ -1,102 +0,0 @@
|
||||
From e651576c1b5c1ffbe0fd1b78f209be9a3f9764e7 Mon Sep 17 00:00:00 2001
|
||||
From: XingWei-Liu <liuxingwei@uniontech.com>
|
||||
Date: Thu, 10 Mar 2022 10:38:11 +0800
|
||||
Subject: [PATCH 1/4] change lvm_status return value from ocf_not_running to
|
||||
ocf_err_generic
|
||||
|
||||
---
|
||||
heartbeat/LVM-activate | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/LVM-activate b/heartbeat/LVM-activate
|
||||
index aed672ea3..0aef76706 100755
|
||||
--- a/heartbeat/LVM-activate
|
||||
+++ b/heartbeat/LVM-activate
|
||||
@@ -790,7 +790,7 @@ lvm_status() {
|
||||
fi
|
||||
|
||||
if [ $dm_count -eq 0 ]; then
|
||||
- return $OCF_NOT_RUNNING
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
|
||||
case "$OCF_CHECK_LEVEL" in
|
||||
|
||||
From 540ae56436a4f9547bb17aa206fe0e8c7a7fea87 Mon Sep 17 00:00:00 2001
|
||||
From: XingWei-Liu <liuxingwei@uniontech.com>
|
||||
Date: Thu, 10 Mar 2022 16:44:25 +0800
|
||||
Subject: [PATCH 2/4] add if ocf_is_probe in monitor func
|
||||
|
||||
---
|
||||
heartbeat/LVM-activate | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/LVM-activate b/heartbeat/LVM-activate
|
||||
index 0aef76706..c86606637 100755
|
||||
--- a/heartbeat/LVM-activate
|
||||
+++ b/heartbeat/LVM-activate
|
||||
@@ -790,7 +790,11 @@ lvm_status() {
|
||||
fi
|
||||
|
||||
if [ $dm_count -eq 0 ]; then
|
||||
- return $OCF_ERR_GENERIC
|
||||
+ if ocf_is_probe ;then
|
||||
+ return $OCF_NOT_RUNNING
|
||||
+ else
|
||||
+ return $OCF_ERR_GENERIC
|
||||
+ fi
|
||||
fi
|
||||
|
||||
case "$OCF_CHECK_LEVEL" in
|
||||
|
||||
From ae3f35d4f671f3288034a257c6dd8eff9a83447a Mon Sep 17 00:00:00 2001
|
||||
From: XingWei-Liu <liuxingwei@uniontech.com>
|
||||
Date: Thu, 10 Mar 2022 16:50:04 +0800
|
||||
Subject: [PATCH 3/4] add if ocf_is_probe in monitor func
|
||||
|
||||
---
|
||||
heartbeat/LVM-activate | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/LVM-activate b/heartbeat/LVM-activate
|
||||
index c86606637..f345f73a9 100755
|
||||
--- a/heartbeat/LVM-activate
|
||||
+++ b/heartbeat/LVM-activate
|
||||
@@ -791,9 +791,9 @@ lvm_status() {
|
||||
|
||||
if [ $dm_count -eq 0 ]; then
|
||||
if ocf_is_probe ;then
|
||||
- return $OCF_NOT_RUNNING
|
||||
- else
|
||||
return $OCF_ERR_GENERIC
|
||||
+ else
|
||||
+ return $OCF_NOT_RUNNING
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
From 1072c0490ef936a1a7dfd8411da434dce1569457 Mon Sep 17 00:00:00 2001
|
||||
From: XingWei-Liu <liuxingwei@uniontech.com>
|
||||
Date: Thu, 10 Mar 2022 18:10:21 +0800
|
||||
Subject: [PATCH 4/4] reverse return value in monitor func
|
||||
|
||||
---
|
||||
heartbeat/LVM-activate | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/LVM-activate b/heartbeat/LVM-activate
|
||||
index f345f73a9..c86606637 100755
|
||||
--- a/heartbeat/LVM-activate
|
||||
+++ b/heartbeat/LVM-activate
|
||||
@@ -791,9 +791,9 @@ lvm_status() {
|
||||
|
||||
if [ $dm_count -eq 0 ]; then
|
||||
if ocf_is_probe ;then
|
||||
- return $OCF_ERR_GENERIC
|
||||
- else
|
||||
return $OCF_NOT_RUNNING
|
||||
+ else
|
||||
+ return $OCF_ERR_GENERIC
|
||||
fi
|
||||
fi
|
||||
|
@ -1,25 +0,0 @@
|
||||
From b3885f7d95fe390371f806c7f3debb3ec8ad012d Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Tue, 7 Jun 2022 15:20:11 +0200
|
||||
Subject: [PATCH] lvmlockd: fail when use_lvmlockd has not been set
|
||||
|
||||
---
|
||||
heartbeat/lvmlockd | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/lvmlockd b/heartbeat/lvmlockd
|
||||
index 05bb0a2e5..dc7bd2d7e 100755
|
||||
--- a/heartbeat/lvmlockd
|
||||
+++ b/heartbeat/lvmlockd
|
||||
@@ -179,6 +179,11 @@ setup_lvm_config()
|
||||
out=$(lvmconfig 'global/locking_type' 2> /dev/null)
|
||||
lock_type=$(echo "$out" | cut -d'=' -f2)
|
||||
|
||||
+ if [ -z "$use_lvmlockd" ]; then
|
||||
+ ocf_exit_reason "\"use_lvmlockd\" not set in /etc/lvm/lvm.conf ..."
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+
|
||||
if [ -n "$use_lvmlockd" ] && [ "$use_lvmlockd" != 1 ] ; then
|
||||
ocf_log info "setting \"use_lvmlockd=1\" in /etc/lvm/lvm.conf ..."
|
||||
sed -i 's,^[[:blank:]]*use_lvmlockd[[:blank:]]*=.*,\ \ \ \ use_lvmlockd = 1,g' /etc/lvm/lvm.conf
|
@ -1,47 +0,0 @@
|
||||
From 99c4f2af92a10155cf072198c72deffaed3883a5 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
Date: Wed, 3 Aug 2022 17:20:31 +0200
|
||||
Subject: [PATCH] CTDB: move process to root cgroup if realtime scheduling is
|
||||
enabled
|
||||
|
||||
---
|
||||
heartbeat/CTDB.in | 2 ++
|
||||
heartbeat/ocf-shellfuncs.in | 12 ++++++++++++
|
||||
2 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/heartbeat/CTDB.in b/heartbeat/CTDB.in
|
||||
index d25d026ca..46f56cfac 100755
|
||||
--- a/heartbeat/CTDB.in
|
||||
+++ b/heartbeat/CTDB.in
|
||||
@@ -709,6 +709,8 @@ EOF
|
||||
invoke_ctdbd() {
|
||||
local vers="$1"
|
||||
|
||||
+ ocf_move_to_root_cgroup_if_rt_enabled
|
||||
+
|
||||
ocf_version_cmp "$vers" "4.9.0"
|
||||
if [ "$?" -ne "0" ]; then
|
||||
# With 4.9+, all ctdbd binary parameters are provided as
|
||||
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
|
||||
index 6be4e4e30..2c53a967a 100644
|
||||
--- a/heartbeat/ocf-shellfuncs.in
|
||||
+++ b/heartbeat/ocf-shellfuncs.in
|
||||
@@ -672,6 +672,18 @@ EOF
|
||||
systemctl daemon-reload
|
||||
}
|
||||
|
||||
+# move process to root cgroup if realtime scheduling is enabled
|
||||
+ocf_move_to_root_cgroup_if_rt_enabled()
|
||||
+{
|
||||
+ if [ -e "/sys/fs/cgroup/cpu/cpu.rt_runtime_us" ]; then
|
||||
+ echo $$ >> /sys/fs/cgroup/cpu/tasks
|
||||
+
|
||||
+ if [ "$?" -ne "0" ]; then
|
||||
+ ocf_log warn "Unable to move PID $$ to the root cgroup"
|
||||
+ fi
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
# usage: crm_mon_no_validation args...
|
||||
# run crm_mon without any cib schema validation
|
||||
# This is useful when an agent runs in a bundle to avoid potential
|
@ -1,82 +0,0 @@
|
||||
From 4420ef84f3172c67fc7b8b6ae41ea173de017bf4 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Pavlu <petr.pavlu@suse.com>
|
||||
Date: Wed, 25 May 2022 15:12:33 +0200
|
||||
Subject: [PATCH] aws-vpc-move-ip: Allow to set the interface label
|
||||
|
||||
Add a parameter to specify an interface label to distinguish the IP
|
||||
address managed by aws-vpc-move-ip, similarly as can be done with
|
||||
IPaddr2. This allows to easily recognize the address from other
|
||||
addresses assigned to a given interface.
|
||||
---
|
||||
heartbeat/aws-vpc-move-ip | 30 +++++++++++++++++++++++++++++-
|
||||
1 file changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip
|
||||
index 5d5204080..dee040300 100755
|
||||
--- a/heartbeat/aws-vpc-move-ip
|
||||
+++ b/heartbeat/aws-vpc-move-ip
|
||||
@@ -43,6 +43,7 @@ OCF_RESKEY_address_default=""
|
||||
OCF_RESKEY_routing_table_default=""
|
||||
OCF_RESKEY_routing_table_role_default=""
|
||||
OCF_RESKEY_interface_default="eth0"
|
||||
+OCF_RESKEY_iflabel_default=""
|
||||
OCF_RESKEY_monapi_default="false"
|
||||
OCF_RESKEY_lookup_type_default="InstanceId"
|
||||
|
||||
@@ -54,6 +55,7 @@ OCF_RESKEY_lookup_type_default="InstanceId"
|
||||
: ${OCF_RESKEY_routing_table=${OCF_RESKEY_routing_table_default}}
|
||||
: ${OCF_RESKEY_routing_table_role=${OCF_RESKEY_routing_table_role_default}}
|
||||
: ${OCF_RESKEY_interface=${OCF_RESKEY_interface_default}}
|
||||
+: ${OCF_RESKEY_iflabel=${OCF_RESKEY_iflabel_default}}
|
||||
: ${OCF_RESKEY_monapi=${OCF_RESKEY_monapi_default}}
|
||||
: ${OCF_RESKEY_lookup_type=${OCF_RESKEY_lookup_type_default}}
|
||||
|
||||
@@ -149,6 +151,18 @@ Name of the network interface, i.e. eth0
|
||||
<content type="string" default="${OCF_RESKEY_interface_default}" />
|
||||
</parameter>
|
||||
|
||||
+<parameter name="iflabel">
|
||||
+<longdesc lang="en">
|
||||
+You can specify an additional label for your IP address here.
|
||||
+This label is appended to your interface name.
|
||||
+
|
||||
+The kernel allows alphanumeric labels up to a maximum length of 15
|
||||
+characters including the interface name and colon (e.g. eth0:foobar1234)
|
||||
+</longdesc>
|
||||
+<shortdesc lang="en">Interface label</shortdesc>
|
||||
+<content type="string" default="${OCF_RESKEY_iflabel_default}"/>
|
||||
+</parameter>
|
||||
+
|
||||
<parameter name="monapi">
|
||||
<longdesc lang="en">
|
||||
Enable enhanced monitoring using AWS API calls to check route table entry
|
||||
@@ -215,6 +229,14 @@ ec2ip_validate() {
|
||||
return $OCF_ERR_CONFIGURED
|
||||
fi
|
||||
|
||||
+ if [ -n "$OCF_RESKEY_iflabel" ]; then
|
||||
+ label=${OCF_RESKEY_interface}:${OFC_RESKEY_iflabel}
|
||||
+ if [ ${#label} -gt 15 ]; then
|
||||
+ ocf_exit_reason "Interface label [$label] exceeds maximum character limit of 15"
|
||||
+ exit $OCF_ERR_CONFIGURED
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
||||
EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id -H "X-aws-ec2-metadata-token: $TOKEN")
|
||||
|
||||
@@ -363,7 +385,13 @@ ec2ip_get_and_configure() {
|
||||
|
||||
# Reconfigure the local ip address
|
||||
ec2ip_drop
|
||||
- cmd="ip addr add ${OCF_RESKEY_ip}/32 dev $OCF_RESKEY_interface"
|
||||
+
|
||||
+ extra_opts=""
|
||||
+ if [ -n "$OCF_RESKEY_iflabel" ]; then
|
||||
+ extra_opts="$extra_opts label $OCF_RESKEY_interface:$OCF_RESKEY_iflabel"
|
||||
+ fi
|
||||
+
|
||||
+ cmd="ip addr add ${OCF_RESKEY_ip}/32 dev $OCF_RESKEY_interface $extra_opts"
|
||||
ocf_log debug "executing command: $cmd"
|
||||
$cmd
|
||||
rc=$?
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user