root/daemons/attrd/pacemaker-attrd.c

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

DEFINITIONS

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

   1 /*
   2  * Copyright 2013-2023 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/cib/internal.h>
  24 #include <crm/msg_xml.h>
  25 #include <crm/pengine/rules.h>
  26 #include <crm/common/cmdline_internal.h>
  27 #include <crm/common/iso8601.h>
  28 #include <crm/common/ipc.h>
  29 #include <crm/common/ipc_internal.h>
  30 #include <crm/common/output_internal.h>
  31 #include <crm/common/xml.h>
  32 #include <crm/cluster/internal.h>
  33 
  34 #include <crm/common/attrd_internal.h>
  35 #include "pacemaker-attrd.h"
  36 
  37 #define SUMMARY "daemon for managing Pacemaker node attributes"
  38 
  39 gboolean stand_alone = FALSE;
  40 gchar **log_files = NULL;
  41 
  42 static GOptionEntry entries[] = {
  43     { "stand-alone", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &stand_alone,
  44       "(Advanced use only) Run in stand-alone mode", NULL },
  45 
  46     { "logfile", 'l', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME_ARRAY,
  47       &log_files, "Send logs to the additional named logfile", NULL },
  48 
  49     { NULL }
  50 };
  51 
  52 static pcmk__output_t *out = NULL;
  53 
  54 static pcmk__supported_format_t formats[] = {
  55     PCMK__SUPPORTED_FORMAT_NONE,
  56     PCMK__SUPPORTED_FORMAT_TEXT,
  57     PCMK__SUPPORTED_FORMAT_XML,
  58     { NULL, NULL, NULL }
  59 };
  60 
  61 lrmd_t *the_lrmd = NULL;
  62 crm_cluster_t *attrd_cluster = NULL;
  63 crm_trigger_t *attrd_config_read = NULL;
  64 crm_exit_t attrd_exit_status = CRM_EX_OK;
  65 
  66 static bool
  67 ipc_already_running(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69     pcmk_ipc_api_t *old_instance = NULL;
  70     int rc = pcmk_rc_ok;
  71 
  72     rc = pcmk_new_ipc_api(&old_instance, pcmk_ipc_attrd);
  73     if (rc != pcmk_rc_ok) {
  74         return false;
  75     }
  76 
  77     rc = pcmk__connect_ipc(old_instance, pcmk_ipc_dispatch_sync, 2);
  78     if (rc != pcmk_rc_ok) {
  79         crm_debug("No existing %s manager instance found: %s",
  80                   pcmk_ipc_name(old_instance, true), pcmk_rc_str(rc));
  81         pcmk_free_ipc_api(old_instance);
  82         return false;
  83     }
  84 
  85     pcmk_disconnect_ipc(old_instance);
  86     pcmk_free_ipc_api(old_instance);
  87     return true;
  88 }
  89 
  90 static GOptionContext *
  91 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     /* [previous][next][first][last][top][bottom][index][help] */
  92     GOptionContext *context = NULL;
  93 
  94     context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
  95     pcmk__add_main_args(context, entries);
  96     return context;
  97 }
  98 
  99 int
 100 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102     int rc = pcmk_rc_ok;
 103 
 104     GError *error = NULL;
 105     bool initialized = false;
 106 
 107     GOptionGroup *output_group = NULL;
 108     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 109     gchar **processed_args = pcmk__cmdline_preproc(argv, NULL);
 110     GOptionContext *context = build_arg_context(args, &output_group);
 111 
 112     attrd_init_mainloop();
 113     crm_log_preinit(NULL, argc, argv);
 114     mainloop_add_signal(SIGTERM, attrd_shutdown);
 115 
 116     pcmk__register_formats(output_group, formats);
 117     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
 118         attrd_exit_status = CRM_EX_USAGE;
 119         goto done;
 120     }
 121 
 122     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
 123     if ((rc != pcmk_rc_ok) || (out == NULL)) {
 124         attrd_exit_status = CRM_EX_ERROR;
 125         g_set_error(&error, PCMK__EXITC_ERROR, attrd_exit_status,
 126                     "Error creating output format %s: %s",
 127                     args->output_ty, pcmk_rc_str(rc));
 128         goto done;
 129     }
 130 
 131     if (args->version) {
 132         out->version(out, false);
 133         goto done;
 134     }
 135 
 136     // Open additional log files
 137     pcmk__add_logfiles(log_files, out);
 138 
 139     crm_log_init(T_ATTRD, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
 140     crm_notice("Starting Pacemaker node attribute manager%s",
 141                stand_alone ? " in standalone mode" : "");
 142 
 143     if (ipc_already_running()) {
 144         const char *msg = "pacemaker-attrd is already active, aborting startup";
 145 
 146         attrd_exit_status = CRM_EX_OK;
 147         g_set_error(&error, PCMK__EXITC_ERROR, attrd_exit_status, "%s", msg);
 148         crm_err("%s", msg);
 149         goto done;
 150     }
 151 
 152     initialized = true;
 153 
 154     attributes = pcmk__strkey_table(NULL, attrd_free_attribute);
 155 
 156     /* Connect to the CIB before connecting to the cluster or listening for IPC.
 157      * This allows us to assume the CIB is connected whenever we process a
 158      * cluster or IPC message (which also avoids start-up race conditions).
 159      */
 160     if (!stand_alone) {
 161         if (attrd_cib_connect(30) != pcmk_ok) {
 162             attrd_exit_status = CRM_EX_FATAL;
 163             g_set_error(&error, PCMK__EXITC_ERROR, attrd_exit_status,
 164                         "Could not connect to the CIB");
 165             goto done;
 166         }
 167         crm_info("CIB connection active");
 168     }
 169 
 170     if (attrd_cluster_connect() != pcmk_ok) {
 171         attrd_exit_status = CRM_EX_FATAL;
 172         g_set_error(&error, PCMK__EXITC_ERROR, attrd_exit_status,
 173                     "Could not connect to the cluster");
 174         goto done;
 175     }
 176     crm_info("Cluster connection active");
 177 
 178     // Initialization that requires the cluster to be connected
 179     attrd_election_init();
 180 
 181     if (!stand_alone) {
 182         attrd_cib_init();
 183     }
 184 
 185     /* Set a private attribute for ourselves with the protocol version we
 186      * support. This lets all nodes determine the minimum supported version
 187      * across all nodes. It also ensures that the writer learns our node name,
 188      * so it can send our attributes to the CIB.
 189      */
 190     attrd_broadcast_protocol();
 191 
 192     attrd_init_ipc();
 193     crm_notice("Pacemaker node attribute manager successfully started and accepting connections");
 194     attrd_run_mainloop();
 195 
 196   done:
 197     if (initialized) {
 198         crm_info("Shutting down attribute manager");
 199 
 200         attrd_election_fini();
 201         attrd_ipc_fini();
 202         attrd_lrmd_disconnect();
 203 
 204         if (!stand_alone) {
 205             attrd_cib_disconnect();
 206         }
 207 
 208         attrd_free_waitlist();
 209         pcmk_cluster_free(attrd_cluster);
 210         g_hash_table_destroy(attributes);
 211     }
 212 
 213     g_strfreev(processed_args);
 214     pcmk__free_arg_context(context);
 215 
 216     g_strfreev(log_files);
 217 
 218     pcmk__output_and_clear_error(&error, out);
 219 
 220     if (out != NULL) {
 221         out->finish(out, attrd_exit_status, true, NULL);
 222         pcmk__output_free(out);
 223     }
 224     pcmk__unregister_formats();
 225     crm_exit(attrd_exit_status);
 226 }

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