bd3bd3
From 0d15568a538349ac41028db6b506d13dd23e8732 Mon Sep 17 00:00:00 2001
bd3bd3
From: Chris Lumens <clumens@redhat.com>
bd3bd3
Date: Tue, 14 Feb 2023 14:00:37 -0500
bd3bd3
Subject: [PATCH] High: libcrmcommon: Fix handling node=NULL in
bd3bd3
 pcmk__attrd_api_query.
bd3bd3
bd3bd3
According to the header file, if node is NULL, pcmk__attrd_api_query
bd3bd3
should query the value of the given attribute on all cluster nodes.
bd3bd3
This is also what the server expects and how attrd_updater is supposed
bd3bd3
to work.
bd3bd3
bd3bd3
However, pcmk__attrd_api_query has no way of letting callers decide
bd3bd3
whether they want to query all nodes or whether they want to use the
bd3bd3
local node.  We were passing NULL for the node name, which it took to
bd3bd3
mean it should look up the local node name.  This calls
bd3bd3
pcmk__node_attr_target, which probes the local cluster name and returns
bd3bd3
that to pcmk__attrd_api_query.  If it returns non-NULL, that value will
bd3bd3
then be put into the XML IPC call which means the server will only
bd3bd3
return the value for that node.
bd3bd3
bd3bd3
In testing this was usually fine.  However, in pratice, the methods
bd3bd3
pcmk__node_attr_target uses to figure out the local cluster node name
bd3bd3
involves checking the OCF_RESKEY_CRM_meta_on_node environment variable
bd3bd3
among others.
bd3bd3
bd3bd3
This variable was never set in testing, but can be set in the real
bd3bd3
world.  This leads to circumstances where the user did "attrd_updater -QA"
bd3bd3
expecting to get the values on all nodes, but instead only got the value
bd3bd3
on the local cluster node.
bd3bd3
bd3bd3
In pacemaker-2.1.4 and prior, pcmk__node_attr_target was simply never
bd3bd3
called if the node was NULL but was called otherwise.
bd3bd3
bd3bd3
The fix is to modify pcmk__attrd_api_query to take an option for
bd3bd3
querying all nodes.  If that's present, we'll query all nodes.  If it's
bd3bd3
not present, we'll look at the given node name - NULL means look it up,
bd3bd3
anything else means just that node.
bd3bd3
bd3bd3
Regression in 2.1.5 introduced by eb20a65577
bd3bd3
---
bd3bd3
 include/crm/common/attrd_internal.h     |  6 +++++-
bd3bd3
 include/crm/common/ipc_attrd_internal.h |  7 +++++--
bd3bd3
 lib/common/ipc_attrd.c                  | 12 ++++++++----
bd3bd3
 tools/attrd_updater.c                   |  5 +++--
bd3bd3
 4 files changed, 21 insertions(+), 9 deletions(-)
bd3bd3
bd3bd3
diff --git a/include/crm/common/attrd_internal.h b/include/crm/common/attrd_internal.h
bd3bd3
index 389be48..7337c38 100644
bd3bd3
--- a/include/crm/common/attrd_internal.h
bd3bd3
+++ b/include/crm/common/attrd_internal.h
bd3bd3
@@ -1,5 +1,5 @@
bd3bd3
 /*
bd3bd3
- * Copyright 2004-2022 the Pacemaker project contributors
bd3bd3
+ * Copyright 2004-2023 the Pacemaker project contributors
bd3bd3
  *
bd3bd3
  * The version control history for this file may have further details.
bd3bd3
  *
bd3bd3
@@ -25,6 +25,10 @@ enum pcmk__node_attr_opts {
bd3bd3
     pcmk__node_attr_perm           = (1 << 5),
bd3bd3
     pcmk__node_attr_sync_local     = (1 << 6),
bd3bd3
     pcmk__node_attr_sync_cluster   = (1 << 7),
bd3bd3
+    // pcmk__node_attr_utilization is 8, but that has not been backported.
bd3bd3
+    // I'm leaving the gap here in case we backport that in the future and
bd3bd3
+    // also to avoid problems on mixed-version clusters.
bd3bd3
+    pcmk__node_attr_query_all      = (1 << 9),
bd3bd3
 };
bd3bd3
 
bd3bd3
 #define pcmk__set_node_attr_flags(node_attr_flags, flags_to_set) do {   \
bd3bd3
diff --git a/include/crm/common/ipc_attrd_internal.h b/include/crm/common/ipc_attrd_internal.h
bd3bd3
index 2c6713f..b1b7584 100644
bd3bd3
--- a/include/crm/common/ipc_attrd_internal.h
bd3bd3
+++ b/include/crm/common/ipc_attrd_internal.h
bd3bd3
@@ -1,5 +1,5 @@
bd3bd3
 /*
bd3bd3
- * Copyright 2022 the Pacemaker project contributors
bd3bd3
+ * Copyright 2022-2023 the Pacemaker project contributors
bd3bd3
  *
bd3bd3
  * The version control history for this file may have further details.
bd3bd3
  *
bd3bd3
@@ -110,10 +110,13 @@ int pcmk__attrd_api_purge(pcmk_ipc_api_t *api, const char *node);
bd3bd3
  *
bd3bd3
  * \param[in,out] api           Connection to pacemaker-attrd
bd3bd3
  * \param[in]     node          Look up the attribute for this node
bd3bd3
- *                              (or NULL for all nodes)
bd3bd3
+ *                              (or NULL for the local node)
bd3bd3
  * \param[in]     name          Attribute name
bd3bd3
  * \param[in]     options       Bitmask of pcmk__node_attr_opts
bd3bd3
  *
bd3bd3
+ * \note Passing pcmk__node_attr_query_all will cause the function to query
bd3bd3
+ *       the value of \p name on all nodes, regardless of the value of \p node.
bd3bd3
+ *
bd3bd3
  * \return Standard Pacemaker return code
bd3bd3
  */
