Blame SOURCES/011-fencing-reasons.patch

f312c6
From 6db8e3adef0441953ec18dd0339c0a67c5c26bdf Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Tue, 14 Dec 2021 16:25:21 -0600
f312c6
Subject: [PATCH 01/17] Doc: Pacemaker Development: update for recent function
f312c6
 renames
f312c6
f312c6
---
f312c6
 doc/sphinx/Pacemaker_Development/components.rst | 16 ++++++++--------
f312c6
 1 file changed, 8 insertions(+), 8 deletions(-)
f312c6
f312c6
diff --git a/doc/sphinx/Pacemaker_Development/components.rst b/doc/sphinx/Pacemaker_Development/components.rst
f312c6
index a51220cac9..68158484ce 100644
f312c6
--- a/doc/sphinx/Pacemaker_Development/components.rst
f312c6
+++ b/doc/sphinx/Pacemaker_Development/components.rst
f312c6
@@ -106,7 +106,7 @@ or messaging layer callback, which calls:
f312c6
       the number of active peers), and if this is the last expected reply,
f312c6
       calls
f312c6
 
f312c6
-      * ``call_remote_stonith()``, which calculates the timeout and sends
f312c6
+      * ``request_peer_fencing()``, which calculates the timeout and sends
f312c6
         ``STONITH_OP_FENCE`` request(s) to carry out the fencing. If the target
