import pacemaker-2.0.5-9.el8

This commit is contained in:
CentOS Sources 2021-05-18 02:43:17 -04:00 committed by Cloud User
parent 98caf1a2ae
commit 65c2d339aa
61 changed files with 63313 additions and 30003 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/nagios-agents-metadata-105ab8a.tar.gz
SOURCES/pacemaker-2deceaa.tar.gz
SOURCES/pacemaker-ba59be7.tar.gz

View File

@ -1,2 +1,2 @@
ea6c0a27fd0ae8ce02f84a11f08a0d79377041c3 SOURCES/nagios-agents-metadata-105ab8a.tar.gz
78c94fdcf59cfb064d4433e1b8f71fd856eeec5f SOURCES/pacemaker-2deceaa.tar.gz
268769bcd0d6c2ea2d50db92aaea0f31637775d0 SOURCES/pacemaker-ba59be7.tar.gz

View File

@ -0,0 +1,704 @@
From d81282f1ac5e1226fbf6cfa1bd239d317e106def Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 13 Oct 2020 10:08:21 +0200
Subject: [PATCH 1/3] Feature: crmadmin: implement formatted output
---
include/crm/crm.h | 2 +-
tools/crmadmin.c | 312 ++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 232 insertions(+), 82 deletions(-)
diff --git a/include/crm/crm.h b/include/crm/crm.h
index 389b6aa..4eca278 100644
--- a/include/crm/crm.h
+++ b/include/crm/crm.h
@@ -51,7 +51,7 @@ extern "C" {
* >=3.0.13: Fail counts include operation name and interval
* >=3.2.0: DC supports PCMK_LRM_OP_INVALID and PCMK_LRM_OP_NOT_CONNECTED
*/
-# define CRM_FEATURE_SET "3.6.1"
+# define CRM_FEATURE_SET "3.6.2"
# define EOS '\0'
# define DIMOF(a) ((int) (sizeof(a)/sizeof(a[0])) )
diff --git a/tools/crmadmin.c b/tools/crmadmin.c
index 0b87d01..14078e6 100644
--- a/tools/crmadmin.c
+++ b/tools/crmadmin.c
@@ -20,6 +20,7 @@
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/cmdline_internal.h>
+#include <crm/common/output_internal.h>
#include <crm/common/xml.h>
#include <crm/common/iso8601.h>
#include <crm/common/ipc_controld.h>
@@ -38,7 +39,6 @@ bool need_controld_api = true;
bool need_pacemakerd_api = false;
bool do_work(pcmk_ipc_api_t *api);
-void do_find_node_list(xmlNode *xml_node);
static char *ipc_name = NULL;
gboolean admin_message_timeout(gpointer data);
@@ -55,13 +55,12 @@ static enum {
static gboolean BE_VERBOSE = FALSE;
static gboolean BASH_EXPORT = FALSE;
-static gboolean BE_SILENT = FALSE;
static char *dest_node = NULL;
static crm_exit_t exit_code = CRM_EX_OK;
+pcmk__output_t *out = NULL;
struct {
- gboolean quiet;
gboolean health;
gint timeout;
} options;
@@ -168,6 +167,191 @@ command_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError
return TRUE;
}
+PCMK__OUTPUT_ARGS("health", "char *", "char *", "char *", "char *")
+static int
+health_text(pcmk__output_t *out, va_list args)
+{
+ char *sys_from = va_arg(args, char *);
+ char *host_from = va_arg(args, char *);
+ char *fsa_state = va_arg(args, char *);
+ char *result = va_arg(args, char *);
+
+ if (!out->is_quiet(out)) {
+ out->info(out, "Status of %s@%s: %s (%s)", crm_str(sys_from),
+ crm_str(host_from), crm_str(fsa_state), crm_str(result));
+ } else if (fsa_state != NULL) {
+ out->info(out, "%s", fsa_state);
+ }
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("health", "char *", "char *", "char *", "char *")
+static int
+health_xml(pcmk__output_t *out, va_list args)
+{
+ char *sys_from = va_arg(args, char *);
+ char *host_from = va_arg(args, char *);
+ char *fsa_state = va_arg(args, char *);
+ char *result = va_arg(args, char *);
+
+ xmlNodePtr node = pcmk__output_create_xml_node(out, crm_str(sys_from));
+ xmlSetProp(node, (pcmkXmlStr) "node_name", (pcmkXmlStr) crm_str(host_from));
+ xmlSetProp(node, (pcmkXmlStr) "state", (pcmkXmlStr) crm_str(fsa_state));
+ xmlSetProp(node, (pcmkXmlStr) "result", (pcmkXmlStr) crm_str(result));
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("pacemakerd-health", "char *", "char *", "char *")
+static int
+pacemakerd_health_text(pcmk__output_t *out, va_list args)
+{
+ char *sys_from = va_arg(args, char *);
+ char *state = va_arg(args, char *);
+ char *last_updated = va_arg(args, char *);
+
+ if (!out->is_quiet(out)) {
+ out->info(out, "Status of %s: '%s' %s %s", crm_str(sys_from),
+ crm_str(state), (!pcmk__str_empty(last_updated))?
+ "last updated":"", crm_str(last_updated));
+ } else {
+ out->info(out, "%s", crm_str(state));
+ }
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("pacemakerd-health", "char *", "char *", "char *")
+static int
+pacemakerd_health_xml(pcmk__output_t *out, va_list args)
+{
+ char *sys_from = va_arg(args, char *);
+ char *state = va_arg(args, char *);
+ char *last_updated = va_arg(args, char *);
+
+
+ xmlNodePtr node = pcmk__output_create_xml_node(out, crm_str(sys_from));
+ xmlSetProp(node, (pcmkXmlStr) "state", (pcmkXmlStr) crm_str(state));
+ xmlSetProp(node, (pcmkXmlStr) "last_updated", (pcmkXmlStr) crm_str(last_updated));
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("dc", "char *")
+static int
+dc_text(pcmk__output_t *out, va_list args)
+{
+ char *dc = va_arg(args, char *);
+
+ if (!out->is_quiet(out)) {
+ out->info(out, "Designated Controller is: %s", crm_str(dc));
+ } else if (dc != NULL) {
+ out->info(out, "%s", dc);
+ }
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("dc", "char *")
+static int
+dc_xml(pcmk__output_t *out, va_list args)
+{
+ char *dc = va_arg(args, char *);
+
+ xmlNodePtr node = pcmk__output_create_xml_node(out, "dc");
+ xmlSetProp(node, (pcmkXmlStr) "node_name", (pcmkXmlStr) crm_str(dc));
+
+ return pcmk_rc_ok;
+}
+
+
+PCMK__OUTPUT_ARGS("crmadmin-node-list", "xmlNode *")
+static int
+crmadmin_node_list(pcmk__output_t *out, va_list args)
+{
+ xmlNode *xml_node = va_arg(args, xmlNode *);
+ int found = 0;
+ xmlNode *node = NULL;
+ xmlNode *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node);
+
+ out->begin_list(out, NULL, NULL, "Nodes");
+
+ for (node = first_named_child(nodes, XML_CIB_TAG_NODE); node != NULL;
+ node = crm_next_same_xml(node)) {
+ const char *node_type = BASH_EXPORT ? NULL :
+ crm_element_value(node, XML_ATTR_TYPE);
+ out->message(out, "crmadmin-node", node_type,
+ crm_str(crm_element_value(node, XML_ATTR_UNAME)),
+ crm_str(crm_element_value(node, XML_ATTR_ID)));
+
+ found++;
+ }
+ // @TODO List Pacemaker Remote nodes that don't have a <node> entry
+
+ out->end_list(out);
+
+ if (found == 0) {
+ out->info(out, "No nodes configured");
+ }
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("crmadmin-node", "char *", "char *", "char *")
+static int
+crmadmin_node_text(pcmk__output_t *out, va_list args)
+{
+ char *type = va_arg(args, char *);
+ char *name = va_arg(args, char *);
+ char *id = va_arg(args, char *);
+
+ if (BASH_EXPORT) {
+ out->info(out, "export %s=%s", crm_str(name), crm_str(id));
+ } else {
+ out->info(out, "%s node: %s (%s)", type ? type : "member",
+ crm_str(name), crm_str(id));
+ }
+
+ return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("crmadmin-node", "char *", "char *", "char *")
+static int
+crmadmin_node_xml(pcmk__output_t *out, va_list args)
+{
+ char *type = va_arg(args, char *);
+ char *name = va_arg(args, char *);
+ char *id = va_arg(args, char *);
+
+ xmlNodePtr node = pcmk__output_create_xml_node(out, "crmadmin-node");
+ xmlSetProp(node, (pcmkXmlStr) "type", (pcmkXmlStr) (type ? type : "member"));
+ xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) crm_str(name));
+ xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) crm_str(id));
+
+ return pcmk_rc_ok;
+}
+
+static pcmk__message_entry_t fmt_functions[] = {
+ {"health", "default", health_text },
+ {"health", "xml", health_xml },
+ {"pacemakerd-health", "default", pacemakerd_health_text },
+ {"pacemakerd-health", "xml", pacemakerd_health_xml },
+ {"dc", "default", dc_text },
+ {"dc", "xml", dc_xml },
+ {"crmadmin-node-list", "default", crmadmin_node_list },
+ {"crmadmin-node", "default", crmadmin_node_text },
+ {"crmadmin-node", "xml", crmadmin_node_xml },
+
+ { NULL, NULL, NULL }
+};
+
+static pcmk__supported_format_t formats[] = {
+ PCMK__SUPPORTED_FORMAT_TEXT,
+ PCMK__SUPPORTED_FORMAT_XML,
+ { NULL, NULL, NULL }
+};
+
static void
quit_main_loop(crm_exit_t ec)
{
@@ -191,7 +375,7 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
switch (event_type) {
case pcmk_ipc_event_disconnect:
if (exit_code == CRM_EX_DISCONNECT) { // Unexpected
- fprintf(stderr, "error: Lost connection to controller\n");
+ out->err(out, "error: Lost connection to controller");
}
goto done;
break;
@@ -209,14 +393,14 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
}
if (status != CRM_EX_OK) {
- fprintf(stderr, "error: Bad reply from controller: %s",
+ out->err(out, "error: Bad reply from controller: %s",
crm_exit_str(status));
exit_code = status;
goto done;
}
if (reply->reply_type != pcmk_controld_reply_ping) {
- fprintf(stderr, "error: Unknown reply type %d from controller\n",
+ out->err(out, "error: Unknown reply type %d from controller",
reply->reply_type);
goto done;
}
@@ -224,22 +408,16 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
// Parse desired information from reply
switch (command) {
case cmd_health:
- printf("Status of %s@%s: %s (%s)\n",
+ out->message(out, "health",
reply->data.ping.sys_from,
reply->host_from,
reply->data.ping.fsa_state,
reply->data.ping.result);
- if (BE_SILENT && (reply->data.ping.fsa_state != NULL)) {
- fprintf(stderr, "%s\n", reply->data.ping.fsa_state);
- }
exit_code = CRM_EX_OK;
break;
case cmd_whois_dc:
- printf("Designated Controller is: %s\n", reply->host_from);
- if (BE_SILENT && (reply->host_from != NULL)) {
- fprintf(stderr, "%s\n", reply->host_from);
- }
+ out->message(out, "dc", reply->host_from);
exit_code = CRM_EX_OK;
break;
@@ -263,7 +441,7 @@ pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
switch (event_type) {
case pcmk_ipc_event_disconnect:
if (exit_code == CRM_EX_DISCONNECT) { // Unexpected
- fprintf(stderr, "error: Lost connection to pacemakerd\n");
+ out->err(out, "error: Lost connection to pacemakerd");
}
goto done;
break;
@@ -281,14 +459,14 @@ pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
}
if (status != CRM_EX_OK) {
- fprintf(stderr, "error: Bad reply from pacemakerd: %s",
+ out->err(out, "error: Bad reply from pacemakerd: %s",
crm_exit_str(status));
exit_code = status;
goto done;
}
if (reply->reply_type != pcmk_pacemakerd_reply_ping) {
- fprintf(stderr, "error: Unknown reply type %d from pacemakerd\n",
+ out->err(out, "error: Unknown reply type %d from pacemakerd",
reply->reply_type);
goto done;
}
@@ -305,21 +483,12 @@ pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
crm_time_log_date | crm_time_log_timeofday |
crm_time_log_with_timezone);
- printf("Status of %s: '%s' %s %s\n",
+ out->message(out, "pacemakerd-health",
reply->data.ping.sys_from,
(reply->data.ping.status == pcmk_rc_ok)?
pcmk_pacemakerd_api_daemon_state_enum2text(
reply->data.ping.state):"query failed",
- (reply->data.ping.status == pcmk_rc_ok)?"last updated":"",
(reply->data.ping.status == pcmk_rc_ok)?pinged_buf:"");
- if (BE_SILENT &&
- (reply->data.ping.state != pcmk_pacemakerd_state_invalid)) {
- fprintf(stderr, "%s\n",
- (reply->data.ping.status == pcmk_rc_ok)?
- pcmk_pacemakerd_api_daemon_state_enum2text(
- reply->data.ping.state):
- "query failed");
- }
exit_code = CRM_EX_OK;
free(pinged_buf);
}
@@ -354,7 +523,7 @@ list_nodes()
rc = the_cib->cmds->query(the_cib, NULL, &output,
cib_scope_local | cib_sync_call);
if (rc == pcmk_ok) {
- do_find_node_list(output);
+ out->message(out, "crmadmin-node-list", output);
free_xml(output);
}
the_cib->cmds->signoff(the_cib);
@@ -362,20 +531,20 @@ list_nodes()
}
static GOptionContext *
-build_arg_context(pcmk__common_args_t *args) {
+build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
GOptionContext *context = NULL;
const char *description = "Report bugs to users@clusterlabs.org";
GOptionEntry extra_prog_entries[] = {
- { "quiet", 'q', 0, G_OPTION_ARG_NONE, &options.quiet,
+ { "quiet", 'q', 0, G_OPTION_ARG_NONE, &(args->quiet),
"Display only the essential query information",
NULL },
{ NULL }
};
- context = pcmk__build_arg_context(args, NULL, NULL, NULL);
+ context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
g_option_context_set_description(context, description);
/* Add the -q option, which cannot be part of the globally supported options
@@ -402,9 +571,11 @@ main(int argc, char **argv)
GError *error = NULL;
GOptionContext *context = NULL;
+ GOptionGroup *output_group = NULL;
gchar **processed_args = NULL;
- context = build_arg_context(args);
+ context = build_arg_context(args, &output_group);
+ pcmk__register_formats(output_group, formats);
crm_log_cli_init("crmadmin");
@@ -421,9 +592,21 @@ main(int argc, char **argv)
crm_bump_log_level(argc, argv);
}
+ rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
+ if (rc != pcmk_rc_ok) {
+ fprintf(stderr, "Error creating output format %s: %s\n",
+ args->output_ty, pcmk_rc_str(rc));
+ exit_code = CRM_EX_ERROR;
+ goto done;
+ }
+
+ out->quiet = args->quiet;
+
+ pcmk__register_messages(out, fmt_functions);
+
if (args->version) {
- /* FIXME: When crmadmin is converted to use formatted output, this can go. */
- pcmk__cli_help('v', CRM_EX_USAGE);
+ out->version(out, false);
+ goto done;
}
if (options.timeout) {
@@ -433,12 +616,8 @@ main(int argc, char **argv)
}
}
- if (options.quiet) {
- BE_SILENT = TRUE;
- }
-
if (options.health) {
- fprintf(stderr, "Cluster-wide health option not supported\n");
+ out->err(out, "Cluster-wide health option not supported");
++argerr;
}
@@ -447,14 +626,14 @@ main(int argc, char **argv)
}
if (command == cmd_none) {
- fprintf(stderr, "error: Must specify a command option\n\n");
+ out->err(out, "error: Must specify a command option");
++argerr;
}
if (argerr) {
char *help = g_option_context_get_help(context, TRUE, NULL);
- fprintf(stderr, "%s", help);
+ out->err(out, "%s", help);
g_free(help);
exit_code = CRM_EX_USAGE;
goto done;
@@ -464,7 +643,7 @@ main(int argc, char **argv)
if (need_controld_api) {
rc = pcmk_new_ipc_api(&controld_api, pcmk_ipc_controld);
if (controld_api == NULL) {
- fprintf(stderr, "error: Could not connect to controller: %s\n",
+ out->err(out, "error: Could not connect to controller: %s",
pcmk_rc_str(rc));
exit_code = pcmk_rc2exitc(rc);
goto done;
@@ -472,7 +651,7 @@ main(int argc, char **argv)
pcmk_register_ipc_callback(controld_api, controller_event_cb, NULL);
rc = pcmk_connect_ipc(controld_api, pcmk_ipc_dispatch_main);
if (rc != pcmk_rc_ok) {
- fprintf(stderr, "error: Could not connect to controller: %s\n",
+ out->err(out, "error: Could not connect to controller: %s",
pcmk_rc_str(rc));
exit_code = pcmk_rc2exitc(rc);
goto done;
@@ -483,7 +662,7 @@ main(int argc, char **argv)
if (need_pacemakerd_api) {
rc = pcmk_new_ipc_api(&pacemakerd_api, pcmk_ipc_pacemakerd);
if (pacemakerd_api == NULL) {
- fprintf(stderr, "error: Could not connect to pacemakerd: %s\n",
+ out->err(out, "error: Could not connect to pacemakerd: %s",
pcmk_rc_str(rc));
exit_code = pcmk_rc2exitc(rc);
goto done;
@@ -491,7 +670,7 @@ main(int argc, char **argv)
pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, NULL);
rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_main);
if (rc != pcmk_rc_ok) {
- fprintf(stderr, "error: Could not connect to pacemakerd: %s\n",
+ out->err(out, "error: Could not connect to pacemakerd: %s",
pcmk_rc_str(rc));
exit_code = pcmk_rc2exitc(rc);
goto done;
@@ -528,6 +707,10 @@ done:
g_strfreev(processed_args);
g_clear_error(&error);
pcmk__free_arg_context(context);
+ if (out != NULL) {
+ out->finish(out, exit_code, true, NULL);
+ pcmk__output_free(out);
+ }
return crm_exit(exit_code);
}
@@ -567,7 +750,7 @@ do_work(pcmk_ipc_api_t *api)
break;
}
if (rc != pcmk_rc_ok) {
- fprintf(stderr, "error: Command failed: %s", pcmk_rc_str(rc));
+ out->err(out, "error: Command failed: %s", pcmk_rc_str(rc));
exit_code = pcmk_rc2exitc(rc);
}
return need_reply;
@@ -576,43 +759,10 @@ do_work(pcmk_ipc_api_t *api)
gboolean
admin_message_timeout(gpointer data)
{
- fprintf(stderr,
- "error: No reply received from controller before timeout (%dms)\n",
+ out->err(out,
+ "error: No reply received from controller before timeout (%dms)",
message_timeout_ms);
message_timer_id = 0;
quit_main_loop(CRM_EX_TIMEOUT);
return FALSE; // Tells glib to remove source
}
-
-void
-do_find_node_list(xmlNode * xml_node)
-{
- int found = 0;
- xmlNode *node = NULL;
- xmlNode *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node);
-
- for (node = first_named_child(nodes, XML_CIB_TAG_NODE); node != NULL;
- node = crm_next_same_xml(node)) {
-
- if (BASH_EXPORT) {
- printf("export %s=%s\n",
- crm_element_value(node, XML_ATTR_UNAME),
- crm_element_value(node, XML_ATTR_ID));
- } else {
- const char *node_type = crm_element_value(node, XML_ATTR_TYPE);
-
- if (node_type == NULL) {
- node_type = "member";
- }
- printf("%s node: %s (%s)\n", node_type,
- crm_element_value(node, XML_ATTR_UNAME),
- crm_element_value(node, XML_ATTR_ID));
- }
- found++;
- }
- // @TODO List Pacemaker Remote nodes that don't have a <node> entry
-
- if (found == 0) {
- printf("No nodes configured\n");
- }
-}
--
1.8.3.1
From 2b121066c8eead96e85dc3bf6ecc1c2674cbdf32 Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 20 Oct 2020 16:19:03 +0200
Subject: [PATCH 2/3] Refactor: crmadmin: use simple XML lists
---
tools/crmadmin.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tools/crmadmin.c b/tools/crmadmin.c
index 14078e6..b80a31a 100644
--- a/tools/crmadmin.c
+++ b/tools/crmadmin.c
@@ -275,7 +275,7 @@ crmadmin_node_list(pcmk__output_t *out, va_list args)
xmlNode *node = NULL;
xmlNode *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node);
- out->begin_list(out, NULL, NULL, "Nodes");
+ out->begin_list(out, NULL, NULL, "nodes");
for (node = first_named_child(nodes, XML_CIB_TAG_NODE); node != NULL;
node = crm_next_same_xml(node)) {
@@ -324,7 +324,7 @@ crmadmin_node_xml(pcmk__output_t *out, va_list args)
char *name = va_arg(args, char *);
char *id = va_arg(args, char *);
- xmlNodePtr node = pcmk__output_create_xml_node(out, "crmadmin-node");
+ xmlNodePtr node = pcmk__output_create_xml_node(out, "node");
xmlSetProp(node, (pcmkXmlStr) "type", (pcmkXmlStr) (type ? type : "member"));
xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) crm_str(name));
xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) crm_str(id));
@@ -604,6 +604,10 @@ main(int argc, char **argv)
pcmk__register_messages(out, fmt_functions);
+ if (!pcmk__force_args(context, &error, "%s --xml-simple-list --xml-substitute", g_get_prgname())) {
+ goto done;
+ }
+
if (args->version) {
out->version(out, false);
goto done;
--
1.8.3.1
From 9b53a7eda078db736be5212aeb77daf8117e2f17 Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 20 Oct 2020 16:21:12 +0200
Subject: [PATCH 3/3] Feature: xml: add schema for new crmadmin output
---
xml/Makefile.am | 2 +-
xml/api/crmadmin-2.4.rng | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+), 1 deletion(-)
create mode 100644 xml/api/crmadmin-2.4.rng
diff --git a/xml/Makefile.am b/xml/Makefile.am
index c045522..892c811 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -45,7 +45,7 @@ version_pairs_last = $(wordlist \
)
# Names of API schemas that form the choices for pacemaker-result content
-API_request_base = command-output crm_mon stonith_admin version
+API_request_base = command-output crm_mon crmadmin stonith_admin version
# Names of CIB schemas that form the choices for cib/configuration content
CIB_cfg_base = options nodes resources constraints fencing acls tags alerts
diff --git a/xml/api/crmadmin-2.4.rng b/xml/api/crmadmin-2.4.rng
new file mode 100644
index 0000000..34c9ca4
--- /dev/null
+++ b/xml/api/crmadmin-2.4.rng
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="element-crmadmin"/>
+ </start>
+
+ <define name="element-crmadmin">
+ <optional>
+ <ref name="element-status" />
+ </optional>
+ <optional>
+ <ref name="element-pacemakerd" />
+ </optional>
+ <optional>
+ <ref name="element-dc" />
+ </optional>
+ <optional>
+ <ref name="crmadmin-nodes-list" />
+ </optional>
+ </define>
+
+ <define name="element-status">
+ <element name="crmd">
+ <attribute name="node_name"> <text /> </attribute>
+ <attribute name="state"> <text /> </attribute>
+ <attribute name="result"> <text /> </attribute>
+ </element>
+ </define>
+
+ <define name="element-pacemakerd">
+ <element name="pacemakerd">
+ <attribute name="state"> <text /> </attribute>
+ <attribute name="last_updated"> <text /> </attribute>
+ </element>
+ </define>
+
+ <define name="element-dc">
+ <element name="dc">
+ <attribute name="node_name"> <text /> </attribute>
+ </element>
+ </define>
+
+ <define name="crmadmin-nodes-list">
+ <element name="nodes">
+ <zeroOrMore>
+ <ref name="element-crmadmin-node" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-crmadmin-node">
+ <element name="node">
+ <attribute name="type">
+ <choice>
+ <value>unknown</value>
+ <value>member</value>
+ <value>remote</value>
+ <value>ping</value>
+ </choice>
+ </attribute>
+
+ <attribute name="name"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ </element>
+ </define>
+</grammar>
--
1.8.3.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
From 12e59f337f838d647deb8f84850324f785e58824 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 20 Oct 2020 10:53:26 -0400
Subject: [PATCH] Feature: libcrmcommon: Add a spacer formatted output message.
---
include/crm/common/output_internal.h | 10 +++++++++-
lib/common/output_html.c | 6 ++++++
lib/common/output_log.c | 6 ++++++
lib/common/output_text.c | 6 ++++++
lib/common/output_xml.c | 6 ++++++
tools/crm_mon_curses.c | 6 ++++++
6 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/include/crm/common/output_internal.h b/include/crm/common/output_internal.h
index 2874259..e1bd295 100644
--- a/include/crm/common/output_internal.h
+++ b/include/crm/common/output_internal.h
@@ -460,6 +460,14 @@ struct pcmk__output_s {
* \return true if output should be supressed, false otherwise.
*/
bool (*is_quiet) (pcmk__output_t *out);
+
+ /*!
+ * \internal
+ * \brief Output a spacer. Not all formatter will do this.
+ *
+ * \param[in] out The output functions structure.
+ */
+ void (*spacer) (pcmk__output_t *out);
};
/*!
@@ -745,7 +753,7 @@ G_GNUC_NULL_TERMINATED;
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond) \
if (cond) { \
- out_obj->info(out_obj, "%s", ""); \
+ out->spacer(out); \
}
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...) \
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
index 156887d..e354b5d 100644
--- a/lib/common/output_html.c
+++ b/lib/common/output_html.c
@@ -368,6 +368,11 @@ html_is_quiet(pcmk__output_t *out) {
return false;
}
+static void
+html_spacer(pcmk__output_t *out) {
+ pcmk__output_create_xml_node(out, "br");
+}
+
pcmk__output_t *
pcmk__mk_html_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
@@ -399,6 +404,7 @@ pcmk__mk_html_output(char **argv) {
retval->end_list = html_end_list;
retval->is_quiet = html_is_quiet;
+ retval->spacer = html_spacer;
return retval;
}
diff --git a/lib/common/output_log.c b/lib/common/output_log.c
index fd13c89..6336fa2 100644
--- a/lib/common/output_log.c
+++ b/lib/common/output_log.c
@@ -226,6 +226,11 @@ log_is_quiet(pcmk__output_t *out) {
return false;
}
+static void
+log_spacer(pcmk__output_t *out) {
+ /* This function intentionally left blank */
+}
+
pcmk__output_t *
pcmk__mk_log_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
@@ -256,6 +261,7 @@ pcmk__mk_log_output(char **argv) {
retval->end_list = log_end_list;
retval->is_quiet = log_is_quiet;
+ retval->spacer = log_spacer;
return retval;
}
diff --git a/lib/common/output_text.c b/lib/common/output_text.c
index 9b3c09a..3432505 100644
--- a/lib/common/output_text.c
+++ b/lib/common/output_text.c
@@ -244,6 +244,11 @@ text_is_quiet(pcmk__output_t *out) {
return out->quiet;
}
+static void
+text_spacer(pcmk__output_t *out) {
+ fprintf(out->dest, "\n");
+}
+
pcmk__output_t *
pcmk__mk_text_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
@@ -275,6 +280,7 @@ pcmk__mk_text_output(char **argv) {
retval->end_list = text_end_list;
retval->is_quiet = text_is_quiet;
+ retval->spacer = text_spacer;
return retval;
}
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
index 9a08d20..1710fac 100644
--- a/lib/common/output_xml.c
+++ b/lib/common/output_xml.c
@@ -376,6 +376,11 @@ xml_is_quiet(pcmk__output_t *out) {
return false;
}
+static void
+xml_spacer(pcmk__output_t *out) {
+ /* This function intentionally left blank */
+}
+
pcmk__output_t *
pcmk__mk_xml_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
@@ -407,6 +412,7 @@ pcmk__mk_xml_output(char **argv) {
retval->end_list = xml_end_list;
retval->is_quiet = xml_is_quiet;
+ retval->spacer = xml_spacer;
return retval;
}
diff --git a/tools/crm_mon_curses.c b/tools/crm_mon_curses.c
index 2c092df..8a08578 100644
--- a/tools/crm_mon_curses.c
+++ b/tools/crm_mon_curses.c
@@ -247,6 +247,11 @@ curses_is_quiet(pcmk__output_t *out) {
return out->quiet;
}
+static void
+curses_spacer(pcmk__output_t *out) {
+ addch('\n');
+}
+
pcmk__output_t *
crm_mon_mk_curses_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
@@ -278,6 +283,7 @@ crm_mon_mk_curses_output(char **argv) {
retval->end_list = curses_end_list;
retval->is_quiet = curses_is_quiet;
+ retval->spacer = curses_spacer;
return retval;
}
--
1.8.3.1

View File

@ -0,0 +1,208 @@
From 0deb5145c336bc4b32766c6f7af259d643af9143 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 28 Oct 2020 13:56:09 -0400
Subject: [PATCH 1/2] Fix: scheduler, tools: Update typing on maint-mode args.
---
lib/pengine/pe_output.c | 2 +-
tools/crm_mon_curses.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/pengine/pe_output.c b/lib/pengine/pe_output.c
index 186be33..d0f96f4 100644
--- a/lib/pengine/pe_output.c
+++ b/lib/pengine/pe_output.c
@@ -686,7 +686,7 @@ pe__cluster_dc_xml(pcmk__output_t *out, va_list args) {
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long")
+PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long int")
int
pe__cluster_maint_mode_text(pcmk__output_t *out, va_list args) {
unsigned long long flags = va_arg(args, unsigned long long);
diff --git a/tools/crm_mon_curses.c b/tools/crm_mon_curses.c
index 8a08578..9cf28dc 100644
--- a/tools/crm_mon_curses.c
+++ b/tools/crm_mon_curses.c
@@ -365,7 +365,7 @@ stonith_event_console(pcmk__output_t *out, va_list args) {
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long")
+PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long int")
static int
cluster_maint_mode_console(pcmk__output_t *out, va_list args) {
unsigned long long flags = va_arg(args, unsigned long long);
--
1.8.3.1
From 7a61ae2384b0a1653b4a06926b4ec23099ccf292 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 28 Oct 2020 13:57:51 -0400
Subject: [PATCH 2/2] Fix: tools: Update typing on formatted output args in
crmadmin.
A lot of these are actually taking const char * as an argument, not
regular char *.
---
tools/crmadmin.c | 62 ++++++++++++++++++++++++++++----------------------------
1 file changed, 31 insertions(+), 31 deletions(-)
diff --git a/tools/crmadmin.c b/tools/crmadmin.c
index b80a31a..e61dbf4 100644
--- a/tools/crmadmin.c
+++ b/tools/crmadmin.c
@@ -167,14 +167,14 @@ command_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError
return TRUE;
}
-PCMK__OUTPUT_ARGS("health", "char *", "char *", "char *", "char *")
+PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
static int
health_text(pcmk__output_t *out, va_list args)
{
- char *sys_from = va_arg(args, char *);
- char *host_from = va_arg(args, char *);
- char *fsa_state = va_arg(args, char *);
- char *result = va_arg(args, char *);
+ const char *sys_from = va_arg(args, const char *);
+ const char *host_from = va_arg(args, const char *);
+ const char *fsa_state = va_arg(args, const char *);
+ const char *result = va_arg(args, const char *);
if (!out->is_quiet(out)) {
out->info(out, "Status of %s@%s: %s (%s)", crm_str(sys_from),
@@ -186,14 +186,14 @@ health_text(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("health", "char *", "char *", "char *", "char *")
+PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
static int
health_xml(pcmk__output_t *out, va_list args)
{
- char *sys_from = va_arg(args, char *);
- char *host_from = va_arg(args, char *);
- char *fsa_state = va_arg(args, char *);
- char *result = va_arg(args, char *);
+ const char *sys_from = va_arg(args, const char *);
+ const char *host_from = va_arg(args, const char *);
+ const char *fsa_state = va_arg(args, const char *);
+ const char *result = va_arg(args, const char *);
xmlNodePtr node = pcmk__output_create_xml_node(out, crm_str(sys_from));
xmlSetProp(node, (pcmkXmlStr) "node_name", (pcmkXmlStr) crm_str(host_from));
@@ -203,13 +203,13 @@ health_xml(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("pacemakerd-health", "char *", "char *", "char *")
+PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
static int
pacemakerd_health_text(pcmk__output_t *out, va_list args)
{
- char *sys_from = va_arg(args, char *);
- char *state = va_arg(args, char *);
- char *last_updated = va_arg(args, char *);
+ const char *sys_from = va_arg(args, const char *);
+ const char *state = va_arg(args, const char *);
+ const char *last_updated = va_arg(args, const char *);
if (!out->is_quiet(out)) {
out->info(out, "Status of %s: '%s' %s %s", crm_str(sys_from),
@@ -222,13 +222,13 @@ pacemakerd_health_text(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("pacemakerd-health", "char *", "char *", "char *")
+PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
static int
pacemakerd_health_xml(pcmk__output_t *out, va_list args)
{
- char *sys_from = va_arg(args, char *);
- char *state = va_arg(args, char *);
- char *last_updated = va_arg(args, char *);
+ const char *sys_from = va_arg(args, const char *);
+ const char *state = va_arg(args, const char *);
+ const char *last_updated = va_arg(args, const char *);
xmlNodePtr node = pcmk__output_create_xml_node(out, crm_str(sys_from));
@@ -238,11 +238,11 @@ pacemakerd_health_xml(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("dc", "char *")
+PCMK__OUTPUT_ARGS("dc", "const char *")
static int
dc_text(pcmk__output_t *out, va_list args)
{
- char *dc = va_arg(args, char *);
+ const char *dc = va_arg(args, const char *);
if (!out->is_quiet(out)) {
out->info(out, "Designated Controller is: %s", crm_str(dc));
@@ -253,11 +253,11 @@ dc_text(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("dc", "char *")
+PCMK__OUTPUT_ARGS("dc", "const char *")
static int
dc_xml(pcmk__output_t *out, va_list args)
{
- char *dc = va_arg(args, char *);
+ const char *dc = va_arg(args, const char *);
xmlNodePtr node = pcmk__output_create_xml_node(out, "dc");
xmlSetProp(node, (pcmkXmlStr) "node_name", (pcmkXmlStr) crm_str(dc));
@@ -266,7 +266,7 @@ dc_xml(pcmk__output_t *out, va_list args)
}
-PCMK__OUTPUT_ARGS("crmadmin-node-list", "xmlNode *")
+PCMK__OUTPUT_ARGS("crmadmin-node-list", "struct xmlNode *")
static int
crmadmin_node_list(pcmk__output_t *out, va_list args)
{
@@ -298,13 +298,13 @@ crmadmin_node_list(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("crmadmin-node", "char *", "char *", "char *")
+PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *")
static int
crmadmin_node_text(pcmk__output_t *out, va_list args)
{
- char *type = va_arg(args, char *);
- char *name = va_arg(args, char *);
- char *id = va_arg(args, char *);
+ const char *type = va_arg(args, const char *);
+ const char *name = va_arg(args, const char *);
+ const char *id = va_arg(args, const char *);
if (BASH_EXPORT) {
out->info(out, "export %s=%s", crm_str(name), crm_str(id));
@@ -316,13 +316,13 @@ crmadmin_node_text(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("crmadmin-node", "char *", "char *", "char *")
+PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *")
static int
crmadmin_node_xml(pcmk__output_t *out, va_list args)
{
- char *type = va_arg(args, char *);
- char *name = va_arg(args, char *);
- char *id = va_arg(args, char *);
+ const char *type = va_arg(args, const char *);
+ const char *name = va_arg(args, const char *);
+ const char *id = va_arg(args, const char *);
xmlNodePtr node = pcmk__output_create_xml_node(out, "node");
xmlSetProp(node, (pcmkXmlStr) "type", (pcmkXmlStr) (type ? type : "member"));
--
1.8.3.1

View File

@ -1,30 +0,0 @@
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

View File

@ -0,0 +1,771 @@
From 9faa62f0701801f1d420462025e863d8ca3d6a06 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 21 Sep 2020 14:19:19 -0400
Subject: [PATCH 1/6] Fix: libcrmcommon: Automatically lower case XML list
names.
---
lib/common/output_xml.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
index 1710fac..6a6ed6e 100644
--- a/lib/common/output_xml.c
+++ b/lib/common/output_xml.c
@@ -50,7 +50,6 @@ typedef struct subst_s {
} subst_t;
static subst_t substitutions[] = {
- { "Attributes", "attributes" },
{ "Active Resources", "resources" },
{ "Full List of Resources", "resources" },
{ "Inactive Resources", "resources" },
@@ -61,8 +60,6 @@ static subst_t substitutions[] = {
{ "Operations", "node_history" },
{ "Negative Location Constraints", "bans" },
{ "Node Attributes", "node_attributes" },
- { "Resources", "resources" },
- { "Tickets", "tickets" },
{ NULL, NULL }
};
@@ -288,7 +285,7 @@ static void
xml_begin_list(pcmk__output_t *out, const char *singular_noun, const char *plural_noun,
const char *format, ...) {
va_list ap;
- const char *name = NULL;
+ char *name = NULL;
char *buf = NULL;
int len;
@@ -300,14 +297,14 @@ xml_begin_list(pcmk__output_t *out, const char *singular_noun, const char *plura
if (substitute) {
for (subst_t *s = substitutions; s->from != NULL; s++) {
if (!strcmp(s->from, buf)) {
- name = s->to;
+ name = g_strdup(s->to);
break;
}
}
}
if (name == NULL) {
- name = buf;
+ name = g_ascii_strdown(buf, -1);
}
if (legacy_xml || simple_list) {
@@ -319,6 +316,7 @@ xml_begin_list(pcmk__output_t *out, const char *singular_noun, const char *plura
xmlSetProp(list_node, (pcmkXmlStr) "name", (pcmkXmlStr) name);
}
+ g_free(name);
free(buf);
}
--
1.8.3.1
From 7a77441ae8d3ab943dfafebfc06b63402be323e1 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 27 Oct 2020 12:49:45 -0400
Subject: [PATCH 2/6] Feature: xml: Move resource-related XML schema into its
own file.
This allows it to be shared between the crm_mon and crm_resource
schemas. Also, this adds support for resource XML to crm_mon given that
this is now technically possible as part of the library output.
---
xml/Makefile.am | 2 +-
xml/api/crm_mon-2.4.rng | 311 ++++++++++++++++++++++++++++++++++++++++++++++
xml/api/resources-2.4.rng | 109 ++++++++++++++++
3 files changed, 421 insertions(+), 1 deletion(-)
create mode 100644 xml/api/crm_mon-2.4.rng
create mode 100644 xml/api/resources-2.4.rng
diff --git a/xml/Makefile.am b/xml/Makefile.am
index 892c811..79ce900 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -51,7 +51,7 @@ API_request_base = command-output crm_mon crmadmin stonith_admin version
CIB_cfg_base = options nodes resources constraints fencing acls tags alerts
# Names of all schemas (including top level and those included by others)
-API_base = $(API_request_base) fence-event item status
+API_base = $(API_request_base) fence-event item resources status
CIB_base = cib $(CIB_cfg_base) status score rule nvset
# Static schema files and transforms (only CIB has transforms)
diff --git a/xml/api/crm_mon-2.4.rng b/xml/api/crm_mon-2.4.rng
new file mode 100644
index 0000000..88973a4
--- /dev/null
+++ b/xml/api/crm_mon-2.4.rng
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="element-crm-mon"/>
+ </start>
+
+ <define name="element-crm-mon">
+ <optional>
+ <ref name="element-summary" />
+ </optional>
+ <optional>
+ <ref name="nodes-list" />
+ </optional>
+ <optional>
+ <ref name="resources-list" />
+ </optional>
+ <optional>
+ <ref name="node-attributes-list" />
+ </optional>
+ <optional>
+ <ref name="node-history-list" />
+ </optional>
+ <optional>
+ <ref name="failures-list" />
+ </optional>
+ <optional>
+ <ref name="fence-event-list" />
+ </optional>
+ <optional>
+ <ref name="tickets-list" />
+ </optional>
+ <optional>
+ <ref name="bans-list" />
+ </optional>
+ </define>
+
+ <define name="element-summary">
+ <element name="summary">
+ <optional>
+ <element name="stack">
+ <attribute name="type"> <text /> </attribute>
+ </element>
+ </optional>
+ <optional>
+ <element name="current_dc">
+ <attribute name="present"> <data type="boolean" /> </attribute>
+ <optional>
+ <group>
+ <attribute name="version"> <text /> </attribute>
+ <attribute name="name"> <text /> </attribute>
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="with_quorum"> <data type="boolean" /> </attribute>
+ </group>
+ </optional>
+ </element>
+ </optional>
+ <optional>
+ <element name="last_update">
+ <attribute name="time"> <text /> </attribute>
+ </element>
+ <element name="last_change">
+ <attribute name="time"> <text /> </attribute>
+ <attribute name="user"> <text /> </attribute>
+ <attribute name="client"> <text /> </attribute>
+ <attribute name="origin"> <text /> </attribute>
+ </element>
+ </optional>
+ <optional>
+ <element name="nodes_configured">
+ <attribute name="number"> <data type="nonNegativeInteger" /> </attribute>
+ </element>
+ <element name="resources_configured">
+ <attribute name="number"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="disabled"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="blocked"> <data type="nonNegativeInteger" /> </attribute>
+ </element>
+ </optional>
+ <optional>
+ <element name="cluster_options">
+ <attribute name="stonith-enabled"> <data type="boolean" /> </attribute>
+ <attribute name="symmetric-cluster"> <data type="boolean" /> </attribute>
+ <attribute name="no-quorum-policy"> <text /> </attribute>
+ <attribute name="maintenance-mode"> <data type="boolean" /> </attribute>
+ <attribute name="stop-all-resources"> <data type="boolean" /> </attribute>
+ </element>
+ </optional>
+ </element>
+ </define>
+
+ <define name="resources-list">
+ <element name="resources">
+ <zeroOrMore>
+ <externalRef href="resources-2.4.rng" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="nodes-list">
+ <element name="nodes">
+ <zeroOrMore>
+ <ref name="element-full-node" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="node-attributes-list">
+ <element name="node_attributes">
+ <zeroOrMore>
+ <ref name="element-node-with-attributes" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="node-history-list">
+ <element name="node_history">
+ <zeroOrMore>
+ <ref name="element-node-history" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="failures-list">
+ <element name="failures">
+ <zeroOrMore>
+ <ref name="element-failure" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="fence-event-list">
+ <element name="fence_history">
+ <optional>
+ <attribute name="status"> <data type="integer" /> </attribute>
+ </optional>
+ <zeroOrMore>
+ <externalRef href="fence-event-2.0.rng" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="tickets-list">
+ <element name="tickets">
+ <zeroOrMore>
+ <ref name="element-ticket" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="bans-list">
+ <element name="bans">
+ <zeroOrMore>
+ <ref name="element-ban" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-full-node">
+ <element name="node">
+ <attribute name="name"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="online"> <data type="boolean" /> </attribute>
+ <attribute name="standby"> <data type="boolean" /> </attribute>
+ <attribute name="standby_onfail"> <data type="boolean" /> </attribute>
+ <attribute name="maintenance"> <data type="boolean" /> </attribute>
+ <attribute name="pending"> <data type="boolean" /> </attribute>
+ <attribute name="unclean"> <data type="boolean" /> </attribute>
+ <attribute name="shutdown"> <data type="boolean" /> </attribute>
+ <attribute name="expected_up"> <data type="boolean" /> </attribute>
+ <attribute name="is_dc"> <data type="boolean" /> </attribute>
+ <attribute name="resources_running"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="type">
+ <choice>
+ <value>unknown</value>
+ <value>member</value>
+ <value>remote</value>
+ <value>ping</value>
+ </choice>
+ </attribute>
+ <optional>
+ <!-- for virtualized pacemaker_remote nodes, crm_mon 1.1.13 uses
+ "container_id" while later versions use "id_as_resource" -->
+ <choice>
+ <attribute name="container_id"> <text/> </attribute>
+ <attribute name="id_as_resource"> <text/> </attribute>
+ </choice>
+ </optional>
+ <externalRef href="resources-2.4.rng" />
+ </element>
+ </define>
+
+ <define name="element-node-with-attributes">
+ <element name="node">
+ <attribute name="name"> <text /> </attribute>
+ <zeroOrMore>
+ <element name="attribute">
+ <attribute name="name"> <text /> </attribute>
+ <attribute name="value"> <text /> </attribute>
+ <optional>
+ <attribute name="expected"> <data type="nonNegativeInteger" /> </attribute>
+ </optional>
+ </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-node-history">
+ <element name="node">
+ <attribute name="name"> <text /> </attribute>
+ <zeroOrMore>
+ <ref name="element-resource-history" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-resource-history">
+ <element name="resource_history">
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="orphan"> <data type="boolean" /> </attribute>
+ <optional>
+ <group>
+ <attribute name="migration-threshold"> <data type="nonNegativeInteger" /> </attribute>
+ <optional>
+ <attribute name="fail-count"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="last-failure"> <text /> </attribute>
+ </optional>
+ </group>
+ </optional>
+ <zeroOrMore>
+ <ref name="element-operation-history" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-operation-history">
+ <element name="operation_history">
+ <attribute name="call"> <text /> </attribute>
+ <attribute name="task"> <text /> </attribute>
+ <optional>
+ <attribute name="interval"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="last-rc-change"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="last-run"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="exec-time"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="queue-time"> <text /> </attribute>
+ </optional>
+ <attribute name="rc"> <data type="integer" /> </attribute>
+ <attribute name="rc_text"> <text /> </attribute>
+ </element>
+ </define>
+
+ <define name="element-failure">
+ <element name="failure">
+ <choice>
+ <attribute name="op_key"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ </choice>
+ <attribute name="node"> <text /> </attribute>
+ <attribute name="exitstatus"> <text /> </attribute>
+ <attribute name="exitreason"> <text /> </attribute>
+ <attribute name="exitcode"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="status"> <text /> </attribute>
+ <optional>
+ <group>
+ <attribute name="last-rc-change"> <text /> </attribute>
+ <attribute name="queued"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="exec"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="interval"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="task"> <text /> </attribute>
+ </group>
+ </optional>
+ </element>
+ </define>
+
+ <define name="element-ticket">
+ <element name="ticket">
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="status">
+ <choice>
+ <value>granted</value>
+ <value>revoked</value>
+ </choice>
+ </attribute>
+ <attribute name="standby"> <data type="boolean" /> </attribute>
+ <optional>
+ <attribute name="last-granted"> <text /> </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="element-ban">
+ <element name="ban">
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="resource"> <text /> </attribute>
+ <attribute name="node"> <text /> </attribute>
+ <attribute name="weight"> <data type="integer" /> </attribute>
+ <attribute name="master_only"> <data type="boolean" /> </attribute>
+ </element>
+ </define>
+</grammar>
diff --git a/xml/api/resources-2.4.rng b/xml/api/resources-2.4.rng
new file mode 100644
index 0000000..e279583
--- /dev/null
+++ b/xml/api/resources-2.4.rng
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="element-resource-list"/>
+ </start>
+
+ <define name="element-resource-list">
+ <interleave>
+ <zeroOrMore>
+ <ref name="element-bundle" />
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="element-clone" />
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="element-group" />
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="element-resource" />
+ </zeroOrMore>
+ </interleave>
+ </define>
+
+ <define name="element-bundle">
+ <element name="bundle">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="type">
+ <choice>
+ <value>docker</value>
+ <value>rkt</value>
+ <value>podman</value>
+ </choice>
+ </attribute>
+ <attribute name="image"> <text/> </attribute>
+ <attribute name="unique"> <data type="boolean" /> </attribute>
+ <attribute name="managed"> <data type="boolean" /> </attribute>
+ <attribute name="failed"> <data type="boolean" /> </attribute>
+ <zeroOrMore>
+ <element name="replica">
+ <attribute name="id"> <data type="nonNegativeInteger" /> </attribute>
+ <zeroOrMore>
+ <ref name="element-resource" />
+ </zeroOrMore>
+ </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-clone">
+ <element name="clone">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="multi_state"> <data type="boolean" /> </attribute>
+ <attribute name="unique"> <data type="boolean" /> </attribute>
+ <attribute name="managed"> <data type="boolean" /> </attribute>
+ <attribute name="disabled"> <data type="boolean" /> </attribute>
+ <attribute name="failed"> <data type="boolean" /> </attribute>
+ <attribute name="failure_ignored"> <data type="boolean" /> </attribute>
+ <optional>
+ <attribute name="target_role"> <text/> </attribute>
+ </optional>
+ <ref name="element-resource-list" />
+ </element>
+ </define>
+
+ <define name="element-group">
+ <element name="group">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="number_resources"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="managed"> <data type="boolean" /> </attribute>
+ <attribute name="disabled"> <data type="boolean" /> </attribute>
+ <ref name="element-resource-list" />
+ </element>
+ </define>
+
+ <define name="element-resource">
+ <element name="resource">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="resource_agent"> <text/> </attribute>
+ <attribute name="role"> <text/> </attribute>
+ <optional>
+ <attribute name="target_role"> <text/> </attribute>
+ </optional>
+ <attribute name="active"> <data type="boolean" /> </attribute>
+ <attribute name="orphaned"> <data type="boolean" /> </attribute>
+ <optional>
+ <attribute name="blocked"> <data type="boolean" /> </attribute>
+ </optional>
+ <attribute name="managed"> <data type="boolean" /> </attribute>
+ <attribute name="failed"> <data type="boolean" /> </attribute>
+ <attribute name="failure_ignored"> <data type="boolean" /> </attribute>
+ <attribute name="nodes_running_on"> <data type="nonNegativeInteger" /> </attribute>
+ <optional>
+ <attribute name="pending"> <text/> </attribute>
+ </optional>
+ <zeroOrMore>
+ <element name="node">
+ <attribute name="name"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="cached"> <data type="boolean" /> </attribute>
+ </element>
+ </zeroOrMore>
+ <optional>
+ <element name="xml"> <text/> </element>
+ </optional>
+ </element>
+ </define>
+</grammar>
--
1.8.3.1
From 814eb921cd429692220f33722c9bc061266bd838 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 29 Oct 2020 14:45:02 -0400
Subject: [PATCH 3/6] Feature: xml: Add a generic list XML schema file.
Formatted output supports a generic list structure that isn't used in
too many places at the moment, but it could be getting used more in the
future. It's also really easy to have a schema for this piece of XML.
---
xml/Makefile.am | 7 ++++++-
xml/api/generic-list-2.4.rng | 21 +++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
create mode 100644 xml/api/generic-list-2.4.rng
diff --git a/xml/Makefile.am b/xml/Makefile.am
index 79ce900..2f99f1c 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -44,6 +44,11 @@ version_pairs_last = $(wordlist \
),$(1),$(2) \
)
+# NOTE: All files in API_request_base, CIB_cfg_base, API_base, and CIB_base
+# need to start with a unique prefix. These variables all get iterated over
+# and globbed, and two files starting with the same prefix will cause
+# problems.
+
# Names of API schemas that form the choices for pacemaker-result content
API_request_base = command-output crm_mon crmadmin stonith_admin version
@@ -51,7 +56,7 @@ API_request_base = command-output crm_mon crmadmin stonith_admin version
CIB_cfg_base = options nodes resources constraints fencing acls tags alerts
# Names of all schemas (including top level and those included by others)
-API_base = $(API_request_base) fence-event item resources status
+API_base = $(API_request_base) fence-event generic-list item resources status
CIB_base = cib $(CIB_cfg_base) status score rule nvset
# Static schema files and transforms (only CIB has transforms)
diff --git a/xml/api/generic-list-2.4.rng b/xml/api/generic-list-2.4.rng
new file mode 100644
index 0000000..fee93a9
--- /dev/null
+++ b/xml/api/generic-list-2.4.rng
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="generic-list"/>
+ </start>
+
+ <define name="generic-list">
+ <element name="list">
+ <attribute name="name"> <text /> </attribute>
+ <attribute name="count"> <data type="nonNegativeInteger" /> </attribute>
+ <choice>
+ <empty/>
+ <oneOrMore>
+ <externalRef href="item-1.1.rng"/>
+ </oneOrMore>
+ </choice>
+ </element>
+ </define>
+</grammar>
--
1.8.3.1
From 316b6f66ca5425093503c51c2f8738922287ebca Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 16 Sep 2020 15:59:34 -0400
Subject: [PATCH 4/6] Fix: tools: Save the optarg parameter for
--list-ocf-alternatives.
We need this so it can be added to the XML output of crm_resource.
---
tools/crm_resource.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 6573ad5..acaddc0 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -720,9 +720,7 @@ list_alternatives_cb(const gchar *option_name, const gchar *optarg,
gpointer data, GError **error)
{
SET_COMMAND(cmd_list_alternatives);
- options.require_cib = FALSE;
- options.require_dataset = FALSE;
- options.require_resource = FALSE;
+ get_agent_spec(optarg);
return TRUE;
}
--
1.8.3.1
From c063ce9b193f2022611e651c13afcb3ceb5969e3 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 2 Sep 2020 16:20:10 -0400
Subject: [PATCH 5/6] Fix: scheduler: Use the default format handler in a few
more places.
---
lib/pengine/pe_output.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/lib/pengine/pe_output.c b/lib/pengine/pe_output.c
index d0f96f4..9d43e5f 100644
--- a/lib/pengine/pe_output.c
+++ b/lib/pengine/pe_output.c
@@ -1847,9 +1847,7 @@ static pcmk__message_entry_t fmt_functions[] = {
{ "cluster-times", "log", pe__cluster_times_text },
{ "cluster-times", "text", pe__cluster_times_text },
{ "cluster-times", "xml", pe__cluster_times_xml },
- { "failed-action", "html", pe__failed_action_text },
- { "failed-action", "log", pe__failed_action_text },
- { "failed-action", "text", pe__failed_action_text },
+ { "failed-action", "default", pe__failed_action_text },
{ "failed-action", "xml", pe__failed_action_xml },
{ "group", "xml", pe__group_xml },
{ "group", "html", pe__group_html },
@@ -1868,9 +1866,7 @@ static pcmk__message_entry_t fmt_functions[] = {
{ "node-attribute", "log", pe__node_attribute_text },
{ "node-attribute", "text", pe__node_attribute_text },
{ "node-attribute", "xml", pe__node_attribute_xml },
- { "op-history", "html", pe__op_history_text },
- { "op-history", "log", pe__op_history_text },
- { "op-history", "text", pe__op_history_text },
+ { "op-history", "default", pe__op_history_text },
{ "op-history", "xml", pe__op_history_xml },
{ "primitive", "xml", pe__resource_xml },
{ "primitive", "html", pe__resource_html },
--
1.8.3.1
From a32b99f5fd09ec15dbba6785c5d8dc2e220417a3 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 3 Sep 2020 10:23:16 -0400
Subject: [PATCH 6/6] Refactor: scheduler: Expose native_output_string as
pcmk__native_output_string.
The plan is that this function can be used to help build the string that
is output for each line of "crm_resource -o" output. It appears that
output only happens for primitive resources. However, I've added a
check at the beginning just in case it's called for some other type of
resource.
---
include/crm/pengine/internal.h | 3 +++
lib/pengine/native.c | 24 ++++++++++++++----------
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h
index abe7a76..d658e86 100644
--- a/include/crm/pengine/internal.h
+++ b/include/crm/pengine/internal.h
@@ -243,6 +243,9 @@ void clone_print(pe_resource_t * rsc, const char *pre_text, long options, void *
void pe__print_bundle(pe_resource_t *rsc, const char *pre_text, long options,
void *print_data);
+gchar * pcmk__native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node,
+ long options, const char *target_role, bool show_nodes);
+
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name
, size_t pairs_count, ...);
char *pe__node_display_name(pe_node_t *node, bool print_detail);
diff --git a/lib/pengine/native.c b/lib/pengine/native.c
index 8f0c5c9..bf1f5c0 100644
--- a/lib/pengine/native.c
+++ b/lib/pengine/native.c
@@ -570,17 +570,21 @@ add_output_node(GString *s, const char *node, bool have_nodes)
* \return Newly allocated string description of resource
* \note Caller must free the result with g_free().
*/
-static gchar *
-native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node,
- long options, const char *target_role, bool show_nodes)
+gchar *
+pcmk__native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node,
+ long options, const char *target_role, bool show_nodes)
{
const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
const char *provider = NULL;
const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
- char *retval = NULL;
+ gchar *retval = NULL;
GString *outstr = NULL;
bool have_flags = false;
+ if (rsc->variant != pe_native) {
+ return NULL;
+ }
+
CRM_CHECK(name != NULL, name = "unknown");
CRM_CHECK(kind != NULL, kind = "unknown");
CRM_CHECK(class != NULL, class = "unknown");
@@ -758,8 +762,8 @@ pe__common_output_html(pcmk__output_t *out, pe_resource_t * rsc,
}
{
- gchar *s = native_output_string(rsc, name, node, options, target_role,
- true);
+ gchar *s = pcmk__native_output_string(rsc, name, node, options,
+ target_role, true);
list_node = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
pcmk_create_html_node(list_node, "span", NULL, cl, s);
@@ -826,8 +830,8 @@ pe__common_output_text(pcmk__output_t *out, pe_resource_t * rsc,
}
{
- gchar *s = native_output_string(rsc, name, node, options, target_role,
- true);
+ gchar *s = pcmk__native_output_string(rsc, name, node, options,
+ target_role, true);
out->list_item(out, NULL, "%s", s);
g_free(s);
@@ -923,8 +927,8 @@ common_print(pe_resource_t * rsc, const char *pre_text, const char *name, pe_nod
}
{
- gchar *resource_s = native_output_string(rsc, name, node, options,
- target_role, false);
+ gchar *resource_s = pcmk__native_output_string(rsc, name, node, options,
+ target_role, false);
status_print("%s%s", (pre_text? pre_text : ""), resource_s);
g_free(resource_s);
}
--
1.8.3.1

View File

@ -1,27 +0,0 @@
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

View File

@ -0,0 +1,210 @@
From 477b7b679d58455dc38c2594b29a1ecfbe88e80c Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 2 Nov 2020 14:55:27 -0500
Subject: [PATCH 1/2] Fix: libcrmcommon: Prevent a segfault in
pcmk__cmdline_preproc.
The list of special single-character args is optional. The function
currently handles it being an empty string, but it should handle a NULL
as well.
---
lib/common/cmdline.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/common/cmdline.c b/lib/common/cmdline.c
index d66ccc7..66f1976 100644
--- a/lib/common/cmdline.c
+++ b/lib/common/cmdline.c
@@ -203,7 +203,7 @@ pcmk__cmdline_preproc(char **argv, const char *special) {
* glib does not. Grab both the argument and its value and
* separate them into a new argument.
*/
- if (strchr(special, *ch) != NULL) {
+ if (special != NULL && strchr(special, *ch) != NULL) {
/* The argument does not occur at the end of this string of
* arguments. Take everything through the end as its value.
*/
--
1.8.3.1
From d1f4a975fa783045254521f415f1899b34ee96e3 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 2 Nov 2020 16:06:29 -0500
Subject: [PATCH 2/2] Test: libcrmcommon: Add unit tests for
pcmk__cmdline_preproc.
---
configure.ac | 1 +
lib/common/tests/Makefile.am | 2 +-
lib/common/tests/cmdline/Makefile.am | 29 ++++++
.../tests/cmdline/pcmk__cmdline_preproc_test.c | 102 +++++++++++++++++++++
4 files changed, 133 insertions(+), 1 deletion(-)
create mode 100644 lib/common/tests/cmdline/Makefile.am
create mode 100644 lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c
diff --git a/configure.ac b/configure.ac
index 7ed4a30..36e85a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2006,6 +2006,7 @@ AC_CONFIG_FILES(Makefile \
lib/pacemaker-cluster.pc \
lib/common/Makefile \
lib/common/tests/Makefile \
+ lib/common/tests/cmdline/Makefile \
lib/common/tests/flags/Makefile \
lib/common/tests/operations/Makefile \
lib/common/tests/strings/Makefile \
diff --git a/lib/common/tests/Makefile.am b/lib/common/tests/Makefile.am
index 33c45cb..f3eaeec 100644
--- a/lib/common/tests/Makefile.am
+++ b/lib/common/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = flags operations strings utils
+SUBDIRS = cmdline flags operations strings utils
diff --git a/lib/common/tests/cmdline/Makefile.am b/lib/common/tests/cmdline/Makefile.am
new file mode 100644
index 0000000..e69ef21
--- /dev/null
+++ b/lib/common/tests/cmdline/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright 2020 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
+LDADD = $(top_builddir)/lib/common/libcrmcommon.la
+
+include $(top_srcdir)/mk/glib-tap.mk
+
+# Add each test program here. Each test should be written as a little standalone
+# program using the glib unit testing functions. See the documentation for more
+# information.
+#
+# https://developer.gnome.org/glib/unstable/glib-Testing.html
+#
+# Add "_test" to the end of all test program names to simplify .gitignore.
+test_programs = pcmk__cmdline_preproc_test
+
+# If any extra data needs to be added to the source distribution, add it to the
+# following list.
+dist_test_data =
+
+# If any extra data needs to be used by tests but should not be added to the
+# source distribution, add it to the following list.
+test_data =
diff --git a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c
new file mode 100644
index 0000000..e13c983
--- /dev/null
+++ b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+#include <crm/common/cmdline_internal.h>
+
+#define LISTS_EQ(a, b) { \
+ g_assert_cmpint(g_strv_length((gchar **) (a)), ==, g_strv_length((gchar **) (b))); \
+ for (int i = 0; i < g_strv_length((a)); i++) { \
+ g_assert_cmpstr((a)[i], ==, (b)[i]); \
+ } \
+}
+
+static void
+empty_input(void) {
+ g_assert_cmpint(pcmk__cmdline_preproc(NULL, "") == NULL, ==, TRUE);
+}
+
+static void
+no_specials(void) {
+ const char *argv[] = { "-a", "-b", "-c", "-d", NULL };
+ const gchar *expected[] = { "-a", "-b", "-c", "-d", NULL };
+
+ gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+
+ processed = pcmk__cmdline_preproc((char **) argv, "");
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+}
+
+static void
+single_dash(void) {
+ const char *argv[] = { "-", NULL };
+ const gchar *expected[] = { "-", NULL };
+
+ gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+}
+
+static void
+double_dash(void) {
+ const char *argv[] = { "-a", "--", "-bc", NULL };
+ const gchar *expected[] = { "-a", "--", "-bc", NULL };
+
+ gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+}
+
+static void
+special_args(void) {
+ const char *argv[] = { "-aX", "-Fval", NULL };
+ const gchar *expected[] = { "-a", "X", "-F", "val", NULL };
+
+ gchar **processed = pcmk__cmdline_preproc((char **) argv, "aF");
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+}
+
+static void
+special_arg_at_end(void) {
+ const char *argv[] = { "-a", NULL };
+ const gchar *expected[] = { "-a", NULL };
+
+ gchar **processed = pcmk__cmdline_preproc((char **) argv, "a");
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+}
+
+static void
+long_arg(void) {
+ const char *argv[] = { "--blah=foo", NULL };
+ const gchar *expected[] = { "--blah=foo", NULL };
+
+ gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+ LISTS_EQ(processed, expected);
+ g_strfreev(processed);
+}
+
+int
+main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/common/cmdline/preproc/empty_input", empty_input);
+ g_test_add_func("/common/cmdline/preproc/no_specials", no_specials);
+ g_test_add_func("/common/cmdline/preproc/single_dash", single_dash);
+ g_test_add_func("/common/cmdline/preproc/double_dash", double_dash);
+ g_test_add_func("/common/cmdline/preproc/special_args", special_args);
+ g_test_add_func("/common/cmdline/preproc/special_arg_at_end", special_arg_at_end);
+ g_test_add_func("/common/cmdline/preproc/long_arg", long_arg);
+ return g_test_run();
+}
--
1.8.3.1

View File

@ -1,32 +0,0 @@
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

7903
SOURCES/006-digests.patch Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,685 +0,0 @@
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

1764
SOURCES/008-digests.patch Normal file

File diff suppressed because it is too large Load Diff

846
SOURCES/009-digests.patch Normal file
View File

@ -0,0 +1,846 @@
From df587aaec07b4a08364d4024b3d0c73e6dede562 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Mon, 9 Nov 2020 14:55:42 -0600
Subject: [PATCH 1/9] Refactor: scheduler: simplify XML attribute filtering
function
---
lib/pengine/pe_digest.c | 52 ++++++++++++++++++++++++++-----------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
index 5bcd22b..1e119f9 100644
--- a/lib/pengine/pe_digest.c
+++ b/lib/pengine/pe_digest.c
@@ -45,30 +45,38 @@ pe__free_digests(gpointer ptr)
}
}
+/*!
+ * \internal
+ * \brief Remove named attributes from an XML element
+ *
+ * \param[in,out] param_set XML to be filtered
+ * \param[in] param_string Space-separated list of attribute names
+ * \param[in] need_present Whether to remove attributes that match,
+ * or those that don't match
+ */
static void
-filter_parameters(xmlNode * param_set, const char *param_string, bool need_present)
+filter_parameters(xmlNode *param_set, const char *param_string,
+ bool need_present)
{
- if (param_set && param_string) {
- xmlAttrPtr xIter = param_set->properties;
-
- while (xIter) {
- const char *prop_name = (const char *)xIter->name;
- char *name = crm_strdup_printf(" %s ", prop_name);
- char *match = strstr(param_string, name);
+ if ((param_set == NULL) || (param_string == NULL)) {
+ return;
+ }
+ for (xmlAttrPtr xIter = param_set->properties; xIter; ) {
+ const char *prop_name = (const char *) xIter->name;
+ char *name = crm_strdup_printf(" %s ", prop_name);
+ char *match = strstr(param_string, name);
- free(name);
+ free(name);
- // Do now, because current entry might get removed below
- xIter = xIter->next;
+ // Do now, because current entry might get removed below
+ xIter = xIter->next;
- if (need_present && match == NULL) {
- crm_trace("%s not found in %s", prop_name, param_string);
- xml_remove_prop(param_set, prop_name);
+ if ((need_present && (match == NULL))
+ || (!need_present && (match != NULL))) {
- } else if (need_present == FALSE && match) {
- crm_trace("%s found in %s", prop_name, param_string);
- xml_remove_prop(param_set, prop_name);
- }
+ crm_trace("Filtering %s (%sfound in '%s')",
+ prop_name, (need_present? "not " : ""), param_string);
+ xml_remove_prop(param_set, prop_name);
}
}
}
@@ -203,9 +211,7 @@ calculate_secure_digest(op_digest_cache_t *data, pe_resource_t *rsc,
g_hash_table_foreach(overrides, hash2field, data->params_secure);
}
g_hash_table_foreach(rsc->parameters, hash2field, data->params_secure);
- if (secure_list != NULL) {
- filter_parameters(data->params_secure, secure_list, FALSE);
- }
+ filter_parameters(data->params_secure, secure_list, FALSE);
if (pcmk_is_set(pcmk_get_ra_caps(class),
pcmk_ra_cap_fence_params)) {
/* For stonith resources, Pacemaker adds special parameters,
@@ -259,9 +265,7 @@ calculate_restart_digest(op_digest_cache_t *data, xmlNode *xml_op,
// Then filter out reloadable parameters, if any
value = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);
- if (value != NULL) {
- filter_parameters(data->params_restart, value, TRUE);
- }
+ filter_parameters(data->params_restart, value, TRUE);
value = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
data->digest_restart_calc = calculate_operation_digest(data->params_restart,
--
1.8.3.1
From f030af8771601d46947ac9276538c46c6c296504 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Mon, 9 Nov 2020 18:37:37 -0600
Subject: [PATCH 2/9] Refactor: scheduler: remember whether action is probe
when unpacking
... to reduce code duplication and improve readability
---
lib/pengine/utils.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
index 04110be..b0922fa 100644
--- a/lib/pengine/utils.c
+++ b/lib/pengine/utils.c
@@ -995,6 +995,8 @@ unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * contai
{
int timeout_ms = 0;
const char *value = NULL;
+ bool is_probe = pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
+ && (interval_ms == 0);
#if ENABLE_VERSIONED_ATTRS
pe_rsc_action_details_t *rsc_details = NULL;
#endif
@@ -1026,8 +1028,7 @@ unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * contai
action->meta, NULL, FALSE, data_set);
// Determine probe default timeout differently
- if (pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
- && (interval_ms == 0)) {
+ if (is_probe) {
xmlNode *min_interval_mon = find_min_interval_mon(action->rsc, FALSE);
if (min_interval_mon) {
@@ -1099,8 +1100,7 @@ unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * contai
if (pcmk_is_set(pcmk_get_ra_caps(rsc_rule_data.standard),
pcmk_ra_cap_fence_params)
&& (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)
- || (pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
- && (interval_ms == 0)))
+ || is_probe)
&& action->rsc->parameters) {
value = g_hash_table_lookup(action->rsc->parameters,
--
1.8.3.1
From 9de547849697cd6a3581db3f83b04f68d0405d9d Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 10 Nov 2020 15:15:01 -0600
Subject: [PATCH 3/9] Refactor: scheduler: don't include originally unpacked
resource parameters in digest
Previously, when calculating an operation digest, calculate_main_digest() would
grab the following, in order of highest to lowest precedence:
* instance attributes evaluated for the appropriate node
* instance attributes specified with the operation
* instance attributes as originally unpacked (without evaluating for any node)
* resource meta-attributes
Adding the originally unpacked instance attributes was redundant, since
node-evaluated instance attributes would always be a superset of those and
would take precedence.
---
lib/pengine/pe_digest.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c
index 1e119f9..dd6b753 100644
--- a/lib/pengine/pe_digest.c
+++ b/lib/pengine/pe_digest.c
@@ -162,7 +162,6 @@ calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc,
}
g_hash_table_foreach(local_rsc_params, hash2field, data->params_all);
g_hash_table_foreach(action->extra, hash2field, data->params_all);
- g_hash_table_foreach(rsc->parameters, hash2field, data->params_all);
g_hash_table_foreach(action->meta, hash2metafield, data->params_all);
#if ENABLE_VERSIONED_ATTRS
--
1.8.3.1
From e9921b2ab3e9eeab6227d97cc12b85fa04dfd187 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 13 Nov 2020 09:27:12 -0600
Subject: [PATCH 4/9] Refactor: scheduler: reuse existing function to check for
remote in XML
... to reduce code duplication and improve readability
---
lib/pengine/bundle.c | 21 +++------------------
1 file changed, 3 insertions(+), 18 deletions(-)
diff --git a/lib/pengine/bundle.c b/lib/pengine/bundle.c
index 76730c7..4f6eac3 100644
--- a/lib/pengine/bundle.c
+++ b/lib/pengine/bundle.c
@@ -959,28 +959,13 @@ pe__bundle_needs_remote_name(pe_resource_t *rsc)
const char *value;
if (rsc == NULL) {
- return FALSE;
+ return false;
}
value = g_hash_table_lookup(rsc->parameters, XML_RSC_ATTR_REMOTE_RA_ADDR);
- if (!pcmk__str_eq(value, "#uname", pcmk__str_casei)) {
- return FALSE;
- } else {
- const char *match[3][2] = {
- { XML_ATTR_TYPE, "remote" },
- { XML_AGENT_ATTR_CLASS, PCMK_RESOURCE_CLASS_OCF },
- { XML_AGENT_ATTR_PROVIDER, "pacemaker" },
- };
-
- for (int m = 0; m < 3; m++) {
- value = crm_element_value(rsc->xml, match[m][0]);
- if (!pcmk__str_eq(value, match[m][1], pcmk__str_casei)) {
- return FALSE;
- }
- }
- }
- return TRUE;
+ return pcmk__str_eq(value, "#uname", pcmk__str_casei)
+ && xml_contains_remote_node(rsc->xml);
}
const char *
--
1.8.3.1
From 0f220e1cd25ec095492ac4b346452520f4b71cf1 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Wed, 11 Nov 2020 15:29:46 -0600
Subject: [PATCH 5/9] Refactor: scheduler: remove dead code
Several internal expression-testing functions were unused. While they might
have had some potential future value, the abundance of similarly named
functions made debugging difficult. Comment blocks were added to the functions
they wrapped, which should add similar value.
Also, we had an internal wrapper for pe__eval_date_expr() that was used
only in crm_rule, so it was moved there.
---
include/crm/pengine/rules_internal.h | 10 +--
lib/pengine/rules.c | 130 +++++++++++------------------------
tools/crm_rule.c | 27 +++++++-
3 files changed, 66 insertions(+), 101 deletions(-)
diff --git a/include/crm/pengine/rules_internal.h b/include/crm/pengine/rules_internal.h
index f60263a..7380826 100644
--- a/include/crm/pengine/rules_internal.h
+++ b/include/crm/pengine/rules_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2019 the Pacemaker project contributors
+ * Copyright 2015-2020 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -28,14 +28,6 @@ gboolean pe__eval_op_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data);
gboolean pe__eval_role_expr(xmlNode *expr, pe_rule_eval_data_t *rule_data);
gboolean pe__eval_rsc_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data);
-int pe_eval_date_expression(xmlNode *time_expr,
- crm_time_t *now,
- crm_time_t *next_change);
-gboolean pe_test_date_expression(xmlNode *time_expr, crm_time_t *now,
- crm_time_t *next_change);
int pe_cron_range_satisfied(crm_time_t * now, xmlNode * cron_spec);
-gboolean pe_test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now,
- pe_match_data_t *match_data);
-gboolean pe_test_role_expression(xmlNode * expr, enum rsc_role_e role, crm_time_t * now);
#endif
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
index 28562aa..be30e67 100644
--- a/lib/pengine/rules.c
+++ b/lib/pengine/rules.c
@@ -140,37 +140,6 @@ find_expression_type(xmlNode * expr)
return attr_expr;
}
-gboolean
-pe_test_role_expression(xmlNode *expr, enum rsc_role_e role, crm_time_t *now)
-{
- pe_rule_eval_data_t rule_data = {
- .node_hash = NULL,
- .role = role,
- .now = now,
- .match_data = NULL,
- .rsc_data = NULL,
- .op_data = NULL
- };
-
- return pe__eval_role_expr(expr, &rule_data);
-}
-
-gboolean
-pe_test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now,
- pe_match_data_t *match_data)
-{
- pe_rule_eval_data_t rule_data = {
- .node_hash = hash,
- .role = RSC_ROLE_UNKNOWN,
- .now = now,
- .match_data = match_data,
- .rsc_data = NULL,
- .op_data = NULL
- };
-
- return pe__eval_attr_expr(expr, &rule_data);
-}
-
/* As per the nethack rules:
*
* moon period = 29.53058 days ~= 30, year = 365.2422 days
@@ -331,38 +300,6 @@ pe_parse_xml_duration(crm_time_t * start, xmlNode * duration_spec)
return end;
}
-/*!
- * \internal
- * \brief Test a date expression (pass/fail) for a specific time
- *
- * \param[in] time_expr date_expression XML
- * \param[in] now Time for which to evaluate expression
- * \param[out] next_change If not NULL, set to when evaluation will change
- *
- * \return TRUE if date expression is in effect at given time, FALSE otherwise
- */
-gboolean
-pe_test_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
-{
- pe_rule_eval_data_t rule_data = {
- .node_hash = NULL,
- .role = RSC_ROLE_UNKNOWN,
- .now = now,
- .match_data = NULL,
- .rsc_data = NULL,
- .op_data = NULL
- };
-
- switch (pe__eval_date_expr(expr, &rule_data, next_change)) {
- case pcmk_rc_within_range:
- case pcmk_rc_ok:
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
// Set next_change to t if t is earlier
static void
crm_time_set_if_earlier(crm_time_t *next_change, crm_time_t *t)
@@ -375,31 +312,6 @@ crm_time_set_if_earlier(crm_time_t *next_change, crm_time_t *t)
}
}
-/*!
- * \internal
- * \brief Evaluate a date expression for a specific time
- *
- * \param[in] time_expr date_expression XML
- * \param[in] now Time for which to evaluate expression
- * \param[out] next_change If not NULL, set to when evaluation will change
- *
- * \return Standard Pacemaker return code
- */
-int
-pe_eval_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
-{
- pe_rule_eval_data_t rule_data = {
- .node_hash = NULL,
- .role = RSC_ROLE_UNKNOWN,
- .now = now,
- .match_data = NULL,
- .rsc_data = NULL,
- .op_data = NULL
- };
-
- return pe__eval_date_expr(expr, &rule_data, next_change);
-}
-
// Information about a block of nvpair elements
typedef struct sorted_set_s {
int score; // This block's score for sorting
@@ -908,7 +820,16 @@ pe_eval_subexpr(xmlNode *expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_
break;
case time_expr:
- accept = pe_test_date_expression(expr, rule_data->now, next_change);
+ switch (pe__eval_date_expr(expr, rule_data, next_change)) {
+ case pcmk_rc_within_range:
+ case pcmk_rc_ok:
+ accept = TRUE;
+ break;
+
+ default:
+ accept = FALSE;
+ break;
+ }
break;
case role_expr:
@@ -1104,6 +1025,16 @@ accept_attr_expr(const char *l_val, const char *r_val, const char *type,
return false; // Should never reach this point
}
+/*!
+ * \internal
+ * \brief Evaluate a node attribute expression based on #uname, #id, #kind,
+ * or a generic node attribute
+ *
+ * \param[in] expr XML of rule expression
+ * \param[in] rule_data The match_data and node_hash members are used
+ *
+ * \return TRUE if rule_data satisfies the expression, FALSE otherwise
+ */
gboolean
pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
{
@@ -1169,8 +1100,16 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
return accept_attr_expr(h_val, value, type, op);
}
-
-
+/*!
+ * \internal
+ * \brief Evaluate a date_expression
+ *
+ * \param[in] expr XML of rule expression
+ * \param[in] rule_data Only the now member is used
+ * \param[out] next_change If not NULL, set to when evaluation will change
+ *
+ * \return Standard Pacemaker return code
+ */
int
pe__eval_date_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
{
@@ -1285,6 +1224,15 @@ pe__eval_op_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data) {
return TRUE;
}
+/*!
+ * \internal
+ * \brief Evaluate a node attribute expression based on #role
+ *
+ * \param[in] expr XML of rule expression
+ * \param[in] rule_data Only the role member is used
+ *
+ * \return TRUE if rule_data->role satisfies the expression, FALSE otherwise
+ */
gboolean
pe__eval_role_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
{
diff --git a/tools/crm_rule.c b/tools/crm_rule.c
index 0e44828..2871f3d 100644
--- a/tools/crm_rule.c
+++ b/tools/crm_rule.c
@@ -75,6 +75,31 @@ mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **e
return TRUE;
}
+/*!
+ * \internal
+ * \brief Evaluate a date expression for a specific time
+ *
+ * \param[in] time_expr date_expression XML
+ * \param[in] now Time for which to evaluate expression
+ * \param[out] next_change If not NULL, set to when evaluation will change
+ *
+ * \return Standard Pacemaker return code
+ */
+static int
+eval_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
+{
+ pe_rule_eval_data_t rule_data = {
+ .node_hash = NULL,
+ .role = RSC_ROLE_UNKNOWN,
+ .now = now,
+ .match_data = NULL,
+ .rsc_data = NULL,
+ .op_data = NULL
+ };
+
+ return pe__eval_date_expr(expr, &rule_data, next_change);
+}
+
static int
crm_rule_check(pe_working_set_t *data_set, const char *rule_id, crm_time_t *effective_date)
{
@@ -156,7 +181,7 @@ crm_rule_check(pe_working_set_t *data_set, const char *rule_id, crm_time_t *effe
CRM_ASSERT(match != NULL);
CRM_ASSERT(find_expression_type(match) == time_expr);
- rc = pe_eval_date_expression(match, effective_date, NULL);
+ rc = eval_date_expression(match, effective_date, NULL);
if (rc == pcmk_rc_within_range) {
printf("Rule %s is still in effect\n", rule_id);
--
1.8.3.1
From 91a6ec4bec86de7389fcd64cb27e315da760f0dd Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Wed, 11 Nov 2020 16:44:57 -0600
Subject: [PATCH 6/9] Refactor: scheduler: make constraint unpacking function
static
... for linker efficiency and readability. Also change the return type to void
since it was ignored (and the same for some related functions).
---
include/pcmki/pcmki_sched_allocate.h | 4 +--
lib/pacemaker/pcmk_sched_constraints.c | 46 ++++++++++++++++------------------
2 files changed, 23 insertions(+), 27 deletions(-)
diff --git a/include/pcmki/pcmki_sched_allocate.h b/include/pcmki/pcmki_sched_allocate.h
index efc0da6..a7f8c11 100644
--- a/include/pcmki/pcmki_sched_allocate.h
+++ b/include/pcmki/pcmki_sched_allocate.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2019 the Pacemaker project contributors
+ * Copyright 2004-2020 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -143,8 +143,6 @@ extern gboolean unpack_rsc_order(xmlNode * xml_obj, pe_working_set_t * data_set)
extern gboolean unpack_rsc_colocation(xmlNode * xml_obj, pe_working_set_t * data_set);
-extern gboolean unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set);
-
extern gboolean unpack_rsc_ticket(xmlNode * xml_obj, pe_working_set_t * data_set);
void LogNodeActions(pe_working_set_t * data_set, gboolean terminal);
diff --git a/lib/pacemaker/pcmk_sched_constraints.c b/lib/pacemaker/pcmk_sched_constraints.c
index 6ed2d8c..121754d 100644
--- a/lib/pacemaker/pcmk_sched_constraints.c
+++ b/lib/pacemaker/pcmk_sched_constraints.c
@@ -48,6 +48,7 @@ static pe__location_t *generate_location_rule(pe_resource_t *rsc,
crm_time_t *next_change,
pe_working_set_t *data_set,
pe_match_data_t *match_data);
+static void unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set);
static bool
evaluate_lifetime(xmlNode *lifetime, pe_working_set_t *data_set)
@@ -709,11 +710,13 @@ tag_to_set(xmlNode * xml_obj, xmlNode ** rsc_set, const char * attr,
return TRUE;
}
-static gboolean unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role,
- const char * score, pe_working_set_t * data_set, pe_match_data_t * match_data);
+static void unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc_lh,
+ const char *role, const char *score,
+ pe_working_set_t *data_set,
+ pe_match_data_t *match_data);
-static gboolean
-unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
+static void
+unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set)
{
const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
const char *value = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
@@ -721,7 +724,7 @@ unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
if(value) {
pe_resource_t *rsc_lh = pe_find_constraint_resource(data_set->resources, value);
- return unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
+ unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
}
value = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE_PATTERN);
@@ -741,7 +744,7 @@ unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
" has invalid value '%s'", id, value);
regfree(r_patt);
free(r_patt);
- return FALSE;
+ return;
}
for (rIter = data_set->resources; rIter; rIter = rIter->next) {
@@ -787,13 +790,12 @@ unpack_simple_location(xmlNode * xml_obj, pe_working_set_t * data_set)
regfree(r_patt);
free(r_patt);
}
-
- return FALSE;
}
-static gboolean
-unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role,
- const char * score, pe_working_set_t * data_set, pe_match_data_t * match_data)
+static void
+unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc_lh, const char *role,
+ const char *score, pe_working_set_t *data_set,
+ pe_match_data_t *match_data)
{
pe__location_t *location = NULL;
const char *id_lh = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
@@ -804,7 +806,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
if (rsc_lh == NULL) {
pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
"does not exist", id, id_lh);
- return FALSE;
+ return;
}
if (score == NULL) {
@@ -816,7 +818,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
pe_node_t *match = pe_find_node(data_set->nodes, node);
if (!match) {
- return FALSE;
+ return;
}
location = rsc2node_new(id, rsc_lh, score_i, discovery, match, data_set);
@@ -850,7 +852,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
pe__update_recheck_time(t, data_set);
}
crm_time_free(next_change);
- return TRUE;
+ return;
}
if (role == NULL) {
@@ -860,7 +862,7 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
if (location && role) {
if (text2role(role) == RSC_ROLE_UNKNOWN) {
pe_err("Invalid constraint %s: Bad role %s", id, role);
- return FALSE;
+ return;
} else {
enum rsc_role_e r = text2role(role);
@@ -877,8 +879,6 @@ unpack_rsc_location(xmlNode * xml_obj, pe_resource_t * rsc_lh, const char * role
}
}
}
-
- return TRUE;
}
static gboolean
@@ -992,8 +992,8 @@ unpack_location_set(xmlNode * location, xmlNode * set, pe_working_set_t * data_s
return TRUE;
}
-gboolean
-unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
+static void
+unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
{
xmlNode *set = NULL;
gboolean any_sets = FALSE;
@@ -1002,7 +1002,7 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
xmlNode *expanded_xml = NULL;
if (unpack_location_tags(xml_obj, &expanded_xml, data_set) == FALSE) {
- return FALSE;
+ return;
}
if (expanded_xml) {
@@ -1020,7 +1020,7 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
if (expanded_xml) {
free_xml(expanded_xml);
}
- return FALSE;
+ return;
}
}
}
@@ -1031,10 +1031,8 @@ unpack_location(xmlNode * xml_obj, pe_working_set_t * data_set)
}
if (any_sets == FALSE) {
- return unpack_simple_location(xml_obj, data_set);
+ unpack_simple_location(xml_obj, data_set);
}
-
- return TRUE;
}
static int
--
1.8.3.1
From df842adafca8ba56ddb5b448490ffef54ea785d4 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 13 Nov 2020 09:19:51 -0600
Subject: [PATCH 7/9] Refactor: scheduler: trivial refactoring of nvpair
evaluation
... for readability
---
lib/pengine/rules.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
index be30e67..86e7899 100644
--- a/lib/pengine/rules.c
+++ b/lib/pengine/rules.c
@@ -529,20 +529,19 @@ static GList *
make_pairs(xmlNode *top, xmlNode *xml_obj, const char *set_name,
const char *always_first)
{
- GListPtr unsorted = NULL;
- const char *score = NULL;
- sorted_set_t *pair = NULL;
- xmlNode *attr_set = NULL;
+ GList *unsorted = NULL;
if (xml_obj == NULL) {
return NULL;
}
- for (attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
+ for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
attr_set = pcmk__xe_next(attr_set)) {
- /* Uncertain if set_name == NULL check is strictly necessary here */
- if (pcmk__str_eq(set_name, (const char *)attr_set->name, pcmk__str_null_matches)) {
- pair = NULL;
+ if (pcmk__str_eq(set_name, (const char *) attr_set->name,
+ pcmk__str_null_matches)) {
+ const char *score = NULL;
+ sorted_set_t *pair = NULL;
+
attr_set = expand_idref(attr_set, top);
if (attr_set == NULL) {
continue;
--
1.8.3.1
From 373c224ac1c41bd47a928a7523744c6c678a6543 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 13 Nov 2020 09:21:35 -0600
Subject: [PATCH 8/9] Low: scheduler: correctly skip dangling id-ref
When evaluating XML nvpair blocks, make_pairs() previously reused the
"for" loop variable when expanding id-ref's. However if the id-ref was dangling
(only possible if schema enforcement is turned off), this would make it NULL
and thus exiting the loop instead of continuing.
---
lib/pengine/rules.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
index 86e7899..1bd807f 100644
--- a/lib/pengine/rules.c
+++ b/lib/pengine/rules.c
@@ -541,18 +541,19 @@ make_pairs(xmlNode *top, xmlNode *xml_obj, const char *set_name,
pcmk__str_null_matches)) {
const char *score = NULL;
sorted_set_t *pair = NULL;
+ xmlNode *expanded_attr_set = expand_idref(attr_set, top);
- attr_set = expand_idref(attr_set, top);
- if (attr_set == NULL) {
+ if (expanded_attr_set == NULL) {
+ // Schema (if not "none") prevents this
continue;
}
pair = calloc(1, sizeof(sorted_set_t));
- pair->name = ID(attr_set);
+ pair->name = ID(expanded_attr_set);
pair->special_name = always_first;
- pair->attr_set = attr_set;
+ pair->attr_set = expanded_attr_set;
- score = crm_element_value(attr_set, XML_RULE_ATTR_SCORE);
+ score = crm_element_value(expanded_attr_set, XML_RULE_ATTR_SCORE);
pair->score = char2score(score);
unsorted = g_list_prepend(unsorted, pair);
--
1.8.3.1
From b59717751c168ec745bedbcc5696bee11036d931 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 12 Nov 2020 14:37:27 -0600
Subject: [PATCH 9/9] Low: scheduler: treat missing parameter as NULL in rules
with value-source
Previously, if value-source were set to "param" or "meta", and an affected
resource did not have the specified parameter, the parameter name would wrongly
be used as the value to compare against. Now, use NULL as the value to compare
against.
---
lib/pengine/rules.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c
index 1bd807f..e5d452f 100644
--- a/lib/pengine/rules.c
+++ b/lib/pengine/rules.c
@@ -1041,6 +1041,7 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
gboolean attr_allocated = FALSE;
const char *h_val = NULL;
GHashTable *table = NULL;
+ bool literal = true;
const char *op = NULL;
const char *type = NULL;
@@ -1071,18 +1072,22 @@ pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
}
if (pcmk__str_eq(value_source, "param", pcmk__str_casei)) {
+ literal = false;
table = rule_data->match_data->params;
} else if (pcmk__str_eq(value_source, "meta", pcmk__str_casei)) {
+ literal = false;
table = rule_data->match_data->meta;
}
}
- if (table) {
+ if (!literal) {
const char *param_name = value;
const char *param_value = NULL;
- if (param_name && param_name[0]) {
- if ((param_value = (const char *)g_hash_table_lookup(table, param_name))) {
+ value = NULL;
+ if ((table != NULL) && !pcmk__str_empty(param_name)) {
+ param_value = (const char *)g_hash_table_lookup(table, param_name);
+ if (param_value != NULL) {
value = param_value;
}
}
--
1.8.3.1

View File

@ -1,34 +0,0 @@
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

View File

@ -1,476 +0,0 @@
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

View File

@ -0,0 +1,26 @@
From d1b6b6cb5151763888ac8bc55708d2e7cbbf590b Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 19 Nov 2020 13:35:31 -0500
Subject: [PATCH] Fix: scheduler: Fix output of failed actions without an
operation_key.
---
lib/pengine/pe_output.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/pengine/pe_output.c b/lib/pengine/pe_output.c
index 1a3f93d..b91348f 100644
--- a/lib/pengine/pe_output.c
+++ b/lib/pengine/pe_output.c
@@ -975,7 +975,7 @@ pe__failed_action_xml(pcmk__output_t *out, va_list args) {
xmlNodePtr node = pcmk__output_create_xml_node(out, "failure");
xmlSetProp(node, (pcmkXmlStr) (op_key ? "op_key" : "id"),
- (pcmkXmlStr) (op_key ? op_key : "id"));
+ (pcmkXmlStr) (op_key ? op_key : ID(xml_op)));
xmlSetProp(node, (pcmkXmlStr) "node",
(pcmkXmlStr) crm_element_value(xml_op, XML_ATTR_UNAME));
xmlSetProp(node, (pcmkXmlStr) "exitstatus",
--
1.8.3.1

View File

@ -1,270 +0,0 @@
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,85 +0,0 @@
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,285 @@
From 0700a4814a598d0e2e9bd54f970c6d3ff66184df Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 24 Nov 2020 16:17:34 +0100
Subject: [PATCH 1/2] Refactor: move stonith__register_messages() call from
pcmk__out_prologue() to the calling functions
---
lib/pacemaker/pcmk_fence.c | 14 ++++++++++++++
lib/pacemaker/pcmk_output.c | 1 -
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c
index 7beedff..d591379 100644
--- a/lib/pacemaker/pcmk_fence.c
+++ b/lib/pacemaker/pcmk_fence.c
@@ -247,6 +247,8 @@ pcmk_fence_history(xmlNodePtr *xml, stonith_t *st, char *target, unsigned int ti
return rc;
}
+ stonith__register_messages(out);
+
out->quiet = quiet;
rc = pcmk__fence_history(out, st, target, timeout, verbose, broadcast, cleanup);
@@ -287,6 +289,8 @@ pcmk_fence_installed(xmlNodePtr *xml, stonith_t *st, unsigned int timeout) {
return rc;
}
+ stonith__register_messages(out);
+
rc = pcmk__fence_installed(out, st, timeout);
pcmk__out_epilogue(out, xml, rc);
return rc;
@@ -321,6 +325,8 @@ pcmk_fence_last(xmlNodePtr *xml, const char *target, bool as_nodeid) {
return rc;
}
+ stonith__register_messages(out);
+
rc = pcmk__fence_last(out, target, as_nodeid);
pcmk__out_epilogue(out, xml, rc);
return rc;
@@ -364,6 +370,8 @@ pcmk_fence_list_targets(xmlNodePtr *xml, stonith_t *st, const char *device_id,
return rc;
}
+ stonith__register_messages(out);
+
rc = pcmk__fence_list_targets(out, st, device_id, timeout);
pcmk__out_epilogue(out, xml, rc);
return rc;
@@ -398,6 +406,8 @@ pcmk_fence_metadata(xmlNodePtr *xml, stonith_t *st, char *agent,
return rc;
}
+ stonith__register_messages(out);
+
rc = pcmk__fence_metadata(out, st, agent, timeout);
pcmk__out_epilogue(out, xml, rc);
return rc;
@@ -442,6 +452,8 @@ pcmk_fence_registered(xmlNodePtr *xml, stonith_t *st, char *target,
return rc;
}
+ stonith__register_messages(out);
+
rc = pcmk__fence_registered(out, st, target, timeout);
pcmk__out_epilogue(out, xml, rc);
return rc;
@@ -501,6 +513,8 @@ pcmk_fence_validate(xmlNodePtr *xml, stonith_t *st, const char *agent,
return rc;
}
+ stonith__register_messages(out);
+
rc = pcmk__fence_validate(out, st, agent, id, params, timeout);
pcmk__out_epilogue(out, xml, rc);
return rc;
diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 74a7c59..a637031 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -34,7 +34,6 @@ pcmk__out_prologue(pcmk__output_t **out, xmlNodePtr *xml) {
return rc;
}
- stonith__register_messages(*out);
return rc;
}
--
1.8.3.1
From 27677a6d03ba42aeb0d6a971df9d9b8861232903 Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 24 Nov 2020 16:19:59 +0100
Subject: [PATCH 2/2] API: libpacemaker: add public API functions for cluster
queries
---
include/pacemaker.h | 45 +++++++++++++++++++++-
lib/pacemaker/pcmk_cluster_queries.c | 75 ++++++++++++++++++++++++++++++++++++
2 files changed, 118 insertions(+), 2 deletions(-)
diff --git a/include/pacemaker.h b/include/pacemaker.h
index a1e76d0..b2a73cd 100644
--- a/include/pacemaker.h
+++ b/include/pacemaker.h
@@ -14,8 +14,6 @@
extern "C" {
#endif
-#ifdef BUILD_PUBLIC_LIBPACEMAKER
-
/**
* \file
* \brief High Level API
@@ -26,6 +24,49 @@ extern "C" {
# include <libxml/tree.h>
/*!
+ * \brief Get controller status
+ *
+ * \param[in,out] xml The destination for the result, as an XML tree.
+ * \param[in] dest_node Destination node for request
+ * \param[in] message_timeout_ms Message timeout
+ *
+ * \return Standard Pacemaker return code
+ */
+int pcmk_controller_status(xmlNodePtr *xml, char *dest_node, unsigned int message_timeout_ms);
+
+/*!
+ * \brief Get designated controller
+ *
+ * \param[in,out] xml The destination for the result, as an XML tree.
+ * \param[in] message_timeout_ms Message timeout
+ *
+ * \return Standard Pacemaker return code
+ */
+int pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms);
+
+/*!
+ * \brief Get pacemakerd status
+ *
+ * \param[in,out] xml The destination for the result, as an XML tree.
+ * \param[in] ipc_name IPC name for request
+ * \param[in] message_timeout_ms Message timeout
+ *
+ * \return Standard Pacemaker return code
+ */
+int pcmk_pacemakerd_status(xmlNodePtr *xml, char *ipc_name, unsigned int message_timeout_ms);
+
+#ifdef BUILD_PUBLIC_LIBPACEMAKER
+
+/*!
+ * \brief Get nodes list
+ *
+ * \param[in,out] xml The destination for the result, as an XML tree.
+ *
+ * \return Standard Pacemaker return code
+ */
+int pcmk_list_nodes(xmlNodePtr *xml);
+
+/*!
* \brief Perform a STONITH action.
*
* \param[in] st A connection to the STONITH API.
diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c
index 8d729eb..c705b7f 100644
--- a/lib/pacemaker/pcmk_cluster_queries.c
+++ b/lib/pacemaker/pcmk_cluster_queries.c
@@ -1,6 +1,7 @@
#include <glib.h> // gboolean, GMainLoop, etc.
#include <libxml/tree.h> // xmlNode
+#include <pacemaker.h>
#include <pacemaker-internal.h>
#include <crm/crm.h>
@@ -282,6 +283,24 @@ pcmk__controller_status(pcmk__output_t *out, char *dest_node, guint message_time
}
int
+pcmk_controller_status(xmlNodePtr *xml, char *dest_node, unsigned int message_timeout_ms)
+{
+ pcmk__output_t *out = NULL;
+ int rc = pcmk_rc_ok;
+
+ rc = pcmk__out_prologue(&out, xml);
+ if (rc != pcmk_rc_ok) {
+ return rc;
+ }
+
+ pcmk__register_lib_messages(out);
+
+ rc = pcmk__controller_status(out, dest_node, (guint) message_timeout_ms);
+ pcmk__out_epilogue(out, xml, rc);
+ return rc;
+}
+
+int
pcmk__designated_controller(pcmk__output_t *out, guint message_timeout_ms)
{
data_t data = {
@@ -309,6 +328,24 @@ pcmk__designated_controller(pcmk__output_t *out, guint message_timeout_ms)
}
int
+pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms)
+{
+ pcmk__output_t *out = NULL;
+ int rc = pcmk_rc_ok;
+
+ rc = pcmk__out_prologue(&out, xml);
+ if (rc != pcmk_rc_ok) {
+ return rc;
+ }
+
+ pcmk__register_lib_messages(out);
+
+ rc = pcmk__designated_controller(out, (guint) message_timeout_ms);
+ pcmk__out_epilogue(out, xml, rc);
+ return rc;
+}
+
+int
pcmk__pacemakerd_status(pcmk__output_t *out, char *ipc_name, guint message_timeout_ms)
{
data_t data = {
@@ -335,6 +372,24 @@ pcmk__pacemakerd_status(pcmk__output_t *out, char *ipc_name, guint message_timeo
return data.rc;
}
+int
+pcmk_pacemakerd_status(xmlNodePtr *xml, char *ipc_name, unsigned int message_timeout_ms)
+{
+ pcmk__output_t *out = NULL;
+ int rc = pcmk_rc_ok;
+
+ rc = pcmk__out_prologue(&out, xml);
+ if (rc != pcmk_rc_ok) {
+ return rc;
+ }
+
+ pcmk__register_lib_messages(out);
+
+ rc = pcmk__pacemakerd_status(out, ipc_name, (guint) message_timeout_ms);
+ pcmk__out_epilogue(out, xml, rc);
+ return rc;
+}
+
// \return Standard Pacemaker return code
int
pcmk__list_nodes(pcmk__output_t *out, gboolean BASH_EXPORT)
@@ -361,6 +416,26 @@ pcmk__list_nodes(pcmk__output_t *out, gboolean BASH_EXPORT)
return pcmk_legacy2rc(rc);
}
+#ifdef BUILD_PUBLIC_LIBPACEMAKER
+int
+pcmk_list_nodes(xmlNodePtr *xml)
+{
+ pcmk__output_t *out = NULL;
+ int rc = pcmk_rc_ok;
+
+ rc = pcmk__out_prologue(&out, xml);
+ if (rc != pcmk_rc_ok) {
+ return rc;
+ }
+
+ pcmk__register_lib_messages(out);
+
+ rc = pcmk__list_nodes(out, FALSE);
+ pcmk__out_epilogue(out, xml, rc);
+ return rc;
+}
+#endif
+
// remove when parameters removed from tools/crmadmin.c
int
pcmk__shutdown_controller(pcmk__output_t *out, char *dest_node)
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
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

View File

@ -0,0 +1,114 @@
From 12b30c920dd15287a7b295475ce1cc4a6cb1f43f Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 8 Dec 2020 15:48:38 -0500
Subject: [PATCH] Fix: scheduler: Don't output a resource header with no list.
If there's no resources to print, don't output just the header with
nothing under it. This potentially comes up if there are only inactive
resources, but inactive_resources is FALSE.
---
lib/pengine/pe_output.c | 48 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 36 insertions(+), 12 deletions(-)
diff --git a/lib/pengine/pe_output.c b/lib/pengine/pe_output.c
index 5562eb6..f1a6b43 100644
--- a/lib/pengine/pe_output.c
+++ b/lib/pengine/pe_output.c
@@ -1761,6 +1761,21 @@ resource_history_xml(pcmk__output_t *out, va_list args) {
return pcmk_rc_ok;
}
+static void
+print_resource_header(pcmk__output_t *out, gboolean group_by_node,
+ gboolean inactive_resources)
+{
+ if (group_by_node) {
+ /* Active resources have already been printed by node */
+ out->begin_list(out, NULL, NULL, "Inactive Resources");
+ } else if (inactive_resources) {
+ out->begin_list(out, NULL, NULL, "Full List of Resources");
+ } else {
+ out->begin_list(out, NULL, NULL, "Active Resources");
+ }
+}
+
+
PCMK__OUTPUT_ARGS("resource-list", "pe_working_set_t *", "unsigned int", "gboolean",
"gboolean", "gboolean", "gboolean", "GList *", "GList *", "gboolean")
static int
@@ -1778,6 +1793,7 @@ resource_list(pcmk__output_t *out, va_list args)
GList *rsc_iter;
int rc = pcmk_rc_no_output;
+ bool printed_header = false;
/* If we already showed active resources by node, and
* we're not showing inactive resources, we have nothing to do
@@ -1786,22 +1802,15 @@ resource_list(pcmk__output_t *out, va_list args)
return rc;
}
- PCMK__OUTPUT_SPACER_IF(out, print_spacer);
-
- if (group_by_node) {
- /* Active resources have already been printed by node */
- out->begin_list(out, NULL, NULL, "Inactive Resources");
- } else if (inactive_resources) {
- out->begin_list(out, NULL, NULL, "Full List of Resources");
- } else {
- out->begin_list(out, NULL, NULL, "Active Resources");
- }
-
/* If we haven't already printed resources grouped by node,
* and brief output was requested, print resource summary */
if (brief_output && !group_by_node) {
GList *rscs = pe__filter_rsc_list(data_set->resources, only_rsc);
+ PCMK__OUTPUT_SPACER_IF(out, print_spacer);
+ print_resource_header(out, group_by_node, inactive_resources);
+ printed_header = true;
+
pe__rscs_brief_output(out, rscs, print_opts, inactive_resources);
g_list_free(rscs);
}
@@ -1839,6 +1848,12 @@ resource_list(pcmk__output_t *out, va_list args)
continue;
}
+ if (!printed_header) {
+ PCMK__OUTPUT_SPACER_IF(out, print_spacer);
+ print_resource_header(out, group_by_node, inactive_resources);
+ printed_header = true;
+ }
+
/* Print this resource */
x = out->message(out, crm_map_element_name(rsc->xml), print_opts, rsc,
only_node, only_rsc);
@@ -1848,6 +1863,12 @@ resource_list(pcmk__output_t *out, va_list args)
}
if (print_summary && rc != pcmk_rc_ok) {
+ if (!printed_header) {
+ PCMK__OUTPUT_SPACER_IF(out, print_spacer);
+ print_resource_header(out, group_by_node, inactive_resources);
+ printed_header = true;
+ }
+
if (group_by_node) {
out->list_item(out, NULL, "No inactive resources");
} else if (inactive_resources) {
@@ -1857,7 +1878,10 @@ resource_list(pcmk__output_t *out, va_list args)
}
}
- out->end_list(out);
+ if (printed_header) {
+ out->end_list(out);
+ }
+
return rc;
}
--
1.8.3.1

View File

@ -1,513 +0,0 @@
From 3aa33bcc9c70d197b5ed0760b12d65dfab4d4da5 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 9 Oct 2020 09:56:03 -0500
Subject: [PATCH 1/7] Log: executor: show CRM_OP_REGISTER rc in debug message
Previously, process_lrmd_signon() would add the rc to the client reply
but not pass it back to process_lrmd_message(), which would always log "OK" in
its debug message, even if the sign-on was rejected.
---
daemons/execd/execd_commands.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
index 4d0e457..8487dd4 100644
--- a/daemons/execd/execd_commands.c
+++ b/daemons/execd/execd_commands.c
@@ -1494,10 +1494,10 @@ free_rsc(gpointer data)
free(rsc);
}
-static xmlNode *
-process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id)
+static int
+process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id,
+ xmlNode **reply)
{
- xmlNode *reply = NULL;
int rc = pcmk_ok;
const char *is_ipc_provider = crm_element_value(request, F_LRMD_IS_IPC_PROVIDER);
const char *protocol_version = crm_element_value(request, F_LRMD_PROTOCOL_VERSION);
@@ -1508,18 +1508,19 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id)
rc = -EPROTO;
}
- reply = create_lrmd_reply(__FUNCTION__, rc, call_id);
- crm_xml_add(reply, F_LRMD_OPERATION, CRM_OP_REGISTER);
- crm_xml_add(reply, F_LRMD_CLIENTID, client->id);
- crm_xml_add(reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION);
-
if (crm_is_true(is_ipc_provider)) {
// This is a remote connection from a cluster node's controller
#ifdef SUPPORT_REMOTE
ipc_proxy_add_provider(client);
#endif
}
- return reply;
+
+ *reply = create_lrmd_reply(__func__, rc, call_id);
+ crm_xml_add(*reply, F_LRMD_OPERATION, CRM_OP_REGISTER);
+ crm_xml_add(*reply, F_LRMD_CLIENTID, client->id);
+ crm_xml_add(*reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION);
+
+ return rc;
}
static int
@@ -1832,7 +1833,7 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
#endif
do_reply = 1;
} else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) {
- reply = process_lrmd_signon(client, request, call_id);
+ rc = process_lrmd_signon(client, request, call_id, &reply);
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) {
rc = process_lrmd_rsc_register(client, id, request);
--
1.8.3.1
From d0002343faa4595e42b790119b7f3037db1130c4 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 9 Oct 2020 15:16:39 -0500
Subject: [PATCH 2/7] Low: executor: mark controller connections to
pacemaker-remoted as privileged
Previously, pcmk__client_privileged was only set when local clients connected
(as root or hacluster). Now, set it when pacemaker-remoted successfully
completes the TLS handshake with a remote client (i.e., the controller on a
cluster node).
This has no effect as of this commit but will with later commits.
---
daemons/execd/remoted_tls.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/daemons/execd/remoted_tls.c b/daemons/execd/remoted_tls.c
index 1a1f8b2..c835549 100644
--- a/daemons/execd/remoted_tls.c
+++ b/daemons/execd/remoted_tls.c
@@ -72,6 +72,11 @@ remoted__read_handshake_data(pcmk__client_t *client)
client->remote->tls_handshake_complete = TRUE;
crm_notice("Remote client connection accepted");
+ /* Only a client with access to the TLS key can connect, so we can treat
+ * it as privileged.
+ */
+ set_bit(client->flags, pcmk__client_privileged);
+
// Alert other clients of the new connection
notify_of_new_client(client);
return 0;
--
1.8.3.1
From 3db100d775aee214fff8f54eae0076a5fcc41c56 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 15 Oct 2020 15:33:13 -0500
Subject: [PATCH 3/7] Low: executor: return appropriate error code when no
remote support
---
daemons/execd/execd_commands.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
index 8487dd4..41c8169 100644
--- a/daemons/execd/execd_commands.c
+++ b/daemons/execd/execd_commands.c
@@ -1509,9 +1509,11 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id,
}
if (crm_is_true(is_ipc_provider)) {
- // This is a remote connection from a cluster node's controller
#ifdef SUPPORT_REMOTE
+ // This is a remote connection from a cluster node's controller
ipc_proxy_add_provider(client);
+#else
+ rc = -EPROTONOSUPPORT;
#endif
}
@@ -1830,6 +1832,8 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) {
#ifdef SUPPORT_REMOTE
ipc_proxy_forward_client(client, request);
+#else
+ rc = -EPROTONOSUPPORT;
#endif
do_reply = 1;
} else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) {
--
1.8.3.1
From f273f1c16f21ff96983797ed5ceb2978dafe545a Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 15 Oct 2020 15:33:57 -0500
Subject: [PATCH 4/7] High: executor: restrict certain IPC requests to
Pacemaker daemons
The executor IPC API allows clients to register resources, request agent
execution, and so forth.
If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs and
execute any code as root. (If ACLs are not enabled, users in the haclient group
have full access to the CIB, which already gives them that ability, so there is
no additional exposure in that case.)
When ACLs are supported, this commit effectively disables the executor IPC API
for clients that aren't connecting as root or hacluster. Such clients can only
register and poke now.
---
daemons/execd/execd_commands.c | 91 +++++++++++++++++++++++++++++++++---------
1 file changed, 73 insertions(+), 18 deletions(-)
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
index 41c8169..207eb6a 100644
--- a/daemons/execd/execd_commands.c
+++ b/daemons/execd/execd_commands.c
@@ -1510,8 +1510,12 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id,
if (crm_is_true(is_ipc_provider)) {
#ifdef SUPPORT_REMOTE
- // This is a remote connection from a cluster node's controller
- ipc_proxy_add_provider(client);
+ if ((client->remote != NULL) && client->remote->tls_handshake_complete) {
+ // This is a remote connection from a cluster node's controller
+ ipc_proxy_add_provider(client);
+ } else {
+ rc = -EACCES;
+ }
#else
rc = -EPROTONOSUPPORT;
#endif
@@ -1826,12 +1830,26 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
int do_notify = 0;
xmlNode *reply = NULL;
+ bool allowed = true;
+
+#if ENABLE_ACL
+ /* Certain IPC commands may be done only by privileged users (i.e. root or
+ * hacluster) when ACLs are enabled, because they would otherwise provide a
+ * means of bypassing ACLs.
+ */
+ allowed = is_set(client->flags, pcmk__client_privileged);
+#endif
+
crm_trace("Processing %s operation from %s", op, client->id);
crm_element_value_int(request, F_LRMD_CALLID, &call_id);
if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) {
#ifdef SUPPORT_REMOTE
- ipc_proxy_forward_client(client, request);
+ if (allowed) {
+ ipc_proxy_forward_client(client, request);
+ } else {
+ rc = -EACCES;
+ }
#else
rc = -EPROTONOSUPPORT;
#endif
@@ -1840,38 +1858,70 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
rc = process_lrmd_signon(client, request, call_id, &reply);
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) {
- rc = process_lrmd_rsc_register(client, id, request);
- do_notify = 1;
+ if (allowed) {
+ rc = process_lrmd_rsc_register(client, id, request);
+ do_notify = 1;
+ } else {
+ rc = -EACCES;
+ }
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) {
- reply = process_lrmd_get_rsc_info(request, call_id);
+ if (allowed) {
+ reply = process_lrmd_get_rsc_info(request, call_id);
+ } else {
+ rc = -EACCES;
+ }
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) {
- rc = process_lrmd_rsc_unregister(client, id, request);
- /* don't notify anyone about failed un-registers */
- if (rc == pcmk_ok || rc == -EINPROGRESS) {
- do_notify = 1;
+ if (allowed) {
+ rc = process_lrmd_rsc_unregister(client, id, request);
+ /* don't notify anyone about failed un-registers */
+ if (rc == pcmk_ok || rc == -EINPROGRESS) {
+ do_notify = 1;
+ }
+ } else {
+ rc = -EACCES;
}
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) {
- rc = process_lrmd_rsc_exec(client, id, request);
+ if (allowed) {
+ rc = process_lrmd_rsc_exec(client, id, request);
+ } else {
+ rc = -EACCES;
+ }
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) {
- rc = process_lrmd_rsc_cancel(client, id, request);
+ if (allowed) {
+ rc = process_lrmd_rsc_cancel(client, id, request);
+ } else {
+ rc = -EACCES;
+ }
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_POKE, TRUE)) {
do_notify = 1;
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_CHECK, TRUE)) {
- xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA);
- const char *timeout = crm_element_value(data, F_LRMD_WATCHDOG);
- CRM_LOG_ASSERT(data != NULL);
- pcmk__valid_sbd_timeout(timeout);
+ if (allowed) {
+ xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA);
+
+ CRM_LOG_ASSERT(data != NULL);
+ pcmk__valid_sbd_timeout(crm_element_value(data, F_LRMD_WATCHDOG));
+ } else {
+ rc = -EACCES;
+ }
} else if (crm_str_eq(op, LRMD_OP_ALERT_EXEC, TRUE)) {
- rc = process_lrmd_alert_exec(client, id, request);
+ if (allowed) {
+ rc = process_lrmd_alert_exec(client, id, request);
+ } else {
+ rc = -EACCES;
+ }
do_reply = 1;
} else if (crm_str_eq(op, LRMD_OP_GET_RECURRING, TRUE)) {
- reply = process_lrmd_get_recurring(request, call_id);
+ if (allowed) {
+ reply = process_lrmd_get_recurring(request, call_id);
+ } else {
+ rc = -EACCES;
+ }
do_reply = 1;
} else {
rc = -EOPNOTSUPP;
@@ -1879,6 +1929,11 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
crm_err("Unknown IPC request '%s' from %s", op, client->name);
}
+ if (rc == -EACCES) {
+ crm_warn("Rejecting IPC request '%s' from unprivileged client %s",
+ op, pcmk__client_name(client));
+ }
+
crm_debug("Processed %s operation from %s: rc=%d, reply=%d, notify=%d",
op, client->id, rc, do_reply, do_notify);
--
1.8.3.1
From f13759f6971402dac3bea1aac45214a84d838728 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 9 Oct 2020 11:16:43 -0500
Subject: [PATCH 5/7] Low: pacemakerd: check client for NULL before using it
... to guard against bugs in client tracking
---
daemons/pacemakerd/pacemakerd.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c
index 5ed4626..573ea5a 100644
--- a/daemons/pacemakerd/pacemakerd.c
+++ b/daemons/pacemakerd/pacemakerd.c
@@ -553,9 +553,12 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
uint32_t id = 0;
uint32_t flags = 0;
const char *task = NULL;
+ xmlNode *msg = NULL;
pcmk__client_t *c = pcmk__find_client(qbc);
- xmlNode *msg = pcmk__client_data2xml(c, data, &id, &flags);
+ CRM_CHECK(c != NULL, return 0);
+
+ msg = pcmk__client_data2xml(c, data, &id, &flags);
pcmk__ipc_send_ack(c, id, flags, "ack");
if (msg == NULL) {
return 0;
--
1.8.3.1
From 021081c1e28b254a0f68143fa55e517f0fcc4edb Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 9 Oct 2020 11:17:18 -0500
Subject: [PATCH 6/7] High: pacemakerd: ignore shutdown requests from
unprivileged users
The pacemakerd IPC API supports a shutdown request, along with a
command-line interface for using it (pacemakerd --shutdown).
Only the haclient group has access to the IPC. Without ACLs, that group can
already shut down Pacemaker via the CIB, so there's no security implication.
However, it might not be desired to allow ACL-restricted users to shut down
Pacemaker, so block users other than root or hacluster if ACLs are supported.
---
daemons/pacemakerd/pacemakerd.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c
index 573ea5a..2e69bd1 100644
--- a/daemons/pacemakerd/pacemakerd.c
+++ b/daemons/pacemakerd/pacemakerd.c
@@ -566,9 +566,26 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
task = crm_element_value(msg, F_CRM_TASK);
if (crm_str_eq(task, CRM_OP_QUIT, TRUE)) {
- crm_notice("Shutting down in response to IPC request %s from %s",
- crm_element_value(msg, F_CRM_REFERENCE), crm_element_value(msg, F_CRM_ORIGIN));
- pcmk_shutdown(15);
+ bool allowed = true;
+
+#if ENABLE_ACL
+ /* Only allow privileged users (i.e. root or hacluster)
+ * to shut down Pacemaker from the command line (or direct IPC).
+ *
+ * We only check when ACLs are enabled, because without them, any client
+ * with IPC access could shut down Pacemaker via the CIB anyway.
+ */
+ allowed = is_set(c->flags, pcmk__client_privileged);
+#endif
+ if (allowed) {
+ crm_notice("Shutting down in response to IPC request %s from %s",
+ crm_element_value(msg, F_CRM_REFERENCE),
+ crm_element_value(msg, F_CRM_ORIGIN));
+ pcmk_shutdown(15);
+ } else {
+ crm_warn("Ignoring shutdown request from unprivileged client %s",
+ pcmk__client_name(c));
+ }
} else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) {
crm_trace("Ignoring IPC request to purge node "
--
1.8.3.1
From 80eb5ddfd529be02214f38669f1b177535186fbc Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Fri, 9 Oct 2020 11:55:26 -0500
Subject: [PATCH 7/7] Fix: fencer: restrict certain IPC requests to privileged
users
The fencer IPC API allows clients to register fence devices.
If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs to
configure fencing. If the user is able to install executables to the standard
fencing agent locations, have arbitrary code executed as root (the standard
locations generally require root for write access, so that is unlikely to be an
issue).
If ACLs are not enabled, users in the haclient group have full access to the
CIB, which already gives them these capabilities, so there is no additional
exposure in that case.
This commit does not restrict unprivileged users from using other fencing API,
such as requesting actual fencing.
---
daemons/fenced/fenced_commands.c | 41 ++++++++++++++++++++++++++++++++++++----
1 file changed, 37 insertions(+), 4 deletions(-)
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
index 859e7b7..a8c90a6 100644
--- a/daemons/fenced/fenced_commands.c
+++ b/daemons/fenced/fenced_commands.c
@@ -2531,6 +2531,18 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags,
const char *op = crm_element_value(request, F_STONITH_OPERATION);
const char *client_id = crm_element_value(request, F_STONITH_CLIENTID);
+ bool allowed = true;
+
+#if ENABLE_ACL
+ /* IPC commands related to fencing configuration may be done only by
+ * privileged users (i.e. root or hacluster) when ACLs are supported,
+ * because all other users should go through the CIB to have ACLs applied.
+ */
+ if (client != NULL) {
+ allowed = is_set(client->flags, pcmk__client_privileged);
+ }
+#endif
+
crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options);
if (is_set(call_options, st_opt_sync_call)) {
@@ -2687,27 +2699,43 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags,
} else if (crm_str_eq(op, STONITH_OP_DEVICE_ADD, TRUE)) {
const char *device_id = NULL;
- rc = stonith_device_register(request, &device_id, FALSE);
+ if (allowed) {
+ rc = stonith_device_register(request, &device_id, FALSE);
+ } else {
+ rc = -EACCES;
+ }
do_stonith_notify_device(call_options, op, rc, device_id);
} else if (crm_str_eq(op, STONITH_OP_DEVICE_DEL, TRUE)) {
xmlNode *dev = get_xpath_object("//" F_STONITH_DEVICE, request, LOG_ERR);
const char *device_id = crm_element_value(dev, XML_ATTR_ID);
- rc = stonith_device_remove(device_id, FALSE);
+ if (allowed) {
+ rc = stonith_device_remove(device_id, FALSE);
+ } else {
+ rc = -EACCES;
+ }
do_stonith_notify_device(call_options, op, rc, device_id);
} else if (crm_str_eq(op, STONITH_OP_LEVEL_ADD, TRUE)) {
char *device_id = NULL;
- rc = stonith_level_register(request, &device_id);
+ if (allowed) {
+ rc = stonith_level_register(request, &device_id);
+ } else {
+ rc = -EACCES;
+ }
do_stonith_notify_level(call_options, op, rc, device_id);
free(device_id);
} else if (crm_str_eq(op, STONITH_OP_LEVEL_DEL, TRUE)) {
char *device_id = NULL;
- rc = stonith_level_remove(request, &device_id);
+ if (allowed) {
+ rc = stonith_level_remove(request, &device_id);
+ } else {
+ rc = -EACCES;
+ }
do_stonith_notify_level(call_options, op, rc, device_id);
} else if(safe_str_eq(op, CRM_OP_RM_NODE_CACHE)) {
@@ -2727,6 +2755,11 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags,
done:
+ if (rc == -EACCES) {
+ crm_warn("Rejecting IPC request '%s' from unprivileged client %s",
+ crm_str(op), pcmk__client_name(client));
+ }
+
/* Always reply unless the request is in process still.
* If in progress, a reply will happen async after the request
* processing is finished */
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
From a66f63e1001c2c93e286978c0383b4256abfce6b Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 4 Jan 2021 16:46:52 -0500
Subject: [PATCH] Test: cts: Distribute the new constraints.xml file.
---
cts/Makefile.am | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cts/Makefile.am b/cts/Makefile.am
index 6abb42f..5666a9f 100644
--- a/cts/Makefile.am
+++ b/cts/Makefile.am
@@ -60,7 +60,8 @@ cts_SCRIPTS = CTSlab.py \
pacemaker-cts-dummyd
clidir = $(testdir)/cli
-dist_cli_DATA = cli/crm_diff_new.xml \
+dist_cli_DATA = cli/constraints.xml \
+ cli/crm_diff_new.xml \
cli/crm_diff_old.xml \
cli/crm_mon.xml \
cli/crm_mon-partial.xml \
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +0,0 @@
From bd4f396f267d8ef8f9c9bcbf286a77dc78d4e1b0 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 2 Mar 2021 10:26:13 -0500
Subject: [PATCH 1/2] Med: Generate xml/crm_mon.rng from the contents of
xml/crm_mon*.
This prevents the version reference in it from getting out of sync.
See: rhbz#1931332
---
xml/Makefile.am | 28 +++++++++++++++++++++++-----
xml/crm_mon.rng | 16 ----------------
3 files changed, 24 insertions(+), 21 deletions(-)
delete mode 100644 xml/crm_mon.rng
diff --git a/xml/Makefile.am b/xml/Makefile.am
index cb6cfa0..c52b968 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -76,22 +76,24 @@ CIB_abs_xsl = $(abs_srcdir)/upgrade-1.3.xsl \
$(abs_srcdir)/upgrade-2.10.xsl \
$(wildcard $(abs_srcdir)/upgrade-*enter.xsl) \
$(wildcard $(abs_srcdir)/upgrade-*leave.xsl)
-MON_abs_files = $(abs_srcdir)/crm_mon.rng
+MON_abs_files = $(abs_srcdir)/crm_mon.rng
API_files = $(foreach base,$(API_base),$(wildcard $(srcdir)/api/$(base)*.rng))
CIB_files = $(foreach base,$(CIB_base),$(wildcard $(srcdir)/$(base).rng $(srcdir)/$(base)-*.rng))
CIB_xsl = $(srcdir)/upgrade-1.3.xsl \
$(srcdir)/upgrade-2.10.xsl \
$(wildcard $(srcdir)/upgrade-*enter.xsl) \
$(wildcard $(srcdir)/upgrade-*leave.xsl)
-MON_files = $(srcdir)/crm_mon.rng
+MON_files = $(srcdir)/crm_mon.rng
# Sorted lists of all numeric schema versions
API_numeric_versions = $(call numeric_versions,${API_files})
CIB_numeric_versions = $(call numeric_versions,${CIB_files})
+MON_numeric_versions = $(call numeric_versions,$(wildcard $(srcdir)/api/crm_mon*.rng))
# The highest numeric schema version
API_max ?= $(lastword $(API_numeric_versions))
CIB_max ?= $(lastword $(CIB_numeric_versions))
+MON_max ?= $(lastword $(MON_numeric_versions))
# Sorted lists of all schema versions (including "next")
API_versions = next $(API_numeric_versions)
@@ -100,11 +102,12 @@ CIB_versions = next $(CIB_numeric_versions)
# Build tree locations of static schema files and transforms (for VPATH builds)
API_build_copies = $(foreach f,$(API_abs_files),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
CIB_build_copies = $(foreach f,$(CIB_abs_files) $(CIB_abs_xsl),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
-MON_build_copies = $(foreach f,$(MON_abs_files),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
+MON_build_copies = $(foreach f,$(MON_abs_files),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
# Dynamically generated schema files
API_generated = api/api-result.rng $(foreach base,$(API_versions),api/api-result-$(base).rng)
CIB_generated = pacemaker.rng $(foreach base,$(CIB_versions),pacemaker-$(base).rng) versions.rng
+MON_generated = crm_mon.rng
CIB_version_pairs = $(call version_pairs,${CIB_numeric_versions})
CIB_version_pairs_cnt = $(words ${CIB_version_pairs})
@@ -112,10 +115,10 @@ CIB_version_pairs_last = $(call version_pairs_last,${CIB_version_pairs_cnt},${C
dist_API_DATA = $(API_files)
dist_CIB_DATA = $(CIB_files) $(CIB_xsl)
-dist_MON_DATA = $(MON_files)
nodist_API_DATA = $(API_generated)
nodist_CIB_DATA = $(CIB_generated)
+nodist_MON_DATA = $(MON_generated)
EXTRA_DIST = Readme.md \
best-match.sh \
@@ -162,6 +165,21 @@ api/api-result-%.rng: $(API_build_copies) best-match.sh Makefile.am
$(AM_V_at)echo ' </start>' >> $@
$(AM_V_SCHEMA)echo '</grammar>' >> $@
+crm_mon.rng: api/crm_mon-$(MON_max).rng
+ $(AM_V_at)echo '<?xml version="1.0" encoding="UTF-8"?>' > $@
+ $(AM_V_at)echo '<grammar xmlns="http://relaxng.org/ns/structure/1.0"' >> $@
+ $(AM_V_at)echo ' datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">' >> $@
+ $(AM_V_at)echo ' <start>' >> $@
+ $(AM_V_at)echo ' <ref name="element-crm_mon-old"/>' >> $@
+ $(AM_V_at)echo ' </start>' >> $@
+ $(AM_V_at)echo ' <define name="element-crm_mon-old">' >> $@
+ $(AM_V_at)echo ' <element name="crm_mon">' >> $@
+ $(AM_V_at)echo ' <attribute name="version"> <text/> </attribute>' >> $@
+ $(AM_V_at)echo ' <externalRef href="$(<)" />' >> $@
+ $(AM_V_at)echo ' </element>' >> $@
+ $(AM_V_at)echo ' </define>' >> $@
+ $(AM_V_SCHEMA)echo '</grammar>' >> $@
+
# Dynamically generated top-level CIB schema
pacemaker.rng: pacemaker-$(CIB_max).rng
$(AM_V_SCHEMA)cp $(top_builddir)/xml/$< $@
@@ -256,7 +274,7 @@ fulldiff: best-match.sh
@echo "# Comparing all changes across all the subsequent increments"
$(call version_diff,${CIB_version_pairs})
-CLEANFILES = $(API_generated) $(CIB_generated)
+CLEANFILES = $(API_generated) $(CIB_generated) $(MON_generated)
clean-local:
if [ "x$(srcdir)" != "x$(builddir)" ]; then \
diff --git a/xml/crm_mon.rng b/xml/crm_mon.rng
deleted file mode 100644
index be87fba..0000000
--- a/xml/crm_mon.rng
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0"
- datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
-
- <start>
- <ref name="element-crm_mon-old"/>
- </start>
-
- <define name="element-crm_mon-old">
- <element name="crm_mon">
- <attribute name="version"> <text/> </attribute>
- <externalRef href="api/crm_mon-2.2.rng" />
- </element>
- </define>
-
-</grammar>
--
1.8.3.1
From 9b6ee6eb5aa1008beebae9d9f6c3889c81c3bbb6 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 2 Mar 2021 10:58:15 -0500
Subject: [PATCH 2/2] Med: Change the schema type of 'expected' and 'call' to
integer.
Regression in 2.0.3.
See: rhbz#1931332
---
xml/api/crm_mon-2.2.rng | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/xml/api/crm_mon-2.2.rng b/xml/api/crm_mon-2.2.rng
index 88973a4..8e6792b 100644
--- a/xml/api/crm_mon-2.2.rng
+++ b/xml/api/crm_mon-2.2.rng
@@ -198,7 +198,7 @@
<attribute name="name"> <text /> </attribute>
<attribute name="value"> <text /> </attribute>
<optional>
- <attribute name="expected"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="expected"> <data type="integer" /> </attribute>
</optional>
</element>
</zeroOrMore>
@@ -269,7 +269,7 @@
<attribute name="exitstatus"> <text /> </attribute>
<attribute name="exitreason"> <text /> </attribute>
<attribute name="exitcode"> <data type="nonNegativeInteger" /> </attribute>
- <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="call"> <data type="integer" /> </attribute>
<attribute name="status"> <text /> </attribute>
<optional>
<group>
--
1.8.3.1

View File

@ -0,0 +1,47 @@
From c3e2edb78e6d0b6ffc8acbe8fc7caef058b35d76 Mon Sep 17 00:00:00 2001
From: Reid Wahl <nrwahl@protonmail.com>
Date: Tue, 22 Dec 2020 22:28:46 -0800
Subject: [PATCH] Fix: liblrmd: Limit node name addition to proxied attrd
update commands
remote_proxy_cb() currently adds the remote node's name as
PCMK__XA_ATTR_NODE_NAME if that attribute is not explicitly set. This is
necessary for attrd update commands. For those, lack of an explicit node
name means to use the local node. Since requests are proxied to full
nodes, the node hosting the remote resource would be incorrectly treated
as the "local node", causing the attribute to be updated for the wrong
node.
However, for other commands, this is not the case. Lack of an explicit
node name can mean "all nodes" (as for CLEAR_FAILURE and QUERY), or a
node name may be ignored (as for REFRESH). In these cases (the
non-update commands), we don't want to add a node name automatically if
it's not explicitly set.
Resolves: RHBZ#1907726
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
---
lib/lrmd/proxy_common.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/lrmd/proxy_common.c b/lib/lrmd/proxy_common.c
index b8d889e..0f1e76a 100644
--- a/lib/lrmd/proxy_common.c
+++ b/lib/lrmd/proxy_common.c
@@ -259,7 +259,11 @@ remote_proxy_cb(lrmd_t *lrmd, const char *node_name, xmlNode *msg)
if (pcmk__str_eq(type, T_ATTRD, pcmk__str_casei)
&& crm_element_value(request,
- PCMK__XA_ATTR_NODE_NAME) == NULL) {
+ PCMK__XA_ATTR_NODE_NAME) == NULL
+ && pcmk__str_any_of(crm_element_value(request, PCMK__XA_TASK),
+ PCMK__ATTRD_CMD_UPDATE,
+ PCMK__ATTRD_CMD_UPDATE_BOTH,
+ PCMK__ATTRD_CMD_UPDATE_DELAY, NULL)) {
crm_xml_add(request, PCMK__XA_ATTR_NODE_NAME, proxy->node_name);
}
--
1.8.3.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
From b1241e5026a4fd9a8674ad4b867c7efa3d8ef466 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 12 Jan 2021 09:03:03 -0600
Subject: [PATCH] Feature: tools: bump feature set for crm_resource --digests
... so script and tools can check for support
---
include/crm/crm.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/crm/crm.h b/include/crm/crm.h
index b07152c..4bbf46a 100644
--- a/include/crm/crm.h
+++ b/include/crm/crm.h
@@ -51,7 +51,7 @@ extern "C" {
* >=3.0.13: Fail counts include operation name and interval
* >=3.2.0: DC supports PCMK_LRM_OP_INVALID and PCMK_LRM_OP_NOT_CONNECTED
*/
-# define CRM_FEATURE_SET "3.6.3"
+# define CRM_FEATURE_SET "3.6.4"
# define EOS '\0'
# define DIMOF(a) ((int) (sizeof(a)/sizeof(a[0])) )
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,505 @@
From cf0eebd913855f9ceda2864cbcd9cbd647fca055 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Wed, 13 Jan 2021 12:10:07 -0600
Subject: [PATCH] Build: xml: rename crm_resource API file
5aadeaf added an API schema 2.5 for crm_resource, but API schema 2.5 was
released with 2.0.5, so rename it to 2.6 to indicate it is a later change.
---
xml/api/crm_resource-2.5.rng | 238 -------------------------------------------
xml/api/crm_resource-2.6.rng | 238 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 238 insertions(+), 238 deletions(-)
delete mode 100644 xml/api/crm_resource-2.5.rng
create mode 100644 xml/api/crm_resource-2.6.rng
diff --git a/xml/api/crm_resource-2.5.rng b/xml/api/crm_resource-2.5.rng
deleted file mode 100644
index b49e24c..0000000
--- a/xml/api/crm_resource-2.5.rng
+++ /dev/null
@@ -1,238 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0"
- datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
-
- <start>
- <ref name="element-crm-resource"/>
- </start>
-
- <define name="element-crm-resource">
- <choice>
- <ref name="agents-list" />
- <ref name="alternatives-list" />
- <ref name="constraints-list" />
- <externalRef href="generic-list-2.4.rng"/>
- <element name="metadata"> <text/> </element>
- <ref name="locate-list" />
- <ref name="operations-list" />
- <ref name="providers-list" />
- <ref name="reasons-list" />
- <ref name="resource-check" />
- <ref name="resource-config" />
- <ref name="resources-list" />
- </choice>
- </define>
-
- <define name="agents-list">
- <element name="agents">
- <attribute name="standard"> <text/> </attribute>
- <optional>
- <attribute name="provider"> <text/> </attribute>
- </optional>
- <zeroOrMore>
- <element name="agent"> <text/> </element>
- </zeroOrMore>
- </element>
- </define>
-
- <define name="alternatives-list">
- <element name="providers">
- <attribute name="for"> <text/> </attribute>
- <zeroOrMore>
- <element name="provider"> <text/> </element>
- </zeroOrMore>
- </element>
- </define>
-
- <define name="constraints-list">
- <element name="constraints">
- <interleave>
- <zeroOrMore>
- <ref name="rsc-location" />
- </zeroOrMore>
- <zeroOrMore>
- <ref name="rsc-colocation" />
- </zeroOrMore>
- </interleave>
- </element>
- </define>
-
- <define name="locate-list">
- <element name="nodes">
- <attribute name="resource"> <text/> </attribute>
- <zeroOrMore>
- <element name="node">
- <optional>
- <attribute name="state"><value>promoted</value></attribute>
- </optional>
- <text/>
- </element>
- </zeroOrMore>
- </element>
- </define>
-
- <define name="rsc-location">
- <element name="rsc_location">
- <attribute name="node"> <text/> </attribute>
- <attribute name="rsc"> <text/> </attribute>
- <attribute name="id"> <text/> </attribute>
- <externalRef href="../score.rng"/>
- </element>
- </define>
-
- <define name="operations-list">
- <element name="operations">
- <oneOrMore>
- <ref name="element-operation-list" />
- </oneOrMore>
- </element>
- </define>
-
- <define name="providers-list">
- <element name="providers">
- <attribute name="standard"> <value>ocf</value> </attribute>
- <optional>
- <attribute name="agent"> <text/> </attribute>
- </optional>
- <zeroOrMore>
- <element name="provider"> <text/> </element>
- </zeroOrMore>
- </element>
- </define>
-
- <define name="reasons-list">
- <choice>
- <ref name="no-resource-or-uname"/>
- <ref name="resource-and-uname"/>
- <ref name="no-resource-but-uname"/>
- <ref name="resource-but-no-uname"/>
- </choice>
- </define>
-
- <define name="no-resource-or-uname">
- <element name="reason">
- <element name="resources">
- <zeroOrMore>
- <element name="resource">
- <attribute name="id"> <text/> </attribute>
- <attribute name="running"> <data type="boolean"/> </attribute>
- <ref name="resource-check"/>
- </element>
- </zeroOrMore>
- </element>
- </element>
- </define>
-
- <define name="resource-and-uname">
- <element name="reason">
- <attribute name="running_on"> <text/> </attribute>
- <ref name="resource-check"/>
- </element>
- </define>
-
- <define name="no-resource-but-uname">
- <element name="reason">
- <element name="resources">
- <zeroOrMore>
- <element name="resource">
- <attribute name="id"> <text/> </attribute>
- <attribute name="running"> <data type="boolean"/> </attribute>
- <attribute name="host"> <text/> </attribute>
- <ref name="resource-check"/>
- </element>
- </zeroOrMore>
- </element>
- </element>
- </define>
-
- <define name="resource-but-no-uname">
- <element name="reason">
- <attribute name="running"> <data type="boolean"/> </attribute>
- <ref name="resource-check"/>
- </element>
- </define>
-
- <define name="resource-config">
- <element name="resource_config">
- <externalRef href="resources-2.4.rng" />
- <element name="xml"> <text/> </element>
- </element>
- </define>
-
- <define name="resource-check">
- <element name="check">
- <attribute name="id"> <text/> </attribute>
- <optional>
- <choice>
- <attribute name="remain_stopped"><value>true</value></attribute>
- <attribute name="promotable"><value>false</value></attribute>
- </choice>
- </optional>
- <optional>
- <attribute name="unmanaged"><value>true</value></attribute>
- </optional>
- <optional>
- <attribute name="locked-to"> <text/> </attribute>
- </optional>
- </element>
- </define>
-
- <define name="resources-list">
- <element name="resources">
- <zeroOrMore>
- <externalRef href="resources-2.4.rng" />
- </zeroOrMore>
- </element>
- </define>
-
- <define name="rsc-colocation">
- <element name="rsc_colocation">
- <attribute name="id"> <text/> </attribute>
- <attribute name="rsc"> <text/> </attribute>
- <attribute name="with-rsc"> <text/> </attribute>
- <externalRef href="../score.rng"/>
- <optional>
- <attribute name="node-attribute"> <text/> </attribute>
- </optional>
- <optional>
- <attribute name="rsc-role">
- <ref name="attribute-roles"/>
- </attribute>
- </optional>
- <optional>
- <attribute name="with-rsc-role">
- <ref name="attribute-roles"/>
- </attribute>
- </optional>
- </element>
- </define>
-
- <define name="element-operation-list">
- <element name="operation">
- <optional>
- <group>
- <attribute name="rsc"> <text/> </attribute>
- <attribute name="agent"> <text/> </attribute>
- </group>
- </optional>
- <attribute name="op"> <text/> </attribute>
- <attribute name="node"> <text/> </attribute>
- <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
- <attribute name="rc"> <data type="nonNegativeInteger" /> </attribute>
- <optional>
- <attribute name="last-rc-change"> <text/> </attribute>
- <attribute name="exec-time"> <data type="nonNegativeInteger" /> </attribute>
- </optional>
- <attribute name="status"> <text/> </attribute>
- </element>
- </define>
-
- <define name="attribute-roles">
- <choice>
- <value>Stopped</value>
- <value>Started</value>
- <value>Master</value>
- <value>Slave</value>
- </choice>
- </define>
-</grammar>
diff --git a/xml/api/crm_resource-2.6.rng b/xml/api/crm_resource-2.6.rng
new file mode 100644
index 0000000..b49e24c
--- /dev/null
+++ b/xml/api/crm_resource-2.6.rng
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="element-crm-resource"/>
+ </start>
+
+ <define name="element-crm-resource">
+ <choice>
+ <ref name="agents-list" />
+ <ref name="alternatives-list" />
+ <ref name="constraints-list" />
+ <externalRef href="generic-list-2.4.rng"/>
+ <element name="metadata"> <text/> </element>
+ <ref name="locate-list" />
+ <ref name="operations-list" />
+ <ref name="providers-list" />
+ <ref name="reasons-list" />
+ <ref name="resource-check" />
+ <ref name="resource-config" />
+ <ref name="resources-list" />
+ </choice>
+ </define>
+
+ <define name="agents-list">
+ <element name="agents">
+ <attribute name="standard"> <text/> </attribute>
+ <optional>
+ <attribute name="provider"> <text/> </attribute>
+ </optional>
+ <zeroOrMore>
+ <element name="agent"> <text/> </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="alternatives-list">
+ <element name="providers">
+ <attribute name="for"> <text/> </attribute>
+ <zeroOrMore>
+ <element name="provider"> <text/> </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="constraints-list">
+ <element name="constraints">
+ <interleave>
+ <zeroOrMore>
+ <ref name="rsc-location" />
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="rsc-colocation" />
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+
+ <define name="locate-list">
+ <element name="nodes">
+ <attribute name="resource"> <text/> </attribute>
+ <zeroOrMore>
+ <element name="node">
+ <optional>
+ <attribute name="state"><value>promoted</value></attribute>
+ </optional>
+ <text/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="rsc-location">
+ <element name="rsc_location">
+ <attribute name="node"> <text/> </attribute>
+ <attribute name="rsc"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ <externalRef href="../score.rng"/>
+ </element>
+ </define>
+
+ <define name="operations-list">
+ <element name="operations">
+ <oneOrMore>
+ <ref name="element-operation-list" />
+ </oneOrMore>
+ </element>
+ </define>
+
+ <define name="providers-list">
+ <element name="providers">
+ <attribute name="standard"> <value>ocf</value> </attribute>
+ <optional>
+ <attribute name="agent"> <text/> </attribute>
+ </optional>
+ <zeroOrMore>
+ <element name="provider"> <text/> </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="reasons-list">
+ <choice>
+ <ref name="no-resource-or-uname"/>
+ <ref name="resource-and-uname"/>
+ <ref name="no-resource-but-uname"/>
+ <ref name="resource-but-no-uname"/>
+ </choice>
+ </define>
+
+ <define name="no-resource-or-uname">
+ <element name="reason">
+ <element name="resources">
+ <zeroOrMore>
+ <element name="resource">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </element>
+ </define>
+
+ <define name="resource-and-uname">
+ <element name="reason">
+ <attribute name="running_on"> <text/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </define>
+
+ <define name="no-resource-but-uname">
+ <element name="reason">
+ <element name="resources">
+ <zeroOrMore>
+ <element name="resource">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <attribute name="host"> <text/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </element>
+ </define>
+
+ <define name="resource-but-no-uname">
+ <element name="reason">
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </define>
+
+ <define name="resource-config">
+ <element name="resource_config">
+ <externalRef href="resources-2.4.rng" />
+ <element name="xml"> <text/> </element>
+ </element>
+ </define>
+
+ <define name="resource-check">
+ <element name="check">
+ <attribute name="id"> <text/> </attribute>
+ <optional>
+ <choice>
+ <attribute name="remain_stopped"><value>true</value></attribute>
+ <attribute name="promotable"><value>false</value></attribute>
+ </choice>
+ </optional>
+ <optional>
+ <attribute name="unmanaged"><value>true</value></attribute>
+ </optional>
+ <optional>
+ <attribute name="locked-to"> <text/> </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="resources-list">
+ <element name="resources">
+ <zeroOrMore>
+ <externalRef href="resources-2.4.rng" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="rsc-colocation">
+ <element name="rsc_colocation">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="rsc"> <text/> </attribute>
+ <attribute name="with-rsc"> <text/> </attribute>
+ <externalRef href="../score.rng"/>
+ <optional>
+ <attribute name="node-attribute"> <text/> </attribute>
+ </optional>
+ <optional>
+ <attribute name="rsc-role">
+ <ref name="attribute-roles"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="with-rsc-role">
+ <ref name="attribute-roles"/>
+ </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="element-operation-list">
+ <element name="operation">
+ <optional>
+ <group>
+ <attribute name="rsc"> <text/> </attribute>
+ <attribute name="agent"> <text/> </attribute>
+ </group>
+ </optional>
+ <attribute name="op"> <text/> </attribute>
+ <attribute name="node"> <text/> </attribute>
+ <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="rc"> <data type="nonNegativeInteger" /> </attribute>
+ <optional>
+ <attribute name="last-rc-change"> <text/> </attribute>
+ <attribute name="exec-time"> <data type="nonNegativeInteger" /> </attribute>
+ </optional>
+ <attribute name="status"> <text/> </attribute>
+ </element>
+ </define>
+
+ <define name="attribute-roles">
+ <choice>
+ <value>Stopped</value>
+ <value>Started</value>
+ <value>Master</value>
+ <value>Slave</value>
+ </choice>
+ </define>
+</grammar>
--
1.8.3.1

26
SOURCES/026-tests.patch Normal file
View File

@ -0,0 +1,26 @@
From 610e54caf9a695d3d108c87c735a630f2ea5657f Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Wed, 2 Dec 2020 15:09:35 -0600
Subject: [PATCH] Test: cts-fencing: update expected output
b16b24ed changed the order of some XML attributes
---
cts/cts-fencing.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cts/cts-fencing.in b/cts/cts-fencing.in
index c901c6c..224b5d4 100644
--- a/cts/cts-fencing.in
+++ b/cts/cts-fencing.in
@@ -1102,7 +1102,7 @@ class Tests(object):
test.add_cmd("stonith_admin", "--output-as=xml -F node3 -t 5 -V")
- test.add_cmd_check_stdout("stonith_admin", "--output-as=xml -H node3", 'status="success" .* action="off" target="node3"')
+ test.add_cmd_check_stdout("stonith_admin", "--output-as=xml -H node3", 'action="off" target="node3" .* status="success"')
# simple test of dynamic list query
for test_type in test_types:
--
1.8.3.1

962
SOURCES/027-crm_mon.patch Normal file
View File

@ -0,0 +1,962 @@
From a32b6e14ba51fefbda2d4a699cf1c48dd3a1bb5a Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 7 Jan 2021 11:37:51 -0500
Subject: [PATCH 01/10] Fix: tools: Don't pass stonith history to
print_simple_status.
It's not being used.
---
tools/crm_mon.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 4555516..729f6a1 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.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.
*
@@ -1451,14 +1451,13 @@ main(int argc, char **argv)
* \brief Print one-line status suitable for use with monitoring software
*
* \param[in] data_set Working set of CIB state
- * \param[in] history List of stonith actions
*
* \note This function's output (and the return code when the program exits)
* should conform to https://www.monitoring-plugins.org/doc/guidelines.html
*/
static void
print_simple_status(pcmk__output_t *out, pe_working_set_t * data_set,
- stonith_history_t *history, unsigned int mon_ops)
+ unsigned int mon_ops)
{
GListPtr gIter = NULL;
int nodes_online = 0;
@@ -2012,7 +2011,7 @@ mon_refresh_display(gpointer user_data)
break;
case mon_output_monitor:
- print_simple_status(out, mon_data_set, stonith_history, options.mon_ops);
+ print_simple_status(out, mon_data_set, options.mon_ops);
if (pcmk_is_set(options.mon_ops, mon_op_has_warnings)) {
clean_up(MON_STATUS_WARN);
return FALSE;
--
1.8.3.1
From 8b9c47089c70295bc0529671ba5991c6d831e14b Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 7 Jan 2021 13:17:04 -0500
Subject: [PATCH 02/10] Refactor: tools: Don't pass output_format to
mon_refresh_display.
output_format is a global variable.
---
tools/crm_mon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 729f6a1..b801560 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -827,7 +827,7 @@ cib_connect(gboolean full)
rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
if (rc == pcmk_ok) {
- mon_refresh_display(&output_format);
+ mon_refresh_display(NULL);
}
if (rc == pcmk_ok && full) {
--
1.8.3.1
From a1b14ad96f12746167da8588dc086b20e6f6d1d6 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 7 Jan 2021 13:20:14 -0500
Subject: [PATCH 03/10] Refactor: tools: Remove unnecessary checks for cib !=
NULL.
cib is guaranteed to not be NULL at these points, so there's no need to
do an additional check. This code was leftover from a previous
reorganization that changed when the cib variable gets initialized.
---
tools/crm_mon.c | 41 +++++++++++++++++++----------------------
1 file changed, 19 insertions(+), 22 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index b801560..1eedd38 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -1346,7 +1346,7 @@ main(int argc, char **argv)
/* Extra sanity checks when in CGI mode */
if (output_format == mon_output_cgi) {
- if (cib && cib->variant == cib_file) {
+ if (cib->variant == cib_file) {
g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE, "CGI mode used with CIB file");
return clean_up(CRM_EX_USAGE);
} else if (options.external_agent != NULL) {
@@ -1370,33 +1370,30 @@ main(int argc, char **argv)
crm_info("Starting %s", crm_system_name);
- if (cib) {
-
- do {
- if (!pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
- print_as(output_format ,"Waiting until cluster is available on this node ...\n");
- }
- rc = cib_connect(!pcmk_is_set(options.mon_ops, mon_op_one_shot));
+ do {
+ if (!pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
+ print_as(output_format ,"Waiting until cluster is available on this node ...\n");
+ }
+ rc = cib_connect(!pcmk_is_set(options.mon_ops, mon_op_one_shot));
- if (pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
- break;
+ if (pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
+ break;
- } else if (rc != pcmk_ok) {
- sleep(options.reconnect_msec / 1000);
+ } else if (rc != pcmk_ok) {
+ sleep(options.reconnect_msec / 1000);
#if CURSES_ENABLED
- if (output_format == mon_output_console) {
- clear();
- refresh();
- }
+ if (output_format == mon_output_console) {
+ clear();
+ refresh();
+ }
#endif
- } else {
- if (output_format == mon_output_html && out->dest != stdout) {
- printf("Writing html to %s ...\n", args->output_dest);
- }
+ } else {
+ if (output_format == mon_output_html && out->dest != stdout) {
+ printf("Writing html to %s ...\n", args->output_dest);
}
+ }
- } while (rc == -ENOTCONN);
- }
+ } while (rc == -ENOTCONN);
if (rc != pcmk_ok) {
if (output_format == mon_output_monitor) {
--
1.8.3.1
From fe5284a12765e775905bdfe58711c5733a063132 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 7 Jan 2021 14:15:40 -0500
Subject: [PATCH 04/10] Fix: tools: mon_refresh_display should return an int.
While GSourceFunc is defined as returning a boolean, our public API
mainloop function expect the dispatch function to return an int. So
change mon_refresh_display to do so.
---
tools/crm_mon.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 1eedd38..8657a89 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -125,7 +125,7 @@ struct {
static void clean_up_connections(void);
static crm_exit_t clean_up(crm_exit_t exit_code);
static void crm_diff_update(const char *event, xmlNode * msg);
-static gboolean mon_refresh_display(gpointer user_data);
+static int mon_refresh_display(gpointer user_data);
static int cib_connect(gboolean full);
static void mon_st_callback_event(stonith_t * st, stonith_event_t * e);
static void mon_st_callback_display(stonith_t * st, stonith_event_t * e);
@@ -1925,7 +1925,7 @@ crm_diff_update(const char *event, xmlNode * msg)
kick_refresh(cib_updated);
}
-static gboolean
+static int
mon_refresh_display(gpointer user_data)
{
xmlNode *cib_copy = copy_xml(current_cib);
@@ -1940,7 +1940,7 @@ mon_refresh_display(gpointer user_data)
}
out->err(out, "Upgrade failed: %s", pcmk_strerror(-pcmk_err_schema_validation));
clean_up(CRM_EX_CONFIG);
- return FALSE;
+ return 0;
}
/* get the stonith-history if there is evidence we need it
@@ -1966,7 +1966,7 @@ mon_refresh_display(gpointer user_data)
}
free_xml(cib_copy);
out->err(out, "Reading stonith-history failed");
- return FALSE;
+ return 0;
}
if (mon_data_set == NULL) {
@@ -1995,7 +1995,7 @@ mon_refresh_display(gpointer user_data)
options.only_node, options.only_rsc) != 0) {
g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_CANTCREAT, "Critical: Unable to output html file");
clean_up(CRM_EX_CANTCREAT);
- return FALSE;
+ return 0;
}
break;
@@ -2044,7 +2044,7 @@ mon_refresh_display(gpointer user_data)
stonith_history_free(stonith_history);
stonith_history = NULL;
pe_reset_working_set(mon_data_set);
- return TRUE;
+ return 1;
}
static void
--
1.8.3.1
From 7f88a5a428ed73fb5161096ece2517abe1119f06 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 7 Jan 2021 16:59:02 -0500
Subject: [PATCH 05/10] Refactor: tools: Change a conditional in cib_connect.
This allows unindenting everything that occurs inside that conditional,
which I think makes it a little bit easier to understand what is going
on.
---
tools/crm_mon.c | 86 +++++++++++++++++++++++++++++----------------------------
1 file changed, 44 insertions(+), 42 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 8657a89..b8ba56b 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -804,55 +804,57 @@ cib_connect(gboolean full)
}
}
- if (cib->state != cib_connected_query && cib->state != cib_connected_command) {
- crm_trace("Connecting to the CIB");
-
- /* Hack: the CIB signon will print the prompt for a password if needed,
- * but to stderr. If we're in curses, show it on the screen instead.
- *
- * @TODO Add a password prompt (maybe including input) function to
- * pcmk__output_t and use it in libcib.
- */
- if ((output_format == mon_output_console) && need_pass && (cib->variant == cib_remote)) {
- need_pass = FALSE;
- print_as(output_format, "Password:");
- }
+ if (cib->state == cib_connected_query || cib->state == cib_connected_command) {
+ return rc;
+ }
- rc = cib->cmds->signon(cib, crm_system_name, cib_query);
- if (rc != pcmk_ok) {
- out->err(out, "Could not connect to the CIB: %s",
- pcmk_strerror(rc));
- return rc;
- }
+ crm_trace("Connecting to the CIB");
- rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
- if (rc == pcmk_ok) {
- mon_refresh_display(NULL);
- }
+ /* Hack: the CIB signon will print the prompt for a password if needed,
+ * but to stderr. If we're in curses, show it on the screen instead.
+ *
+ * @TODO Add a password prompt (maybe including input) function to
+ * pcmk__output_t and use it in libcib.
+ */
+ if ((output_format == mon_output_console) && need_pass && (cib->variant == cib_remote)) {
+ need_pass = FALSE;
+ print_as(output_format, "Password:");
+ }
- if (rc == pcmk_ok && full) {
- if (rc == pcmk_ok) {
- rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
- if (rc == -EPROTONOSUPPORT) {
- print_as
- (output_format, "Notification setup not supported, won't be able to reconnect after failure");
- if (output_format == mon_output_console) {
- sleep(2);
- }
- rc = pcmk_ok;
- }
+ rc = cib->cmds->signon(cib, crm_system_name, cib_query);
+ if (rc != pcmk_ok) {
+ out->err(out, "Could not connect to the CIB: %s",
+ pcmk_strerror(rc));
+ return rc;
+ }
- }
+ rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
+ if (rc == pcmk_ok) {
+ mon_refresh_display(NULL);
+ }
- if (rc == pcmk_ok) {
- cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
- rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
+ if (rc == pcmk_ok && full) {
+ if (rc == pcmk_ok) {
+ rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
+ if (rc == -EPROTONOSUPPORT) {
+ print_as
+ (output_format, "Notification setup not supported, won't be able to reconnect after failure");
+ if (output_format == mon_output_console) {
+ sleep(2);
+ }
+ rc = pcmk_ok;
}
- if (rc != pcmk_ok) {
- out->err(out, "Notification setup failed, could not monitor CIB actions");
- clean_up_connections();
- }
+ }
+
+ if (rc == pcmk_ok) {
+ cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
+ rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
+ }
+
+ if (rc != pcmk_ok) {
+ out->err(out, "Notification setup failed, could not monitor CIB actions");
+ clean_up_connections();
}
}
return rc;
--
1.8.3.1
From 178ba17e4ee62bef28f8e71cad2c002f823661b5 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 7 Jan 2021 17:37:36 -0500
Subject: [PATCH 06/10] Refactor: tools: Remove an unnecessary conditional in
cib_connect.
---
tools/crm_mon.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index b8ba56b..36249e8 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -834,17 +834,14 @@ cib_connect(gboolean full)
}
if (rc == pcmk_ok && full) {
- if (rc == pcmk_ok) {
- rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
- if (rc == -EPROTONOSUPPORT) {
- print_as
- (output_format, "Notification setup not supported, won't be able to reconnect after failure");
- if (output_format == mon_output_console) {
- sleep(2);
- }
- rc = pcmk_ok;
+ rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
+ if (rc == -EPROTONOSUPPORT) {
+ print_as
+ (output_format, "Notification setup not supported, won't be able to reconnect after failure");
+ if (output_format == mon_output_console) {
+ sleep(2);
}
-
+ rc = pcmk_ok;
}
if (rc == pcmk_ok) {
--
1.8.3.1
From 33bac5886417afc5c7bbf56f4d31e0e36f8ae947 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 8 Jan 2021 10:00:50 -0500
Subject: [PATCH 07/10] Refactor: tools: Simplify another conditional in
crm_mon.
---
tools/crm_mon.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 36249e8..8b47bbc 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -1386,10 +1386,8 @@ main(int argc, char **argv)
refresh();
}
#endif
- } else {
- if (output_format == mon_output_html && out->dest != stdout) {
- printf("Writing html to %s ...\n", args->output_dest);
- }
+ } else if (output_format == mon_output_html && out->dest != stdout) {
+ printf("Writing html to %s ...\n", args->output_dest);
}
} while (rc == -ENOTCONN);
--
1.8.3.1
From 40bc8b3147e7ebef4318211fa69973a8b5d32e79 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 8 Jan 2021 12:12:37 -0500
Subject: [PATCH 08/10] Refactor: libcrmcommon,tools,daemons: Put common xpath
code in one place.
---
configure.ac | 1 +
daemons/controld/controld_te_callbacks.c | 26 +++-----------
include/crm/common/xml_internal.h | 14 +++++++-
lib/common/tests/Makefile.am | 2 +-
lib/common/tests/xpath/Makefile.am | 29 +++++++++++++++
lib/common/tests/xpath/pcmk__xpath_node_id_test.c | 43 +++++++++++++++++++++++
lib/common/xpath.c | 34 +++++++++++++++++-
tools/crm_mon.c | 25 ++-----------
8 files changed, 127 insertions(+), 47 deletions(-)
create mode 100644 lib/common/tests/xpath/Makefile.am
create mode 100644 lib/common/tests/xpath/pcmk__xpath_node_id_test.c
diff --git a/configure.ac b/configure.ac
index 5959116..ce0f1fe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1920,6 +1920,7 @@ AC_CONFIG_FILES(Makefile \
lib/common/tests/operations/Makefile \
lib/common/tests/strings/Makefile \
lib/common/tests/utils/Makefile \
+ lib/common/tests/xpath/Makefile \
lib/cluster/Makefile \
lib/cib/Makefile \
lib/gnu/Makefile \
diff --git a/daemons/controld/controld_te_callbacks.c b/daemons/controld/controld_te_callbacks.c
index 66fc645..4e3e4e6 100644
--- a/daemons/controld/controld_te_callbacks.c
+++ b/daemons/controld/controld_te_callbacks.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.
*
@@ -276,24 +276,6 @@ process_resource_updates(const char *node, xmlNode *xml, xmlNode *change,
}
}
-#define NODE_PATT "/lrm[@id="
-static char *get_node_from_xpath(const char *xpath)
-{
- char *nodeid = NULL;
- char *tmp = strstr(xpath, NODE_PATT);
-
- if(tmp) {
- tmp += strlen(NODE_PATT);
- tmp += 1;
-
- nodeid = strdup(tmp);
- tmp = strstr(nodeid, "\'");
- CRM_ASSERT(tmp);
- tmp[0] = 0;
- }
- return nodeid;
-}
-
static char *extract_node_uuid(const char *xpath)
{
char *mutable_path = strdup(xpath);
@@ -522,19 +504,19 @@ te_update_diff_v2(xmlNode *diff)
process_resource_updates(ID(match), match, change, op, xpath);
} else if (strcmp(name, XML_LRM_TAG_RESOURCES) == 0) {
- char *local_node = get_node_from_xpath(xpath);
+ char *local_node = pcmk__xpath_node_id(xpath, "lrm");
process_resource_updates(local_node, match, change, op, xpath);
free(local_node);
} else if (strcmp(name, XML_LRM_TAG_RESOURCE) == 0) {
- char *local_node = get_node_from_xpath(xpath);
+ char *local_node = pcmk__xpath_node_id(xpath, "lrm");
process_lrm_resource_diff(match, local_node);
free(local_node);
} else if (strcmp(name, XML_LRM_TAG_RSC_OP) == 0) {
- char *local_node = get_node_from_xpath(xpath);
+ char *local_node = pcmk__xpath_node_id(xpath, "lrm");
process_graph_event(match, local_node);
free(local_node);
diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h
index 1e80bc6..d8694ee 100644
--- a/include/crm/common/xml_internal.h
+++ b/include/crm/common/xml_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2020 the Pacemaker project contributors
+ * Copyright 2017-2021 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -273,4 +273,16 @@ pcmk__xe_first_attr(const xmlNode *xe)
return (xe == NULL)? NULL : xe->properties;
}
+/*!
+ * \internal
+ * \brief Extract the ID attribute from an XML element
+ *
+ * \param[in] xpath String to search
+ * \param[in] node Node to get the ID for
+ *
+ * \return ID attribute of \p node in xpath string \p xpath
+ */
+char *
+pcmk__xpath_node_id(const char *xpath, const char *node);
+
#endif // PCMK__XML_INTERNAL__H
diff --git a/lib/common/tests/Makefile.am b/lib/common/tests/Makefile.am
index 2c33cc5..4c6e8b4 100644
--- a/lib/common/tests/Makefile.am
+++ b/lib/common/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = agents cmdline flags operations strings utils
+SUBDIRS = agents cmdline flags operations strings utils xpath
diff --git a/lib/common/tests/xpath/Makefile.am b/lib/common/tests/xpath/Makefile.am
new file mode 100644
index 0000000..7a53683
--- /dev/null
+++ b/lib/common/tests/xpath/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright 2021 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
+LDADD = $(top_builddir)/lib/common/libcrmcommon.la
+
+include $(top_srcdir)/mk/glib-tap.mk
+
+# Add each test program here. Each test should be written as a little standalone
+# program using the glib unit testing functions. See the documentation for more
+# information.
+#
+# https://developer.gnome.org/glib/unstable/glib-Testing.html
+#
+# Add "_test" to the end of all test program names to simplify .gitignore.
+test_programs = pcmk__xpath_node_id_test
+
+# If any extra data needs to be added to the source distribution, add it to the
+# following list.
+dist_test_data =
+
+# If any extra data needs to be used by tests but should not be added to the
+# source distribution, add it to the following list.
+test_data =
diff --git a/lib/common/tests/xpath/pcmk__xpath_node_id_test.c b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c
new file mode 100644
index 0000000..f6b5c10
--- /dev/null
+++ b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+#include <crm/common/xml_internal.h>
+
+static void
+empty_input(void) {
+ g_assert_null(pcmk__xpath_node_id(NULL, "lrm"));
+ g_assert_null(pcmk__xpath_node_id("", "lrm"));
+ g_assert_null(pcmk__xpath_node_id("/blah/blah", NULL));
+ g_assert_null(pcmk__xpath_node_id("/blah/blah", ""));
+ g_assert_null(pcmk__xpath_node_id(NULL, NULL));
+}
+
+static void
+not_present(void) {
+ g_assert_null(pcmk__xpath_node_id("/some/xpath/string[@id='xyz']", "lrm"));
+ g_assert_null(pcmk__xpath_node_id("/some/xpath/containing[@id='lrm']", "lrm"));
+}
+
+static void
+present(void) {
+ g_assert_cmpint(strcmp(pcmk__xpath_node_id("/some/xpath/containing/lrm[@id='xyz']", "lrm"), "xyz"), ==, 0);
+ g_assert_cmpint(strcmp(pcmk__xpath_node_id("/some/other/lrm[@id='xyz']/xpath", "lrm"), "xyz"), ==, 0);
+}
+
+int
+main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/common/xpath/node_id/empty_input", empty_input);
+ g_test_add_func("/common/xpath/node_id/not_present", not_present);
+ g_test_add_func("/common/xpath/node_id/present", present);
+ return g_test_run();
+}
diff --git a/lib/common/xpath.c b/lib/common/xpath.c
index 6fa4941..7851a7c 100644
--- a/lib/common/xpath.c
+++ b/lib/common/xpath.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.
*
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <string.h>
#include <crm/msg_xml.h>
+#include <crm/common/xml_internal.h>
#include "crmcommon_private.h"
/*
@@ -297,3 +298,34 @@ xml_get_path(xmlNode *xml)
}
return NULL;
}
+
+char *
+pcmk__xpath_node_id(const char *xpath, const char *node)
+{
+ char *retval = NULL;
+ char *patt = NULL;
+ char *start = NULL;
+ char *end = NULL;
+
+ if (node == NULL || xpath == NULL) {
+ return retval;
+ }
+
+ patt = crm_strdup_printf("/%s[@id=", node);
+ start = strstr(xpath, patt);
+
+ if (!start) {
+ free(patt);
+ return retval;
+ }
+
+ start += strlen(patt);
+ start++;
+
+ end = strstr(start, "\'");
+ CRM_ASSERT(end);
+ retval = strndup(start, end-start);
+
+ free(patt);
+ return retval;
+}
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 8b47bbc..ff1b86b 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -1719,25 +1719,6 @@ mon_trigger_refresh(gpointer user_data)
return FALSE;
}
-#define NODE_PATT "/lrm[@id="
-static char *
-get_node_from_xpath(const char *xpath)
-{
- char *nodeid = NULL;
- char *tmp = strstr(xpath, NODE_PATT);
-
- if(tmp) {
- tmp += strlen(NODE_PATT);
- tmp += 1;
-
- nodeid = strdup(tmp);
- tmp = strstr(nodeid, "\'");
- CRM_ASSERT(tmp);
- tmp[0] = 0;
- }
- return nodeid;
-}
-
static void
crm_diff_update_v2(const char *event, xmlNode * msg)
{
@@ -1822,19 +1803,19 @@ crm_diff_update_v2(const char *event, xmlNode * msg)
handle_rsc_op(match, node);
} else if(strcmp(name, XML_LRM_TAG_RESOURCES) == 0) {
- char *local_node = get_node_from_xpath(xpath);
+ char *local_node = pcmk__xpath_node_id(xpath, "lrm");
handle_rsc_op(match, local_node);
free(local_node);
} else if(strcmp(name, XML_LRM_TAG_RESOURCE) == 0) {
- char *local_node = get_node_from_xpath(xpath);
+ char *local_node = pcmk__xpath_node_id(xpath, "lrm");
handle_rsc_op(match, local_node);
free(local_node);
} else if(strcmp(name, XML_LRM_TAG_RSC_OP) == 0) {
- char *local_node = get_node_from_xpath(xpath);
+ char *local_node = pcmk__xpath_node_id(xpath, "lrm");
handle_rsc_op(match, local_node);
free(local_node);
--
1.8.3.1
From b0126373d8b2a739ec5b985a7e1f530e850618d3 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 11 Jan 2021 10:20:11 -0500
Subject: [PATCH 09/10] Refactor: libpacemaker: Move reduce_stonith_history
into the library.
And also rename it to pcmk__reduce_fence_history. I don't see anywhere
else that could use this function at the moment, but it seems too
generic to keep in crm_mon.
---
include/pcmki/pcmki_fence.h | 16 +++++++++++++-
lib/pacemaker/pcmk_fence.c | 45 ++++++++++++++++++++++++++++++++++++++-
tools/crm_mon.c | 52 +--------------------------------------------
3 files changed, 60 insertions(+), 53 deletions(-)
diff --git a/include/pcmki/pcmki_fence.h b/include/pcmki/pcmki_fence.h
index 241d030..d4cef68 100644
--- a/include/pcmki/pcmki_fence.h
+++ b/include/pcmki/pcmki_fence.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the Pacemaker project contributors
+ * Copyright 2019-2021 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -219,4 +219,18 @@ int pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
const char *id, stonith_key_value_t *params,
unsigned int timeout);
+/**
+ * \brief Reduce the STONITH history
+ *
+ * STONITH history is reduced as follows:
+ * - The last successful action of every action-type and target is kept
+ * - For failed actions, who failed is kept
+ * - All actions in progress are kept
+ *
+ * \param[in] history List of STONITH actions
+ *
+ * \return The reduced history
+ */
+stonith_history_t *
+pcmk__reduce_fence_history(stonith_history_t *history);
#endif
diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c
index d591379..34540cc 100644
--- a/lib/pacemaker/pcmk_fence.c
+++ b/lib/pacemaker/pcmk_fence.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2020 the Pacemaker project contributors
+ * Copyright 2009-2021 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -520,3 +520,46 @@ pcmk_fence_validate(xmlNodePtr *xml, stonith_t *st, const char *agent,
return rc;
}
#endif
+
+stonith_history_t *
+pcmk__reduce_fence_history(stonith_history_t *history)
+{
+ stonith_history_t *new, *hp, *np;
+
+ if (!history) {
+ return history;
+ }
+
+ new = history;
+ hp = new->next;
+ new->next = NULL;
+
+ while (hp) {
+ stonith_history_t *hp_next = hp->next;
+
+ hp->next = NULL;
+
+ for (np = new; ; np = np->next) {
+ if ((hp->state == st_done) || (hp->state == st_failed)) {
+ /* action not in progress */
+ if (pcmk__str_eq(hp->target, np->target, pcmk__str_casei) &&
+ pcmk__str_eq(hp->action, np->action, pcmk__str_casei) &&
+ (hp->state == np->state) &&
+ ((hp->state == st_done) ||
+ pcmk__str_eq(hp->delegate, np->delegate, pcmk__str_casei))) {
+ /* purge older hp */
+ stonith_history_free(hp);
+ break;
+ }
+ }
+
+ if (!np->next) {
+ np->next = hp;
+ break;
+ }
+ }
+ hp = hp_next;
+ }
+
+ return new;
+}
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index ff1b86b..2179f53 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -1520,56 +1520,6 @@ print_simple_status(pcmk__output_t *out, pe_working_set_t * data_set,
/* coverity[leaked_storage] False positive */
}
-/*!
- * \internal
- * \brief Reduce the stonith-history
- * for successful actions we keep the last of every action-type & target
- * for failed actions we record as well who had failed
- * for actions in progress we keep full track
- *
- * \param[in] history List of stonith actions
- *
- */
-static stonith_history_t *
-reduce_stonith_history(stonith_history_t *history)
-{
- stonith_history_t *new = history, *hp, *np;
-
- if (new) {
- hp = new->next;
- new->next = NULL;
-
- while (hp) {
- stonith_history_t *hp_next = hp->next;
-
- hp->next = NULL;
-
- for (np = new; ; np = np->next) {
- if ((hp->state == st_done) || (hp->state == st_failed)) {
- /* action not in progress */
- if (pcmk__str_eq(hp->target, np->target, pcmk__str_casei) &&
- pcmk__str_eq(hp->action, np->action, pcmk__str_casei) &&
- (hp->state == np->state) &&
- ((hp->state == st_done) ||
- pcmk__str_eq(hp->delegate, np->delegate, pcmk__str_casei))) {
- /* purge older hp */
- stonith_history_free(hp);
- break;
- }
- }
-
- if (!np->next) {
- np->next = hp;
- break;
- }
- }
- hp = hp_next;
- }
- }
-
- return new;
-}
-
static int
send_custom_trap(const char *node, const char *rsc, const char *task, int target_rc, int rc,
int status, const char *desc)
@@ -1935,7 +1885,7 @@ mon_refresh_display(gpointer user_data)
if (!pcmk_is_set(options.mon_ops, mon_op_fence_full_history)
&& (output_format != mon_output_xml)) {
- stonith_history = reduce_stonith_history(stonith_history);
+ stonith_history = pcmk__reduce_fence_history(stonith_history);
}
break; /* all other cases are errors */
}
--
1.8.3.1
From af3f1368bc76eb498c2c96b3eda9324b579c9380 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 12 Jan 2021 15:46:55 -0500
Subject: [PATCH 10/10] Low: tools: Adjust fencing shown indicator in crm_mon.
If any of the various fencing flags are set, but not all of them, no '*'
will be shown next to the fencing line in the interactive change screen.
This makes it seem like fencing should not be shown, and hitting 'm'
should toggle the fencing display on. However, that's not the case and
hitting 'm' will actually toggle fencing off. Hitting it again will
toggle it on and the '*' will appear.
This is confusing, so just display the '*' if any fencing flag is set.
---
tools/crm_mon.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 2179f53..8ec97bb 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -984,7 +984,10 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_dat
print_option_help(out, 'R', pcmk_is_set(options.mon_ops, mon_op_print_clone_detail));
print_option_help(out, 'b', pcmk_is_set(options.mon_ops, mon_op_print_brief));
print_option_help(out, 'j', pcmk_is_set(options.mon_ops, mon_op_print_pending));
- print_option_help(out, 'm', pcmk_is_set(show, mon_show_fencing_all));
+ print_option_help(out, 'm', pcmk_any_flags_set(show,
+ mon_show_fence_failed
+ |mon_show_fence_pending
+ |mon_show_fence_worked));
out->info(out, "%s", "\nToggle fields via field letter, type any other key to return");
}
--
1.8.3.1

1305
SOURCES/028-crm_mon.patch Normal file

File diff suppressed because it is too large Load Diff

202
SOURCES/029-crm_mon.patch Normal file
View File

@ -0,0 +1,202 @@
From bc60f9c84bd6f0fa4d73db8d140030dfcdbf4f5e Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 19 Jan 2021 15:58:36 -0500
Subject: [PATCH 1/2] Fix: tools: Describe interactive crm_mon use in help and
man page.
---
tools/crm_mon.8.inc | 3 +++
tools/crm_mon.c | 4 ++++
tools/fix-manpages | 2 +-
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/tools/crm_mon.8.inc b/tools/crm_mon.8.inc
index e4cd7e3..6b46d7b 100644
--- a/tools/crm_mon.8.inc
+++ b/tools/crm_mon.8.inc
@@ -12,3 +12,6 @@ crm_mon mode [options]
/command line arguments./
.SH TIME SPECIFICATION
+
+/or --exclude=list./
+.SH INTERACTIVE USE
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 083b7ae..aafc80f 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -1062,6 +1062,10 @@ build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
"times on the command line, and each can give a comma-separated list of sections.\n"
"The options are applied to the default set, from left to right as seen on the\n"
"command line. For a list of valid sections, pass --include=list or --exclude=list.\n\n"
+ "Interactive Use:\n\n"
+ "When run interactively, crm_mon can be told to hide and display various sections\n"
+ "of output. To see a help screen explaining the options, hit '?'. Any key stroke\n"
+ "aside from those listed will cause the screen to refresh.\n\n"
"Examples:\n\n"
"Display the cluster status on the console with updates as they occur:\n\n"
"\tcrm_mon\n\n"
diff --git a/tools/fix-manpages b/tools/fix-manpages
index 714ecce..f1f6f0d 100644
--- a/tools/fix-manpages
+++ b/tools/fix-manpages
@@ -26,7 +26,7 @@
# This leaves the --help-all output looking good and removes redundant
# stuff from the man page. Feel free to add additional headers here.
# Not all tools will have all headers.
-/.SH NOTES\|.SH OPERATION SPECIFICATION\|.SH OUTPUT CONTROL\|.SH TIME SPECIFICATION/{ n
+/.SH NOTES\|.SH INTERACTIVE USE\|.SH OPERATION SPECIFICATION\|.SH OUTPUT CONTROL\|.SH TIME SPECIFICATION/{ n
N
N
d
--
1.8.3.1
From ed4e4370dc97bc220878db89d69c71426b9458a3 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 19 Jan 2021 17:02:45 -0500
Subject: [PATCH 2/2] Fix: tools: The 'm' key in crm_mon is a cycle, not a
toggle.
Each time it's pressed, a different amount of fencing information should
be shown, cycling back to nothing after level 3.
---
tools/crm_mon.c | 76 +++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 55 insertions(+), 21 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index aafc80f..0981634 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -83,6 +83,8 @@ static gchar **processed_args = NULL;
static time_t last_refresh = 0;
crm_trigger_t *refresh_trigger = NULL;
+int interactive_fence_level = 0;
+
static pcmk__supported_format_t formats[] = {
#if CURSES_ENABLED
CRM_MON_SUPPORTED_FORMAT_CURSES,
@@ -382,9 +384,9 @@ as_xml_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError *
static gboolean
fence_history_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **err) {
- int rc = crm_atoi(optarg, "2");
+ interactive_fence_level = crm_atoi(optarg, "2");
- switch (rc) {
+ switch (interactive_fence_level) {
case 3:
options.mon_ops |= mon_op_fence_full_history | mon_op_fence_history | mon_op_fence_connect;
return include_exclude_cb("--include", "fencing", data, err);
@@ -862,6 +864,38 @@ cib_connect(gboolean full)
return rc;
}
+/* This is used to set up the fencing options after the interactive UI has been stared.
+ * fence_history_cb can't be used because it builds up a list of includes/excludes that
+ * then have to be processed with apply_include_exclude and that could affect other
+ * things.
+ */
+static void
+set_fencing_options(int level)
+{
+ switch (level) {
+ case 3:
+ options.mon_ops |= mon_op_fence_full_history | mon_op_fence_history | mon_op_fence_connect;
+ show |= mon_show_fencing_all;
+ break;
+
+ case 2:
+ options.mon_ops |= mon_op_fence_history | mon_op_fence_connect;
+ show |= mon_show_fencing_all;
+ break;
+
+ case 1:
+ options.mon_ops |= mon_op_fence_history | mon_op_fence_connect;
+ show |= mon_show_fence_failed | mon_show_fence_pending;
+ break;
+
+ default:
+ level = 0;
+ options.mon_ops &= ~(mon_op_fence_history | mon_op_fence_connect);
+ show &= ~mon_show_fencing_all;
+ break;
+ }
+}
+
#if CURSES_ENABLED
static const char *
get_option_desc(char c)
@@ -900,23 +934,12 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_dat
switch (c) {
case 'm':
- if (!pcmk_is_set(show, mon_show_fencing_all)) {
- options.mon_ops |= mon_op_fence_history;
- options.mon_ops |= mon_op_fence_connect;
- if (st == NULL) {
- mon_cib_connection_destroy(NULL);
- }
- }
-
- if (pcmk_any_flags_set(show,
- mon_show_fence_failed
- |mon_show_fence_pending
- |mon_show_fence_worked)) {
- show &= ~mon_show_fencing_all;
- } else {
- show |= mon_show_fencing_all;
+ interactive_fence_level++;
+ if (interactive_fence_level > 3) {
+ interactive_fence_level = 0;
}
+ set_fencing_options(interactive_fence_level);
break;
case 'c':
show ^= mon_show_tickets;
@@ -997,10 +1020,7 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_dat
print_option_help(out, 'R', pcmk_is_set(options.mon_ops, mon_op_print_clone_detail));
print_option_help(out, 'b', pcmk_is_set(options.mon_ops, mon_op_print_brief));
print_option_help(out, 'j', pcmk_is_set(options.mon_ops, mon_op_print_pending));
- print_option_help(out, 'm', pcmk_any_flags_set(show,
- mon_show_fence_failed
- |mon_show_fence_pending
- |mon_show_fence_worked));
+ out->info(out, "%d m: \t%s", interactive_fence_level, get_option_desc('m'));
out->info(out, "%s", "\nToggle fields via field letter, type any other key to return");
}
@@ -1400,6 +1420,19 @@ main(int argc, char **argv)
return clean_up(CRM_EX_USAGE);
}
+ /* Sync up the initial value of interactive_fence_level with whatever was set with
+ * --include/--exclude= options.
+ */
+ if (pcmk_is_set(show, mon_show_fencing_all)) {
+ interactive_fence_level = 3;
+ } else if (pcmk_is_set(show, mon_show_fence_worked)) {
+ interactive_fence_level = 2;
+ } else if (pcmk_any_flags_set(show, mon_show_fence_failed | mon_show_fence_pending)) {
+ interactive_fence_level = 1;
+ } else {
+ interactive_fence_level = 0;
+ }
+
crm_mon_register_messages(out);
pe__register_messages(out);
stonith__register_messages(out);
@@ -1460,6 +1493,7 @@ main(int argc, char **argv)
} while (rc == -ENOTCONN);
handle_connection_failures(rc);
+ set_fencing_options(interactive_fence_level);
mon_refresh_display(NULL);
mainloop = g_main_loop_new(NULL, FALSE);
--
1.8.3.1

1505
SOURCES/030-crmadmin.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
From 240b9ec01e6a6e6554f0ae13d759c01339835a40 Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Wed, 27 Jan 2021 10:10:03 +0100
Subject: [PATCH] Feature: cibsecret: use crmadmin -N (which also lists guest
and remote nodes) to get nodes to sync to
---
tools/cibsecret.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/cibsecret.in b/tools/cibsecret.in
index 8923a70..6326bf0 100644
--- a/tools/cibsecret.in
+++ b/tools/cibsecret.in
@@ -182,9 +182,9 @@ get_live_peers() {
[ $? -eq 0 ] || fatal $CRM_EX_UNAVAILABLE "couldn't get local node name"
# Get a list of all other cluster nodes
- GLP_ALL_PEERS="$(crm_node -l)"
+ GLP_ALL_PEERS="$(crmadmin -N -q)"
[ $? -eq 0 ] || fatal $CRM_EX_UNAVAILABLE "couldn't determine cluster nodes"
- GLP_ALL_PEERS="$(echo "$GLP_ALL_PEERS" | awk '{print $2}' | grep -v "^${GLP_LOCAL_NODE}$")"
+ GLP_ALL_PEERS="$(echo "$GLP_ALL_PEERS" | 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
From 494eebe33d56b24e1f3a13ebe6c0ec651c99a2af Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Wed, 3 Feb 2021 09:47:39 -0600
Subject: [PATCH] Fix: tools: get cibsecret stash working again
Broke with dfe636c4
---
tools/cibsecret.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/cibsecret.in b/tools/cibsecret.in
index 6326bf0..ce57a18 100644
--- a/tools/cibsecret.in
+++ b/tools/cibsecret.in
@@ -393,7 +393,7 @@ cibsecret_stash() {
fatal $CRM_EX_NOSUCH "nothing to stash for resource $rsc parameter $param"
is_secret "$CIBSTASH_CURRENT" &&
fatal $CRM_EX_EXISTS "resource $rsc parameter $param already set as secret, nothing to stash"
- cibsecret_set "$CIBSTASH_CURRENT"
+ cibsecret_set "$CIBSTASH_CURRENT" 4
}
cibsecret_unstash() {
--
1.8.3.1

709
SOURCES/034-crm_mon.patch Normal file
View File

@ -0,0 +1,709 @@
From 68139dc8ff5efbfd81d3b5e868462e7eaefa2c74 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Mon, 25 Jan 2021 15:35:33 +0100
Subject: [PATCH 1/7] Fix: crm_mon: add explicit void to one_shot prototype for
compat
---
tools/crm_mon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 0981634..1eca1b7 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -1226,7 +1226,7 @@ handle_connection_failures(int rc)
}
static void
-one_shot()
+one_shot(void)
{
int rc;
--
1.8.3.1
From 8c7a01f8880efff8457e8421c381082b250d4512 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Mon, 25 Jan 2021 16:26:30 +0100
Subject: [PATCH 2/7] Refactor: crm_mon: cib_connect &
handle_connection_failures -> new rc
---
tools/crm_mon.c | 62 ++++++++++++++++++++++++++++++++-------------------------
1 file changed, 35 insertions(+), 27 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 1eca1b7..3fbac5f 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -690,7 +690,7 @@ reconnect_after_timeout(gpointer data)
print_as(output_format, "Reconnecting...\n");
fencing_connect();
- if (cib_connect(TRUE) == pcmk_ok) {
+ if (cib_connect(TRUE) == pcmk_rc_ok) {
/* Redraw the screen and reinstall ourselves to get called after another reconnect_msec. */
mon_refresh_display(NULL);
return FALSE;
@@ -804,16 +804,17 @@ fencing_connect(void)
static int
cib_connect(gboolean full)
{
- int rc = pcmk_ok;
+ int rc = pcmk_rc_ok;
static gboolean need_pass = TRUE;
- CRM_CHECK(cib != NULL, return -EINVAL);
+ CRM_CHECK(cib != NULL, return EINVAL);
if (getenv("CIB_passwd") != NULL) {
need_pass = FALSE;
}
- if (cib->state == cib_connected_query || cib->state == cib_connected_command) {
+ if (cib->state == cib_connected_query ||
+ cib->state == cib_connected_command) {
return rc;
}
@@ -825,37 +826,44 @@ cib_connect(gboolean full)
* @TODO Add a password prompt (maybe including input) function to
* pcmk__output_t and use it in libcib.
*/
- if ((output_format == mon_output_console) && need_pass && (cib->variant == cib_remote)) {
+ if ((output_format == mon_output_console) &&
+ need_pass &&
+ (cib->variant == cib_remote)) {
need_pass = FALSE;
print_as(output_format, "Password:");
}
- rc = cib->cmds->signon(cib, crm_system_name, cib_query);
- if (rc != pcmk_ok) {
+ rc = pcmk_legacy2rc(cib->cmds->signon(cib, crm_system_name, cib_query));
+ if (rc != pcmk_rc_ok) {
out->err(out, "Could not connect to the CIB: %s",
- pcmk_strerror(rc));
+ pcmk_rc_str(rc));
return rc;
}
- rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
+ rc = pcmk_legacy2rc(cib->cmds->query(cib, NULL, &current_cib,
+ cib_scope_local | cib_sync_call));
- if (rc == pcmk_ok && full) {
- rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy);
- if (rc == -EPROTONOSUPPORT) {
- print_as
- (output_format, "Notification setup not supported, won't be able to reconnect after failure");
+ if (rc == pcmk_rc_ok && full) {
+ rc = pcmk_legacy2rc(cib->cmds->set_connection_dnotify(cib,
+ mon_cib_connection_destroy));
+ if (rc == EPROTONOSUPPORT) {
+ print_as(output_format,
+ "Notification setup not supported, won't be "
+ "able to reconnect after failure");
if (output_format == mon_output_console) {
sleep(2);
}
- rc = pcmk_ok;
+ rc = pcmk_rc_ok;
}
- if (rc == pcmk_ok) {
- cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
- rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
+ if (rc == pcmk_rc_ok) {
+ cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY,
+ crm_diff_update);
+ rc = pcmk_legacy2rc(cib->cmds->add_notify_callback(cib,
+ T_CIB_DIFF_NOTIFY, crm_diff_update));
}
- if (rc != pcmk_ok) {
+ if (rc != pcmk_rc_ok) {
out->err(out, "Notification setup failed, could not monitor CIB actions");
clean_up_cib_connection();
clean_up_fencing_connection();
@@ -1206,20 +1214,20 @@ reconcile_output_format(pcmk__common_args_t *args) {
static void
handle_connection_failures(int rc)
{
- if (rc == pcmk_ok) {
+ if (rc == pcmk_rc_ok) {
return;
}
if (output_format == mon_output_monitor) {
g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "CLUSTER CRIT: Connection to cluster failed: %s",
- pcmk_strerror(rc));
+ pcmk_rc_str(rc));
rc = MON_STATUS_CRIT;
- } else if (rc == -ENOTCONN) {
+ } else if (rc == ENOTCONN) {
g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Error: cluster is not available on this node");
- rc = crm_errno2exit(rc);
+ rc = pcmk_rc2exitc(rc);
} else {
- g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Connection to cluster failed: %s", pcmk_strerror(rc));
- rc = crm_errno2exit(rc);
+ g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Connection to cluster failed: %s", pcmk_rc_str(rc));
+ rc = pcmk_rc2exitc(rc);
}
clean_up(rc);
@@ -1478,7 +1486,7 @@ main(int argc, char **argv)
fencing_connect();
rc = cib_connect(TRUE);
- if (rc != pcmk_ok) {
+ if (rc != pcmk_rc_ok) {
sleep(options.reconnect_msec / 1000);
#if CURSES_ENABLED
if (output_format == mon_output_console) {
@@ -1490,7 +1498,7 @@ main(int argc, char **argv)
printf("Writing html to %s ...\n", args->output_dest);
}
- } while (rc == -ENOTCONN);
+ } while (rc == ENOTCONN);
handle_connection_failures(rc);
set_fencing_options(interactive_fence_level);
--
1.8.3.1
From 9b8fb7b608280f65a3b76d66a99b575a4da70944 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Mon, 25 Jan 2021 18:26:04 +0100
Subject: [PATCH 3/7] Fix: tools: Report pacemakerd in state waiting for sbd
Waiting for pacemakerd to report that all subdaemons are started
before trying to connect to cib and fencer should remove the
potential race introduced by making fencer connection failure
non fatal when cib is faster to come up.
---
tools/crm_mon.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
tools/crm_mon.h | 1 +
2 files changed, 148 insertions(+), 11 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 3fbac5f..61f070d 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -132,6 +132,7 @@ static void handle_connection_failures(int rc);
static int mon_refresh_display(gpointer user_data);
static int cib_connect(gboolean full);
static int fencing_connect(void);
+static int pacemakerd_status(void);
static void mon_st_callback_event(stonith_t * st, stonith_event_t * e);
static void mon_st_callback_display(stonith_t * st, stonith_event_t * e);
static void refresh_after_event(gboolean data_updated);
@@ -689,11 +690,13 @@ reconnect_after_timeout(gpointer data)
}
print_as(output_format, "Reconnecting...\n");
- fencing_connect();
- if (cib_connect(TRUE) == pcmk_rc_ok) {
- /* Redraw the screen and reinstall ourselves to get called after another reconnect_msec. */
- mon_refresh_display(NULL);
- return FALSE;
+ if (pacemakerd_status() == pcmk_rc_ok) {
+ fencing_connect();
+ if (cib_connect(TRUE) == pcmk_rc_ok) {
+ /* Redraw the screen and reinstall ourselves to get called after another reconnect_msec. */
+ mon_refresh_display(NULL);
+ return FALSE;
+ }
}
reconnect_timer = g_timeout_add(options.reconnect_msec, reconnect_after_timeout, NULL);
@@ -840,6 +843,13 @@ cib_connect(gboolean full)
return rc;
}
+#if CURSES_ENABLED
+ /* just show this if refresh is gonna remove all traces */
+ if (output_format == mon_output_console) {
+ print_as(output_format ,"Waiting for CIB ...\n");
+ }
+#endif
+
rc = pcmk_legacy2rc(cib->cmds->query(cib, NULL, &current_cib,
cib_scope_local | cib_sync_call));
@@ -904,6 +914,121 @@ set_fencing_options(int level)
}
}
+/* Before trying to connect to fencer or cib check for state of
+ pacemakerd - just no sense in trying till pacemakerd has
+ taken care of starting all the sub-processes
+
+ Only noteworthy thing to show here is when pacemakerd is
+ waiting for startup-trigger from SBD.
+ */
+static void
+pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
+ enum pcmk_ipc_event event_type, crm_exit_t status,
+ void *event_data, void *user_data)
+{
+ pcmk_pacemakerd_api_reply_t *reply = event_data;
+ enum pcmk_pacemakerd_state *state =
+ (enum pcmk_pacemakerd_state *) user_data;
+
+ /* we are just interested in the latest reply */
+ *state = pcmk_pacemakerd_state_invalid;
+
+ switch (event_type) {
+ case pcmk_ipc_event_reply:
+ break;
+
+ default:
+ return;
+ }
+
+ if (status != CRM_EX_OK) {
+ out->err(out, "Bad reply from pacemakerd: %s",
+ crm_exit_str(status));
+ return;
+ }
+
+ if (reply->reply_type != pcmk_pacemakerd_reply_ping) {
+ out->err(out, "Unknown reply type %d from pacemakerd",
+ reply->reply_type);
+ } else {
+ if ((reply->data.ping.last_good != (time_t) 0) &&
+ (reply->data.ping.status == pcmk_rc_ok)) {
+ *state = reply->data.ping.state;
+ }
+ }
+}
+
+static int
+pacemakerd_status(void)
+{
+ int rc = pcmk_rc_ok;
+ pcmk_ipc_api_t *pacemakerd_api = NULL;
+ enum pcmk_pacemakerd_state state = pcmk_pacemakerd_state_invalid;
+
+ if (!pcmk_is_set(options.mon_ops, mon_op_cib_native)) {
+ /* we don't need fully functional pacemakerd otherwise */
+ return rc;
+ }
+ if (cib != NULL &&
+ (cib->state == cib_connected_query ||
+ cib->state == cib_connected_command)) {
+ /* As long as we have a cib-connection let's go with
+ * that to fetch further cluster-status and avoid
+ * unnecessary pings to pacemakerd.
+ * If cluster is going down and fencer is down already
+ * this will lead to a silently failing fencer reconnect.
+ * On cluster startup we shouldn't see this situation
+ * as first we do is wait for pacemakerd to report all
+ * daemons running.
+ */
+ return rc;
+ }
+ rc = pcmk_new_ipc_api(&pacemakerd_api, pcmk_ipc_pacemakerd);
+ if (pacemakerd_api == NULL) {
+ out->err(out, "Could not connect to pacemakerd: %s",
+ pcmk_rc_str(rc));
+ /* this is unrecoverable so return with rc we have */
+ return rc;
+ }
+ pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, (void *) &state);
+ rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_poll);
+ if (rc == pcmk_rc_ok) {
+ rc = pcmk_pacemakerd_api_ping(pacemakerd_api, crm_system_name);
+ if (rc == pcmk_rc_ok) {
+ rc = pcmk_poll_ipc(pacemakerd_api, options.reconnect_msec/2);
+ if (rc == pcmk_rc_ok) {
+ pcmk_dispatch_ipc(pacemakerd_api);
+ rc = ENOTCONN;
+ switch (state) {
+ case pcmk_pacemakerd_state_running:
+ rc = pcmk_rc_ok;
+ break;
+ case pcmk_pacemakerd_state_starting_daemons:
+ print_as(output_format ,"Pacemaker daemons starting ...\n");
+ break;
+ case pcmk_pacemakerd_state_wait_for_ping:
+ print_as(output_format ,"Waiting for startup-trigger from SBD ...\n");
+ break;
+ case pcmk_pacemakerd_state_shutting_down:
+ print_as(output_format ,"Pacemaker daemons shutting down ...\n");
+ break;
+ case pcmk_pacemakerd_state_shutdown_complete:
+ /* assuming pacemakerd doesn't dispatch any pings after entering
+ * that state unless it is waiting for SBD
+ */
+ print_as(output_format ,"Pacemaker daemons shut down - reporting to SBD ...\n");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ pcmk_free_ipc_api(pacemakerd_api);
+ /* returning with ENOTCONN triggers a retry */
+ return (rc == pcmk_rc_ok)?rc:ENOTCONN;
+}
+
#if CURSES_ENABLED
static const char *
get_option_desc(char c)
@@ -1033,8 +1158,11 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_dat
}
refresh:
- fencing_connect();
- rc = cib_connect(FALSE);
+ rc = pacemakerd_status();
+ if (rc == pcmk_rc_ok) {
+ fencing_connect();
+ rc = cib_connect(FALSE);
+ }
if (rc == pcmk_rc_ok) {
mon_refresh_display(NULL);
} else {
@@ -1238,9 +1366,13 @@ one_shot(void)
{
int rc;
- fencing_connect();
+ rc = pacemakerd_status();
+
+ if (rc == pcmk_rc_ok) {
+ fencing_connect();
+ rc = cib_connect(FALSE);
+ }
- rc = cib_connect(FALSE);
if (rc == pcmk_rc_ok) {
mon_refresh_display(NULL);
} else {
@@ -1316,6 +1448,7 @@ main(int argc, char **argv)
case cib_native:
/* cib & fencing - everything available */
+ options.mon_ops |= mon_op_cib_native;
break;
case cib_file:
@@ -1483,8 +1616,11 @@ main(int argc, char **argv)
do {
print_as(output_format ,"Waiting until cluster is available on this node ...\n");
- fencing_connect();
- rc = cib_connect(TRUE);
+ rc = pacemakerd_status();
+ if (rc == pcmk_rc_ok) {
+ fencing_connect();
+ rc = cib_connect(TRUE);
+ }
if (rc != pcmk_rc_ok) {
sleep(options.reconnect_msec / 1000);
diff --git a/tools/crm_mon.h b/tools/crm_mon.h
index 73c926d..b556913 100644
--- a/tools/crm_mon.h
+++ b/tools/crm_mon.h
@@ -91,6 +91,7 @@ typedef enum mon_output_format_e {
#define mon_op_print_brief (0x0200U)
#define mon_op_print_pending (0x0400U)
#define mon_op_print_clone_detail (0x0800U)
+#define mon_op_cib_native (0x1000U)
#define mon_op_default (mon_op_print_pending | mon_op_fence_history | mon_op_fence_connect)
--
1.8.3.1
From 046516dbe66fb2c52b90f36215cf60c5ad3c269b Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Thu, 28 Jan 2021 16:38:22 +0100
Subject: [PATCH 4/7] Refactor: crm_mon: do refreshes rather via
refresh_after_event
---
tools/crm_mon.c | 35 ++++++++++++++---------------------
1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 61f070d..195e7b5 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -135,7 +135,7 @@ static int fencing_connect(void);
static int pacemakerd_status(void);
static void mon_st_callback_event(stonith_t * st, stonith_event_t * e);
static void mon_st_callback_display(stonith_t * st, stonith_event_t * e);
-static void refresh_after_event(gboolean data_updated);
+static void refresh_after_event(gboolean data_updated, gboolean enforce);
static unsigned int
all_includes(mon_output_format_t fmt) {
@@ -694,13 +694,13 @@ reconnect_after_timeout(gpointer data)
fencing_connect();
if (cib_connect(TRUE) == pcmk_rc_ok) {
/* Redraw the screen and reinstall ourselves to get called after another reconnect_msec. */
- mon_refresh_display(NULL);
+ refresh_after_event(FALSE, TRUE);
return FALSE;
}
}
reconnect_timer = g_timeout_add(options.reconnect_msec, reconnect_after_timeout, NULL);
- return TRUE;
+ return FALSE;
}
/* Called from various places when we are disconnected from the CIB or from the
@@ -1057,7 +1057,6 @@ static gboolean
detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_data)
{
int c;
- int rc;
gboolean config_mode = FALSE;
while (1) {
@@ -1158,16 +1157,7 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_dat
}
refresh:
- rc = pacemakerd_status();
- if (rc == pcmk_rc_ok) {
- fencing_connect();
- rc = cib_connect(FALSE);
- }
- if (rc == pcmk_rc_ok) {
- mon_refresh_display(NULL);
- } else {
- handle_connection_failures(rc);
- }
+ refresh_after_event(FALSE, TRUE);
return TRUE;
}
@@ -2087,7 +2077,7 @@ crm_diff_update(const char *event, xmlNode * msg)
}
stale = FALSE;
- refresh_after_event(cib_updated);
+ refresh_after_event(cib_updated, FALSE);
}
static int
@@ -2246,7 +2236,7 @@ mon_st_callback_event(stonith_t * st, stonith_event_t * e)
* fencing event is received or a CIB diff occurrs.
*/
static void
-refresh_after_event(gboolean data_updated)
+refresh_after_event(gboolean data_updated, gboolean enforce)
{
static int updates = 0;
time_t now = time(NULL);
@@ -2259,12 +2249,15 @@ refresh_after_event(gboolean data_updated)
refresh_timer = mainloop_timer_add("refresh", 2000, FALSE, mon_trigger_refresh, NULL);
}
- if ((now - last_refresh) > (options.reconnect_msec / 1000)) {
- mainloop_set_trigger(refresh_trigger);
+ if (reconnect_timer > 0) {
+ /* we will receive a refresh request after successful reconnect */
mainloop_timer_stop(refresh_timer);
- updates = 0;
+ return;
+ }
- } else if(updates >= 10) {
+ if (enforce ||
+ now - last_refresh > options.reconnect_msec / 1000 ||
+ updates >= 10) {
mainloop_set_trigger(refresh_trigger);
mainloop_timer_stop(refresh_timer);
updates = 0;
@@ -2285,7 +2278,7 @@ mon_st_callback_display(stonith_t * st, stonith_event_t * e)
mon_cib_connection_destroy(NULL);
} else {
print_dot(output_format);
- refresh_after_event(TRUE);
+ refresh_after_event(TRUE, FALSE);
}
}
--
1.8.3.1
From a63af2713f96719fc1d5ef594eb033d0f251187f Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Thu, 28 Jan 2021 16:52:57 +0100
Subject: [PATCH 5/7] Fix: crm_mon: retry fencer connection as not fatal
initially
and cleanup fencer api to not leak memory on multiple reconnects
---
tools/crm_mon.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 195e7b5..a768ca9 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -798,7 +798,7 @@ fencing_connect(void)
st->cmds->register_notification(st, T_STONITH_NOTIFY_HISTORY, mon_st_callback_display);
}
} else {
- st = NULL;
+ clean_up_fencing_connection();
}
return rc;
@@ -2255,6 +2255,12 @@ refresh_after_event(gboolean data_updated, gboolean enforce)
return;
}
+ /* as we're not handling initial failure of fencer-connection as
+ * fatal give it a retry here
+ * not getting here if cib-reconnection is already on the way
+ */
+ fencing_connect();
+
if (enforce ||
now - last_refresh > options.reconnect_msec / 1000 ||
updates >= 10) {
--
1.8.3.1
From b6f4b5dfc0b5fec8cdc029409fc61252de019415 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Thu, 28 Jan 2021 18:08:43 +0100
Subject: [PATCH 6/7] Refactor: crm_mon: have reconnect-timer removed
implicitly
---
tools/crm_mon.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index a768ca9..4f73379 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -684,23 +684,19 @@ reconnect_after_timeout(gpointer data)
}
#endif
- if (reconnect_timer > 0) {
- g_source_remove(reconnect_timer);
- reconnect_timer = 0;
- }
-
print_as(output_format, "Reconnecting...\n");
if (pacemakerd_status() == pcmk_rc_ok) {
fencing_connect();
if (cib_connect(TRUE) == pcmk_rc_ok) {
- /* Redraw the screen and reinstall ourselves to get called after another reconnect_msec. */
+ /* trigger redrawing the screen (needs reconnect_timer == 0) */
+ reconnect_timer = 0;
refresh_after_event(FALSE, TRUE);
- return FALSE;
+ return G_SOURCE_REMOVE;
}
}
reconnect_timer = g_timeout_add(options.reconnect_msec, reconnect_after_timeout, NULL);
- return FALSE;
+ return G_SOURCE_REMOVE;
}
/* Called from various places when we are disconnected from the CIB or from the
--
1.8.3.1
From 586e69ec38d5273b348c42a61b9bc7bbcc2b93b3 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Thu, 28 Jan 2021 21:08:16 +0100
Subject: [PATCH 7/7] Fix: crm_mon: suppress pacemakerd-status for non-text
output
---
tools/crm_mon.c | 53 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 32 insertions(+), 21 deletions(-)
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index 4f73379..d4d4ac3 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -995,27 +995,38 @@ pacemakerd_status(void)
if (rc == pcmk_rc_ok) {
pcmk_dispatch_ipc(pacemakerd_api);
rc = ENOTCONN;
- switch (state) {
- case pcmk_pacemakerd_state_running:
- rc = pcmk_rc_ok;
- break;
- case pcmk_pacemakerd_state_starting_daemons:
- print_as(output_format ,"Pacemaker daemons starting ...\n");
- break;
- case pcmk_pacemakerd_state_wait_for_ping:
- print_as(output_format ,"Waiting for startup-trigger from SBD ...\n");
- break;
- case pcmk_pacemakerd_state_shutting_down:
- print_as(output_format ,"Pacemaker daemons shutting down ...\n");
- break;
- case pcmk_pacemakerd_state_shutdown_complete:
- /* assuming pacemakerd doesn't dispatch any pings after entering
- * that state unless it is waiting for SBD
- */
- print_as(output_format ,"Pacemaker daemons shut down - reporting to SBD ...\n");
- break;
- default:
- break;
+ if ((output_format == mon_output_console) ||
+ (output_format == mon_output_plain)) {
+ switch (state) {
+ case pcmk_pacemakerd_state_running:
+ rc = pcmk_rc_ok;
+ break;
+ case pcmk_pacemakerd_state_starting_daemons:
+ print_as(output_format ,"Pacemaker daemons starting ...\n");
+ break;
+ case pcmk_pacemakerd_state_wait_for_ping:
+ print_as(output_format ,"Waiting for startup-trigger from SBD ...\n");
+ break;
+ case pcmk_pacemakerd_state_shutting_down:
+ print_as(output_format ,"Pacemaker daemons shutting down ...\n");
+ break;
+ case pcmk_pacemakerd_state_shutdown_complete:
+ /* assuming pacemakerd doesn't dispatch any pings after entering
+ * that state unless it is waiting for SBD
+ */
+ print_as(output_format ,"Pacemaker daemons shut down - reporting to SBD ...\n");
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (state) {
+ case pcmk_pacemakerd_state_running:
+ rc = pcmk_rc_ok;
+ break;
+ default:
+ break;
+ }
}
}
}
--
1.8.3.1

267
SOURCES/035-crm_mon.patch Normal file
View File

@ -0,0 +1,267 @@
From f4e3d77c94906a062641c7bf34243049de521a87 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Wed, 3 Feb 2021 13:25:22 +0100
Subject: [PATCH] Fix: crm_mon: detect when run on remote-node
---
daemons/execd/remoted_proxy.c | 17 +++++++
daemons/pacemakerd/pacemakerd.c | 6 +--
include/crm/common/ipc_internal.h | 2 +
lib/common/ipc_server.c | 26 ++++++++++
tools/crm_mon.c | 99 ++++++++++++++++++++++++---------------
5 files changed, 106 insertions(+), 44 deletions(-)
diff --git a/daemons/execd/remoted_proxy.c b/daemons/execd/remoted_proxy.c
index 9329fa6..0fe39bf 100644
--- a/daemons/execd/remoted_proxy.c
+++ b/daemons/execd/remoted_proxy.c
@@ -29,6 +29,7 @@ static qb_ipcs_service_t *cib_shm = NULL;
static qb_ipcs_service_t *attrd_ipcs = NULL;
static qb_ipcs_service_t *crmd_ipcs = NULL;
static qb_ipcs_service_t *stonith_ipcs = NULL;
+static qb_ipcs_service_t *pacemakerd_ipcs = NULL;
// An IPC provider is a cluster node controller connecting as a client
static GList *ipc_providers = NULL;
@@ -126,6 +127,12 @@ stonith_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
}
static int32_t
+pacemakerd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
+{
+ return -EREMOTEIO;
+}
+
+static int32_t
cib_proxy_accept_rw(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
{
return ipc_proxy_accept(c, uid, gid, PCMK__SERVER_BASED_RW);
@@ -356,6 +363,14 @@ static struct qb_ipcs_service_handlers stonith_proxy_callbacks = {
.connection_destroyed = ipc_proxy_destroy
};
+static struct qb_ipcs_service_handlers pacemakerd_proxy_callbacks = {
+ .connection_accept = pacemakerd_proxy_accept,
+ .connection_created = NULL,
+ .msg_process = NULL,
+ .connection_closed = NULL,
+ .connection_destroyed = NULL
+};
+
static struct qb_ipcs_service_handlers cib_proxy_callbacks_ro = {
.connection_accept = cib_proxy_accept_ro,
.connection_created = NULL,
@@ -422,6 +437,7 @@ ipc_proxy_init(void)
&cib_proxy_callbacks_rw);
pcmk__serve_attrd_ipc(&attrd_ipcs, &attrd_proxy_callbacks);
pcmk__serve_fenced_ipc(&stonith_ipcs, &stonith_proxy_callbacks);
+ pcmk__serve_pacemakerd_ipc(&pacemakerd_ipcs, &pacemakerd_proxy_callbacks);
crmd_ipcs = pcmk__serve_controld_ipc(&crmd_proxy_callbacks);
if (crmd_ipcs == NULL) {
crm_err("Failed to create controller: exiting and inhibiting respawn");
@@ -444,6 +460,7 @@ ipc_proxy_cleanup(void)
pcmk__stop_based_ipc(cib_ro, cib_rw, cib_shm);
qb_ipcs_destroy(attrd_ipcs);
qb_ipcs_destroy(stonith_ipcs);
+ qb_ipcs_destroy(pacemakerd_ipcs);
qb_ipcs_destroy(crmd_ipcs);
cib_ro = NULL;
cib_rw = NULL;
diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c
index 509b0f8..4572b70 100644
--- a/daemons/pacemakerd/pacemakerd.c
+++ b/daemons/pacemakerd/pacemakerd.c
@@ -1287,11 +1287,7 @@ main(int argc, char **argv)
// Don't build CRM_RSCTMP_DIR, pacemaker-execd will do it
- ipcs = mainloop_add_ipc_server(CRM_SYSTEM_MCP, QB_IPC_NATIVE, &mcp_ipc_callbacks);
- if (ipcs == NULL) {
- crm_err("Couldn't start IPC server");
- crm_exit(CRM_EX_OSERR);
- }
+ pcmk__serve_pacemakerd_ipc(&ipcs, &mcp_ipc_callbacks);
#ifdef SUPPORT_COROSYNC
/* Allows us to block shutdown */
diff --git a/include/crm/common/ipc_internal.h b/include/crm/common/ipc_internal.h
index cf935f3..fb82ce1 100644
--- a/include/crm/common/ipc_internal.h
+++ b/include/crm/common/ipc_internal.h
@@ -221,6 +221,8 @@ void pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs,
struct qb_ipcs_service_handlers *cb);
void pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs,
struct qb_ipcs_service_handlers *cb);
+void pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs,
+ struct qb_ipcs_service_handlers *cb);
qb_ipcs_service_t *pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb);
void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro,
diff --git a/lib/common/ipc_server.c b/lib/common/ipc_server.c
index 4d3e954..b3aaf8e 100644
--- a/lib/common/ipc_server.c
+++ b/lib/common/ipc_server.c
@@ -922,6 +922,32 @@ pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs,
}
/*!
+ * \internal
+ * \brief Add an IPC server to the main loop for the pacemakerd API
+ *
+ * \param[in] cb IPC callbacks
+ *
+ * \note This function exits with CRM_EX_OSERR if unable to create the servers.
+ */
+void
+pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs,
+ struct qb_ipcs_service_handlers *cb)
+{
+ *ipcs = mainloop_add_ipc_server(CRM_SYSTEM_MCP, QB_IPC_NATIVE, cb);
+
+ if (*ipcs == NULL) {
+ crm_err("Couldn't start pacemakerd IPC server");
+ crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
+ /* sub-daemons are observed by pacemakerd. Thus we exit CRM_EX_FATAL
+ * if we want to prevent pacemakerd from restarting them.
+ * With pacemakerd we leave the exit-code shown to e.g. systemd
+ * to what it was prior to moving the code here from pacemakerd.c
+ */
+ crm_exit(CRM_EX_OSERR);
+ }
+}
+
+/*!
* \brief Check whether string represents a client name used by cluster daemons
*
* \param[in] name String to check
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
index d4d4ac3..e58fed2 100644
--- a/tools/crm_mon.c
+++ b/tools/crm_mon.c
@@ -83,6 +83,8 @@ static gchar **processed_args = NULL;
static time_t last_refresh = 0;
crm_trigger_t *refresh_trigger = NULL;
+static gboolean on_remote_node = FALSE;
+
int interactive_fence_level = 0;
static pcmk__supported_format_t formats[] = {
@@ -988,48 +990,63 @@ pacemakerd_status(void)
}
pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, (void *) &state);
rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_poll);
- if (rc == pcmk_rc_ok) {
- rc = pcmk_pacemakerd_api_ping(pacemakerd_api, crm_system_name);
- if (rc == pcmk_rc_ok) {
- rc = pcmk_poll_ipc(pacemakerd_api, options.reconnect_msec/2);
+ switch (rc) {
+ case pcmk_rc_ok:
+ rc = pcmk_pacemakerd_api_ping(pacemakerd_api, crm_system_name);
if (rc == pcmk_rc_ok) {
- pcmk_dispatch_ipc(pacemakerd_api);
- rc = ENOTCONN;
- if ((output_format == mon_output_console) ||
- (output_format == mon_output_plain)) {
- switch (state) {
- case pcmk_pacemakerd_state_running:
- rc = pcmk_rc_ok;
- break;
- case pcmk_pacemakerd_state_starting_daemons:
- print_as(output_format ,"Pacemaker daemons starting ...\n");
- break;
- case pcmk_pacemakerd_state_wait_for_ping:
- print_as(output_format ,"Waiting for startup-trigger from SBD ...\n");
- break;
- case pcmk_pacemakerd_state_shutting_down:
- print_as(output_format ,"Pacemaker daemons shutting down ...\n");
- break;
- case pcmk_pacemakerd_state_shutdown_complete:
- /* assuming pacemakerd doesn't dispatch any pings after entering
- * that state unless it is waiting for SBD
- */
- print_as(output_format ,"Pacemaker daemons shut down - reporting to SBD ...\n");
- break;
- default:
- break;
- }
- } else {
- switch (state) {
- case pcmk_pacemakerd_state_running:
- rc = pcmk_rc_ok;
- break;
- default:
- break;
+ rc = pcmk_poll_ipc(pacemakerd_api, options.reconnect_msec/2);
+ if (rc == pcmk_rc_ok) {
+ pcmk_dispatch_ipc(pacemakerd_api);
+ rc = ENOTCONN;
+ if ((output_format == mon_output_console) ||
+ (output_format == mon_output_plain)) {
+ switch (state) {
+ case pcmk_pacemakerd_state_running:
+ rc = pcmk_rc_ok;
+ break;
+ case pcmk_pacemakerd_state_starting_daemons:
+ print_as(output_format ,"Pacemaker daemons starting ...\n");
+ break;
+ case pcmk_pacemakerd_state_wait_for_ping:
+ print_as(output_format ,"Waiting for startup-trigger from SBD ...\n");
+ break;
+ case pcmk_pacemakerd_state_shutting_down:
+ print_as(output_format ,"Pacemaker daemons shutting down ...\n");
+ break;
+ case pcmk_pacemakerd_state_shutdown_complete:
+ /* assuming pacemakerd doesn't dispatch any pings after entering
+ * that state unless it is waiting for SBD
+ */
+ print_as(output_format ,"Pacemaker daemons shut down - reporting to SBD ...\n");
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (state) {
+ case pcmk_pacemakerd_state_running:
+ rc = pcmk_rc_ok;
+ break;
+ default:
+ break;
+ }
}
}
}
- }
+ break;
+ case EREMOTEIO:
+ rc = pcmk_rc_ok;
+ on_remote_node = TRUE;
+#if CURSES_ENABLED
+ /* just show this if refresh is gonna remove all traces */
+ if (output_format == mon_output_console) {
+ print_as(output_format ,
+ "Running on remote-node waiting to be connected by cluster ...\n");
+ }
+#endif
+ break;
+ default:
+ break;
}
pcmk_free_ipc_api(pacemakerd_api);
/* returning with ENOTCONN triggers a retry */
@@ -1348,7 +1365,11 @@ handle_connection_failures(int rc)
pcmk_rc_str(rc));
rc = MON_STATUS_CRIT;
} else if (rc == ENOTCONN) {
- g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Error: cluster is not available on this node");
+ if (on_remote_node) {
+ g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Error: remote-node not connected to cluster");
+ } else {
+ g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Error: cluster is not available on this node");
+ }
rc = pcmk_rc2exitc(rc);
} else {
g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Connection to cluster failed: %s", pcmk_rc_str(rc));
--
1.8.3.1

File diff suppressed because it is too large Load Diff

6493
SOURCES/037-scheduler.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
From 98589d8e1ef9b57d806702b9968ff7e5560e9c8f Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 12 Feb 2021 11:51:16 -0500
Subject: [PATCH] Low: Fix a problem with crm_resource exit code handling.
If no output is produced but an error message is printed (like, when an
inactive resource is provided on the command line), don't print the
error message for the pcmk_rc_no_output error code. It's weird to see
output and a message about no output at the same time.
Similarly, don't print an "Error: OK" message when usage is printed.
---
tools/crm_resource.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 7d2f0f6..29b0a04 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1534,9 +1534,9 @@ main(int argc, char **argv)
rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
if (rc != pcmk_rc_ok) {
- fprintf(stderr, "Error creating output format %s: %s\n",
- args->output_ty, pcmk_rc_str(rc));
exit_code = CRM_EX_ERROR;
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",
+ args->output_ty, pcmk_rc_str(rc));
goto done;
}
@@ -2039,7 +2039,12 @@ main(int argc, char **argv)
*/
done:
- if (rc != pcmk_rc_ok) {
+ /* Don't do any of this for pcmk_rc_no_output (doesn't make sense to show an
+ * error message for no output) or for CRM_EX_USAGE (we don't want to show
+ * an "error: OK" message from pcmk_rc_str).
+ */
+ if ((rc != pcmk_rc_ok && rc != pcmk_rc_no_output) ||
+ (exit_code != CRM_EX_OK && exit_code != CRM_EX_USAGE)) {
if (rc == pcmk_rc_no_quorum) {
g_prefix_error(&error, "To ignore quorum, use the force option.\n");
}
@@ -2054,10 +2059,10 @@ done:
g_set_error(&error, PCMK__RC_ERROR, rc,
"Error performing operation: %s", pcmk_rc_str(rc));
}
+ }
- if (exit_code == CRM_EX_OK) {
- exit_code = pcmk_rc2exitc(rc);
- }
+ if (exit_code == CRM_EX_OK) {
+ exit_code = pcmk_rc2exitc(rc);
}
g_free(options.host_uname);
--
1.8.3.1

760
SOURCES/039-crm_mon.patch Normal file
View File

@ -0,0 +1,760 @@
From bd4f396f267d8ef8f9c9bcbf286a77dc78d4e1b0 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 2 Mar 2021 10:26:13 -0500
Subject: [PATCH 1/3] Med: Generate xml/crm_mon.rng from the contents of
xml/crm_mon*.
This prevents the version reference in it from getting out of sync.
See: rhbz#1931332
---
xml/Makefile.am | 28 +++++++++++++++++++++++-----
xml/crm_mon.rng | 16 ----------------
3 files changed, 24 insertions(+), 21 deletions(-)
delete mode 100644 xml/crm_mon.rng
diff --git a/xml/Makefile.am b/xml/Makefile.am
index cb6cfa0..c52b968 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -76,22 +76,24 @@ CIB_abs_xsl = $(abs_srcdir)/upgrade-1.3.xsl \
$(abs_srcdir)/upgrade-2.10.xsl \
$(wildcard $(abs_srcdir)/upgrade-*enter.xsl) \
$(wildcard $(abs_srcdir)/upgrade-*leave.xsl)
-MON_abs_files = $(abs_srcdir)/crm_mon.rng
+MON_abs_files = $(abs_srcdir)/crm_mon.rng
API_files = $(foreach base,$(API_base),$(wildcard $(srcdir)/api/$(base)*.rng))
CIB_files = $(foreach base,$(CIB_base),$(wildcard $(srcdir)/$(base).rng $(srcdir)/$(base)-*.rng))
CIB_xsl = $(srcdir)/upgrade-1.3.xsl \
$(srcdir)/upgrade-2.10.xsl \
$(wildcard $(srcdir)/upgrade-*enter.xsl) \
$(wildcard $(srcdir)/upgrade-*leave.xsl)
-MON_files = $(srcdir)/crm_mon.rng
+MON_files = $(srcdir)/crm_mon.rng
# Sorted lists of all numeric schema versions
API_numeric_versions = $(call numeric_versions,${API_files})
CIB_numeric_versions = $(call numeric_versions,${CIB_files})
+MON_numeric_versions = $(call numeric_versions,$(wildcard $(srcdir)/api/crm_mon*.rng))
# The highest numeric schema version
API_max ?= $(lastword $(API_numeric_versions))
CIB_max ?= $(lastword $(CIB_numeric_versions))
+MON_max ?= $(lastword $(MON_numeric_versions))
# Sorted lists of all schema versions (including "next")
API_versions = next $(API_numeric_versions)
@@ -100,11 +102,12 @@ CIB_versions = next $(CIB_numeric_versions)
# Build tree locations of static schema files and transforms (for VPATH builds)
API_build_copies = $(foreach f,$(API_abs_files),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
CIB_build_copies = $(foreach f,$(CIB_abs_files) $(CIB_abs_xsl),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
-MON_build_copies = $(foreach f,$(MON_abs_files),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
+MON_build_copies = $(foreach f,$(MON_abs_files),$(subst $(abs_srcdir),$(abs_builddir),$(f)))
# Dynamically generated schema files
API_generated = api/api-result.rng $(foreach base,$(API_versions),api/api-result-$(base).rng)
CIB_generated = pacemaker.rng $(foreach base,$(CIB_versions),pacemaker-$(base).rng) versions.rng
+MON_generated = crm_mon.rng
CIB_version_pairs = $(call version_pairs,${CIB_numeric_versions})
CIB_version_pairs_cnt = $(words ${CIB_version_pairs})
@@ -112,10 +115,10 @@ CIB_version_pairs_last = $(call version_pairs_last,${CIB_version_pairs_cnt},${C
dist_API_DATA = $(API_files)
dist_CIB_DATA = $(CIB_files) $(CIB_xsl)
-dist_MON_DATA = $(MON_files)
nodist_API_DATA = $(API_generated)
nodist_CIB_DATA = $(CIB_generated)
+nodist_MON_DATA = $(MON_generated)
EXTRA_DIST = Readme.md \
best-match.sh \
@@ -162,6 +165,21 @@ api/api-result-%.rng: $(API_build_copies) best-match.sh Makefile.am
$(AM_V_at)echo ' </start>' >> $@
$(AM_V_SCHEMA)echo '</grammar>' >> $@
+crm_mon.rng: api/crm_mon-$(MON_max).rng
+ $(AM_V_at)echo '<?xml version="1.0" encoding="UTF-8"?>' > $@
+ $(AM_V_at)echo '<grammar xmlns="http://relaxng.org/ns/structure/1.0"' >> $@
+ $(AM_V_at)echo ' datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">' >> $@
+ $(AM_V_at)echo ' <start>' >> $@
+ $(AM_V_at)echo ' <ref name="element-crm_mon-old"/>' >> $@
+ $(AM_V_at)echo ' </start>' >> $@
+ $(AM_V_at)echo ' <define name="element-crm_mon-old">' >> $@
+ $(AM_V_at)echo ' <element name="crm_mon">' >> $@
+ $(AM_V_at)echo ' <attribute name="version"> <text/> </attribute>' >> $@
+ $(AM_V_at)echo ' <externalRef href="$(<)" />' >> $@
+ $(AM_V_at)echo ' </element>' >> $@
+ $(AM_V_at)echo ' </define>' >> $@
+ $(AM_V_SCHEMA)echo '</grammar>' >> $@
+
# Dynamically generated top-level CIB schema
pacemaker.rng: pacemaker-$(CIB_max).rng
$(AM_V_SCHEMA)cp $(top_builddir)/xml/$< $@
@@ -256,7 +274,7 @@ fulldiff: best-match.sh
@echo "# Comparing all changes across all the subsequent increments"
$(call version_diff,${CIB_version_pairs})
-CLEANFILES = $(API_generated) $(CIB_generated)
+CLEANFILES = $(API_generated) $(CIB_generated) $(MON_generated)
clean-local:
if [ "x$(srcdir)" != "x$(builddir)" ]; then \
diff --git a/xml/crm_mon.rng b/xml/crm_mon.rng
deleted file mode 100644
index be87fba..0000000
--- a/xml/crm_mon.rng
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0"
- datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
-
- <start>
- <ref name="element-crm_mon-old"/>
- </start>
-
- <define name="element-crm_mon-old">
- <element name="crm_mon">
- <attribute name="version"> <text/> </attribute>
- <externalRef href="api/crm_mon-2.3.rng" />
- </element>
- </define>
-
-</grammar>
--
1.8.3.1
From 0cbc5b0a66ac0bf206ff45f36206253a60620e07 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 2 Mar 2021 10:53:17 -0500
Subject: [PATCH 2/3] Med: Copy crm_mon.rng and crm_resource.rng in preparation
for updates.
See: rhbz#1931332
---
xml/api/crm_mon-2.7.rng | 311 +++++++++++++++++++++++++++++++++++++++++++
xml/api/crm_resource-2.7.rng | 238 +++++++++++++++++++++++++++++++++
2 files changed, 549 insertions(+)
create mode 100644 xml/api/crm_mon-2.7.rng
create mode 100644 xml/api/crm_resource-2.7.rng
diff --git a/xml/api/crm_mon-2.7.rng b/xml/api/crm_mon-2.7.rng
new file mode 100644
index 0000000..88973a4
--- /dev/null
+++ b/xml/api/crm_mon-2.7.rng
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="element-crm-mon"/>
+ </start>
+
+ <define name="element-crm-mon">
+ <optional>
+ <ref name="element-summary" />
+ </optional>
+ <optional>
+ <ref name="nodes-list" />
+ </optional>
+ <optional>
+ <ref name="resources-list" />
+ </optional>
+ <optional>
+ <ref name="node-attributes-list" />
+ </optional>
+ <optional>
+ <ref name="node-history-list" />
+ </optional>
+ <optional>
+ <ref name="failures-list" />
+ </optional>
+ <optional>
+ <ref name="fence-event-list" />
+ </optional>
+ <optional>
+ <ref name="tickets-list" />
+ </optional>
+ <optional>
+ <ref name="bans-list" />
+ </optional>
+ </define>
+
+ <define name="element-summary">
+ <element name="summary">
+ <optional>
+ <element name="stack">
+ <attribute name="type"> <text /> </attribute>
+ </element>
+ </optional>
+ <optional>
+ <element name="current_dc">
+ <attribute name="present"> <data type="boolean" /> </attribute>
+ <optional>
+ <group>
+ <attribute name="version"> <text /> </attribute>
+ <attribute name="name"> <text /> </attribute>
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="with_quorum"> <data type="boolean" /> </attribute>
+ </group>
+ </optional>
+ </element>
+ </optional>
+ <optional>
+ <element name="last_update">
+ <attribute name="time"> <text /> </attribute>
+ </element>
+ <element name="last_change">
+ <attribute name="time"> <text /> </attribute>
+ <attribute name="user"> <text /> </attribute>
+ <attribute name="client"> <text /> </attribute>
+ <attribute name="origin"> <text /> </attribute>
+ </element>
+ </optional>
+ <optional>
+ <element name="nodes_configured">
+ <attribute name="number"> <data type="nonNegativeInteger" /> </attribute>
+ </element>
+ <element name="resources_configured">
+ <attribute name="number"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="disabled"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="blocked"> <data type="nonNegativeInteger" /> </attribute>
+ </element>
+ </optional>
+ <optional>
+ <element name="cluster_options">
+ <attribute name="stonith-enabled"> <data type="boolean" /> </attribute>
+ <attribute name="symmetric-cluster"> <data type="boolean" /> </attribute>
+ <attribute name="no-quorum-policy"> <text /> </attribute>
+ <attribute name="maintenance-mode"> <data type="boolean" /> </attribute>
+ <attribute name="stop-all-resources"> <data type="boolean" /> </attribute>
+ </element>
+ </optional>
+ </element>
+ </define>
+
+ <define name="resources-list">
+ <element name="resources">
+ <zeroOrMore>
+ <externalRef href="resources-2.4.rng" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="nodes-list">
+ <element name="nodes">
+ <zeroOrMore>
+ <ref name="element-full-node" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="node-attributes-list">
+ <element name="node_attributes">
+ <zeroOrMore>
+ <ref name="element-node-with-attributes" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="node-history-list">
+ <element name="node_history">
+ <zeroOrMore>
+ <ref name="element-node-history" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="failures-list">
+ <element name="failures">
+ <zeroOrMore>
+ <ref name="element-failure" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="fence-event-list">
+ <element name="fence_history">
+ <optional>
+ <attribute name="status"> <data type="integer" /> </attribute>
+ </optional>
+ <zeroOrMore>
+ <externalRef href="fence-event-2.0.rng" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="tickets-list">
+ <element name="tickets">
+ <zeroOrMore>
+ <ref name="element-ticket" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="bans-list">
+ <element name="bans">
+ <zeroOrMore>
+ <ref name="element-ban" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-full-node">
+ <element name="node">
+ <attribute name="name"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="online"> <data type="boolean" /> </attribute>
+ <attribute name="standby"> <data type="boolean" /> </attribute>
+ <attribute name="standby_onfail"> <data type="boolean" /> </attribute>
+ <attribute name="maintenance"> <data type="boolean" /> </attribute>
+ <attribute name="pending"> <data type="boolean" /> </attribute>
+ <attribute name="unclean"> <data type="boolean" /> </attribute>
+ <attribute name="shutdown"> <data type="boolean" /> </attribute>
+ <attribute name="expected_up"> <data type="boolean" /> </attribute>
+ <attribute name="is_dc"> <data type="boolean" /> </attribute>
+ <attribute name="resources_running"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="type">
+ <choice>
+ <value>unknown</value>
+ <value>member</value>
+ <value>remote</value>
+ <value>ping</value>
+ </choice>
+ </attribute>
+ <optional>
+ <!-- for virtualized pacemaker_remote nodes, crm_mon 1.1.13 uses
+ "container_id" while later versions use "id_as_resource" -->
+ <choice>
+ <attribute name="container_id"> <text/> </attribute>
+ <attribute name="id_as_resource"> <text/> </attribute>
+ </choice>
+ </optional>
+ <externalRef href="resources-2.4.rng" />
+ </element>
+ </define>
+
+ <define name="element-node-with-attributes">
+ <element name="node">
+ <attribute name="name"> <text /> </attribute>
+ <zeroOrMore>
+ <element name="attribute">
+ <attribute name="name"> <text /> </attribute>
+ <attribute name="value"> <text /> </attribute>
+ <optional>
+ <attribute name="expected"> <data type="nonNegativeInteger" /> </attribute>
+ </optional>
+ </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-node-history">
+ <element name="node">
+ <attribute name="name"> <text /> </attribute>
+ <zeroOrMore>
+ <ref name="element-resource-history" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-resource-history">
+ <element name="resource_history">
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="orphan"> <data type="boolean" /> </attribute>
+ <optional>
+ <group>
+ <attribute name="migration-threshold"> <data type="nonNegativeInteger" /> </attribute>
+ <optional>
+ <attribute name="fail-count"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="last-failure"> <text /> </attribute>
+ </optional>
+ </group>
+ </optional>
+ <zeroOrMore>
+ <ref name="element-operation-history" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="element-operation-history">
+ <element name="operation_history">
+ <attribute name="call"> <text /> </attribute>
+ <attribute name="task"> <text /> </attribute>
+ <optional>
+ <attribute name="interval"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="last-rc-change"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="last-run"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="exec-time"> <text /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="queue-time"> <text /> </attribute>
+ </optional>
+ <attribute name="rc"> <data type="integer" /> </attribute>
+ <attribute name="rc_text"> <text /> </attribute>
+ </element>
+ </define>
+
+ <define name="element-failure">
+ <element name="failure">
+ <choice>
+ <attribute name="op_key"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ </choice>
+ <attribute name="node"> <text /> </attribute>
+ <attribute name="exitstatus"> <text /> </attribute>
+ <attribute name="exitreason"> <text /> </attribute>
+ <attribute name="exitcode"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="status"> <text /> </attribute>
+ <optional>
+ <group>
+ <attribute name="last-rc-change"> <text /> </attribute>
+ <attribute name="queued"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="exec"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="interval"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="task"> <text /> </attribute>
+ </group>
+ </optional>
+ </element>
+ </define>
+
+ <define name="element-ticket">
+ <element name="ticket">
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="status">
+ <choice>
+ <value>granted</value>
+ <value>revoked</value>
+ </choice>
+ </attribute>
+ <attribute name="standby"> <data type="boolean" /> </attribute>
+ <optional>
+ <attribute name="last-granted"> <text /> </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="element-ban">
+ <element name="ban">
+ <attribute name="id"> <text /> </attribute>
+ <attribute name="resource"> <text /> </attribute>
+ <attribute name="node"> <text /> </attribute>
+ <attribute name="weight"> <data type="integer" /> </attribute>
+ <attribute name="master_only"> <data type="boolean" /> </attribute>
+ </element>
+ </define>
+</grammar>
diff --git a/xml/api/crm_resource-2.7.rng b/xml/api/crm_resource-2.7.rng
new file mode 100644
index 0000000..b49e24c
--- /dev/null
+++ b/xml/api/crm_resource-2.7.rng
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+ <start>
+ <ref name="element-crm-resource"/>
+ </start>
+
+ <define name="element-crm-resource">
+ <choice>
+ <ref name="agents-list" />
+ <ref name="alternatives-list" />
+ <ref name="constraints-list" />
+ <externalRef href="generic-list-2.4.rng"/>
+ <element name="metadata"> <text/> </element>
+ <ref name="locate-list" />
+ <ref name="operations-list" />
+ <ref name="providers-list" />
+ <ref name="reasons-list" />
+ <ref name="resource-check" />
+ <ref name="resource-config" />
+ <ref name="resources-list" />
+ </choice>
+ </define>
+
+ <define name="agents-list">
+ <element name="agents">
+ <attribute name="standard"> <text/> </attribute>
+ <optional>
+ <attribute name="provider"> <text/> </attribute>
+ </optional>
+ <zeroOrMore>
+ <element name="agent"> <text/> </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="alternatives-list">
+ <element name="providers">
+ <attribute name="for"> <text/> </attribute>
+ <zeroOrMore>
+ <element name="provider"> <text/> </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="constraints-list">
+ <element name="constraints">
+ <interleave>
+ <zeroOrMore>
+ <ref name="rsc-location" />
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="rsc-colocation" />
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+
+ <define name="locate-list">
+ <element name="nodes">
+ <attribute name="resource"> <text/> </attribute>
+ <zeroOrMore>
+ <element name="node">
+ <optional>
+ <attribute name="state"><value>promoted</value></attribute>
+ </optional>
+ <text/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="rsc-location">
+ <element name="rsc_location">
+ <attribute name="node"> <text/> </attribute>
+ <attribute name="rsc"> <text/> </attribute>
+ <attribute name="id"> <text/> </attribute>
+ <externalRef href="../score.rng"/>
+ </element>
+ </define>
+
+ <define name="operations-list">
+ <element name="operations">
+ <oneOrMore>
+ <ref name="element-operation-list" />
+ </oneOrMore>
+ </element>
+ </define>
+
+ <define name="providers-list">
+ <element name="providers">
+ <attribute name="standard"> <value>ocf</value> </attribute>
+ <optional>
+ <attribute name="agent"> <text/> </attribute>
+ </optional>
+ <zeroOrMore>
+ <element name="provider"> <text/> </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="reasons-list">
+ <choice>
+ <ref name="no-resource-or-uname"/>
+ <ref name="resource-and-uname"/>
+ <ref name="no-resource-but-uname"/>
+ <ref name="resource-but-no-uname"/>
+ </choice>
+ </define>
+
+ <define name="no-resource-or-uname">
+ <element name="reason">
+ <element name="resources">
+ <zeroOrMore>
+ <element name="resource">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </element>
+ </define>
+
+ <define name="resource-and-uname">
+ <element name="reason">
+ <attribute name="running_on"> <text/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </define>
+
+ <define name="no-resource-but-uname">
+ <element name="reason">
+ <element name="resources">
+ <zeroOrMore>
+ <element name="resource">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <attribute name="host"> <text/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </element>
+ </define>
+
+ <define name="resource-but-no-uname">
+ <element name="reason">
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <ref name="resource-check"/>
+ </element>
+ </define>
+
+ <define name="resource-config">
+ <element name="resource_config">
+ <externalRef href="resources-2.4.rng" />
+ <element name="xml"> <text/> </element>
+ </element>
+ </define>
+
+ <define name="resource-check">
+ <element name="check">
+ <attribute name="id"> <text/> </attribute>
+ <optional>
+ <choice>
+ <attribute name="remain_stopped"><value>true</value></attribute>
+ <attribute name="promotable"><value>false</value></attribute>
+ </choice>
+ </optional>
+ <optional>
+ <attribute name="unmanaged"><value>true</value></attribute>
+ </optional>
+ <optional>
+ <attribute name="locked-to"> <text/> </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="resources-list">
+ <element name="resources">
+ <zeroOrMore>
+ <externalRef href="resources-2.4.rng" />
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="rsc-colocation">
+ <element name="rsc_colocation">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="rsc"> <text/> </attribute>
+ <attribute name="with-rsc"> <text/> </attribute>
+ <externalRef href="../score.rng"/>
+ <optional>
+ <attribute name="node-attribute"> <text/> </attribute>
+ </optional>
+ <optional>
+ <attribute name="rsc-role">
+ <ref name="attribute-roles"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="with-rsc-role">
+ <ref name="attribute-roles"/>
+ </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="element-operation-list">
+ <element name="operation">
+ <optional>
+ <group>
+ <attribute name="rsc"> <text/> </attribute>
+ <attribute name="agent"> <text/> </attribute>
+ </group>
+ </optional>
+ <attribute name="op"> <text/> </attribute>
+ <attribute name="node"> <text/> </attribute>
+ <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="rc"> <data type="nonNegativeInteger" /> </attribute>
+ <optional>
+ <attribute name="last-rc-change"> <text/> </attribute>
+ <attribute name="exec-time"> <data type="nonNegativeInteger" /> </attribute>
+ </optional>
+ <attribute name="status"> <text/> </attribute>
+ </element>
+ </define>
+
+ <define name="attribute-roles">
+ <choice>
+ <value>Stopped</value>
+ <value>Started</value>
+ <value>Master</value>
+ <value>Slave</value>
+ </choice>
+ </define>
+</grammar>
--
1.8.3.1
From 9b6ee6eb5aa1008beebae9d9f6c3889c81c3bbb6 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 2 Mar 2021 10:58:15 -0500
Subject: [PATCH 3/3] Med: Change the schema type of 'expected' and 'call' to
integer.
Regression in 2.0.3.
See: rhbz#1931332
---
xml/api/crm_mon-2.7.rng | 4 ++--
xml/api/crm_resource-2.7.rng | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/xml/api/crm_mon-2.7.rng b/xml/api/crm_mon-2.7.rng
index 88973a4..8e6792b 100644
--- a/xml/api/crm_mon-2.7.rng
+++ b/xml/api/crm_mon-2.7.rng
@@ -198,7 +198,7 @@
<attribute name="name"> <text /> </attribute>
<attribute name="value"> <text /> </attribute>
<optional>
- <attribute name="expected"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="expected"> <data type="integer" /> </attribute>
</optional>
</element>
</zeroOrMore>
@@ -269,7 +269,7 @@
<attribute name="exitstatus"> <text /> </attribute>
<attribute name="exitreason"> <text /> </attribute>
<attribute name="exitcode"> <data type="nonNegativeInteger" /> </attribute>
- <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="call"> <data type="integer" /> </attribute>
<attribute name="status"> <text /> </attribute>
<optional>
<group>
diff --git a/xml/api/crm_resource-2.7.rng b/xml/api/crm_resource-2.7.rng
index b49e24c..8e386db 100644
--- a/xml/api/crm_resource-2.7.rng
+++ b/xml/api/crm_resource-2.7.rng
@@ -217,7 +217,7 @@
</optional>
<attribute name="op"> <text/> </attribute>
<attribute name="node"> <text/> </attribute>
- <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+ <attribute name="call"> <data type="integer" /> </attribute>
<attribute name="rc"> <data type="nonNegativeInteger" /> </attribute>
<optional>
<attribute name="last-rc-change"> <text/> </attribute>
--
1.8.3.1

View File

@ -0,0 +1,36 @@
From 34b2d8ab82dcdf49535c74e6a580240455498759 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Wed, 2 Dec 2020 22:51:33 +0100
Subject: [PATCH] default to syncing with sbd
---
lib/common/watchdog.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/lib/common/watchdog.c b/lib/common/watchdog.c
index 03ee7f1..bf5df18 100644
--- a/lib/common/watchdog.c
+++ b/lib/common/watchdog.c
@@ -244,12 +244,16 @@ pcmk__get_sbd_timeout(void)
bool
pcmk__get_sbd_sync_resource_startup(void)
{
- static bool sync_resource_startup = false;
+ static bool sync_resource_startup = true; // default overruled by env
static bool checked_sync_resource_startup = false;
if (!checked_sync_resource_startup) {
- sync_resource_startup =
- crm_is_true(getenv("SBD_SYNC_RESOURCE_STARTUP"));
+ gboolean ret = FALSE;
+ const char *s = getenv("SBD_SYNC_RESOURCE_STARTUP");
+
+ if ((s != NULL) && (crm_str_to_boolean(s, &ret) > 0)) {
+ sync_resource_startup = ret;
+ }
checked_sync_resource_startup = true;
}
--
1.8.3.1

View File

@ -22,11 +22,11 @@
## Upstream pacemaker version, and its package version (specversion
## can be incremented to build packages reliably considered "newer"
## than previously built packages with the same pcmkversion)
%global pcmkversion 2.0.4
%global specversion 6
%global pcmkversion 2.0.5
%global specversion 9
## Upstream commit (full commit ID, abbreviated commit ID, or tag) to build
%global commit 2deceaa3ae1fbadd844f5c5b47fd33129fa2c227
%global commit ba59be71228fed04f78ab374dfac748d314d0e89
## Since git v2.11, the extent of abbreviation is autoscaled by default
## (used to be constant of 7), so we need to convey it for non-tags, too.
%global commit_abbrev 7
@ -214,7 +214,6 @@
}
%endif
# Keep sane profiling data if requested
%if %{with profiling}
@ -227,14 +226,14 @@
Name: pacemaker
Summary: Scalable High-Availability cluster resource manager
Version: %{pcmkversion}
Release: %{pcmk_release}%{?dist}.2
Release: %{pcmk_release}%{?dist}
%if %{defined _unitdir}
License: GPLv2+ and LGPLv2+
%else
# initscript is Revised BSD
License: GPLv2+ and LGPLv2+ and BSD
%endif
Url: http://www.clusterlabs.org
Url: https://www.clusterlabs.org/
Group: System Environment/Daemons
# Example: https://codeload.github.com/ClusterLabs/pacemaker/tar.gz/e91769e
@ -249,27 +248,48 @@ Source0: https://codeload.github.com/%{github_owner}/%{name}/tar.gz/%{arch
Source1: nagios-agents-metadata-%{nagios_hash}.tar.gz
# upstream commits
Patch1: 001-rules.patch
Patch2: 002-demote.patch
Patch3: 003-trace.patch
Patch4: 004-test.patch
Patch5: 005-sysconfig.patch
Patch6: 006-ipc_refactor.patch
Patch7: 007-ipc_model.patch
Patch8: 008-crm_node.patch
Patch9: 009-timeout-log.patch
Patch10: 010-crm_mon.patch
Patch11: 011-cts.patch
Patch12: 012-ipc_fix.patch
Patch13: 013-pacemakerd.patch
Patch14: 014-sbd.patch
Patch15: 015-cibsecret.patch
Patch16: 016-CVE-2020-25654.patch
Patch17: 017-promotion.patch
Patch18: 018-api-schema.patch
Patch1: 001-feature-set.patch
Patch2: 002-feature-set.patch
Patch3: 003-feature-set.patch
Patch4: 004-feature-set.patch
Patch5: 005-feature-set.patch
Patch6: 006-digests.patch
Patch7: 007-feature-set.patch
Patch8: 008-digests.patch
Patch9: 009-digests.patch
Patch10: 010-feature-set.patch
Patch11: 011-feature-set.patch
Patch12: 012-feature-set.patch
Patch13: 013-feature-set.patch
Patch14: 014-feature-set.patch
Patch15: 015-feature-set.patch
Patch16: 016-feature-set.patch
Patch17: 017-feature-set.patch
Patch18: 018-rhbz1907726.patch
Patch19: 019-rhbz1371576.patch
Patch20: 020-rhbz1872376.patch
Patch21: 021-rhbz1872376.patch
Patch22: 022-rhbz1872376.patch
Patch23: 023-rhbz1872376.patch
Patch24: 024-rhbz1371576.patch
Patch25: 025-feature-set.patch
Patch26: 026-tests.patch
Patch27: 027-crm_mon.patch
Patch28: 028-crm_mon.patch
Patch29: 029-crm_mon.patch
Patch30: 030-crmadmin.patch
Patch31: 031-cibsecret.patch
Patch32: 032-rhbz1898457.patch
Patch33: 033-cibsecret.patch
Patch34: 034-crm_mon.patch
Patch35: 035-crm_mon.patch
Patch36: 036-crm_resource.patch
Patch37: 037-scheduler.patch
Patch38: 038-feature-set.patch
Patch39: 039-crm_mon.patch
# downstream-only commits
#Patch100: xxx.patch
Patch100: 100-default-to-syncing-with-sbd.patch
Requires: resource-agents
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
@ -383,7 +403,10 @@ Group: System Environment/Daemons
Requires(pre): %{pkgname_shadow_utils}
Requires: %{name}-schemas = %{version}-%{release}
# sbd 1.4.0+ supports the libpe_status API for pe_working_set_t
Conflicts: sbd < 1.4.0
# sbd 1.4.2+ supports startup/shutdown handshake via pacemakerd-api
# and handshake defaults to enabled with rhel-builds
# applying 100-default-to-syncing-with-sbd.patch
Conflicts: sbd < 1.4.2
%description -n %{pkgname_pcmk_libs}
Pacemaker is an advanced, scalable High-Availability cluster resource
@ -528,9 +551,6 @@ monitor resources.
%build
# Early versions of autotools (e.g. RHEL <= 5) do not support --docdir
export docdir=%{pcmk_docdir}
export systemdsystemunitdir=%{?_unitdir}%{!?_unitdir:no}
# RHEL changes pacemaker's concurrent-fencing default to true
@ -964,15 +984,75 @@ exit 0
%license %{nagios_name}-%{nagios_hash}/COPYING
%changelog
* Thu Mar 4 2021 Ken Gaillot <kgaillot@redhat.com> - 2.0.4-6.2
- Avoid situation where promotion is not scheduled until next transition
* Tue Mar 2 2021 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-9
- Avoid pcs failures when Pacemaker records negative call ID in history
- Resolves: rhbz1935240
- Resolves: rhbz1939533
- Resolves: rhbz1931332
* Mon Oct 26 2020 Ken Gaillot <kgaillot@redhat.com> - 2.0.4-6.1
- Prevent users from bypassing ACLs by using IPC directly (CVE-2020-25654)
- Resolves: rhbz1891528
* Mon Feb 15 2021 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-8
- Route cancellations through correct node when remote connection is moving
- Resolves: rhbz1928762
* Fri Feb 12 2021 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-7
- Do not introduce regression in crm_resource --locate
- Resolves: rhbz1925681
* Wed Feb 3 2021 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-6
- crm_mon --daemonize should reconnect if cluster restarts
- crm_mon should show more informative messages when cluster is starting
- crm_mon should show rest of status if fencing history is unavailable
- cibsecret now works on remote nodes (as long as name can be reached via ssh)
- Stop remote nodes correctly when connection history is later than node history
- Resolves: rhbz1466875
- Resolves: rhbz1872490
- Resolves: rhbz1880426
- Resolves: rhbz1881537
- Resolves: rhbz1898457
* Thu Jan 14 2021 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-5
- Allow non-critical resources that stop rather than make another resource move
- Support crm_resource --digests option for showing operation digests
- Clean-up of all resources should work from remote nodes
- Resolves: rhbz1371576
- Resolves: rhbz1872376
- Resolves: rhbz1907726
* Wed Dec 2 2020 Klaus Wenninger <kwenning@redhat.com> - 2.0.5-4
- Rebase on upstream 2.0.5 release
- Make waiting to be pinged by sbd via pacemakerd-api the default
- Resolves: rhbz1885645
- Resolves: rhbz1873138
* Wed Nov 18 2020 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-3
- Rebase on upstream 2.0.5-rc3 release
- Resolves: rhbz1885645
* Wed Oct 28 2020 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-2
- Rebase on upstream 2.0.5-rc2 release
- Prevent ACL bypass (CVE-2020-25654)
- Resolves: rhbz1885645
- Resolves: rhbz1889582
* Tue Oct 20 2020 Ken Gaillot <kgaillot@redhat.com> - 2.0.5-1
- crm_mon --resource option to filter output by resource
- Avoid filling /dev/shm after frequent corosync errors
- Allow configurable permissions for log files
- Ensure ACL write permission always supersedes read
- Use fence device monitor timeout for starts and probes
- Allow type="integer" in rule expressions
- Avoid error messages when running crm_node inside bundles
- Avoid situation where promotion is not scheduled until next transition
- crm_mon should show more clearly when an entire group is disabled
- Rebase on upstream 2.0.5-rc1 release
- Resolves: rhbz1300597
- Resolves: rhbz1614166
- Resolves: rhbz1647136
- Resolves: rhbz1833173
- Resolves: rhbz1856015
- Resolves: rhbz1866573
- Resolves: rhbz1874391
- Resolves: rhbz1835717
- Resolves: rhbz1748139
- Resolves: rhbz1885645
* Thu Aug 20 2020 Ken Gaillot <kgaillot@redhat.com> - 2.0.4-6
- Fix cibsecret bug when node name is different from hostname