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