f312c6
 	node has a fencing "topology" (which allows specifications such as
f312c6
 	"this node can be fenced either with device A, or devices B and C in
f312c6
@@ -156,7 +156,7 @@ returns, and calls
f312c6
   * done callback (``st_child_done()``), which calls ``schedule_stonith_command()``
f312c6
     for a new device if there are further required actions to execute or if the
f312c6
     original action failed, then builds and sends an XML reply to the original
f312c6
-    fencer (via ``stonith_send_async_reply()``), then checks whether any
f312c6
+    fencer (via ``send_async_reply()``), then checks whether any
f312c6
     pending actions are the same as the one just executed and merges them if so.
f312c6
 
f312c6
 Fencing replies
f312c6
@@ -169,18 +169,18 @@ messaging layer callback, which calls:
f312c6
 
f312c6
   * ``handle_reply()``, which calls
f312c6
 
f312c6
-    * ``process_remote_stonith_exec()``, which calls either
f312c6
-      ``call_remote_stonith()`` (to retry a failed operation, or try the next
f312c6
-       device in a topology is appropriate, which issues a new
f312c6
+    * ``fenced_process_fencing_reply()``, which calls either
f312c6
+      ``request_peer_fencing()`` (to retry a failed operation, or try the next
f312c6
+      device in a topology is appropriate, which issues a new
f312c6
       ``STONITH_OP_FENCE`` request, proceeding as before) or
f312c6
-      ``remote_op_done()`` (if the operation is definitively failed or
f312c6
+      ``finalize_op()`` (if the operation is definitively failed or
f312c6
       successful).
f312c6
 
f312c6
-      * remote_op_done() broadcasts the result to all peers.
f312c6
+      * ``finalize_op()`` broadcasts the result to all peers.
f312c6
 
f312c6
 Finally, all peers receive the broadcast result and call
f312c6
 
f312c6
-* ``remote_op_done()``, which sends the result to all local clients.
f312c6
+* ``finalize_op()``, which sends the result to all local clients.
f312c6
 
f312c6
 
f312c6
 .. index::
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 47db9e5fb410b1e911710727d646eb7180a70c90 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Fri, 12 Nov 2021 09:58:16 -0600
f312c6
Subject: [PATCH 02/17] Refactor: fencing: add full result to fence action
f312c6
 callback data
f312c6
f312c6
stonith_callback_data_t previously only contained the legacy return code for
f312c6
the action. Use its new opaque member to store the full result, along with
f312c6
accessors (available only internally for now).
f312c6
---
f312c6
 include/crm/fencing/internal.h |  3 ++
f312c6
 lib/fencing/st_client.c        | 99 ++++++++++++++++++++++++++--------
f312c6
 2 files changed, 81 insertions(+), 21 deletions(-)
f312c6
f312c6
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
f312c6
index f0d294a0b3..eff689e59b 100644
f312c6
--- a/include/crm/fencing/internal.h
f312c6
+++ b/include/crm/fencing/internal.h
f312c6
@@ -187,6 +187,9 @@ bool stonith__event_state_eq(stonith_history_t *history, void *user_data);
f312c6
 bool stonith__event_state_neq(stonith_history_t *history, void *user_data);
f312c6
 
f312c6
 int stonith__legacy2status(int rc);
f312c6
+int stonith__exit_status(stonith_callback_data_t *data);
f312c6
+int stonith__execution_status(stonith_callback_data_t *data);
f312c6
+const char *stonith__exit_reason(stonith_callback_data_t *data);
f312c6
 
f312c6
 /*!
f312c6
  * \internal
f312c6
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
f312c6
index 2ca094566b..9d93ffd481 100644
f312c6
--- a/lib/fencing/st_client.c
f312c6
+++ b/lib/fencing/st_client.c
f312c6
@@ -854,20 +854,23 @@ stonith_api_del_callback(stonith_t * stonith, int call_id, bool all_callbacks)
f312c6
  * \param[in] st        Fencer API connection
f312c6
  * \param[in] call_id   If positive, call ID of completed fence action, otherwise
f312c6
  *                      legacy return code for early action failure
f312c6
- * \param[in] rc        Legacy return code for action result
f312c6
+ * \param[in] result    Full result for action
f312c6
  * \param[in] userdata  User data to pass to callback
f312c6
  * \param[in] callback  Fence action callback to invoke
f312c6
  */
f312c6
 static void
f312c6
-invoke_fence_action_callback(stonith_t *st, int call_id, int rc, void *userdata,
f312c6
+invoke_fence_action_callback(stonith_t *st, int call_id,
f312c6
+                             pcmk__action_result_t *result,
f312c6
+                             void *userdata,
f312c6
                              void (*callback) (stonith_t *st,
f312c6
                                                stonith_callback_data_t *data))
f312c6
 {
f312c6
     stonith_callback_data_t data = { 0, };
f312c6
 
f312c6
     data.call_id = call_id;
f312c6
-    data.rc = rc;
f312c6
+    data.rc = pcmk_rc2legacy(stonith__result2rc(result));
f312c6
     data.userdata = userdata;
f312c6
+    data.opaque = (void *) result;
f312c6
 
f312c6
     callback(st, &data);
f312c6
 }
f312c6
@@ -888,7 +891,7 @@ invoke_registered_callbacks(stonith_t *stonith, xmlNode *msg, int call_id)
f312c6
 {
f312c6
     stonith_private_t *private = NULL;
f312c6
     stonith_callback_client_t *cb_info = NULL;
f312c6
-    int rc = pcmk_ok;
f312c6
+    pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
f312c6
 
f312c6
     CRM_CHECK(stonith != NULL, return);
f312c6
     CRM_CHECK(stonith->st_private != NULL, return);
f312c6
@@ -897,20 +900,17 @@ invoke_registered_callbacks(stonith_t *stonith, xmlNode *msg, int call_id)
f312c6
 
f312c6
     if (msg == NULL) {
f312c6
         // Fencer didn't reply in time
f312c6
-        rc = -ETIME;
f312c6
+        pcmk__set_result(&result, CRM_EX_ERROR, PCMK_EXEC_TIMEOUT,
f312c6
+                         "Timeout waiting for reply from fencer");
f312c6
         CRM_LOG_ASSERT(call_id > 0);
f312c6
 
f312c6
     } else {
f312c6
         // We have the fencer reply
f312c6
-
f312c6
-        if (crm_element_value_int(msg, F_STONITH_RC, &rc) != 0) {
f312c6
-            rc = -pcmk_err_generic;
f312c6
-        }
f312c6
-
f312c6
         if ((crm_element_value_int(msg, F_STONITH_CALLID, &call_id) != 0)
f312c6
             || (call_id <= 0)) {
f312c6
             crm_log_xml_warn(msg, "Bad fencer reply");
f312c6
         }
f312c6
+        stonith__xe_get_result(msg, &result);
f312c6
     }
f312c6
 
f312c6
     if (call_id > 0) {
f312c6
@@ -919,27 +919,29 @@ invoke_registered_callbacks(stonith_t *stonith, xmlNode *msg, int call_id)
f312c6
     }
f312c6
 
f312c6
     if ((cb_info != NULL) && (cb_info->callback != NULL)
f312c6
-        && (rc == pcmk_ok || !(cb_info->only_success))) {
f312c6
+        && (pcmk__result_ok(&result) || !(cb_info->only_success))) {
f312c6
         crm_trace("Invoking callback %s for call %d",
f312c6
                   crm_str(cb_info->id), call_id);
f312c6
-        invoke_fence_action_callback(stonith, call_id, rc, cb_info->user_data,
f312c6
-                                     cb_info->callback);
f312c6
+        invoke_fence_action_callback(stonith, call_id, &result,
f312c6
+                                     cb_info->user_data, cb_info->callback);
f312c6
 
f312c6
-    } else if ((private->op_callback == NULL) && (rc != pcmk_ok)) {
f312c6
-        crm_warn("Fencing action without registered callback failed: %s",
f312c6
-                 pcmk_strerror(rc));
f312c6
+    } else if ((private->op_callback == NULL) && !pcmk__result_ok(&result)) {
f312c6
+        crm_warn("Fencing action without registered callback failed: %d (%s)",
f312c6
+                 result.exit_status,
f312c6
+                 pcmk_exec_status_str(result.execution_status));
f312c6
         crm_log_xml_debug(msg, "Failed fence update");
f312c6
     }
f312c6
 
f312c6
     if (private->op_callback != NULL) {
f312c6
         crm_trace("Invoking global callback for call %d", call_id);
f312c6
-        invoke_fence_action_callback(stonith, call_id, rc, NULL,
f312c6
+        invoke_fence_action_callback(stonith, call_id, &result, NULL,
f312c6
                                      private->op_callback);
f312c6
     }
f312c6
 
f312c6
     if (cb_info != NULL) {
f312c6
         stonith_api_del_callback(stonith, call_id, FALSE);
f312c6
     }
f312c6
+    pcmk__reset_result(&result);
f312c6
 }
f312c6
 
f312c6
 static gboolean
f312c6
@@ -1252,14 +1254,18 @@ stonith_api_add_callback(stonith_t * stonith, int call_id, int timeout, int opti
f312c6
     CRM_CHECK(stonith->st_private != NULL, return -EINVAL);
f312c6
     private = stonith->st_private;
f312c6
 
f312c6
-    if (call_id == 0) {
f312c6
+    if (call_id == 0) { // Add global callback
f312c6
         private->op_callback = callback;
f312c6
 
f312c6
-    } else if (call_id < 0) {
f312c6
+    } else if (call_id < 0) { // Call failed immediately, so call callback now
f312c6
         if (!(options & st_opt_report_only_success)) {
f312c6
+            pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
f312c6
+
f312c6
             crm_trace("Call failed, calling %s: %s", callback_name, pcmk_strerror(call_id));
f312c6
-            invoke_fence_action_callback(stonith, call_id, call_id, user_data,
f312c6
-                                         callback);
f312c6
+            pcmk__set_result(&result, CRM_EX_ERROR,
f312c6
+                             stonith__legacy2status(call_id), NULL);
f312c6
+            invoke_fence_action_callback(stonith, call_id, &result,
f312c6
+                                         user_data, callback);
f312c6
         } else {
f312c6
             crm_warn("Fencer call failed: %s", pcmk_strerror(call_id));
f312c6
         }
f312c6
@@ -2293,6 +2299,57 @@ stonith__device_parameter_flags(uint32_t *device_flags, const char *device_name,
f312c6
     freeXpathObject(xpath);
f312c6
 }
f312c6
 
f312c6
+/*!
f312c6
+ * \internal
f312c6
+ * \brief Return the exit status from an async action callback
f312c6
+ *
f312c6
+ * \param[in] data  Callback data
f312c6
+ *
f312c6
+ * \return Exit status from callback data
f312c6
+ */
f312c6
+int
f312c6
+stonith__exit_status(stonith_callback_data_t *data)
f312c6
+{
f312c6
+    if ((data == NULL) || (data->opaque == NULL)) {
f312c6
+        return CRM_EX_ERROR;
f312c6
+    }
f312c6
+    return ((pcmk__action_result_t *) data->opaque)->exit_status;
f312c6
+}
f312c6
+
f312c6
+/*!
f312c6
+ * \internal
f312c6
+ * \brief Return the execution status from an async action callback
f312c6
+ *
f312c6
+ * \param[in] data  Callback data
f312c6
+ *
f312c6
+ * \return Execution status from callback data
f312c6
+ */
f312c6
+int
f312c6
+stonith__execution_status(stonith_callback_data_t *data)
f312c6
+{
f312c6
+    if ((data == NULL) || (data->opaque == NULL)) {
f312c6
+        return PCMK_EXEC_UNKNOWN;
f312c6
+    }
f312c6
+    return ((pcmk__action_result_t *) data->opaque)->execution_status;
f312c6
+}
f312c6
+
f312c6
+/*!
f312c6
+ * \internal
f312c6
+ * \brief Return the exit reason from an async action callback
f312c6
+ *
f312c6
+ * \param[in] data  Callback data
f312c6
+ *
f312c6
+ * \return Exit reason from callback data
f312c6
+ */
f312c6
+const char *
f312c6
+stonith__exit_reason(stonith_callback_data_t *data)
f312c6
+{
f312c6
+    if ((data == NULL) || (data->opaque == NULL)) {
f312c6
+        return NULL;
f312c6
+    }
f312c6
+    return ((pcmk__action_result_t *) data->opaque)->exit_reason;
f312c6
+}
f312c6
+
f312c6
 // Deprecated functions kept only for backward API compatibility
f312c6
 // LCOV_EXCL_START
f312c6
 
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 1e076370ef4ac7993b5ff21ed1cdfb3c4a494cf0 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Tue, 9 Nov 2021 16:16:03 -0600
f312c6
Subject: [PATCH 03/17] Log: controller: improve fencing result messages
f312c6
f312c6
Now that fence callbacks get the full result, we can log a better message.
f312c6
Also check for error conditions better, improve message wording, and ensure
f312c6
only a single message is logged per result.
f312c6
---
f312c6
 daemons/controld/controld_fencing.c | 83 +++++++++++++++++++----------
f312c6
 1 file changed, 56 insertions(+), 27 deletions(-)
f312c6
f312c6
diff --git a/daemons/controld/controld_fencing.c b/daemons/controld/controld_fencing.c
f312c6
index f5a252c813..f8d2fc13f4 100644
f312c6
--- a/daemons/controld/controld_fencing.c
f312c6
+++ b/daemons/controld/controld_fencing.c
f312c6
@@ -714,45 +714,64 @@ tengine_stonith_callback(stonith_t *stonith, stonith_callback_data_t *data)
f312c6
     int stonith_id = -1;
f312c6
     int transition_id = -1;
f312c6
     crm_action_t *action = NULL;
f312c6
-    int call_id = data->call_id;
f312c6
-    int rc = data->rc;
f312c6
-    char *userdata = data->userdata;
f312c6
-
f312c6
-    CRM_CHECK(userdata != NULL, return);
f312c6
-    crm_notice("Stonith operation %d/%s: %s (%d)", call_id, (char *)userdata,
f312c6
-               pcmk_strerror(rc), rc);
f312c6
+    const char *target = NULL;
f312c6
 
f312c6
-    if (AM_I_DC == FALSE) {
f312c6
+    if ((data == NULL) || (data->userdata == NULL)) {
f312c6
+        crm_err("Ignoring fence operation %d result: "
f312c6
+                "No transition key given (bug?)",
f312c6
+                ((data == NULL)? -1 : data->call_id));
f312c6
         return;
f312c6
     }
f312c6
 
f312c6
-    /* crm_info("call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s", */
f312c6
-    /*       op->call_id, op->optype, op->node_name, op->op_result, */
f312c6
-    /*       (char *)op->node_list, op->private_data); */
f312c6
+    if (!AM_I_DC) {
f312c6
+        const char *reason = stonith__exit_reason(data);
f312c6
+
f312c6
+        if (reason == NULL) {
f312c6
+           reason = pcmk_exec_status_str(stonith__execution_status(data));
f312c6
+        }
f312c6
+        crm_notice("Result of fence operation %d: %d (%s) " CRM_XS " key=%s",
f312c6
+                   data->call_id, stonith__exit_status(data), reason,
f312c6
+                   (const char *) data->userdata);
f312c6
+        return;
f312c6
+    }
f312c6
 
f312c6
-    /* filter out old STONITH actions */
f312c6
-    CRM_CHECK(decode_transition_key(userdata, &uuid, &transition_id, &stonith_id, NULL),
f312c6
+    CRM_CHECK(decode_transition_key(data->userdata, &uuid, &transition_id,
f312c6
+                                    &stonith_id, NULL),
f312c6
               goto bail);
f312c6
 
f312c6
-    if (transition_graph->complete || stonith_id < 0 || !pcmk__str_eq(uuid, te_uuid, pcmk__str_casei)
f312c6
-        || transition_graph->id != transition_id) {
f312c6
-        crm_info("Ignoring STONITH action initiated outside of the current transition");
f312c6
+    if (transition_graph->complete || (stonith_id < 0)
f312c6
+        || !pcmk__str_eq(uuid, te_uuid, pcmk__str_none)
f312c6
+        || (transition_graph->id != transition_id)) {
f312c6
+        crm_info("Ignoring fence operation %d result: "
f312c6
+                 "Not from current transition " CRM_XS
f312c6
+                 " complete=%s action=%d uuid=%s (vs %s) transition=%d (vs %d)",
f312c6
+                 data->call_id, pcmk__btoa(transition_graph->complete),
f312c6
+                 stonith_id, uuid, te_uuid, transition_id, transition_graph->id);
f312c6
         goto bail;
f312c6
     }
f312c6
 
f312c6
     action = controld_get_action(stonith_id);
f312c6
     if (action == NULL) {
f312c6
-        crm_err("Stonith action not matched");
f312c6
+        crm_err("Ignoring fence operation %d result: "
f312c6
+                "Action %d not found in transition graph (bug?) "
f312c6
+                CRM_XS " uuid=%s transition=%d",
f312c6
+                data->call_id, stonith_id, uuid, transition_id);
f312c6
+        goto bail;
f312c6
+    }
f312c6
+
f312c6
+    target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
f312c6
+    if (target == NULL) {
f312c6
+        crm_err("Ignoring fence operation %d result: No target given (bug?)",
f312c6
+                data->call_id);
f312c6
         goto bail;
f312c6
     }
f312c6
 
f312c6
     stop_te_timer(action->timer);
f312c6
-    if (rc == pcmk_ok) {
f312c6
-        const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
f312c6
+    if (stonith__exit_status(data) == CRM_EX_OK) {
f312c6
         const char *uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);
f312c6
         const char *op = crm_meta_value(action->params, "stonith_action");
f312c6
 
f312c6
-        crm_info("Stonith operation %d for %s passed", call_id, target);
f312c6
+        crm_notice("Fence operation %d for %s passed", data->call_id, target);
f312c6
         if (!(pcmk_is_set(action->flags, pcmk__graph_action_confirmed))) {
f312c6
             te_action_confirmed(action, NULL);
f312c6
             if (pcmk__str_eq("on", op, pcmk__str_casei)) {
f312c6
@@ -791,20 +810,30 @@ tengine_stonith_callback(stonith_t *stonith, stonith_callback_data_t *data)
f312c6
         st_fail_count_reset(target);
f312c6
 
f312c6
     } else {
f312c6
-        const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
f312c6
         enum transition_action abort_action = tg_restart;
f312c6
+        int status = stonith__execution_status(data);
f312c6
+        const char *reason = stonith__exit_reason(data);
f312c6
 
f312c6
+        if (reason == NULL) {
f312c6
+            if (status == PCMK_EXEC_DONE) {
f312c6
+                reason = "Agent returned error";
f312c6
+            } else {
f312c6
+                reason = pcmk_exec_status_str(status);
f312c6
+            }
f312c6
+        }
f312c6
         crm__set_graph_action_flags(action, pcmk__graph_action_failed);
f312c6
-        crm_notice("Stonith operation %d for %s failed (%s): aborting transition.",
f312c6
-                   call_id, target, pcmk_strerror(rc));
f312c6
 
f312c6
         /* If no fence devices were available, there's no use in immediately
f312c6
          * checking again, so don't start a new transition in that case.
f312c6
          */
f312c6
-        if (rc == -ENODEV) {
f312c6
-            crm_warn("No devices found in cluster to fence %s, giving up",
f312c6
-                     target);
f312c6
+        if (status == PCMK_EXEC_NO_FENCE_DEVICE) {
f312c6
+            crm_warn("Fence operation %d for %s failed: %s "
f312c6
+                     "(aborting transition and giving up for now)",
f312c6
+                     data->call_id, target, reason);
f312c6
             abort_action = tg_stop;
f312c6
+        } else {
f312c6
+            crm_notice("Fence operation %d for %s failed: %s "
f312c6
+                       "(aborting transition)", data->call_id, target, reason);
f312c6
         }
f312c6
 
f312c6
         /* Increment the fail count now, so abort_for_stonith_failure() can
f312c6
@@ -818,7 +847,7 @@ tengine_stonith_callback(stonith_t *stonith, stonith_callback_data_t *data)
f312c6
     trigger_graph();
f312c6
 
f312c6
   bail:
f312c6
-    free(userdata);
f312c6
+    free(data->userdata);
f312c6
     free(uuid);
f312c6
     return;
f312c6
 }
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 25547e3b7e6eb23efad1c359388d6e8d0df62363 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Mon, 22 Nov 2021 12:37:16 -0600
f312c6
Subject: [PATCH 04/17] Refactor: executor: drop action_get_uniform_rc()
f312c6
 function
f312c6
f312c6
action_get_uniform_rc() called stonith2uniform_rc() or services_result2ocf() as
f312c6
appropriate to the action standard. However, it was called only from a place
f312c6
that did not process stonith actions, so that place can just call
f312c6
services_result2ocf() directly.
f312c6
f312c6
This will simplify planned changes.
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 24 ++++++------------------
f312c6
 1 file changed, 6 insertions(+), 18 deletions(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 5bb2aab692..5e123e322e 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -780,23 +780,6 @@ stonith2uniform_rc(const char *action, int rc)
f312c6
     return rc;
f312c6
 }
f312c6
 
f312c6
-static int
f312c6
-action_get_uniform_rc(svc_action_t *action)
f312c6
-{
f312c6
-    lrmd_cmd_t *cmd = action->cb_data;
f312c6
-
f312c6
-    if (pcmk__str_eq(action->standard, PCMK_RESOURCE_CLASS_STONITH,
f312c6
-                            pcmk__str_casei)) {
f312c6
-        return stonith2uniform_rc(cmd->action, action->rc);
f312c6
-    } else {
f312c6
-        enum ocf_exitcode code = services_result2ocf(action->standard,
f312c6
-                                                     cmd->action, action->rc);
f312c6
-
f312c6
-        // Cast variable instead of function return to keep compilers happy
f312c6
-        return (int) code;
f312c6
-    }
f312c6
-}
f312c6
-
f312c6
 struct notify_new_client_data {
f312c6
     xmlNode *notify;
f312c6
     pcmk__client_t *new_client;
f312c6
@@ -848,6 +831,7 @@ action_complete(svc_action_t * action)
f312c6
 {
f312c6
     lrmd_rsc_t *rsc;
f312c6
     lrmd_cmd_t *cmd = action->cb_data;
f312c6
+    enum ocf_exitcode code;
f312c6
 
f312c6
 #ifdef PCMK__TIME_USE_CGT
f312c6
     const char *rclass = NULL;
f312c6
@@ -867,8 +851,12 @@ action_complete(svc_action_t * action)
f312c6
 #endif
f312c6
 
f312c6
     cmd->last_pid = action->pid;
f312c6
-    pcmk__set_result(&(cmd->result), action_get_uniform_rc(action),
f312c6
+
f312c6
+    // Cast variable instead of function return to keep compilers happy
f312c6
+    code = services_result2ocf(action->standard, cmd->action, action->rc);
f312c6
+    pcmk__set_result(&(cmd->result), (int) code,
f312c6
                      action->status, services__exit_reason(action));
f312c6
+
f312c6
     rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL;
f312c6
 
f312c6
 #ifdef PCMK__TIME_USE_CGT
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From b5e31ba2539da4e94c124c3f0c8c72f7039f9a7a Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Mon, 22 Nov 2021 12:39:30 -0600
f312c6
Subject: [PATCH 05/17] Feature: executor: use full result from fencer for
f312c6
 fence actions
f312c6
f312c6
Now that fence callbacks get the full result, we can improve the executor
f312c6
command result for fence actions. stonith_action_complete() now takes a
f312c6
full result, allowing the executor to use that directly rather than map a
f312c6
legacy return code.
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 140 +++++++++++++++++++--------------
f312c6
 1 file changed, 80 insertions(+), 60 deletions(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 5e123e322e..e722994012 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -8,6 +8,7 @@
f312c6
  */
f312c6
 
f312c6
 #include <crm_internal.h>
f312c6
+#include <crm/fencing/internal.h>
f312c6
 
f312c6
 #include <glib.h>
f312c6
 
f312c6
@@ -748,38 +749,6 @@ cmd_finalize(lrmd_cmd_t * cmd, lrmd_rsc_t * rsc)
f312c6
     }
f312c6
 }
f312c6
 
f312c6
-static int
f312c6
-stonith2uniform_rc(const char *action, int rc)
f312c6
-{
f312c6
-    switch (rc) {
f312c6
-        case pcmk_ok:
f312c6
-            rc = PCMK_OCF_OK;
f312c6
-            break;
f312c6
-
f312c6
-        case -ENODEV:
f312c6
-            /* This should be possible only for probes in practice, but
f312c6
-             * interpret for all actions to be safe.
f312c6
-             */
f312c6
-            if (pcmk__str_eq(action, "monitor", pcmk__str_casei)) {
f312c6
-                rc = PCMK_OCF_NOT_RUNNING;
f312c6
-            } else if (pcmk__str_eq(action, "stop", pcmk__str_casei)) {
f312c6
-                rc = PCMK_OCF_OK;
f312c6
-            } else {
f312c6
-                rc = PCMK_OCF_NOT_INSTALLED;
f312c6
-            }
f312c6
-            break;
f312c6
-
f312c6
-        case -EOPNOTSUPP:
f312c6
-            rc = PCMK_OCF_UNIMPLEMENT_FEATURE;
f312c6
-            break;
f312c6
-
f312c6
-        default:
f312c6
-            rc = PCMK_OCF_UNKNOWN_ERROR;
f312c6
-            break;
f312c6
-    }
f312c6
-    return rc;
f312c6
-}
f312c6
-
f312c6
 struct notify_new_client_data {
f312c6
     xmlNode *notify;
f312c6
     pcmk__client_t *new_client;
f312c6
@@ -988,46 +957,84 @@ action_complete(svc_action_t * action)
f312c6
     cmd_finalize(cmd, rsc);
f312c6
 }
f312c6
 
f312c6
+/*!
f312c6
+ * \internal
f312c6
+ * \brief Process the result of a fence device action (start, stop, or monitor)
f312c6
+ *
f312c6
+ * \param[in] cmd               Fence device action that completed
f312c6
+ * \param[in] exit_status       Fencer API exit status for action
f312c6
+ * \param[in] execution_status  Fencer API execution status for action
f312c6
+ * \param[in] exit_reason       Human-friendly detail, if action failed
f312c6
+ */
f312c6
 static void
f312c6
-stonith_action_complete(lrmd_cmd_t * cmd, int rc)
f312c6
+stonith_action_complete(lrmd_cmd_t *cmd, int exit_status,
f312c6
+                        enum pcmk_exec_status execution_status,
f312c6
+                        const char *exit_reason)
f312c6
 {
f312c6
     // This can be NULL if resource was removed before command completed
f312c6
     lrmd_rsc_t *rsc = g_hash_table_lookup(rsc_list, cmd->rsc_id);
f312c6
 
f312c6
-    cmd->result.exit_status = stonith2uniform_rc(cmd->action, rc);
f312c6
+    // Simplify fencer exit status to uniform exit status
f312c6
+    if (exit_status != CRM_EX_OK) {
f312c6
+        exit_status = PCMK_OCF_UNKNOWN_ERROR;
f312c6
+    }
f312c6
 
f312c6
-    /* This function may be called with status already set to cancelled, if a
f312c6
-     * pending action was aborted. Otherwise, we need to determine status from
f312c6
-     * the fencer return code.
f312c6
-     */
f312c6
-    if (cmd->result.execution_status != PCMK_EXEC_CANCELLED) {
f312c6
-        cmd->result.execution_status = stonith__legacy2status(rc);
f312c6
+    if (cmd->result.execution_status == PCMK_EXEC_CANCELLED) {
f312c6
+        /* An in-flight fence action was cancelled. The execution status is
f312c6
+         * already correct, so don't overwrite it.
f312c6
+         */
f312c6
+        execution_status = PCMK_EXEC_CANCELLED;
f312c6
 
f312c6
-        // Simplify status codes from fencer
f312c6
-        switch (cmd->result.execution_status) {
f312c6
+    } else {
f312c6
+        /* Some execution status codes have specific meanings for the fencer
f312c6
+         * that executor clients may not expect, so map them to a simple error
f312c6
+         * status.
f312c6
+         */
f312c6
+        switch (execution_status) {
f312c6
             case PCMK_EXEC_NOT_CONNECTED:
f312c6
             case PCMK_EXEC_INVALID:
f312c6
-            case PCMK_EXEC_NO_FENCE_DEVICE:
f312c6
             case PCMK_EXEC_NO_SECRETS:
f312c6
-                cmd->result.execution_status = PCMK_EXEC_ERROR;
f312c6
+                execution_status = PCMK_EXEC_ERROR;
f312c6
                 break;
f312c6
-            default:
f312c6
+
f312c6
+            case PCMK_EXEC_NO_FENCE_DEVICE:
f312c6
+                /* This should be possible only for probes in practice, but
f312c6
+                 * interpret for all actions to be safe.
f312c6
+                 */
f312c6
+                if (pcmk__str_eq(cmd->action, CRMD_ACTION_STATUS,
f312c6
+                                 pcmk__str_none)) {
f312c6
+                    exit_status = PCMK_OCF_NOT_RUNNING;
f312c6
+
f312c6
+                } else if (pcmk__str_eq(cmd->action, CRMD_ACTION_STOP,
f312c6
+                                        pcmk__str_none)) {
f312c6
+                    exit_status = PCMK_OCF_OK;
f312c6
+
f312c6
+                } else {
f312c6
+                    exit_status = PCMK_OCF_NOT_INSTALLED;
f312c6
+                }
f312c6
+                execution_status = PCMK_EXEC_ERROR;
f312c6
                 break;
f312c6
-        }
f312c6
 
f312c6
-        // Certain successful actions change the known state of the resource
f312c6
-        if ((rsc != NULL) && pcmk__result_ok(&(cmd->result))) {
f312c6
-            if (pcmk__str_eq(cmd->action, "start", pcmk__str_casei)) {
f312c6
-                rsc->st_probe_rc = pcmk_ok; // maps to PCMK_OCF_OK
f312c6
-            } else if (pcmk__str_eq(cmd->action, "stop", pcmk__str_casei)) {
f312c6
-                rsc->st_probe_rc = -ENODEV; // maps to PCMK_OCF_NOT_RUNNING
f312c6
-            }
f312c6
+            case PCMK_EXEC_NOT_SUPPORTED:
f312c6
+                exit_status = PCMK_OCF_UNIMPLEMENT_FEATURE;
f312c6
+                break;
f312c6
+
f312c6
+            default:
f312c6
+                break;
f312c6
         }
f312c6
     }
f312c6
 
f312c6
-    // Give the user more detail than an OCF code
f312c6
-    if (rc != -pcmk_err_generic) {
f312c6
-        cmd->result.exit_reason = strdup(pcmk_strerror(rc));
f312c6
+    pcmk__set_result(&cmd->result, exit_status, execution_status, exit_reason);
f312c6
+
f312c6
+    // Certain successful actions change the known state of the resource
f312c6
+    if ((rsc != NULL) && pcmk__result_ok(&(cmd->result))) {
f312c6
+
f312c6
+        if (pcmk__str_eq(cmd->action, "start", pcmk__str_casei)) {
f312c6
+            rsc->st_probe_rc = pcmk_ok; // maps to PCMK_OCF_OK
f312c6
+
f312c6
+        } else if (pcmk__str_eq(cmd->action, "stop", pcmk__str_casei)) {
f312c6
+            rsc->st_probe_rc = -ENODEV; // maps to PCMK_OCF_NOT_RUNNING
f312c6
+        }
f312c6
     }
f312c6
 
f312c6
     /* The recurring timer should not be running at this point in any case, but
f312c6
@@ -1050,7 +1057,15 @@ stonith_action_complete(lrmd_cmd_t * cmd, int rc)
f312c6
 static void
f312c6
 lrmd_stonith_callback(stonith_t * stonith, stonith_callback_data_t * data)
f312c6
 {
f312c6
-    stonith_action_complete(data->userdata, data->rc);
f312c6
+    if ((data == NULL) || (data->userdata == NULL)) {
f312c6
+        crm_err("Ignoring fence action result: "
f312c6
+                "Invalid callback arguments (bug?)");
f312c6
+    } else {
f312c6
+        stonith_action_complete((lrmd_cmd_t *) data->userdata,
f312c6
+                                stonith__exit_status(data),
f312c6
+                                stonith__execution_status(data),
f312c6
+                                stonith__exit_reason(data));
f312c6
+    }
f312c6
 }
f312c6
 
f312c6
 void
f312c6
@@ -1097,7 +1112,9 @@ stonith_connection_failed(void)
f312c6
     crm_err("Connection to fencer failed, finalizing %d pending operations",
f312c6
             g_list_length(cmd_list));
f312c6
     for (cmd_iter = cmd_list; cmd_iter; cmd_iter = cmd_iter->next) {
f312c6
-        stonith_action_complete(cmd_iter->data, -ENOTCONN);
f312c6
+        stonith_action_complete((lrmd_cmd_t *) cmd_iter->data,
f312c6
+                                CRM_EX_ERROR, PCMK_EXEC_NOT_CONNECTED,
f312c6
+                                "Lost connection to fencer");
f312c6
     }
f312c6
     g_list_free(cmd_list);
f312c6
 }
f312c6
@@ -1210,7 +1227,7 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
 
f312c6
     } else if (pcmk__str_eq(cmd->action, "start", pcmk__str_casei)) {
f312c6
         rc = execd_stonith_start(stonith_api, rsc, cmd);
f312c6
-        if (rc == 0) {
f312c6
+        if (rc == pcmk_ok) {
f312c6
             do_monitor = TRUE;
f312c6
         }
f312c6
 
f312c6
@@ -1233,7 +1250,10 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
         }
f312c6
     }
f312c6
 
f312c6
-    stonith_action_complete(cmd, rc);
f312c6
+    stonith_action_complete(cmd,
f312c6
+                            ((rc == pcmk_ok)? CRM_EX_OK : CRM_EX_ERROR),
f312c6
+                            stonith__legacy2status(rc),
f312c6
+                            rc == -pcmk_err_generic? NULL : pcmk_strerror(rc));
f312c6
 }
f312c6
 
f312c6
 static int
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 0cdc8506c2383cf05c2f62ab1ac9438958daf210 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Mon, 22 Nov 2021 16:15:05 -0600
f312c6
Subject: [PATCH 06/17] Fix: executor,scheduler: treat "no secrets" fence
f312c6
 results as a hard error
f312c6
f312c6
Previously, the executor mapped the fencer's PCMK_EXEC_NO_SECRETS status to
f312c6
PCMK_EXEC_ERROR to keep handling of that situation the same as before the new
f312c6
code was added.
f312c6
f312c6
However, the earlier handling was less than ideal -- a resource action that
f312c6
failed due to missing secrets would be retried on the same node, and almost
f312c6
certainly fail again for the same reason. Now, the executor passes along
f312c6
PCMK_EXEC_NO_SECRETS to clients; the controller will record the result in the
f312c6
CIB status, and the scheduler will treat it as a hard error (i.e. not retrying
f312c6
on the same node).
f312c6
f312c6
Backward compatibility isn't a problem because the scheduler treats unknown
f312c6
status codes the same as PCMK_EXEC_ERROR, so an older DC will continue to
f312c6
handle it as before. The CRM feature set has been bumped so the handling can't
f312c6
flip back and forth in a mixed-version cluster.
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 1 -
f312c6
 include/crm/crm.h              | 4 ++--
f312c6
 lib/pengine/unpack.c           | 3 ---
f312c6
 3 files changed, 2 insertions(+), 6 deletions(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index e722994012..4ced6d1d5c 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -993,7 +993,6 @@ stonith_action_complete(lrmd_cmd_t *cmd, int exit_status,
f312c6
         switch (execution_status) {
f312c6
             case PCMK_EXEC_NOT_CONNECTED:
f312c6
             case PCMK_EXEC_INVALID:
f312c6
-            case PCMK_EXEC_NO_SECRETS:
f312c6
                 execution_status = PCMK_EXEC_ERROR;
f312c6
                 break;
f312c6
 
f312c6
diff --git a/include/crm/crm.h b/include/crm/crm.h
f312c6
index 16b35e9c55..56b07cb12a 100644
f312c6
--- a/include/crm/crm.h
f312c6
+++ b/include/crm/crm.h
f312c6
@@ -1,5 +1,5 @@
f312c6
 /*
f312c6
- * Copyright 2004-2021 the Pacemaker project contributors
f312c6
+ * Copyright 2004-2022 the Pacemaker project contributors
f312c6
  *
f312c6
  * The version control history for this file may have further details.
f312c6
  *
f312c6
@@ -66,7 +66,7 @@ extern "C" {
f312c6
  * >=3.0.13: Fail counts include operation name and interval
f312c6
  * >=3.2.0:  DC supports PCMK_EXEC_INVALID and PCMK_EXEC_NOT_CONNECTED
f312c6
  */
f312c6
-#  define CRM_FEATURE_SET		"3.12.0"
f312c6
+#  define CRM_FEATURE_SET		"3.13.0"
f312c6
 
f312c6
 /* Pacemaker's CPG protocols use fixed-width binary fields for the sender and
f312c6
  * recipient of a CPG message. This imposes an arbitrary limit on cluster node
f312c6
diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c
f312c6
index 3e0384cd2a..8a2d2a6d6d 100644
f312c6
--- a/lib/pengine/unpack.c
f312c6
+++ b/lib/pengine/unpack.c
f312c6
@@ -3879,9 +3879,6 @@ unpack_rsc_op(pe_resource_t *rsc, pe_node_t *node, xmlNode *xml_op,
f312c6
         case PCMK_EXEC_INVALID:
f312c6
             break; // Not done, do error handling
f312c6
 
f312c6
-        /* These should only be possible in fence action results, not operation
f312c6
-         * history, but have some handling in place as a fail-safe.
f312c6
-         */
f312c6
         case PCMK_EXEC_NO_FENCE_DEVICE:
f312c6
         case PCMK_EXEC_NO_SECRETS:
f312c6
             status = PCMK_EXEC_ERROR_HARD;
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 75c1bdcf3ffc406e6fa286fd5fcff83e1e65591a Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Wed, 10 Nov 2021 12:05:20 -0600
f312c6
Subject: [PATCH 07/17] Low: executor: improve result for fence device probes
f312c6
f312c6
Now that lrmd_rsc_execute_stonith() sets a full result instead of just a legacy
f312c6
return code, refactor lrmd_rsc_t's st_probe_rc as an execution status (and
f312c6
rename to fence_probe_result). Set an appropriate exit reason when available.
f312c6
---
f312c6
 daemons/execd/execd_commands.c  | 57 ++++++++++++++++++++++++++-------
f312c6
 daemons/execd/pacemaker-execd.h |  9 +++++-
f312c6
 2 files changed, 54 insertions(+), 12 deletions(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 4ced6d1d5c..6e5505e973 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -285,7 +285,9 @@ build_rsc_from_xml(xmlNode * msg)
f312c6
     rsc->provider = crm_element_value_copy(rsc_xml, F_LRMD_PROVIDER);
f312c6
     rsc->type = crm_element_value_copy(rsc_xml, F_LRMD_TYPE);
f312c6
     rsc->work = mainloop_add_trigger(G_PRIORITY_HIGH, lrmd_rsc_dispatch, rsc);
f312c6
-    rsc->st_probe_rc = -ENODEV; // if stonith, initialize to "not running"
f312c6
+
f312c6
+    // Initialize fence device probes (to return "not running")
f312c6
+    rsc->fence_probe_result = PCMK_EXEC_NO_FENCE_DEVICE;
f312c6
     return rsc;
f312c6
 }
f312c6
 
f312c6
@@ -1029,10 +1031,10 @@ stonith_action_complete(lrmd_cmd_t *cmd, int exit_status,
f312c6
     if ((rsc != NULL) && pcmk__result_ok(&(cmd->result))) {
f312c6
 
f312c6
         if (pcmk__str_eq(cmd->action, "start", pcmk__str_casei)) {
f312c6
-            rsc->st_probe_rc = pcmk_ok; // maps to PCMK_OCF_OK
f312c6
+            rsc->fence_probe_result = PCMK_EXEC_DONE; // "running"
f312c6
 
f312c6
         } else if (pcmk__str_eq(cmd->action, "stop", pcmk__str_casei)) {
f312c6
-            rsc->st_probe_rc = -ENODEV; // maps to PCMK_OCF_NOT_RUNNING
f312c6
+            rsc->fence_probe_result = PCMK_EXEC_NO_FENCE_DEVICE; // "not running"
f312c6
         }
f312c6
     }
f312c6
 
f312c6
@@ -1081,14 +1083,13 @@ stonith_connection_failed(void)
f312c6
         if (pcmk__str_eq(rsc->class, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
f312c6
             /* If we registered this fence device, we don't know whether the
f312c6
              * fencer still has the registration or not. Cause future probes to
f312c6
-             * return PCMK_OCF_UNKNOWN_ERROR until the resource is stopped or
f312c6
-             * started successfully. This is especially important if the
f312c6
-             * controller also went away (possibly due to a cluster layer
f312c6
-             * restart) and won't receive our client notification of any
f312c6
-             * monitors finalized below.
f312c6
+             * return an error until the resource is stopped or started
f312c6
+             * successfully. This is especially important if the controller also
f312c6
+             * went away (possibly due to a cluster layer restart) and won't
f312c6
+             * receive our client notification of any monitors finalized below.
f312c6
              */
f312c6
-            if (rsc->st_probe_rc == pcmk_ok) {
f312c6
-                rsc->st_probe_rc = pcmk_err_generic;
f312c6
+            if (rsc->fence_probe_result == PCMK_EXEC_DONE) {
f312c6
+                rsc->fence_probe_result = PCMK_EXEC_NOT_CONNECTED;
f312c6
             }
f312c6
 
f312c6
             if (rsc->active) {
f312c6
@@ -1213,6 +1214,39 @@ execd_stonith_monitor(stonith_t *stonith_api, lrmd_rsc_t *rsc, lrmd_cmd_t *cmd)
f312c6
     return rc;
f312c6
 }
f312c6
 
f312c6
+/*!
f312c6
+ * \internal
f312c6
+ * \brief  Finalize the result of a fence device probe
f312c6
+ *
f312c6
+ * \param[in] cmd           Probe action
f312c6
+ * \param[in] probe_result  Probe result
f312c6
+ */
f312c6
+static void
f312c6
+finalize_fence_device_probe(lrmd_cmd_t *cmd, enum pcmk_exec_status probe_result)
f312c6
+{
f312c6
+    int exit_status = CRM_EX_ERROR;
f312c6
+    const char *reason = NULL;
f312c6
+
f312c6
+    switch (probe_result) {
f312c6
+        case PCMK_EXEC_DONE: // Device is "running"
f312c6
+            exit_status = CRM_EX_OK;
f312c6
+            break;
f312c6
+
f312c6
+        case PCMK_EXEC_NO_FENCE_DEVICE: // Device is "not running"
f312c6
+            break;
f312c6
+
f312c6
+        case PCMK_EXEC_NOT_CONNECTED: // stonith_connection_failed()
f312c6
+            reason = "Lost connection to fencer";
f312c6
+            break;
f312c6
+
f312c6
+        default: // Shouldn't be possible
f312c6
+            probe_result = PCMK_EXEC_ERROR;
f312c6
+            reason = "Invalid fence device probe result (bug?)";
f312c6
+            break;
f312c6
+    }
f312c6
+    stonith_action_complete(cmd, exit_status, probe_result, reason);
f312c6
+}
f312c6
+
f312c6
 static void
f312c6
 lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
 {
f312c6
@@ -1237,7 +1271,8 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
         if (cmd->interval_ms > 0) {
f312c6
             do_monitor = TRUE;
f312c6
         } else {
f312c6
-            rc = rsc->st_probe_rc;
f312c6
+            finalize_fence_device_probe(cmd, rsc->fence_probe_result);
f312c6
+            return;
f312c6
         }
f312c6
     }
f312c6
 
f312c6
diff --git a/daemons/execd/pacemaker-execd.h b/daemons/execd/pacemaker-execd.h
f312c6
index 51ef8d22e6..057d889584 100644
f312c6
--- a/daemons/execd/pacemaker-execd.h
f312c6
+++ b/daemons/execd/pacemaker-execd.h
f312c6
@@ -41,7 +41,14 @@ typedef struct lrmd_rsc_s {
f312c6
      * that have been handed off from the pending ops list. */
f312c6
     GList *recurring_ops;
f312c6
 
f312c6
-    int st_probe_rc; // What value should be returned for a probe if stonith
f312c6
+    /* If this resource is a fence device, probes are handled internally by the
f312c6
+     * executor, and this value indicates the result that should currently be
f312c6
+     * returned for probes. It should be one of:
f312c6
+     * PCMK_EXEC_DONE (to indicate "running"),
f312c6
+     * PCMK_EXEC_NO_FENCE_DEVICE ("not running"), or
f312c6
+     * PCMK_EXEC_NOT_CONNECTED ("unknown because fencer connection was lost").
f312c6
+     */
f312c6
+    enum pcmk_exec_status fence_probe_result;
f312c6
 
f312c6
     crm_trigger_t *work;
f312c6
 } lrmd_rsc_t;
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 1ab799d945171ab8d91bd0aada64e70a71193e5c Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Wed, 10 Nov 2021 12:14:48 -0600
f312c6
Subject: [PATCH 08/17] Low: executor: don't require a fencer connection for
f312c6
 probes
f312c6
f312c6
For fence devices, probe results are based on earlier state determinations,
f312c6
so handle them before requiring an active fencer connection. The effect may be
f312c6
negligible, but it would allow probes to proceed while waiting for a
f312c6
reconnection.
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 15 ++++++++-------
f312c6
 1 file changed, 8 insertions(+), 7 deletions(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 6e5505e973..5999ba19c9 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -1255,7 +1255,13 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
 
f312c6
     stonith_t *stonith_api = get_stonith_connection();
f312c6
 
f312c6
-    if (!stonith_api) {
f312c6
+    if (pcmk__str_eq(cmd->action, "monitor", pcmk__str_casei)
f312c6
+        && (cmd->interval_ms == 0)) {
f312c6
+        // Probes don't require a fencer connection
f312c6
+        finalize_fence_device_probe(cmd, rsc->fence_probe_result);
f312c6
+        return;
f312c6
+
f312c6
+    } else if (stonith_api == NULL) {
f312c6
         rc = -ENOTCONN;
f312c6
 
f312c6
     } else if (pcmk__str_eq(cmd->action, "start", pcmk__str_casei)) {
f312c6
@@ -1268,12 +1274,7 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
         rc = execd_stonith_stop(stonith_api, rsc);
f312c6
 
f312c6
     } else if (pcmk__str_eq(cmd->action, "monitor", pcmk__str_casei)) {
f312c6
-        if (cmd->interval_ms > 0) {
f312c6
-            do_monitor = TRUE;
f312c6
-        } else {
f312c6
-            finalize_fence_device_probe(cmd, rsc->fence_probe_result);
f312c6
-            return;
f312c6
-        }
f312c6
+        do_monitor = TRUE;
f312c6
     }
f312c6
 
f312c6
     if (do_monitor) {
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From adf41fb1637bcc9a6e057be52d61a0b26e4535cc Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Wed, 10 Nov 2021 12:20:34 -0600
f312c6
Subject: [PATCH 09/17] Low: executor: return an error for unsupported fence
f312c6
 device actions
f312c6
f312c6
... and set an exit reason. Previously, it would return success for unsupported
f312c6
actions. It shouldn't be possible, but it would be nice to have an indication
f312c6
of what is wrong if a bug is introduced.
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 6 ++++++
f312c6
 1 file changed, 6 insertions(+)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 5999ba19c9..772d6446dc 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -1275,6 +1275,12 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
 
f312c6
     } else if (pcmk__str_eq(cmd->action, "monitor", pcmk__str_casei)) {
f312c6
         do_monitor = TRUE;
f312c6
+
f312c6
+    } else {
f312c6
+        stonith_action_complete(cmd, PCMK_OCF_UNIMPLEMENT_FEATURE,
f312c6
+                                PCMK_EXEC_ERROR,
f312c6
+                                "Invalid fence device action (bug?)");
f312c6
+        return;
f312c6
     }
f312c6
 
f312c6
     if (do_monitor) {
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From af59dfe85bc83f5609d0a3b3b7939271549cb76f Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Wed, 10 Nov 2021 12:24:07 -0600
f312c6
Subject: [PATCH 10/17] Low: executor: set exit reason if no fencer connection
f312c6
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 5 ++++-
f312c6
 1 file changed, 4 insertions(+), 1 deletion(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 772d6446dc..7ae309d94c 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -1262,7 +1262,10 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
         return;
f312c6
 
f312c6
     } else if (stonith_api == NULL) {
f312c6
-        rc = -ENOTCONN;
f312c6
+        stonith_action_complete(cmd, PCMK_OCF_UNKNOWN_ERROR,
f312c6
+                                PCMK_EXEC_NOT_CONNECTED,
f312c6
+                                "No connection to fencer");
f312c6
+        return;
f312c6
 
f312c6
     } else if (pcmk__str_eq(cmd->action, "start", pcmk__str_casei)) {
f312c6
         rc = execd_stonith_start(stonith_api, rsc, cmd);
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From ad0930b75d5617490c3a0dc3c6b83411b3c4536d Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Wed, 10 Nov 2021 14:42:26 -0600
f312c6
Subject: [PATCH 11/17] Test: cts-fence-helper: log full result in fence
f312c6
 callback
f312c6
f312c6
---
f312c6
 daemons/fenced/cts-fence-helper.c | 7 +++++--
f312c6
 1 file changed, 5 insertions(+), 2 deletions(-)
f312c6
f312c6
diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c
f312c6
index 2adb032f24..c2b55d73b9 100644
f312c6
--- a/daemons/fenced/cts-fence-helper.c
f312c6
+++ b/daemons/fenced/cts-fence-helper.c
f312c6
@@ -1,5 +1,5 @@
f312c6
 /*
f312c6
- * Copyright 2009-2020 the Pacemaker project contributors
f312c6
+ * Copyright 2009-2021 the Pacemaker project contributors
f312c6
  *
f312c6
  * This source code is licensed under the GNU General Public License version 2
f312c6
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
f312c6
@@ -132,7 +132,10 @@ st_callback(stonith_t * st, stonith_event_t * e)
f312c6
 static void
f312c6
 st_global_callback(stonith_t * stonith, stonith_callback_data_t * data)
f312c6
 {
f312c6
-    crm_notice("Call id %d completed with rc %d", data->call_id, data->rc);
f312c6
+    crm_notice("Call %d exited %d: %s (%s)",
f312c6
+               data->call_id, stonith__exit_status(data),
f312c6
+               stonith__execution_status(data),
f312c6
+               crm_str(stonith__exit_reason(data)));
f312c6
 }
f312c6
 
f312c6
 static void
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 1b50ff4d83b7a96cd70389891b7b6568812f66f6 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Wed, 10 Nov 2021 15:10:14 -0600
f312c6
Subject: [PATCH 12/17] Test: cts-fence-helper: track full result instead of
f312c6
 legacy return code
f312c6
f312c6
---
f312c6
 daemons/fenced/cts-fence-helper.c | 77 +++++++++++++++----------------
f312c6
 1 file changed, 37 insertions(+), 40 deletions(-)
f312c6
f312c6
diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c
f312c6
index c2b55d73b9..2739f57804 100644
f312c6
--- a/daemons/fenced/cts-fence-helper.c
f312c6
+++ b/daemons/fenced/cts-fence-helper.c
f312c6
@@ -34,23 +34,12 @@
f312c6
 static GMainLoop *mainloop = NULL;
f312c6
 static crm_trigger_t *trig = NULL;
f312c6
 static int mainloop_iter = 0;
f312c6
-static int callback_rc = 0;
f312c6
+static pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
f312c6
+
f312c6
 typedef void (*mainloop_test_iteration_cb) (int check_event);
f312c6
 
f312c6
 #define MAINLOOP_DEFAULT_TIMEOUT 2
f312c6
 
f312c6
-#define mainloop_test_done(pass) \
f312c6
-    if (pass) { \
f312c6
-        crm_info("SUCCESS - %s", __func__); \
f312c6
-        mainloop_iter++;   \
f312c6
-        mainloop_set_trigger(trig);  \
f312c6
-    } else { \
f312c6
-        crm_err("FAILURE = %s async_callback %d", __func__, callback_rc); \
f312c6
-        crm_exit(CRM_EX_ERROR); \
f312c6
-    } \
f312c6
-    callback_rc = 0; \
f312c6
-
f312c6
-
f312c6
 enum test_modes {
f312c6
     test_standard = 0,  // test using a specific developer environment
f312c6
     test_passive,       // watch notifications only
f312c6
@@ -93,6 +82,23 @@ static const int st_opts = st_opt_sync_call;
f312c6
 static int expected_notifications = 0;
f312c6
 static int verbose = 0;
f312c6
 
f312c6
+static void
f312c6
+mainloop_test_done(const char *origin, bool pass)
f312c6
+{
f312c6
+    if (pass) {
f312c6
+        crm_info("SUCCESS - %s", origin);
f312c6
+        mainloop_iter++;
f312c6
+        mainloop_set_trigger(trig);
f312c6
+        result.execution_status = PCMK_EXEC_UNKNOWN;
f312c6
+        result.exit_status = CRM_EX_OK;
f312c6
+    } else {
f312c6
+        crm_err("FAILURE - %s (%d: %s)", origin, result.exit_status,
f312c6
+                pcmk_exec_status_str(result.execution_status));
f312c6
+        crm_exit(CRM_EX_ERROR);
f312c6
+    }
f312c6
+}
f312c6
+
f312c6
+
f312c6
 static void
f312c6
 dispatch_helper(int timeout)
f312c6
 {
f312c6
@@ -385,7 +391,9 @@ static void
f312c6
 static void
f312c6
 mainloop_callback(stonith_t * stonith, stonith_callback_data_t * data)
f312c6
 {
f312c6
-    callback_rc = data->rc;
f312c6
+    pcmk__set_result(&result, stonith__exit_status(data),
f312c6
+                     stonith__execution_status(data),
f312c6
+                     stonith__exit_reason(data));
f312c6
     iterate_mainloop_tests(TRUE);
f312c6
 }
f312c6
 
f312c6
@@ -404,18 +412,14 @@ test_async_fence_pass(int check_event)
f312c6
     int rc = 0;
f312c6
 
f312c6
     if (check_event) {
f312c6
-        if (callback_rc != 0) {
f312c6
-            mainloop_test_done(FALSE);
f312c6
-        } else {
f312c6
-            mainloop_test_done(TRUE);
f312c6
-        }
f312c6
+        mainloop_test_done(__func__, (result.exit_status == CRM_EX_OK));
f312c6
         return;
f312c6
     }
f312c6
 
f312c6
     rc = st->cmds->fence(st, 0, "true_1_node1", "off", MAINLOOP_DEFAULT_TIMEOUT, 0);
f312c6
     if (rc < 0) {
f312c6
         crm_err("fence failed with rc %d", rc);
f312c6
-        mainloop_test_done(FALSE);
f312c6
+        mainloop_test_done(__func__, false);
f312c6
     }
f312c6
     register_callback_helper(rc);
f312c6
     /* wait for event */
f312c6
@@ -431,15 +435,15 @@ test_async_fence_custom_timeout(int check_event)
f312c6
     if (check_event) {
f312c6
         uint32_t diff = (time(NULL) - begin);
f312c6
 
f312c6
-        if (callback_rc != -ETIME) {
f312c6
-            mainloop_test_done(FALSE);
f312c6
+        if (result.execution_status != PCMK_EXEC_TIMEOUT) {
f312c6
+            mainloop_test_done(__func__, false);
f312c6
         } else if (diff < CUSTOM_TIMEOUT_ADDITION + MAINLOOP_DEFAULT_TIMEOUT) {
f312c6
             crm_err
f312c6
                 ("Custom timeout test failed, callback expiration should be updated to %d, actual timeout was %d",
f312c6
                  CUSTOM_TIMEOUT_ADDITION + MAINLOOP_DEFAULT_TIMEOUT, diff);
f312c6
-            mainloop_test_done(FALSE);
f312c6
+            mainloop_test_done(__func__, false);
f312c6
         } else {
f312c6
-            mainloop_test_done(TRUE);
f312c6
+            mainloop_test_done(__func__, true);
f312c6
         }
f312c6
         return;
f312c6
     }
f312c6
@@ -448,7 +452,7 @@ test_async_fence_custom_timeout(int check_event)
f312c6
     rc = st->cmds->fence(st, 0, "custom_timeout_node1", "off", MAINLOOP_DEFAULT_TIMEOUT, 0);
f312c6
     if (rc < 0) {
f312c6
         crm_err("fence failed with rc %d", rc);
f312c6
-        mainloop_test_done(FALSE);
f312c6
+        mainloop_test_done(__func__, false);
f312c6
     }
f312c6
     register_callback_helper(rc);
f312c6
     /* wait for event */
f312c6
@@ -460,18 +464,15 @@ test_async_fence_timeout(int check_event)
f312c6
     int rc = 0;
f312c6
 
f312c6
     if (check_event) {
f312c6
-        if (callback_rc != -ENODEV) {
f312c6
-            mainloop_test_done(FALSE);
f312c6
-        } else {
f312c6
-            mainloop_test_done(TRUE);
f312c6
-        }
f312c6
+        mainloop_test_done(__func__,
f312c6
+                           (result.execution_status == PCMK_EXEC_NO_FENCE_DEVICE));
f312c6
         return;
f312c6
     }
f312c6
 
f312c6
     rc = st->cmds->fence(st, 0, "false_1_node2", "off", MAINLOOP_DEFAULT_TIMEOUT, 0);
f312c6
     if (rc < 0) {
f312c6
         crm_err("fence failed with rc %d", rc);
f312c6
-        mainloop_test_done(FALSE);
f312c6
+        mainloop_test_done(__func__, false);
f312c6
     }
f312c6
     register_callback_helper(rc);
f312c6
     /* wait for event */
f312c6
@@ -483,18 +484,14 @@ test_async_monitor(int check_event)
f312c6
     int rc = 0;
f312c6
 
f312c6
     if (check_event) {
f312c6
-        if (callback_rc) {
f312c6
-            mainloop_test_done(FALSE);
f312c6
-        } else {
f312c6
-            mainloop_test_done(TRUE);
f312c6
-        }
f312c6
+        mainloop_test_done(__func__, (result.exit_status == CRM_EX_OK));
f312c6
         return;
f312c6
     }
f312c6
 
f312c6
     rc = st->cmds->monitor(st, 0, "false_1", MAINLOOP_DEFAULT_TIMEOUT);
f312c6
     if (rc < 0) {
f312c6
         crm_err("monitor failed with rc %d", rc);
f312c6
-        mainloop_test_done(FALSE);
f312c6
+        mainloop_test_done(__func__, false);
f312c6
     }
f312c6
 
f312c6
     register_callback_helper(rc);
f312c6
@@ -531,7 +528,7 @@ test_register_async_devices(int check_event)
f312c6
                               params);
f312c6
     stonith_key_value_freeall(params, 1, 1);
f312c6
 
f312c6
-    mainloop_test_done(TRUE);
f312c6
+    mainloop_test_done(__func__, true);
f312c6
 }
f312c6
 
f312c6
 static void
f312c6
@@ -540,11 +537,11 @@ try_mainloop_connect(int check_event)
f312c6
     int rc = stonith_api_connect_retry(st, crm_system_name, 10);
f312c6
 
f312c6
     if (rc == pcmk_ok) {
f312c6
-        mainloop_test_done(TRUE);
f312c6
+        mainloop_test_done(__func__, true);
f312c6
         return;
f312c6
     }
f312c6
     crm_err("API CONNECTION FAILURE");
f312c6
-    mainloop_test_done(FALSE);
f312c6
+    mainloop_test_done(__func__, false);
f312c6
 }
f312c6
 
f312c6
 static void
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 8ff4b384a34828a4a9eebe896324ba8c89e5d66c Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Mon, 10 Jan 2022 10:27:45 -0600
f312c6
Subject: [PATCH 13/17] Doc: Pacemaker Development: correct typo
f312c6
f312c6
caught in review
f312c6
---
f312c6
 doc/sphinx/Pacemaker_Development/components.rst | 2 +-
f312c6
 1 file changed, 1 insertion(+), 1 deletion(-)
f312c6
f312c6
diff --git a/doc/sphinx/Pacemaker_Development/components.rst b/doc/sphinx/Pacemaker_Development/components.rst
f312c6
index 68158484ce..c4d10fc9f5 100644
f312c6
--- a/doc/sphinx/Pacemaker_Development/components.rst
f312c6
+++ b/doc/sphinx/Pacemaker_Development/components.rst
f312c6
@@ -171,7 +171,7 @@ messaging layer callback, which calls:
f312c6
 
f312c6
     * ``fenced_process_fencing_reply()``, which calls either
f312c6
       ``request_peer_fencing()`` (to retry a failed operation, or try the next
f312c6
-      device in a topology is appropriate, which issues a new
f312c6
+      device in a topology if appropriate, which issues a new
f312c6
       ``STONITH_OP_FENCE`` request, proceeding as before) or
f312c6
       ``finalize_op()`` (if the operation is definitively failed or
f312c6
       successful).
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 822ee6fbd8583a2939c636b3bccceffcc338c567 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Mon, 10 Jan 2022 11:05:40 -0600
f312c6
Subject: [PATCH 14/17] Doc: Pacemaker Development: add a placeholder for how
f312c6
 fencing history works
f312c6
f312c6
---
f312c6
 doc/sphinx/Pacemaker_Development/components.rst | 15 +++++++++++++++
f312c6
 1 file changed, 15 insertions(+)
f312c6
f312c6
diff --git a/doc/sphinx/Pacemaker_Development/components.rst b/doc/sphinx/Pacemaker_Development/components.rst
f312c6
index c4d10fc9f5..760da77c9b 100644
f312c6
--- a/doc/sphinx/Pacemaker_Development/components.rst
f312c6
+++ b/doc/sphinx/Pacemaker_Development/components.rst
f312c6
@@ -183,6 +183,21 @@ Finally, all peers receive the broadcast result and call
f312c6
 * ``finalize_op()``, which sends the result to all local clients.
f312c6
 
f312c6
 
f312c6
+.. index::
f312c6
+   single: fence history
f312c6
+
f312c6
+Fencing History
f312c6
+_______________
f312c6
+
f312c6
+The fencer keeps a running history of all fencing operations. The bulk of the
f312c6
+relevant code is in `fenced_history.c` and ensures the history is synchronized
f312c6
+across all nodes even if a node leaves and rejoins the cluster.
f312c6
+
f312c6
+In libstonithd, this information is represented by `stonith_history_t` and is
f312c6
+queryable by the `stonith_api_operations_t:history()` method. `crm_mon` and
f312c6
+`stonith_admin` use this API to display the history.
f312c6
+
f312c6
+
f312c6
 .. index::
f312c6
    single: scheduler
f312c6
    single: pacemaker-schedulerd
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From d9b4060f2dadb40d5ee7535e0b2890a83d216c1e Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Mon, 10 Jan 2022 11:25:31 -0600
f312c6
Subject: [PATCH 15/17] Log: fencing: add exit reason for results without a
f312c6
 callback
f312c6
f312c6
---
f312c6
 lib/fencing/st_client.c | 6 ++++--
f312c6
 1 file changed, 4 insertions(+), 2 deletions(-)
f312c6
f312c6
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
f312c6
index 9d93ffd481..4823751267 100644
f312c6
--- a/lib/fencing/st_client.c
f312c6
+++ b/lib/fencing/st_client.c
f312c6
@@ -926,9 +926,11 @@ invoke_registered_callbacks(stonith_t *stonith, xmlNode *msg, int call_id)
f312c6
                                      cb_info->user_data, cb_info->callback);
f312c6
 
f312c6
     } else if ((private->op_callback == NULL) && !pcmk__result_ok(&result)) {
f312c6
-        crm_warn("Fencing action without registered callback failed: %d (%s)",
f312c6
+        crm_warn("Fencing action without registered callback failed: %d (%s%s%s)",
f312c6
                  result.exit_status,
f312c6
-                 pcmk_exec_status_str(result.execution_status));
f312c6
+                 pcmk_exec_status_str(result.execution_status),
f312c6
+                 ((result.exit_reason == NULL)? "" : ": "),
f312c6
+                 ((result.exit_reason == NULL)? "" : result.exit_reason));
f312c6
         crm_log_xml_debug(msg, "Failed fence update");
f312c6
     }
f312c6
 
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 9956b3ad2f1c6fba305252616ad0b35a38ab96da Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Tue, 11 Jan 2022 09:28:27 -0600
f312c6
Subject: [PATCH 16/17] Refactor: executor: keep formatting consistent
f312c6
f312c6
... even if the line runs a little long
f312c6
---
f312c6
 daemons/execd/execd_commands.c | 4 ++--
f312c6
 1 file changed, 2 insertions(+), 2 deletions(-)
f312c6
f312c6
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
f312c6
index 7ae309d94c..bc3b392b2c 100644
f312c6
--- a/daemons/execd/execd_commands.c
f312c6
+++ b/daemons/execd/execd_commands.c
f312c6
@@ -1,5 +1,5 @@
f312c6
 /*
f312c6
- * Copyright 2012-2021 the Pacemaker project contributors
f312c6
+ * Copyright 2012-2022 the Pacemaker project contributors
f312c6
  *
f312c6
  * The version control history for this file may have further details.
f312c6
  *
f312c6
@@ -1297,7 +1297,7 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd)
f312c6
     stonith_action_complete(cmd,
f312c6
                             ((rc == pcmk_ok)? CRM_EX_OK : CRM_EX_ERROR),
f312c6
                             stonith__legacy2status(rc),
f312c6
-                            rc == -pcmk_err_generic? NULL : pcmk_strerror(rc));
f312c6
+                            ((rc == -pcmk_err_generic)? NULL : pcmk_strerror(rc)));
f312c6
 }
f312c6
 
f312c6
 static int
f312c6
-- 
f312c6
2.27.0
f312c6
f312c6
f312c6
From 69d8ecb17568d6c3ecad0e5735756f58a4bce5a1 Mon Sep 17 00:00:00 2001
f312c6
From: Ken Gaillot <kgaillot@redhat.com>
f312c6
Date: Tue, 11 Jan 2022 09:29:03 -0600
f312c6
Subject: [PATCH 17/17] Test: cts-fence-helper: use more intuitive execution
f312c6
 status for completed tests
f312c6
f312c6
It doesn't matter since the value is only checked against a couple of specific
f312c6
failure values, but this is less confusing.
f312c6
---
f312c6
 daemons/fenced/cts-fence-helper.c | 4 ++--
f312c6
 1 file changed, 2 insertions(+), 2 deletions(-)
f312c6
f312c6
diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c
f312c6
index 2739f57804..e222a59f9f 100644
f312c6
--- a/daemons/fenced/cts-fence-helper.c
f312c6
+++ b/daemons/fenced/cts-fence-helper.c
f312c6
@@ -1,5 +1,5 @@
f312c6
 /*
f312c6
- * Copyright 2009-2021 the Pacemaker project contributors
f312c6
+ * Copyright 2009-2022 the Pacemaker project contributors
f312c6
  *
f312c6
  * This source code is licensed under the GNU General Public License version 2
f312c6
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
f312c6
@@ -89,7 +89,7 @@ mainloop_test_done(const char *origin, bool pass)
f312c6
         crm_info("SUCCESS - %s", origin);
f312c6
         mainloop_iter++;
f312c6
         mainloop_set_trigger(trig);
f312c6
-        result.execution_status = PCMK_EXEC_UNKNOWN;
f312c6
+        result.execution_status = PCMK_EXEC_DONE;
f312c6
         result.exit_status = CRM_EX_OK;
f312c6
     } else {
f312c6
         crm_err("FAILURE - %s (%d: %s)", origin, result.exit_status,
f312c6
-- 
f312c6
2.27.0
f312c6