root/daemons/fenced/fenced_cib.c

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

DEFINITIONS

This source file includes following definitions.
  1. node_has_attr
  2. remove_topology_level
  3. register_fencing_topology
  4. fencing_topology_init
  5. update_stonith_watchdog_timeout_ms
  6. mark_dirty_if_cib_registered
  7. device_is_dirty
  8. cib_devices_update
  9. update_cib_stonith_devices
  10. watchdog_device_update
  11. fenced_query_cib
  12. update_fencing_topology
  13. update_cib_cache_cb
  14. init_cib_cache_cb
  15. cib_connection_destroy
  16. fenced_cib_cleanup
  17. setup_cib

   1 /*
   2  * Copyright 2009-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 <stdbool.h>
  13 #include <stdio.h>
  14 #include <libxml/tree.h>            // xmlNode
  15 #include <libxml/xpath.h>           // xmlXPathObject, etc.
  16 
  17 #include <crm/crm.h>
  18 #include <crm/common/xml.h>
  19 
  20 #include <crm/cluster/internal.h>
  21 
  22 #include <crm/cib.h>
  23 #include <crm/cib/internal.h>
  24 
  25 #include <pacemaker-fenced.h>
  26 
  27 static xmlNode *local_cib = NULL;
  28 static cib_t *cib_api = NULL;
  29 static bool have_cib_devices = FALSE;
  30 
  31 /*!
  32  * \internal
  33  * \brief Check whether a node has a specific attribute name/value
  34  *
  35  * \param[in] node    Name of node to check
  36  * \param[in] name    Name of an attribute to look for
  37  * \param[in] value   The value the named attribute needs to be set to in order to be considered a match
  38  *
  39  * \return TRUE if the locally cached CIB has the specified node attribute
  40  */
  41 gboolean
  42 node_has_attr(const char *node, const char *name, const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44     GString *xpath = NULL;
  45     xmlNode *match;
  46 
  47     CRM_CHECK((local_cib != NULL) && (node != NULL) && (name != NULL)
  48               && (value != NULL), return FALSE);
  49 
  50     /* Search for the node's attributes in the CIB. While the schema allows
  51      * multiple sets of instance attributes, and allows instance attributes to
  52      * use id-ref to reference values elsewhere, that is intended for resources,
  53      * so we ignore that here.
  54      */
  55     xpath = g_string_sized_new(256);
  56     pcmk__g_strcat(xpath,
  57                    "//" PCMK_XE_NODES "/" PCMK_XE_NODE
  58                    "[@" PCMK_XA_UNAME "='", node, "']"
  59                    "/" PCMK_XE_INSTANCE_ATTRIBUTES
  60                    "/" PCMK_XE_NVPAIR
  61                    "[@" PCMK_XA_NAME "='", name, "' "
  62                    "and @" PCMK_XA_VALUE "='", value, "']", NULL);
  63 
  64     match = pcmk__xpath_find_one(local_cib->doc, xpath->str, LOG_NEVER);
  65 
  66     g_string_free(xpath, TRUE);
  67     return (match != NULL);
  68 }
  69 
  70 static void
  71 remove_topology_level(xmlNode *match)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73     int index = 0;
  74     char *key = NULL;
  75     xmlNode *data = NULL;
  76 
  77     CRM_CHECK(match != NULL, return);
  78 
  79     key = stonith_level_key(match, fenced_target_by_unknown);
  80     crm_element_value_int(match, PCMK_XA_INDEX, &index);
  81 
  82     data = pcmk__xe_create(NULL, PCMK_XE_FENCING_LEVEL);
  83     crm_xml_add(data, PCMK__XA_ST_ORIGIN, __func__);
  84     crm_xml_add(data, PCMK_XA_TARGET, key);
  85     crm_xml_add_int(data, PCMK_XA_INDEX, index);
  86 
  87     fenced_unregister_level(data, NULL);
  88 
  89     free(key);
  90     pcmk__xml_free(data);
  91 }
  92 
  93 static void
  94 register_fencing_topology(xmlXPathObjectPtr xpathObj)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96     int max = pcmk__xpath_num_results(xpathObj);
  97 
  98     for (int lpc = 0; lpc < max; lpc++) {
  99         xmlNode *match = pcmk__xpath_result(xpathObj, lpc);
 100 
 101         if (match == NULL) {
 102             continue;
 103         }
 104         remove_topology_level(match);
 105         fenced_register_level(match, NULL);
 106     }
 107 }
 108 
 109 /* Fencing
 110 <diff crm_feature_set="3.0.6">
 111   <diff-removed>
 112     <fencing-topology>
 113       <fencing-level id="f-p1.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="removed:top"/>
 114       <fencing-level id="f-p1.2" target="pcmk-1" index="2" devices="power" __crm_diff_marker__="removed:top"/>
 115       <fencing-level devices="disk,network" id="f-p2.1"/>
 116     </fencing-topology>
 117   </diff-removed>
 118   <diff-added>
 119     <fencing-topology>
 120       <fencing-level id="f-p.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="added:top"/>
 121       <fencing-level id="f-p2.1" target="pcmk-2" index="1" devices="disk,something"/>
 122       <fencing-level id="f-p3.1" target="pcmk-2" index="2" devices="power" __crm_diff_marker__="added:top"/>
 123     </fencing-topology>
 124   </diff-added>
 125 </diff>
 126 */
 127 
 128 void
 129 fencing_topology_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131     xmlXPathObject *xpathObj = NULL;
 132     const char *xpath = "//" PCMK_XE_FENCING_LEVEL;
 133 
 134     crm_trace("Full topology refresh");
 135     free_topology_list();
 136     init_topology_list();
 137 
 138     /* Grab everything */
 139     xpathObj = pcmk__xpath_search(local_cib->doc, xpath);
 140     register_fencing_topology(xpathObj);
 141 
 142     xmlXPathFreeObject(xpathObj);
 143 }
 144 
 145 #define XPATH_WATCHDOG_TIMEOUT "//" PCMK_XE_NVPAIR      \
 146                                "[@" PCMK_XA_NAME "='"   \
 147                                     PCMK_OPT_STONITH_WATCHDOG_TIMEOUT "']"
 148 
 149 static void
 150 update_stonith_watchdog_timeout_ms(xmlNode *cib)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152     long long timeout_ms = 0;
 153     xmlNode *stonith_watchdog_xml = NULL;
 154     const char *value = NULL;
 155 
 156     // @TODO An XPath search can't handle multiple instances or rules
 157     stonith_watchdog_xml = pcmk__xpath_find_one(cib->doc,
 158                                                 XPATH_WATCHDOG_TIMEOUT,
 159                                                 LOG_NEVER);
 160     if (stonith_watchdog_xml) {
 161         value = crm_element_value(stonith_watchdog_xml, PCMK_XA_VALUE);
 162     }
 163     if (value) {
 164         timeout_ms = crm_get_msec(value);
 165     }
 166 
 167     if (timeout_ms < 0) {
 168         timeout_ms = pcmk__auto_stonith_watchdog_timeout();
 169     }
 170 
 171     stonith_watchdog_timeout_ms = timeout_ms;
 172 }
 173 
 174 /*!
 175  * \internal
 176  * \brief Mark a fence device dirty if its \c fenced_df_cib_registered flag is
 177  *        set
 178  *
 179  * \param[in]     key        Ignored
 180  * \param[in,out] value      Fence device (<tt>fenced_device_t *</tt>)
 181  * \param[in]     user_data  Ignored
 182  *
 183  * \note This function is suitable for use with \c g_hash_table_foreach().
 184  */
 185 static void
 186 mark_dirty_if_cib_registered(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188     fenced_device_t *device = value;
 189 
 190     if (pcmk_is_set(device->flags, fenced_df_cib_registered)) {
 191         fenced_device_set_flags(device, fenced_df_dirty);
 192     }
 193 }
 194 
 195 /*!
 196  * \internal
 197  * \brief Return the value of a fence device's \c dirty flag
 198  *
 199  * \param[in] key        Ignored
 200  * \param[in] value      Fence device (<tt>fenced_device_t *</tt>)
 201  * \param[in] user_data  Ignored
 202  *
 203  * \return \c dirty flag of \p value
 204  *
 205  * \note This function is suitable for use with
 206  *       \c g_hash_table_foreach_remove().
 207  */
 208 static gboolean
 209 device_is_dirty(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211     fenced_device_t *device = value;
 212 
 213     return pcmk_is_set(device->flags, fenced_df_dirty);
 214 }
 215 
 216 /*!
 217  * \internal
 218  * \brief Update all STONITH device definitions based on current CIB
 219  */
 220 static void
 221 cib_devices_update(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 222 {
 223     crm_info("Updating devices to version %s.%s.%s",
 224              crm_element_value(local_cib, PCMK_XA_ADMIN_EPOCH),
 225              crm_element_value(local_cib, PCMK_XA_EPOCH),
 226              crm_element_value(local_cib, PCMK_XA_NUM_UPDATES));
 227 
 228     fenced_foreach_device(mark_dirty_if_cib_registered, NULL);
 229 
 230     /* have list repopulated if cib has a watchdog-fencing-resource
 231        TODO: keep a cached list for queries happening while we are refreshing
 232      */
 233     g_list_free_full(stonith_watchdog_targets, free);
 234     stonith_watchdog_targets = NULL;
 235 
 236     fenced_scheduler_run(local_cib);
 237 
 238     fenced_foreach_device_remove(device_is_dirty);
 239 }
 240 
 241 #define PRIMITIVE_ID_XP_FRAGMENT "/" PCMK_XE_PRIMITIVE "[@" PCMK_XA_ID "='"
 242 
 243 static void
 244 update_cib_stonith_devices(const xmlNode *patchset)
     /* [previous][next][first][last][top][bottom][index][help] */
 245 {
 246     char *reason = NULL;
 247 
 248     for (const xmlNode *change = pcmk__xe_first_child(patchset, NULL, NULL,
 249                                                       NULL);
 250          change != NULL; change = pcmk__xe_next(change, NULL)) {
 251 
 252         const char *op = crm_element_value(change, PCMK_XA_OPERATION);
 253         const char *xpath = crm_element_value(change, PCMK_XA_PATH);
 254         const char *primitive_xpath = NULL;
 255 
 256         if (pcmk__str_eq(op, PCMK_VALUE_MOVE, pcmk__str_null_matches)
 257             || (strstr(xpath, "/" PCMK_XE_STATUS) != NULL)) {
 258             continue;
 259         }
 260 
 261         primitive_xpath = strstr(xpath, PRIMITIVE_ID_XP_FRAGMENT);
 262         if ((primitive_xpath != NULL)
 263             && pcmk__str_eq(op, PCMK_VALUE_DELETE, pcmk__str_none)) {
 264 
 265             const char *rsc_id = NULL;
 266             const char *end_quote = NULL;
 267 
 268             if ((strstr(primitive_xpath, PCMK_XE_INSTANCE_ATTRIBUTES) != NULL)
 269                 || (strstr(primitive_xpath, PCMK_XE_META_ATTRIBUTES) != NULL)) {
 270 
 271                 reason = pcmk__str_copy("(meta) attribute deleted from "
 272                                         "resource");
 273                 break;
 274             }
 275 
 276             rsc_id = primitive_xpath + sizeof(PRIMITIVE_ID_XP_FRAGMENT) - 1;
 277             end_quote = strchr(rsc_id, '\'');
 278 
 279             CRM_LOG_ASSERT(end_quote != NULL);
 280             if (end_quote == NULL) {
 281                 crm_err("Bug: Malformed item in Pacemaker-generated patchset");
 282                 continue;
 283             }
 284 
 285             if (strchr(end_quote, '/') == NULL) {
 286                 /* The primitive element itself was deleted. If this was a
 287                  * fencing resource, it's faster to remove it directly than to
 288                  * run the scheduler and update all device registrations.
 289                 */
 290                 char *copy = strndup(rsc_id, end_quote - rsc_id);
 291 
 292                 pcmk__assert(copy != NULL);
 293                 stonith_device_remove(copy, true);
 294 
 295                 /* watchdog_device_update called afterwards
 296                    to fall back to implicit definition if needed */
 297 
 298                 free(copy);
 299                 continue;
 300             }
 301         }
 302 
 303         if (strstr(xpath, "/" PCMK_XE_RESOURCES)
 304             || strstr(xpath, "/" PCMK_XE_CONSTRAINTS)
 305             || strstr(xpath, "/" PCMK_XE_RSC_DEFAULTS)) {
 306 
 307             const char *shortpath = strrchr(xpath, '/');
 308 
 309             reason = crm_strdup_printf("%s %s", op, shortpath + 1);
 310             break;
 311         }
 312     }
 313 
 314     if (reason != NULL) {
 315         crm_info("Updating device list from CIB: %s", reason);
 316         cib_devices_update();
 317         free(reason);
 318     } else {
 319         crm_trace("No updates for device list found in CIB");
 320     }
 321 }
 322 
 323 static void
 324 watchdog_device_update(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326     if (stonith_watchdog_timeout_ms > 0) {
 327         if (!fenced_has_watchdog_device()
 328             && (stonith_watchdog_targets == NULL)) {
 329             /* getting here watchdog-fencing enabled, no device there yet
 330                and reason isn't stonith_watchdog_targets preventing that
 331              */
 332             int rc;
 333             xmlNode *xml;
 334 
 335             xml = create_device_registration_xml(
 336                     STONITH_WATCHDOG_ID,
 337                     st_namespace_internal,
 338                     STONITH_WATCHDOG_AGENT,
 339                     NULL, /* fenced_device_register() will add our
 340                              own name as PCMK_STONITH_HOST_LIST param
 341                              so we can skip that here
 342                            */
 343                     NULL);
 344             rc = fenced_device_register(xml, true);
 345             pcmk__xml_free(xml);
 346             if (rc != pcmk_rc_ok) {
 347                 exit_code = CRM_EX_FATAL;
 348                 crm_crit("Cannot register watchdog pseudo fence agent: %s",
 349                          pcmk_rc_str(rc));
 350                 stonith_shutdown(0);
 351             }
 352         }
 353 
 354     } else if (fenced_has_watchdog_device()) {
 355         /* be silent if no device - todo parameter to stonith_device_remove */
 356         stonith_device_remove(STONITH_WATCHDOG_ID, true);
 357     }
 358 }
 359 
 360 /*!
 361  * \internal
 362  * \brief Query the full CIB
 363  *
 364  * \return Standard Pacemaker return code
 365  */
 366 static int
 367 fenced_query_cib(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369     int rc = pcmk_ok;
 370 
 371     crm_trace("Re-requesting full CIB");
 372     rc = cib_api->cmds->query(cib_api, NULL, &local_cib, cib_sync_call);
 373     rc = pcmk_legacy2rc(rc);
 374     if (rc == pcmk_rc_ok) {
 375         pcmk__assert(local_cib != NULL);
 376     } else {
 377         crm_err("Couldn't retrieve the CIB: %s " QB_XS " rc=%d",
 378                 pcmk_rc_str(rc), rc);
 379     }
 380     return rc;
 381 }
 382 
 383 static void
 384 update_fencing_topology(const char *event, xmlNode *msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386     xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT,
 387                                             NULL, NULL);
 388     xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
 389 
 390     int format = 1;
 391 
 392     int add[] = { 0, 0, 0 };
 393     int del[] = { 0, 0, 0 };
 394 
 395     CRM_CHECK(patchset != NULL, return);
 396 
 397     crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
 398     if (format != 2) {
 399         crm_warn("Unknown patch format: %d", format);
 400         return;
 401     }
 402 
 403     xml_patch_versions(patchset, add, del);
 404 
 405     for (xmlNode *change = pcmk__xe_first_child(patchset, NULL, NULL, NULL);
 406          change != NULL; change = pcmk__xe_next(change, NULL)) {
 407 
 408         const char *op = crm_element_value(change, PCMK_XA_OPERATION);
 409         const char *xpath = crm_element_value(change, PCMK_XA_PATH);
 410 
 411         if (op == NULL) {
 412             continue;
 413         }
 414 
 415         if (strstr(xpath, "/" PCMK_XE_FENCING_LEVEL) != NULL) {
 416             // Change to a specific entry
 417             crm_trace("Handling %s operation %d.%d.%d for %s",
 418                       op, add[0], add[1], add[2], xpath);
 419 
 420             if (strcmp(op, PCMK_VALUE_DELETE) == 0) {
 421                 /* We have only path and ID, which is not enough info to remove
 422                  * a specific entry. Re-initialize the whole topology.
 423                  */
 424                 crm_info("Re-initializing fencing topology after %s operation "
 425                          "%d.%d.%d for %s",
 426                          op, add[0], add[1], add[2], xpath);
 427                 fencing_topology_init();
 428                 return;
 429             }
 430 
 431             if (strcmp(op, PCMK_VALUE_CREATE) == 0) {
 432                 fenced_register_level(change->children, NULL);
 433 
 434             } else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) {
 435                 xmlNode *match = pcmk__xe_first_child(change,
 436                                                       PCMK_XE_CHANGE_RESULT,
 437                                                       NULL, NULL);
 438 
 439                 if (match != NULL) {
 440                     remove_topology_level(match->children);
 441                     fenced_register_level(match->children, NULL);
 442                 }
 443             }
 444             continue;
 445         }
 446 
 447         if (strstr(xpath, "/" PCMK_XE_FENCING_TOPOLOGY) != NULL) {
 448             // Change to the topology in general
 449             crm_info("Re-initializing fencing topology after top-level "
 450                      "%s operation %d.%d.%d for %s",
 451                      op, add[0], add[1], add[2], xpath);
 452             fencing_topology_init();
 453             return;
 454         }
 455 
 456         if ((strstr(xpath, "/" PCMK_XE_CONFIGURATION) != NULL)
 457             && (pcmk__xe_first_child(change, PCMK_XE_FENCING_TOPOLOGY, NULL,
 458                                      NULL) != NULL)
 459             && pcmk__str_any_of(op, PCMK_VALUE_CREATE, PCMK_VALUE_DELETE,
 460                                 NULL)) {
 461 
 462             // Topology was created or entire configuration section was deleted
 463             crm_info("Re-initializing fencing topology after top-level "
 464                      "%s operation %d.%d.%d for %s",
 465                      op, add[0], add[1], add[2], xpath);
 466             fencing_topology_init();
 467             return;
 468         }
 469 
 470         crm_trace("Nothing for us in %s operation %d.%d.%d for %s",
 471                   op, add[0], add[1], add[2], xpath);
 472     }
 473 }
 474 
 475 static void
 476 update_cib_cache_cb(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 477 {
 478     xmlNode *patchset = NULL;
 479     long long timeout_ms_saved = stonith_watchdog_timeout_ms;
 480     bool need_full_refresh = false;
 481 
 482     if(!have_cib_devices) {
 483         crm_trace("Skipping updates until we get a full dump");
 484         return;
 485 
 486     } else if(msg == NULL) {
 487         crm_trace("Missing %s update", event);
 488         return;
 489     }
 490 
 491     /* Maintain a local copy of the CIB so that we have full access
 492      * to device definitions, location constraints, and node attributes
 493      */
 494     if (local_cib != NULL) {
 495         int rc = pcmk_ok;
 496         xmlNode *wrapper = NULL;
 497 
 498         crm_element_value_int(msg, PCMK__XA_CIB_RC, &rc);
 499         if (rc != pcmk_ok) {
 500             return;
 501         }
 502 
 503         wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, NULL,
 504                                        NULL);
 505         patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
 506 
 507         rc = xml_apply_patchset(local_cib, patchset, TRUE);
 508         switch (rc) {
 509             case pcmk_ok:
 510             case -pcmk_err_old_data:
 511                 /* @TODO Full refresh (with or without query) in case of
 512                  * -pcmk_err_old_data? It seems wrong to call
 513                  * stonith_device_remove() based on primitive deletion in an
 514                  * old diff.
 515                  */
 516                 break;
 517             case -pcmk_err_diff_resync:
 518             case -pcmk_err_diff_failed:
 519                 crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc);
 520                 pcmk__xml_free(local_cib);
 521                 local_cib = NULL;
 522                 break;
 523             default:
 524                 crm_warn("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc);
 525                 pcmk__xml_free(local_cib);
 526                 local_cib = NULL;
 527         }
 528     }
 529 
 530     if (local_cib == NULL) {
 531         if (fenced_query_cib() != pcmk_rc_ok) {
 532             return;
 533         }
 534         need_full_refresh = true;
 535     }
 536 
 537     pcmk__refresh_node_caches_from_cib(local_cib);
 538     update_stonith_watchdog_timeout_ms(local_cib);
 539 
 540     if (timeout_ms_saved != stonith_watchdog_timeout_ms) {
 541         need_full_refresh = true;
 542     }
 543 
 544     if (need_full_refresh) {
 545         fencing_topology_init();
 546         cib_devices_update();
 547     } else {
 548         // Partial refresh
 549         update_fencing_topology(event, msg);
 550         update_cib_stonith_devices(patchset);
 551     }
 552 
 553     watchdog_device_update();
 554 }
 555 
 556 static void
 557 init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 558 {
 559     crm_info("Updating device list from CIB");
 560     have_cib_devices = TRUE;
 561     local_cib = pcmk__xml_copy(NULL, output);
 562 
 563     pcmk__refresh_node_caches_from_cib(local_cib);
 564     update_stonith_watchdog_timeout_ms(local_cib);
 565 
 566     fencing_topology_init();
 567     cib_devices_update();
 568     watchdog_device_update();
 569 }
 570 
 571 static void
 572 cib_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 573 {
 574     if (stonith_shutdown_flag) {
 575         crm_info("Connection to the CIB manager closed");
 576         return;
 577     } else {
 578         crm_crit("Lost connection to the CIB manager, shutting down");
 579     }
 580     if (cib_api) {
 581         cib_api->cmds->signoff(cib_api);
 582     }
 583     stonith_shutdown(0);
 584 }
 585 
 586 /*!
 587  * \internal
 588  * \brief Disconnect from CIB manager
 589  */
 590 void
 591 fenced_cib_cleanup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 592 {
 593     if (cib_api != NULL) {
 594         cib_api->cmds->del_notify_callback(cib_api, PCMK__VALUE_CIB_DIFF_NOTIFY,
 595                                            update_cib_cache_cb);
 596         cib__clean_up_connection(&cib_api);
 597     }
 598     pcmk__xml_free(local_cib);
 599     local_cib = NULL;
 600 }
 601 
 602 void
 603 setup_cib(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 604 {
 605     int rc, retries = 0;
 606 
 607     cib_api = cib_new();
 608     if (cib_api == NULL) {
 609         crm_err("No connection to the CIB manager");
 610         return;
 611     }
 612 
 613     do {
 614         sleep(retries);
 615         rc = cib_api->cmds->signon(cib_api, crm_system_name, cib_command);
 616     } while (rc == -ENOTCONN && ++retries < 5);
 617 
 618     if (rc != pcmk_ok) {
 619         crm_err("Could not connect to the CIB manager: %s (%d)", pcmk_strerror(rc), rc);
 620         return;
 621     }
 622 
 623     rc = cib_api->cmds->add_notify_callback(cib_api,
 624                                             PCMK__VALUE_CIB_DIFF_NOTIFY,
 625                                             update_cib_cache_cb);
 626     if (rc != pcmk_ok) {
 627         crm_err("Could not set CIB notification callback");
 628         return;
 629     }
 630 
 631     rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_none);
 632     cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL,
 633                                      "init_cib_cache_cb", init_cib_cache_cb);
 634     cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy);
 635     crm_info("Watching for fencing topology changes");
 636 }

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