From ce3a9863dfbf5d20eedccab45da877feffac1470 Mon Sep 17 00:00:00 2001
From: Reid Wahl <nrwahl@protonmail.com>
Date: Wed, 3 Apr 2024 16:43:43 -0700
Subject: [PATCH 1/3] Low: libpacemaker: pcmk__inject_failcount should set an
 integer value

Currently it sets the new failcount value to "value++". The idea was
that this should increment the existing value. In practice, it always
sets the value to 1. This is due to a bug in fix_plus_plus_recursive
that will be fixed in an upcoming commit. To summarize,
fix_plus_plus_recursive() doesn't have access to the initial value, so
it treats the initial value as zero when incrementing it.

Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
---
 lib/pacemaker/libpacemaker_private.h |  6 +--
 lib/pacemaker/pcmk_injections.c      | 59 +++++++++++++++++++---------
 lib/pacemaker/pcmk_simulate.c        |  2 +-
 3 files changed, 44 insertions(+), 23 deletions(-)

Index: pacemaker-2.1.7+20231219.0f7f88312/lib/pacemaker/libpacemaker_private.h
===================================================================
--- pacemaker-2.1.7+20231219.0f7f88312.orig/lib/pacemaker/libpacemaker_private.h
+++ pacemaker-2.1.7+20231219.0f7f88312/lib/pacemaker/libpacemaker_private.h
@@ -1024,9 +1024,9 @@ xmlNode *pcmk__inject_resource_history(p
                                        const char *rprovider);
 
 G_GNUC_INTERNAL
-void pcmk__inject_failcount(pcmk__output_t *out, xmlNode *cib_node,
-                            const char *resource, const char *task,
-                            guint interval_ms, int rc);
+void pcmk__inject_failcount(pcmk__output_t *out, cib_t *cib_conn,
+                            xmlNode *cib_node, const char *resource,
+                            const char *task, guint interval_ms, int rc);
 
 G_GNUC_INTERNAL
 xmlNode *pcmk__inject_action_result(xmlNode *cib_resource,
Index: pacemaker-2.1.7+20231219.0f7f88312/lib/pacemaker/pcmk_injections.c
===================================================================
--- pacemaker-2.1.7+20231219.0f7f88312.orig/lib/pacemaker/pcmk_injections.c
+++ pacemaker-2.1.7+20231219.0f7f88312/lib/pacemaker/pcmk_injections.c
@@ -79,38 +79,58 @@ inject_transient_attr(pcmk__output_t *ou
  * \brief Inject a fictitious fail count into a scheduler input
  *
  * \param[in,out] out          Output object for displaying error messages
+ * \param[in,out] cib_conn     CIB connection
  * \param[in,out] cib_node     Node state XML to inject into
  * \param[in]     resource     ID of resource for fail count to inject
  * \param[in]     task         Action name for fail count to inject
  * \param[in]     interval_ms  Action interval (in milliseconds) for fail count
- * \param[in]     rc           Action result for fail count to inject (if 0, or
- *                             7 when interval_ms is 0, inject nothing)
+ * \param[in]     exit_status  Action result for fail count to inject (if
+ *                             \c PCMK_OCF_OK, or \c PCMK_OCF_NOT_RUNNING when
+ *                             \p interval_ms is 0, inject nothing)
  */
 void
-pcmk__inject_failcount(pcmk__output_t *out, xmlNode *cib_node,
+pcmk__inject_failcount(pcmk__output_t *out, cib_t *cib_conn, xmlNode *cib_node,
                        const char *resource, const char *task,
-                       guint interval_ms, int rc)
+                       guint interval_ms, int exit_status)
 {
-    if (rc == 0) {
-        return;
+    char *name = NULL;
+    char *value = NULL;
+
+    int failcount = 0;
+    xmlNode *output = NULL;
 
-    } else if ((rc == 7) && (interval_ms == 0)) {
+    CRM_CHECK((out != NULL) && (cib_conn != NULL) && (cib_node != NULL)
+              && (resource != NULL) && (task != NULL), return);
+
+    if ((exit_status == PCMK_OCF_OK)
+        || ((exit_status == PCMK_OCF_NOT_RUNNING) && (interval_ms == 0))) {
         return;
+    }
 
-    } else {
-        char *name = NULL;
-        char *now = pcmk__ttoa(time(NULL));
+    // Get current failcount and increment it
+    name = pcmk__failcount_name(resource, task, interval_ms);
 
-        name = pcmk__failcount_name(resource, task, interval_ms);
-        inject_transient_attr(out, cib_node, name, "value++");
-        free(name);
-
-        name = pcmk__lastfailure_name(resource, task, interval_ms);
-        inject_transient_attr(out, cib_node, name, now);
-        free(name);
+    if (cib__get_node_attrs(out, cib_conn, PCMK_ACTION_STATUS,
+                            ID(cib_node), NULL, NULL, NULL, name,
+                            NULL, &output) == pcmk_rc_ok) {
 
-        free(now);
+        if (crm_element_value_int(output, name, &failcount) != 0) {
+            failcount = 0;
+        }
     }
+    value = pcmk__itoa(failcount + 1);
+    inject_transient_attr(out, cib_node, name, value);
+
+    free(name);
+    free(value);
+    free_xml(output);
+
+    name = pcmk__lastfailure_name(resource, task, interval_ms);
+    value = pcmk__ttoa(time(NULL));
+    inject_transient_attr(out, cib_node, name, value);
+
+    free(name);
+    free(value);
 }
 
 /*!
@@ -603,7 +623,8 @@ inject_action(pcmk__output_t *out, const
     cib_node = pcmk__inject_node(cib, node, NULL);
     CRM_ASSERT(cib_node != NULL);
 
-    pcmk__inject_failcount(out, cib_node, resource, task, interval_ms, outcome);
+    pcmk__inject_failcount(out, cib, cib_node, resource, task, interval_ms,
+                           outcome);
 
     cib_resource = pcmk__inject_resource_history(out, cib_node,
                                                  resource, resource,
Index: pacemaker-2.1.7+20231219.0f7f88312/lib/pacemaker/pcmk_simulate.c
===================================================================
--- pacemaker-2.1.7+20231219.0f7f88312.orig/lib/pacemaker/pcmk_simulate.c
+++ pacemaker-2.1.7+20231219.0f7f88312/lib/pacemaker/pcmk_simulate.c
@@ -631,7 +631,7 @@ simulate_resource_action(pcmk__graph_t *
                   action->id, op->rc);
         pcmk__set_graph_action_flags(action, pcmk__graph_action_failed);
         graph->abort_priority = INFINITY;
-        pcmk__inject_failcount(out, cib_node, match_name, op->op_type,
+        pcmk__inject_failcount(out, fake_cib, cib_node, match_name, op->op_type,
                                op->interval_ms, op->rc);
         break;
     }
