import pacemaker-2.0.4-6.el8
# Conflicts: # .gitignore # .pacemaker.metadata # SPECS/pacemaker.spec
This commit is contained in:
commit
c6b88556ad
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
SOURCES/nagios-agents-metadata-105ab8a.tar.gz
|
||||
SOURCES/pacemaker-2deceaa.tar.gz
|
2
.pacemaker.metadata
Normal file
2
.pacemaker.metadata
Normal file
@ -0,0 +1,2 @@
|
||||
ea6c0a27fd0ae8ce02f84a11f08a0d79377041c3 SOURCES/nagios-agents-metadata-105ab8a.tar.gz
|
||||
78c94fdcf59cfb064d4433e1b8f71fd856eeec5f SOURCES/pacemaker-2deceaa.tar.gz
|
4947
SOURCES/001-rules.patch
Normal file
4947
SOURCES/001-rules.patch
Normal file
File diff suppressed because it is too large
Load Diff
8664
SOURCES/002-demote.patch
Normal file
8664
SOURCES/002-demote.patch
Normal file
File diff suppressed because it is too large
Load Diff
30
SOURCES/003-trace.patch
Normal file
30
SOURCES/003-trace.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 47c3e06b098c7e148c54675588d03b4d2bea40b5 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Mon, 22 Jun 2020 16:20:01 -0400
|
||||
Subject: [PATCH] Fix: libpacemaker: Don't allow a potential NULL in a format
|
||||
string.
|
||||
|
||||
This is only tripping up F32 s390x builds, but I don't suppose there's
|
||||
any reason it couldn't come up elsewhere later.
|
||||
---
|
||||
lib/pacemaker/pcmk_sched_constraints.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/pacemaker/pcmk_sched_constraints.c b/lib/pacemaker/pcmk_sched_constraints.c
|
||||
index 9c3a88d..d8c3e69 100644
|
||||
--- a/lib/pacemaker/pcmk_sched_constraints.c
|
||||
+++ b/lib/pacemaker/pcmk_sched_constraints.c
|
||||
@@ -1595,8 +1595,8 @@ custom_action_order(pe_resource_t * lh_rsc, char *lh_action_task, pe_action_t *
|
||||
order = calloc(1, sizeof(pe__ordering_t));
|
||||
|
||||
crm_trace("Creating[%d] %s %s %s - %s %s %s", data_set->order_id,
|
||||
- lh_rsc?lh_rsc->id:"NA", lh_action_task, lh_action?lh_action->uuid:"NA",
|
||||
- rh_rsc?rh_rsc->id:"NA", rh_action_task, rh_action?rh_action->uuid:"NA");
|
||||
+ lh_rsc?lh_rsc->id:"NA", lh_action_task?lh_action_task:"NA", lh_action?lh_action->uuid:"NA",
|
||||
+ rh_rsc?rh_rsc->id:"NA", rh_action_task?rh_action_task:"NA", rh_action?rh_action->uuid:"NA");
|
||||
|
||||
/* CRM_ASSERT(data_set->order_id != 291); */
|
||||
|
||||
--
|
||||
1.8.3.1
|
||||
|
27
SOURCES/004-test.patch
Normal file
27
SOURCES/004-test.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 7ed7675615ada7d0be5654e0dcb26de60cf5b5e9 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Mon, 22 Jun 2020 20:03:56 -0500
|
||||
Subject: [PATCH] Test: scheduler: explicitly disable concurrent-fencing in
|
||||
on_fail_demote4
|
||||
|
||||
... so the expected output is the same regardless of what default the build was
|
||||
compiled with
|
||||
---
|
||||
cts/scheduler/on_fail_demote4.xml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/cts/scheduler/on_fail_demote4.xml b/cts/scheduler/on_fail_demote4.xml
|
||||
index eb4c4cc..1082266 100644
|
||||
--- a/cts/scheduler/on_fail_demote4.xml
|
||||
+++ b/cts/scheduler/on_fail_demote4.xml
|
||||
@@ -8,6 +8,7 @@
|
||||
<nvpair id="cts-shutdown-escalation" name="shutdown-escalation" value="5min"/>
|
||||
<nvpair id="cts-batch-limit" name="batch-limit" value="10"/>
|
||||
<nvpair id="cts-dc-deadtime" name="dc-deadtime" value="5s"/>
|
||||
+ <nvpair id="cts-concurrent-fencing" name="concurrent-fencing" value="false"/>
|
||||
<nvpair id="cib-bootstrap-options-have-watchdog" name="have-watchdog" value="false"/>
|
||||
<nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="2.0.4-578.6e1b582.git.el7_8-6e1b582"/>
|
||||
<nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"/>
|
||||
--
|
||||
1.8.3.1
|
||||
|
32
SOURCES/005-sysconfig.patch
Normal file
32
SOURCES/005-sysconfig.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 85040eb19b9405464b01a7e67eb6769d2a03c611 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 17:49:22 -0500
|
||||
Subject: [PATCH] Doc: sysconfig: remove outdated reference to wildcards in
|
||||
PCMK_trace_files
|
||||
|
||||
Wildcards stopped working when the log filtering implementation changed in
|
||||
1.1.8 to support PCMK_trace_tags. It's not worth the effort to fix at this
|
||||
point, so just update the comment in the sysconfig file.
|
||||
---
|
||||
daemons/pacemakerd/pacemaker.sysconfig | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemons/pacemakerd/pacemaker.sysconfig b/daemons/pacemakerd/pacemaker.sysconfig
|
||||
index c7745d8..e4a5c4d 100644
|
||||
--- a/daemons/pacemakerd/pacemaker.sysconfig
|
||||
+++ b/daemons/pacemakerd/pacemaker.sysconfig
|
||||
@@ -34,9 +34,8 @@
|
||||
# Log all messages from a comma-separated list of functions.
|
||||
# PCMK_trace_functions=function1,function2,function3
|
||||
|
||||
-# Log all messages from a comma-separated list of files (no path).
|
||||
-# Wildcards are supported, e.g. PCMK_trace_files=prefix*.c
|
||||
-# PCMK_trace_files=file.c,other.h
|
||||
+# Log all messages from a comma-separated list of file names (without path).
|
||||
+# PCMK_trace_files=file1.c,file2.c
|
||||
|
||||
# Log all messages matching comma-separated list of formats.
|
||||
# PCMK_trace_formats="Sent delete %d"
|
||||
--
|
||||
1.8.3.1
|
||||
|
5198
SOURCES/006-ipc_refactor.patch
Normal file
5198
SOURCES/006-ipc_refactor.patch
Normal file
File diff suppressed because it is too large
Load Diff
4146
SOURCES/007-ipc_model.patch
Normal file
4146
SOURCES/007-ipc_model.patch
Normal file
File diff suppressed because it is too large
Load Diff
685
SOURCES/008-crm_node.patch
Normal file
685
SOURCES/008-crm_node.patch
Normal file
@ -0,0 +1,685 @@
|
||||
From e01a1178fd8f5b99895683b3af9998e9485d12a4 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 24 Apr 2020 16:42:02 -0500
|
||||
Subject: [PATCH 1/3] Feature: controller: add new IPC API command for getting
|
||||
node list
|
||||
|
||||
This is based on and will replace the corresponding functionality in
|
||||
pacemakerd.
|
||||
---
|
||||
daemons/controld/controld_messages.c | 44 ++++++++++++++++++++++++++++--
|
||||
include/crm/common/ipc_controld.h | 13 +++++++++
|
||||
include/crm_internal.h | 1 +
|
||||
lib/common/ipc_controld.c | 53 ++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 109 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/controld/controld_messages.c b/daemons/controld/controld_messages.c
|
||||
index 0be04d0..423f006 100644
|
||||
--- a/daemons/controld/controld_messages.c
|
||||
+++ b/daemons/controld/controld_messages.c
|
||||
@@ -375,10 +375,11 @@ relay_message(xmlNode * msg, gboolean originated_locally)
|
||||
is_local = 0;
|
||||
|
||||
} else if (is_for_crm) {
|
||||
- if (safe_str_eq(task, CRM_OP_NODE_INFO)) {
|
||||
+ if (safe_str_eq(task, CRM_OP_NODE_INFO)
|
||||
+ || safe_str_eq(task, PCMK__CONTROLD_CMD_NODES)) {
|
||||
/* Node info requests do not specify a host, which is normally
|
||||
* treated as "all hosts", because the whole point is that the
|
||||
- * client doesn't know the local node name. Always handle these
|
||||
+ * client may not know the local node name. Always handle these
|
||||
* requests locally.
|
||||
*/
|
||||
is_local = 1;
|
||||
@@ -784,6 +785,42 @@ handle_ping(xmlNode *msg)
|
||||
}
|
||||
|
||||
/*!
|
||||
+ * \brief Handle a PCMK__CONTROLD_CMD_NODES message
|
||||
+ *
|
||||
+ * \return Next FSA input
|
||||
+ */
|
||||
+static enum crmd_fsa_input
|
||||
+handle_node_list(xmlNode *request)
|
||||
+{
|
||||
+ GHashTableIter iter;
|
||||
+ crm_node_t *node = NULL;
|
||||
+ xmlNode *reply = NULL;
|
||||
+ xmlNode *reply_data = NULL;
|
||||
+
|
||||
+ // Create message data for reply
|
||||
+ reply_data = create_xml_node(NULL, XML_CIB_TAG_NODES);
|
||||
+ g_hash_table_iter_init(&iter, crm_peer_cache);
|
||||
+ while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
|
||||
+ xmlNode *xml = create_xml_node(reply_data, XML_CIB_TAG_NODE);
|
||||
+
|
||||
+ crm_xml_add_ll(xml, XML_ATTR_ID, (long long) node->id); // uint32_t
|
||||
+ crm_xml_add(xml, XML_ATTR_UNAME, node->uname);
|
||||
+ crm_xml_add(xml, XML_NODE_IN_CLUSTER, node->state);
|
||||
+ }
|
||||
+
|
||||
+ // Create and send reply
|
||||
+ reply = create_reply(request, reply_data);
|
||||
+ free_xml(reply_data);
|
||||
+ if (reply) {
|
||||
+ (void) relay_message(reply, TRUE);
|
||||
+ free_xml(reply);
|
||||
+ }
|
||||
+
|
||||
+ // Nothing further to do
|
||||
+ return I_NULL;
|
||||
+}
|
||||
+
|
||||
+/*!
|
||||
* \brief Handle a CRM_OP_NODE_INFO request
|
||||
*
|
||||
* \param[in] msg Message XML
|
||||
@@ -1080,6 +1117,9 @@ handle_request(xmlNode *stored_msg, enum crmd_fsa_cause cause)
|
||||
|
||||
remote_ra_process_maintenance_nodes(xml);
|
||||
|
||||
+ } else if (strcmp(op, PCMK__CONTROLD_CMD_NODES) == 0) {
|
||||
+ return handle_node_list(stored_msg);
|
||||
+
|
||||
/*========== (NOT_DC)-Only Actions ==========*/
|
||||
} else if (!AM_I_DC) {
|
||||
|
||||
diff --git a/include/crm/common/ipc_controld.h b/include/crm/common/ipc_controld.h
|
||||
index 0ebabfc..b817357 100644
|
||||
--- a/include/crm/common/ipc_controld.h
|
||||
+++ b/include/crm/common/ipc_controld.h
|
||||
@@ -22,6 +22,7 @@ extern "C" {
|
||||
*/
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
+#include <glib.h> // GList
|
||||
#include <libxml/tree.h> // xmlNode
|
||||
#include <crm/common/ipc.h> // pcmk_ipc_api_t
|
||||
|
||||
@@ -32,8 +33,16 @@ enum pcmk_controld_api_reply {
|
||||
pcmk_controld_reply_info,
|
||||
pcmk_controld_reply_resource,
|
||||
pcmk_controld_reply_ping,
|
||||
+ pcmk_controld_reply_nodes,
|
||||
};
|
||||
|
||||
+// Node information passed with pcmk_controld_reply_nodes
|
||||
+typedef struct {
|
||||
+ uint32_t id;
|
||||
+ const char *uname;
|
||||
+ const char *state;
|
||||
+} pcmk_controld_api_node_t;
|
||||
+
|
||||
/*!
|
||||
* Controller reply passed to event callback
|
||||
*
|
||||
@@ -72,6 +81,9 @@ typedef struct {
|
||||
const char *fsa_state;
|
||||
const char *result;
|
||||
} ping;
|
||||
+
|
||||
+ // pcmk_controld_reply_nodes
|
||||
+ GList *nodes; // list of pcmk_controld_api_node_t *
|
||||
} data;
|
||||
} pcmk_controld_api_reply_t;
|
||||
|
||||
@@ -88,6 +100,7 @@ int pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
|
||||
const char *provider, const char *type,
|
||||
bool cib_only);
|
||||
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name);
|
||||
+int pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api);
|
||||
int pcmk_controld_api_shutdown(pcmk_ipc_api_t *api, const char *node_name);
|
||||
int pcmk_controld_api_start_election(pcmk_ipc_api_t *api);
|
||||
unsigned int pcmk_controld_api_replies_expected(pcmk_ipc_api_t *api);
|
||||
diff --git a/include/crm_internal.h b/include/crm_internal.h
|
||||
index fd56fc6..cf8999f 100644
|
||||
--- a/include/crm_internal.h
|
||||
+++ b/include/crm_internal.h
|
||||
@@ -122,6 +122,7 @@ pid_t pcmk_locate_sbd(void);
|
||||
#define PCMK__ATTRD_CMD_SYNC_RESPONSE "sync-response"
|
||||
#define PCMK__ATTRD_CMD_CLEAR_FAILURE "clear-failure"
|
||||
|
||||
+#define PCMK__CONTROLD_CMD_NODES "list-nodes"
|
||||
|
||||
/*
|
||||
* Environment variables used by Pacemaker
|
||||
diff --git a/lib/common/ipc_controld.c b/lib/common/ipc_controld.c
|
||||
index 22bb733..a733dd3 100644
|
||||
--- a/lib/common/ipc_controld.c
|
||||
+++ b/lib/common/ipc_controld.c
|
||||
@@ -120,6 +120,28 @@ set_ping_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
|
||||
data->data.ping.result = crm_element_value(msg_data, XML_PING_ATTR_STATUS);
|
||||
}
|
||||
|
||||
+static void
|
||||
+set_nodes_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
|
||||
+{
|
||||
+ pcmk_controld_api_node_t *node_info;
|
||||
+
|
||||
+ data->reply_type = pcmk_controld_reply_nodes;
|
||||
+ for (xmlNode *node = first_named_child(msg_data, XML_CIB_TAG_NODE);
|
||||
+ node != NULL; node = crm_next_same_xml(node)) {
|
||||
+
|
||||
+ long long id_ll = 0;
|
||||
+
|
||||
+ node_info = calloc(1, sizeof(pcmk_controld_api_node_t));
|
||||
+ crm_element_value_ll(node, XML_ATTR_ID, &id_ll);
|
||||
+ if (id_ll > 0) {
|
||||
+ node_info->id = id_ll;
|
||||
+ }
|
||||
+ node_info->uname = crm_element_value(node, XML_ATTR_UNAME);
|
||||
+ node_info->state = crm_element_value(node, XML_NODE_IN_CLUSTER);
|
||||
+ data->data.nodes = g_list_prepend(data->data.nodes, node_info);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static bool
|
||||
reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
|
||||
{
|
||||
@@ -201,6 +223,9 @@ dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
|
||||
} else if (!strcmp(value, CRM_OP_PING)) {
|
||||
set_ping_data(&reply_data, msg_data);
|
||||
|
||||
+ } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
+ set_nodes_data(&reply_data, msg_data);
|
||||
+
|
||||
} else {
|
||||
crm_debug("Unrecognizable controller message: unknown command '%s'",
|
||||
value);
|
||||
@@ -210,6 +235,11 @@ dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
|
||||
}
|
||||
|
||||
pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
|
||||
+
|
||||
+ // Free any reply data that was allocated
|
||||
+ if (safe_str_eq(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
+ g_list_free_full(reply_data.data.nodes, free);
|
||||
+ }
|
||||
}
|
||||
|
||||
pcmk__ipc_methods_t *
|
||||
@@ -376,6 +406,29 @@ pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
|
||||
}
|
||||
|
||||
/*!
|
||||
+ * \brief Ask the controller for cluster information
|
||||
+ *
|
||||
+ * \param[in] api Controller connection
|
||||
+ *
|
||||
+ * \return Standard Pacemaker return code
|
||||
+ * \note Event callback will get a reply of type pcmk_controld_reply_nodes.
|
||||
+ */
|
||||
+int
|
||||
+pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api)
|
||||
+{
|
||||
+ xmlNode *request;
|
||||
+ int rc = EINVAL;
|
||||
+
|
||||
+ request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
|
||||
+ NULL);
|
||||
+ if (request != NULL) {
|
||||
+ rc = send_controller_request(api, request, true);
|
||||
+ free_xml(request);
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*!
|
||||
* \internal
|
||||
* \brief Ask the controller to shut down
|
||||
*
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 74e2d8d18bf534c1ec6f0e0f44a90772d393a553 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 11:51:56 -0500
|
||||
Subject: [PATCH 2/3] Refactor: functionize numeric comparisons of strings
|
||||
|
||||
This moves the guts of sort_node_uname() from libpe_status to a new function,
|
||||
pcmk_numeric_strcasecmp(), in libcrmcommon, so it can be used with strings and
|
||||
not just pe_node_t objects.
|
||||
---
|
||||
include/crm/common/util.h | 1 +
|
||||
lib/common/strings.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
lib/pengine/utils.c | 50 ++----------------------------------
|
||||
3 files changed, 68 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/util.h b/include/crm/common/util.h
|
||||
index 67d74d2..bb97b0a 100644
|
||||
--- a/include/crm/common/util.h
|
||||
+++ b/include/crm/common/util.h
|
||||
@@ -59,6 +59,7 @@ gboolean crm_strcase_equal(gconstpointer a, gconstpointer b);
|
||||
char *crm_strdup_printf(char const *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end);
|
||||
gboolean pcmk__str_in_list(GList *lst, const gchar *s);
|
||||
+int pcmk_numeric_strcasecmp(const char *s1, const char *s2);
|
||||
|
||||
# define safe_str_eq(a, b) crm_str_eq(a, b, FALSE)
|
||||
# define crm_str_hash g_str_hash_traditional
|
||||
diff --git a/lib/common/strings.c b/lib/common/strings.c
|
||||
index 4562738..bd68ccf 100644
|
||||
--- a/lib/common/strings.c
|
||||
+++ b/lib/common/strings.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
+#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <bzlib.h>
|
||||
#include <sys/types.h>
|
||||
@@ -715,3 +716,67 @@ pcmk__str_none_of(const char *s, ...)
|
||||
|
||||
return g_list_find_custom(lst, s, (GCompareFunc) strcmp) != NULL;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * \brief Sort strings, with numeric portions sorted numerically
|
||||
+ *
|
||||
+ * Sort two strings case-insensitively like strcasecmp(), but with any numeric
|
||||
+ * portions of the string sorted numerically. This is particularly useful for
|
||||
+ * node names (for example, "node10" will sort higher than "node9" but lower
|
||||
+ * than "remotenode9").
|
||||
+ *
|
||||
+ * \param[in] s1 First string to compare (must not be NULL)
|
||||
+ * \param[in] s2 Second string to compare (must not be NULL)
|
||||
+ *
|
||||
+ * \retval -1 \p s1 comes before \p s2
|
||||
+ * \retval 0 \p s1 and \p s2 are equal
|
||||
+ * \retval 1 \p s1 comes after \p s2
|
||||
+ */
|
||||
+int
|
||||
+pcmk_numeric_strcasecmp(const char *s1, const char *s2)
|
||||
+{
|
||||
+ while (*s1 && *s2) {
|
||||
+ if (isdigit(*s1) && isdigit(*s2)) {
|
||||
+ // If node names contain a number, sort numerically
|
||||
+
|
||||
+ char *end1 = NULL;
|
||||
+ char *end2 = NULL;
|
||||
+ long num1 = strtol(s1, &end1, 10);
|
||||
+ long num2 = strtol(s2, &end2, 10);
|
||||
+
|
||||
+ // allow ordering e.g. 007 > 7
|
||||
+ size_t len1 = end1 - s1;
|
||||
+ size_t len2 = end2 - s2;
|
||||
+
|
||||
+ if (num1 < num2) {
|
||||
+ return -1;
|
||||
+ } else if (num1 > num2) {
|
||||
+ return 1;
|
||||
+ } else if (len1 < len2) {
|
||||
+ return -1;
|
||||
+ } else if (len1 > len2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ s1 = end1;
|
||||
+ s2 = end2;
|
||||
+ } else {
|
||||
+ // Compare non-digits case-insensitively
|
||||
+ int lower1 = tolower(*s1);
|
||||
+ int lower2 = tolower(*s2);
|
||||
+
|
||||
+ if (lower1 < lower2) {
|
||||
+ return -1;
|
||||
+ } else if (lower1 > lower2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ ++s1;
|
||||
+ ++s2;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!*s1 && *s2) {
|
||||
+ return -1;
|
||||
+ } else if (*s1 && !*s2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
|
||||
index ce3c260..584def4 100644
|
||||
--- a/lib/pengine/utils.c
|
||||
+++ b/lib/pengine/utils.c
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <crm/common/xml.h>
|
||||
#include <crm/common/util.h>
|
||||
|
||||
-#include <ctype.h>
|
||||
#include <glib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -214,53 +213,8 @@ pe__node_list2table(GList *list)
|
||||
gint
|
||||
sort_node_uname(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
- const char *name_a = ((const pe_node_t *) a)->details->uname;
|
||||
- const char *name_b = ((const pe_node_t *) b)->details->uname;
|
||||
-
|
||||
- while (*name_a && *name_b) {
|
||||
- if (isdigit(*name_a) && isdigit(*name_b)) {
|
||||
- // If node names contain a number, sort numerically
|
||||
-
|
||||
- char *end_a = NULL;
|
||||
- char *end_b = NULL;
|
||||
- long num_a = strtol(name_a, &end_a, 10);
|
||||
- long num_b = strtol(name_b, &end_b, 10);
|
||||
-
|
||||
- // allow ordering e.g. 007 > 7
|
||||
- size_t len_a = end_a - name_a;
|
||||
- size_t len_b = end_b - name_b;
|
||||
-
|
||||
- if (num_a < num_b) {
|
||||
- return -1;
|
||||
- } else if (num_a > num_b) {
|
||||
- return 1;
|
||||
- } else if (len_a < len_b) {
|
||||
- return -1;
|
||||
- } else if (len_a > len_b) {
|
||||
- return 1;
|
||||
- }
|
||||
- name_a = end_a;
|
||||
- name_b = end_b;
|
||||
- } else {
|
||||
- // Compare non-digits case-insensitively
|
||||
- int lower_a = tolower(*name_a);
|
||||
- int lower_b = tolower(*name_b);
|
||||
-
|
||||
- if (lower_a < lower_b) {
|
||||
- return -1;
|
||||
- } else if (lower_a > lower_b) {
|
||||
- return 1;
|
||||
- }
|
||||
- ++name_a;
|
||||
- ++name_b;
|
||||
- }
|
||||
- }
|
||||
- if (!*name_a && *name_b) {
|
||||
- return -1;
|
||||
- } else if (*name_a && !*name_b) {
|
||||
- return 1;
|
||||
- }
|
||||
- return 0;
|
||||
+ return pcmk_numeric_strcasecmp(((const pe_node_t *) a)->details->uname,
|
||||
+ ((const pe_node_t *) b)->details->uname);
|
||||
}
|
||||
|
||||
/*!
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 8461509158e06365122dc741c527c83c94e966ce Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 24 Apr 2020 19:35:19 -0500
|
||||
Subject: [PATCH 3/3] Fix: tools: crm_node -l and -p now work from Pacemaker
|
||||
Remote nodes
|
||||
|
||||
crm_node now asks the controller for the cluster node list, instead of
|
||||
pacemakerd. This allows it to work from Pacemaker Remote nodes, since
|
||||
controller IPC is proxied but pacemakerd IPC is not.
|
||||
---
|
||||
tools/crm_node.c | 176 +++++++++++++++++++++----------------------------------
|
||||
1 file changed, 67 insertions(+), 109 deletions(-)
|
||||
|
||||
diff --git a/tools/crm_node.c b/tools/crm_node.c
|
||||
index 57c2ee5..146454d 100644
|
||||
--- a/tools/crm_node.c
|
||||
+++ b/tools/crm_node.c
|
||||
@@ -130,6 +130,16 @@ remove_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError *
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static gint
|
||||
+sort_node(gconstpointer a, gconstpointer b)
|
||||
+{
|
||||
+ const pcmk_controld_api_node_t *node_a = a;
|
||||
+ const pcmk_controld_api_node_t *node_b = b;
|
||||
+
|
||||
+ return pcmk_numeric_strcasecmp((node_a->uname? node_a->uname : ""),
|
||||
+ (node_b->uname? node_b->uname : ""));
|
||||
+}
|
||||
+
|
||||
static void
|
||||
controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
enum pcmk_ipc_event event_type, crm_exit_t status,
|
||||
@@ -157,15 +167,16 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
crm_exit_str(status));
|
||||
goto done;
|
||||
}
|
||||
- if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
- fprintf(stderr, "error: Unknown reply type %d from controller\n",
|
||||
- reply->reply_type);
|
||||
- goto done;
|
||||
- }
|
||||
|
||||
// Parse desired info from reply and display to user
|
||||
switch (options.command) {
|
||||
case 'i':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
if (reply->data.node_info.id == 0) {
|
||||
fprintf(stderr,
|
||||
"error: Controller reply did not contain node ID\n");
|
||||
@@ -177,6 +188,12 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
|
||||
case 'n':
|
||||
case 'N':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
if (reply->data.node_info.uname == NULL) {
|
||||
fprintf(stderr, "Node is not known to cluster\n");
|
||||
exit_code = CRM_EX_NOHOST;
|
||||
@@ -186,6 +203,12 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
printf("%d\n", reply->data.node_info.have_quorum);
|
||||
if (!(reply->data.node_info.have_quorum)) {
|
||||
exit_code = CRM_EX_QUORUM;
|
||||
@@ -193,6 +216,36 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
}
|
||||
break;
|
||||
|
||||
+ case 'l':
|
||||
+ case 'p':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_nodes) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
+ reply->data.nodes = g_list_sort(reply->data.nodes, sort_node);
|
||||
+ for (GList *node_iter = reply->data.nodes;
|
||||
+ node_iter != NULL; node_iter = node_iter->next) {
|
||||
+
|
||||
+ pcmk_controld_api_node_t *node = node_iter->data;
|
||||
+ const char *uname = (node->uname? node->uname : "");
|
||||
+ const char *state = (node->state? node->state : "");
|
||||
+
|
||||
+ if (options.command == 'l') {
|
||||
+ printf("%lu %s %s\n",
|
||||
+ (unsigned long) node->id, uname, state);
|
||||
+
|
||||
+ // i.e. CRM_NODE_MEMBER, but we don't want to include cluster.h
|
||||
+ } else if (!strcmp(state, "member")) {
|
||||
+ printf("%s ", uname);
|
||||
+ }
|
||||
+ }
|
||||
+ if (options.command == 'p') {
|
||||
+ printf("\n");
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
fprintf(stderr, "internal error: Controller reply not expected\n");
|
||||
exit_code = CRM_EX_SOFTWARE;
|
||||
@@ -207,7 +260,7 @@ done:
|
||||
}
|
||||
|
||||
static void
|
||||
-run_controller_mainloop(uint32_t nodeid)
|
||||
+run_controller_mainloop(uint32_t nodeid, bool list_nodes)
|
||||
{
|
||||
pcmk_ipc_api_t *controld_api = NULL;
|
||||
int rc;
|
||||
@@ -233,7 +286,11 @@ run_controller_mainloop(uint32_t nodeid)
|
||||
return;
|
||||
}
|
||||
|
||||
- rc = pcmk_controld_api_node_info(controld_api, nodeid);
|
||||
+ if (list_nodes) {
|
||||
+ rc = pcmk_controld_api_list_nodes(controld_api);
|
||||
+ } else {
|
||||
+ rc = pcmk_controld_api_node_info(controld_api, nodeid);
|
||||
+ }
|
||||
if (rc != pcmk_rc_ok) {
|
||||
fprintf(stderr, "error: Could not ping controller: %s\n",
|
||||
pcmk_rc_str(rc));
|
||||
@@ -263,7 +320,7 @@ print_node_name(void)
|
||||
|
||||
} else {
|
||||
// Otherwise ask the controller
|
||||
- run_controller_mainloop(0);
|
||||
+ run_controller_mainloop(0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,105 +501,6 @@ remove_node(const char *target_uname)
|
||||
exit_code = CRM_EX_OK;
|
||||
}
|
||||
|
||||
-static gint
|
||||
-compare_node_xml(gconstpointer a, gconstpointer b)
|
||||
-{
|
||||
- const char *a_name = crm_element_value((xmlNode*) a, "uname");
|
||||
- const char *b_name = crm_element_value((xmlNode*) b, "uname");
|
||||
-
|
||||
- return strcmp((a_name? a_name : ""), (b_name? b_name : ""));
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-node_mcp_dispatch(const char *buffer, ssize_t length, gpointer userdata)
|
||||
-{
|
||||
- GList *nodes = NULL;
|
||||
- xmlNode *node = NULL;
|
||||
- xmlNode *msg = string2xml(buffer);
|
||||
- const char *uname;
|
||||
- const char *state;
|
||||
-
|
||||
- if (msg == NULL) {
|
||||
- fprintf(stderr, "error: Could not understand pacemakerd response\n");
|
||||
- exit_code = CRM_EX_PROTOCOL;
|
||||
- g_main_loop_quit(mainloop);
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- crm_log_xml_trace(msg, "message");
|
||||
-
|
||||
- for (node = __xml_first_child(msg); node != NULL; node = __xml_next(node)) {
|
||||
- nodes = g_list_insert_sorted(nodes, node, compare_node_xml);
|
||||
- }
|
||||
-
|
||||
- for (GList *iter = nodes; iter; iter = iter->next) {
|
||||
- node = (xmlNode*) iter->data;
|
||||
- uname = crm_element_value(node, "uname");
|
||||
- state = crm_element_value(node, "state");
|
||||
-
|
||||
- if (options.command == 'l') {
|
||||
- int id = 0;
|
||||
-
|
||||
- crm_element_value_int(node, "id", &id);
|
||||
- printf("%d %s %s\n", id, (uname? uname : ""), (state? state : ""));
|
||||
-
|
||||
- // This is CRM_NODE_MEMBER but we don't want to include cluster header
|
||||
- } else if ((options.command == 'p') && safe_str_eq(state, "member")) {
|
||||
- printf("%s ", (uname? uname : ""));
|
||||
- }
|
||||
- }
|
||||
- if (options.command == 'p') {
|
||||
- fprintf(stdout, "\n");
|
||||
- }
|
||||
-
|
||||
- free_xml(msg);
|
||||
- exit_code = CRM_EX_OK;
|
||||
- g_main_loop_quit(mainloop);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-lost_pacemakerd(gpointer user_data)
|
||||
-{
|
||||
- fprintf(stderr, "error: Lost connection to cluster\n");
|
||||
- exit_code = CRM_EX_DISCONNECT;
|
||||
- g_main_loop_quit(mainloop);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-run_pacemakerd_mainloop(void)
|
||||
-{
|
||||
- crm_ipc_t *ipc = NULL;
|
||||
- xmlNode *poke = NULL;
|
||||
- mainloop_io_t *source = NULL;
|
||||
-
|
||||
- struct ipc_client_callbacks ipc_callbacks = {
|
||||
- .dispatch = node_mcp_dispatch,
|
||||
- .destroy = lost_pacemakerd
|
||||
- };
|
||||
-
|
||||
- source = mainloop_add_ipc_client(CRM_SYSTEM_MCP, G_PRIORITY_DEFAULT, 0,
|
||||
- NULL, &ipc_callbacks);
|
||||
- ipc = mainloop_get_ipc_client(source);
|
||||
- if (ipc == NULL) {
|
||||
- fprintf(stderr,
|
||||
- "error: Could not connect to cluster (is it running?)\n");
|
||||
- exit_code = CRM_EX_DISCONNECT;
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // Sending anything will get us a list of nodes
|
||||
- poke = create_xml_node(NULL, "poke");
|
||||
- crm_ipc_send(ipc, poke, 0, 0, NULL);
|
||||
- free_xml(poke);
|
||||
-
|
||||
- // Handle reply via node_mcp_dispatch()
|
||||
- mainloop = g_main_loop_new(NULL, FALSE);
|
||||
- g_main_loop_run(mainloop);
|
||||
- g_main_loop_unref(mainloop);
|
||||
- mainloop = NULL;
|
||||
-}
|
||||
-
|
||||
static GOptionContext *
|
||||
build_arg_context(pcmk__common_args_t *args, GOptionGroup *group) {
|
||||
GOptionContext *context = NULL;
|
||||
@@ -627,11 +585,11 @@ main(int argc, char **argv)
|
||||
case 'i':
|
||||
case 'q':
|
||||
case 'N':
|
||||
- run_controller_mainloop(options.nodeid);
|
||||
+ run_controller_mainloop(options.nodeid, false);
|
||||
break;
|
||||
case 'l':
|
||||
case 'p':
|
||||
- run_pacemakerd_mainloop();
|
||||
+ run_controller_mainloop(0, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
--
|
||||
1.8.3.1
|
||||
|
34
SOURCES/009-timeout-log.patch
Normal file
34
SOURCES/009-timeout-log.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From b542a8f667002519fbc07693a796553746c43c12 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Sat, 11 Jul 2020 18:31:55 -0700
|
||||
Subject: [PATCH] Log: controld: Show action timer plus cluster-delay in
|
||||
action_timer cb
|
||||
|
||||
`action_timer_callback()` prints a misleading error message. If it
|
||||
times out waiting for an action result, the error message prints the
|
||||
timeout value followed by "(action timeout plus cluster-delay)".
|
||||
However, only the `action->timeout` value is displayed. `cluster-delay`
|
||||
is not added in.
|
||||
|
||||
Resolves: RHBZ#1856035
|
||||
---
|
||||
daemons/controld/controld_te_callbacks.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/controld/controld_te_callbacks.c b/daemons/controld/controld_te_callbacks.c
|
||||
index 8506f26..6ddaffe 100644
|
||||
--- a/daemons/controld/controld_te_callbacks.c
|
||||
+++ b/daemons/controld/controld_te_callbacks.c
|
||||
@@ -697,7 +697,8 @@ action_timer_callback(gpointer data)
|
||||
crm_err("Node %s did not send %s result (via %s) within %dms "
|
||||
"(action timeout plus cluster-delay)",
|
||||
(on_node? on_node : ""), (task? task : "unknown action"),
|
||||
- (via_node? via_node : "controller"), timer->timeout);
|
||||
+ (via_node? via_node : "controller"),
|
||||
+ timer->timeout + transition_graph->network_delay);
|
||||
print_action(LOG_ERR, "Aborting transition, action lost: ", timer->action);
|
||||
|
||||
timer->action->failed = TRUE;
|
||||
--
|
||||
1.8.3.1
|
||||
|
476
SOURCES/010-crm_mon.patch
Normal file
476
SOURCES/010-crm_mon.patch
Normal file
@ -0,0 +1,476 @@
|
||||
From 7056ae08bfa5cafeec9c454cb40aefa7553af6df Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 12:53:24 -0400
|
||||
Subject: [PATCH 1/4] Fix: libcrmcommon: Set out->priv to NULL in free_priv.
|
||||
|
||||
init won't do anything if priv is not NULL, so when the private data is
|
||||
freed, also set it to NULL. This prevents segfaults when reset is
|
||||
called.
|
||||
---
|
||||
lib/common/output_html.c | 1 +
|
||||
lib/common/output_log.c | 1 +
|
||||
lib/common/output_text.c | 1 +
|
||||
lib/common/output_xml.c | 1 +
|
||||
tools/crm_mon_curses.c | 1 +
|
||||
5 files changed, 5 insertions(+)
|
||||
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index c8f0088..fc06641 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -72,6 +72,7 @@ html_free_priv(pcmk__output_t *out) {
|
||||
g_queue_free(priv->parent_q);
|
||||
g_slist_free(priv->errors);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/lib/common/output_log.c b/lib/common/output_log.c
|
||||
index 5b45ce4..0208046 100644
|
||||
--- a/lib/common/output_log.c
|
||||
+++ b/lib/common/output_log.c
|
||||
@@ -44,6 +44,7 @@ log_free_priv(pcmk__output_t *out) {
|
||||
|
||||
g_queue_free(priv->prefixes);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/lib/common/output_text.c b/lib/common/output_text.c
|
||||
index 54c409a..8f15849 100644
|
||||
--- a/lib/common/output_text.c
|
||||
+++ b/lib/common/output_text.c
|
||||
@@ -43,6 +43,7 @@ text_free_priv(pcmk__output_t *out) {
|
||||
|
||||
g_queue_free(priv->parent_q);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
|
||||
index 8565bfe..858da3f 100644
|
||||
--- a/lib/common/output_xml.c
|
||||
+++ b/lib/common/output_xml.c
|
||||
@@ -54,6 +54,7 @@ xml_free_priv(pcmk__output_t *out) {
|
||||
g_queue_free(priv->parent_q);
|
||||
g_slist_free(priv->errors);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/tools/crm_mon_curses.c b/tools/crm_mon_curses.c
|
||||
index d93b847..e9cc023 100644
|
||||
--- a/tools/crm_mon_curses.c
|
||||
+++ b/tools/crm_mon_curses.c
|
||||
@@ -46,6 +46,7 @@ curses_free_priv(pcmk__output_t *out) {
|
||||
|
||||
g_queue_free(priv->parent_q);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 3779152993ca0e88dc407c918882568217f1b630 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 13:50:24 -0400
|
||||
Subject: [PATCH 2/4] Fix: libcrmcommon: Make reset and finish work more
|
||||
similarly.
|
||||
|
||||
When finish is called for HTML and XML output formats, various extra
|
||||
nodes and headers are added, errors are added, etc. None of this stuff
|
||||
happens on reset. For the HTML format, this also means things like the
|
||||
CGI headers and title don't get added when reset is called. Make these
|
||||
two functions much more similar.
|
||||
|
||||
Regression in 2.0.3.
|
||||
|
||||
See: rhbz#1857728
|
||||
---
|
||||
lib/common/output_html.c | 26 ++++++++++++++++----------
|
||||
lib/common/output_xml.c | 30 ++++++++++++++++--------------
|
||||
2 files changed, 32 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index fc06641..6127df2 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -113,18 +113,11 @@ add_error_node(gpointer data, gpointer user_data) {
|
||||
}
|
||||
|
||||
static void
|
||||
-html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+finish_reset_common(pcmk__output_t *out, crm_exit_t exit_status, bool print) {
|
||||
private_data_t *priv = out->priv;
|
||||
htmlNodePtr head_node = NULL;
|
||||
htmlNodePtr charset_node = NULL;
|
||||
|
||||
- /* If root is NULL, html_init failed and we are being called from pcmk__output_free
|
||||
- * in the pcmk__output_new path.
|
||||
- */
|
||||
- if (priv == NULL || priv->root == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (cgi_output && print) {
|
||||
fprintf(out->dest, "Content-Type: text/html\n\n");
|
||||
}
|
||||
@@ -174,6 +167,20 @@ html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy
|
||||
if (print) {
|
||||
htmlDocDump(out->dest, priv->root->doc);
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+ private_data_t *priv = out->priv;
|
||||
+
|
||||
+ /* If root is NULL, html_init failed and we are being called from pcmk__output_free
|
||||
+ * in the pcmk__output_new path.
|
||||
+ */
|
||||
+ if (priv == NULL || priv->root == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ finish_reset_common(out, exit_status, print);
|
||||
|
||||
if (copy_dest != NULL) {
|
||||
*copy_dest = copy_xml(priv->root);
|
||||
@@ -185,8 +192,7 @@ html_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
if (out->priv != NULL) {
|
||||
- private_data_t *priv = out->priv;
|
||||
- htmlDocDump(out->dest, priv->root->doc);
|
||||
+ finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
|
||||
html_free_priv(out);
|
||||
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
|
||||
index 858da3f..b64a71d 100644
|
||||
--- a/lib/common/output_xml.c
|
||||
+++ b/lib/common/output_xml.c
|
||||
@@ -106,17 +106,10 @@ add_error_node(gpointer data, gpointer user_data) {
|
||||
}
|
||||
|
||||
static void
|
||||
-xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+finish_reset_common(pcmk__output_t *out, crm_exit_t exit_status, bool print) {
|
||||
xmlNodePtr node;
|
||||
private_data_t *priv = out->priv;
|
||||
|
||||
- /* If root is NULL, xml_init failed and we are being called from pcmk__output_free
|
||||
- * in the pcmk__output_new path.
|
||||
- */
|
||||
- if (priv == NULL || priv->root == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (legacy_xml) {
|
||||
GSList *node = priv->errors;
|
||||
|
||||
@@ -148,6 +141,20 @@ xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_
|
||||
fprintf(out->dest, "%s", buf);
|
||||
free(buf);
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+ private_data_t *priv = out->priv;
|
||||
+
|
||||
+ /* If root is NULL, xml_init failed and we are being called from pcmk__output_free
|
||||
+ * in the pcmk__output_new path.
|
||||
+ */
|
||||
+ if (priv == NULL || priv->root == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ finish_reset_common(out, exit_status, print);
|
||||
|
||||
if (copy_dest != NULL) {
|
||||
*copy_dest = copy_xml(priv->root);
|
||||
@@ -156,15 +163,10 @@ xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_
|
||||
|
||||
static void
|
||||
xml_reset(pcmk__output_t *out) {
|
||||
- char *buf = NULL;
|
||||
-
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
if (out->priv != NULL) {
|
||||
- private_data_t *priv = out->priv;
|
||||
- buf = dump_xml_formatted_with_text(priv->root);
|
||||
- fprintf(out->dest, "%s", buf);
|
||||
- free(buf);
|
||||
+ finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
|
||||
xml_free_priv(out);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 0f8e4ca5d9a429c934f1e91a1bdf572efd07e0db Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 16:09:08 -0400
|
||||
Subject: [PATCH 3/4] Fix: tools, libcrmcommon: Reopen the output dest on
|
||||
reset.
|
||||
|
||||
This is needed when running crm_mon as a daemon. When we do a reset,
|
||||
we need to clear out any existing output destination and start writing
|
||||
again from the beginning. This really only matters when the destination
|
||||
is a file.
|
||||
|
||||
The extra freopen at the end of crm_mon is to handle when crm_mon is
|
||||
killed. We need to reset the output file to its beginning before
|
||||
calling finish.
|
||||
---
|
||||
lib/common/output_html.c | 3 +++
|
||||
lib/common/output_log.c | 3 +++
|
||||
lib/common/output_text.c | 3 +++
|
||||
lib/common/output_xml.c | 3 +++
|
||||
tools/crm_mon.c | 9 +++++++++
|
||||
5 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index 6127df2..6e21031 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -191,6 +191,9 @@ static void
|
||||
html_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
if (out->priv != NULL) {
|
||||
finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
diff --git a/lib/common/output_log.c b/lib/common/output_log.c
|
||||
index 0208046..8422ac2 100644
|
||||
--- a/lib/common/output_log.c
|
||||
+++ b/lib/common/output_log.c
|
||||
@@ -72,6 +72,9 @@ static void
|
||||
log_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
log_free_priv(out);
|
||||
log_init(out);
|
||||
}
|
||||
diff --git a/lib/common/output_text.c b/lib/common/output_text.c
|
||||
index 8f15849..2f7e5b0 100644
|
||||
--- a/lib/common/output_text.c
|
||||
+++ b/lib/common/output_text.c
|
||||
@@ -75,6 +75,9 @@ static void
|
||||
text_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
text_free_priv(out);
|
||||
text_init(out);
|
||||
}
|
||||
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
|
||||
index b64a71d..9f8e01b 100644
|
||||
--- a/lib/common/output_xml.c
|
||||
+++ b/lib/common/output_xml.c
|
||||
@@ -165,6 +165,9 @@ static void
|
||||
xml_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
if (out->priv != NULL) {
|
||||
finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
|
||||
index b2e143b..10624c1 100644
|
||||
--- a/tools/crm_mon.c
|
||||
+++ b/tools/crm_mon.c
|
||||
@@ -2014,6 +2014,10 @@ mon_refresh_display(gpointer user_data)
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (options.daemonize) {
|
||||
+ out->reset(out);
|
||||
+ }
|
||||
+
|
||||
stonith_history_free(stonith_history);
|
||||
stonith_history = NULL;
|
||||
pe_reset_working_set(mon_data_set);
|
||||
@@ -2179,6 +2183,11 @@ clean_up(crm_exit_t exit_code)
|
||||
* crm_mon to be able to do so.
|
||||
*/
|
||||
if (out != NULL) {
|
||||
+ if (options.daemonize) {
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+ }
|
||||
+
|
||||
switch (output_format) {
|
||||
case mon_output_cgi:
|
||||
case mon_output_html:
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From b655c039414d2c7af77c3532222b04684ef1f3d0 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Fri, 17 Jul 2020 10:58:32 -0400
|
||||
Subject: [PATCH 4/4] Fix: tools: Add the http-equiv header to crm_mon at the
|
||||
right time.
|
||||
|
||||
This header is only getting added on termination, which is not a lot of
|
||||
help if you're running crm_mon in daemonize mode. Putting this header
|
||||
in at the right time requires a couple changes:
|
||||
|
||||
* pcmk__html_add_header doesn't need a parent argument. It was not
|
||||
being used in the first place.
|
||||
|
||||
* The extra_headers list in output_html.c should not be freed in the
|
||||
reset function. This means it would get freed after every time the
|
||||
daemonized output is refreshed, which means the header would have to be
|
||||
added every time too. extra_headers will now only be freed when the
|
||||
program exits. This is a behavior change, but I can't see why it's
|
||||
going to be a problem.
|
||||
|
||||
* To support that, we need to copy each item in the extra_headers list
|
||||
when it gets added to the output XML document. This prevents segfaults
|
||||
when we later free that document.
|
||||
|
||||
* handle_html_output no longer needs to exist. That function only
|
||||
existed to add the http-equiv header at the end, which is wrong.
|
||||
---
|
||||
include/crm/common/output.h | 5 ++---
|
||||
lib/common/output_html.c | 7 ++++---
|
||||
tools/crm_mon.c | 26 +++++++-------------------
|
||||
3 files changed, 13 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/output.h b/include/crm/common/output.h
|
||||
index e7c9417..186bcfe 100644
|
||||
--- a/include/crm/common/output.h
|
||||
+++ b/include/crm/common/output.h
|
||||
@@ -703,15 +703,14 @@ pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, con
|
||||
* the following code would generate the tag "<meta http-equiv='refresh' content='19'>":
|
||||
*
|
||||
* \code
|
||||
- * pcmk__html_add_header(parent, "meta", "http-equiv", "refresh", "content", "19", NULL);
|
||||
+ * pcmk__html_add_header("meta", "http-equiv", "refresh", "content", "19", NULL);
|
||||
* \endcode
|
||||
*
|
||||
- * \param[in,out] parent The node that will be the parent of the new node.
|
||||
* \param[in] name The HTML tag for the new node.
|
||||
* \param[in] ... A NULL-terminated key/value list of attributes.
|
||||
*/
|
||||
void
|
||||
-pcmk__html_add_header(xmlNodePtr parent, const char *name, ...)
|
||||
+pcmk__html_add_header(const char *name, ...)
|
||||
G_GNUC_NULL_TERMINATED;
|
||||
|
||||
#ifdef __cplusplus
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index 6e21031..259e412 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -139,7 +139,7 @@ finish_reset_common(pcmk__output_t *out, crm_exit_t exit_status, bool print) {
|
||||
|
||||
/* Add any extra header nodes the caller might have created. */
|
||||
for (int i = 0; i < g_slist_length(extra_headers); i++) {
|
||||
- xmlAddChild(head_node, g_slist_nth_data(extra_headers, i));
|
||||
+ xmlAddChild(head_node, xmlCopyNode(g_slist_nth_data(extra_headers, i), 1));
|
||||
}
|
||||
|
||||
/* Stylesheets are included two different ways. The first is via a built-in
|
||||
@@ -185,6 +185,8 @@ html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy
|
||||
if (copy_dest != NULL) {
|
||||
*copy_dest = copy_xml(priv->root);
|
||||
}
|
||||
+
|
||||
+ g_slist_free_full(extra_headers, (GDestroyNotify) xmlFreeNode);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -199,7 +201,6 @@ html_reset(pcmk__output_t *out) {
|
||||
}
|
||||
|
||||
html_free_priv(out);
|
||||
- g_slist_free_full(extra_headers, (GDestroyNotify) xmlFreeNode);
|
||||
html_init(out);
|
||||
}
|
||||
|
||||
@@ -412,7 +413,7 @@ pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, con
|
||||
}
|
||||
|
||||
void
|
||||
-pcmk__html_add_header(xmlNodePtr parent, const char *name, ...) {
|
||||
+pcmk__html_add_header(const char *name, ...) {
|
||||
htmlNodePtr header_node;
|
||||
va_list ap;
|
||||
|
||||
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
|
||||
index 10624c1..7fd2b9c 100644
|
||||
--- a/tools/crm_mon.c
|
||||
+++ b/tools/crm_mon.c
|
||||
@@ -1346,6 +1346,12 @@ main(int argc, char **argv)
|
||||
options.mon_ops |= mon_op_print_timing | mon_op_inactive_resources;
|
||||
}
|
||||
|
||||
+ if ((output_format == mon_output_html || output_format == mon_output_cgi) &&
|
||||
+ out->dest != stdout) {
|
||||
+ pcmk__html_add_header("meta", "http-equiv", "refresh", "content",
|
||||
+ crm_itoa(options.reconnect_msec/1000), NULL);
|
||||
+ }
|
||||
+
|
||||
crm_info("Starting %s", crm_system_name);
|
||||
|
||||
if (cib) {
|
||||
@@ -2106,15 +2112,6 @@ clean_up_connections(void)
|
||||
}
|
||||
}
|
||||
|
||||
-static void
|
||||
-handle_html_output(crm_exit_t exit_code) {
|
||||
- xmlNodePtr html = NULL;
|
||||
-
|
||||
- pcmk__html_add_header(html, "meta", "http-equiv", "refresh", "content",
|
||||
- crm_itoa(options.reconnect_msec/1000), NULL);
|
||||
- out->finish(out, exit_code, true, (void **) &html);
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* De-init ncurses, disconnect from the CIB manager, disconnect fencing,
|
||||
* deallocate memory and show usage-message if requested.
|
||||
@@ -2188,16 +2185,7 @@ clean_up(crm_exit_t exit_code)
|
||||
CRM_ASSERT(out->dest != NULL);
|
||||
}
|
||||
|
||||
- switch (output_format) {
|
||||
- case mon_output_cgi:
|
||||
- case mon_output_html:
|
||||
- handle_html_output(exit_code);
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- out->finish(out, exit_code, true, NULL);
|
||||
- break;
|
||||
- }
|
||||
+ out->finish(out, exit_code, true, NULL);
|
||||
|
||||
pcmk__output_free(out);
|
||||
pcmk__unregister_formats();
|
||||
--
|
||||
1.8.3.1
|
||||
|
270
SOURCES/011-cts.patch
Normal file
270
SOURCES/011-cts.patch
Normal file
@ -0,0 +1,270 @@
|
||||
From 4e190ebc5460563bae2586b28afb0415f2eb3d1a Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Wed, 1 Jul 2020 20:38:16 -0500
|
||||
Subject: [PATCH 1/4] Test: CTS: libqb shared memory creates directories now
|
||||
|
||||
... so use "rm -rf" instead of "rm -f"
|
||||
---
|
||||
cts/CTS.py.in | 2 +-
|
||||
cts/CTSaudits.py | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cts/CTS.py.in b/cts/CTS.py.in
|
||||
index c418318..091bb1f 100644
|
||||
--- a/cts/CTS.py.in
|
||||
+++ b/cts/CTS.py.in
|
||||
@@ -546,7 +546,7 @@ class ClusterManager(UserDict):
|
||||
if self.rsh(node, self.templates["StopCmd"]) == 0:
|
||||
# Make sure we can continue even if corosync leaks
|
||||
# fdata-* is the old name
|
||||
- #self.rsh(node, "rm -f /dev/shm/qb-* /dev/shm/fdata-*")
|
||||
+ #self.rsh(node, "rm -rf /dev/shm/qb-* /dev/shm/fdata-*")
|
||||
self.ShouldBeStatus[node] = "down"
|
||||
self.cluster_stable(self.Env["DeadTime"])
|
||||
return 1
|
||||
diff --git a/cts/CTSaudits.py b/cts/CTSaudits.py
|
||||
index b7e0827..cc82171 100755
|
||||
--- a/cts/CTSaudits.py
|
||||
+++ b/cts/CTSaudits.py
|
||||
@@ -233,7 +233,7 @@ class FileAudit(ClusterAudit):
|
||||
for line in lsout:
|
||||
self.CM.debug("ps[%s]: %s" % (node, line))
|
||||
|
||||
- self.CM.rsh(node, "rm -f /dev/shm/qb-*")
|
||||
+ self.CM.rsh(node, "rm -rf /dev/shm/qb-*")
|
||||
|
||||
else:
|
||||
self.CM.debug("Skipping %s" % node)
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 4316507d50d51c7864d8d34aac1da31a232b9f42 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 16:09:20 -0500
|
||||
Subject: [PATCH 2/4] Test: CTS: ignore error logged by recent pcs versions
|
||||
|
||||
... because it is expected when a node is fenced, and we should already see
|
||||
pacemaker errors if a node is unexpectedly fenced
|
||||
---
|
||||
cts/patterns.py | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/cts/patterns.py b/cts/patterns.py
|
||||
index 96d6471..7eed90c 100644
|
||||
--- a/cts/patterns.py
|
||||
+++ b/cts/patterns.py
|
||||
@@ -21,6 +21,10 @@ class BasePatterns(object):
|
||||
|
||||
# Logging bug in some versions of libvirtd
|
||||
r"libvirtd.*: internal error: Failed to parse PCI config address",
|
||||
+
|
||||
+ # pcs can log this when node is fenced, but fencing is OK in some
|
||||
+ # tests (and we will catch it in pacemaker logs when not OK)
|
||||
+ r"pcs.daemon:No response from: .* request: get_configs, error:",
|
||||
]
|
||||
self.BadNews = []
|
||||
self.components = {}
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 598ae0f65bad6ed16978d1ab6e24e8e358e0a1a4 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 20:40:00 -0500
|
||||
Subject: [PATCH 3/4] Low: libcrmcommon: avoid assertion on controller protocol
|
||||
errors
|
||||
|
||||
Previously, after a protocol error, we would set reply to NULL and then try to
|
||||
call crm_element_value() on it, which would log an assertion.
|
||||
---
|
||||
lib/common/ipc_controld.c | 46 ++++++++++++++++++++++------------------------
|
||||
1 file changed, 22 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/common/ipc_controld.c b/lib/common/ipc_controld.c
|
||||
index 5917cc5..22cb9e0 100644
|
||||
--- a/lib/common/ipc_controld.c
|
||||
+++ b/lib/common/ipc_controld.c
|
||||
@@ -187,53 +187,51 @@ dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
|
||||
crm_debug("Unrecognizable controller message: invalid message type '%s'",
|
||||
crm_str(value));
|
||||
status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
if (crm_element_value(reply, XML_ATTR_REFERENCE) == NULL) {
|
||||
crm_debug("Unrecognizable controller message: no reference");
|
||||
status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
value = crm_element_value(reply, F_CRM_TASK);
|
||||
if (value == NULL) {
|
||||
crm_debug("Unrecognizable controller message: no command name");
|
||||
status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
// Parse useful info from reply
|
||||
|
||||
- if (reply != NULL) {
|
||||
- reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
|
||||
- reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
|
||||
- msg_data = get_message_xml(reply, F_CRM_DATA);
|
||||
+ reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
|
||||
+ reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
|
||||
+ msg_data = get_message_xml(reply, F_CRM_DATA);
|
||||
|
||||
- if (!strcmp(value, CRM_OP_REPROBE)) {
|
||||
- reply_data.reply_type = pcmk_controld_reply_reprobe;
|
||||
+ if (!strcmp(value, CRM_OP_REPROBE)) {
|
||||
+ reply_data.reply_type = pcmk_controld_reply_reprobe;
|
||||
|
||||
- } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
|
||||
- set_node_info_data(&reply_data, msg_data);
|
||||
+ } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
|
||||
+ set_node_info_data(&reply_data, msg_data);
|
||||
|
||||
- } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
|
||||
- reply_data.reply_type = pcmk_controld_reply_resource;
|
||||
- reply_data.data.resource.node_state = msg_data;
|
||||
+ } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
|
||||
+ reply_data.reply_type = pcmk_controld_reply_resource;
|
||||
+ reply_data.data.resource.node_state = msg_data;
|
||||
|
||||
- } else if (!strcmp(value, CRM_OP_PING)) {
|
||||
- set_ping_data(&reply_data, msg_data);
|
||||
+ } else if (!strcmp(value, CRM_OP_PING)) {
|
||||
+ set_ping_data(&reply_data, msg_data);
|
||||
|
||||
- } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
- set_nodes_data(&reply_data, msg_data);
|
||||
+ } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
+ set_nodes_data(&reply_data, msg_data);
|
||||
|
||||
- } else {
|
||||
- crm_debug("Unrecognizable controller message: unknown command '%s'",
|
||||
- value);
|
||||
- status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
- }
|
||||
+ } else {
|
||||
+ crm_debug("Unrecognizable controller message: unknown command '%s'",
|
||||
+ value);
|
||||
+ status = CRM_EX_PROTOCOL;
|
||||
}
|
||||
|
||||
+done:
|
||||
pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
|
||||
|
||||
// Free any reply data that was allocated
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 5ae4101b60f8c0cd96eb2097a65a59aaa1750d73 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 17 Jul 2020 17:20:23 -0500
|
||||
Subject: [PATCH 4/4] Log: fencer: don't log assertion if unable to create full
|
||||
request reply
|
||||
|
||||
Previously, we would log an assertion and a warning if asked to create a reply
|
||||
to a NULL request. However there is a possible sequence for this to happen:
|
||||
|
||||
- Some nodes are up and some down at cluster start-up
|
||||
- One node is elected DC and schedules fencing of the down nodes
|
||||
- Fencing is initiated for one of the down nodes
|
||||
- One of the other down nodes comes up and is elected DC
|
||||
- The fencing result comes back and all peers (including new DC) are notified
|
||||
- New DC tries to create a notification for its client (the controller)
|
||||
but doesn't know anything about the initial request
|
||||
|
||||
For now, just log a warning and drop the assertion. Longer term, maybe we
|
||||
should synchronize in-flight request information when a fencer joins the
|
||||
process group.
|
||||
---
|
||||
daemons/fenced/fenced_commands.c | 55 +++++++++++++++++++++++-----------------
|
||||
1 file changed, 32 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
||||
index 05c5437..9c27d61 100644
|
||||
--- a/daemons/fenced/fenced_commands.c
|
||||
+++ b/daemons/fenced/fenced_commands.c
|
||||
@@ -2336,22 +2336,8 @@ stonith_fence(xmlNode * msg)
|
||||
xmlNode *
|
||||
stonith_construct_reply(xmlNode * request, const char *output, xmlNode * data, int rc)
|
||||
{
|
||||
- int lpc = 0;
|
||||
xmlNode *reply = NULL;
|
||||
|
||||
- const char *name = NULL;
|
||||
- const char *value = NULL;
|
||||
-
|
||||
- const char *names[] = {
|
||||
- F_STONITH_OPERATION,
|
||||
- F_STONITH_CALLID,
|
||||
- F_STONITH_CLIENTID,
|
||||
- F_STONITH_CLIENTNAME,
|
||||
- F_STONITH_REMOTE_OP_ID,
|
||||
- F_STONITH_CALLOPTS
|
||||
- };
|
||||
-
|
||||
- crm_trace("Creating a basic reply");
|
||||
reply = create_xml_node(NULL, T_STONITH_REPLY);
|
||||
|
||||
crm_xml_add(reply, "st_origin", __FUNCTION__);
|
||||
@@ -2359,16 +2345,39 @@ stonith_construct_reply(xmlNode * request, const char *output, xmlNode * data, i
|
||||
crm_xml_add(reply, "st_output", output);
|
||||
crm_xml_add_int(reply, F_STONITH_RC, rc);
|
||||
|
||||
- CRM_CHECK(request != NULL, crm_warn("Can't create a sane reply"); return reply);
|
||||
- for (lpc = 0; lpc < DIMOF(names); lpc++) {
|
||||
- name = names[lpc];
|
||||
- value = crm_element_value(request, name);
|
||||
- crm_xml_add(reply, name, value);
|
||||
- }
|
||||
+ if (request == NULL) {
|
||||
+ /* Most likely, this is the result of a stonith operation that was
|
||||
+ * initiated before we came up. Unfortunately that means we lack enough
|
||||
+ * information to provide clients with a full result.
|
||||
+ *
|
||||
+ * @TODO Maybe synchronize this information at start-up?
|
||||
+ */
|
||||
+ crm_warn("Missing request information for client notifications for "
|
||||
+ "operation with result %d (initiated before we came up?)", rc);
|
||||
|
||||
- if (data != NULL) {
|
||||
- crm_trace("Attaching reply output");
|
||||
- add_message_xml(reply, F_STONITH_CALLDATA, data);
|
||||
+ } else {
|
||||
+ const char *name = NULL;
|
||||
+ const char *value = NULL;
|
||||
+
|
||||
+ const char *names[] = {
|
||||
+ F_STONITH_OPERATION,
|
||||
+ F_STONITH_CALLID,
|
||||
+ F_STONITH_CLIENTID,
|
||||
+ F_STONITH_CLIENTNAME,
|
||||
+ F_STONITH_REMOTE_OP_ID,
|
||||
+ F_STONITH_CALLOPTS
|
||||
+ };
|
||||
+
|
||||
+ crm_trace("Creating a result reply with%s reply output (rc=%d)",
|
||||
+ (data? "" : "out"), rc);
|
||||
+ for (int lpc = 0; lpc < DIMOF(names); lpc++) {
|
||||
+ name = names[lpc];
|
||||
+ value = crm_element_value(request, name);
|
||||
+ crm_xml_add(reply, name, value);
|
||||
+ }
|
||||
+ if (data != NULL) {
|
||||
+ add_message_xml(reply, F_STONITH_CALLDATA, data);
|
||||
+ }
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
85
SOURCES/012-ipc_fix.patch
Normal file
85
SOURCES/012-ipc_fix.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From f7389ac6f67804f20393951462a59a0b505dfe03 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 21 Jul 2020 16:41:18 -0500
|
||||
Subject: [PATCH] Fix: executor: only send executor notifications to executor
|
||||
clients
|
||||
|
||||
This bug has existed since Pacemaker Remote was first implemented, but was
|
||||
hidden until crm_node -l/-p was recently modified to go through controller IPC,
|
||||
because other command-line IPC API clients either fire-and-forget IPC requests
|
||||
or merely count replies, rather than parse the content of replies.
|
||||
|
||||
Previously, when the executor sent notifications of results, it broadcast the
|
||||
notification to all IPC clients. Normally this behavior makes sense, but for
|
||||
the executor in particular, it may be running as pacemaker-remoted, in which
|
||||
case its IPC clients include not only clients that connected to the executor
|
||||
IPC, but clients that connected via proxy to other IPC APIs on the cluster node
|
||||
hosting the remote connection.
|
||||
|
||||
With crm_node -l/-p, this meant that it was possible for an executor API
|
||||
notification to arrive while crm_node was waiting for a controller IPC reply.
|
||||
It would not find the information it needed and would report a protocol
|
||||
violation error.
|
||||
|
||||
The fix is to send executor notifications only to executor clients.
|
||||
---
|
||||
daemons/execd/execd_commands.c | 9 +++++++++
|
||||
daemons/execd/remoted_proxy.c | 5 +++++
|
||||
include/crm/common/ipc_internal.h | 5 +++--
|
||||
3 files changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
|
||||
index aaf2976..685fcc7 100644
|
||||
--- a/daemons/execd/execd_commands.c
|
||||
+++ b/daemons/execd/execd_commands.c
|
||||
@@ -507,6 +507,15 @@ send_client_notify(gpointer key, gpointer value, gpointer user_data)
|
||||
crm_trace("Skipping notification to client without name");
|
||||
return;
|
||||
}
|
||||
+ if (is_set(client->flags, pcmk__client_to_proxy)) {
|
||||
+ /* We only want to notify clients of the executor IPC API. If we are
|
||||
+ * running as Pacemaker Remote, we may have clients proxied to other
|
||||
+ * IPC services in the cluster, so skip those.
|
||||
+ */
|
||||
+ crm_trace("Skipping executor API notification to %s IPC client",
|
||||
+ client->name);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
rc = lrmd_server_send_notify(client, update_msg);
|
||||
if (rc == pcmk_rc_ok) {
|
||||
diff --git a/daemons/execd/remoted_proxy.c b/daemons/execd/remoted_proxy.c
|
||||
index dda7eed..5c58de4 100644
|
||||
--- a/daemons/execd/remoted_proxy.c
|
||||
+++ b/daemons/execd/remoted_proxy.c
|
||||
@@ -88,6 +88,11 @@ ipc_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid, const char *ipc
|
||||
client->userdata = strdup(ipc_proxy->id);
|
||||
client->name = crm_strdup_printf("proxy-%s-%d-%.8s", ipc_channel, client->pid, client->id);
|
||||
|
||||
+ /* Allow remote executor to distinguish between proxied local clients and
|
||||
+ * actual executor API clients
|
||||
+ */
|
||||
+ set_bit(client->flags, pcmk__client_to_proxy);
|
||||
+
|
||||
g_hash_table_insert(ipc_clients, client->id, client);
|
||||
|
||||
msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
|
||||
diff --git a/include/crm/common/ipc_internal.h b/include/crm/common/ipc_internal.h
|
||||
index 6a1fcf3..91b3435 100644
|
||||
--- a/include/crm/common/ipc_internal.h
|
||||
+++ b/include/crm/common/ipc_internal.h
|
||||
@@ -121,8 +121,9 @@ struct pcmk__remote_s {
|
||||
};
|
||||
|
||||
enum pcmk__client_flags {
|
||||
- pcmk__client_proxied = 0x00001, /* ipc_proxy code only */
|
||||
- pcmk__client_privileged = 0x00002, /* root or cluster user */
|
||||
+ pcmk__client_proxied = (1 << 0), // Remote client behind proxy
|
||||
+ pcmk__client_privileged = (1 << 1), // root or cluster user
|
||||
+ pcmk__client_to_proxy = (1 << 2), // Local client to be proxied
|
||||
};
|
||||
|
||||
struct pcmk__client_s {
|
||||
--
|
||||
1.8.3.1
|
||||
|
1072
SOURCES/013-pacemakerd.patch
Normal file
1072
SOURCES/013-pacemakerd.patch
Normal file
File diff suppressed because it is too large
Load Diff
1187
SOURCES/014-sbd.patch
Normal file
1187
SOURCES/014-sbd.patch
Normal file
File diff suppressed because it is too large
Load Diff
123
SOURCES/015-cibsecret.patch
Normal file
123
SOURCES/015-cibsecret.patch
Normal file
@ -0,0 +1,123 @@
|
||||
From 2e7a40570d6b21534ec0215ac5ebc174796cf17c Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 20 Aug 2020 10:02:20 -0500
|
||||
Subject: [PATCH 1/2] Refactor: tools: rename function in cibsecret to be more
|
||||
clear
|
||||
|
||||
It led me to initially misdiagnose a problem.
|
||||
---
|
||||
tools/cibsecret.in | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/tools/cibsecret.in b/tools/cibsecret.in
|
||||
index 9b74ba3..dabbfc0 100644
|
||||
--- a/tools/cibsecret.in
|
||||
+++ b/tools/cibsecret.in
|
||||
@@ -162,28 +162,28 @@ check_env() {
|
||||
}
|
||||
|
||||
# This must be called (and return success) before calling $rsh or $rcp_to_from
|
||||
-get_live_nodes() {
|
||||
- # Get a list of all cluster nodes
|
||||
+get_live_peers() {
|
||||
+ # Get a list of all other cluster nodes
|
||||
GLN_ALL_NODES="$(crm_node -l | awk '{print $2}' | grep -v "$(uname -n)")"
|
||||
|
||||
# Make a list of those that respond to pings
|
||||
if [ "$(id -u)" = "0" ] && which fping >/dev/null 2>&1; then
|
||||
- LIVE_NODES=$(fping -a $GLN_ALL_NODES 2>/dev/null)
|
||||
+ LIVE_NODES=$(fping -a $GLP_ALL_PEERS 2>/dev/null)
|
||||
else
|
||||
LIVE_NODES=""
|
||||
- for GLN_NODE in $GLN_ALL_NODES; do \
|
||||
- ping -c 2 -q "$GLN_NODE" >/dev/null 2>&1 &&
|
||||
- LIVE_NODES="$LIVE_NODES $GLN_NODE"
|
||||
+ for GLP_NODE in $GLP_ALL_PEERS; do \
|
||||
+ ping -c 2 -q "$GLP_NODE" >/dev/null 2>&1 &&
|
||||
+ LIVE_NODES="$LIVE_NODES $GLP_NODE"
|
||||
done
|
||||
fi
|
||||
|
||||
# Warn the user about any that didn't respond to pings
|
||||
- GLN_DOWN="$( (for GLN_NODE in $LIVE_NODES $GLN_ALL_NODES; do echo "$GLN_NODE"; done) | sort | uniq -u)"
|
||||
- if [ "$(echo "$GLN_DOWN" | wc -w)" = "1" ]; then
|
||||
- warn "node $GLN_DOWN is down"
|
||||
+ GLP_DOWN="$( (for GLP_NODE in $LIVE_NODES $GLP_ALL_PEERS; do echo "$GLP_NODE"; done) | sort | uniq -u)"
|
||||
+ if [ "$(echo "$GLP_DOWN" | wc -w)" = "1" ]; then
|
||||
+ warn "node $GLP_DOWN is down"
|
||||
warn "you'll need to update it using \"$PROG sync\" later"
|
||||
- elif [ -n "$GLN_DOWN" ]; then
|
||||
- warn "nodes $(echo "$GLN_DOWN" | tr '\n' ' ')are down"
|
||||
+ elif [ -n "$GLP_DOWN" ]; then
|
||||
+ warn "nodes $(echo "$GLP_DOWN" | tr '\n' ' ')are down"
|
||||
warn "you'll need to update them using \"$PROG sync\" later"
|
||||
fi
|
||||
|
||||
@@ -235,7 +235,7 @@ scp_fun() {
|
||||
# TODO: this procedure should be replaced with csync2
|
||||
# provided that csync2 has already been configured
|
||||
sync_files() {
|
||||
- get_live_nodes || return
|
||||
+ get_live_peers || return
|
||||
info "syncing $LRM_CIBSECRETS to $(echo "$LIVE_NODES" | tr '\n' ' ') ..."
|
||||
$rsh rm -rf "$LRM_CIBSECRETS" &&
|
||||
$rsh mkdir -p "$(dirname "$LRM_CIBSECRETS")" &&
|
||||
@@ -244,7 +244,7 @@ sync_files() {
|
||||
|
||||
sync_one() {
|
||||
SO_FILE="$1"
|
||||
- get_live_nodes || return
|
||||
+ get_live_peers || return
|
||||
info "syncing $SO_FILE to $(echo "$LIVE_NODES" | tr '\n' ' ') ..."
|
||||
$rsh mkdir -p "$(dirname "$SO_FILE")" &&
|
||||
if [ -f "$SO_FILE" ]; then
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 9c1517e6a681f35d62b4714e854b258c17ab5e59 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 20 Aug 2020 10:03:23 -0500
|
||||
Subject: [PATCH 2/2] Fix: tools: properly detect local node name
|
||||
|
||||
cibsecret had two serious problems when generating a list of other nodes to
|
||||
sync secrets to:
|
||||
|
||||
* It used `uname -n` to remove the local node from the list. If the local node
|
||||
name is different from its uname, this could cause local secrets to be
|
||||
removed from the local node rather than synced to other nodes.
|
||||
|
||||
* It removed not just the local node name, but any node name that contained
|
||||
the local node name as a substring (e.g. "node1" and "node10"). This could
|
||||
cause secrets to not be synced to such nodes.
|
||||
|
||||
Now, use `crm_node -n` to determine the local node name, check crm_node for
|
||||
errors to get better error messages, and remove only the node name that matches
|
||||
the local node name in its entirety.
|
||||
---
|
||||
tools/cibsecret.in | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/cibsecret.in b/tools/cibsecret.in
|
||||
index dabbfc0..568833c 100644
|
||||
--- a/tools/cibsecret.in
|
||||
+++ b/tools/cibsecret.in
|
||||
@@ -163,8 +163,14 @@ check_env() {
|
||||
|
||||
# This must be called (and return success) before calling $rsh or $rcp_to_from
|
||||
get_live_peers() {
|
||||
+ # Get local node name
|
||||
+ GLP_LOCAL_NODE="$(crm_node -n)"
|
||||
+ [ $? -eq 0 ] || fatal "couldn't get local node name"
|
||||
+
|
||||
# Get a list of all other cluster nodes
|
||||
- GLN_ALL_NODES="$(crm_node -l | awk '{print $2}' | grep -v "$(uname -n)")"
|
||||
+ GLP_ALL_PEERS="$(crm_node -l)"
|
||||
+ [ $? -eq 0 ] || fatal "couldn't determine cluster nodes"
|
||||
+ GLP_ALL_PEERS="$(echo "$GLP_ALL_PEERS" | awk '{print $2}' | grep -v "^${GLP_LOCAL_NODE}$")"
|
||||
|
||||
# Make a list of those that respond to pings
|
||||
if [ "$(id -u)" = "0" ] && which fping >/dev/null 2>&1; then
|
||||
--
|
||||
1.8.3.1
|
||||
|
1341
SPECS/pacemaker.spec
Normal file
1341
SPECS/pacemaker.spec
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user