root/daemons/fenced/pacemaker-fenced.c

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

DEFINITIONS

This source file includes following definitions.
  1. st_ipc_accept
  2. st_ipc_dispatch
  3. st_ipc_closed
  4. st_ipc_destroy
  5. stonith_peer_callback
  6. stonith_peer_ais_callback
  7. stonith_peer_cs_destroy
  8. do_local_reply
  9. get_stonith_flag
  10. stonith_notify_client
  11. do_stonith_async_timeout_update
  12. fenced_send_notification
  13. fenced_send_config_notification
  14. node_does_watchdog_fencing
  15. stonith_shutdown
  16. stonith_cleanup
  17. stand_alone_cpg_cb
  18. st_peer_update_callback
  19. fencer_metadata
  20. build_arg_context
  21. main

   1 /*
   2  * Copyright 2009-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 #include <sys/utsname.h>
  18 
  19 #include <stdlib.h>
  20 #include <errno.h>
  21 #include <fcntl.h>
  22 #include <inttypes.h>  // PRIu32, PRIx32
  23 
  24 #include <crm/crm.h>
  25 #include <crm/common/cmdline_internal.h>
  26 #include <crm/common/ipc.h>
  27 #include <crm/common/ipc_internal.h>
  28 #include <crm/common/output_internal.h>
  29 
  30 #include <crm/stonith-ng.h>
  31 #include <crm/fencing/internal.h>
  32 #include <crm/common/xml.h>
  33 #include <crm/common/xml_internal.h>
  34 
  35 #include <crm/common/mainloop.h>
  36 
  37 #include <crm/cib/internal.h>
  38 
  39 #include <pacemaker-fenced.h>
  40 
  41 #define SUMMARY "daemon for executing fencing devices in a Pacemaker cluster"
  42 
  43 char *stonith_our_uname = NULL;
  44 long long stonith_watchdog_timeout_ms = 0;
  45 GList *stonith_watchdog_targets = NULL;
  46 
  47 static GMainLoop *mainloop = NULL;
  48 
  49 gboolean stand_alone = FALSE;
  50 gboolean stonith_shutdown_flag = FALSE;
  51 
  52 static qb_ipcs_service_t *ipcs = NULL;
  53 static pcmk__output_t *out = NULL;
  54 
  55 pcmk__supported_format_t formats[] = {
  56     PCMK__SUPPORTED_FORMAT_NONE,
  57     PCMK__SUPPORTED_FORMAT_TEXT,
  58     PCMK__SUPPORTED_FORMAT_XML,
  59     { NULL, NULL, NULL }
  60 };
  61 
  62 static struct {
  63     bool no_cib_connect;
  64     gchar **log_files;
  65 } options;
  66 
  67 crm_exit_t exit_code = CRM_EX_OK;
  68 
  69 static void stonith_cleanup(void);
  70 
  71 static int32_t
  72 st_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74     if (stonith_shutdown_flag) {
  75         crm_info("Ignoring new client [%d] during shutdown",
  76                  pcmk__client_pid(c));
  77         return -ECONNREFUSED;
  78     }
  79 
  80     if (pcmk__new_client(c, uid, gid) == NULL) {
  81         return -ENOMEM;
  82     }
  83     return 0;
  84 }
  85 
  86 /* Exit code means? */
  87 static int32_t
  88 st_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     uint32_t id = 0;
  91     uint32_t flags = 0;
  92     int call_options = 0;
  93     xmlNode *request = NULL;
  94     pcmk__client_t *c = pcmk__find_client(qbc);
  95     const char *op = NULL;
  96 
  97     if (c == NULL) {
  98         crm_info("Invalid client: %p", qbc);
  99         return 0;
 100     }
 101 
 102     request = pcmk__client_data2xml(c, data, &id, &flags);
 103     if (request == NULL) {
 104         pcmk__ipc_send_ack(c, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL);
 105         return 0;
 106     }
 107 
 108 
 109     op = crm_element_value(request, PCMK__XA_CRM_TASK);
 110     if(pcmk__str_eq(op, CRM_OP_RM_NODE_CACHE, pcmk__str_casei)) {
 111         crm_xml_add(request, PCMK__XA_T, PCMK__VALUE_STONITH_NG);
 112         crm_xml_add(request, PCMK__XA_ST_OP, op);
 113         crm_xml_add(request, PCMK__XA_ST_CLIENTID, c->id);
 114         crm_xml_add(request, PCMK__XA_ST_CLIENTNAME, pcmk__client_name(c));
 115         crm_xml_add(request, PCMK__XA_ST_CLIENTNODE, stonith_our_uname);
 116 
 117         pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, request);
 118         free_xml(request);
 119         return 0;
 120     }
 121 
 122     if (c->name == NULL) {
 123         const char *value = crm_element_value(request, PCMK__XA_ST_CLIENTNAME);
 124 
 125         c->name = crm_strdup_printf("%s.%u", pcmk__s(value, "unknown"), c->pid);
 126     }
 127 
 128     crm_element_value_int(request, PCMK__XA_ST_CALLOPT, &call_options);
 129     crm_trace("Flags %#08" PRIx32 "/%#08x for command %" PRIu32
 130               " from client %s", flags, call_options, id, pcmk__client_name(c));
 131 
 132     if (pcmk_is_set(call_options, st_opt_sync_call)) {
 133         CRM_ASSERT(flags & crm_ipc_client_response);
 134         CRM_LOG_ASSERT(c->request_id == 0);     /* This means the client has two synchronous events in-flight */
 135         c->request_id = id;     /* Reply only to the last one */
 136     }
 137 
 138     crm_xml_add(request, PCMK__XA_ST_CLIENTID, c->id);
 139     crm_xml_add(request, PCMK__XA_ST_CLIENTNAME, pcmk__client_name(c));
 140     crm_xml_add(request, PCMK__XA_ST_CLIENTNODE, stonith_our_uname);
 141 
 142     crm_log_xml_trace(request, "ipc-received");
 143     stonith_command(c, id, flags, request, NULL);
 144 
 145     free_xml(request);
 146     return 0;
 147 }
 148 
 149 /* Error code means? */
 150 static int32_t
 151 st_ipc_closed(qb_ipcs_connection_t * c)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153     pcmk__client_t *client = pcmk__find_client(c);
 154 
 155     if (client == NULL) {
 156         return 0;
 157     }
 158 
 159     crm_trace("Connection %p closed", c);
 160     pcmk__free_client(client);
 161 
 162     /* 0 means: yes, go ahead and destroy the connection */
 163     return 0;
 164 }
 165 
 166 static void
 167 st_ipc_destroy(qb_ipcs_connection_t * c)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169     crm_trace("Connection %p destroyed", c);
 170     st_ipc_closed(c);
 171 }
 172 
 173 static void
 174 stonith_peer_callback(xmlNode * msg, void *private_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176     const char *remote_peer = crm_element_value(msg, PCMK__XA_SRC);
 177     const char *op = crm_element_value(msg, PCMK__XA_ST_OP);
 178 
 179     if (pcmk__str_eq(op, STONITH_OP_POKE, pcmk__str_none)) {
 180         return;
 181     }
 182 
 183     crm_log_xml_trace(msg, "Peer[inbound]");
 184     stonith_command(NULL, 0, 0, msg, remote_peer);
 185 }
 186 
 187 #if SUPPORT_COROSYNC
 188 static void
 189 stonith_peer_ais_callback(cpg_handle_t handle,
     /* [previous][next][first][last][top][bottom][index][help] */
 190                           const struct cpg_name *groupName,
 191                           uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
 192 {
 193     uint32_t kind = 0;
 194     xmlNode *xml = NULL;
 195     const char *from = NULL;
 196     char *data = pcmk__cpg_message_data(handle, nodeid, pid, msg, &kind, &from);
 197 
 198     if(data == NULL) {
 199         return;
 200     }
 201     if (kind == crm_class_cluster) {
 202         xml = pcmk__xml_parse(data);
 203         if (xml == NULL) {
 204             crm_err("Invalid XML: '%.120s'", data);
 205             free(data);
 206             return;
 207         }
 208         crm_xml_add(xml, PCMK__XA_SRC, from);
 209         stonith_peer_callback(xml, NULL);
 210     }
 211 
 212     free_xml(xml);
 213     free(data);
 214     return;
 215 }
 216 
 217 static void
 218 stonith_peer_cs_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220     crm_crit("Lost connection to cluster layer, shutting down");
 221     stonith_shutdown(0);
 222 }
 223 #endif
 224 
 225 void
 226 do_local_reply(const xmlNode *notify_src, pcmk__client_t *client,
     /* [previous][next][first][last][top][bottom][index][help] */
 227                int call_options)
 228 {
 229     /* send callback to originating child */
 230     int local_rc = pcmk_rc_ok;
 231     int rid = 0;
 232     uint32_t ipc_flags = crm_ipc_server_event;
 233 
 234     if (pcmk_is_set(call_options, st_opt_sync_call)) {
 235         CRM_LOG_ASSERT(client->request_id);
 236         rid = client->request_id;
 237         client->request_id = 0;
 238         ipc_flags = crm_ipc_flags_none;
 239     }
 240 
 241     local_rc = pcmk__ipc_send_xml(client, rid, notify_src, ipc_flags);
 242     if (local_rc == pcmk_rc_ok) {
 243         crm_trace("Sent response %d to client %s",
 244                   rid, pcmk__client_name(client));
 245     } else {
 246         crm_warn("%synchronous reply to client %s failed: %s",
 247                  (pcmk_is_set(call_options, st_opt_sync_call)? "S" : "As"),
 248                  pcmk__client_name(client), pcmk_rc_str(local_rc));
 249     }
 250 }
 251 
 252 uint64_t
 253 get_stonith_flag(const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255     if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_FENCE, pcmk__str_none)) {
 256         return st_callback_notify_fence;
 257 
 258     } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_ADD, pcmk__str_casei)) {
 259         return st_callback_device_add;
 260 
 261     } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_DEL, pcmk__str_casei)) {
 262         return st_callback_device_del;
 263 
 264     } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY,
 265                             pcmk__str_none)) {
 266         return st_callback_notify_history;
 267 
 268     } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED,
 269                             pcmk__str_none)) {
 270         return st_callback_notify_history_synced;
 271 
 272     }
 273     return st_callback_unknown;
 274 }
 275 
 276 static void
 277 stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279 
 280     const xmlNode *update_msg = user_data;
 281     pcmk__client_t *client = value;
 282     const char *type = NULL;
 283 
 284     CRM_CHECK(client != NULL, return);
 285     CRM_CHECK(update_msg != NULL, return);
 286 
 287     type = crm_element_value(update_msg, PCMK__XA_SUBT);
 288     CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);
 289 
 290     if (client->ipcs == NULL) {
 291         crm_trace("Skipping client with NULL channel");
 292         return;
 293     }
 294 
 295     if (pcmk_is_set(client->flags, get_stonith_flag(type))) {
 296         int rc = pcmk__ipc_send_xml(client, 0, update_msg,
 297                                     crm_ipc_server_event);
 298 
 299         if (rc != pcmk_rc_ok) {
 300             crm_warn("%s notification of client %s failed: %s "
 301                      CRM_XS " id=%.8s rc=%d", type, pcmk__client_name(client),
 302                      pcmk_rc_str(rc), client->id, rc);
 303         } else {
 304             crm_trace("Sent %s notification to client %s",
 305                       type, pcmk__client_name(client));
 306         }
 307     }
 308 }
 309 
 310 void
 311 do_stonith_async_timeout_update(const char *client_id, const char *call_id, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313     pcmk__client_t *client = NULL;
 314     xmlNode *notify_data = NULL;
 315 
 316     if (!timeout || !call_id || !client_id) {
 317         return;
 318     }
 319 
 320     client = pcmk__find_client_by_id(client_id);
 321     if (!client) {
 322         return;
 323     }
 324 
 325     notify_data = pcmk__xe_create(NULL, PCMK__XE_ST_ASYNC_TIMEOUT_VALUE);
 326     crm_xml_add(notify_data, PCMK__XA_T, PCMK__VALUE_ST_ASYNC_TIMEOUT_VALUE);
 327     crm_xml_add(notify_data, PCMK__XA_ST_CALLID, call_id);
 328     crm_xml_add_int(notify_data, PCMK__XA_ST_TIMEOUT, timeout);
 329 
 330     crm_trace("timeout update is %d for client %s and call id %s", timeout, client_id, call_id);
 331 
 332     if (client) {
 333         pcmk__ipc_send_xml(client, 0, notify_data, crm_ipc_server_event);
 334     }
 335 
 336     free_xml(notify_data);
 337 }
 338 
 339 /*!
 340  * \internal
 341  * \brief Notify relevant IPC clients of a fencing operation result
 342  *
 343  * \param[in] type     Notification type
 344  * \param[in] result   Result of fencing operation (assume success if NULL)
 345  * \param[in] data     If not NULL, add to notification as call data
 346  */
 347 void
 348 fenced_send_notification(const char *type, const pcmk__action_result_t *result,
     /* [previous][next][first][last][top][bottom][index][help] */
 349                          xmlNode *data)
 350 {
 351     /* TODO: Standardize the contents of data */
 352     xmlNode *update_msg = pcmk__xe_create(NULL, PCMK__XE_NOTIFY);
 353 
 354     CRM_LOG_ASSERT(type != NULL);
 355 
 356     crm_xml_add(update_msg, PCMK__XA_T, PCMK__VALUE_ST_NOTIFY);
 357     crm_xml_add(update_msg, PCMK__XA_SUBT, type);
 358     crm_xml_add(update_msg, PCMK__XA_ST_OP, type);
 359     stonith__xe_set_result(update_msg, result);
 360 
 361     if (data != NULL) {
 362         xmlNode *wrapper = pcmk__xe_create(update_msg, PCMK__XE_ST_CALLDATA);
 363 
 364         pcmk__xml_copy(wrapper, data);
 365     }
 366 
 367     crm_trace("Notifying clients");
 368     pcmk__foreach_ipc_client(stonith_notify_client, update_msg);
 369     free_xml(update_msg);
 370     crm_trace("Notify complete");
 371 }
 372 
 373 /*!
 374  * \internal
 375  * \brief Send notifications for a configuration change to subscribed clients
 376  *
 377  * \param[in] op      Notification type (\c STONITH_OP_DEVICE_ADD,
 378  *                    \c STONITH_OP_DEVICE_DEL, \c STONITH_OP_LEVEL_ADD, or
 379  *                    \c STONITH_OP_LEVEL_DEL)
 380  * \param[in] result  Operation result
 381  * \param[in] desc    Description of what changed (either device ID or string
 382  *                    representation of level
 383  *                    (<tt><target>[<level_index>]</tt>))
 384  */
 385 void
 386 fenced_send_config_notification(const char *op,
     /* [previous][next][first][last][top][bottom][index][help] */
 387                                 const pcmk__action_result_t *result,
 388                                 const char *desc)
 389 {
 390     xmlNode *notify_data = pcmk__xe_create(NULL, op);
 391 
 392     crm_xml_add(notify_data, PCMK__XA_ST_DEVICE_ID, desc);
 393 
 394     fenced_send_notification(op, result, notify_data);
 395     free_xml(notify_data);
 396 }
 397 
 398 /*!
 399  * \internal
 400  * \brief Check whether a node does watchdog-fencing
 401  *
 402  * \param[in] node    Name of node to check
 403  *
 404  * \return TRUE if node found in stonith_watchdog_targets
 405  *         or stonith_watchdog_targets is empty indicating
 406  *         all nodes are doing watchdog-fencing
 407  */
 408 gboolean
 409 node_does_watchdog_fencing(const char *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411     return ((stonith_watchdog_targets == NULL) ||
 412             pcmk__str_in_list(node, stonith_watchdog_targets, pcmk__str_casei));
 413 }
 414 
 415 void
 416 stonith_shutdown(int nsig)
     /* [previous][next][first][last][top][bottom][index][help] */
 417 {
 418     crm_info("Terminating with %d clients", pcmk__ipc_client_count());
 419     stonith_shutdown_flag = TRUE;
 420     if (mainloop != NULL && g_main_loop_is_running(mainloop)) {
 421         g_main_loop_quit(mainloop);
 422     }
 423 }
 424 
 425 static void
 426 stonith_cleanup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 427 {
 428     fenced_cib_cleanup();
 429     if (ipcs) {
 430         qb_ipcs_destroy(ipcs);
 431     }
 432 
 433     pcmk__cluster_destroy_node_caches();
 434     pcmk__client_cleanup();
 435     free_stonith_remote_op_list();
 436     free_topology_list();
 437     free_device_list();
 438     free_metadata_cache();
 439     fenced_unregister_handlers();
 440 
 441     free(stonith_our_uname);
 442     stonith_our_uname = NULL;
 443 }
 444 
 445 static gboolean
 446 stand_alone_cpg_cb(const gchar *option_name, const gchar *optarg, gpointer data,
     /* [previous][next][first][last][top][bottom][index][help] */
 447                    GError **error)
 448 {
 449     stand_alone = FALSE;
 450     options.no_cib_connect = true;
 451     return TRUE;
 452 }
 453 
 454 struct qb_ipcs_service_handlers ipc_callbacks = {
 455     .connection_accept = st_ipc_accept,
 456     .connection_created = NULL,
 457     .msg_process = st_ipc_dispatch,
 458     .connection_closed = st_ipc_closed,
 459     .connection_destroyed = st_ipc_destroy
 460 };
 461 
 462 /*!
 463  * \internal
 464  * \brief Callback for peer status changes
 465  *
 466  * \param[in] type  What changed
 467  * \param[in] node  What peer had the change
 468  * \param[in] data  Previous value of what changed
 469  */
 470 static void
 471 st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 472 {
 473     if ((type != crm_status_processes)
 474         && !pcmk_is_set(node->flags, crm_remote_node)) {
 475         /*
 476          * This is a hack until we can send to a nodeid and/or we fix node name lookups
 477          * These messages are ignored in stonith_peer_callback()
 478          */
 479         xmlNode *query = pcmk__xe_create(NULL, PCMK__XE_STONITH_COMMAND);
 480 
 481         crm_xml_add(query, PCMK__XA_T, PCMK__VALUE_STONITH_NG);
 482         crm_xml_add(query, PCMK__XA_ST_OP, STONITH_OP_POKE);
 483 
 484         crm_debug("Broadcasting our uname because of node %u", node->id);
 485         pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, query);
 486 
 487         free_xml(query);
 488     }
 489 }
 490 
 491 /* @COMPAT Deprecated since 2.1.8. Use pcmk_list_fence_attrs() or
 492  * crm_resource --list-options=fencing instead of querying daemon metadata.
 493  */
 494 static int
 495 fencer_metadata(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 496 {
 497     const char *name = "pacemaker-fenced";
 498     const char *desc_short = N_("Instance attributes available for all "
 499                                 "\"stonith\"-class resources");
 500     const char *desc_long = N_("Instance attributes available for all "
 501                                "\"stonith\"-class resources and used by "
 502                                "Pacemaker's fence daemon, formerly known as "
 503                                "stonithd");
 504 
 505     return pcmk__daemon_metadata(out, name, desc_short, desc_long,
 506                                  pcmk__opt_fencing);
 507 }
 508 
 509 static GOptionEntry entries[] = {
 510     { "stand-alone", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &stand_alone,
 511       N_("Deprecated (will be removed in a future release)"), NULL },
 512 
 513     { "stand-alone-w-cpg", 'c', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
 514       stand_alone_cpg_cb, N_("Intended for use in regression testing only"), NULL },
 515 
 516     { "logfile", 'l', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME_ARRAY,
 517       &options.log_files, N_("Send logs to the additional named logfile"), NULL },
 518 
 519     { NULL }
 520 };
 521 
 522 static GOptionContext *
 523 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525     GOptionContext *context = NULL;
 526 
 527     context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
 528     pcmk__add_main_args(context, entries);
 529     return context;
 530 }
 531 
 532 int
 533 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535     int rc = pcmk_rc_ok;
 536     pcmk_cluster_t *cluster = NULL;
 537     crm_ipc_t *old_instance = NULL;
 538 
 539     GError *error = NULL;
 540 
 541     GOptionGroup *output_group = NULL;
 542     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 543     gchar **processed_args = pcmk__cmdline_preproc(argv, "l");
 544     GOptionContext *context = build_arg_context(args, &output_group);
 545 
 546     crm_log_preinit(NULL, argc, argv);
 547 
 548     pcmk__register_formats(output_group, formats);
 549     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
 550         exit_code = CRM_EX_USAGE;
 551         goto done;
 552     }
 553 
 554     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
 555     if (rc != pcmk_rc_ok) {
 556         exit_code = CRM_EX_ERROR;
 557         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 558                     "Error creating output format %s: %s",
 559                     args->output_ty, pcmk_rc_str(rc));
 560         goto done;
 561     }
 562 
 563     if (args->version) {
 564         out->version(out, false);
 565         goto done;
 566     }
 567 
 568     if ((g_strv_length(processed_args) >= 2)
 569         && pcmk__str_eq(processed_args[1], "metadata", pcmk__str_none)) {
 570 
 571         rc = fencer_metadata();
 572         if (rc != pcmk_rc_ok) {
 573             exit_code = CRM_EX_FATAL;
 574             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 575                         "Unable to display metadata: %s", pcmk_rc_str(rc));
 576         }
 577         goto done;
 578     }
 579 
 580     // Open additional log files
 581     pcmk__add_logfiles(options.log_files, out);
 582 
 583     crm_log_init(NULL, LOG_INFO + args->verbosity, TRUE,
 584                  (args->verbosity > 0), argc, argv, FALSE);
 585 
 586     crm_notice("Starting Pacemaker fencer");
 587 
 588     old_instance = crm_ipc_new("stonith-ng", 0);
 589     if (old_instance == NULL) {
 590         /* crm_ipc_new() will have already logged an error message with
 591          * crm_err()
 592          */
 593         exit_code = CRM_EX_FATAL;
 594         goto done;
 595     }
 596 
 597     if (pcmk__connect_generic_ipc(old_instance) == pcmk_rc_ok) {
 598         // IPC endpoint already up
 599         crm_ipc_close(old_instance);
 600         crm_ipc_destroy(old_instance);
 601         crm_err("pacemaker-fenced is already active, aborting startup");
 602         goto done;
 603     } else {
 604         // Not up or not authentic, we'll proceed either way
 605         crm_ipc_destroy(old_instance);
 606         old_instance = NULL;
 607     }
 608 
 609     mainloop_add_signal(SIGTERM, stonith_shutdown);
 610 
 611     pcmk__cluster_init_node_caches();
 612 
 613     rc = fenced_scheduler_init();
 614     if (rc != pcmk_rc_ok) {
 615         exit_code = CRM_EX_FATAL;
 616         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 617                     "Error initializing scheduler data: %s", pcmk_rc_str(rc));
 618         goto done;
 619     }
 620 
 621     cluster = pcmk_cluster_new();
 622 
 623     if (!stand_alone) {
 624 #if SUPPORT_COROSYNC
 625         if (pcmk_get_cluster_layer() == pcmk_cluster_layer_corosync) {
 626             pcmk_cluster_set_destroy_fn(cluster, stonith_peer_cs_destroy);
 627             pcmk_cpg_set_deliver_fn(cluster, stonith_peer_ais_callback);
 628             pcmk_cpg_set_confchg_fn(cluster, pcmk__cpg_confchg_cb);
 629         }
 630 #endif // SUPPORT_COROSYNC
 631 
 632         pcmk__cluster_set_status_callback(&st_peer_update_callback);
 633 
 634         if (pcmk_cluster_connect(cluster) != pcmk_rc_ok) {
 635             exit_code = CRM_EX_FATAL;
 636             crm_crit("Cannot sign in to the cluster... terminating");
 637             goto done;
 638         }
 639         pcmk__str_update(&stonith_our_uname, cluster->uname);
 640 
 641         if (!options.no_cib_connect) {
 642             setup_cib();
 643         }
 644 
 645     } else {
 646         pcmk__str_update(&stonith_our_uname, "localhost");
 647         crm_warn("Stand-alone mode is deprecated and will be removed "
 648                  "in a future release");
 649     }
 650 
 651     init_device_list();
 652     init_topology_list();
 653 
 654     pcmk__serve_fenced_ipc(&ipcs, &ipc_callbacks);
 655 
 656     // Create the mainloop and run it...
 657     mainloop = g_main_loop_new(NULL, FALSE);
 658     crm_notice("Pacemaker fencer successfully started and accepting connections");
 659     g_main_loop_run(mainloop);
 660 
 661 done:
 662     g_strfreev(processed_args);
 663     pcmk__free_arg_context(context);
 664 
 665     g_strfreev(options.log_files);
 666 
 667     stonith_cleanup();
 668     pcmk_cluster_free(cluster);
 669     fenced_scheduler_cleanup();
 670 
 671     pcmk__output_and_clear_error(&error, out);
 672 
 673     if (out != NULL) {
 674         out->finish(out, exit_code, true, NULL);
 675         pcmk__output_free(out);
 676     }
 677 
 678     pcmk__unregister_formats();
 679     crm_exit(exit_code);
 680 }

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