bd3bd3
 int pcmk__attrd_api_query(pcmk_ipc_api_t *api, const char *node, const char *name,
bd3bd3
diff --git a/lib/common/ipc_attrd.c b/lib/common/ipc_attrd.c
bd3bd3
index 4606509..dece49b 100644
bd3bd3
--- a/lib/common/ipc_attrd.c
bd3bd3
+++ b/lib/common/ipc_attrd.c
bd3bd3
@@ -1,5 +1,5 @@
bd3bd3
 /*
bd3bd3
- * Copyright 2011-2022 the Pacemaker project contributors
bd3bd3
+ * Copyright 2011-2023 the Pacemaker project contributors
bd3bd3
  *
bd3bd3
  * The version control history for this file may have further details.
bd3bd3
  *
bd3bd3
@@ -332,10 +332,14 @@ pcmk__attrd_api_query(pcmk_ipc_api_t *api, const char *node, const char *name,
bd3bd3
         return EINVAL;
bd3bd3
     }
bd3bd3
 
bd3bd3
-    target = pcmk__node_attr_target(node);
bd3bd3
+    if (pcmk_is_set(options, pcmk__node_attr_query_all)) {
bd3bd3
+        node = NULL;
bd3bd3
+    } else {
bd3bd3
+        target = pcmk__node_attr_target(node);
bd3bd3
 
bd3bd3
-    if (target != NULL) {
bd3bd3
-        node = target;
bd3bd3
+        if (target != NULL) {
bd3bd3
+            node = target;
bd3bd3
+        }
bd3bd3
     }
bd3bd3
 
bd3bd3
     request = create_attrd_op(NULL);
bd3bd3
diff --git a/tools/attrd_updater.c b/tools/attrd_updater.c
bd3bd3
index 3cd766d..cbd341d 100644
bd3bd3
--- a/tools/attrd_updater.c
bd3bd3
+++ b/tools/attrd_updater.c
bd3bd3
@@ -376,6 +376,7 @@ attrd_event_cb(pcmk_ipc_api_t *attrd_api, enum pcmk_ipc_event event_type,
bd3bd3
 static int
bd3bd3
 send_attrd_query(pcmk__output_t *out, const char *attr_name, const char *attr_node, gboolean query_all)
bd3bd3
 {
bd3bd3
+    uint32_t options = pcmk__node_attr_none;
bd3bd3
     pcmk_ipc_api_t *attrd_api = NULL;
bd3bd3
     int rc = pcmk_rc_ok;
bd3bd3
 
bd3bd3
@@ -400,10 +401,10 @@ send_attrd_query(pcmk__output_t *out, const char *attr_name, const char *attr_no
bd3bd3
 
bd3bd3
     /* Decide which node(s) to query */
bd3bd3
     if (query_all == TRUE) {
bd3bd3
-        attr_node = NULL;
bd3bd3
+        options |= pcmk__node_attr_query_all;
bd3bd3
     }
bd3bd3
 
bd3bd3
-    rc = pcmk__attrd_api_query(attrd_api, attr_node, attr_name, 0);
bd3bd3
+    rc = pcmk__attrd_api_query(attrd_api, attr_node, attr_name, options);
bd3bd3
 
bd3bd3
     if (rc != pcmk_rc_ok) {
bd3bd3
         g_set_error(&error, PCMK__RC_ERROR, rc, "Could not query value of %s: %s (%d)",
bd3bd3
-- 
bd3bd3
2.31.1
bd3bd3