diff --git a/SOURCES/bz1471182-crypt-1-new-ra.patch b/SOURCES/bz1471182-crypt-1-new-ra.patch new file mode 100644 index 0000000..7ed08b5 --- /dev/null +++ b/SOURCES/bz1471182-crypt-1-new-ra.patch @@ -0,0 +1,415 @@ +From 019c3108feff48d8ad496cd0759349c46170dc2d Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 6 Apr 2020 10:23:51 +0200 +Subject: [PATCH 1/2] crypt: new resource agent + +--- + doc/man/Makefile.am | 1 + + heartbeat/Makefile.am | 1 + + heartbeat/crypt | 337 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 339 insertions(+) + create mode 100755 heartbeat/crypt + +diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am +index 478fbe4f8..53c9975ec 100644 +--- a/doc/man/Makefile.am ++++ b/doc/man/Makefile.am +@@ -105,6 +105,7 @@ man_MANS = ocf_heartbeat_AoEtarget.7 \ + ocf_heartbeat_azure-lb.7 \ + ocf_heartbeat_clvm.7 \ + ocf_heartbeat_conntrackd.7 \ ++ ocf_heartbeat_crypt.7 \ + ocf_heartbeat_db2.7 \ + ocf_heartbeat_dhcpd.7 \ + ocf_heartbeat_docker.7 \ +diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am +index 893115810..bbc9590ac 100644 +--- a/heartbeat/Makefile.am ++++ b/heartbeat/Makefile.am +@@ -101,6 +101,7 @@ ocf_SCRIPTS = AoEtarget \ + azure-lb \ + clvm \ + conntrackd \ ++ crypt \ + db2 \ + dhcpd \ + dnsupdate \ +diff --git a/heartbeat/crypt b/heartbeat/crypt +new file mode 100755 +index 000000000..6bffdff89 +--- /dev/null ++++ b/heartbeat/crypt +@@ -0,0 +1,337 @@ ++#!/bin/sh ++# ++# crypt/LUKS OCF RA. Manages cryptsetup devices. ++# ++# Copyright (c) 2020 Red Hat GmbH, Heinz Mauelshagen ++# 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 ++ ++# Parameter defaults ++OCF_RESKEY_encrypted_dev_default="" ++OCF_RESKEY_crypt_dev_default="" ++OCF_RESKEY_key_file_default="" ++OCF_RESKEY_crypt_type_default="" ++OCF_RESKEY_force_stop_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}} ++ ++####################################################################### ++ ++meta_data() { ++ cat < ++ ++ ++1.0 ++ ++ ++This is a LUKS/crypt Resource Agent managing encrypted devices via cryptsetup(8). ++The agent imposes limitations on device types supported: luks, luks[1..N]. ++ ++LUKS/crypt resource agent ++ ++ ++ ++ ++ ++Encrypted backing device, which should be defined by UUID, ++36 characters including '-'s as reported by blkid(8). ++ ++Although it can be defined as a block device path (e.g. /dev/sdh), ++the UUID should be preferred over the block device path to allow for the ++unique discovery of the crypt backing device given the volatile nature of ++/dev entries (e.g. /dev/sdh on one node may be /dev/sdg on another). ++ ++Only define as block device path if you know what you are doing. ++ ++Encrypted device ++ ++ ++ ++ ++ ++Encrypted device name, no path. I.e. the one given in "cryptsetup open name ...". ++The resulting block device path is /dev/mapper/name. ++ ++Encrypted device ++ ++ ++ ++ ++ ++Key file path containing the encryption passphrase ++(aka key; see cryptsetup(8)). For LUKS, the passphrase as of the key_file ++parameter is used to decrypt a randomly selected key when the device was created. ++ ++Key file ++ ++ ++ ++ ++ ++Encryption (device) type (e.g. "luks" or "luks2"). ++ ++This parameter affirms the encryption format as of the crypt metadata ++thus allowing for safety measures when starting the encrypted resource. ++ ++Encryption type ++ ++ ++ ++ ++ ++If processes or kernel threads are using the crypt device, it cannot ++be stopped. We will try to stop processes, first by sending TERM and ++then, if that doesn't help in $PROC_CLEANUP_TIME seconds, using KILL. ++The lsof(8) program is required to get the list of array users. ++Of course, the kernel threads cannot be stopped this way. ++If the processes are critical for data integrity, then set this ++parameter to false. Note that in that case the stop operation ++will fail and the node will be fenced. ++ ++force stop processes using the crpyt device ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++END ++} ++ ++# Disable cryptsetup auto-recovery if cloned. ++disable_locks="" ++ocf_is_clone && disable_locks="--disable-locks" ++ ++crypt_usage() { ++ cat </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 ++ fi ++ if [ ! -r "$key_file" ]; then ++ ocf_exit_reason "Hash key file $key_file not accessible" ++ return $OCF_ERR_ARGS ++ fi ++ if ! ocf_is_true "$force_stop" && "$force_stop" != "false" ]]; then ++ ocf_exit_reason "Bogus force_stop=\"$force_stop\" attribute" ++ return $OCF_ERR_CONFIGURED ++ fi ++ if "$force_stop" = "true" && ! have_binary lsof; then ++ ocf_exit_reason "Force stop requested, please install lsof(8)" ++ return $OCF_ERR_INSTALLED ++ fi ++ cryptsetup isLuks $encrypted_dev 2>/dev/null ++ if [ $? -ne 0 ]; then ++ ocf_exit_reason "$encrypted_dev is not a Luks formatted device" ++ return $OCF_ERR_CONFIGURED ++ fi ++ ++ return $OCF_SUCCESS ++} ++ ++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' ++} ++ ++stop_crypt_users() { ++ local pids=`get_users_pids` ++ ++ if [ -z "$pids" ]; then ++ ocf_log warn "lsof reported no users holding arrays" ++ return 2 ++ fi ++ ++ ocf_stop_processes TERM $PROC_CLEANUP_TIME $pids ++} ++ ++show_users() { ++ local dm_dev ++ ++ ocf_log info "running lsof to list \"$crypt_dev\" users..." ++ ocf_run -warn lsof $crypt_dev_path ++ ++ dm_dev=$(basename $(realpath $crypt_dev_path)) ++ if [ -d /sys/block/$dm_dev/holders ]; then ++ ocf_log debug "ls -l /sys/block/$dm_dev/holders" ++ ocf_run -warn ls -l /sys/block/$dm_dev/holders ++ fi ++} ++ ++crypt_stop_one() { ++ cryptsetup close $crypt_dev $disable_locks ++} ++ ++####################################################################### ++# ++# Action: START an encrypted resource ++# ++crypt_start() { ++ local rc ++ ++ cryptsetup open $encrypted_dev $crypt_dev --type $crypt_type $disable_locks --key-file=$key_file ++ rc=$? ++ if [ $rc -eq 0 ];then ++ crypt_monitor ++ rc=$? ++ else ++ rc=$OCF_ERR_GERNERIC ++ fi ++ [ $rc -ne $OCF_SUCCESS ] ocf_exit_reason "Failed to start encrypted device \"$crypt_dev\"" ++ ++ return $rc ++} ++ ++# ++# Action: STOP an encrypted resource ++# ++crypt_stop() { ++ local rc ++ ++ crypt_monitor ++ rc=$? ++ if [ $rc -ne $OCF_NOT_RUNNING ]; then ++ crypt_stop_one ++ crypt_monitor ++ rc=$? ++ fi ++ if [ $rc -ne $OCF_NOT_RUNNING ] && ocf_is_true $FORCESTOP; then ++ stop_crypt_users ++ case $? in ++ 2) rc=$OCF_SUCCESS;; ++ *) crypt_stop_one ++ crypt_monitor ++ rc=$?;; ++ esac ++ fi ++ if [ $rc -ne $OCF_NOT_RUNNING ]; then ++ ocf_log warn "Couldn't stop crypt device \"$crypt_dev\" (rc=$rc)" ++ show_users ++ ocf_exit_reason "Failed to stop crypt device \"$crypt_dev\"!" ++ return $OCF_ERR_GENERIC ++ fi ++ ++ return $OCF_SUCCESS ++} ++ ++# ++# Action: MONITOR an encrypted resource ++# ++crypt_monitor() { ++ cryptsetup status $crypt_dev $disable_locks &>/dev/null ++ if [ $? -eq 0 ]; then ++ [ -L $crypt_dev_path ] && return $OCF_SUCCESS ++ return $OCF_ERR_GENERIC ++ fi ++ ++ [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe && ocf_exit_reason "Crypt resource not running" ++ return $OCF_NOT_RUNNING ++} ++ ++# Check for stange argument count. ++if [ $# -ne 1 ]; then ++ usage ++ exit $OCF_ERR_ARGS ++fi ++ ++case "$__OCF_ACTION" in ++meta-data) meta_data ++ exit $OCF_SUCCESS;; ++usage|help) crypt_usage ++ exit $OCF_SUCCESS;; ++esac ++ ++# XME: remove once pacemaker is fixed and calls this action ++crypt_validate_all ++rc=$? ++[ $rc -ne $OCF_SUCCESS ] && exit $rc ++ ++case "$__OCF_ACTION" in ++start) crypt_start; rc=$?;; ++stop) crypt_stop; rc=$?;; ++monitor) crypt_monitor; rc=$?;; ++validate-all) rc=$OCF_SUCCESS;; # crypt_validate_all would have errored out above already. ++*) crypt_usage ++ exit $OCF_ERR_UNIMPLEMENTED;; ++esac ++ ++ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" ++exit $rc + +From 5e0d35f8db967419ea9f1234ab621b88babcf3ea Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 7 Apr 2020 12:39:24 +0200 +Subject: [PATCH 2/2] crypt: force_stop check fixes + +--- + heartbeat/crypt | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/heartbeat/crypt b/heartbeat/crypt +index 6bffdff89..8bfa1094d 100755 +--- a/heartbeat/crypt ++++ b/heartbeat/crypt +@@ -190,11 +190,7 @@ crypt_validate_all() { + ocf_exit_reason "Hash key file $key_file not accessible" + return $OCF_ERR_ARGS + fi +- if ! ocf_is_true "$force_stop" && "$force_stop" != "false" ]]; then +- ocf_exit_reason "Bogus force_stop=\"$force_stop\" attribute" +- return $OCF_ERR_CONFIGURED +- fi +- if "$force_stop" = "true" && ! have_binary lsof; then ++ if ocf_is_true "$force_stop" && ! have_binary lsof; then + ocf_exit_reason "Force stop requested, please install lsof(8)" + return $OCF_ERR_INSTALLED + fi +@@ -273,7 +269,7 @@ crypt_stop() { + crypt_monitor + rc=$? + fi +- if [ $rc -ne $OCF_NOT_RUNNING ] && ocf_is_true $FORCESTOP; then ++ if [ $rc -ne $OCF_NOT_RUNNING ] && ocf_is_true $force_stop; then + stop_crypt_users + case $? in + 2) rc=$OCF_SUCCESS;; diff --git a/SOURCES/bz1471182-crypt-2-fix-bashism.patch b/SOURCES/bz1471182-crypt-2-fix-bashism.patch new file mode 100644 index 0000000..dace36f --- /dev/null +++ b/SOURCES/bz1471182-crypt-2-fix-bashism.patch @@ -0,0 +1,22 @@ +From 2915fa336e95b609d3d738d335799f015022c493 Mon Sep 17 00:00:00 2001 +From: Valentin Vidic +Date: Sat, 13 Jun 2020 08:47:36 +0200 +Subject: [PATCH] crypt: fix bashism + +--- + heartbeat/crypt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/crypt b/heartbeat/crypt +index 8bfa1094d..2727b5b23 100755 +--- a/heartbeat/crypt ++++ b/heartbeat/crypt +@@ -292,7 +292,7 @@ crypt_stop() { + # Action: MONITOR an encrypted resource + # + crypt_monitor() { +- cryptsetup status $crypt_dev $disable_locks &>/dev/null ++ cryptsetup status $crypt_dev $disable_locks >/dev/null 2>&1 + if [ $? -eq 0 ]; then + [ -L $crypt_dev_path ] && return $OCF_SUCCESS + return $OCF_ERR_GENERIC diff --git a/SOURCES/bz1471182-crypt-3-fix-missing-and.patch b/SOURCES/bz1471182-crypt-3-fix-missing-and.patch new file mode 100644 index 0000000..8a0deaf --- /dev/null +++ b/SOURCES/bz1471182-crypt-3-fix-missing-and.patch @@ -0,0 +1,22 @@ +From 635c344fb85ef225b8a0c094687d2838b0b0cd2c Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 26 Oct 2020 16:36:06 +0100 +Subject: [PATCH] crypt: fix missing && to set exit_reason + +--- + heartbeat/crypt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/crypt b/heartbeat/crypt +index 2727b5b23..0e49b6c2d 100755 +--- a/heartbeat/crypt ++++ b/heartbeat/crypt +@@ -251,7 +251,7 @@ crypt_start() { + else + rc=$OCF_ERR_GERNERIC + fi +- [ $rc -ne $OCF_SUCCESS ] ocf_exit_reason "Failed to start encrypted device \"$crypt_dev\"" ++ [ $rc -ne $OCF_SUCCESS ] && ocf_exit_reason "Failed to start encrypted device \"$crypt_dev\"" + + return $rc + } diff --git a/SOURCES/bz1640587-pgsql-ignore-masters-re-promote.patch b/SOURCES/bz1640587-pgsql-ignore-masters-re-promote.patch new file mode 100644 index 0000000..b371857 --- /dev/null +++ b/SOURCES/bz1640587-pgsql-ignore-masters-re-promote.patch @@ -0,0 +1,40 @@ +From 355cd29f2dee828bfe0a4ab64f425827aba7dd3b Mon Sep 17 00:00:00 2001 +From: Hideo Yamauchi +Date: Wed, 17 Oct 2018 09:54:37 +0900 +Subject: [PATCH] Mid: pgsql: Fix to ignore Master's re-promote. + +--- + heartbeat/pgsql | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/heartbeat/pgsql b/heartbeat/pgsql +index 380866da1..38f6ceeb7 100755 +--- a/heartbeat/pgsql ++++ b/heartbeat/pgsql +@@ -680,6 +680,7 @@ pgsql_start() { + + #pgsql_promote: Promote PostgreSQL + pgsql_promote() { ++ local output + local target + local rc + +@@ -687,6 +688,18 @@ pgsql_promote() { + ocf_exit_reason "Not in a replication mode." + return $OCF_ERR_CONFIGURED + fi ++ ++ output=`exec_sql "${CHECK_MS_SQL}"` ++ if [ $? -ne 0 ]; then ++ report_psql_error $rc $loglevel "Can't get PostgreSQL recovery status on promote." ++ return $OCF_ERR_GENERIC ++ fi ++ ++ if [ "$output" = "f" ]; then ++ ocf_log info "PostgreSQL is alredy Master. Don't execute promote." ++ return $OCF_SUCCESS ++ fi ++ + rm -f ${XLOG_NOTE_FILE}.* + + for target in $NODE_LIST; do diff --git a/SOURCES/bz1763249-manpages-fix-pcs-syntax.patch b/SOURCES/bz1763249-manpages-fix-pcs-syntax.patch new file mode 100644 index 0000000..eff376b --- /dev/null +++ b/SOURCES/bz1763249-manpages-fix-pcs-syntax.patch @@ -0,0 +1,53 @@ +From 0903a60930238238d5caa6c3b42b28d7bc4cccf4 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 26 Oct 2020 13:11:05 +0100 +Subject: [PATCH 1/2] man: use promotable keyword in manpage examples + +--- + doc/man/ra2refentry.xsl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/doc/man/ra2refentry.xsl b/doc/man/ra2refentry.xsl +index d0535fd36..f3cdcdbb2 100644 +--- a/doc/man/ra2refentry.xsl ++++ b/doc/man/ra2refentry.xsl +@@ -556,7 +556,7 @@ + + +- --master ++ promotable + + + + +From bfcd5796ae12e6a43a245d0c785f183342943393 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 26 Oct 2020 16:56:00 +0100 +Subject: [PATCH 2/2] man: use OCF_CHECK_LEVEL for depth parameters in pcs + examples + +--- + doc/man/ra2refentry.xsl | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/doc/man/ra2refentry.xsl b/doc/man/ra2refentry.xsl +index f3cdcdbb2..f8e12321f 100644 +--- a/doc/man/ra2refentry.xsl ++++ b/doc/man/ra2refentry.xsl +@@ -612,7 +612,14 @@ + + + +- ++ ++ ++ ++ ++ ++ OCF_CHECK_LEVEL ++ ++ + =" + + " diff --git a/SOURCES/bz1795535-pgsql-1-add-postgresql-12-support.patch b/SOURCES/bz1795535-pgsql-1-add-postgresql-12-support.patch new file mode 100644 index 0000000..3c05aba --- /dev/null +++ b/SOURCES/bz1795535-pgsql-1-add-postgresql-12-support.patch @@ -0,0 +1,105 @@ +From a43075be72683e1d4ddab700ec16d667164d359c Mon Sep 17 00:00:00 2001 +From: Kazutomo Nakahira +Date: Mon, 25 Nov 2019 17:40:33 +0900 +Subject: [PATCH 1/2] High: pgsql: Support for PostgreSQL 12 + +--- + heartbeat/pgsql | 32 +++++++++++++++++++++++++++++++- + 1 file changed, 31 insertions(+), 1 deletion(-) + +diff --git a/heartbeat/pgsql b/heartbeat/pgsql +index b1c070ead..5bc76cc4c 100755 +--- a/heartbeat/pgsql ++++ b/heartbeat/pgsql +@@ -1612,12 +1612,24 @@ make_recovery_conf() { + fi + + cat > $RECOVERY_CONF <> $RECOVERY_CONF <> $RECOVERY_CONF + ocf_log debug "Created recovery.conf. host=${OCF_RESKEY_master_ip}, user=${OCF_RESKEY_repuser}" + return 0 +@@ -1835,6 +1847,7 @@ pgsql_validate_all() { + local version + local check_config_rc + local rep_mode_string ++ local recovery_conf_string + local socket_directories + local rc + +@@ -1898,6 +1911,22 @@ pgsql_validate_all() { + ocf_exit_reason "Replication mode needs PostgreSQL 9.1 or higher." + return $OCF_ERR_INSTALLED + fi ++ ocf_version_cmp "$version" "12" ++ rc=$? ++ if [ $rc -eq 1 ]||[ $rc -eq 2 ]; then ++ # change the standby method for PosrgreSQL 12 or later. ++ USE_STANDBY_SIGNAL=true ++ # change the path to recovery.conf because it cause PostgreSQL start error. ++ RECOVERY_CONF=${OCF_RESKEY_tmpdir}/recovery.conf ++ if [ $check_config_rc -eq 0 ]; then ++ # adding recovery parameters to postgresql.conf. ++ recovery_conf_string="include '$RECOVERY_CONF' # added by pgsql RA" ++ if ! grep -q "^[[:space:]]*$recovery_conf_string" $OCF_RESKEY_config; then ++ ocf_log info "adding include directive $recovery_conf_string into $OCF_RESKEY_config" ++ echo "$recovery_conf_string" >> $OCF_RESKEY_config ++ fi ++ fi ++ fi + if [ ! -n "$OCF_RESKEY_master_ip" ]; then + ocf_exit_reason "master_ip can't be empty." + return $OCF_ERR_CONFIGURED +@@ -2107,6 +2136,7 @@ RESOURCE_NAME=`echo $OCF_RESOURCE_INSTANCE | cut -d ":" -f 1` + PGSQL_WAL_RECEIVER_STATUS_ATTR="${RESOURCE_NAME}-receiver-status" + RECOVERY_CONF=${OCF_RESKEY_pgdata}/recovery.conf + NODENAME=$(ocf_local_nodename | tr '[A-Z]' '[a-z]') ++USE_STANDBY_SIGNAL=false + + case "$1" in + methods) pgsql_methods + +From 5ab3339e8cb236583d375f5577f5a4dc129d5b27 Mon Sep 17 00:00:00 2001 +From: munenari +Date: Thu, 16 Jan 2020 09:27:59 +0900 +Subject: [PATCH 2/2] Remove standby.signal when promote with restart + +--- + heartbeat/pgsql | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/heartbeat/pgsql b/heartbeat/pgsql +index 5bc76cc4c..d5baa7b35 100755 +--- a/heartbeat/pgsql ++++ b/heartbeat/pgsql +@@ -720,7 +720,11 @@ pgsql_promote() { + ocf_log info "Restarting PostgreSQL instead of promote." + #stop : this function returns $OCF_SUCCESS only. + pgsql_real_stop slave +- rm -f $RECOVERY_CONF ++ if "${USE_STANDBY_SIGNAL}"; then ++ rm -f ${OCF_RESKEY_pgdata}/standby.signal ++ else ++ rm -f $RECOVERY_CONF ++ fi + pgsql_real_start + rc=$? + if [ $rc -ne $OCF_RUNNING_MASTER ]; then diff --git a/SOURCES/bz1795535-pgsql-2-fix-uppercase-hostname-support.patch b/SOURCES/bz1795535-pgsql-2-fix-uppercase-hostname-support.patch new file mode 100644 index 0000000..06c9aef --- /dev/null +++ b/SOURCES/bz1795535-pgsql-2-fix-uppercase-hostname-support.patch @@ -0,0 +1,48 @@ +From e56d0e1727bf84d0664db544a129a0237a1757c0 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 11 Sep 2020 10:12:21 +0200 +Subject: [PATCH 1/2] pgsql: lower-case application_name to avoid issues with + upper-case hostnames + +--- + heartbeat/pgsql | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/pgsql b/heartbeat/pgsql +index 99e074287..de9f750c5 100755 +--- a/heartbeat/pgsql ++++ b/heartbeat/pgsql +@@ -1960,7 +1960,7 @@ pgsql_validate_all() { + else + CHECK_XLOG_LOC_SQL="select pg_last_xlog_replay_location(),pg_last_xlog_receive_location()" + fi +- CHECK_REPLICATION_STATE_SQL="select application_name,upper(state),upper(sync_state) from pg_stat_replication" ++ CHECK_REPLICATION_STATE_SQL="select lower(application_name),upper(state),upper(sync_state) from pg_stat_replication" + + PGSQL_STATUS_ATTR="${RESOURCE_NAME}-status" + PGSQL_DATA_STATUS_ATTR="${RESOURCE_NAME}-data-status" + +From 5aee799878180bb8daca82aebc2290c2735045eb Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 11 Sep 2020 10:13:47 +0200 +Subject: [PATCH 2/2] pgsql: set exit-reason when failing due to remaining + PGSQL.lock + +--- + heartbeat/pgsql | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/heartbeat/pgsql b/heartbeat/pgsql +index de9f750c5..5a0628b7a 100755 +--- a/heartbeat/pgsql ++++ b/heartbeat/pgsql +@@ -966,6 +966,9 @@ pgsql_real_monitor() { + if ! pgsql_status + then + ocf_log info "PostgreSQL is down" ++ if [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe && [ -f $PGSQL_LOCK ]; then ++ ocf_exit_reason "My data may be inconsistent. You have to remove $PGSQL_LOCK file to force start." ++ fi + return $OCF_NOT_RUNNING + fi + diff --git a/SOURCES/bz1815013-redis-parse-password-correctly-based-on-version.patch b/SOURCES/bz1815013-redis-parse-password-correctly-based-on-version.patch new file mode 100644 index 0000000..c61a306 --- /dev/null +++ b/SOURCES/bz1815013-redis-parse-password-correctly-based-on-version.patch @@ -0,0 +1,169 @@ +From 2270c5d6aaf8b3b6d663d413a8e7193a493cfdc5 Mon Sep 17 00:00:00 2001 +From: Konstantin Pokotilenko +Date: Tue, 24 Sep 2019 17:26:11 +0300 +Subject: [PATCH 1/2] Consider redis-cli features to choose optimal password + passing method and warning filtering workaround + +--- + heartbeat/redis.in | 60 +++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 3 deletions(-) + +diff --git a/heartbeat/redis.in b/heartbeat/redis.in +index ec7186d8b..409961d0b 100644 +--- a/heartbeat/redis.in ++++ b/heartbeat/redis.in +@@ -237,6 +237,51 @@ CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name ${INST + MASTER_HOST="" + MASTER_ACTIVE_CACHED="" + MASTER_ACTIVE="" ++CLI_HAVE_AUTH_WARNING=0 ++CLI_HAVE_ARG_NO_AUTH_WARNING=0 ++CLI_HAVE_ENV_AUTH=0 ++ ++cmp_redis_version() ++{ ++ ++ if [ "$1" == "$2" ]; then ++ return 1 ++ elif [ $(echo -e "$1\n$2" | sort -V | head -1) == "$1" ]; then ++ return 0 ++ else ++ return 2 ++ fi ++} ++ ++redis_cli_features() ++{ ++ ++ CLI_VER=$(redis-cli --version | tr " " "\n" | tail -1) ++ # Starting with 4.0.10 there is a warning on stderr when using a pass ++ # Starting with 5.0.0 there is an argument to silence the warning: --no-auth-warning ++ # Starting with 5.0.3 there is an option to use REDISCLI_AUTH evironment variable for password, no warning in this case ++ ++ cmp_redis_version $CLI_VER 5.0.3 ++ res=$? ++ echo 5.0.3: $res ++ if [[ res -ge 1 ]]; then ++ CLI_HAVE_ENV_AUTH=1 ++ fi ++ ++ cmp_redis_version $CLI_VER 5.0.0 ++ res=$? ++ echo 5.0.0: $res ++ if [[ res -ge 1 ]]; then ++ CLI_HAVE_ARG_NO_AUTH_WARNING=1 ++ fi ++ ++ cmp_redis_version $CLI_VER 4.0.10 ++ res=$? ++ echo 4.0.10: $res ++ if [[ res -ge 1 ]]; then ++ CLI_HAVE_AUTH_WARNING=1 ++ fi ++} + + master_is_active() + { +@@ -315,9 +360,16 @@ set_score() + redis_client() { + ocf_log debug "redis_client: '$REDIS_CLIENT' -s '$REDIS_SOCKET' $*" + if [ -n "$clientpasswd" ]; then +- # Starting with 4.0.10 there is a warning on stderr when using a pass +- # Once we stop supporting versions < 5.0.0 we can add --no-auth-warning here +- ("$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" 2>&1 >&3 3>&- | grep -v "Using a password" >&2 3>&-) 3>&1 | sed 's/\r//' ++ # Consider redis-cli features to choose optimal password passing method and warning filtering workaround ++ if [[ CLI_HAVE_ENV_AUTH -eq 1 ]]; then ++ REDISCLI_AUTH=$clientpasswd "$REDIS_CLIENT" -s "$REDIS_SOCKET" "$@" | sed 's/\r//' ++ elif [[ CLI_HAVE_ARG_NO_AUTH_WARNING -eq 1 ]]; then ++ "$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" --no-auth-warning | sed 's/\r//' ++ elif [[ CLI_HAVE_AUTH_WARNING -eq 1 ]]; then ++ ("$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" 2>&1 >&3 3>&- | grep -v "Using a password" >&2 3>&-) 3>&1 | sed 's/\r//' ++ else ++ "$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" | sed 's/\r//' ++ fi + else + "$REDIS_CLIENT" -s "$REDIS_SOCKET" "$@" | sed 's/\r//' + fi +@@ -686,6 +738,8 @@ if [ -r "$REDIS_CONFIG" ]; then + clientpasswd="$(sed -n -e 's/^\s*requirepass\s*\(.*\)\s*$/\1/p' < $REDIS_CONFIG | tail -n 1)" + fi + ++redis_cli_features ++ + ocf_log debug "action=${1:-$__OCF_ACTION} notify_type=${OCF_RESKEY_CRM_meta_notify_type} notify_operation=${OCF_RESKEY_CRM_meta_notify_operation} master_host=${OCF_RESKEY_CRM_meta_notify_master_uname} slave_host=${OCF_RESKEY_CRM_meta_notify_slave_uname} promote_host=${OCF_RESKEY_CRM_meta_notify_promote_uname} demote_host=${OCF_RESKEY_CRM_meta_notify_demote_uname}; params: bin=${OCF_RESKEY_bin} client_bin=${OCF_RESKEY_client_bin} config=${OCF_RESKEY_config} user=${OCF_RESKEY_user} rundir=${OCF_RESKEY_rundir} port=${OCF_RESKEY_port}" + + case "${1:-$__OCF_ACTION}" in + +From 0b9f942a88bfc3ad04938aa5135fad8f8bece69c Mon Sep 17 00:00:00 2001 +From: Konstantin Pokotilenko +Date: Tue, 24 Sep 2019 18:35:59 +0300 +Subject: [PATCH 2/2] use ocf_version_cmp instead of own implementation use + same method of getting redis-cli version as already used before in file, this + also uses redis client from variable instead of hardcoded remove debug output + fix --no-auth-warning argument position + +--- + heartbeat/redis.in | 25 +++++-------------------- + 1 file changed, 5 insertions(+), 20 deletions(-) + +diff --git a/heartbeat/redis.in b/heartbeat/redis.in +index 409961d0b..d722fb12c 100644 +--- a/heartbeat/redis.in ++++ b/heartbeat/redis.in +@@ -241,43 +241,28 @@ CLI_HAVE_AUTH_WARNING=0 + CLI_HAVE_ARG_NO_AUTH_WARNING=0 + CLI_HAVE_ENV_AUTH=0 + +-cmp_redis_version() +-{ +- +- if [ "$1" == "$2" ]; then +- return 1 +- elif [ $(echo -e "$1\n$2" | sort -V | head -1) == "$1" ]; then +- return 0 +- else +- return 2 +- fi +-} +- + redis_cli_features() + { + +- CLI_VER=$(redis-cli --version | tr " " "\n" | tail -1) ++ CLI_VER=$("$REDIS_CLIENT" -v | awk '{print $NF}') + # Starting with 4.0.10 there is a warning on stderr when using a pass + # Starting with 5.0.0 there is an argument to silence the warning: --no-auth-warning + # Starting with 5.0.3 there is an option to use REDISCLI_AUTH evironment variable for password, no warning in this case + +- cmp_redis_version $CLI_VER 5.0.3 ++ ocf_version_cmp $CLI_VER 5.0.3 + res=$? +- echo 5.0.3: $res + if [[ res -ge 1 ]]; then + CLI_HAVE_ENV_AUTH=1 + fi + +- cmp_redis_version $CLI_VER 5.0.0 ++ ocf_version_cmp $CLI_VER 5.0.0 + res=$? +- echo 5.0.0: $res + if [[ res -ge 1 ]]; then + CLI_HAVE_ARG_NO_AUTH_WARNING=1 + fi + +- cmp_redis_version $CLI_VER 4.0.10 ++ ocf_version_cmp $CLI_VER 4.0.10 + res=$? +- echo 4.0.10: $res + if [[ res -ge 1 ]]; then + CLI_HAVE_AUTH_WARNING=1 + fi +@@ -364,7 +349,7 @@ redis_client() { + if [[ CLI_HAVE_ENV_AUTH -eq 1 ]]; then + REDISCLI_AUTH=$clientpasswd "$REDIS_CLIENT" -s "$REDIS_SOCKET" "$@" | sed 's/\r//' + elif [[ CLI_HAVE_ARG_NO_AUTH_WARNING -eq 1 ]]; then +- "$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" --no-auth-warning | sed 's/\r//' ++ "$REDIS_CLIENT" -s "$REDIS_SOCKET" --no-auth-warning -a "$clientpasswd" "$@" | sed 's/\r//' + elif [[ CLI_HAVE_AUTH_WARNING -eq 1 ]]; then + ("$REDIS_CLIENT" -s "$REDIS_SOCKET" -a "$clientpasswd" "$@" 2>&1 >&3 3>&- | grep -v "Using a password" >&2 3>&-) 3>&1 | sed 's/\r//' + else diff --git a/SOURCES/bz1848025-sybaseASE-run-verify-for-start-action-only.patch b/SOURCES/bz1848025-sybaseASE-run-verify-for-start-action-only.patch new file mode 100644 index 0000000..402bbd6 --- /dev/null +++ b/SOURCES/bz1848025-sybaseASE-run-verify-for-start-action-only.patch @@ -0,0 +1,41 @@ +From 953f689cb2a37606b6d4b2250ebec23f129f5095 Mon Sep 17 00:00:00 2001 +From: Reid wahl +Date: Thu, 9 Jul 2020 23:32:22 -0700 +Subject: [PATCH] sybaseASE: Run verify_all() for start operation only + +The `sybaseASE` resource agent runs the `verify_all()` function at the +beginning of start, stop, and monitor operations. + +When `verify_all()` is run for a probe (monitor) operation and +`sybase_home` resides on a cluster-managed filesystem, the probe often +fails with `$OCF_ERR_GENERIC` because the filesystem isn't mounted yet. +This prevents the resource from starting on that node. + +For the stop operation, there's simply no reason to run `verify_all()`. + +This patch removes `verify_all()` for the stop and monitor operations. +It is now only run for the start operation. + +Resolves: RHBZ#1848673 +Resolves: RHBZ#1848025 +--- + heartbeat/sybaseASE.in | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/heartbeat/sybaseASE.in b/heartbeat/sybaseASE.in +index 9ddd429be..7ff30bd31 100755 +--- a/heartbeat/sybaseASE.in ++++ b/heartbeat/sybaseASE.in +@@ -864,12 +864,10 @@ case $__OCF_ACTION in + exit $? + ;; + stop) +- verify_all || exit $OCF_ERR_GENERIC + ase_stop + exit $? + ;; + status | monitor) +- verify_all || exit $OCF_ERR_GENERIC + ase_status $OCF_CHECK_LEVEL + exit $? + ;; diff --git a/SOURCES/bz1858752-Filesystem-support-whitespace-device-dir.patch b/SOURCES/bz1858752-Filesystem-support-whitespace-device-dir.patch new file mode 100644 index 0000000..15fb71f --- /dev/null +++ b/SOURCES/bz1858752-Filesystem-support-whitespace-device-dir.patch @@ -0,0 +1,566 @@ +From a8051cf9e21d231ce3c445f09631266157ffc2e0 Mon Sep 17 00:00:00 2001 +From: Reid wahl +Date: Fri, 10 Jul 2020 03:44:18 -0700 +Subject: [PATCH 1/3] Filesystem: Support whitespace in device or directory + name + +Whitespace in a device name (e.g., a CIFS share) or a directory name +breaks resource operations. + +One issue is that many of the variable occurrences aren't quoted, so a +string containing whitespace is split into multiple tokens. This is a +problem when the string meant to be passed as a single argument to a +function (e.g., `list_submounts()`). + +Another issue involves the parsing of `list_mounts()` output. +`list_mounts()` can pull data from `/proc/mounts`, `/etc/mtab`, or the +`mount` command. `/proc/mounts` and `/etc/mtab` represent spaces within +a field as octal `\040` strings, while `mount` represents them as +literal space characters. + +`list_mounts()` had to be modified to output the mount list as three +distinct fields ((`device`, `mountpoint`, `fstype`), separated by tab +characters) regardless of the data source. Parsers of `list_mounts()` +were modified to use tabs as field delimiters. + +The for loop in `Filesystem_stop()` also had to become a while loop to +read line-by-line irrespective of spaces. A for loop splits on spaces. + +Resolves: RHBZ#1624591 +--- + heartbeat/Filesystem | 106 +++++++++++++++++++++++++------------------ + 1 file changed, 61 insertions(+), 45 deletions(-) + +diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem +index 2f07a90ad..9a52aa712 100755 +--- a/heartbeat/Filesystem ++++ b/heartbeat/Filesystem +@@ -91,6 +91,7 @@ fi + + # Variables used by multiple methods + HOSTOS=`uname` ++TAB=' ' + + # The status file is going to an extra directory, by default + # +@@ -100,7 +101,7 @@ suffix="${OCF_RESOURCE_INSTANCE}" + [ "$OCF_RESKEY_CRM_meta_clone" ] && + suffix="${suffix}_$OCF_RESKEY_CRM_meta_clone" + suffix="${suffix}_`uname -n`" +-STATUSFILE=${OCF_RESKEY_directory}/$prefix$suffix ++STATUSFILE="${OCF_RESKEY_directory}/$prefix$suffix" + + ####################################################################### + +@@ -283,6 +284,7 @@ flushbufs() { + is_bind_mount() { + echo "$options" | grep -w bind >/dev/null 2>&1 + } ++ + list_mounts() { + local inpf="" + local mount_list="" +@@ -296,15 +298,23 @@ list_mounts() { + + # Make sure that the mount list has not been changed while reading. + while [ "$mount_list" != "$check_list" ]; do +- check_list=$mount_list ++ check_list="$mount_list" + if [ "$inpf" ]; then +- mount_list=$(cut -d' ' -f1,2,3 < $inpf) ++ # ... ++ # Spaces in device or mountpoint are octal \040 in $inpf ++ # Convert literal spaces (field separators) to tabs ++ mount_list=$(cut -d' ' -f1,2,3 < $inpf | tr ' ' "$TAB") + else +- mount_list=$($MOUNT | cut -d' ' -f1,3,5) ++ # on type ... ++ # Use tabs as field separators ++ match_string='\(.*\) on \(.*\) type \([^[:space:]]\)' ++ replace_string="\\1${TAB}\\3${TAB}\\5" ++ mount_list=$($MOUNT | sed "s/$match_string/$replace_string/g") + fi + done + +- echo "$mount_list" ++ # Convert octal \040 to space characters ++ printf "$mount_list" + } + + determine_blockdevice() { +@@ -318,7 +328,8 @@ determine_blockdevice() { + nfs4|nfs|smbfs|cifs|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|none|lustre) + : ;; + *) +- DEVICE=`list_mounts | grep " $CANONICALIZED_MOUNTPOINT " | cut -d' ' -f1` ++ match_string="${TAB}${CANONICALIZED_MOUNTPOINT}${TAB}" ++ DEVICE=`list_mounts | grep "$match_string" | cut -d"$TAB" -f1` + if [ -b "$DEVICE" ]; then + blockdevice=yes + fi +@@ -329,7 +340,7 @@ determine_blockdevice() { + # Lists all filesystems potentially mounted under a given path, + # excluding the path itself. + list_submounts() { +- list_mounts | grep " $1/" | cut -d' ' -f2 | sort -r ++ list_mounts | grep "${TAB}${1}/" | cut -d"$TAB" -f2 | sort -r + } + + # kernels < 2.6.26 can't handle bind remounts +@@ -358,15 +369,15 @@ bind_mount() { + if is_bind_mount && [ "$options" != "-o bind" ] + then + bind_kernel_check +- bind_opts=`echo $options | sed 's/bind/remount/'` +- $MOUNT $bind_opts $MOUNTPOINT ++ bind_opts=`echo "$options" | sed 's/bind/remount/'` ++ $MOUNT $bind_opts "$MOUNTPOINT" + else + true # make sure to return OK + fi + } + + is_option() { +- echo $OCF_RESKEY_options | grep -w "$1" >/dev/null 2>&1 ++ echo "$OCF_RESKEY_options" | grep -w "$1" >/dev/null 2>&1 + } + + is_fsck_needed() { +@@ -374,7 +385,7 @@ is_fsck_needed() { + force) true;; + no) false;; + ""|auto) +- case $FSTYPE in ++ 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) + false;; + *) +@@ -403,7 +414,7 @@ fstype_supported() + fi + + # support fuse-filesystems (e.g. GlusterFS) +- case $FSTYPE in ++ case "$FSTYPE" in + fuse.*|glusterfs|rozofs) support="fuse";; + esac + +@@ -486,7 +497,8 @@ trigger_udev_rules_if_needed() + Filesystem_start() + { + # Check if there are any mounts mounted under the mountpoint +- if list_mounts | grep -q -E " $CANONICALIZED_MOUNTPOINT/\w+" >/dev/null 2>&1; then ++ match_string="${TAB}${CANONICALIZED_MOUNTPOINT}" ++ if list_mounts | grep -q -E "$match_string/\w+" >/dev/null 2>&1; then + ocf_log err "There is one or more mounts mounted under $MOUNTPOINT." + return $OCF_ERR_CONFIGURED + fi +@@ -514,9 +526,9 @@ Filesystem_start() + if is_fsck_needed; then + ocf_log info "Starting filesystem check on $DEVICE" + if [ -z "$FSTYPE" ]; then +- $FSCK -p $DEVICE ++ $FSCK -p "$DEVICE" + else +- $FSCK -t $FSTYPE -p $DEVICE ++ $FSCK -t "$FSTYPE" -p "$DEVICE" + fi + + # NOTE: if any errors at all are detected, it returns non-zero +@@ -529,20 +541,20 @@ Filesystem_start() + fi + + [ -d "$MOUNTPOINT" ] || +- ocf_run mkdir -p $MOUNTPOINT ++ ocf_run mkdir -p "$MOUNTPOINT" + if [ ! -d "$MOUNTPOINT" ] ; then + ocf_exit_reason "Couldn't find directory [$MOUNTPOINT] to use as a mount point" + exit $OCF_ERR_INSTALLED + fi + +- flushbufs $DEVICE ++ flushbufs "$DEVICE" + # Mount the filesystem. + case "$FSTYPE" in +- none) $MOUNT $options $DEVICE $MOUNTPOINT && ++ none) $MOUNT $options "$DEVICE" "$MOUNTPOINT" && + bind_mount + ;; +- "") $MOUNT $options $DEVICE $MOUNTPOINT ;; +- *) $MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT ;; ++ "") $MOUNT $options "$DEVICE" "$MOUNTPOINT" ;; ++ *) $MOUNT -t "$FSTYPE" $options "$DEVICE" "$MOUNTPOINT" ;; + esac + + if [ $? -ne 0 ]; then +@@ -595,23 +607,23 @@ signal_processes() { + done + } + try_umount() { +- local SUB=$1 +- $UMOUNT $umount_force $SUB +- list_mounts | grep -q " $SUB " >/dev/null 2>&1 || { ++ local SUB="$1" ++ $UMOUNT $umount_force "$SUB" ++ list_mounts | grep -q "${TAB}${SUB}${TAB}" >/dev/null 2>&1 || { + ocf_log info "unmounted $SUB successfully" + return $OCF_SUCCESS + } + return $OCF_ERR_GENERIC + } + fs_stop() { +- local SUB=$1 timeout=$2 sig cnt ++ local SUB="$1" timeout=$2 sig cnt + for sig in TERM KILL; do + cnt=$((timeout/2)) # try half time with TERM + while [ $cnt -gt 0 ]; do +- try_umount $SUB && ++ try_umount "$SUB" && + return $OCF_SUCCESS + ocf_exit_reason "Couldn't unmount $SUB; trying cleanup with $sig" +- signal_processes $SUB $sig ++ signal_processes "$SUB" $sig + cnt=$((cnt-1)) + sleep 1 + done +@@ -633,7 +645,7 @@ Filesystem_stop() + # Wipe the status file, but continue with a warning if + # removal fails -- the file system might be read only + if [ $OCF_CHECK_LEVEL -eq 20 ]; then +- rm -f ${STATUSFILE} ++ rm -f "${STATUSFILE}" + if [ $? -ne 0 ]; then + ocf_log warn "Failed to remove status file ${STATUSFILE}." + fi +@@ -650,7 +662,7 @@ Filesystem_stop() + + # Umount all sub-filesystems mounted under $MOUNTPOINT/ too. + local timeout +- for SUB in `list_submounts $MOUNTPOINT` $MOUNTPOINT; do ++ while read SUB; do + ocf_log info "Trying to unmount $SUB" + if ocf_is_true "$FAST_STOP"; then + timeout=6 +@@ -658,15 +670,18 @@ Filesystem_stop() + timeout=${OCF_RESKEY_CRM_meta_timeout:="20000"} + timeout=$((timeout/1000)) + fi +- fs_stop $SUB $timeout ++ fs_stop "$SUB" $timeout + rc=$? + if [ $rc -ne $OCF_SUCCESS ]; then + ocf_exit_reason "Couldn't unmount $SUB, giving up!" + fi +- done ++ done <<-EOF ++ $(list_submounts "$CANONICALIZED_MOUNTPOINT"; \ ++ echo $CANONICALIZED_MOUNTPOINT) ++ EOF + fi + +- flushbufs $DEVICE ++ flushbufs "$DEVICE" + + return $rc + } +@@ -677,7 +692,8 @@ Filesystem_stop() + # + Filesystem_status() + { +- if list_mounts | grep -q " $CANONICALIZED_MOUNTPOINT " >/dev/null 2>&1; then ++ match_string="${TAB}${CANONICALIZED_MOUNTPOINT}${TAB}" ++ if list_mounts | grep -q "$match_string" >/dev/null 2>&1; then + rc=$OCF_SUCCESS + msg="$MOUNTPOINT is mounted (running)" + else +@@ -712,7 +728,7 @@ Filesystem_monitor_10() + return $OCF_SUCCESS + fi + dd_opts="iflag=direct bs=4k count=1" +- err_output=`dd if=$DEVICE $dd_opts 2>&1 >/dev/null` ++ err_output=`dd if="$DEVICE" $dd_opts 2>&1 >/dev/null` + if [ $? -ne 0 ]; then + ocf_exit_reason "Failed to read device $DEVICE" + ocf_log err "dd said: $err_output" +@@ -733,20 +749,20 @@ Filesystem_monitor_20() + # to bypass caches. + dd_opts="oflag=direct,sync bs=4k conv=fsync,sync" + fi +- status_dir=`dirname $STATUSFILE` ++ status_dir=$(dirname "$STATUSFILE") + [ -d "$status_dir" ] || mkdir -p "$status_dir" +- err_output=`echo "${OCF_RESOURCE_INSTANCE}" | dd of=${STATUSFILE} $dd_opts 2>&1` ++ err_output=`echo "${OCF_RESOURCE_INSTANCE}" | dd of="${STATUSFILE}" $dd_opts 2>&1` + if [ $? -ne 0 ]; then + ocf_exit_reason "Failed to write status file ${STATUSFILE}" + ocf_log err "dd said: $err_output" + return $OCF_ERR_GENERIC + fi +- test -f ${STATUSFILE} ++ test -f "${STATUSFILE}" + if [ $? -ne 0 ]; then + ocf_exit_reason "Cannot stat the status file ${STATUSFILE}" + return $OCF_ERR_GENERIC + fi +- cat ${STATUSFILE} > /dev/null ++ cat "${STATUSFILE}" > /dev/null + if [ $? -ne 0 ]; then + ocf_exit_reason "Cannot read the status file ${STATUSFILE}" + return $OCF_ERR_GENERIC +@@ -791,9 +807,9 @@ Filesystem_validate_all() + # 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 -q ^$FSTYPE$ ++ cut -f2 /proc/filesystems |grep -q "^${FSTYPE}$" + if [ $? -ne 0 ]; then +- modpath=/lib/modules/`uname -r` ++ modpath=/lib/modules/`uname -r` + moddep=$modpath/modules.dep + # Do we have $FSTYPE in modules.dep? + cut -d' ' -f1 $moddep |grep -q "^$modpath.*$FSTYPE\.k\?o:$" +@@ -826,7 +842,7 @@ set_blockdevice_var() { + blockdevice=no + + # these are definitely not block devices +- case $FSTYPE in ++ case "$FSTYPE" in + nfs4|nfs|smbfs|cifs|none|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs) return;; + esac + +@@ -834,7 +850,7 @@ set_blockdevice_var() { + return + fi + +- case $DEVICE in ++ case "$DEVICE" in + -*) # Oh... An option to mount instead... Typically -U or -L + ;; + /dev/null) # Special case for BSC +@@ -863,7 +879,7 @@ if [ -n "${OCF_RESKEY_force_unmount}" ]; then + FORCE_UNMOUNT=$OCF_RESKEY_force_unmount + fi + +-DEVICE=$OCF_RESKEY_device ++DEVICE="$OCF_RESKEY_device" + FSTYPE=$OCF_RESKEY_fstype + if [ ! -z "$OCF_RESKEY_options" ]; then + options="-o $OCF_RESKEY_options" +@@ -899,10 +915,10 @@ if [ -z "$OCF_RESKEY_directory" ]; then + exit $OCF_ERR_CONFIGURED + fi + else +- MOUNTPOINT=$(echo $OCF_RESKEY_directory | sed 's/\/*$//') ++ MOUNTPOINT="$(echo "$OCF_RESKEY_directory" | sed 's/\/*$//')" + : ${MOUNTPOINT:=/} + if [ -e "$MOUNTPOINT" ] ; then +- CANONICALIZED_MOUNTPOINT=$(readlink -f "$MOUNTPOINT") ++ CANONICALIZED_MOUNTPOINT="$(readlink -f "$MOUNTPOINT")" + if [ $? -ne 0 ]; then + ocf_exit_reason "Could not canonicalize $MOUNTPOINT because readlink failed" + exit $OCF_ERR_GENERIC +@@ -947,7 +963,7 @@ CLUSTERSAFE=0 + is_option "ro" && + CLUSTERSAFE=2 + +-case $FSTYPE in ++case "$FSTYPE" in + nfs4|nfs|smbfs|cifs|none|gfs2|glusterfs|ceph|ocfs2|overlay|overlayfs|tmpfs|cvfs) + CLUSTERSAFE=1 # this is kind of safe too + ;; + +From eca9a96ad3356df3636bfa3187afe1b1954693b2 Mon Sep 17 00:00:00 2001 +From: Reid wahl +Date: Fri, 10 Jul 2020 16:38:04 -0700 +Subject: [PATCH 2/3] Filesystem: POSIX-compliant syntax for portability + +Updated to use POSIX `$()` instead of Bourne-shell backticks, and to +use `grep ... >/dev/null 2>&1` instead of `grep -q`. (Note: `grep -q` +only suppresses `stdout` anyway. `grep -q -s` would be required to +suppress both `stdout` and `stderr`.) +--- + heartbeat/Filesystem | 33 +++++++++++++++++---------------- + 1 file changed, 17 insertions(+), 16 deletions(-) + +diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem +index 9a52aa712..34ade20d7 100755 +--- a/heartbeat/Filesystem ++++ b/heartbeat/Filesystem +@@ -90,7 +90,7 @@ fi + : ${OCF_RESKEY_force_unmount=${OCF_RESKEY_force_unmount_default}} + + # Variables used by multiple methods +-HOSTOS=`uname` ++HOSTOS=$(uname) + TAB=' ' + + # The status file is going to an extra directory, by default +@@ -100,7 +100,7 @@ prefix=${OCF_RESKEY_statusfile_prefix} + suffix="${OCF_RESOURCE_INSTANCE}" + [ "$OCF_RESKEY_CRM_meta_clone" ] && + suffix="${suffix}_$OCF_RESKEY_CRM_meta_clone" +-suffix="${suffix}_`uname -n`" ++suffix="${suffix}_$(uname -n)" + STATUSFILE="${OCF_RESKEY_directory}/$prefix$suffix" + + ####################################################################### +@@ -329,7 +329,7 @@ determine_blockdevice() { + : ;; + *) + match_string="${TAB}${CANONICALIZED_MOUNTPOINT}${TAB}" +- DEVICE=`list_mounts | grep "$match_string" | cut -d"$TAB" -f1` ++ DEVICE=$(list_mounts | grep "$match_string" | cut -d"$TAB" -f1) + if [ -b "$DEVICE" ]; then + blockdevice=yes + fi +@@ -354,7 +354,7 @@ bind_kernel_check() { + exit(1); + }' + [ $? -ne 0 ] && +- ocf_log warn "kernel `uname -r` cannot handle read only bind mounts" ++ ocf_log warn "kernel $(uname -r) cannot handle read only bind mounts" + } + + bind_root_mount_check() { +@@ -369,7 +369,7 @@ bind_mount() { + if is_bind_mount && [ "$options" != "-o bind" ] + then + bind_kernel_check +- bind_opts=`echo "$options" | sed 's/bind/remount/'` ++ bind_opts=$(echo "$options" | sed 's/bind/remount/') + $MOUNT $bind_opts "$MOUNTPOINT" + else + true # make sure to return OK +@@ -469,7 +469,7 @@ trigger_udev_rules_if_needed() + refresh_flag="yes" + fi + else +- tmp="`echo $DEVICE|awk '{$1=""; print substr($0,2)}'`" ++ tmp="$(echo $DEVICE|awk '{$1=""; print substr($0,2)}')" + case "$DEVICE" in + -U*|--uuid*) + tmp="/dev/disk/by-uuid/$tmp" +@@ -498,7 +498,7 @@ Filesystem_start() + { + # Check if there are any mounts mounted under the mountpoint + match_string="${TAB}${CANONICALIZED_MOUNTPOINT}" +- if list_mounts | grep -q -E "$match_string/\w+" >/dev/null 2>&1; then ++ if list_mounts | grep -E "$match_string/\w+" >/dev/null 2>&1; then + ocf_log err "There is one or more mounts mounted under $MOUNTPOINT." + return $OCF_ERR_CONFIGURED + fi +@@ -602,14 +602,14 @@ signal_processes() { + return + fi + for pid in $pids; do +- ocf_log info "sending signal $sig to: `ps -f $pid | tail -1`" ++ ocf_log info "sending signal $sig to: $(ps -f $pid | tail -1)" + kill -s $sig $pid + done + } + try_umount() { + local SUB="$1" + $UMOUNT $umount_force "$SUB" +- list_mounts | grep -q "${TAB}${SUB}${TAB}" >/dev/null 2>&1 || { ++ list_mounts | grep "${TAB}${SUB}${TAB}" >/dev/null 2>&1 || { + ocf_log info "unmounted $SUB successfully" + return $OCF_SUCCESS + } +@@ -693,7 +693,7 @@ Filesystem_stop() + Filesystem_status() + { + match_string="${TAB}${CANONICALIZED_MOUNTPOINT}${TAB}" +- if list_mounts | grep -q "$match_string" >/dev/null 2>&1; then ++ if list_mounts | grep "$match_string" >/dev/null 2>&1; then + rc=$OCF_SUCCESS + msg="$MOUNTPOINT is mounted (running)" + else +@@ -728,7 +728,7 @@ Filesystem_monitor_10() + return $OCF_SUCCESS + fi + dd_opts="iflag=direct bs=4k count=1" +- err_output=`dd if="$DEVICE" $dd_opts 2>&1 >/dev/null` ++ err_output=$(dd if="$DEVICE" $dd_opts 2>&1 >/dev/null) + if [ $? -ne 0 ]; then + ocf_exit_reason "Failed to read device $DEVICE" + ocf_log err "dd said: $err_output" +@@ -751,7 +751,7 @@ Filesystem_monitor_20() + fi + status_dir=$(dirname "$STATUSFILE") + [ -d "$status_dir" ] || mkdir -p "$status_dir" +- err_output=`echo "${OCF_RESOURCE_INSTANCE}" | dd of="${STATUSFILE}" $dd_opts 2>&1` ++ err_output=$(echo "${OCF_RESOURCE_INSTANCE}" | dd of="${STATUSFILE}" $dd_opts 2>&1) + if [ $? -ne 0 ]; then + ocf_exit_reason "Failed to write status file ${STATUSFILE}" + ocf_log err "dd said: $err_output" +@@ -807,12 +807,13 @@ Filesystem_validate_all() + # 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 -q "^${FSTYPE}$" ++ cut -f2 /proc/filesystems | grep "^${FSTYPE}$" >/dev/null 2>&1 + if [ $? -ne 0 ]; then +- modpath=/lib/modules/`uname -r` ++ modpath=/lib/modules/$(uname -r) + moddep=$modpath/modules.dep + # Do we have $FSTYPE in modules.dep? +- cut -d' ' -f1 $moddep |grep -q "^$modpath.*$FSTYPE\.k\?o:$" ++ 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 +@@ -846,7 +847,7 @@ set_blockdevice_var() { + nfs4|nfs|smbfs|cifs|none|glusterfs|ceph|tmpfs|overlay|overlayfs|rozofs|zfs|cvfs|lustre) return;; + esac + +- if `is_option "loop"`; then ++ if $(is_option "loop"); then + return + fi + + +From 5517712f4bb6e90b23cde6310c03509c9061cb36 Mon Sep 17 00:00:00 2001 +From: Reid wahl +Date: Fri, 10 Jul 2020 16:44:17 -0700 +Subject: [PATCH 3/3] Filesystem: Convert leading space characters to tabs + +A few lines started with spaces instead of tabs. Tabs are the +convention in this file. +--- + heartbeat/Filesystem | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem +index 34ade20d7..501e5a0d0 100755 +--- a/heartbeat/Filesystem ++++ b/heartbeat/Filesystem +@@ -359,10 +359,10 @@ bind_kernel_check() { + + bind_root_mount_check() { + if [ "$(df -P "$1" | awk 'END{print $6}')" = "/" ]; then +- return 1 +- else +- return 0 +- fi ++ return 1 ++ else ++ return 0 ++ fi + } + + bind_mount() { +@@ -571,10 +571,10 @@ get_pids() + local procs + local mmap_procs + +- if is_bind_mount && ocf_is_true "$FORCE_UNMOUNT" && ! bind_root_mount_check "$DEVICE"; then +- ocf_log debug "Change force_umount from '$FORCE_UNMOUNT' to 'safe'" +- FORCE_UNMOUNT=safe +- fi ++ if is_bind_mount && ocf_is_true "$FORCE_UNMOUNT" && ! bind_root_mount_check "$DEVICE"; then ++ ocf_log debug "Change force_umount from '$FORCE_UNMOUNT' to 'safe'" ++ FORCE_UNMOUNT=safe ++ fi + + if ocf_is_true "$FORCE_UNMOUNT"; then + if [ "X${HOSTOS}" = "XOpenBSD" ];then diff --git a/SOURCES/bz1861001-sybaseASE-add-logfile-parameter.patch b/SOURCES/bz1861001-sybaseASE-add-logfile-parameter.patch new file mode 100644 index 0000000..b294584 --- /dev/null +++ b/SOURCES/bz1861001-sybaseASE-add-logfile-parameter.patch @@ -0,0 +1,53 @@ +From d62d8776df8aaa1da32e8452b3816505d1ea1f7f Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 28 Oct 2020 15:06:47 +0100 +Subject: [PATCH] sybaseASE: add logfile parameter + +--- + heartbeat/sybaseASE.in | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/heartbeat/sybaseASE.in b/heartbeat/sybaseASE.in +index 7ff30bd31..fef76474e 100755 +--- a/heartbeat/sybaseASE.in ++++ b/heartbeat/sybaseASE.in +@@ -115,6 +115,13 @@ fi + interfaces_file_default="${OCF_RESKEY_sybase_home}/interfaces" + : ${OCF_RESKEY_interfaces_file=${interfaces_file_default}} + ++if [ $__OCF_ACTION != "meta-data" ]; then ++ logfile_default="$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase/install/$OCF_RESKEY_server_name.log" ++else ++ logfile_default="detect" ++fi ++: ${OCF_RESKEY_logfile=${logfile_default}} ++ + export LD_POINTER_GUARD=0 + + ####################################################################################### +@@ -122,7 +129,7 @@ export LD_POINTER_GUARD=0 + ####################################################################################### + declare login_string="" + declare RUNSERVER_SCRIPT=$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase/install/RUN_$OCF_RESKEY_server_name +-declare CONSOLE_LOG=$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase/install/$OCF_RESKEY_server_name.log ++declare CONSOLE_LOG="$OCF_RESKEY_logfile" + + ################################################################################################## + # This function will be called by Pacemaker to get the meta data of resource agent "sybaseASE". # +@@ -223,6 +230,16 @@ meta_data() + + + ++ ++ ++ Logfile ++ ++ ++ Logfile ++ ++ ++ ++ + + + diff --git a/SOURCES/bz1872999-aws-vpc-move-ip-add-region-parameter.patch b/SOURCES/bz1872999-aws-vpc-move-ip-add-region-parameter.patch new file mode 100644 index 0000000..4fef3d5 --- /dev/null +++ b/SOURCES/bz1872999-aws-vpc-move-ip-add-region-parameter.patch @@ -0,0 +1,81 @@ +--- ClusterLabs-resource-agents-e711383f/heartbeat/aws-vpc-move-ip 2020-09-23 11:57:38.855067216 +0200 ++++ aws-vpc-move-ip.tmp 2020-09-23 11:57:17.993045991 +0200 +@@ -37,13 +37,17 @@ + # Defaults + OCF_RESKEY_awscli_default="/usr/bin/aws" + OCF_RESKEY_profile_default="default" ++OCF_RESKEY_region_default="" + OCF_RESKEY_routing_table_role_default="" + OCF_RESKEY_monapi_default="false" + + : ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} + : ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} ++: ${OCF_RESKEY_region=${OCF_RESKEY_region_default}} + : ${OCF_RESKEY_routing_table_role=${OCF_RESKEY_routing_table_role_default}} + : ${OCF_RESKEY_monapi=${OCF_RESKEY_monapi_default}} ++ ++[ -n "$OCF_RESKEY_region" ] && region_opt="--region $OCF_RESKEY_region" + ####################################################################### + + +@@ -87,6 +91,14 @@ + + + ++ ++ ++Valid AWS region name (e.g., 'us-west-2') ++ ++region name ++ ++ ++ + + + VPC private IP address +@@ -151,7 +163,7 @@ + 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 --output=text)" ++ output="$($OCF_RESKEY_awscli sts assume-role --role-arn $role --role-session-name AWSCLI-RouteTableUpdate --profile $OCF_RESKEY_profile $region_opt --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}')" +@@ -198,11 +210,11 @@ + 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 --output text ec2 describe-route-tables --route-table-ids $rtb --query RouteTables[*].Routes[?DestinationCidrBlock=='$OCF_RESKEY_ip/32'].InstanceId" ++ 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'].InstanceId" + ocf_log debug "executing command: $cmd" + ROUTE_TO_INSTANCE="$($cmd)" + else +- cmd="$OCF_RESKEY_awscli --output text ec2 describe-route-tables --route-table-ids $rtb --query RouteTables[*].Routes[?DestinationCidrBlock=='$OCF_RESKEY_ip/32'].InstanceId" ++ cmd="$OCF_RESKEY_awscli $region_opt --output text ec2 describe-route-tables --route-table-ids $rtb --query RouteTables[*].Routes[?DestinationCidrBlock=='$OCF_RESKEY_ip/32'].InstanceId" + ROUTE_TO_INSTANCE="$(execute_cmd_as_role "$cmd" $OCF_RESKEY_routing_table_role)" + fi + ocf_log debug "Overlay IP is currently routed to ${ROUTE_TO_INSTANCE}" +@@ -283,11 +295,11 @@ + + 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 --output text ec2 replace-route --route-table-id $rtb --destination-cidr-block ${OCF_RESKEY_ip}/32 --network-interface-id $EC2_NETWORK_INTERFACE_ID" ++ 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" + ocf_log debug "executing command: $cmd" + $cmd + else +- cmd="$OCF_RESKEY_awscli --output text ec2 replace-route --route-table-id $rtb --destination-cidr-block ${OCF_RESKEY_ip}/32 --network-interface-id $EC2_NETWORK_INTERFACE_ID" ++ cmd="$OCF_RESKEY_awscli $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" + update_response="$(execute_cmd_as_role "$cmd" $OCF_RESKEY_routing_table_role)" + fi + rc=$? +@@ -397,7 +409,7 @@ + ec2ip_monitor;; + validate-all) + exit $?;; +- *) ++ *) + echo $USAGE + exit $OCF_ERR_UNIMPLEMENTED + ;; diff --git a/SOURCES/bz1881114-galera-recover-joining-non-existing-cluster.patch b/SOURCES/bz1881114-galera-recover-joining-non-existing-cluster.patch new file mode 100644 index 0000000..17b823a --- /dev/null +++ b/SOURCES/bz1881114-galera-recover-joining-non-existing-cluster.patch @@ -0,0 +1,51 @@ +From 028bd6aab181104fe68166c8ec9c0485e12f9376 Mon Sep 17 00:00:00 2001 +From: Damien Ciabrini +Date: Fri, 18 Sep 2020 18:34:22 +0200 +Subject: [PATCH] galera: recover from joining a non existing cluster + +galera being a M/S resource, the resource agent decides +when and how to promote a resource based on the current +state of the galera cluster. If there's no cluster, +a resource is promoted as the bootstrap node. Otherwise +it is promoted as a joiner node. + +There can be some time between the moment when a node is +promoted and when the promote operation effectively +takes place. So if a node is promoted for joining a cluster, +all the running galera nodes are stopped before the promote +operation start, the joining node won't be able to join the +cluster, and it can't bootstrap a new one either because it +doesn't have the most recent copy of the DB. + +In that case, do not make the promotion fail, and force +a demotion instead. This ensures that a normal bootstrap +election will take place eventually, without blocking +the joining node due to a failed promotion. +--- + heartbeat/galera | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/heartbeat/galera b/heartbeat/galera +index 74f11d8c5..d2f4faa86 100755 +--- a/heartbeat/galera ++++ b/heartbeat/galera +@@ -727,9 +727,16 @@ galera_promote() + ocf_log info "Node <${NODENAME}> is bootstrapping the cluster" + extra_opts="--wsrep-cluster-address=gcomm://" + else +- ocf_exit_reason "Failure, Attempted to promote Master instance of $OCF_RESOURCE_INSTANCE before bootstrap node has been detected." +- clear_last_commit +- return $OCF_ERR_GENERIC ++ # We are being promoted without having the bootstrap ++ # attribute in the CIB, which means we are supposed to ++ # join a cluster; however if we end up here, there is no ++ # Master remaining right now, which means there is no ++ # cluster to join anymore. So force a demotion, and and ++ # let the RA decide later which node should be the next ++ # bootstrap node. ++ ocf_log warn "There is no running cluster to join, demoting ourself" ++ clear_master_score ++ return $OCF_SUCCESS + fi + fi + diff --git a/SOURCES/bz1886262-podman-recover-from-killed-conmon.patch b/SOURCES/bz1886262-podman-recover-from-killed-conmon.patch new file mode 100644 index 0000000..3fa5934 --- /dev/null +++ b/SOURCES/bz1886262-podman-recover-from-killed-conmon.patch @@ -0,0 +1,63 @@ +From 3aa0dda4e0c2a3b801d65aeacc4fdfd713a604f2 Mon Sep 17 00:00:00 2001 +From: Damien Ciabrini +Date: Tue, 27 Oct 2020 18:01:36 +0100 +Subject: [PATCH] podman: recover from killed conmon side process + +When podman containers are created by the resource-agent, the podman +runtime spawns a side process (conmon) to monitor the container and +record the exit status. + +If the conmon process dies unexpectedly (e.g. kill -9), the podman +container can still be stopped, even if the cli returns a generic +error. + +Try to distinguish this specific failure condition and make the stop +operation resilient; when it happens, just log a warning and finish +the usual stop actions. +--- + heartbeat/podman | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/heartbeat/podman b/heartbeat/podman +index 81b00ee6f..9f8c2a091 100755 +--- a/heartbeat/podman ++++ b/heartbeat/podman +@@ -419,6 +419,7 @@ podman_start() + podman_stop() + { + local timeout=60 ++ local rc + podman_simple_status + if [ $? -eq $OCF_NOT_RUNNING ]; then + remove_container +@@ -434,16 +435,27 @@ podman_stop() + + if ocf_is_true "$OCF_RESKEY_force_kill"; then + ocf_run podman kill $CONTAINER ++ rc=$? + else + ocf_log debug "waiting $timeout second[s] before killing container" + ocf_run podman stop -t=$timeout $CONTAINER ++ rc=$? + # on stop, systemd will automatically delete any transient + # drop-in conf that has been created earlier + fi + +- if [ $? -ne 0 ]; then +- ocf_exit_reason "Failed to stop container, ${CONTAINER}, based on image, ${OCF_RESKEY_image}." +- return $OCF_ERR_GENERIC ++ if [ $rc -ne 0 ]; then ++ # If the stop failed, it could be because the controlling conmon ++ # process died unexpectedly. If so, a generic error code is returned ++ # but the associated container exit code is -1. If that's the case, ++ # assume there's no failure and continue with the rm as usual. ++ if [ $rc -eq 125 ] && \ ++ podman inspect --format '{{.State.Status}}:{{.State.ExitCode}}' $CONTAINER | grep -wq "stopped:-1"; then ++ ocf_log warn "Container ${CONTAINER} had an unexpected stop outcome. Trying to remove it anyway." ++ else ++ ocf_exit_reason "Failed to stop container, ${CONTAINER}, based on image, ${OCF_RESKEY_image}." ++ return $OCF_ERR_GENERIC ++ fi + fi + + remove_container diff --git a/SOURCES/bz1890068-gcp-pd-move-fix-partially-matched-disk_name.patch b/SOURCES/bz1890068-gcp-pd-move-fix-partially-matched-disk_name.patch new file mode 100644 index 0000000..83aef93 --- /dev/null +++ b/SOURCES/bz1890068-gcp-pd-move-fix-partially-matched-disk_name.patch @@ -0,0 +1,58 @@ +From 2927279ba1677e9dda202121176a8245a7ef76ca Mon Sep 17 00:00:00 2001 +From: tositaka77 <45960626+tositaka77@users.noreply.github.com> +Date: Wed, 14 Oct 2020 22:22:56 +0900 +Subject: [PATCH] fixes and improvements + +- Fixed "regional" PD functionality in attach_disk() +- Improve to exact match disk_name with disks.source in detach_disk() +--- + heartbeat/gcp-pd-move.in | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/heartbeat/gcp-pd-move.in b/heartbeat/gcp-pd-move.in +index f82bd25e5..e99cc71f8 100644 +--- a/heartbeat/gcp-pd-move.in ++++ b/heartbeat/gcp-pd-move.in +@@ -49,6 +49,7 @@ else: + CONN = None + PROJECT = None + ZONE = None ++REGION = None + LIST_DISK_ATTACHED_INSTANCES = None + INSTANCE_NAME = None + +@@ -148,6 +149,7 @@ def populate_vars(): + global INSTANCE_NAME + global PROJECT + global ZONE ++ global REGION + global LIST_DISK_ATTACHED_INSTANCES + + # Populate global vars +@@ -175,6 +177,7 @@ def populate_vars(): + PROJECT = get_metadata('project/project-id') + if PARAMETERS['disk_scope'] in ['detect', 'regional']: + ZONE = get_metadata('instance/zone').split('/')[-1] ++ REGION = ZONE[:-2] + else: + ZONE = PARAMETERS['disk_scope'] + LIST_DISK_ATTACHED_INSTANCES = get_disk_attached_instances( +@@ -255,7 +258,7 @@ def detach_disk(instance, disk_name): + + device_name = None + for disk in response['disks']: +- if disk_name in disk['source']: ++ if disk_name == re.sub('.*disks/',"",disk['source']): + device_name = disk['deviceName'] + break + +@@ -273,6 +276,9 @@ def detach_disk(instance, disk_name): + + def attach_disk(instance, disk_name): + location = 'zones/%s' % ZONE ++ if PARAMETERS['disk_scope'] == 'regional': ++ location = 'regions/%s' % REGION ++ + prefix = 'https://www.googleapis.com/compute/v1' + body = { + 'source': '%(prefix)s/projects/%(project)s/%(location)s/disks/%(disk)s' % { diff --git a/SOURCES/bz1891835-galera-set-bootstrap-attribute-before-promote.patch b/SOURCES/bz1891835-galera-set-bootstrap-attribute-before-promote.patch new file mode 100644 index 0000000..7dfdc48 --- /dev/null +++ b/SOURCES/bz1891835-galera-set-bootstrap-attribute-before-promote.patch @@ -0,0 +1,36 @@ +From ac213f158ff851422d78ae8f56b022e8e30751bc Mon Sep 17 00:00:00 2001 +From: Damien Ciabrini +Date: Mon, 26 Oct 2020 14:54:05 +0100 +Subject: [PATCH] galera: set bootstrap attribute before promote + +When the master detection takes place, the node chosen for +becoming the master is given two attributes in the CIB: +a master score and a bootstrap flag. The master score makes +pacemaker schedule a promote operation, and the bootstrap flag +drives how the galera server is started. + +The order in which we set the attributes is racy; it may happen +that a promote operation is started before the current master +detection function has set the bootstrap flag, in which case +the promotion will fail. + +Reverse the order in which we set the attributes on a bootstrap +node to close the race. +--- + heartbeat/galera | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/galera b/heartbeat/galera +index d2f4faa86..b4d7e187d 100755 +--- a/heartbeat/galera ++++ b/heartbeat/galera +@@ -587,8 +587,8 @@ detect_first_master() + fi + + ocf_log info "Promoting $best_node to be our bootstrap node" +- set_master_score $best_node + set_bootstrap_node $best_node ++ set_master_score $best_node + } + + detect_safe_to_bootstrap() diff --git a/SOURCES/bz1891855-galera-recover-2-node-cluster.patch b/SOURCES/bz1891855-galera-recover-2-node-cluster.patch new file mode 100644 index 0000000..22ab885 --- /dev/null +++ b/SOURCES/bz1891855-galera-recover-2-node-cluster.patch @@ -0,0 +1,80 @@ +--- a/heartbeat/galera 2020-10-28 16:28:48.125700714 +0100 ++++ b/heartbeat/galera 2020-10-28 16:31:14.932820752 +0100 +@@ -81,6 +81,11 @@ + . /etc/default/clustercheck + fi + ++# Parameter defaults ++ ++OCF_RESKEY_two_node_mode_default="false" ++: ${OCF_RESKEY_two_node_mode=${OCF_RESKEY_two_node_mode_default}} ++ + ####################################################################### + + usage() { +@@ -249,6 +254,16 @@ + + + ++ ++ ++If running in a 2-node pacemaker cluster, rely on pacemaker quorum ++to allow automatic recovery even when the other node is unreachable. ++Use it with caution! (and fencing) ++ ++Special recovery when running on a 2-node cluster ++ ++ ++ + + + +@@ -400,6 +415,27 @@ + return 0 + } + ++is_two_node_mode_active() ++{ ++ # crm_node or corosync-quorumtool cannot access various corosync ++ # flags when running inside a bundle, so only count the cluster ++ # members ++ ocf_is_true "$OCF_RESKEY_two_node_mode" && ${HA_SBIN_DIR}/crm_mon -1X | xmllint --xpath "count(//nodes/node[@type='member'])" - | grep -q -w 2 ++} ++ ++is_last_node_in_quorate_partition() ++{ ++ # when a network split occurs in a 2-node cluster, pacemaker ++ # fences the other node and try to retain quorum. So until ++ # the fencing is resolved (and the status of the peer node ++ # is clean), we shouldn't consider ourself quorate. ++ local partition_members=$(${HA_SBIN_DIR}/crm_node -p | wc -w) ++ local quorate=$(${HA_SBIN_DIR}/crm_node -q) ++ local clean_members=$(${HA_SBIN_DIR}/crm_mon -1X | xmllint --xpath 'count(//nodes/node[@type="member" and @unclean="false"])' -) ++ ++ [ "$partition_members" = 1 ] && [ "$quorate" = 1 ] && [ "$clean_members" = 2 ] ++} ++ + master_exists() + { + if [ "$__OCF_ACTION" = "demote" ]; then +@@ -518,8 +554,20 @@ + done + + for node in $nodes_recovered $nodes; do ++ # On clean shutdown, galera sets the last stopped node as 'safe to bootstrap', ++ # so use this hint when we can + safe_to_bootstrap=$(get_safe_to_bootstrap $node) + ++ # Special case for 2-node clusters: during a network split, rely on ++ # pacemaker's quorum to check whether we can restart galera ++ if [ "$safe_to_bootstrap" != "1" ] && [ "$node" = "$NODENAME" ] && is_two_node_mode_active; then ++ is_last_node_in_quorate_partition ++ if [ $? -eq 0 ]; then ++ ocf_log warn "Survived a split in a 2-node cluster, considering ourselves safe to bootstrap" ++ safe_to_bootstrap=1 ++ fi ++ fi ++ + if [ "$safe_to_bootstrap" = "1" ]; then + # Galera marked the node as safe to boostrap during shutdown. Let's just + # pick it as our bootstrap node. diff --git a/SOURCES/bz1895811-aws-vpc-move-ip-dont-warn-for-expected-scenarios.patch b/SOURCES/bz1895811-aws-vpc-move-ip-dont-warn-for-expected-scenarios.patch new file mode 100644 index 0000000..385e034 --- /dev/null +++ b/SOURCES/bz1895811-aws-vpc-move-ip-dont-warn-for-expected-scenarios.patch @@ -0,0 +1,84 @@ +From 8d459216c9718269303b9caf227a971d73ec4df9 Mon Sep 17 00:00:00 2001 +From: Reid Wahl +Date: Thu, 27 Aug 2020 01:34:01 -0700 +Subject: [PATCH] aws-vpc-move-ip: Don't warn for expected scenarios + +Make log levels more appropriate to the situation. Before this patch, a +normal start looked like this: + +Operation start for aws-vip (ocf:heartbeat:aws-vpc-move-ip) returned: 'ok' (0) + > stderr: Nov 09 02:38:20 INFO: EC2: Moving IP address 10.0.1.65 to this host by adjusting routing table rtb-01b4ea1ae0ec0a4d9 + > stderr: Nov 09 02:38:20 INFO: monitor: check routing table (API call) - rtb-01b4ea1ae0ec0a4d9 + > stderr: Nov 09 02:38:22 WARNING: IP 10.0.1.65 not assigned to running interface + > stderr: Nov 09 02:38:22 INFO: EC2: Adjusting routing table and locally configuring IP address + > stderr: RTNETLINK answers: Cannot assign requested address + > stderr: Nov 09 02:38:24 WARNING: command failed, rc 2 + > stderr: Nov 09 02:38:24 INFO: monitor: check routing table (API call) - rtb-01b4ea1ae0ec0a4d9 + +Now it looks like this: + +Operation start for aws-vip (ocf:heartbeat:aws-vpc-move-ip) returned: 'ok' (0) + > stderr: Nov 09 02:40:43 INFO: EC2: Moving IP address 10.0.1.65 to this host by adjusting routing table rtb-01b4ea1ae0ec0a4d9 + > stderr: Nov 09 02:40:43 INFO: monitor: check routing table (API call) - rtb-01b4ea1ae0ec0a4d9 + > stderr: Nov 09 02:40:44 INFO: IP 10.0.1.65 not assigned to running interface + > stderr: Nov 09 02:40:44 INFO: EC2: Adjusting routing table and locally configuring IP address + > stderr: Nov 09 02:40:46 INFO: monitor: check routing table (API call) - rtb-01b4ea1ae0ec0a4d9 + +Under normal circumstances, the call to `ec2ip_drop()` within +`ec2ip_get_and_configure` should not be required at all. The drop +function deletes the address before the get_and_configure function +immediately re-adds the address. This call could probably be removed +altogether. Instead, I left the call and silenced its output just in +case of unexpected edge cases. + +Resolves: RHBZ#1895811 + +Signed-off-by: Reid Wahl +--- + heartbeat/aws-vpc-move-ip | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip +index a5b28ad92..72a89ecb1 100755 +--- a/heartbeat/aws-vpc-move-ip ++++ b/heartbeat/aws-vpc-move-ip +@@ -270,7 +270,13 @@ ec2ip_monitor() { + ocf_log debug "executing command: $cmd" + RESULT=$($cmd | grep "$OCF_RESKEY_ip") + if [ -z "$RESULT" ]; then +- ocf_log warn "IP $OCF_RESKEY_ip not assigned to running interface" ++ if [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe; then ++ level="error" ++ else ++ level="info" ++ fi ++ ++ ocf_log "$level" "IP $OCF_RESKEY_ip not assigned to running interface" + return $OCF_NOT_RUNNING + fi + +@@ -282,11 +288,22 @@ ec2ip_monitor() { + ec2ip_drop() { + cmd="ip addr delete ${OCF_RESKEY_ip}/32 dev $OCF_RESKEY_interface" + ocf_log debug "executing command: $cmd" +- $cmd ++ output=$($cmd 2>&1) + rc=$? ++ + if [ "$rc" -gt 0 ]; then +- ocf_log warn "command failed, rc $rc" ++ if [ "$__OCF_ACTION" = "start" ]; then ++ # expected to fail during start ++ level="debug" ++ else ++ level="warn" ++ fi ++ ++ ocf_log "$level" "command failed, rc $rc" ++ ocf_log "$level" "output/error: $output" + return $OCF_ERR_GENERIC ++ else ++ ocf_log debug "output/error: $output" + fi + + # delete remaining route-entries if any diff --git a/SOURCES/bz1905587-aws-add-imdsv2-support.patch b/SOURCES/bz1897570-aws-add-imdsv2-support.patch similarity index 100% rename from SOURCES/bz1905587-aws-add-imdsv2-support.patch rename to SOURCES/bz1897570-aws-add-imdsv2-support.patch diff --git a/SOURCES/bz1898690-crypt-make-key_file-crypt_type_not-unique.patch b/SOURCES/bz1898690-crypt-make-key_file-crypt_type_not-unique.patch new file mode 100644 index 0000000..8cecc16 --- /dev/null +++ b/SOURCES/bz1898690-crypt-make-key_file-crypt_type_not-unique.patch @@ -0,0 +1,31 @@ +From 16236f76d086187f6ae6202153519c1eb2fe4f87 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 24 Nov 2020 10:49:14 +0100 +Subject: [PATCH] crypt: make key_file and crypt_type parameters not unique + +--- + heartbeat/crypt | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/heartbeat/crypt b/heartbeat/crypt +index 0e49b6c2d..7d0a5607c 100755 +--- a/heartbeat/crypt ++++ b/heartbeat/crypt +@@ -86,7 +86,7 @@ The resulting block device path is /dev/mapper/name. + + + +- ++ + + Key file path containing the encryption passphrase + (aka key; see cryptsetup(8)). For LUKS, the passphrase as of the key_file +@@ -96,7 +96,7 @@ parameter is used to decrypt a randomly selected key when the device was created + + + +- ++ + + Encryption (device) type (e.g. "luks" or "luks2"). + diff --git a/SOURCES/bz1899551-NovaEvacuate-fix-delay_evacuate-unset.patch b/SOURCES/bz1899551-NovaEvacuate-fix-delay_evacuate-unset.patch new file mode 100644 index 0000000..7af35cc --- /dev/null +++ b/SOURCES/bz1899551-NovaEvacuate-fix-delay_evacuate-unset.patch @@ -0,0 +1,33 @@ +From 11ac2db8f55aa3e6858d6c1b2ab29ee36b612f03 Mon Sep 17 00:00:00 2001 +From: Michele Baldessari +Date: Tue, 17 Nov 2020 15:16:29 +0100 +Subject: [PATCH] Fix delay_evacuate being unset + +In Ie2fe784202d754eda38092479b1ab3ff4d02136a we added an additional +parameter to allow for setting a delay on the evacuation. +While it was tested with a specific delay, the case with a delay +being unset was missed. +Since OCF does not set the defaults from the metadata specification +for a parameter, we need to manually set it ourselves. + +This fixes the following error: +Nov 17 13:00:21 database-1.foo.local pacemaker-execd [185805] (log_op_output) notice: nova-evacuate_monitor_10000[1038417] error output [ /usr/lib/ocf/resource.d/openstack/NovaEvacuate: line 228: [: !=: unary operator expected ] + +Change-Id: I0b7aacd67b77bc44c67fe7da4c494807abbbb4f3 +--- + +diff --git a/heartbeat/NovaEvacuate b/heartbeat/NovaEvacuate +index 596f520..8aa778c 100644 +--- a/heartbeat/NovaEvacuate ++++ b/heartbeat/NovaEvacuate +@@ -359,6 +359,10 @@ + fence_options="${fence_options} -e ${OCF_RESKEY_endpoint_type}" + fi + ++ if [ -z "${OCF_RESKEY_evacuate_delay}" ]; then ++ OCF_RESKEY_evacuate_delay=0 ++ fi ++ + if [ $rc != $OCF_SUCCESS ]; then + exit $rc + fi diff --git a/SOURCES/bz1900015-podman-recover-from-storage-out-of-sync.patch b/SOURCES/bz1900015-podman-recover-from-storage-out-of-sync.patch new file mode 100644 index 0000000..e022612 --- /dev/null +++ b/SOURCES/bz1900015-podman-recover-from-storage-out-of-sync.patch @@ -0,0 +1,64 @@ +From 52d09b57a499ed7b3757e0e2954c2783198d5b23 Mon Sep 17 00:00:00 2001 +From: Damien Ciabrini +Date: Mon, 9 Nov 2020 20:42:19 +0100 +Subject: [PATCH] podman: recover from podman's storage being out of sync + +If a system crash while podman is stopping a container (e.g. a fencing action +took place), it might happen that on reboot, podman is not able to recreate +a container as requested by the resource agent. + +When such a start operation fails, it might be because the internal storage +layer still references an old container with the same name, even though podman +itself thinks there is no such container. If so, purge the storage layer to try +to clean the corruption and try recreating the container. +--- + heartbeat/podman | 29 +++++++++++++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/heartbeat/podman b/heartbeat/podman +index 81b00ee6f..d4d608ca3 100755 +--- a/heartbeat/podman ++++ b/heartbeat/podman +@@ -345,6 +345,32 @@ create_transient_drop_in_dependency() + } + + ++run_new_container() ++{ ++ local opts=$1 ++ local image=$2 ++ local cmd=$3 ++ local rc ++ ++ ocf_log info "running container $CONTAINER for the first time" ++ ocf_run podman run $opts $image $cmd ++ rc=$? ++ if [ $rc -eq 125 ]; then ++ # If an internal podman error occurred, it might be because ++ # the internal storage layer still references an old container ++ # with the same name, even though podman itself thinks there ++ # is no such container. If so, purge the storage layer to try ++ # to clean the corruption and try again. ++ ocf_log warn "Internal podman error while creating new container $CONTAINER. Retrying." ++ ocf_run podman rm --storage $CONTAINER ++ ocf_run podman run $opts $image $cmd ++ rc=$? ++ fi ++ ++ return $rc ++} ++ ++ + podman_start() + { + local cid +@@ -378,8 +404,7 @@ podman_start() + # 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 "running container $CONTAINER for the first time" +- ocf_run podman run $run_opts $OCF_RESKEY_image $OCF_RESKEY_run_cmd ++ run_new_container "$run_opts" $OCF_RESKEY_image "$OCF_RESKEY_run_cmd" + fi + rc=$? + diff --git a/SOURCES/bz1901357-crypt-1-support-symlink-devices.patch b/SOURCES/bz1901357-crypt-1-support-symlink-devices.patch new file mode 100644 index 0000000..6b4f385 --- /dev/null +++ b/SOURCES/bz1901357-crypt-1-support-symlink-devices.patch @@ -0,0 +1,23 @@ +From 4ded33d34505af19ddf19bfa125b5e6c243ebd94 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 26 Nov 2020 12:56:03 +0100 +Subject: [PATCH] crypt: allow encrypted_dev to be symlink to support using + devices in /dev/disk/... or UUID + +--- + heartbeat/crypt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/crypt b/heartbeat/crypt +index 7d0a5607c..3ca28b92d 100755 +--- a/heartbeat/crypt ++++ b/heartbeat/crypt +@@ -177,7 +177,7 @@ crypt_validate_all() { + esac + esac + fi +- if [ ! -b "$encrypted_dev" ]; then ++ if [ ! -b "$encrypted_dev" ] && [ ! -L "$encrypted_dev" ]; then + ocf_exit_reason "Encrypted device $encrypted_dev not accessible" + return $OCF_ERR_ARGS + fi diff --git a/SOURCES/bz1901357-crypt-2-dont-sanity-check-during-probe.patch b/SOURCES/bz1901357-crypt-2-dont-sanity-check-during-probe.patch new file mode 100644 index 0000000..4e259d4 --- /dev/null +++ b/SOURCES/bz1901357-crypt-2-dont-sanity-check-during-probe.patch @@ -0,0 +1,44 @@ +From 6a45c28cd074e14a7bc2e2531b15595b9985965c Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 1 Dec 2020 10:11:52 +0100 +Subject: [PATCH] crypt: avoid failing for LVM exclusive by not running full + sanity check during probes + +--- + heartbeat/crypt | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/heartbeat/crypt b/heartbeat/crypt +index 3ca28b92d..05bded7c5 100755 +--- a/heartbeat/crypt ++++ b/heartbeat/crypt +@@ -177,6 +177,13 @@ crypt_validate_all() { + 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 +@@ -294,11 +301,13 @@ crypt_stop() { + crypt_monitor() { + cryptsetup status $crypt_dev $disable_locks >/dev/null 2>&1 + if [ $? -eq 0 ]; then +- [ -L $crypt_dev_path ] && return $OCF_SUCCESS ++ if [ -b "$encrypted_dev" ] || [ -L $crypt_dev_path ]; then ++ return $OCF_SUCCESS ++ fi + return $OCF_ERR_GENERIC + fi + +- [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe && ocf_exit_reason "Crypt resource not running" ++ [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe && ocf_exit_reason "Crypt resource not running" + return $OCF_NOT_RUNNING + } + diff --git a/SOURCES/bz1902208-LVM-activate-stop-before-storage-service.patch b/SOURCES/bz1902208-LVM-activate-stop-before-storage-service.patch new file mode 100644 index 0000000..1486b29 --- /dev/null +++ b/SOURCES/bz1902208-LVM-activate-stop-before-storage-service.patch @@ -0,0 +1,60 @@ +From 79fb4b2d3d862f4e83b1df72107b6322b420ea34 Mon Sep 17 00:00:00 2001 +From: Reid Wahl +Date: Sat, 28 Nov 2020 18:10:03 -0800 +Subject: [PATCH] LVM-activate: Stop before blk-availability.service + +If storage services (e.g., iscsi-shutdown.service) stop before an +LVM-activate resource stops, the managed VG may become unavailable. Then +the LVM-activate resource may fail to deactivate the volume group and +thus fail its stop operation. + +This commit adds a systemd drop-in "After=blk-availability.service" +directive for resource-agents-deps.target during the LVM-activate start +op. blk-availability includes "After=" directives for other storage +services and thus serves as a convenient wrapper. + +blk-availability is not enabled by default, and a "Wants=" drop-in +that's created after Pacemaker starts would not be able to start +blk-availability automatically. So here we also start blk-availability +during LVM_start(). + +Resolves RHBZ#1902208 + +Signed-off-by: Reid Wahl +--- + heartbeat/LVM-activate | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/heartbeat/LVM-activate b/heartbeat/LVM-activate +index 94f9e5813..b8abd7579 100755 +--- a/heartbeat/LVM-activate ++++ b/heartbeat/LVM-activate +@@ -830,6 +830,28 @@ lvm_start() { + local rc + local vol + ++ if systemd_is_running ; then ++ # Create drop-in to deactivate VG before stopping ++ # storage services during shutdown/reboot. ++ after=$(systemctl show resource-agents-deps.target.d \ ++ --property=After | cut -d'=' -f2) ++ ++ case "$after" in ++ *" blk-availability.service "*) ++ ;; ++ *) ++ systemd_drop_in "99-LVM-activate" "After" \ ++ "blk-availability.service" ++ ;; ++ esac ++ ++ # If blk-availability isn't started, the "After=" ++ # directive has no effect. ++ if ! systemctl is-active blk-availability.service ; then ++ systemctl start blk-availability.service ++ fi ++ fi ++ + if lvm_status ; then + ocf_log info "${vol}: is already active." + return $OCF_SUCCESS diff --git a/SOURCES/bz1903677-ocf-shellfuncs-fix-traceback-redirection-bash5.patch b/SOURCES/bz1903677-ocf-shellfuncs-fix-traceback-redirection-bash5.patch new file mode 100644 index 0000000..8472065 --- /dev/null +++ b/SOURCES/bz1903677-ocf-shellfuncs-fix-traceback-redirection-bash5.patch @@ -0,0 +1,45 @@ +From 908431d416076e3ceb70cc95871957d15265a949 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 2 Dec 2020 16:48:32 +0100 +Subject: [PATCH] ocf-shellfuncs: make ocf_is_bash4() detect Bash v4 or greater + (which it was supposed to according to the comments) + +--- + heartbeat/ocf-shellfuncs.in | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in +index b8d47e3d5..ac75dfc87 100644 +--- a/heartbeat/ocf-shellfuncs.in ++++ b/heartbeat/ocf-shellfuncs.in +@@ -907,13 +907,18 @@ ocf_unique_rundir() + # NB: FD 9 may be used for tracing with bash >= v4 in case + # OCF_TRACE_FILE is set to a path. + # +-ocf_is_bash4() { ++ocf_bash_has_xtracefd() { + echo "$SHELL" | grep bash > /dev/null && +- [ ${BASH_VERSINFO[0]} = "4" ] ++ [ ${BASH_VERSINFO[0]} -ge 4 ] ++} ++# for backwards compatibility ++ocf_is_bash4() { ++ ocf_bash_has_xtracefd ++ return $? + } + ocf_trace_redirect_to_file() { + local dest=$1 +- if ocf_is_bash4; then ++ if ocf_bash_has_xtracefd; then + exec 9>$dest + BASH_XTRACEFD=9 + else +@@ -922,7 +927,7 @@ ocf_trace_redirect_to_file() { + } + ocf_trace_redirect_to_fd() { + local fd=$1 +- if ocf_is_bash4; then ++ if ocf_bash_has_xtracefd; then + BASH_XTRACEFD=$fd + else + exec 2>&$fd diff --git a/SOURCES/bz1913932-1-gcp-vpc-move-add-project-parameter.patch b/SOURCES/bz1913932-1-gcp-vpc-move-add-project-parameter.patch new file mode 100644 index 0000000..16cfb10 --- /dev/null +++ b/SOURCES/bz1913932-1-gcp-vpc-move-add-project-parameter.patch @@ -0,0 +1,86 @@ +From 560683500b3f9d5d8e183a569daea27422ae5268 Mon Sep 17 00:00:00 2001 +From: Reid Wahl +Date: Thu, 7 Jan 2021 12:25:04 -0800 +Subject: [PATCH] gcp-vpc-move-route, gcp-vpc-move-vip: Parameterize project ID + +Resolves: RHBZ#1913932 +Resolves: RHBZ#1913936 + +Signed-off-by: Reid Wahl +--- + heartbeat/gcp-vpc-move-route.in | 13 ++++++++++++- + heartbeat/gcp-vpc-move-vip.in | 16 ++++++++++++++-- + 2 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/heartbeat/gcp-vpc-move-route.in b/heartbeat/gcp-vpc-move-route.in +index d8e8ea8dd..179eba15a 100644 +--- a/heartbeat/gcp-vpc-move-route.in ++++ b/heartbeat/gcp-vpc-move-route.in +@@ -106,6 +106,16 @@ Name of the VPC network + + + ++ ++ ++Project ID of the instance. It can be useful to set this attribute if ++the instance is in a shared service project. Otherwise, the agent should ++be able to determine the project ID automatically. ++ ++Project ID ++ ++ ++ + + + Name of the network interface +@@ -215,7 +225,8 @@ def validate(ctx): + try: + ctx.instance = get_metadata('instance/name') + ctx.zone = get_metadata('instance/zone').split('/')[-1] +- ctx.project = get_metadata('project/project-id') ++ ctx.project = os.environ.get( ++ 'OCF_RESKEY_project', get_metadata('project/project-id')) + except Exception as e: + logger.error( + 'Instance information not found. Is this a GCE instance ?: %s', str(e)) +diff --git a/heartbeat/gcp-vpc-move-vip.in b/heartbeat/gcp-vpc-move-vip.in +index 01d91a59d..e792f71d5 100755 +--- a/heartbeat/gcp-vpc-move-vip.in ++++ b/heartbeat/gcp-vpc-move-vip.in +@@ -75,6 +75,16 @@ METADATA = \ + Host list + + ++ ++ ++ Project ID of the instance. It can be useful to set this ++ attribute if the instance is in a shared service project. ++ Otherwise, the agent should be able to determine the project ID ++ automatically. ++ ++ Project ID ++ ++ + + If enabled (set to true), IP failover logs will be posted to stackdriver logging + Stackdriver-logging support +@@ -267,7 +277,8 @@ def get_instances_list(project, exclude): + def gcp_alias_start(alias): + my_aliases = get_localhost_aliases() + my_zone = get_metadata('instance/zone').split('/')[-1] +- project = get_metadata('project/project-id') ++ project = os.environ.get( ++ 'OCF_RESKEY_project', get_metadata('project/project-id')) + + if alias in my_aliases: + # TODO: Do we need to check alias_range_name? +@@ -315,7 +326,8 @@ def gcp_alias_start(alias): + def gcp_alias_stop(alias): + my_aliases = get_localhost_aliases() + my_zone = get_metadata('instance/zone').split('/')[-1] +- project = get_metadata('project/project-id') ++ project = os.environ.get( ++ 'OCF_RESKEY_project', get_metadata('project/project-id')) + + if alias in my_aliases: + logger.info('Removing %s from %s' % (alias, THIS_VM)) diff --git a/SOURCES/bz1913932-2-gcp-vpc-move-route-fixes.patch b/SOURCES/bz1913932-2-gcp-vpc-move-route-fixes.patch new file mode 100644 index 0000000..a94f0ee --- /dev/null +++ b/SOURCES/bz1913932-2-gcp-vpc-move-route-fixes.patch @@ -0,0 +1,106 @@ +From 523c4cee64b3b8ee9f603a940d83a6628531078d Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 19 Jan 2021 10:56:47 +0100 +Subject: [PATCH 1/2] gcp-vpc-move-route: fix stop-action when route stopped, + and fix check_conflicting_routes() + +--- + heartbeat/gcp-vpc-move-route.in | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/heartbeat/gcp-vpc-move-route.in b/heartbeat/gcp-vpc-move-route.in +index 179eba15a..9fe985832 100644 +--- a/heartbeat/gcp-vpc-move-route.in ++++ b/heartbeat/gcp-vpc-move-route.in +@@ -252,8 +252,19 @@ def validate(ctx): + def check_conflicting_routes(ctx): + fl = '(destRange = "%s*") AND (network = "%s") AND (name != "%s")' % ( + ctx.ip, ctx.vpc_network_url, ctx.route_name) +- request = ctx.conn.routes().list(project=ctx.project, filter=fl) +- response = request.execute() ++ try: ++ request = ctx.conn.routes().list(project=ctx.project, filter=fl) ++ response = request.execute() ++ except googleapiclient.errors.HttpError as e: ++ if e.resp.status == 404: ++ logger.error('VPC network not found') ++ if 'stop' in sys.argv[1]: ++ sys.exit(OCF_SUCCESS) ++ else: ++ sys.exit(OCF_ERR_CONFIGURED) ++ else: ++ raise ++ + route_list = response.get('items', None) + if route_list: + logger.error( +@@ -353,16 +364,16 @@ def route_monitor(ctx): + logger.info('GCP route monitor: checking route table') + + # Ensure that there is no route that we are not aware of that is also handling our IP +- check_conflicting_routes ++ check_conflicting_routes(ctx) + + try: + request = ctx.conn.routes().get(project=ctx.project, route=ctx.route_name) + response = request.execute() + except googleapiclient.errors.HttpError as e: +- if 'Insufficient Permission' in e.content: +- return OCF_ERR_PERM +- elif e.resp.status == 404: ++ if e.resp.status == 404: + return OCF_NOT_RUNNING ++ elif 'Insufficient Permission' in e.content: ++ return OCF_ERR_PERM + else: + raise + + +From 50dbfc3230e87b8d29163c235e6866d15fd6fc1b Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 19 Jan 2021 11:50:22 +0100 +Subject: [PATCH 2/2] gcp-vpc-move-vip: correctly return error when no + instances are returned + +--- + heartbeat/gcp-vpc-move-vip.in | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/heartbeat/gcp-vpc-move-vip.in b/heartbeat/gcp-vpc-move-vip.in +index e792f71d5..bbbd87b7a 100755 +--- a/heartbeat/gcp-vpc-move-vip.in ++++ b/heartbeat/gcp-vpc-move-vip.in +@@ -263,8 +263,14 @@ def get_instances_list(project, exclude): + hostlist = [] + request = CONN.instances().aggregatedList(project=project) + while request is not None: +- response = request.execute() +- zones = response.get('items', {}) ++ try: ++ response = request.execute() ++ zones = response.get('items', {}) ++ except googleapiclient.errors.HttpError as e: ++ if e.resp.status == 404: ++ logger.debug('get_instances_list(): no instances found') ++ return '' ++ + for zone in zones.values(): + for inst in zone.get('instances', []): + if inst['name'] != exclude: +@@ -303,9 +309,13 @@ def gcp_alias_start(alias): + break + + # Add alias IP range to localhost +- add_alias( +- project, my_zone, THIS_VM, alias, +- os.environ.get('OCF_RESKEY_alias_range_name')) ++ try: ++ add_alias( ++ project, my_zone, THIS_VM, alias, ++ os.environ.get('OCF_RESKEY_alias_range_name')) ++ except googleapiclient.errors.HttpError as e: ++ if e.resp.status == 404: ++ sys.exit(OCF_ERR_CONFIGURED) + + # Verify that the IP range has been added + my_aliases = get_localhost_aliases() diff --git a/SOURCES/bz1913932-3-gcp-vpc-move-route-make-vpc_network-optional.patch b/SOURCES/bz1913932-3-gcp-vpc-move-route-make-vpc_network-optional.patch new file mode 100644 index 0000000..5def90a --- /dev/null +++ b/SOURCES/bz1913932-3-gcp-vpc-move-route-make-vpc_network-optional.patch @@ -0,0 +1,22 @@ +From 4812c67894063f8125a3915d32da168931f088c6 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 25 Feb 2021 16:49:55 +0100 +Subject: [PATCH] gcp-vpc-move-route: make "vpc_network" optional + +--- + heartbeat/gcp-vpc-move-route.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/gcp-vpc-move-route.in b/heartbeat/gcp-vpc-move-route.in +index 9fe985832..fd2d2ec59 100644 +--- a/heartbeat/gcp-vpc-move-route.in ++++ b/heartbeat/gcp-vpc-move-route.in +@@ -98,7 +98,7 @@ subnet ranges + + + +- ++ + + Name of the VPC network + diff --git a/SOURCES/bz1937429-azure-lb-redirect-to-avoid-nc-dying-EPIPE-error.patch b/SOURCES/bz1937142-azure-lb-redirect-to-avoid-nc-dying-EPIPE-error.patch similarity index 100% rename from SOURCES/bz1937429-azure-lb-redirect-to-avoid-nc-dying-EPIPE-error.patch rename to SOURCES/bz1937142-azure-lb-redirect-to-avoid-nc-dying-EPIPE-error.patch diff --git a/SOURCES/bz1940363-1-galera-redis-use-output-as.patch b/SOURCES/bz1940363-1-galera-redis-use-output-as.patch new file mode 100644 index 0000000..2d6473f --- /dev/null +++ b/SOURCES/bz1940363-1-galera-redis-use-output-as.patch @@ -0,0 +1,100 @@ +From f510d8e78ce65736ca5a72bd8125d31dcb4ff621 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 16 Jun 2020 13:32:18 +0200 +Subject: [PATCH 1/2] galera/redis: use --output-as for crm_mon w/newer + Pacemaker, and prepare for Promoted role + +--- + heartbeat/galera | 9 ++++++++- + heartbeat/redis.in | 9 ++++++++- + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/heartbeat/galera b/heartbeat/galera +index 4a313e24b..ba3de4b81 100755 +--- a/heartbeat/galera ++++ b/heartbeat/galera +@@ -441,7 +441,14 @@ master_exists() + return 1 + fi + # determine if a master instance is already up and is healthy +- crm_mon --as-xml | grep "resource.*id=\"${INSTANCE_ATTR_NAME}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1 ++ ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.1.0" ++ res=$? ++ if [ -z "$OCF_RESKEY_crm_feature_set" ] || [ $res -eq 2 ]; then ++ XMLOPT="--output-as=xml" ++ else ++ XMLOPT="--as-xml" ++ fi ++ crm_mon -1 $XMLOPT | grep -q -i -E "resource.*id=\"${INSTANCE_ATTR_NAME}\".*role=\"(Promoted|Master)\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" + return $? + } + +diff --git a/heartbeat/redis.in b/heartbeat/redis.in +index da7230a49..7e534db4a 100755 +--- a/heartbeat/redis.in ++++ b/heartbeat/redis.in +@@ -272,7 +272,14 @@ master_is_active() + { + if [ -z "$MASTER_ACTIVE_CACHED" ]; then + # determine if a master instance is already up and is healthy +- crm_mon --as-xml | grep "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1 ++ ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.1.0" ++ res=$? ++ if [ -z "$OCF_RESKEY_crm_feature_set" ] || [ $res -eq 2 ]; then ++ XMLOPT="--output-as=xml" ++ else ++ XMLOPT="--as-xml" ++ fi ++ crm_mon -1 $XMLOPT | grep -q -i -E "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".* role=\"(Promoted|Master)\".* active=\"true\".* orphaned=\"false\".* failed=\"false\"" + MASTER_ACTIVE=$? + MASTER_ACTIVE_CACHED="true" + fi + +From 6f36172da222275124fb44736b4801ea884c3dd0 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 31 Jul 2020 14:31:47 +0200 +Subject: [PATCH 2/2] galera/redis: support RHEL 8.1 pacemaker + +based on dfdb4e645638948cd4dafaba9d65ebddb2152b2c that solves this issue +in pgsql +--- + heartbeat/galera | 7 +++++++ + heartbeat/redis.in | 7 +++++++ + 2 files changed, 14 insertions(+) + +diff --git a/heartbeat/galera b/heartbeat/galera +index ba3de4b81..69d75a854 100755 +--- a/heartbeat/galera ++++ b/heartbeat/galera +@@ -445,6 +445,13 @@ master_exists() + res=$? + if [ -z "$OCF_RESKEY_crm_feature_set" ] || [ $res -eq 2 ]; then + XMLOPT="--output-as=xml" ++ ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.2.0" ++ if [ $? -eq 1 ]; then ++ crm_mon -1 $XMLOPT >/dev/null 2>&1 ++ if [ $? -ne 0 ]; then ++ XMLOPT="--as-xml" ++ fi ++ fi + else + XMLOPT="--as-xml" + fi +diff --git a/heartbeat/redis.in b/heartbeat/redis.in +index 7e534db4a..8afdf08a9 100755 +--- a/heartbeat/redis.in ++++ b/heartbeat/redis.in +@@ -276,6 +276,13 @@ master_is_active() + res=$? + if [ -z "$OCF_RESKEY_crm_feature_set" ] || [ $res -eq 2 ]; then + XMLOPT="--output-as=xml" ++ ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.2.0" ++ if [ $? -eq 1 ]; then ++ crm_mon -1 $XMLOPT >/dev/null 2>&1 ++ if [ $? -ne 0 ]; then ++ XMLOPT="--as-xml" ++ fi ++ fi + else + XMLOPT="--as-xml" + fi diff --git a/SOURCES/bz1940363-2-bundle-disable-validate-with.patch b/SOURCES/bz1940363-2-bundle-disable-validate-with.patch new file mode 100644 index 0000000..c480f89 --- /dev/null +++ b/SOURCES/bz1940363-2-bundle-disable-validate-with.patch @@ -0,0 +1,176 @@ +From 716db89c1ab02ce4fed8ba0916ff1f6d01b4b636 Mon Sep 17 00:00:00 2001 +From: Damien Ciabrini +Date: Thu, 18 Mar 2021 14:11:11 +0100 +Subject: [PATCH] bundle: run crm_mon without performing validation + +We have a use case in OpenStack where the resource agents run +inside bundles (containerized pacemaker remotes), and we cannot +always guarantee an exact match of pacemaker version on the host +and in containers. This can make crm_mon fail to run because +it may not have the latest version of the schema to validate the +CIB that it's getting. + +Add a function crm_mon_no_validation to allow clustered services +like galera, redis and rabbitmq to work when there is a minor +version mismatch between host and containers. This doesn't +impact non-containerized use cases, there is a single version +of pacemaker binaries in this case. + +Related-Bug: rhbz#1940363 +--- + configure.ac | 2 ++ + heartbeat/{galera => galera.in} | 10 +++++----- + heartbeat/ocf-shellfuncs.in | 16 ++++++++++++++++ + .../{rabbitmq-cluster => rabbitmq-cluster.in} | 4 ++-- + heartbeat/redis.in | 4 ++-- + 5 files changed, 27 insertions(+), 9 deletions(-) + rename heartbeat/{galera => galera.in} (98%) + rename heartbeat/{rabbitmq-cluster => rabbitmq-cluster.in} (98%) + +diff --git a/configure.ac b/configure.ac +index ed9dc09bf..11c1b786b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -979,6 +979,7 @@ AC_CONFIG_FILES([heartbeat/dnsupdate], [chmod +x heartbeat/dnsupdate]) + AC_CONFIG_FILES([heartbeat/dnsupdate], [chmod +x heartbeat/dnsupdate]) + AC_CONFIG_FILES([heartbeat/eDir88], [chmod +x heartbeat/eDir88]) + AC_CONFIG_FILES([heartbeat/fio], [chmod +x heartbeat/fio]) ++AC_CONFIG_FILES([heartbeat/galera], [chmod +x heartbeat/galera]) + AC_CONFIG_FILES([heartbeat/gcp-pd-move], [chmod +x heartbeat/gcp-pd-move]) + AC_CONFIG_FILES([heartbeat/gcp-vpc-move-ip], [chmod +x heartbeat/gcp-vpc-move-ip]) + AC_CONFIG_FILES([heartbeat/gcp-vpc-move-vip], [chmod +x heartbeat/gcp-vpc-move-vip]) +@@ -993,6 +994,7 @@ AC_CONFIG_FILES([heartbeat/machine-info], [chmod +x heartbeat/machine-info]) + AC_CONFIG_FILES([heartbeat/mariadb], [chmod +x heartbeat/mariadb]) + AC_CONFIG_FILES([heartbeat/mpathpersist], [chmod +x heartbeat/mpathpersist]) + AC_CONFIG_FILES([heartbeat/nfsnotify], [chmod +x heartbeat/nfsnotify]) ++AC_CONFIG_FILES([heartbeat/rabbitmq-cluster], [chmod +x heartbeat/rabbitmq-cluster]) + AC_CONFIG_FILES([heartbeat/redis], [chmod +x heartbeat/redis]) + AC_CONFIG_FILES([heartbeat/rsyslog], [chmod +x heartbeat/rsyslog]) + AC_CONFIG_FILES([heartbeat/sg_persist], [chmod +x heartbeat/sg_persist]) +diff --git a/heartbeat/galera b/heartbeat/galera.in +similarity index 98% +rename from heartbeat/galera +rename to heartbeat/galera.in +index c2f636f0d..7f5f2f1eb 100755 +--- a/heartbeat/galera ++++ b/heartbeat/galera.in +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!@BASH_SHELL@ + # + # Copyright (c) 2014 David Vossel + # All Rights Reserved. +@@ -447,7 +447,7 @@ is_two_node_mode_active() + # crm_node or corosync-quorumtool cannot access various corosync + # flags when running inside a bundle, so only count the cluster + # members +- ocf_is_true "$OCF_RESKEY_two_node_mode" && ${HA_SBIN_DIR}/crm_mon -1X | xmllint --xpath "count(//nodes/node[@type='member'])" - | grep -q -w 2 ++ ocf_is_true "$OCF_RESKEY_two_node_mode" && crm_mon_no_validation -1X | xmllint --xpath "count(//nodes/node[@type='member'])" - | grep -q -w 2 + } + + is_last_node_in_quorate_partition() +@@ -458,7 +458,7 @@ is_last_node_in_quorate_partition() + # is clean), we shouldn't consider ourself quorate. + local partition_members=$(${HA_SBIN_DIR}/crm_node -p | wc -w) + local quorate=$(${HA_SBIN_DIR}/crm_node -q) +- local clean_members=$(${HA_SBIN_DIR}/crm_mon -1X | xmllint --xpath 'count(//nodes/node[@type="member" and @unclean="false"])' -) ++ local clean_members=$(crm_mon_no_validation -1X | xmllint --xpath 'count(//nodes/node[@type="member" and @unclean="false"])' -) + + [ "$partition_members" = 1 ] && [ "$quorate" = 1 ] && [ "$clean_members" = 2 ] + } +@@ -480,7 +480,7 @@ master_exists() + XMLOPT="--output-as=xml" + ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.2.0" + if [ $? -eq 1 ]; then +- crm_mon -1 $XMLOPT >/dev/null 2>&1 ++ crm_mon_no_validation -1 $XMLOPT >/dev/null 2>&1 + if [ $? -ne 0 ]; then + XMLOPT="--as-xml" + fi +@@ -461,7 +461,7 @@ + else + XMLOPT="--as-xml" + fi +- crm_mon -1 $XMLOPT | grep -q -i -E "resource.*id=\"${INSTANCE_ATTR_NAME}\".*role=\"(Promoted|Master)\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" ++ crm_mon_no_validation -1 $XMLOPT | grep -q -i -E "resource.*id=\"${INSTANCE_ATTR_NAME}\".*role=\"(Promoted|Master)\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" + return $? + } + +diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in +index ac75dfc87..760790cbd 100644 +--- a/heartbeat/ocf-shellfuncs.in ++++ b/heartbeat/ocf-shellfuncs.in +@@ -41,6 +41,8 @@ + unset LC_ALL; export LC_ALL + unset LANGUAGE; export LANGUAGE + ++: ${HA_SBIN_DIR:=@sbindir@} ++ + __SCRIPT_NAME=`basename $0` + + if [ -z "$OCF_ROOT" ]; then +@@ -670,6 +672,20 @@ EOF + systemctl daemon-reload + } + ++# 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 ++# schema validation errors when host and bundle are not perfectly aligned ++# To be used, your shell must support on process substitution (e.g. bash) ++# returns: ++# ++crm_mon_no_validation() ++{ ++ # The subshell prevents parsing error with incompatible shells ++ "$SHELL" -c "CIB_file=<(${HA_SBIN_DIR}/cibadmin -Q | sed 's/validate-with=\"[^\"]*\"/validate-with=\"none\"/') \ ++ ${HA_SBIN_DIR}/crm_mon \$*" -- $* ++} ++ + # + # pseudo_resource status tracking function... + # +diff --git a/heartbeat/rabbitmq-cluster b/heartbeat/rabbitmq-cluster.in +similarity index 98% +rename from heartbeat/rabbitmq-cluster +rename to heartbeat/rabbitmq-cluster.in +index f7d48120c..abd0662f2 100755 +--- a/heartbeat/rabbitmq-cluster ++++ b/heartbeat/rabbitmq-cluster.in +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!@BASH_SHELL@ + # + # Copyright (c) 2014 David Vossel + # All Rights Reserved. +@@ -195,7 +195,7 @@ rmq_join_list() + # ... + local remote_join_list=$(cibadmin -Q --xpath "//node_state//nvpair[@name='$RMQ_CRM_ATTR_COOKIE']" | grep "$RMQ_CRM_ATTR_COOKIE" | sed -n -e "s/^.*value=.\(.*\)\".*$/\1/p") + # The following expression prepares a filter like '-e overcloud-rabbit-0 -e overcloud-rabbit-1 -e ...' +- local filter=$(crm_mon -r --as-xml | xmllint --format --xpath "//nodes//node[@online='true' and @standby='false']/@name" - | xargs -n1 echo | awk -F= '{print "-e "$2}') ++ local filter=$(crm_mon_no_validation -r --as-xml | xmllint --format --xpath "//nodes//node[@online='true' and @standby='false']/@name" - | xargs -n1 echo | awk -F= '{print "-e "$2}') + # export the intersection which gives us only the nodes that + # a) wrote their namein the cib attrd + # b) run on nodes where pacemaker_remote is enabled +diff --git a/heartbeat/redis.in b/heartbeat/redis.in +index 8afdf08a9..f53d46964 100755 +--- a/heartbeat/redis.in ++++ b/heartbeat/redis.in +@@ -278,7 +278,7 @@ master_is_active() + XMLOPT="--output-as=xml" + ocf_version_cmp "$OCF_RESKEY_crm_feature_set" "3.2.0" + if [ $? -eq 1 ]; then +- crm_mon -1 $XMLOPT >/dev/null 2>&1 ++ crm_mon_no_validation -1 $XMLOPT >/dev/null 2>&1 + if [ $? -ne 0 ]; then + XMLOPT="--as-xml" + fi +@@ -286,7 +286,7 @@ master_is_active() + else + XMLOPT="--as-xml" + fi +- crm_mon -1 $XMLOPT | grep -q -i -E "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".* role=\"(Promoted|Master)\".* active=\"true\".* orphaned=\"false\".* failed=\"false\"" ++ crm_mon_no_validation -1 $XMLOPT | grep -q -i -E "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".* role=\"(Promoted|Master)\".* active=\"true\".* orphaned=\"false\".* failed=\"false\"" + MASTER_ACTIVE=$? + MASTER_ACTIVE_CACHED="true" + fi diff --git a/SPECS/resource-agents.spec b/SPECS/resource-agents.spec index 1d336b5..495f784 100644 --- a/SPECS/resource-agents.spec +++ b/SPECS/resource-agents.spec @@ -70,7 +70,7 @@ Name: resource-agents Summary: Open Source HA Reusable Cluster Resource Scripts Version: 4.1.1 -Release: 68%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}.2 +Release: 90%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist} License: GPLv2+ and LGPLv2+ URL: https://github.com/ClusterLabs/resource-agents %if 0%{?fedora} || 0%{?centos_version} || 0%{?rhel} @@ -236,8 +236,38 @@ Patch144: bz1845574-azure-events-2-import-urlerror-encode-postdata.patch Patch145: bz1846733-gcp-vpc-move-vip-1-support-multiple-alias-ips.patch Patch146: bz1846733-gcp-vpc-move-vip-2-fix-list-sort.patch Patch147: bz1850778-azure-lb-fix-redirect-issue.patch -Patch148: bz1905587-aws-add-imdsv2-support.patch -Patch149: bz1937429-azure-lb-redirect-to-avoid-nc-dying-EPIPE-error.patch +Patch148: bz1640587-pgsql-ignore-masters-re-promote.patch +Patch149: bz1795535-pgsql-1-add-postgresql-12-support.patch +Patch150: bz1795535-pgsql-2-fix-uppercase-hostname-support.patch +Patch151: bz1858752-Filesystem-support-whitespace-device-dir.patch +Patch152: bz1872999-aws-vpc-move-ip-add-region-parameter.patch +Patch153: bz1881114-galera-recover-joining-non-existing-cluster.patch +Patch154: bz1815013-redis-parse-password-correctly-based-on-version.patch +Patch155: bz1763249-manpages-fix-pcs-syntax.patch +Patch156: bz1890068-gcp-pd-move-fix-partially-matched-disk_name.patch +Patch157: bz1848025-sybaseASE-run-verify-for-start-action-only.patch +Patch158: bz1861001-sybaseASE-add-logfile-parameter.patch +Patch159: bz1891835-galera-set-bootstrap-attribute-before-promote.patch +Patch160: bz1891855-galera-recover-2-node-cluster.patch +Patch161: bz1471182-crypt-1-new-ra.patch +Patch162: bz1471182-crypt-2-fix-bashism.patch +Patch163: bz1471182-crypt-3-fix-missing-and.patch +Patch164: bz1895811-aws-vpc-move-ip-dont-warn-for-expected-scenarios.patch +Patch165: bz1897570-aws-add-imdsv2-support.patch +Patch166: bz1886262-podman-recover-from-killed-conmon.patch +Patch167: bz1900015-podman-recover-from-storage-out-of-sync.patch +Patch168: bz1898690-crypt-make-key_file-crypt_type_not-unique.patch +Patch169: bz1899551-NovaEvacuate-fix-delay_evacuate-unset.patch +Patch170: bz1901357-crypt-1-support-symlink-devices.patch +Patch171: bz1902208-LVM-activate-stop-before-storage-service.patch +Patch172: bz1901357-crypt-2-dont-sanity-check-during-probe.patch +Patch173: bz1903677-ocf-shellfuncs-fix-traceback-redirection-bash5.patch +Patch174: bz1913932-1-gcp-vpc-move-add-project-parameter.patch +Patch175: bz1913932-2-gcp-vpc-move-route-fixes.patch +Patch176: bz1913932-3-gcp-vpc-move-route-make-vpc_network-optional.patch +Patch177: bz1937142-azure-lb-redirect-to-avoid-nc-dying-EPIPE-error.patch +Patch178: bz1940363-1-galera-redis-use-output-as.patch +Patch179: bz1940363-2-bundle-disable-validate-with.patch # bundle patches Patch1000: 7-gcp-bundled.patch @@ -277,7 +307,14 @@ Requires: /usr/sbin/fuser /bin/mount Requires: /sbin/fsck Requires: /usr/sbin/fsck.ext2 /usr/sbin/fsck.ext3 /usr/sbin/fsck.ext4 Requires: /usr/sbin/fsck.xfs -Requires: /sbin/mount.nfs /sbin/mount.nfs4 /usr/sbin/mount.cifs +Requires: /sbin/mount.nfs /sbin/mount.nfs4 +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: /usr/sbin/mount.cifs +%else +Recommends: /usr/sbin/mount.cifs +%endif +%endif # IPaddr2 Requires: /sbin/ip @@ -536,6 +573,36 @@ exit 1 %patch147 -p1 %patch148 -p1 %patch149 -p1 +%patch150 -p1 +%patch151 -p1 -F1 +%patch152 -p1 +%patch153 -p1 +%patch154 -p1 -F1 +%patch155 -p1 +%patch156 -p1 +%patch157 -p1 +%patch158 -p1 +%patch159 -p1 +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 +%patch165 -p1 +%patch166 -p1 +%patch167 -p1 +%patch168 -p1 +%patch169 -p1 -F2 +%patch170 -p1 +%patch171 -p1 +%patch172 -p1 +%patch173 -p1 +%patch174 -p1 +%patch175 -p1 +%patch176 -p1 +%patch177 -p1 +%patch178 -p1 +%patch179 -p1 chmod 755 heartbeat/nova-compute-wait chmod 755 heartbeat/NovaEvacuate @@ -1099,15 +1166,105 @@ ccs_update_schema > /dev/null 2>&1 ||: %endif %changelog -* Thu Mar 11 2021 Oyvind Albrigtsen - 4.1.1-68.2 +* Mon Mar 22 2021 Oyvind Albrigtsen - 4.1.1-90 +- galera/rabbitmq-cluster/redis: run crm_mon without validation when + running in bundle + + Resolves: rhbz#1940363 + +* Thu Mar 11 2021 Oyvind Albrigtsen - 4.1.1-89 - azure-lb: redirect to avoid nc dying with EPIPE error - Resolves: rhbz#1937429 + Resolves: rhbz#1937142 -* Wed Dec 9 2020 Oyvind Albrigtsen - 4.1.1-68.1 +* Thu Feb 25 2021 Oyvind Albrigtsen - 4.1.1-87 +- gcp-vpc-move-route, gcp-vpc-move-vip: add project parameter and + make vpc_network parameter optional + + Resolves: rhbz#1913932 + +* Thu Dec 3 2020 Oyvind Albrigtsen - 4.1.1-81 +- ocf-shellfuncs: fix traceback redirection for Bash 5+ + + Resolves: rhbz#1903677 + +* Tue Dec 1 2020 Oyvind Albrigtsen - 4.1.1-80 +- crypt: support symlink devices, and dont run sanity checks for probes + + Resolves: rhbz#1901357 + +* Mon Nov 30 2020 Oyvind Albrigtsen - 4.1.1-79 +- LVM-activate: add drop-in during start-action to avoid getting + fenced during reboot + + Resolves: rhbz#1902208 + +* Wed Nov 25 2020 Oyvind Albrigtsen - 4.1.1-77 +- NovaEvacuate: set delay_evacuate to 0 when it's not set + + Resolves: rhbz#1899551 + +* Tue Nov 24 2020 Oyvind Albrigtsen - 4.1.1-76 +- podman: recover from killed conmon process +- podman: recover from podman's storage being out of sync +- crypt: make key_file and crypt_type parameters not unique + + Resolves: rhbz#1886262 + Resolves: rhbz#1900015 + Resolves: rhbz#1898690 + +* Fri Nov 13 2020 Oyvind Albrigtsen - 4.1.1-75 - AWS agents: add support for IMDSv2 - Resolves: rhbz#1905587 + Resolves: rhbz#1897570 + +* Wed Nov 11 2020 Oyvind Albrigtsen - 4.1.1-74 +- aws-vpc-move-ip: don't warn for expected scenarios + + Resolves: rhbz#1895811 + +* Mon Nov 2 2020 Oyvind Albrigtsen - 4.1.1-73 +- crypt: new resource agent + + Resolves: rhbz#1471182 + +* Wed Oct 28 2020 Oyvind Albrigtsen - 4.1.1-72 +- sybaseASE: Run verify_all() for start operation only +- sybaseASE: add logfile parameter +- galera: set bootstrap attribute before promote +- galera: recover after network split in a 2-node cluster + + Resolves: rhbz#1848025 + Resolves: rhbz#1861001 + Resolves: rhbz#1891835 + Resolves: rhbz#1891855 + +* Tue Oct 27 2020 Oyvind Albrigtsen - 4.1.1-71 +- redis: parse password correctly based on version +- all agents: fix pcs syntax in manpage for pcs 0.10+ +- gcp-pd-move: dont stop partially matched "disk_name" + + Resolves: rhbz#1815013 + Resolves: rhbz#1763249 + Resolves: rhbz#1890068 + +* Wed Oct 7 2020 Oyvind Albrigtsen - 4.1.1-70 +- galera: recover from joining a non existing cluster + + Resolves: rhbz#1881114 + +* Wed Sep 23 2020 Oyvind Albrigtsen - 4.1.1-69 +- pgsql: ignore masters re-promote +- pgsql: add PostgreSQL 12 support +- Make Samba/CIFS dependency weak +- Filesystem: Support whitespace in device or directory name +- aws-vpc-move-ip: add region parameter + + Resolves: rhbz#1640587 + Resolves: rhbz#1795535 + Resolves: rhbz#1828600 + Resolves: rhbz#1858752 + Resolves: rhbz#1872999 * Thu Aug 20 2020 Oyvind Albrigtsen - 4.1.1-68 - azure-lb: fix redirect issue