84f732910e
... with selected backports from upstream master branch - Resolves: rhbz2011974
2101 lines
86 KiB
Diff
2101 lines
86 KiB
Diff
From 95b4f87aae5fb2cf771cf9a8f8e5420b65fb213f Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Tue, 21 Sep 2021 10:47:51 -0500
|
|
Subject: [PATCH 01/12] Refactor: fencing: use pcmk__action_result_t in
|
|
stonith_action_t
|
|
|
|
stonith_action_t previously had an rc member for a legacy return code, along
|
|
with output and error members for action stdout/stderr. When setting rc based
|
|
on the svc_action_t result, it used a mapping function svc_action_to_errno().
|
|
|
|
This replaces those with a pcmk__action_result_t member, which means we now
|
|
track the exit status and execution status as originally set by libcrmservice,
|
|
rather than the mapped rc. The library now calls the mapping function, now
|
|
returning standard codes and called result2rc(), when calling the client
|
|
callback.
|
|
|
|
The exit_reason member is unused as of this commit.
|
|
|
|
The behavior should be identical, with the small exception of
|
|
services_action_async() failure leaving the exit status as set by the services
|
|
library, which means callers will get the result2rc() mapping of the actual
|
|
result instead of the former -ECONNABORTED.
|
|
---
|
|
lib/fencing/st_client.c | 118 +++++++++++++++++++++++-----------------
|
|
1 file changed, 68 insertions(+), 50 deletions(-)
|
|
|
|
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
index 08adb51c6..6c607b010 100644
|
|
--- a/lib/fencing/st_client.c
|
|
+++ b/lib/fencing/st_client.c
|
|
@@ -29,6 +29,7 @@
|
|
#include <crm/msg_xml.h>
|
|
#include <crm/common/xml.h>
|
|
#include <crm/common/xml_internal.h>
|
|
+#include <crm/services_internal.h>
|
|
|
|
#include <crm/common/mainloop.h>
|
|
|
|
@@ -57,9 +58,7 @@ struct stonith_action_s {
|
|
int max_retries;
|
|
|
|
int pid;
|
|
- int rc;
|
|
- char *output;
|
|
- char *error;
|
|
+ pcmk__action_result_t result;
|
|
};
|
|
|
|
typedef struct stonith_private_s {
|
|
@@ -120,6 +119,7 @@ static void stonith_connection_destroy(gpointer user_data);
|
|
static void stonith_send_notification(gpointer data, gpointer user_data);
|
|
static int internal_stonith_action_execute(stonith_action_t * action);
|
|
static void log_action(stonith_action_t *action, pid_t pid);
|
|
+static int result2rc(const pcmk__action_result_t *result);
|
|
|
|
/*!
|
|
* \brief Get agent namespace by name
|
|
@@ -196,6 +196,23 @@ stonith_get_namespace(const char *agent, const char *namespace_s)
|
|
return st_namespace_invalid;
|
|
}
|
|
|
|
+/*!
|
|
+ * \internal
|
|
+ * \brief Set an action's result based on services library result
|
|
+ *
|
|
+ * \param[in] action Fence action to set result for
|
|
+ * \param[in] svc_action Service action to get result from
|
|
+ */
|
|
+static void
|
|
+set_result_from_svc_action(stonith_action_t *action, svc_action_t *svc_action)
|
|
+{
|
|
+ pcmk__set_result(&(action->result), svc_action->rc, svc_action->status,
|
|
+ NULL);
|
|
+ pcmk__set_result_output(&(action->result),
|
|
+ services__grab_stdout(svc_action),
|
|
+ services__grab_stderr(svc_action));
|
|
+}
|
|
+
|
|
gboolean
|
|
stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const char *node)
|
|
{
|
|
@@ -259,19 +276,19 @@ stonith__watchdog_fencing_enabled_for_node(const char *node)
|
|
static void
|
|
log_action(stonith_action_t *action, pid_t pid)
|
|
{
|
|
- if (action->output) {
|
|
+ if (action->result.action_stdout != NULL) {
|
|
/* Logging the whole string confuses syslog when the string is xml */
|
|
char *prefix = crm_strdup_printf("%s[%d] stdout:", action->agent, pid);
|
|
|
|
- crm_log_output(LOG_TRACE, prefix, action->output);
|
|
+ crm_log_output(LOG_TRACE, prefix, action->result.action_stdout);
|
|
free(prefix);
|
|
}
|
|
|
|
- if (action->error) {
|
|
+ if (action->result.action_stderr != NULL) {
|
|
/* Logging the whole string confuses syslog when the string is xml */
|
|
char *prefix = crm_strdup_printf("%s[%d] stderr:", action->agent, pid);
|
|
|
|
- crm_log_output(LOG_WARNING, prefix, action->error);
|
|
+ crm_log_output(LOG_WARNING, prefix, action->result.action_stderr);
|
|
free(prefix);
|
|
}
|
|
}
|
|
@@ -645,8 +662,7 @@ stonith__destroy_action(stonith_action_t *action)
|
|
if (action->svc_action) {
|
|
services_action_free(action->svc_action);
|
|
}
|
|
- free(action->output);
|
|
- free(action->error);
|
|
+ pcmk__reset_result(&(action->result));
|
|
free(action);
|
|
}
|
|
}
|
|
@@ -678,15 +694,15 @@ stonith__action_result(stonith_action_t *action, int *rc, char **output,
|
|
}
|
|
if (action != NULL) {
|
|
if (rc) {
|
|
- *rc = action->rc;
|
|
+ *rc = pcmk_rc2legacy(result2rc(&(action->result)));
|
|
}
|
|
- if (output && action->output) {
|
|
- *output = action->output;
|
|
- action->output = NULL; // hand off memory management to caller
|
|
+ if ((output != NULL) && (action->result.action_stdout != NULL)) {
|
|
+ *output = action->result.action_stdout;
|
|
+ action->result.action_stdout = NULL; // hand off ownership to caller
|
|
}
|
|
- if (error_output && action->error) {
|
|
- *error_output = action->error;
|
|
- action->error = NULL; // hand off memory management to caller
|
|
+ if ((error_output != NULL) && (action->result.action_stderr != NULL)) {
|
|
+ *error_output = action->result.action_stderr;
|
|
+ action->result.action_stderr = NULL; // hand off ownership to caller
|
|
}
|
|
}
|
|
}
|
|
@@ -715,6 +731,9 @@ stonith_action_create(const char *agent,
|
|
action->timeout = action->remaining_timeout = timeout;
|
|
action->max_retries = FAILURE_MAX_RETRIES;
|
|
|
|
+ pcmk__set_result(&(action->result), PCMK_OCF_UNKNOWN, PCMK_EXEC_UNKNOWN,
|
|
+ NULL);
|
|
+
|
|
if (device_args) {
|
|
char buffer[512];
|
|
const char *value = NULL;
|
|
@@ -739,7 +758,8 @@ update_remaining_timeout(stonith_action_t * action)
|
|
crm_info("Attempted to execute agent %s (%s) the maximum number of times (%d) allowed",
|
|
action->agent, action->action, action->max_retries);
|
|
action->remaining_timeout = 0;
|
|
- } else if ((action->rc != -ETIME) && diff < (action->timeout * 0.7)) {
|
|
+ } else if ((action->result.execution_status != PCMK_EXEC_TIMEOUT)
|
|
+ && (diff < (action->timeout * 0.7))) {
|
|
/* only set remaining timeout period if there is 30%
|
|
* or greater of the original timeout period left */
|
|
action->remaining_timeout = action->timeout - diff;
|
|
@@ -750,31 +770,31 @@ update_remaining_timeout(stonith_action_t * action)
|
|
}
|
|
|
|
static int
|
|
-svc_action_to_errno(svc_action_t *svc_action) {
|
|
- int rv = pcmk_ok;
|
|
+result2rc(const pcmk__action_result_t *result) {
|
|
+ int rc = pcmk_rc_ok;
|
|
|
|
- if (svc_action->status == PCMK_EXEC_TIMEOUT) {
|
|
- rv = -ETIME;
|
|
+ if (result->execution_status == PCMK_EXEC_TIMEOUT) {
|
|
+ rc = ETIME;
|
|
|
|
- } else if (svc_action->rc != PCMK_OCF_OK) {
|
|
+ } else if (result->exit_status != CRM_EX_OK) {
|
|
/* Try to provide a useful error code based on the fence agent's
|
|
* error output.
|
|
*/
|
|
- if (svc_action->stderr_data == NULL) {
|
|
- rv = -ENODATA;
|
|
+ if (result->action_stderr == NULL) {
|
|
+ rc = ENODATA;
|
|
|
|
- } else if (strstr(svc_action->stderr_data, "imed out")) {
|
|
+ } else if (strstr(result->action_stderr, "imed out")) {
|
|
/* Some agents have their own internal timeouts */
|
|
- rv = -ETIME;
|
|
+ rc = ETIME;
|
|
|
|
- } else if (strstr(svc_action->stderr_data, "Unrecognised action")) {
|
|
- rv = -EOPNOTSUPP;
|
|
+ } else if (strstr(result->action_stderr, "Unrecognised action")) {
|
|
+ rc = EOPNOTSUPP;
|
|
|
|
} else {
|
|
- rv = -pcmk_err_generic;
|
|
+ rc = pcmk_rc_error;
|
|
}
|
|
}
|
|
- return rv;
|
|
+ return rc;
|
|
}
|
|
|
|
static void
|
|
@@ -782,11 +802,7 @@ stonith_action_async_done(svc_action_t *svc_action)
|
|
{
|
|
stonith_action_t *action = (stonith_action_t *) svc_action->cb_data;
|
|
|
|
- action->rc = svc_action_to_errno(svc_action);
|
|
- action->output = svc_action->stdout_data;
|
|
- svc_action->stdout_data = NULL;
|
|
- action->error = svc_action->stderr_data;
|
|
- svc_action->stderr_data = NULL;
|
|
+ set_result_from_svc_action(action, svc_action);
|
|
|
|
svc_action->params = NULL;
|
|
|
|
@@ -795,7 +811,9 @@ stonith_action_async_done(svc_action_t *svc_action)
|
|
|
|
log_action(action, action->pid);
|
|
|
|
- if (action->rc != pcmk_ok && update_remaining_timeout(action)) {
|
|
+ if ((action->result.exit_status != CRM_EX_OK)
|
|
+ && update_remaining_timeout(action)) {
|
|
+
|
|
int rc = internal_stonith_action_execute(action);
|
|
if (rc == pcmk_ok) {
|
|
return;
|
|
@@ -803,7 +821,8 @@ stonith_action_async_done(svc_action_t *svc_action)
|
|
}
|
|
|
|
if (action->done_cb) {
|
|
- action->done_cb(action->pid, action->rc, action->output, action->userdata);
|
|
+ action->done_cb(action->pid, pcmk_rc2legacy(result2rc(&(action->result))),
|
|
+ action->result.action_stdout, action->userdata);
|
|
}
|
|
|
|
action->svc_action = NULL; // don't remove our caller
|
|
@@ -835,9 +854,13 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
static int stonith_sequence = 0;
|
|
char *buffer = NULL;
|
|
|
|
- if ((action == NULL) || (action->action == NULL) || (action->args == NULL)
|
|
+ CRM_CHECK(action != NULL, return -EINVAL);
|
|
+
|
|
+ if ((action->action == NULL) || (action->args == NULL)
|
|
|| (action->agent == NULL)) {
|
|
- return -EPROTO;
|
|
+ pcmk__set_result(&(action->result), PCMK_OCF_UNKNOWN_ERROR,
|
|
+ PCMK_EXEC_ERROR_FATAL, NULL);
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
if (!action->tries) {
|
|
@@ -857,6 +880,7 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
free(buffer);
|
|
|
|
if (svc_action->rc != PCMK_OCF_UNKNOWN) {
|
|
+ set_result_from_svc_action(action, svc_action);
|
|
services_action_free(svc_action);
|
|
return -E2BIG;
|
|
}
|
|
@@ -877,10 +901,7 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
|
|
/* keep retries from executing out of control and free previous results */
|
|
if (is_retry) {
|
|
- free(action->output);
|
|
- action->output = NULL;
|
|
- free(action->error);
|
|
- action->error = NULL;
|
|
+ pcmk__reset_result(&(action->result));
|
|
sleep(1);
|
|
}
|
|
|
|
@@ -889,22 +910,19 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
if (services_action_async_fork_notify(svc_action,
|
|
&stonith_action_async_done,
|
|
&stonith_action_async_forked)) {
|
|
+ pcmk__set_result(&(action->result), PCMK_OCF_UNKNOWN,
|
|
+ PCMK_EXEC_PENDING, NULL);
|
|
return pcmk_ok;
|
|
}
|
|
|
|
} else if (services_action_sync(svc_action)) { // sync success
|
|
rc = pcmk_ok;
|
|
- action->rc = svc_action_to_errno(svc_action);
|
|
- action->output = svc_action->stdout_data;
|
|
- svc_action->stdout_data = NULL;
|
|
- action->error = svc_action->stderr_data;
|
|
- svc_action->stderr_data = NULL;
|
|
|
|
} else { // sync failure
|
|
- action->rc = -ECONNABORTED;
|
|
- rc = action->rc;
|
|
+ rc = -ECONNABORTED;
|
|
}
|
|
|
|
+ set_result_from_svc_action(action, svc_action);
|
|
svc_action->params = NULL;
|
|
services_action_free(svc_action);
|
|
return rc;
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 4c8e0b0ecc53cb3883f0da0eede20b900fff48d1 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Tue, 21 Sep 2021 11:14:31 -0500
|
|
Subject: [PATCH 02/12] Low: fencing: improve return code given back to library
|
|
callers
|
|
|
|
Expose result2rc() internally for future reuse, and expand it to handle more
|
|
cases. In theory, this can give us better log messages and status output for
|
|
failures.
|
|
---
|
|
include/crm/fencing/internal.h | 1 +
|
|
lib/fencing/st_client.c | 63 +++++++++++++++++++++-------------
|
|
2 files changed, 41 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
|
|
index fa9059e6f..0d23967bb 100644
|
|
--- a/include/crm/fencing/internal.h
|
|
+++ b/include/crm/fencing/internal.h
|
|
@@ -60,6 +60,7 @@ stonith_action_t *stonith_action_create(const char *agent,
|
|
void stonith__destroy_action(stonith_action_t *action);
|
|
void stonith__action_result(stonith_action_t *action, int *rc, char **output,
|
|
char **error_output);
|
|
+int stonith__result2rc(const pcmk__action_result_t *result);
|
|
|
|
int
|
|
stonith_action_execute_async(stonith_action_t * action,
|
|
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
index 6c607b010..809be1640 100644
|
|
--- a/lib/fencing/st_client.c
|
|
+++ b/lib/fencing/st_client.c
|
|
@@ -119,7 +119,6 @@ static void stonith_connection_destroy(gpointer user_data);
|
|
static void stonith_send_notification(gpointer data, gpointer user_data);
|
|
static int internal_stonith_action_execute(stonith_action_t * action);
|
|
static void log_action(stonith_action_t *action, pid_t pid);
|
|
-static int result2rc(const pcmk__action_result_t *result);
|
|
|
|
/*!
|
|
* \brief Get agent namespace by name
|
|
@@ -694,7 +693,7 @@ stonith__action_result(stonith_action_t *action, int *rc, char **output,
|
|
}
|
|
if (action != NULL) {
|
|
if (rc) {
|
|
- *rc = pcmk_rc2legacy(result2rc(&(action->result)));
|
|
+ *rc = pcmk_rc2legacy(stonith__result2rc(&(action->result)));
|
|
}
|
|
if ((output != NULL) && (action->result.action_stdout != NULL)) {
|
|
*output = action->result.action_stdout;
|
|
@@ -769,32 +768,49 @@ update_remaining_timeout(stonith_action_t * action)
|
|
return action->remaining_timeout ? TRUE : FALSE;
|
|
}
|
|
|
|
-static int
|
|
-result2rc(const pcmk__action_result_t *result) {
|
|
- int rc = pcmk_rc_ok;
|
|
+/*!
|
|
+ * \internal
|
|
+ * \brief Map a fencing action result to a standard return code
|
|
+ *
|
|
+ * \param[in] result Fencing action result to map
|
|
+ *
|
|
+ * \return Standard Pacemaker return code that best corresponds to \p result
|
|
+ */
|
|
+int
|
|
+stonith__result2rc(const pcmk__action_result_t *result)
|
|
+{
|
|
+ switch (result->execution_status) {
|
|
+ case PCMK_EXEC_CANCELLED: return ECANCELED;
|
|
+ case PCMK_EXEC_TIMEOUT: return ETIME;
|
|
+ case PCMK_EXEC_NOT_INSTALLED: return ENOENT;
|
|
+ case PCMK_EXEC_NOT_SUPPORTED: return EOPNOTSUPP;
|
|
+ case PCMK_EXEC_NOT_CONNECTED: return ENOTCONN;
|
|
+ case PCMK_EXEC_NO_FENCE_DEVICE: return ENODEV;
|
|
+ case PCMK_EXEC_NO_SECRETS: return EACCES;
|
|
+ default: break;
|
|
+ }
|
|
|
|
- if (result->execution_status == PCMK_EXEC_TIMEOUT) {
|
|
- rc = ETIME;
|
|
+ if (result->exit_status == CRM_EX_OK) {
|
|
+ return pcmk_rc_ok;
|
|
+ }
|
|
|
|
- } else if (result->exit_status != CRM_EX_OK) {
|
|
- /* Try to provide a useful error code based on the fence agent's
|
|
- * error output.
|
|
- */
|
|
- if (result->action_stderr == NULL) {
|
|
- rc = ENODATA;
|
|
+ // Try to provide useful error code based on result's error output
|
|
|
|
- } else if (strstr(result->action_stderr, "imed out")) {
|
|
- /* Some agents have their own internal timeouts */
|
|
- rc = ETIME;
|
|
+ if (result->action_stderr == NULL) {
|
|
+ return ENODATA;
|
|
|
|
- } else if (strstr(result->action_stderr, "Unrecognised action")) {
|
|
- rc = EOPNOTSUPP;
|
|
+ } else if (strcasestr(result->action_stderr, "timed out")
|
|
+ || strcasestr(result->action_stderr, "timeout")) {
|
|
+ return ETIME;
|
|
|
|
- } else {
|
|
- rc = pcmk_rc_error;
|
|
- }
|
|
+ } else if (strcasestr(result->action_stderr, "unrecognised action")
|
|
+ || strcasestr(result->action_stderr, "unrecognized action")
|
|
+ || strcasestr(result->action_stderr, "unsupported action")) {
|
|
+ return EOPNOTSUPP;
|
|
}
|
|
- return rc;
|
|
+
|
|
+ // Oh well, we tried
|
|
+ return pcmk_rc_error;
|
|
}
|
|
|
|
static void
|
|
@@ -821,7 +837,8 @@ stonith_action_async_done(svc_action_t *svc_action)
|
|
}
|
|
|
|
if (action->done_cb) {
|
|
- action->done_cb(action->pid, pcmk_rc2legacy(result2rc(&(action->result))),
|
|
+ action->done_cb(action->pid,
|
|
+ pcmk_rc2legacy(stonith__result2rc(&(action->result))),
|
|
action->result.action_stdout, action->userdata);
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 153c9b552a5bad9dd36e8635fa478ed9cad1f240 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Thu, 7 Oct 2021 11:35:44 -0500
|
|
Subject: [PATCH 03/12] Refactor: fencing: return full result from
|
|
stonith__action_result()
|
|
|
|
Previously, stonith__action_result() grabbed an action's legacy rc, stdout, and
|
|
stderr separately. Now, directly return a pointer to the action's result
|
|
object, and map that to a legacy rc in the callers when needed.
|
|
---
|
|
include/crm/fencing/internal.h | 3 +--
|
|
lib/fencing/st_client.c | 36 ++++---------------------
|
|
lib/fencing/st_rhcs.c | 48 ++++++++++++++++++++++++----------
|
|
3 files changed, 40 insertions(+), 47 deletions(-)
|
|
|
|
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
|
|
index 0d23967bb..4e9f50fe8 100644
|
|
--- a/include/crm/fencing/internal.h
|
|
+++ b/include/crm/fencing/internal.h
|
|
@@ -58,8 +58,7 @@ stonith_action_t *stonith_action_create(const char *agent,
|
|
GHashTable * port_map,
|
|
const char * host_arg);
|
|
void stonith__destroy_action(stonith_action_t *action);
|
|
-void stonith__action_result(stonith_action_t *action, int *rc, char **output,
|
|
- char **error_output);
|
|
+pcmk__action_result_t *stonith__action_result(stonith_action_t *action);
|
|
int stonith__result2rc(const pcmk__action_result_t *result);
|
|
|
|
int
|
|
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
index 809be1640..b9df18465 100644
|
|
--- a/lib/fencing/st_client.c
|
|
+++ b/lib/fencing/st_client.c
|
|
@@ -670,40 +670,14 @@ stonith__destroy_action(stonith_action_t *action)
|
|
* \internal
|
|
* \brief Get the result of an executed stonith action
|
|
*
|
|
- * \param[in,out] action Executed action
|
|
- * \param[out] rc Where to store result code (or NULL)
|
|
- * \param[out] output Where to store standard output (or NULL)
|
|
- * \param[out] error_output Where to store standard error output (or NULL)
|
|
+ * \param[in] action Executed action
|
|
*
|
|
- * \note If output or error_output is not NULL, the caller is responsible for
|
|
- * freeing the memory.
|
|
+ * \return Pointer to action's result (or NULL if \p action is NULL)
|
|
*/
|
|
-void
|
|
-stonith__action_result(stonith_action_t *action, int *rc, char **output,
|
|
- char **error_output)
|
|
+pcmk__action_result_t *
|
|
+stonith__action_result(stonith_action_t *action)
|
|
{
|
|
- if (rc) {
|
|
- *rc = pcmk_ok;
|
|
- }
|
|
- if (output) {
|
|
- *output = NULL;
|
|
- }
|
|
- if (error_output) {
|
|
- *error_output = NULL;
|
|
- }
|
|
- if (action != NULL) {
|
|
- if (rc) {
|
|
- *rc = pcmk_rc2legacy(stonith__result2rc(&(action->result)));
|
|
- }
|
|
- if ((output != NULL) && (action->result.action_stdout != NULL)) {
|
|
- *output = action->result.action_stdout;
|
|
- action->result.action_stdout = NULL; // hand off ownership to caller
|
|
- }
|
|
- if ((error_output != NULL) && (action->result.action_stderr != NULL)) {
|
|
- *error_output = action->result.action_stderr;
|
|
- action->result.action_stderr = NULL; // hand off ownership to caller
|
|
- }
|
|
- }
|
|
+ return (action == NULL)? NULL : &(action->result);
|
|
}
|
|
|
|
#define FAILURE_MAX_RETRIES 2
|
|
diff --git a/lib/fencing/st_rhcs.c b/lib/fencing/st_rhcs.c
|
|
index 89a2625bd..23e694975 100644
|
|
--- a/lib/fencing/st_rhcs.c
|
|
+++ b/lib/fencing/st_rhcs.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright 2004-2020 the Pacemaker project contributors
|
|
+ * Copyright 2004-2021 the Pacemaker project contributors
|
|
*
|
|
* The version control history for this file may have further details.
|
|
*
|
|
@@ -123,10 +123,10 @@ stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
|
|
static int
|
|
stonith__rhcs_get_metadata(const char *agent, int timeout, xmlNode **metadata)
|
|
{
|
|
- char *buffer = NULL;
|
|
xmlNode *xml = NULL;
|
|
xmlNode *actions = NULL;
|
|
xmlXPathObject *xpathObj = NULL;
|
|
+ pcmk__action_result_t *result = NULL;
|
|
stonith_action_t *action = stonith_action_create(agent, "metadata", NULL, 0,
|
|
5, NULL, NULL, NULL);
|
|
int rc = stonith__execute(action);
|
|
@@ -138,23 +138,31 @@ stonith__rhcs_get_metadata(const char *agent, int timeout, xmlNode **metadata)
|
|
return rc;
|
|
}
|
|
|
|
- stonith__action_result(action, &rc, &buffer, NULL);
|
|
- stonith__destroy_action(action);
|
|
- if (rc < 0) {
|
|
- crm_warn("Metadata action for %s failed: %s " CRM_XS "rc=%d",
|
|
- agent, pcmk_strerror(rc), rc);
|
|
- free(buffer);
|
|
- return rc;
|
|
+ result = stonith__action_result(action);
|
|
+
|
|
+ if (result->execution_status != PCMK_EXEC_DONE) {
|
|
+ crm_warn("Could not execute metadata action for %s: %s",
|
|
+ agent, pcmk_exec_status_str(result->execution_status));
|
|
+ stonith__destroy_action(action);
|
|
+ return pcmk_rc2legacy(stonith__result2rc(result));
|
|
}
|
|
|
|
- if (buffer == NULL) {
|
|
+ if (result->exit_status != CRM_EX_OK) {
|
|
+ crm_warn("Metadata action for %s returned error code %d",
|
|
+ agent, result->exit_status);
|
|
+ stonith__destroy_action(action);
|
|
+ return pcmk_rc2legacy(stonith__result2rc(result));
|
|
+ }
|
|
+
|
|
+ if (result->action_stdout == NULL) {
|
|
crm_warn("Metadata action for %s returned no data", agent);
|
|
+ stonith__destroy_action(action);
|
|
return -ENODATA;
|
|
}
|
|
|
|
- xml = string2xml(buffer);
|
|
- free(buffer);
|
|
- buffer = NULL;
|
|
+ xml = string2xml(result->action_stdout);
|
|
+ stonith__destroy_action(action);
|
|
+
|
|
if (xml == NULL) {
|
|
crm_warn("Metadata for %s is invalid", agent);
|
|
return -pcmk_err_schema_validation;
|
|
@@ -289,7 +297,19 @@ stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
|
|
|
|
rc = stonith__execute(action);
|
|
if (rc == pcmk_ok) {
|
|
- stonith__action_result(action, &rc, output, error_output);
|
|
+ pcmk__action_result_t *result = stonith__action_result(action);
|
|
+
|
|
+ rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
+
|
|
+ // Take ownership of output so stonith__destroy_action() doesn't free it
|
|
+ if (output != NULL) {
|
|
+ *output = result->action_stdout;
|
|
+ result->action_stdout = NULL;
|
|
+ }
|
|
+ if (error_output != NULL) {
|
|
+ *error_output = result->action_stderr;
|
|
+ result->action_stderr = NULL;
|
|
+ }
|
|
}
|
|
stonith__destroy_action(action);
|
|
return rc;
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 7f7067014357cccb229a0bef091e234eb3765f7a Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Tue, 21 Sep 2021 13:05:54 -0500
|
|
Subject: [PATCH 04/12] Refactor: fencing: pass full result to async action
|
|
callback
|
|
|
|
When executing an asynchronous fence agent command, the fencing library gets
|
|
the full result (exit status, execution status, and exit reason) from the
|
|
services library, then maps that to a legacy return code.
|
|
|
|
Now, pass the full result object to the fencing async callback, rather than
|
|
separate arguments for legacy code and stdout. The mapping to a legacy code now
|
|
happens in the fencer rather than the fencing library.
|
|
|
|
The goal of this and following commits is to push the full result object
|
|
further down the code path, so that ultimately the full result is always
|
|
available internally, and the legacy code mapping is only done for backward
|
|
compatibility when sending the result back to a client.
|
|
|
|
This commit focuses on the async callback (done_cb() in both the fencer's
|
|
async_command_t and the fencing library's stonith_action_t). Later commits will
|
|
follow the chain:
|
|
|
|
st_child_done() and stonith_fence_get_devices_cb()
|
|
-> stonith_send_async_reply()
|
|
-> stonith_construct_async_reply() and log_async_result()
|
|
---
|
|
daemons/fenced/fenced_commands.c | 78 +++++++++++++++++++++-----------
|
|
include/crm/fencing/internal.h | 3 +-
|
|
lib/fencing/st_client.c | 10 ++--
|
|
3 files changed, 58 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
|
index b5ae28d90..d5d04ae69 100644
|
|
--- a/daemons/fenced/fenced_commands.c
|
|
+++ b/daemons/fenced/fenced_commands.c
|
|
@@ -62,7 +62,8 @@ struct device_search_s {
|
|
};
|
|
|
|
static gboolean stonith_device_dispatch(gpointer user_data);
|
|
-static void st_child_done(int pid, int rc, const char *output, void *user_data);
|
|
+static void st_child_done(int pid, const pcmk__action_result_t *result,
|
|
+ void *user_data);
|
|
static void stonith_send_reply(xmlNode * reply, int call_options, const char *remote_peer,
|
|
const char *client_id);
|
|
|
|
@@ -99,7 +100,8 @@ typedef struct async_command_s {
|
|
GList *device_next;
|
|
|
|
void *internal_user_data;
|
|
- void (*done_cb) (int pid, int rc, const char *output, void *user_data);
|
|
+ void (*done_cb) (int pid, const pcmk__action_result_t *result,
|
|
+ void *user_data);
|
|
guint timer_sigterm;
|
|
guint timer_sigkill;
|
|
/*! If the operation timed out, this is the last signal
|
|
@@ -377,13 +379,25 @@ get_agent_metadata_cb(gpointer data) {
|
|
* \internal
|
|
* \brief Call a command's action callback for an internal (not library) result
|
|
*
|
|
- * \param[in] cmd Command to report result for
|
|
- * \param[in] rc Legacy return code to pass to callback
|
|
+ * \param[in] cmd Command to report result for
|
|
+ * \param[in] execution_status Execution status to use for result
|
|
+ * \param[in] exit_status Exit status to use for result
|
|
+ * \param[in] exit_reason Exit reason to use for result
|
|
*/
|
|
static void
|
|
-report_internal_result(async_command_t *cmd, int rc)
|
|
+report_internal_result(async_command_t *cmd, int exit_status,
|
|
+ int execution_status, const char *exit_reason)
|
|
{
|
|
- cmd->done_cb(0, rc, NULL, cmd);
|
|
+ pcmk__action_result_t result = {
|
|
+ // Ensure we don't pass garbage to free()
|
|
+ .exit_reason = NULL,
|
|
+ .action_stdout = NULL,
|
|
+ .action_stderr = NULL
|
|
+ };
|
|
+
|
|
+ pcmk__set_result(&result, exit_status, execution_status, exit_reason);
|
|
+ cmd->done_cb(0, &result, cmd);
|
|
+ pcmk__reset_result(&result);
|
|
}
|
|
|
|
static gboolean
|
|
@@ -446,7 +460,7 @@ stonith_device_execute(stonith_device_t * device)
|
|
}
|
|
} else {
|
|
crm_info("Faking success for %s watchdog operation", cmd->action);
|
|
- report_internal_result(cmd, pcmk_ok);
|
|
+ report_internal_result(cmd, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
|
|
goto done;
|
|
}
|
|
}
|
|
@@ -462,7 +476,8 @@ stonith_device_execute(stonith_device_t * device)
|
|
crm_err("Considering %s unconfigured "
|
|
"because unable to load CIB secrets: %s",
|
|
device->id, pcmk_rc_str(exec_rc));
|
|
- report_internal_result(cmd, -EACCES);
|
|
+ report_internal_result(cmd, CRM_EX_ERROR, PCMK_EXEC_NO_SECRETS,
|
|
+ NULL);
|
|
goto done;
|
|
}
|
|
}
|
|
@@ -501,7 +516,7 @@ stonith_device_execute(stonith_device_t * device)
|
|
cmd->done_cb, fork_cb);
|
|
if (exec_rc < 0) {
|
|
cmd->activating_on = NULL;
|
|
- report_internal_result(cmd, exec_rc);
|
|
+ cmd->done_cb(0, stonith__action_result(action), cmd);
|
|
stonith__destroy_action(action);
|
|
}
|
|
|
|
@@ -625,7 +640,8 @@ free_device(gpointer data)
|
|
async_command_t *cmd = gIter->data;
|
|
|
|
crm_warn("Removal of device '%s' purged operation '%s'", device->id, cmd->action);
|
|
- report_internal_result(cmd, -ENODEV);
|
|
+ report_internal_result(cmd, CRM_EX_ERROR, PCMK_EXEC_NO_FENCE_DEVICE,
|
|
+ NULL);
|
|
}
|
|
g_list_free(device->pending_ops);
|
|
|
|
@@ -1079,7 +1095,8 @@ schedule_internal_command(const char *origin,
|
|
const char *victim,
|
|
int timeout,
|
|
void *internal_user_data,
|
|
- void (*done_cb) (int pid, int rc, const char *output,
|
|
+ void (*done_cb) (int pid,
|
|
+ const pcmk__action_result_t *result,
|
|
void *user_data))
|
|
{
|
|
async_command_t *cmd = NULL;
|
|
@@ -1111,7 +1128,7 @@ enum fence_status_code {
|
|
};
|
|
|
|
static void
|
|
-status_search_cb(int pid, int rc, const char *output, void *user_data)
|
|
+status_search_cb(int pid, const pcmk__action_result_t *result, void *user_data)
|
|
{
|
|
async_command_t *cmd = user_data;
|
|
struct device_search_s *search = cmd->internal_user_data;
|
|
@@ -1127,7 +1144,7 @@ status_search_cb(int pid, int rc, const char *output, void *user_data)
|
|
|
|
mainloop_set_trigger(dev->work);
|
|
|
|
- switch (rc) {
|
|
+ switch (result->exit_status) {
|
|
case fence_status_unknown:
|
|
crm_trace("%s reported it cannot fence %s", dev->id, search->host);
|
|
break;
|
|
@@ -1141,14 +1158,15 @@ status_search_cb(int pid, int rc, const char *output, void *user_data)
|
|
default:
|
|
crm_warn("Assuming %s cannot fence %s "
|
|
"(status returned unknown code %d)",
|
|
- dev->id, search->host, rc);
|
|
+ dev->id, search->host, result->exit_status);
|
|
break;
|
|
}
|
|
search_devices_record_result(search, dev->id, can);
|
|
}
|
|
|
|
static void
|
|
-dynamic_list_search_cb(int pid, int rc, const char *output, void *user_data)
|
|
+dynamic_list_search_cb(int pid, const pcmk__action_result_t *result,
|
|
+ void *user_data)
|
|
{
|
|
async_command_t *cmd = user_data;
|
|
struct device_search_s *search = cmd->internal_user_data;
|
|
@@ -1169,21 +1187,21 @@ dynamic_list_search_cb(int pid, int rc, const char *output, void *user_data)
|
|
|
|
mainloop_set_trigger(dev->work);
|
|
|
|
- if (rc == CRM_EX_OK) {
|
|
+ if (result->exit_status == CRM_EX_OK) {
|
|
crm_info("Refreshing target list for %s", dev->id);
|
|
g_list_free_full(dev->targets, free);
|
|
- dev->targets = stonith__parse_targets(output);
|
|
+ dev->targets = stonith__parse_targets(result->action_stdout);
|
|
dev->targets_age = time(NULL);
|
|
|
|
} else if (dev->targets != NULL) {
|
|
crm_info("Reusing most recent target list for %s "
|
|
"because list returned error code %d",
|
|
- dev->id, rc);
|
|
+ dev->id, result->exit_status);
|
|
|
|
} else { // We have never successfully executed list
|
|
crm_warn("Assuming %s cannot fence %s "
|
|
"because list returned error code %d",
|
|
- dev->id, search->host, rc);
|
|
+ dev->id, search->host, result->exit_status);
|
|
|
|
/* Fall back to pcmk_host_check="status" if the user didn't explicitly
|
|
* specify "dynamic-list".
|
|
@@ -2407,7 +2425,7 @@ cancel_stonith_command(async_command_t * cmd)
|
|
}
|
|
|
|
static void
|
|
-st_child_done(int pid, int rc, const char *output, void *user_data)
|
|
+st_child_done(int pid, const pcmk__action_result_t *result, void *user_data)
|
|
{
|
|
stonith_device_t *device = NULL;
|
|
stonith_device_t *next_device = NULL;
|
|
@@ -2423,7 +2441,7 @@ st_child_done(int pid, int rc, const char *output, void *user_data)
|
|
/* The device is ready to do something else now */
|
|
device = g_hash_table_lookup(device_list, cmd->device);
|
|
if (device) {
|
|
- if (!device->verified && (rc == pcmk_ok) &&
|
|
+ if (!device->verified && (result->exit_status == CRM_EX_OK) &&
|
|
(pcmk__strcase_any_of(cmd->action, "list", "monitor", "status", NULL))) {
|
|
|
|
device->verified = TRUE;
|
|
@@ -2432,7 +2450,7 @@ st_child_done(int pid, int rc, const char *output, void *user_data)
|
|
mainloop_set_trigger(device->work);
|
|
}
|
|
|
|
- if (rc == 0) {
|
|
+ if (result->exit_status == CRM_EX_OK) {
|
|
GList *iter;
|
|
/* see if there are any required devices left to execute for this op */
|
|
for (iter = cmd->device_next; iter != NULL; iter = iter->next) {
|
|
@@ -2445,7 +2463,8 @@ st_child_done(int pid, int rc, const char *output, void *user_data)
|
|
next_device = NULL;
|
|
}
|
|
|
|
- } else if (rc != 0 && cmd->device_next && (is_action_required(cmd->action, device) == FALSE)) {
|
|
+ } else if ((cmd->device_next != NULL)
|
|
+ && !is_action_required(cmd->action, device)) {
|
|
/* if this device didn't work out, see if there are any others we can try.
|
|
* if the failed device was 'required', we can't pick another device. */
|
|
next_device = g_hash_table_lookup(device_list, cmd->device_next->data);
|
|
@@ -2454,16 +2473,19 @@ st_child_done(int pid, int rc, const char *output, void *user_data)
|
|
|
|
/* this operation requires more fencing, hooray! */
|
|
if (next_device) {
|
|
- log_async_result(cmd, rc, pid, next_device->id, output, FALSE);
|
|
+ log_async_result(cmd, pcmk_rc2legacy(stonith__result2rc(result)), pid,
|
|
+ next_device->id, result->action_stdout, FALSE);
|
|
schedule_stonith_command(cmd, next_device);
|
|
/* Prevent cmd from being freed */
|
|
cmd = NULL;
|
|
goto done;
|
|
}
|
|
|
|
- stonith_send_async_reply(cmd, output, rc, pid, false);
|
|
+ stonith_send_async_reply(cmd, result->action_stdout,
|
|
+ pcmk_rc2legacy(stonith__result2rc(result)), pid,
|
|
+ false);
|
|
|
|
- if (rc != 0) {
|
|
+ if (result->exit_status != CRM_EX_OK) {
|
|
goto done;
|
|
}
|
|
|
|
@@ -2509,7 +2531,9 @@ st_child_done(int pid, int rc, const char *output, void *user_data)
|
|
|
|
cmd_list = g_list_remove_link(cmd_list, gIter);
|
|
|
|
- stonith_send_async_reply(cmd_other, output, rc, pid, true);
|
|
+ stonith_send_async_reply(cmd_other, result->action_stdout,
|
|
+ pcmk_rc2legacy(stonith__result2rc(result)),
|
|
+ pid, true);
|
|
cancel_stonith_command(cmd_other);
|
|
|
|
free_async_command(cmd_other);
|
|
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
|
|
index 4e9f50fe8..6a7e4232c 100644
|
|
--- a/include/crm/fencing/internal.h
|
|
+++ b/include/crm/fencing/internal.h
|
|
@@ -64,7 +64,8 @@ int stonith__result2rc(const pcmk__action_result_t *result);
|
|
int
|
|
stonith_action_execute_async(stonith_action_t * action,
|
|
void *userdata,
|
|
- void (*done) (int pid, int rc, const char *output,
|
|
+ void (*done) (int pid,
|
|
+ const pcmk__action_result_t *result,
|
|
void *user_data),
|
|
void (*fork_cb) (int pid, void *user_data));
|
|
|
|
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
index b9df18465..59dcab9a3 100644
|
|
--- a/lib/fencing/st_client.c
|
|
+++ b/lib/fencing/st_client.c
|
|
@@ -46,7 +46,8 @@ struct stonith_action_s {
|
|
int timeout;
|
|
int async;
|
|
void *userdata;
|
|
- void (*done_cb) (int pid, int status, const char *output, void *user_data);
|
|
+ void (*done_cb) (int pid, const pcmk__action_result_t *result,
|
|
+ void *user_data);
|
|
void (*fork_cb) (int pid, void *user_data);
|
|
|
|
svc_action_t *svc_action;
|
|
@@ -811,9 +812,7 @@ stonith_action_async_done(svc_action_t *svc_action)
|
|
}
|
|
|
|
if (action->done_cb) {
|
|
- action->done_cb(action->pid,
|
|
- pcmk_rc2legacy(stonith__result2rc(&(action->result))),
|
|
- action->result.action_stdout, action->userdata);
|
|
+ action->done_cb(action->pid, &(action->result), action->userdata);
|
|
}
|
|
|
|
action->svc_action = NULL; // don't remove our caller
|
|
@@ -933,7 +932,8 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
int
|
|
stonith_action_execute_async(stonith_action_t * action,
|
|
void *userdata,
|
|
- void (*done) (int pid, int rc, const char *output,
|
|
+ void (*done) (int pid,
|
|
+ const pcmk__action_result_t *result,
|
|
void *user_data),
|
|
void (*fork_cb) (int pid, void *user_data))
|
|
{
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From bbd022306df7a873c0ecb2be2d33c56fbf327b8c Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Tue, 21 Sep 2021 11:51:28 -0500
|
|
Subject: [PATCH 05/12] Feature: fencing: set exit reason for internal
|
|
execution errors
|
|
|
|
... most importantly, copying any exit reason set by the services library.
|
|
This ensures that the stonith_action_t exit reason is set when appropriate.
|
|
However, nothing uses it as of this commit.
|
|
---
|
|
daemons/fenced/fenced_commands.c | 4 ++--
|
|
lib/fencing/st_client.c | 6 +++---
|
|
2 files changed, 5 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
|
index d5d04ae69..f55a32649 100644
|
|
--- a/daemons/fenced/fenced_commands.c
|
|
+++ b/daemons/fenced/fenced_commands.c
|
|
@@ -477,7 +477,7 @@ stonith_device_execute(stonith_device_t * device)
|
|
"because unable to load CIB secrets: %s",
|
|
device->id, pcmk_rc_str(exec_rc));
|
|
report_internal_result(cmd, CRM_EX_ERROR, PCMK_EXEC_NO_SECRETS,
|
|
- NULL);
|
|
+ "Failed to get CIB secrets");
|
|
goto done;
|
|
}
|
|
}
|
|
@@ -641,7 +641,7 @@ free_device(gpointer data)
|
|
|
|
crm_warn("Removal of device '%s' purged operation '%s'", device->id, cmd->action);
|
|
report_internal_result(cmd, CRM_EX_ERROR, PCMK_EXEC_NO_FENCE_DEVICE,
|
|
- NULL);
|
|
+ "Device was removed before action could be executed");
|
|
}
|
|
g_list_free(device->pending_ops);
|
|
|
|
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
index 59dcab9a3..3d4127eff 100644
|
|
--- a/lib/fencing/st_client.c
|
|
+++ b/lib/fencing/st_client.c
|
|
@@ -207,7 +207,7 @@ static void
|
|
set_result_from_svc_action(stonith_action_t *action, svc_action_t *svc_action)
|
|
{
|
|
pcmk__set_result(&(action->result), svc_action->rc, svc_action->status,
|
|
- NULL);
|
|
+ services__exit_reason(svc_action));
|
|
pcmk__set_result_output(&(action->result),
|
|
services__grab_stdout(svc_action),
|
|
services__grab_stderr(svc_action));
|
|
@@ -706,7 +706,7 @@ stonith_action_create(const char *agent,
|
|
action->max_retries = FAILURE_MAX_RETRIES;
|
|
|
|
pcmk__set_result(&(action->result), PCMK_OCF_UNKNOWN, PCMK_EXEC_UNKNOWN,
|
|
- NULL);
|
|
+ "Initialization bug in fencing library");
|
|
|
|
if (device_args) {
|
|
char buffer[512];
|
|
@@ -849,7 +849,7 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
if ((action->action == NULL) || (action->args == NULL)
|
|
|| (action->agent == NULL)) {
|
|
pcmk__set_result(&(action->result), PCMK_OCF_UNKNOWN_ERROR,
|
|
- PCMK_EXEC_ERROR_FATAL, NULL);
|
|
+ PCMK_EXEC_ERROR_FATAL, "Bug in fencing library");
|
|
return -EINVAL;
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From ed08f600688af1d25412d2427502ba5d4a55c0d6 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Thu, 7 Oct 2021 12:06:10 -0500
|
|
Subject: [PATCH 06/12] Fix: fencer: handle dynamic target query failures
|
|
better
|
|
|
|
Previously, the callbacks for list and status queries checked only the result's
|
|
exit status. However, the services library will use PCMK_OCF_UNKNOWN_ERROR (1)
|
|
as the exit status for internal failures, and that value signifies a recognized
|
|
node (not an error) for fence list actions.
|
|
|
|
Now, the callbacks check the execution status as well.
|
|
---
|
|
daemons/fenced/fenced_commands.c | 46 +++++++++++++++++++++++++++-----
|
|
1 file changed, 39 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
|
index f55a32649..7b3fb25a1 100644
|
|
--- a/daemons/fenced/fenced_commands.c
|
|
+++ b/daemons/fenced/fenced_commands.c
|
|
@@ -1144,6 +1144,18 @@ status_search_cb(int pid, const pcmk__action_result_t *result, void *user_data)
|
|
|
|
mainloop_set_trigger(dev->work);
|
|
|
|
+ if (result->execution_status != PCMK_EXEC_DONE) {
|
|
+ crm_warn("Assuming %s cannot fence %s "
|
|
+ "because status could not be executed: %s%s%s%s",
|
|
+ dev->id, search->host,
|
|
+ pcmk_exec_status_str(result->execution_status),
|
|
+ ((result->exit_reason == NULL)? "" : " ("),
|
|
+ ((result->exit_reason == NULL)? "" : result->exit_reason),
|
|
+ ((result->exit_reason == NULL)? "" : ")"));
|
|
+ search_devices_record_result(search, dev->id, FALSE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
switch (result->exit_status) {
|
|
case fence_status_unknown:
|
|
crm_trace("%s reported it cannot fence %s", dev->id, search->host);
|
|
@@ -1187,21 +1199,41 @@ dynamic_list_search_cb(int pid, const pcmk__action_result_t *result,
|
|
|
|
mainloop_set_trigger(dev->work);
|
|
|
|
- if (result->exit_status == CRM_EX_OK) {
|
|
+ if ((result->execution_status == PCMK_EXEC_DONE)
|
|
+ && (result->exit_status == CRM_EX_OK)) {
|
|
crm_info("Refreshing target list for %s", dev->id);
|
|
g_list_free_full(dev->targets, free);
|
|
dev->targets = stonith__parse_targets(result->action_stdout);
|
|
dev->targets_age = time(NULL);
|
|
|
|
} else if (dev->targets != NULL) {
|
|
- crm_info("Reusing most recent target list for %s "
|
|
- "because list returned error code %d",
|
|
- dev->id, result->exit_status);
|
|
+ if (result->execution_status == PCMK_EXEC_DONE) {
|
|
+ crm_info("Reusing most recent target list for %s "
|
|
+ "because list returned error code %d",
|
|
+ dev->id, result->exit_status);
|
|
+ } else {
|
|
+ crm_info("Reusing most recent target list for %s "
|
|
+ "because list could not be executed: %s%s%s%s",
|
|
+ dev->id, pcmk_exec_status_str(result->execution_status),
|
|
+ ((result->exit_reason == NULL)? "" : " ("),
|
|
+ ((result->exit_reason == NULL)? "" : result->exit_reason),
|
|
+ ((result->exit_reason == NULL)? "" : ")"));
|
|
+ }
|
|
|
|
} else { // We have never successfully executed list
|
|
- crm_warn("Assuming %s cannot fence %s "
|
|
- "because list returned error code %d",
|
|
- dev->id, search->host, result->exit_status);
|
|
+ if (result->execution_status == PCMK_EXEC_DONE) {
|
|
+ crm_warn("Assuming %s cannot fence %s "
|
|
+ "because list returned error code %d",
|
|
+ dev->id, search->host, result->exit_status);
|
|
+ } else {
|
|
+ crm_warn("Assuming %s cannot fence %s "
|
|
+ "because list could not be executed: %s%s%s%s",
|
|
+ dev->id, search->host,
|
|
+ pcmk_exec_status_str(result->execution_status),
|
|
+ ((result->exit_reason == NULL)? "" : " ("),
|
|
+ ((result->exit_reason == NULL)? "" : result->exit_reason),
|
|
+ ((result->exit_reason == NULL)? "" : ")"));
|
|
+ }
|
|
|
|
/* Fall back to pcmk_host_check="status" if the user didn't explicitly
|
|
* specify "dynamic-list".
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 5a30238a3b8691a5fc20f53906c0efcc50193306 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Tue, 21 Sep 2021 15:57:50 -0500
|
|
Subject: [PATCH 07/12] Refactor: fencer: pass result object when sending an
|
|
async reply
|
|
|
|
... via stonith_send_async_reply(), instead of sending the mapped legacy code
|
|
and action stdout separately. Also, drop the "stonith_" prefix since the
|
|
function is static.
|
|
|
|
This moves the mapping from the stonith_send_async_reply() callers to the
|
|
function itself, so we use the result object and standard codes as long as
|
|
possible, and map to a legacy code only where needed.
|
|
---
|
|
daemons/fenced/fenced_commands.c | 62 +++++++++++++++++++-------------
|
|
daemons/fenced/fenced_remote.c | 2 +-
|
|
2 files changed, 39 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
|
index 7b3fb25a1..e5f8162ce 100644
|
|
--- a/daemons/fenced/fenced_commands.c
|
|
+++ b/daemons/fenced/fenced_commands.c
|
|
@@ -2376,12 +2376,28 @@ log_async_result(async_command_t *cmd, int rc, int pid, const char *next,
|
|
}
|
|
}
|
|
|
|
+/*!
|
|
+ * \internal
|
|
+ * \brief Reply to requester after asynchronous command completion
|
|
+ *
|
|
+ * \param[in] cmd Command that completed
|
|
+ * \param[in] result Result of command
|
|
+ * \param[in] pid Process ID of command, if available
|
|
+ * \param[in] merged If true, command was merged with another, not executed
|
|
+ */
|
|
static void
|
|
-stonith_send_async_reply(async_command_t *cmd, const char *output, int rc,
|
|
- int pid, bool merged)
|
|
+send_async_reply(async_command_t *cmd, const pcmk__action_result_t *result,
|
|
+ int pid, bool merged)
|
|
{
|
|
xmlNode *reply = NULL;
|
|
gboolean bcast = FALSE;
|
|
+ const char *output = NULL;
|
|
+ int rc = pcmk_ok;
|
|
+
|
|
+ CRM_CHECK((cmd != NULL) && (result != NULL), return);
|
|
+
|
|
+ output = result->action_stdout;
|
|
+ rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
|
|
reply = stonith_construct_async_reply(cmd, output, NULL, rc);
|
|
|
|
@@ -2513,9 +2529,7 @@ st_child_done(int pid, const pcmk__action_result_t *result, void *user_data)
|
|
goto done;
|
|
}
|
|
|
|
- stonith_send_async_reply(cmd, result->action_stdout,
|
|
- pcmk_rc2legacy(stonith__result2rc(result)), pid,
|
|
- false);
|
|
+ send_async_reply(cmd, result, pid, false);
|
|
|
|
if (result->exit_status != CRM_EX_OK) {
|
|
goto done;
|
|
@@ -2563,9 +2577,7 @@ st_child_done(int pid, const pcmk__action_result_t *result, void *user_data)
|
|
|
|
cmd_list = g_list_remove_link(cmd_list, gIter);
|
|
|
|
- stonith_send_async_reply(cmd_other, result->action_stdout,
|
|
- pcmk_rc2legacy(stonith__result2rc(result)),
|
|
- pid, true);
|
|
+ send_async_reply(cmd_other, result, pid, true);
|
|
cancel_stonith_command(cmd_other);
|
|
|
|
free_async_command(cmd_other);
|
|
@@ -2604,26 +2616,28 @@ stonith_fence_get_devices_cb(GList * devices, void *user_data)
|
|
/* Order based on priority */
|
|
devices = g_list_sort(devices, sort_device_priority);
|
|
device = g_hash_table_lookup(device_list, devices->data);
|
|
-
|
|
- if (device) {
|
|
- cmd->device_list = devices;
|
|
- cmd->device_next = devices->next;
|
|
- devices = NULL; /* list owned by cmd now */
|
|
- }
|
|
}
|
|
|
|
- /* we have a device, schedule it for fencing. */
|
|
- if (device) {
|
|
- schedule_stonith_command(cmd, device);
|
|
- /* in progress */
|
|
- return;
|
|
- }
|
|
+ if (device == NULL) { // No device found
|
|
+ pcmk__action_result_t result = {
|
|
+ // Ensure we don't pass garbage to free()
|
|
+ .exit_reason = NULL,
|
|
+ .action_stdout = NULL,
|
|
+ .action_stderr = NULL
|
|
+ };
|
|
|
|
- /* no device found! */
|
|
- stonith_send_async_reply(cmd, NULL, -ENODEV, 0, false);
|
|
+ pcmk__set_result(&result, CRM_EX_ERROR, PCMK_EXEC_NO_FENCE_DEVICE,
|
|
+ "No fence device configured for target");
|
|
+ send_async_reply(cmd, &result, 0, false);
|
|
+ pcmk__reset_result(&result);
|
|
+ free_async_command(cmd);
|
|
+ g_list_free_full(devices, free);
|
|
|
|
- free_async_command(cmd);
|
|
- g_list_free_full(devices, free);
|
|
+ } else { // Device found, schedule it for fencing
|
|
+ cmd->device_list = devices;
|
|
+ cmd->device_next = devices->next;
|
|
+ schedule_stonith_command(cmd, device);
|
|
+ }
|
|
}
|
|
|
|
static int
|
|
diff --git a/daemons/fenced/fenced_remote.c b/daemons/fenced/fenced_remote.c
|
|
index ffaf60018..b09d2865e 100644
|
|
--- a/daemons/fenced/fenced_remote.c
|
|
+++ b/daemons/fenced/fenced_remote.c
|
|
@@ -996,7 +996,7 @@ stonith_manual_ack(xmlNode * msg, remote_fencing_op_t * op)
|
|
|
|
remote_op_done(op, msg, pcmk_ok, FALSE);
|
|
|
|
- /* Replies are sent via done_cb->stonith_send_async_reply()->do_local_reply() */
|
|
+ // Replies are sent via done_cb -> send_async_reply() -> do_local_reply()
|
|
return -EINPROGRESS;
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From c67b6bfbe0baa1253058417ddfb9bc4cf0844e27 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Thu, 7 Oct 2021 17:25:38 -0500
|
|
Subject: [PATCH 08/12] Refactor: fencer: pass result object when building
|
|
async reply
|
|
|
|
... via stonith_construct_async_reply(), instead of passing a mapped legacy rc
|
|
and action output separately, which will be helpful when we add the exit reason
|
|
to the reply. Also, drop the "stonith_" prefix since the function is static, and
|
|
drop an unused argument.
|
|
---
|
|
daemons/fenced/fenced_commands.c | 33 +++++++++++++++-----------------
|
|
1 file changed, 15 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
|
index e5f8162ce..6bc12e6c4 100644
|
|
--- a/daemons/fenced/fenced_commands.c
|
|
+++ b/daemons/fenced/fenced_commands.c
|
|
@@ -112,8 +112,8 @@ typedef struct async_command_s {
|
|
stonith_device_t *activating_on;
|
|
} async_command_t;
|
|
|
|
-static xmlNode *stonith_construct_async_reply(async_command_t * cmd, const char *output,
|
|
- xmlNode * data, int rc);
|
|
+static xmlNode *construct_async_reply(async_command_t *cmd,
|
|
+ const pcmk__action_result_t *result);
|
|
|
|
static gboolean
|
|
is_action_required(const char *action, stonith_device_t *device)
|
|
@@ -2399,7 +2399,7 @@ send_async_reply(async_command_t *cmd, const pcmk__action_result_t *result,
|
|
output = result->action_stdout;
|
|
rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
|
|
- reply = stonith_construct_async_reply(cmd, output, NULL, rc);
|
|
+ reply = construct_async_reply(cmd, result);
|
|
|
|
// Only replies for certain actions are broadcast
|
|
if (pcmk__str_any_of(cmd->action, "metadata", "monitor", "list", "status",
|
|
@@ -2732,17 +2732,20 @@ stonith_construct_reply(xmlNode * request, const char *output, xmlNode * data, i
|
|
return reply;
|
|
}
|
|
|
|
+/*!
|
|
+ * \internal
|
|
+ * \brief Build an XML reply to an asynchronous fencing command
|
|
+ *
|
|
+ * \param[in] cmd Fencing command that reply is for
|
|
+ * \param[in] result Command result
|
|
+ */
|
|
static xmlNode *
|
|
-stonith_construct_async_reply(async_command_t * cmd, const char *output, xmlNode * data, int rc)
|
|
+construct_async_reply(async_command_t *cmd, const pcmk__action_result_t *result)
|
|
{
|
|
- xmlNode *reply = NULL;
|
|
-
|
|
- crm_trace("Creating a basic reply");
|
|
- reply = create_xml_node(NULL, T_STONITH_REPLY);
|
|
+ xmlNode *reply = create_xml_node(NULL, T_STONITH_REPLY);
|
|
|
|
crm_xml_add(reply, "st_origin", __func__);
|
|
crm_xml_add(reply, F_TYPE, T_STONITH_NG);
|
|
-
|
|
crm_xml_add(reply, F_STONITH_OPERATION, cmd->op);
|
|
crm_xml_add(reply, F_STONITH_DEVICE, cmd->device);
|
|
crm_xml_add(reply, F_STONITH_REMOTE_OP_ID, cmd->remote_op_id);
|
|
@@ -2753,15 +2756,9 @@ stonith_construct_async_reply(async_command_t * cmd, const char *output, xmlNode
|
|
crm_xml_add(reply, F_STONITH_ORIGIN, cmd->origin);
|
|
crm_xml_add_int(reply, F_STONITH_CALLID, cmd->id);
|
|
crm_xml_add_int(reply, F_STONITH_CALLOPTS, cmd->options);
|
|
-
|
|
- crm_xml_add_int(reply, F_STONITH_RC, rc);
|
|
-
|
|
- crm_xml_add(reply, "st_output", output);
|
|
-
|
|
- if (data != NULL) {
|
|
- crm_info("Attaching reply output");
|
|
- add_message_xml(reply, F_STONITH_CALLDATA, data);
|
|
- }
|
|
+ crm_xml_add_int(reply, F_STONITH_RC,
|
|
+ pcmk_rc2legacy(stonith__result2rc(result)));
|
|
+ crm_xml_add(reply, "st_output", result->action_stdout);
|
|
return reply;
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 2686caeb3b74f687ddd86a4e483250ca8096ba7c Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Tue, 19 Oct 2021 18:27:31 -0500
|
|
Subject: [PATCH 09/12] Log: fencer: improve messages for asynchronous results
|
|
|
|
Now that we have the full result object, pass it to log_async_result().
|
|
Instead of logging a mapped legacy rc, log the execution status or exit status
|
|
as appropriate, along with the exit reason.
|
|
---
|
|
daemons/fenced/fenced_commands.c | 43 +++++++++++++++++---------------
|
|
1 file changed, 23 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
|
index 6bc12e6c4..9d06c68dc 100644
|
|
--- a/daemons/fenced/fenced_commands.c
|
|
+++ b/daemons/fenced/fenced_commands.c
|
|
@@ -2305,15 +2305,14 @@ stonith_query(xmlNode * msg, const char *remote_peer, const char *client_id, int
|
|
* \brief Log the result of an asynchronous command
|
|
*
|
|
* \param[in] cmd Command the result is for
|
|
- * \param[in] rc Legacy return code corresponding to result
|
|
+ * \param[in] result Result of command
|
|
* \param[in] pid Process ID of command, if available
|
|
* \param[in] next Alternate device that will be tried if command failed
|
|
- * \param[in] output Command output, if any
|
|
* \param[in] op_merged Whether this command was merged with an earlier one
|
|
*/
|
|
static void
|
|
-log_async_result(async_command_t *cmd, int rc, int pid, const char *next,
|
|
- const char *output, gboolean op_merged)
|
|
+log_async_result(async_command_t *cmd, const pcmk__action_result_t *result,
|
|
+ int pid, const char *next, bool op_merged)
|
|
{
|
|
int log_level = LOG_ERR;
|
|
int output_log_level = LOG_NEVER;
|
|
@@ -2321,17 +2320,18 @@ log_async_result(async_command_t *cmd, int rc, int pid, const char *next,
|
|
|
|
GString *msg = g_string_sized_new(80); // Reasonable starting size
|
|
|
|
- // Choose log levels appropriately
|
|
- if (rc == 0) { // Success
|
|
+ // Choose log levels appropriately if we have a result
|
|
+ if ((result->execution_status == PCMK_EXEC_DONE)
|
|
+ && (result->exit_status == CRM_EX_OK)) { // Success
|
|
log_level = (cmd->victim == NULL)? LOG_DEBUG : LOG_NOTICE;
|
|
- if ((output != NULL)
|
|
+ if ((result->action_stdout != NULL)
|
|
&& !pcmk__str_eq(cmd->action, "metadata", pcmk__str_casei)) {
|
|
output_log_level = LOG_DEBUG;
|
|
}
|
|
next = NULL;
|
|
} else { // Failure
|
|
log_level = (cmd->victim == NULL)? LOG_NOTICE : LOG_ERR;
|
|
- if ((output != NULL)
|
|
+ if ((result->action_stdout != NULL)
|
|
&& !pcmk__str_eq(cmd->action, "metadata", pcmk__str_casei)) {
|
|
output_log_level = LOG_WARNING;
|
|
}
|
|
@@ -2347,10 +2347,18 @@ log_async_result(async_command_t *cmd, int rc, int pid, const char *next,
|
|
}
|
|
g_string_append_printf(msg, "using %s ", cmd->device);
|
|
|
|
- // Add result
|
|
- g_string_append_printf(msg, "returned %d (%s)", rc, pcmk_strerror(rc));
|
|
+ // Add exit status or execution status as appropriate
|
|
+ if (result->execution_status == PCMK_EXEC_DONE) {
|
|
+ g_string_append_printf(msg, "returned %d", result->exit_status);
|
|
+ } else {
|
|
+ g_string_append_printf(msg, "could not be executed: %s",
|
|
+ pcmk_exec_status_str(result->execution_status));
|
|
+ }
|
|
|
|
- // Add next device if appropriate
|
|
+ // Add exit reason and next device if appropriate
|
|
+ if (result->exit_reason != NULL) {
|
|
+ g_string_append_printf(msg, " (%s)", result->exit_reason);
|
|
+ }
|
|
if (next != NULL) {
|
|
g_string_append_printf(msg, ", retrying with %s", next);
|
|
}
|
|
@@ -2371,7 +2379,7 @@ log_async_result(async_command_t *cmd, int rc, int pid, const char *next,
|
|
if (output_log_level != LOG_NEVER) {
|
|
char *prefix = crm_strdup_printf("%s[%d]", cmd->device, pid);
|
|
|
|
- crm_log_output(output_log_level, prefix, output);
|
|
+ crm_log_output(output_log_level, prefix, result->action_stdout);
|
|
free(prefix);
|
|
}
|
|
}
|
|
@@ -2391,14 +2399,9 @@ send_async_reply(async_command_t *cmd, const pcmk__action_result_t *result,
|
|
{
|
|
xmlNode *reply = NULL;
|
|
gboolean bcast = FALSE;
|
|
- const char *output = NULL;
|
|
- int rc = pcmk_ok;
|
|
|
|
CRM_CHECK((cmd != NULL) && (result != NULL), return);
|
|
|
|
- output = result->action_stdout;
|
|
- rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
-
|
|
reply = construct_async_reply(cmd, result);
|
|
|
|
// Only replies for certain actions are broadcast
|
|
@@ -2412,7 +2415,7 @@ send_async_reply(async_command_t *cmd, const pcmk__action_result_t *result,
|
|
bcast = TRUE;
|
|
}
|
|
|
|
- log_async_result(cmd, rc, pid, NULL, output, merged);
|
|
+ log_async_result(cmd, result, pid, NULL, merged);
|
|
crm_log_xml_trace(reply, "Reply");
|
|
|
|
if (merged) {
|
|
@@ -2436,6 +2439,7 @@ send_async_reply(async_command_t *cmd, const pcmk__action_result_t *result,
|
|
if (stand_alone) {
|
|
/* Do notification with a clean data object */
|
|
xmlNode *notify_data = create_xml_node(NULL, T_STONITH_NOTIFY_FENCE);
|
|
+ int rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
|
|
crm_xml_add_int(notify_data, F_STONITH_RC, rc);
|
|
crm_xml_add(notify_data, F_STONITH_TARGET, cmd->victim);
|
|
@@ -2521,8 +2525,7 @@ st_child_done(int pid, const pcmk__action_result_t *result, void *user_data)
|
|
|
|
/* this operation requires more fencing, hooray! */
|
|
if (next_device) {
|
|
- log_async_result(cmd, pcmk_rc2legacy(stonith__result2rc(result)), pid,
|
|
- next_device->id, result->action_stdout, FALSE);
|
|
+ log_async_result(cmd, result, pid, next_device->id, false);
|
|
schedule_stonith_command(cmd, next_device);
|
|
/* Prevent cmd from being freed */
|
|
cmd = NULL;
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 9f9dea518da50f629589d505ea0f330a47111d76 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Thu, 28 Oct 2021 13:29:31 -0500
|
|
Subject: [PATCH 10/12] Test: cts-fencing: update expected log messages
|
|
|
|
... which now log the original exit status rather than a mapped legacy rc
|
|
---
|
|
cts/cts-fencing.in | 28 ++++++++++++++--------------
|
|
1 file changed, 14 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/cts/cts-fencing.in b/cts/cts-fencing.in
|
|
index babfb6351..5cd9f7b8f 100644
|
|
--- a/cts/cts-fencing.in
|
|
+++ b/cts/cts-fencing.in
|
|
@@ -886,7 +886,7 @@ class Tests(object):
|
|
test.add_cmd("stonith_admin", "--output-as=xml -F node3 -t 20")
|
|
|
|
test.add_stonith_log_pattern("Total timeout set to 40")
|
|
- test.add_stonith_log_pattern("targeting node3 using false returned -201")
|
|
+ test.add_stonith_log_pattern("targeting node3 using false returned 1")
|
|
test.add_stonith_log_pattern("targeting node3 using true returned 0")
|
|
|
|
# test what happens when the first fencing level fails.
|
|
@@ -920,8 +920,8 @@ class Tests(object):
|
|
test.add_cmd("stonith_admin", "--output-as=xml -F node3 -t 3")
|
|
|
|
test.add_stonith_log_pattern("Total timeout set to 18")
|
|
- test.add_stonith_log_pattern("targeting node3 using false1 returned -201")
|
|
- test.add_stonith_log_pattern("targeting node3 using false2 returned -201")
|
|
+ test.add_stonith_log_pattern("targeting node3 using false1 returned 1")
|
|
+ test.add_stonith_log_pattern("targeting node3 using false2 returned 1")
|
|
test.add_stonith_log_pattern("targeting node3 using true3 returned 0")
|
|
test.add_stonith_log_pattern("targeting node3 using true4 returned 0")
|
|
|
|
@@ -987,7 +987,7 @@ class Tests(object):
|
|
test.add_cmd("stonith_admin", "--output-as=xml -F node3 -t 20")
|
|
|
|
test.add_stonith_log_pattern("Total timeout set to 8")
|
|
- test.add_stonith_log_pattern("targeting node3 using false1 returned -201")
|
|
+ test.add_stonith_log_pattern("targeting node3 using false1 returned 1")
|
|
test.add_stonith_neg_log_pattern("targeting node3 using false2 returned ")
|
|
test.add_stonith_log_pattern("targeting node3 using true3 returned 0")
|
|
test.add_stonith_log_pattern("targeting node3 using true4 returned 0")
|
|
@@ -1147,7 +1147,7 @@ class Tests(object):
|
|
"--output-as=xml -R true1 -a fence_dummy_no_reboot -o \"mode=pass\" -o \"pcmk_host_list=node1 node2 node3\"")
|
|
test.add_cmd("stonith_admin", "--output-as=xml -B node1 -t 5 -V")
|
|
test.add_stonith_log_pattern("does not support reboot")
|
|
- test.add_stonith_log_pattern("using true1 returned 0 (OK)")
|
|
+ test.add_stonith_log_pattern("using true1 returned 0")
|
|
|
|
# make sure reboot is used when reboot action is advertised
|
|
for test_type in test_types:
|
|
@@ -1158,7 +1158,7 @@ class Tests(object):
|
|
"--output-as=xml -R true1 -a fence_dummy -o \"mode=pass\" -o \"pcmk_host_list=node1 node2 node3\"")
|
|
test.add_cmd("stonith_admin", "--output-as=xml -B node1 -t 5 -V")
|
|
test.add_stonith_neg_log_pattern("does not advertise support for 'reboot', performing 'off'")
|
|
- test.add_stonith_log_pattern("using true1 returned 0 (OK)")
|
|
+ test.add_stonith_log_pattern("using true1 returned 0")
|
|
|
|
# make sure requested fencing delay is applied only for the first device in the first level
|
|
# make sure static delay from pcmk_delay_base is added
|
|
@@ -1240,8 +1240,8 @@ class Tests(object):
|
|
'--output-as=xml -R true2 -a fence_dummy_auto_unfence -o "mode=pass" -o "pcmk_host_list=%s"' % (our_uname))
|
|
test.add_cmd("stonith_admin", "--output-as=xml -U %s -t 3" % (our_uname))
|
|
# both devices should be executed
|
|
- test.add_stonith_log_pattern("using true1 returned 0 (OK)")
|
|
- test.add_stonith_log_pattern("using true2 returned 0 (OK)")
|
|
+ test.add_stonith_log_pattern("using true1 returned 0")
|
|
+ test.add_stonith_log_pattern("using true2 returned 0")
|
|
|
|
### verify unfencing using automatic unfencing fails if any of the required agents fail
|
|
test = self.new_test("cpg_unfence_required_2",
|
|
@@ -1264,8 +1264,8 @@ class Tests(object):
|
|
test.add_cmd("stonith_admin", "--output-as=xml -r %s -i 1 -v true1" % (our_uname))
|
|
test.add_cmd("stonith_admin", "--output-as=xml -r %s -i 2 -v true2" % (our_uname))
|
|
test.add_cmd("stonith_admin", "--output-as=xml -U %s -t 3" % (our_uname))
|
|
- test.add_stonith_log_pattern("using true1 returned 0 (OK)")
|
|
- test.add_stonith_log_pattern("using true2 returned 0 (OK)")
|
|
+ test.add_stonith_log_pattern("using true1 returned 0")
|
|
+ test.add_stonith_log_pattern("using true2 returned 0")
|
|
|
|
### verify unfencing using automatic devices with topology
|
|
test = self.new_test("cpg_unfence_required_4",
|
|
@@ -1296,10 +1296,10 @@ class Tests(object):
|
|
test.add_cmd("stonith_admin", "--output-as=xml -r %s -i 3 -v false4" % (our_uname))
|
|
test.add_cmd("stonith_admin", "--output-as=xml -r %s -i 4 -v true4" % (our_uname))
|
|
test.add_cmd("stonith_admin", "--output-as=xml -U %s -t 3" % (our_uname))
|
|
- test.add_stonith_log_pattern("using true1 returned 0 (OK)")
|
|
- test.add_stonith_log_pattern("using true2 returned 0 (OK)")
|
|
- test.add_stonith_log_pattern("using true3 returned 0 (OK)")
|
|
- test.add_stonith_log_pattern("using true4 returned 0 (OK)")
|
|
+ test.add_stonith_log_pattern("using true1 returned 0")
|
|
+ test.add_stonith_log_pattern("using true2 returned 0")
|
|
+ test.add_stonith_log_pattern("using true3 returned 0")
|
|
+ test.add_stonith_log_pattern("using true4 returned 0")
|
|
|
|
def build_unfence_on_target_tests(self):
|
|
""" Register tests that verify unfencing that runs on the target """
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From be72166ed9ccb53c218529783660503df95da719 Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Thu, 16 Sep 2021 16:50:23 -0500
|
|
Subject: [PATCH 11/12] Log: libcrmservice: downgrade failed action messages
|
|
|
|
Previously, we would often get duplicate log messages for failed actions,
|
|
from the service library and again from its callers.
|
|
|
|
Now that the service library tracks and provides exit reasons, callers can log
|
|
sufficient detail with better context, so downgrade the library's messages to
|
|
info level or lower. Similarly, avoid duplicate logs of process output.
|
|
|
|
Certain messages (such as out-of-memory) remain at higher severity.
|
|
---
|
|
daemons/controld/controld_execd.c | 15 +++---
|
|
lib/fencing/st_client.c | 11 ++---
|
|
lib/services/services.c | 14 +++---
|
|
lib/services/services_linux.c | 80 ++++++++++++++++---------------
|
|
lib/services/systemd.c | 20 ++++----
|
|
lib/services/upstart.c | 19 ++++----
|
|
6 files changed, 80 insertions(+), 79 deletions(-)
|
|
|
|
diff --git a/daemons/controld/controld_execd.c b/daemons/controld/controld_execd.c
|
|
index bded6e6b6..3ddff6e13 100644
|
|
--- a/daemons/controld/controld_execd.c
|
|
+++ b/daemons/controld/controld_execd.c
|
|
@@ -2684,16 +2684,15 @@ log_executor_event(lrmd_event_data_t *op, const char *op_key,
|
|
do_crm_log(log_level, "%s", str->str);
|
|
g_string_free(str, TRUE);
|
|
|
|
- if (op->output != NULL) {
|
|
- char *prefix = crm_strdup_printf("%s-" PCMK__OP_FMT ":%d", node_name,
|
|
+ /* The services library has already logged the output at info or debug
|
|
+ * level, so just raise to notice if it looks like a failure.
|
|
+ */
|
|
+ if ((op->output != NULL) && (op->rc != PCMK_OCF_OK)) {
|
|
+ char *prefix = crm_strdup_printf(PCMK__OP_FMT "@%s output",
|
|
op->rsc_id, op->op_type,
|
|
- op->interval_ms, op->call_id);
|
|
+ op->interval_ms, node_name);
|
|
|
|
- if (op->rc) {
|
|
- crm_log_output(LOG_NOTICE, prefix, op->output);
|
|
- } else {
|
|
- crm_log_output(LOG_DEBUG, prefix, op->output);
|
|
- }
|
|
+ crm_log_output(LOG_NOTICE, prefix, op->output);
|
|
free(prefix);
|
|
}
|
|
}
|
|
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
index 3d4127eff..2fbff7f24 100644
|
|
--- a/lib/fencing/st_client.c
|
|
+++ b/lib/fencing/st_client.c
|
|
@@ -276,14 +276,9 @@ stonith__watchdog_fencing_enabled_for_node(const char *node)
|
|
static void
|
|
log_action(stonith_action_t *action, pid_t pid)
|
|
{
|
|
- if (action->result.action_stdout != NULL) {
|
|
- /* Logging the whole string confuses syslog when the string is xml */
|
|
- char *prefix = crm_strdup_printf("%s[%d] stdout:", action->agent, pid);
|
|
-
|
|
- crm_log_output(LOG_TRACE, prefix, action->result.action_stdout);
|
|
- free(prefix);
|
|
- }
|
|
-
|
|
+ /* The services library has already logged the output at info or debug
|
|
+ * level, so just raise to warning for stderr.
|
|
+ */
|
|
if (action->result.action_stderr != NULL) {
|
|
/* Logging the whole string confuses syslog when the string is xml */
|
|
char *prefix = crm_strdup_printf("%s[%d] stderr:", action->agent, pid);
|
|
diff --git a/lib/services/services.c b/lib/services/services.c
|
|
index 86a0a213c..cf8bbc70e 100644
|
|
--- a/lib/services/services.c
|
|
+++ b/lib/services/services.c
|
|
@@ -319,13 +319,13 @@ services__create_resource_action(const char *name, const char *standard,
|
|
rc = services__nagios_prepare(op);
|
|
#endif
|
|
} else {
|
|
- crm_err("Unknown resource standard: %s", op->standard);
|
|
+ crm_info("Unknown resource standard: %s", op->standard);
|
|
rc = ENOENT;
|
|
}
|
|
|
|
if (rc != pcmk_rc_ok) {
|
|
- crm_err("Cannot prepare %s operation for %s: %s",
|
|
- action, name, strerror(rc));
|
|
+ crm_info("Cannot prepare %s operation for %s: %s",
|
|
+ action, name, strerror(rc));
|
|
services__handle_exec_error(op, rc);
|
|
}
|
|
return op;
|
|
@@ -967,14 +967,14 @@ execute_metadata_action(svc_action_t *op)
|
|
const char *class = op->standard;
|
|
|
|
if (op->agent == NULL) {
|
|
- crm_err("meta-data requested without specifying agent");
|
|
+ crm_info("Meta-data requested without specifying agent");
|
|
services__set_result(op, services__generic_error(op),
|
|
PCMK_EXEC_ERROR_FATAL, "Agent not specified");
|
|
return EINVAL;
|
|
}
|
|
|
|
if (class == NULL) {
|
|
- crm_err("meta-data requested for agent %s without specifying class",
|
|
+ crm_info("Meta-data requested for agent %s without specifying class",
|
|
op->agent);
|
|
services__set_result(op, services__generic_error(op),
|
|
PCMK_EXEC_ERROR_FATAL,
|
|
@@ -986,8 +986,8 @@ execute_metadata_action(svc_action_t *op)
|
|
class = resources_find_service_class(op->agent);
|
|
}
|
|
if (class == NULL) {
|
|
- crm_err("meta-data requested for %s, but could not determine class",
|
|
- op->agent);
|
|
+ crm_info("Meta-data requested for %s, but could not determine class",
|
|
+ op->agent);
|
|
services__set_result(op, services__generic_error(op),
|
|
PCMK_EXEC_ERROR_HARD,
|
|
"Agent standard could not be determined");
|
|
diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c
|
|
index b2ff27a0d..9a4c6cf80 100644
|
|
--- a/lib/services/services_linux.c
|
|
+++ b/lib/services/services_linux.c
|
|
@@ -64,8 +64,8 @@ sigchld_setup(struct sigchld_data_s *data)
|
|
|
|
// Block SIGCHLD (saving previous set of blocked signals to restore later)
|
|
if (sigprocmask(SIG_BLOCK, &(data->mask), &(data->old_mask)) < 0) {
|
|
- crm_err("Wait for child process completion failed: %s "
|
|
- CRM_XS " source=sigprocmask", pcmk_strerror(errno));
|
|
+ crm_info("Wait for child process completion failed: %s "
|
|
+ CRM_XS " source=sigprocmask", pcmk_strerror(errno));
|
|
return false;
|
|
}
|
|
return true;
|
|
@@ -81,8 +81,8 @@ sigchld_open(struct sigchld_data_s *data)
|
|
|
|
fd = signalfd(-1, &(data->mask), SFD_NONBLOCK);
|
|
if (fd < 0) {
|
|
- crm_err("Wait for child process completion failed: %s "
|
|
- CRM_XS " source=signalfd", pcmk_strerror(errno));
|
|
+ crm_info("Wait for child process completion failed: %s "
|
|
+ CRM_XS " source=signalfd", pcmk_strerror(errno));
|
|
}
|
|
return fd;
|
|
}
|
|
@@ -108,8 +108,8 @@ sigchld_received(int fd)
|
|
}
|
|
s = read(fd, &fdsi, sizeof(struct signalfd_siginfo));
|
|
if (s != sizeof(struct signalfd_siginfo)) {
|
|
- crm_err("Wait for child process completion failed: %s "
|
|
- CRM_XS " source=read", pcmk_strerror(errno));
|
|
+ crm_info("Wait for child process completion failed: %s "
|
|
+ CRM_XS " source=read", pcmk_strerror(errno));
|
|
|
|
} else if (fdsi.ssi_signo == SIGCHLD) {
|
|
return true;
|
|
@@ -149,8 +149,8 @@ sigchld_handler()
|
|
if ((last_sigchld_data != NULL)
|
|
&& (last_sigchld_data->pipe_fd[1] >= 0)
|
|
&& (write(last_sigchld_data->pipe_fd[1], "", 1) == -1)) {
|
|
- crm_err("Wait for child process completion failed: %s "
|
|
- CRM_XS " source=write", pcmk_strerror(errno));
|
|
+ crm_info("Wait for child process completion failed: %s "
|
|
+ CRM_XS " source=write", pcmk_strerror(errno));
|
|
}
|
|
}
|
|
|
|
@@ -162,19 +162,19 @@ sigchld_setup(struct sigchld_data_s *data)
|
|
data->pipe_fd[0] = data->pipe_fd[1] = -1;
|
|
|
|
if (pipe(data->pipe_fd) == -1) {
|
|
- crm_err("Wait for child process completion failed: %s "
|
|
- CRM_XS " source=pipe", pcmk_strerror(errno));
|
|
+ crm_info("Wait for child process completion failed: %s "
|
|
+ CRM_XS " source=pipe", pcmk_strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
rc = pcmk__set_nonblocking(data->pipe_fd[0]);
|
|
if (rc != pcmk_rc_ok) {
|
|
- crm_warn("Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
|
|
+ crm_info("Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
|
|
pcmk_rc_str(rc), rc);
|
|
}
|
|
rc = pcmk__set_nonblocking(data->pipe_fd[1]);
|
|
if (rc != pcmk_rc_ok) {
|
|
- crm_warn("Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
|
|
+ crm_info("Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
|
|
pcmk_rc_str(rc), rc);
|
|
}
|
|
|
|
@@ -183,8 +183,8 @@ sigchld_setup(struct sigchld_data_s *data)
|
|
data->sa.sa_flags = 0;
|
|
sigemptyset(&(data->sa.sa_mask));
|
|
if (sigaction(SIGCHLD, &(data->sa), &(data->old_sa)) < 0) {
|
|
- crm_err("Wait for child process completion failed: %s "
|
|
- CRM_XS " source=sigaction", pcmk_strerror(errno));
|
|
+ crm_info("Wait for child process completion failed: %s "
|
|
+ CRM_XS " source=sigaction", pcmk_strerror(errno));
|
|
}
|
|
|
|
// Remember data for use in signal handler
|
|
@@ -585,7 +585,11 @@ log_op_output(svc_action_t *op)
|
|
{
|
|
char *prefix = crm_strdup_printf("%s[%d] error output", op->id, op->pid);
|
|
|
|
- crm_log_output(LOG_NOTICE, prefix, op->stderr_data);
|
|
+ /* The library caller has better context to know how important the output
|
|
+ * is, so log it at info and debug severity here. They can log it again at
|
|
+ * higher severity if appropriate.
|
|
+ */
|
|
+ crm_log_output(LOG_INFO, prefix, op->stderr_data);
|
|
strcpy(prefix + strlen(prefix) - strlen("error output"), "output");
|
|
crm_log_output(LOG_DEBUG, prefix, op->stdout_data);
|
|
free(prefix);
|
|
@@ -673,7 +677,7 @@ async_action_complete(mainloop_child_t *p, pid_t pid, int core, int signo,
|
|
parse_exit_reason_from_stderr(op);
|
|
|
|
} else if (mainloop_child_timeout(p)) {
|
|
- crm_warn("%s[%d] timed out after %dms", op->id, op->pid, op->timeout);
|
|
+ crm_info("%s[%d] timed out after %dms", op->id, op->pid, op->timeout);
|
|
services__set_result(op, services__generic_error(op), PCMK_EXEC_TIMEOUT,
|
|
"Process did not exit within specified timeout");
|
|
|
|
@@ -686,7 +690,7 @@ async_action_complete(mainloop_child_t *p, pid_t pid, int core, int signo,
|
|
services__set_result(op, PCMK_OCF_OK, PCMK_EXEC_CANCELLED, NULL);
|
|
|
|
} else {
|
|
- crm_warn("%s[%d] terminated with signal %d (%s)",
|
|
+ crm_info("%s[%d] terminated with signal %d (%s)",
|
|
op->id, op->pid, signo, strsignal(signo));
|
|
services__set_result(op, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_ERROR,
|
|
"Process interrupted by signal");
|
|
@@ -908,12 +912,12 @@ action_launch_child(svc_action_t *op)
|
|
sp.sched_priority = 0;
|
|
|
|
if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
|
|
- crm_warn("Could not reset scheduling policy for %s", op->id);
|
|
+ crm_info("Could not reset scheduling policy for %s", op->id);
|
|
}
|
|
}
|
|
#endif
|
|
if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
|
|
- crm_warn("Could not reset process priority for %s", op->id);
|
|
+ crm_info("Could not reset process priority for %s", op->id);
|
|
}
|
|
|
|
/* Man: The call setpgrp() is equivalent to setpgid(0,0)
|
|
@@ -941,7 +945,7 @@ action_launch_child(svc_action_t *op)
|
|
} else {
|
|
crm_err("Considering %s unconfigured "
|
|
"because unable to load CIB secrets: %s",
|
|
- op->rsc, pcmk_rc_str(rc));
|
|
+ op->rsc, pcmk_rc_str(rc));
|
|
exit_child(op, services__configuration_error(op, false),
|
|
"Unable to load CIB secrets");
|
|
}
|
|
@@ -1043,7 +1047,7 @@ wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
|
|
|
|
} else if (wait_rc < 0) {
|
|
wait_reason = pcmk_rc_str(errno);
|
|
- crm_warn("Wait for completion of %s[%d] failed: %s "
|
|
+ crm_info("Wait for completion of %s[%d] failed: %s "
|
|
CRM_XS " source=waitpid",
|
|
op->id, op->pid, wait_reason);
|
|
wait_rc = 0; // Act as if process is still running
|
|
@@ -1057,8 +1061,8 @@ wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
|
|
|
|
} else if ((poll_rc < 0) && (errno != EINTR)) {
|
|
wait_reason = pcmk_rc_str(errno);
|
|
- crm_err("Wait for completion of %s[%d] failed: %s "
|
|
- CRM_XS " source=poll", op->id, op->pid, wait_reason);
|
|
+ crm_info("Wait for completion of %s[%d] failed: %s "
|
|
+ CRM_XS " source=poll", op->id, op->pid, wait_reason);
|
|
break;
|
|
}
|
|
|
|
@@ -1078,7 +1082,7 @@ wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
|
|
services__set_result(op, services__generic_error(op),
|
|
PCMK_EXEC_TIMEOUT,
|
|
"Process did not exit within specified timeout");
|
|
- crm_warn("%s[%d] timed out after %dms",
|
|
+ crm_info("%s[%d] timed out after %dms",
|
|
op->id, op->pid, op->timeout);
|
|
|
|
} else {
|
|
@@ -1110,8 +1114,8 @@ wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
|
|
|
|
services__set_result(op, services__generic_error(op), PCMK_EXEC_ERROR,
|
|
"Process interrupted by signal");
|
|
- crm_err("%s[%d] terminated with signal %d (%s)",
|
|
- op->id, op->pid, signo, strsignal(signo));
|
|
+ crm_info("%s[%d] terminated with signal %d (%s)",
|
|
+ op->id, op->pid, signo, strsignal(signo));
|
|
|
|
#ifdef WCOREDUMP
|
|
if (WCOREDUMP(status)) {
|
|
@@ -1155,7 +1159,7 @@ services__execute_file(svc_action_t *op)
|
|
// Catch common failure conditions early
|
|
if (stat(op->opaque->exec, &st) != 0) {
|
|
rc = errno;
|
|
- crm_warn("Cannot execute '%s': %s " CRM_XS " stat rc=%d",
|
|
+ crm_info("Cannot execute '%s': %s " CRM_XS " stat rc=%d",
|
|
op->opaque->exec, pcmk_strerror(rc), rc);
|
|
services__handle_exec_error(op, rc);
|
|
goto done;
|
|
@@ -1163,8 +1167,8 @@ services__execute_file(svc_action_t *op)
|
|
|
|
if (pipe(stdout_fd) < 0) {
|
|
rc = errno;
|
|
- crm_err("Cannot execute '%s': %s " CRM_XS " pipe(stdout) rc=%d",
|
|
- op->opaque->exec, pcmk_strerror(rc), rc);
|
|
+ crm_info("Cannot execute '%s': %s " CRM_XS " pipe(stdout) rc=%d",
|
|
+ op->opaque->exec, pcmk_strerror(rc), rc);
|
|
services__handle_exec_error(op, rc);
|
|
goto done;
|
|
}
|
|
@@ -1174,8 +1178,8 @@ services__execute_file(svc_action_t *op)
|
|
|
|
close_pipe(stdout_fd);
|
|
|
|
- crm_err("Cannot execute '%s': %s " CRM_XS " pipe(stderr) rc=%d",
|
|
- op->opaque->exec, pcmk_strerror(rc), rc);
|
|
+ crm_info("Cannot execute '%s': %s " CRM_XS " pipe(stderr) rc=%d",
|
|
+ op->opaque->exec, pcmk_strerror(rc), rc);
|
|
services__handle_exec_error(op, rc);
|
|
goto done;
|
|
}
|
|
@@ -1187,8 +1191,8 @@ services__execute_file(svc_action_t *op)
|
|
close_pipe(stdout_fd);
|
|
close_pipe(stderr_fd);
|
|
|
|
- crm_err("Cannot execute '%s': %s " CRM_XS " pipe(stdin) rc=%d",
|
|
- op->opaque->exec, pcmk_strerror(rc), rc);
|
|
+ crm_info("Cannot execute '%s': %s " CRM_XS " pipe(stdin) rc=%d",
|
|
+ op->opaque->exec, pcmk_strerror(rc), rc);
|
|
services__handle_exec_error(op, rc);
|
|
goto done;
|
|
}
|
|
@@ -1212,8 +1216,8 @@ services__execute_file(svc_action_t *op)
|
|
close_pipe(stdout_fd);
|
|
close_pipe(stderr_fd);
|
|
|
|
- crm_err("Cannot execute '%s': %s " CRM_XS " fork rc=%d",
|
|
- op->opaque->exec, pcmk_strerror(rc), rc);
|
|
+ crm_info("Cannot execute '%s': %s " CRM_XS " fork rc=%d",
|
|
+ op->opaque->exec, pcmk_strerror(rc), rc);
|
|
services__handle_exec_error(op, rc);
|
|
if (op->synchronous) {
|
|
sigchld_cleanup(&data);
|
|
@@ -1271,7 +1275,7 @@ services__execute_file(svc_action_t *op)
|
|
op->opaque->stdout_fd = stdout_fd[0];
|
|
rc = pcmk__set_nonblocking(op->opaque->stdout_fd);
|
|
if (rc != pcmk_rc_ok) {
|
|
- crm_warn("Could not set '%s' output non-blocking: %s "
|
|
+ crm_info("Could not set '%s' output non-blocking: %s "
|
|
CRM_XS " rc=%d",
|
|
op->opaque->exec, pcmk_rc_str(rc), rc);
|
|
}
|
|
@@ -1279,7 +1283,7 @@ services__execute_file(svc_action_t *op)
|
|
op->opaque->stderr_fd = stderr_fd[0];
|
|
rc = pcmk__set_nonblocking(op->opaque->stderr_fd);
|
|
if (rc != pcmk_rc_ok) {
|
|
- crm_warn("Could not set '%s' error output non-blocking: %s "
|
|
+ crm_info("Could not set '%s' error output non-blocking: %s "
|
|
CRM_XS " rc=%d",
|
|
op->opaque->exec, pcmk_rc_str(rc), rc);
|
|
}
|
|
@@ -1290,7 +1294,7 @@ services__execute_file(svc_action_t *op)
|
|
// as long as no other standard uses stdin_fd assume stonith
|
|
rc = pcmk__set_nonblocking(op->opaque->stdin_fd);
|
|
if (rc != pcmk_rc_ok) {
|
|
- crm_warn("Could not set '%s' input non-blocking: %s "
|
|
+ crm_info("Could not set '%s' input non-blocking: %s "
|
|
CRM_XS " fd=%d,rc=%d", op->opaque->exec,
|
|
pcmk_rc_str(rc), op->opaque->stdin_fd, rc);
|
|
}
|
|
diff --git a/lib/services/systemd.c b/lib/services/systemd.c
|
|
index 6f5bef960..8e9fff484 100644
|
|
--- a/lib/services/systemd.c
|
|
+++ b/lib/services/systemd.c
|
|
@@ -232,7 +232,8 @@ systemd_daemon_reload_complete(DBusPendingCall *pending, void *user_data)
|
|
}
|
|
|
|
if (pcmk_dbus_find_error(pending, reply, &error)) {
|
|
- crm_err("Could not issue systemd reload %d: %s", reload_count, error.message);
|
|
+ crm_warn("Could not issue systemd reload %d: %s",
|
|
+ reload_count, error.message);
|
|
dbus_error_free(&error);
|
|
|
|
} else {
|
|
@@ -291,8 +292,8 @@ set_result_from_method_error(svc_action_t *op, const DBusError *error)
|
|
PCMK_EXEC_NOT_INSTALLED, "systemd unit not found");
|
|
}
|
|
|
|
- crm_err("DBus request for %s of systemd unit %s for resource %s failed: %s",
|
|
- op->action, op->agent, crm_str(op->rsc), error->message);
|
|
+ crm_info("DBus request for %s of systemd unit %s for resource %s failed: %s",
|
|
+ op->action, op->agent, crm_str(op->rsc), error->message);
|
|
}
|
|
|
|
/*!
|
|
@@ -325,11 +326,11 @@ execute_after_loadunit(DBusMessage *reply, svc_action_t *op)
|
|
if (op != NULL) {
|
|
services__set_result(op, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_ERROR,
|
|
"systemd DBus method had unexpected reply");
|
|
- crm_err("Could not load systemd unit %s for %s: "
|
|
- "DBus reply has unexpected type", op->agent, op->id);
|
|
+ crm_info("Could not load systemd unit %s for %s: "
|
|
+ "DBus reply has unexpected type", op->agent, op->id);
|
|
} else {
|
|
- crm_err("Could not load systemd unit: "
|
|
- "DBus reply has unexpected type");
|
|
+ crm_info("Could not load systemd unit: "
|
|
+ "DBus reply has unexpected type");
|
|
}
|
|
|
|
} else {
|
|
@@ -688,7 +689,7 @@ process_unit_method_reply(DBusMessage *reply, svc_action_t *op)
|
|
|
|
} else if (!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH,
|
|
__func__, __LINE__)) {
|
|
- crm_warn("DBus request for %s of %s succeeded but "
|
|
+ crm_info("DBus request for %s of %s succeeded but "
|
|
"return type was unexpected", op->action, crm_str(op->rsc));
|
|
services__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE,
|
|
"systemd DBus method had unexpected reply");
|
|
@@ -981,7 +982,8 @@ systemd_timeout_callback(gpointer p)
|
|
svc_action_t * op = p;
|
|
|
|
op->opaque->timerid = 0;
|
|
- crm_warn("%s operation on systemd unit %s named '%s' timed out", op->action, op->agent, op->rsc);
|
|
+ crm_info("%s action for systemd unit %s named '%s' timed out",
|
|
+ op->action, op->agent, op->rsc);
|
|
services__set_result(op, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_TIMEOUT,
|
|
"Systemd action did not complete within specified timeout");
|
|
services__finalize_async_op(op);
|
|
diff --git a/lib/services/upstart.c b/lib/services/upstart.c
|
|
index 2fdc229ad..2ece803e1 100644
|
|
--- a/lib/services/upstart.c
|
|
+++ b/lib/services/upstart.c
|
|
@@ -308,21 +308,21 @@ get_first_instance(const gchar * job, int timeout)
|
|
dbus_message_unref(msg);
|
|
|
|
if (dbus_error_is_set(&error)) {
|
|
- crm_err("Call to %s failed: %s", method, error.message);
|
|
+ crm_info("Call to %s failed: %s", method, error.message);
|
|
dbus_error_free(&error);
|
|
goto done;
|
|
|
|
} else if(reply == NULL) {
|
|
- crm_err("Call to %s failed: no reply", method);
|
|
+ crm_info("Call to %s failed: no reply", method);
|
|
goto done;
|
|
|
|
} else if (!dbus_message_iter_init(reply, &args)) {
|
|
- crm_err("Call to %s failed: Message has no arguments", method);
|
|
+ crm_info("Call to %s failed: Message has no arguments", method);
|
|
goto done;
|
|
}
|
|
|
|
if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __func__, __LINE__)) {
|
|
- crm_err("Call to %s failed: Message has invalid arguments", method);
|
|
+ crm_info("Call to %s failed: Message has invalid arguments", method);
|
|
goto done;
|
|
}
|
|
|
|
@@ -432,8 +432,8 @@ set_result_from_method_error(svc_action_t *op, const DBusError *error)
|
|
return;
|
|
}
|
|
|
|
- crm_err("DBus request for %s of Upstart job %s for resource %s failed: %s",
|
|
- op->action, op->agent, crm_str(op->rsc), error->message);
|
|
+ crm_info("DBus request for %s of Upstart job %s for resource %s failed: %s",
|
|
+ op->action, op->agent, crm_str(op->rsc), error->message);
|
|
}
|
|
|
|
/*!
|
|
@@ -468,7 +468,7 @@ job_method_complete(DBusPendingCall *pending, void *user_data)
|
|
|
|
} else if (!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH,
|
|
__func__, __LINE__)) {
|
|
- crm_warn("DBus request for %s of %s succeeded but "
|
|
+ crm_info("DBus request for %s of %s succeeded but "
|
|
"return type was unexpected", op->action, crm_str(op->rsc));
|
|
services__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE, NULL);
|
|
|
|
@@ -667,7 +667,8 @@ services__execute_upstart(svc_action_t *op)
|
|
|
|
} else if (!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH,
|
|
__func__, __LINE__)) {
|
|
- crm_warn("Call to %s passed but return type was unexpected", op->action);
|
|
+ crm_info("Call to %s passed but return type was unexpected",
|
|
+ op->action);
|
|
services__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE, NULL);
|
|
|
|
} else {
|
|
@@ -675,7 +676,7 @@ services__execute_upstart(svc_action_t *op)
|
|
|
|
dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
|
|
DBUS_TYPE_INVALID);
|
|
- crm_info("Call to %s passed: %s", op->action, path);
|
|
+ crm_debug("Call to %s passed: %s", op->action, path);
|
|
services__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE, NULL);
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|
|
|
|
From 39f6861c72eb9dd76d2cf3da287fe7485615631b Mon Sep 17 00:00:00 2001
|
|
From: Ken Gaillot <kgaillot@redhat.com>
|
|
Date: Mon, 8 Nov 2021 09:43:38 -0600
|
|
Subject: [PATCH 12/12] Low: fencing: avoid use-after-free with new result
|
|
object
|
|
|
|
itnroduced by 153c9b552 (not released)
|
|
---
|
|
lib/fencing/st_rhcs.c | 6 ++++--
|
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/lib/fencing/st_rhcs.c b/lib/fencing/st_rhcs.c
|
|
index 23e694975..6c8cbedc7 100644
|
|
--- a/lib/fencing/st_rhcs.c
|
|
+++ b/lib/fencing/st_rhcs.c
|
|
@@ -143,15 +143,17 @@ stonith__rhcs_get_metadata(const char *agent, int timeout, xmlNode **metadata)
|
|
if (result->execution_status != PCMK_EXEC_DONE) {
|
|
crm_warn("Could not execute metadata action for %s: %s",
|
|
agent, pcmk_exec_status_str(result->execution_status));
|
|
+ rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
stonith__destroy_action(action);
|
|
- return pcmk_rc2legacy(stonith__result2rc(result));
|
|
+ return rc;
|
|
}
|
|
|
|
if (result->exit_status != CRM_EX_OK) {
|
|
crm_warn("Metadata action for %s returned error code %d",
|
|
agent, result->exit_status);
|
|
+ rc = pcmk_rc2legacy(stonith__result2rc(result));
|
|
stonith__destroy_action(action);
|
|
- return pcmk_rc2legacy(stonith__result2rc(result));
|
|
+ return rc;
|
|
}
|
|
|
|
if (result->action_stdout == NULL) {
|
|
--
|
|
2.27.0
|
|
|