diff --git a/daemons/schedulerd/Makefile.am b/daemons/schedulerd/Makefile.am index 87c84aa809..57e819bd98 100644 --- a/daemons/schedulerd/Makefile.am +++ b/daemons/schedulerd/Makefile.am @@ -1,50 +1,53 @@ # # Copyright 2004-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. # include $(top_srcdir)/mk/common.mk include $(top_srcdir)/mk/man.mk AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) halibdir = $(CRM_DAEMON_DIR) ## binary progs halib_PROGRAMS = pacemaker-schedulerd if BUILD_XML_HELP man7_MANS = pacemaker-schedulerd.7 endif ## SOURCES +noinst_HEADERS = pacemaker-schedulerd.h + pacemaker_schedulerd_CFLAGS = $(CFLAGS_HARDENED_EXE) pacemaker_schedulerd_LDFLAGS = $(LDFLAGS_HARDENED_EXE) pacemaker_schedulerd_LDADD = $(top_builddir)/lib/common/libcrmcommon.la \ $(top_builddir)/lib/pengine/libpe_status.la \ $(top_builddir)/lib/pacemaker/libpacemaker.la # libcib for get_object_root() pacemaker_schedulerd_SOURCES = pacemaker-schedulerd.c +pacemaker_schedulerd_SOURCES += schedulerd_messages.c install-exec-local: $(INSTALL) -d -m 750 $(DESTDIR)/$(PE_STATE_DIR) -chown $(CRM_DAEMON_USER):$(CRM_DAEMON_GROUP) $(DESTDIR)/$(PE_STATE_DIR) if BUILD_LEGACY_LINKS install-exec-hook: cd $(DESTDIR)$(CRM_DAEMON_DIR) && rm -f pengine && $(LN_S) pacemaker-schedulerd pengine uninstall-hook: cd $(DESTDIR)$(CRM_DAEMON_DIR) && rm -f pengine endif uninstall-local: -rmdir $(DESTDIR)/$(PE_STATE_DIR) CLEANFILES = $(man7_MANS) diff --git a/daemons/schedulerd/pacemaker-schedulerd.c b/daemons/schedulerd/pacemaker-schedulerd.c index 76869b8771..6f6075b9df 100644 --- a/daemons/schedulerd/pacemaker-schedulerd.c +++ b/daemons/schedulerd/pacemaker-schedulerd.c @@ -1,439 +1,184 @@ /* * Copyright 2004-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. */ #include #include #include #include -#include -#include -#include #include #include -#include - -#include #include #include #include #include #include -#include + +#include "pacemaker-schedulerd.h" #define SUMMARY "pacemaker-schedulerd - daemon for calculating a Pacemaker cluster's response to events" struct { gchar **remainder; } options; +pe_working_set_t *sched_data_set = NULL; +pcmk__output_t *logger_out = NULL; +pcmk__output_t *out = NULL; + static GMainLoop *mainloop = NULL; static qb_ipcs_service_t *ipcs = NULL; -static pe_working_set_t *sched_data_set = NULL; -static pcmk__output_t *logger_out = NULL; -static pcmk__output_t *out = NULL; static crm_exit_t exit_code = CRM_EX_OK; pcmk__supported_format_t formats[] = { PCMK__SUPPORTED_FORMAT_NONE, PCMK__SUPPORTED_FORMAT_TEXT, PCMK__SUPPORTED_FORMAT_XML, { NULL, NULL, NULL } }; void pengine_shutdown(int nsig); -static void -init_working_set(void) -{ - crm_config_error = FALSE; - crm_config_warning = FALSE; - - was_processing_error = FALSE; - was_processing_warning = FALSE; - - if (sched_data_set == NULL) { - sched_data_set = pe_new_working_set(); - CRM_ASSERT(sched_data_set != NULL); - pe__set_working_set_flags(sched_data_set, - pe_flag_no_counts|pe_flag_no_compat); - pe__set_working_set_flags(sched_data_set, - pe_flag_show_utilization); - sched_data_set->priv = logger_out; - } else { - pe_reset_working_set(sched_data_set); - } -} - -static void -handle_pecalc_op(xmlNode *msg, xmlNode *xml_data, pcmk__client_t *sender) -{ - static struct series_s { - const char *name; - const char *param; - - /* Maximum number of inputs of this kind to save to disk. - * If -1, save all; if 0, save none. - */ - int wrap; - } series[] = { - { "pe-error", "pe-error-series-max", -1 }, - { "pe-warn", "pe-warn-series-max", 5000 }, - { "pe-input", "pe-input-series-max", 4000 }, - }; - static char *last_digest = NULL; - static char *filename = NULL; - - unsigned int seq; - int series_id = 0; - int series_wrap = 0; - char *digest = NULL; - const char *value = NULL; - time_t execution_date = time(NULL); - xmlNode *converted = NULL; - xmlNode *reply = NULL; - bool is_repoke = false; - bool process = true; - - init_working_set(); - - digest = calculate_xml_versioned_digest(xml_data, FALSE, FALSE, - CRM_FEATURE_SET); - converted = copy_xml(xml_data); - if (!cli_config_update(&converted, NULL, TRUE)) { - sched_data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH); - crm_xml_add_int(sched_data_set->graph, "transition_id", 0); - crm_xml_add_int(sched_data_set->graph, "cluster-delay", 0); - process = false; - free(digest); - - } else if (pcmk__str_eq(digest, last_digest, pcmk__str_casei)) { - is_repoke = true; - free(digest); - - } else { - free(last_digest); - last_digest = digest; - } - - if (process) { - pcmk__schedule_actions(sched_data_set, converted, NULL); - } - - // Get appropriate index into series[] array - if (was_processing_error) { - series_id = 0; - } else if (was_processing_warning) { - series_id = 1; - } else { - series_id = 2; - } - - value = pe_pref(sched_data_set->config_hash, series[series_id].param); - if ((value == NULL) - || (pcmk__scan_min_int(value, &series_wrap, -1) != pcmk_rc_ok)) { - series_wrap = series[series_id].wrap; - } - - if (pcmk__read_series_sequence(PE_STATE_DIR, series[series_id].name, - &seq) != pcmk_rc_ok) { - // @TODO maybe handle errors better ... - seq = 0; - } - crm_trace("Series %s: wrap=%d, seq=%u, pref=%s", - series[series_id].name, series_wrap, seq, value); - - sched_data_set->input = NULL; - reply = create_reply(msg, sched_data_set->graph); - CRM_ASSERT(reply != NULL); - - if (series_wrap == 0) { // Don't save any inputs of this kind - free(filename); - filename = NULL; - - } else if (!is_repoke) { // Input changed, save to disk - free(filename); - filename = pcmk__series_filename(PE_STATE_DIR, - series[series_id].name, seq, true); - } - - crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename); - crm_xml_add_int(reply, "graph-errors", was_processing_error); - crm_xml_add_int(reply, "graph-warnings", was_processing_warning); - crm_xml_add_int(reply, "config-errors", crm_config_error); - crm_xml_add_int(reply, "config-warnings", crm_config_warning); - - if (pcmk__ipc_send_xml(sender, 0, reply, - crm_ipc_server_event) != pcmk_rc_ok) { - int graph_file_fd = 0; - char *graph_file = NULL; - umask(S_IWGRP | S_IWOTH | S_IROTH); - - graph_file = crm_strdup_printf("%s/pengine.graph.XXXXXX", - PE_STATE_DIR); - graph_file_fd = mkstemp(graph_file); - - crm_err("Couldn't send transition graph to peer, writing to %s instead", - graph_file); - - crm_xml_add(reply, F_CRM_TGRAPH, graph_file); - write_xml_fd(sched_data_set->graph, graph_file, graph_file_fd, FALSE); - - free(graph_file); - free_xml(first_named_child(reply, F_CRM_DATA)); - CRM_ASSERT(pcmk__ipc_send_xml(sender, 0, reply, - crm_ipc_server_event) == pcmk_rc_ok); - } - - free_xml(reply); - pcmk__log_transition_summary(filename); - - if (series_wrap == 0) { - crm_debug("Not saving input to disk (disabled by configuration)"); - - } else if (is_repoke) { - crm_info("Input has not changed since last time, not saving to disk"); - - } else { - unlink(filename); - crm_xml_add_ll(xml_data, "execution-date", (long long) execution_date); - write_xml_file(xml_data, filename, TRUE); - pcmk__write_series_sequence(PE_STATE_DIR, series[series_id].name, - ++seq, series_wrap); - } - - free_xml(converted); -} - -static gboolean -process_pe_message(xmlNode *msg, xmlNode *xml_data, pcmk__client_t *sender) -{ - const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); - const char *op = crm_element_value(msg, F_CRM_TASK); - const char *ref = crm_element_value(msg, F_CRM_REFERENCE); - - crm_trace("Processing %s op (ref=%s)...", op, ref); - - if (op == NULL) { - /* error */ - - } else if (strcasecmp(op, CRM_OP_HELLO) == 0) { - /* ignore */ - - } else if (pcmk__str_eq(crm_element_value(msg, F_CRM_MSG_TYPE), XML_ATTR_RESPONSE, pcmk__str_casei)) { - /* ignore */ - - } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_PENGINE) != 0) { - crm_trace("Bad sys-to %s", crm_str(sys_to)); - return FALSE; - - } else if (strcasecmp(op, CRM_OP_PECALC) == 0) { - handle_pecalc_op(msg, xml_data, sender); - } - - return TRUE; -} - -static int32_t -pe_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) -{ - crm_trace("Connection %p", c); - if (pcmk__new_client(c, uid, gid) == NULL) { - return -EIO; - } - return 0; -} - -gboolean process_pe_message(xmlNode *msg, xmlNode *xml_data, - pcmk__client_t *sender); - -static int32_t -pe_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) -{ - uint32_t id = 0; - uint32_t flags = 0; - pcmk__client_t *c = pcmk__find_client(qbc); - xmlNode *msg = pcmk__client_data2xml(c, data, &id, &flags); - - pcmk__ipc_send_ack(c, id, flags, "ack", CRM_EX_INDETERMINATE); - if (msg != NULL) { - xmlNode *data_xml = get_message_xml(msg, F_CRM_DATA); - - process_pe_message(msg, data_xml, c); - free_xml(msg); - } - return 0; -} - -/* Error code means? */ -static int32_t -pe_ipc_closed(qb_ipcs_connection_t * c) -{ - pcmk__client_t *client = pcmk__find_client(c); - - if (client == NULL) { - return 0; - } - crm_trace("Connection %p", c); - pcmk__free_client(client); - return 0; -} - -static void -pe_ipc_destroy(qb_ipcs_connection_t * c) -{ - crm_trace("Connection %p", c); - pe_ipc_closed(c); -} - -struct qb_ipcs_service_handlers ipc_callbacks = { - .connection_accept = pe_ipc_accept, - .connection_created = NULL, - .msg_process = pe_ipc_dispatch, - .connection_closed = pe_ipc_closed, - .connection_destroyed = pe_ipc_destroy -}; - static GOptionContext * build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { GOptionContext *context = NULL; GOptionEntry extra_prog_entries[] = { { G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING_ARRAY, &options.remainder, NULL, NULL }, { NULL } }; context = pcmk__build_arg_context(args, "text (default), xml", group, NULL); pcmk__add_main_args(context, extra_prog_entries); return context; } int 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, NULL); GOptionContext *context = build_arg_context(args, &output_group); crm_log_preinit(NULL, argc, argv); mainloop_add_signal(SIGTERM, pengine_shutdown); pcmk__register_formats(NULL, 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) || (out == NULL)) { exit_code = CRM_EX_FATAL; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", args->output_ty, pcmk_rc_str(rc)); goto done; } pe__register_messages(out); pcmk__register_lib_messages(out); if (options.remainder) { if (g_strv_length(options.remainder) == 1 && pcmk__str_eq("metadata", options.remainder[0], pcmk__str_casei)) { pe_metadata(); goto done; } else { exit_code = CRM_EX_USAGE; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Unsupported extra command line parameters"); goto done; } } if (args->version) { out->version(out, false); goto done; } pcmk__cli_init_logging("pacemaker-schedulerd", args->verbosity); crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE); crm_notice("Starting Pacemaker scheduler"); if (pcmk__daemon_can_write(PE_STATE_DIR, NULL) == FALSE) { crm_err("Terminating due to bad permissions on " PE_STATE_DIR); exit_code = CRM_EX_FATAL; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "ERROR: Bad permissions on %s (see logs for details)", PE_STATE_DIR); goto done; } ipcs = mainloop_add_ipc_server(CRM_SYSTEM_PENGINE, QB_IPC_SHM, &ipc_callbacks); if (ipcs == NULL) { crm_err("Failed to create IPC server: shutting down and inhibiting respawn"); exit_code = CRM_EX_FATAL; goto done; } logger_out = pcmk__new_logger(); if (logger_out == NULL) { exit_code = CRM_EX_FATAL; goto done; } pcmk__output_set_log_level(logger_out, LOG_TRACE); /* Create the mainloop and run it... */ mainloop = g_main_loop_new(NULL, FALSE); crm_notice("Pacemaker scheduler successfully started and accepting connections"); g_main_loop_run(mainloop); done: g_strfreev(options.remainder); g_strfreev(processed_args); pcmk__free_arg_context(context); pcmk__output_and_clear_error(error, out); pengine_shutdown(0); } void pengine_shutdown(int nsig) { if (ipcs != NULL) { mainloop_del_ipc_server(ipcs); ipcs = NULL; } if (sched_data_set != NULL) { pe_free_working_set(sched_data_set); sched_data_set = NULL; } if (logger_out != NULL) { logger_out->finish(logger_out, exit_code, true, NULL); pcmk__output_free(logger_out); logger_out = NULL; } if (out != NULL) { out->finish(out, exit_code, true, NULL); pcmk__output_free(out); out = NULL; } pcmk__unregister_formats(); crm_exit(exit_code); } diff --git a/daemons/schedulerd/pacemaker-schedulerd.h b/daemons/schedulerd/pacemaker-schedulerd.h new file mode 100644 index 0000000000..757e848b29 --- /dev/null +++ b/daemons/schedulerd/pacemaker-schedulerd.h @@ -0,0 +1,21 @@ +/* + * Copyright 2004-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. + */ + +#ifndef PCMK__PACEMAKER_SCHEDULERD__H +#define PCMK__PACEMAKER_SCHEDULERD__H + +#include +#include + +extern pe_working_set_t *sched_data_set; +extern pcmk__output_t *logger_out; +extern pcmk__output_t *out; +extern struct qb_ipcs_service_handlers ipc_callbacks; + +#endif diff --git a/daemons/schedulerd/pacemaker-schedulerd.c b/daemons/schedulerd/schedulerd_messages.c similarity index 61% copy from daemons/schedulerd/pacemaker-schedulerd.c copy to daemons/schedulerd/schedulerd_messages.c index 76869b8771..96fdd721e0 100644 --- a/daemons/schedulerd/pacemaker-schedulerd.c +++ b/daemons/schedulerd/schedulerd_messages.c @@ -1,439 +1,268 @@ /* * Copyright 2004-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. */ #include -#include -#include +#include +#include + #include #include #include #include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#define SUMMARY "pacemaker-schedulerd - daemon for calculating a Pacemaker cluster's response to events" - -struct { - gchar **remainder; -} options; - -static GMainLoop *mainloop = NULL; -static qb_ipcs_service_t *ipcs = NULL; -static pe_working_set_t *sched_data_set = NULL; -static pcmk__output_t *logger_out = NULL; -static pcmk__output_t *out = NULL; -static crm_exit_t exit_code = CRM_EX_OK; - -pcmk__supported_format_t formats[] = { - PCMK__SUPPORTED_FORMAT_NONE, - PCMK__SUPPORTED_FORMAT_TEXT, - PCMK__SUPPORTED_FORMAT_XML, - { NULL, NULL, NULL } -}; - -void pengine_shutdown(int nsig); +#include "pacemaker-schedulerd.h" static void init_working_set(void) { crm_config_error = FALSE; crm_config_warning = FALSE; was_processing_error = FALSE; was_processing_warning = FALSE; if (sched_data_set == NULL) { sched_data_set = pe_new_working_set(); CRM_ASSERT(sched_data_set != NULL); pe__set_working_set_flags(sched_data_set, pe_flag_no_counts|pe_flag_no_compat); pe__set_working_set_flags(sched_data_set, pe_flag_show_utilization); sched_data_set->priv = logger_out; } else { pe_reset_working_set(sched_data_set); } } static void handle_pecalc_op(xmlNode *msg, xmlNode *xml_data, pcmk__client_t *sender) { static struct series_s { const char *name; const char *param; /* Maximum number of inputs of this kind to save to disk. * If -1, save all; if 0, save none. */ int wrap; } series[] = { { "pe-error", "pe-error-series-max", -1 }, { "pe-warn", "pe-warn-series-max", 5000 }, { "pe-input", "pe-input-series-max", 4000 }, }; static char *last_digest = NULL; static char *filename = NULL; unsigned int seq; int series_id = 0; int series_wrap = 0; char *digest = NULL; const char *value = NULL; time_t execution_date = time(NULL); xmlNode *converted = NULL; xmlNode *reply = NULL; bool is_repoke = false; bool process = true; init_working_set(); digest = calculate_xml_versioned_digest(xml_data, FALSE, FALSE, CRM_FEATURE_SET); converted = copy_xml(xml_data); if (!cli_config_update(&converted, NULL, TRUE)) { sched_data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH); crm_xml_add_int(sched_data_set->graph, "transition_id", 0); crm_xml_add_int(sched_data_set->graph, "cluster-delay", 0); process = false; free(digest); } else if (pcmk__str_eq(digest, last_digest, pcmk__str_casei)) { is_repoke = true; free(digest); } else { free(last_digest); last_digest = digest; } if (process) { pcmk__schedule_actions(sched_data_set, converted, NULL); } // Get appropriate index into series[] array if (was_processing_error) { series_id = 0; } else if (was_processing_warning) { series_id = 1; } else { series_id = 2; } value = pe_pref(sched_data_set->config_hash, series[series_id].param); if ((value == NULL) || (pcmk__scan_min_int(value, &series_wrap, -1) != pcmk_rc_ok)) { series_wrap = series[series_id].wrap; } if (pcmk__read_series_sequence(PE_STATE_DIR, series[series_id].name, &seq) != pcmk_rc_ok) { // @TODO maybe handle errors better ... seq = 0; } crm_trace("Series %s: wrap=%d, seq=%u, pref=%s", series[series_id].name, series_wrap, seq, value); sched_data_set->input = NULL; reply = create_reply(msg, sched_data_set->graph); CRM_ASSERT(reply != NULL); if (series_wrap == 0) { // Don't save any inputs of this kind free(filename); filename = NULL; } else if (!is_repoke) { // Input changed, save to disk free(filename); filename = pcmk__series_filename(PE_STATE_DIR, series[series_id].name, seq, true); } crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename); crm_xml_add_int(reply, "graph-errors", was_processing_error); crm_xml_add_int(reply, "graph-warnings", was_processing_warning); crm_xml_add_int(reply, "config-errors", crm_config_error); crm_xml_add_int(reply, "config-warnings", crm_config_warning); if (pcmk__ipc_send_xml(sender, 0, reply, crm_ipc_server_event) != pcmk_rc_ok) { int graph_file_fd = 0; char *graph_file = NULL; umask(S_IWGRP | S_IWOTH | S_IROTH); graph_file = crm_strdup_printf("%s/pengine.graph.XXXXXX", PE_STATE_DIR); graph_file_fd = mkstemp(graph_file); crm_err("Couldn't send transition graph to peer, writing to %s instead", graph_file); crm_xml_add(reply, F_CRM_TGRAPH, graph_file); write_xml_fd(sched_data_set->graph, graph_file, graph_file_fd, FALSE); free(graph_file); free_xml(first_named_child(reply, F_CRM_DATA)); CRM_ASSERT(pcmk__ipc_send_xml(sender, 0, reply, crm_ipc_server_event) == pcmk_rc_ok); } free_xml(reply); pcmk__log_transition_summary(filename); if (series_wrap == 0) { crm_debug("Not saving input to disk (disabled by configuration)"); } else if (is_repoke) { crm_info("Input has not changed since last time, not saving to disk"); } else { unlink(filename); crm_xml_add_ll(xml_data, "execution-date", (long long) execution_date); write_xml_file(xml_data, filename, TRUE); pcmk__write_series_sequence(PE_STATE_DIR, series[series_id].name, ++seq, series_wrap); } free_xml(converted); } static gboolean process_pe_message(xmlNode *msg, xmlNode *xml_data, pcmk__client_t *sender) { const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); const char *op = crm_element_value(msg, F_CRM_TASK); const char *ref = crm_element_value(msg, F_CRM_REFERENCE); crm_trace("Processing %s op (ref=%s)...", op, ref); if (op == NULL) { /* error */ } else if (strcasecmp(op, CRM_OP_HELLO) == 0) { /* ignore */ } else if (pcmk__str_eq(crm_element_value(msg, F_CRM_MSG_TYPE), XML_ATTR_RESPONSE, pcmk__str_casei)) { /* ignore */ } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_PENGINE) != 0) { crm_trace("Bad sys-to %s", crm_str(sys_to)); return FALSE; } else if (strcasecmp(op, CRM_OP_PECALC) == 0) { handle_pecalc_op(msg, xml_data, sender); } return TRUE; } static int32_t pe_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) { crm_trace("Connection %p", c); if (pcmk__new_client(c, uid, gid) == NULL) { return -EIO; } return 0; } -gboolean process_pe_message(xmlNode *msg, xmlNode *xml_data, - pcmk__client_t *sender); - static int32_t pe_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) { uint32_t id = 0; uint32_t flags = 0; pcmk__client_t *c = pcmk__find_client(qbc); xmlNode *msg = pcmk__client_data2xml(c, data, &id, &flags); pcmk__ipc_send_ack(c, id, flags, "ack", CRM_EX_INDETERMINATE); if (msg != NULL) { xmlNode *data_xml = get_message_xml(msg, F_CRM_DATA); process_pe_message(msg, data_xml, c); free_xml(msg); } return 0; } /* Error code means? */ static int32_t pe_ipc_closed(qb_ipcs_connection_t * c) { pcmk__client_t *client = pcmk__find_client(c); if (client == NULL) { return 0; } crm_trace("Connection %p", c); pcmk__free_client(client); return 0; } static void pe_ipc_destroy(qb_ipcs_connection_t * c) { crm_trace("Connection %p", c); pe_ipc_closed(c); } struct qb_ipcs_service_handlers ipc_callbacks = { .connection_accept = pe_ipc_accept, .connection_created = NULL, .msg_process = pe_ipc_dispatch, .connection_closed = pe_ipc_closed, .connection_destroyed = pe_ipc_destroy }; - -static GOptionContext * -build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { - GOptionContext *context = NULL; - - GOptionEntry extra_prog_entries[] = { - { G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING_ARRAY, &options.remainder, - NULL, - NULL }, - - { NULL } - }; - - context = pcmk__build_arg_context(args, "text (default), xml", group, NULL); - pcmk__add_main_args(context, extra_prog_entries); - return context; -} - -int -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, NULL); - GOptionContext *context = build_arg_context(args, &output_group); - - crm_log_preinit(NULL, argc, argv); - mainloop_add_signal(SIGTERM, pengine_shutdown); - - pcmk__register_formats(NULL, 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) || (out == NULL)) { - exit_code = CRM_EX_FATAL; - g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", - args->output_ty, pcmk_rc_str(rc)); - goto done; - } - - pe__register_messages(out); - pcmk__register_lib_messages(out); - - if (options.remainder) { - if (g_strv_length(options.remainder) == 1 && - pcmk__str_eq("metadata", options.remainder[0], pcmk__str_casei)) { - pe_metadata(); - goto done; - } else { - exit_code = CRM_EX_USAGE; - g_set_error(&error, PCMK__EXITC_ERROR, exit_code, - "Unsupported extra command line parameters"); - goto done; - } - } - - if (args->version) { - out->version(out, false); - goto done; - } - - pcmk__cli_init_logging("pacemaker-schedulerd", args->verbosity); - crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE); - crm_notice("Starting Pacemaker scheduler"); - - if (pcmk__daemon_can_write(PE_STATE_DIR, NULL) == FALSE) { - crm_err("Terminating due to bad permissions on " PE_STATE_DIR); - exit_code = CRM_EX_FATAL; - g_set_error(&error, PCMK__EXITC_ERROR, exit_code, - "ERROR: Bad permissions on %s (see logs for details)", PE_STATE_DIR); - goto done; - } - - ipcs = mainloop_add_ipc_server(CRM_SYSTEM_PENGINE, QB_IPC_SHM, &ipc_callbacks); - if (ipcs == NULL) { - crm_err("Failed to create IPC server: shutting down and inhibiting respawn"); - exit_code = CRM_EX_FATAL; - goto done; - } - - logger_out = pcmk__new_logger(); - if (logger_out == NULL) { - exit_code = CRM_EX_FATAL; - goto done; - } - - pcmk__output_set_log_level(logger_out, LOG_TRACE); - - /* Create the mainloop and run it... */ - mainloop = g_main_loop_new(NULL, FALSE); - crm_notice("Pacemaker scheduler successfully started and accepting connections"); - g_main_loop_run(mainloop); - -done: - g_strfreev(options.remainder); - g_strfreev(processed_args); - pcmk__free_arg_context(context); - - pcmk__output_and_clear_error(error, out); - pengine_shutdown(0); -} - -void -pengine_shutdown(int nsig) -{ - if (ipcs != NULL) { - mainloop_del_ipc_server(ipcs); - ipcs = NULL; - } - - if (sched_data_set != NULL) { - pe_free_working_set(sched_data_set); - sched_data_set = NULL; - } - - if (logger_out != NULL) { - logger_out->finish(logger_out, exit_code, true, NULL); - pcmk__output_free(logger_out); - logger_out = NULL; - } - - if (out != NULL) { - out->finish(out, exit_code, true, NULL); - pcmk__output_free(out); - out = NULL; - } - - pcmk__unregister_formats(); - crm_exit(exit_code); -}