From 716db89c1ab02ce4fed8ba0916ff1f6d01b4b636 Mon Sep 17 00:00:00 2001
From: Damien Ciabrini <damien.ciabrini@gmail.com>
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 <davidvossel@gmail.com>
# 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 error codes>
+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 <davidvossel@gmail.com>
# 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