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

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