From 7c35387a9896cb968cf4087b5cbed94af44e1ea5 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Fri, 14 May 2021 12:03:46 -0400 Subject: [PATCH 1/5] Feature: daemons: Convert pacemakerd to formatted output. The main purpose of this is to finish getting pacemakerd moved off the existing command line handling code (pcmk__cli_help in particular) so that code can eventually be deprecated or removed. pacemakerd itself does fairly little printing. --- daemons/pacemakerd/pacemakerd.c | 58 ++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c index ce194bf..bd59729 100644 --- a/daemons/pacemakerd/pacemakerd.c +++ b/daemons/pacemakerd/pacemakerd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,14 @@ struct { gboolean standby; } options; +static pcmk__output_t *out = NULL; + +static pcmk__supported_format_t formats[] = { + PCMK__SUPPORTED_FORMAT_NONE, + PCMK__SUPPORTED_FORMAT_TEXT, + { NULL, NULL, NULL } +}; + static gboolean pid_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **err) { return TRUE; @@ -1167,10 +1176,10 @@ pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api, } static GOptionContext * -build_arg_context(pcmk__common_args_t *args) { +build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { GOptionContext *context = NULL; - context = pcmk__build_arg_context(args, NULL, NULL, NULL); + context = pcmk__build_arg_context(args, "text", group, NULL); pcmk__add_main_args(context, entries); return context; } @@ -1182,9 +1191,11 @@ main(int argc, char **argv) GError *error = NULL; + int rc = pcmk_rc_ok; + GOptionGroup *output_group = NULL; pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY); gchar **processed_args = pcmk__cmdline_preproc(argv, "p"); - GOptionContext *context = build_arg_context(args); + GOptionContext *context = build_arg_context(args, &output_group); bool old_instance_connected = false; @@ -1195,23 +1205,30 @@ main(int argc, char **argv) mainloop_add_signal(SIGHUP, pcmk_ignore); mainloop_add_signal(SIGQUIT, pcmk_sigquit); + pcmk__register_formats(output_group, formats); if (!g_option_context_parse_strv(context, &processed_args, &error)) { exit_code = CRM_EX_USAGE; goto done; } + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + if (rc != pcmk_rc_ok) { + 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; + } + if (options.features) { - printf("Pacemaker %s (Build: %s)\n Supporting v%s: %s\n", PACEMAKER_VERSION, BUILD_VERSION, - CRM_FEATURE_SET, CRM_FEATURES); + out->info(out, "Pacemaker %s (Build: %s)\n Supporting v%s: %s", PACEMAKER_VERSION, + BUILD_VERSION, CRM_FEATURE_SET, CRM_FEATURES); exit_code = CRM_EX_OK; goto done; } if (args->version) { - g_strfreev(processed_args); - pcmk__free_arg_context(context); - /* FIXME: When pacemakerd is converted to use formatted output, this can go. */ - pcmk__cli_help('v', CRM_EX_USAGE); + out->version(out, false); + goto done; } setenv("LC_ALL", "C", 1); @@ -1248,6 +1265,13 @@ main(int argc, char **argv) crm_ipc_close(old_instance); crm_ipc_destroy(old_instance); + /* Don't allow any accidental output after this point. */ + if (out != NULL) { + out->finish(out, exit_code, true, NULL); + pcmk__output_free(out); + out = NULL; + } + #ifdef SUPPORT_COROSYNC if (mcp_read_config() == FALSE) { exit_code = CRM_EX_UNAVAILABLE; @@ -1333,6 +1357,11 @@ done: g_strfreev(processed_args); pcmk__free_arg_context(context); - pcmk__output_and_clear_error(error, NULL); + pcmk__output_and_clear_error(error, out); + + if (out != NULL) { + out->finish(out, exit_code, true, NULL); + pcmk__output_free(out); + } crm_exit(exit_code); } -- 1.8.3.1 From 35e6da64381fcb092d81ce16835cc28670b077cb Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Mon, 17 May 2021 10:04:04 -0400 Subject: [PATCH 2/5] Features: daemons: Output the pacemakerd feature list in XML. --- daemons/pacemakerd/pacemakerd.c | 45 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c index bd59729..93cf743 100644 --- a/daemons/pacemakerd/pacemakerd.c +++ b/daemons/pacemakerd/pacemakerd.c @@ -43,6 +43,42 @@ static pcmk__output_t *out = NULL; static pcmk__supported_format_t formats[] = { PCMK__SUPPORTED_FORMAT_NONE, PCMK__SUPPORTED_FORMAT_TEXT, + PCMK__SUPPORTED_FORMAT_XML, + { NULL, NULL, NULL } +}; + +static int +pacemakerd_features(pcmk__output_t *out, va_list args) { + out->info(out, "Pacemaker %s (Build: %s)\n Supporting v%s: %s", PACEMAKER_VERSION, + BUILD_VERSION, CRM_FEATURE_SET, CRM_FEATURES); + return pcmk_rc_ok; +} + +static int +pacemakerd_features_xml(pcmk__output_t *out, va_list args) { + gchar **feature_list = g_strsplit(CRM_FEATURES, " ", 0); + + pcmk__output_xml_create_parent(out, "pacemakerd", + "version", PACEMAKER_VERSION, + "build", BUILD_VERSION, + "feature_set", CRM_FEATURE_SET, + NULL); + out->begin_list(out, NULL, NULL, "features"); + + for (char **s = feature_list; *s != NULL; s++) { + pcmk__output_create_xml_text_node(out, "feature", *s); + } + + out->end_list(out); + + g_strfreev(feature_list); + return pcmk_rc_ok; +} + +static pcmk__message_entry_t fmt_functions[] = { + { "features", "default", pacemakerd_features }, + { "features", "xml", pacemakerd_features_xml }, + { NULL, NULL, NULL } }; @@ -200,7 +236,7 @@ static GOptionContext * build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { GOptionContext *context = NULL; - context = pcmk__build_arg_context(args, "text", group, NULL); + context = pcmk__build_arg_context(args, "text (default), xml", group, NULL); pcmk__add_main_args(context, entries); return context; } @@ -241,9 +277,12 @@ main(int argc, char **argv) goto done; } + pcmk__force_args(context, &error, "%s --xml-simple-list", g_get_prgname()); + + pcmk__register_messages(out, fmt_functions); + if (options.features) { - out->info(out, "Pacemaker %s (Build: %s)\n Supporting v%s: %s", PACEMAKER_VERSION, - BUILD_VERSION, CRM_FEATURE_SET, CRM_FEATURES); + out->message(out, "features"); exit_code = CRM_EX_OK; goto done; } -- 1.8.3.1 From 5b7f5eb35b025b59805cf3c7c3dcb6a3cf4b71b3 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Mon, 17 May 2021 11:09:53 -0400 Subject: [PATCH 3/5] Low: daemons: Conditionally enable logging in pacemakerd. If we're doing an interactive command-line call, use pcmk__cli_init_logging. At the moment, all command line calls except for --shutdown do their work before logging would even come up, so we really only need to do this for --shutdown. If we're doing a daemon call, use crm_log_init. --- daemons/pacemakerd/pacemakerd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c index 93cf743..c20bde7 100644 --- a/daemons/pacemakerd/pacemakerd.c +++ b/daemons/pacemakerd/pacemakerd.c @@ -296,8 +296,11 @@ main(int argc, char **argv) pcmk__set_env_option("mcp", "true"); - pcmk__cli_init_logging("pacemakerd", args->verbosity); - crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE); + if (options.shutdown) { + pcmk__cli_init_logging("pacemakerd", args->verbosity); + } else { + crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE); + } crm_debug("Checking for existing Pacemaker instance"); old_instance = crm_ipc_new(CRM_SYSTEM_MCP, 0); -- 1.8.3.1 From 2393362bb7489e86d937ed46a1c5cfb93d9bf3ab Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Mon, 17 May 2021 11:58:06 -0400 Subject: [PATCH 4/5] Fix: include: Bump CRM_FEATURE_SET for new pacemakerd args. --- 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 fdfc825..92a98fa 100644 --- a/include/crm/crm.h +++ b/include/crm/crm.h @@ -66,7 +66,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.10.0" +# define CRM_FEATURE_SET "3.10.1" /* Pacemaker's CPG protocols use fixed-width binary fields for the sender and * recipient of a CPG message. This imposes an arbitrary limit on cluster node -- 1.8.3.1 From 3ad8edbd91631b87ef5f53fa2d68f0c8bbb9ee2b Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Mon, 17 May 2021 11:57:09 -0400 Subject: [PATCH 5/5] Feature: xml: Add schema for pacemakerd. --- xml/Makefile.am | 1 + xml/api/pacemakerd-2.10.rng | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 xml/api/pacemakerd-2.10.rng diff --git a/xml/Makefile.am b/xml/Makefile.am index 12a51c5..b9448d4 100644 --- a/xml/Makefile.am +++ b/xml/Makefile.am @@ -56,6 +56,7 @@ API_request_base = command-output \ crm_simulate \ crmadmin \ digests \ + pacemakerd \ stonith_admin \ version diff --git a/xml/api/pacemakerd-2.10.rng b/xml/api/pacemakerd-2.10.rng new file mode 100644 index 0000000..41a11e7 --- /dev/null +++ b/xml/api/pacemakerd-2.10.rng @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 1.8.3.1