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

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