root/daemons/controld/pacemaker-controld.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. controld_metadata
  2. build_arg_context
  3. main

   1 /*
   2  * Copyright 2004-2024 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <sys/param.h>
  13 #include <stdio.h>
  14 #include <sys/types.h>
  15 #include <sys/stat.h>
  16 #include <unistd.h>
  17 
  18 #include <stdlib.h>
  19 #include <errno.h>
  20 #include <fcntl.h>
  21 
  22 #include <crm/crm.h>
  23 #include <crm/common/cmdline_internal.h>
  24 #include <crm/common/ipc.h>
  25 #include <crm/common/output_internal.h>
  26 #include <crm/common/xml.h>
  27 
  28 #include <pacemaker-controld.h>
  29 
  30 #define SUMMARY "daemon for coordinating a Pacemaker cluster's response "   \
  31                 "to events"
  32 
  33 controld_globals_t controld_globals = {
  34     // Automatic initialization to 0, false, or NULL is fine for most members
  35     .fsa_state = S_STARTING,
  36     .fsa_actions = A_NOTHING,
  37 };
  38 
  39 static pcmk__supported_format_t formats[] = {
  40     PCMK__SUPPORTED_FORMAT_NONE,
  41     PCMK__SUPPORTED_FORMAT_TEXT,
  42     PCMK__SUPPORTED_FORMAT_XML,
  43     { NULL, NULL, NULL }
  44 };
  45 
  46 /* @COMPAT Deprecated since 2.1.8. Use pcmk_list_cluster_options() or
  47  * crm_attribute --list-options=cluster instead of querying daemon metadata.
  48  *
  49  * NOTE: pcs (as of at least 0.11.8) uses this
  50  */
  51 static int
  52 controld_metadata(pcmk__output_t *out)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54     return pcmk__daemon_metadata(out, PCMK__SERVER_CONTROLD,
  55                                  "Pacemaker controller options",
  56                                  "Cluster options used by Pacemaker's "
  57                                  "controller",
  58                                  pcmk__opt_controld);
  59 }
  60 
  61 static GOptionContext *
  62 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64     return pcmk__build_arg_context(args, "text (default), xml", group, NULL);
  65 }
  66 
  67 int
  68 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70     int rc = pcmk_rc_ok;
  71     crm_exit_t exit_code = CRM_EX_OK;
  72     bool initialize = true;
  73     enum crmd_fsa_state state;
  74 
  75     crm_ipc_t *old_instance = NULL;
  76 
  77     pcmk__output_t *out = NULL;
  78 
  79     GError *error = NULL;
  80 
  81     GOptionGroup *output_group = NULL;
  82     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
  83     gchar **processed_args = pcmk__cmdline_preproc(argv, NULL);
  84     GOptionContext *context = build_arg_context(args, &output_group);
  85 
  86     crm_log_preinit(NULL, argc, argv);
  87 
  88     pcmk__register_formats(output_group, formats);
  89     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
  90         exit_code = CRM_EX_USAGE;
  91         goto done;
  92     }
  93 
  94     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
  95     if (rc != pcmk_rc_ok) {
  96         exit_code = CRM_EX_ERROR;
  97         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
  98                     "Error creating output format %s: %s",
  99                     args->output_ty, pcmk_rc_str(rc));
 100         goto done;
 101     }
 102 
 103     if (args->version) {
 104         out->version(out, false);
 105         initialize = false;
 106         goto done;
 107     }
 108 
 109     if ((g_strv_length(processed_args) >= 2)
 110         && pcmk__str_eq(processed_args[1], "metadata", pcmk__str_none)) {
 111 
 112         initialize = false;
 113         rc = controld_metadata(out);
 114         if (rc != pcmk_rc_ok) {
 115             exit_code = CRM_EX_FATAL;
 116             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 117                         "Unable to display metadata: %s", pcmk_rc_str(rc));
 118         }
 119         goto done;
 120     }
 121 
 122     pcmk__cli_init_logging(PCMK__SERVER_CONTROLD, args->verbosity);
 123     crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
 124     crm_notice("Starting Pacemaker controller");
 125 
 126     old_instance = crm_ipc_new(CRM_SYSTEM_CRMD, 0);
 127     if (old_instance == NULL) {
 128         /* crm_ipc_new will have already printed an error message with crm_err. */
 129         exit_code = CRM_EX_FATAL;
 130         goto done;
 131     }
 132 
 133     if (pcmk__connect_generic_ipc(old_instance) == pcmk_rc_ok) {
 134         /* IPC end-point already up */
 135         crm_ipc_close(old_instance);
 136         crm_ipc_destroy(old_instance);
 137         crm_crit("Aborting start-up because another controller instance is "
 138                  "already active");
 139         initialize = false;
 140         goto done;
 141 
 142     } else {
 143         /* not up or not authentic, we'll proceed either way */
 144         crm_ipc_destroy(old_instance);
 145         old_instance = NULL;
 146     }
 147 
 148     if (pcmk__daemon_can_write(PCMK_SCHEDULER_INPUT_DIR, NULL) == FALSE) {
 149         exit_code = CRM_EX_FATAL;
 150         crm_err("Terminating due to bad permissions on " PCMK_SCHEDULER_INPUT_DIR);
 151         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 152                     "Bad permissions on " PCMK_SCHEDULER_INPUT_DIR
 153                     " (see logs for details)");
 154         goto done;
 155 
 156     } else if (pcmk__daemon_can_write(CRM_CONFIG_DIR, NULL) == FALSE) {
 157         exit_code = CRM_EX_FATAL;
 158         crm_err("Terminating due to bad permissions on " CRM_CONFIG_DIR);
 159         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 160                     "Bad permissions on " CRM_CONFIG_DIR
 161                     " (see logs for details)");
 162         goto done;
 163     }
 164 
 165     if (pcmk__log_output_new(&(controld_globals.logger_out)) != pcmk_rc_ok) {
 166         exit_code = CRM_EX_FATAL;
 167         goto done;
 168     }
 169 
 170     pcmk__output_set_log_level(controld_globals.logger_out, LOG_TRACE);
 171 
 172 done:
 173     g_strfreev(processed_args);
 174     pcmk__free_arg_context(context);
 175 
 176     // We no longer need output
 177     pcmk__output_and_clear_error(&error, out);
 178     if (out != NULL) {
 179         out->finish(out, exit_code, true, NULL);
 180         pcmk__output_free(out);
 181     }
 182     pcmk__unregister_formats();
 183 
 184     // Exit on error or command-line queries
 185     if ((exit_code != CRM_EX_OK) || !initialize) {
 186         crm_exit(exit_code);
 187     }
 188 
 189     // Initialize FSA
 190     register_fsa_input(C_STARTUP, I_STARTUP, NULL);
 191     pcmk__cluster_init_node_caches();
 192     state = s_crmd_fsa(C_STARTUP);
 193     if ((state != S_PENDING) && (state != S_STARTING)) {
 194         crm_err("Controller startup failed " QB_XS " FSA state %s",
 195                 crm_system_name, fsa_state2string(state));
 196         crmd_fast_exit(CRM_EX_ERROR); // Does not return
 197     }
 198 
 199     // Run mainloop
 200     controld_globals.mainloop = g_main_loop_new(NULL, FALSE);
 201     g_main_loop_run(controld_globals.mainloop);
 202     if (pcmk_is_set(controld_globals.fsa_input_register, R_STAYDOWN)) {
 203         crm_info("Inhibiting automated respawn");
 204         exit_code = CRM_EX_FATAL;
 205     }
 206     crmd_fast_exit(exit_code);
 207 }

/* [previous][next][first][last][top][bottom][index][help] */