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. add_topology_level
  3. topology_remove_helper
  4. remove_topology_level
  5. register_fencing_topology
  6. fencing_topology_init
  7. remove_cib_device
  8. update_stonith_watchdog_timeout_ms
  9. cib_devices_update
  10. update_cib_stonith_devices_v1
  11. update_cib_stonith_devices_v2
  12. update_cib_stonith_devices
  13. watchdog_device_update
  14. fenced_query_cib
  15. remove_fencing_topology
  16. update_fencing_topology
  17. update_cib_cache_cb
  18. init_cib_cache_cb
  19. cib_connection_destroy
  20. fenced_cib_cleanup
  21. setup_cib

   1 /*
   2  * Copyright 2009-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 <stdbool.h>
  13 #include <stdio.h>
  14 #include <libxml/tree.h>
  15 #include <libxml/xpath.h>
  16 
  17 #include <crm/crm.h>
  18 #include <crm/msg_xml.h>
  19 #include <crm/common/xml.h>
  20 
  21 #include <crm/cluster/internal.h>
  22 
  23 #include <crm/cib.h>
  24 #include <crm/cib/internal.h>
  25 
  26 #include <pacemaker-fenced.h>
  27 
  28 static xmlNode *local_cib = NULL;
  29 static cib_t *cib_api = NULL;
  30 static bool have_cib_devices = FALSE;
  31 
  32 /*!
  33  * \internal
  34  * \brief Check whether a node has a specific attribute name/value
  35  *
  36  * \param[in] node    Name of node to check
  37  * \param[in] name    Name of an attribute to look for
  38  * \param[in] value   The value the named attribute needs to be set to in order to be considered a match
  39  *
  40  * \return TRUE if the locally cached CIB has the specified node attribute
  41  */
  42 gboolean
  43 node_has_attr(const char *node, const char *name, const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45     GString *xpath = NULL;
  46     xmlNode *match;
  47 
  48     CRM_CHECK((local_cib != NULL) && (node != NULL) && (name != NULL)
  49               && (value != NULL), return FALSE);
  50 
  51     /* Search for the node's attributes in the CIB. While the schema allows
  52      * multiple sets of instance attributes, and allows instance attributes to
  53      * use id-ref to reference values elsewhere, that is intended for resources,
  54      * so we ignore that here.
  55      */
  56     xpath = g_string_sized_new(256);
  57     pcmk__g_strcat(xpath,
  58                    "//" XML_CIB_TAG_NODES "/" XML_CIB_TAG_NODE
  59                    "[@" XML_ATTR_UNAME "='", node, "']/" XML_TAG_ATTR_SETS
  60                    "/" XML_CIB_TAG_NVPAIR
  61                    "[@" XML_NVPAIR_ATTR_NAME "='", name, "' "
  62                    "and @" XML_NVPAIR_ATTR_VALUE "='", value, "']", NULL);
  63 
  64     match = get_xpath_object((const char *) xpath->str, local_cib, LOG_NEVER);
  65 
  66     g_string_free(xpath, TRUE);
  67     return (match != NULL);
  68 }
  69 
  70 static void
  71 add_topology_level(xmlNode *match)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73     char *desc = NULL;
  74     pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
  75 
  76     CRM_CHECK(match != NULL, return);
  77 
  78     fenced_register_level(match, &desc, &result);
  79     fenced_send_level_notification(STONITH_OP_LEVEL_ADD, &result, desc);
  80     pcmk__reset_result(&result);
  81     free(desc);
  82 }
  83 
  84 static void
  85 topology_remove_helper(const char *node, int level)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87     char *desc = NULL;
  88     pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
  89     xmlNode *data = create_xml_node(NULL, XML_TAG_FENCING_LEVEL);
  90 
  91     crm_xml_add(data, F_STONITH_ORIGIN, __func__);
  92     crm_xml_add_int(data, XML_ATTR_STONITH_INDEX, level);
  93     crm_xml_add(data, XML_ATTR_STONITH_TARGET, node);
  94 
  95     fenced_unregister_level(data, &desc, &result);
  96     fenced_send_level_notification(STONITH_OP_LEVEL_DEL, &result, desc);
  97     pcmk__reset_result(&result);
  98     free_xml(data);
  99     free(desc);
 100 }
 101 
 102 static void
 103 remove_topology_level(xmlNode *match)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105     int index = 0;
 106     char *key = NULL;
 107 
 108     CRM_CHECK(match != NULL, return);
 109 
 110     key = stonith_level_key(match, fenced_target_by_unknown);
 111     crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
 112     topology_remove_helper(key, index);
 113     free(key);
 114 }
 115 
 116 static void
 117 register_fencing_topology(xmlXPathObjectPtr xpathObj)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119     int max = numXpathResults(xpathObj), lpc = 0;
 120 
 121     for (lpc = 0; lpc < max; lpc++) {
 122         xmlNode *match = getXpathResult(xpathObj, lpc);
 123 
 124         remove_topology_level(match);
 125         add_topology_level(match);
 126     }
 127 }
 128 
 129 /* Fencing
 130 <diff crm_feature_set="3.0.6">
 131   <diff-removed>
 132     <fencing-topology>
 133       <fencing-level id="f-p1.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="removed:top"/>
 134       <fencing-level id="f-p1.2" target="pcmk-1" index="2" devices="power" __crm_diff_marker__="removed:top"/>
 135       <fencing-level devices="disk,network" id="f-p2.1"/>
 136     </fencing-topology>
 137   </diff-removed>
 138   <diff-added>
 139     <fencing-topology>
 140       <fencing-level id="f-p.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="added:top"/>
 141       <fencing-level id="f-p2.1" target="pcmk-2" index="1" devices="disk,something"/>
 142       <fencing-level id="f-p3.1" target="pcmk-2" index="2" devices="power" __crm_diff_marker__="added:top"/>
 143     </fencing-topology>
 144   </diff-added>
 145 </diff>
 146 */
 147 
 148 void
 149 fencing_topology_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151     xmlXPathObjectPtr xpathObj = NULL;
 152     const char *xpath = "//" XML_TAG_FENCING_LEVEL;
 153 
 154     crm_trace("Full topology refresh");
 155     free_topology_list();
 156     init_topology_list();
 157 
 158     /* Grab everything */
 159     xpathObj = xpath_search(local_cib, xpath);
 160     register_fencing_topology(xpathObj);
 161 
 162     freeXpathObject(xpathObj);
 163 }
 164 
 165 static void
 166 remove_cib_device(xmlXPathObjectPtr xpathObj)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168     int max = numXpathResults(xpathObj), lpc = 0;
 169 
 170     for (lpc = 0; lpc < max; lpc++) {
 171         const char *rsc_id = NULL;
 172         const char *standard = NULL;
 173         xmlNode *match = getXpathResult(xpathObj, lpc);
 174 
 175         CRM_LOG_ASSERT(match != NULL);
 176         if(match != NULL) {
 177             standard = crm_element_value(match, XML_AGENT_ATTR_CLASS);
 178         }
 179 
 180         if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
 181             continue;
 182         }
 183 
 184         rsc_id = crm_element_value(match, XML_ATTR_ID);
 185 
 186         stonith_device_remove(rsc_id, true);
 187     }
 188 }
 189 
 190 static void
 191 update_stonith_watchdog_timeout_ms(xmlNode *cib)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193     long timeout_ms = 0;
 194     xmlNode *stonith_watchdog_xml = NULL;
 195     const char *value = NULL;
 196 
 197     stonith_watchdog_xml = get_xpath_object("//nvpair[@name='stonith-watchdog-timeout']",
 198                                             cib, LOG_NEVER);
 199     if (stonith_watchdog_xml) {
 200         value = crm_element_value(stonith_watchdog_xml, XML_NVPAIR_ATTR_VALUE);
 201     }
 202     if (value) {
 203         timeout_ms = crm_get_msec(value);
 204     }
 205 
 206     if (timeout_ms < 0) {
 207         timeout_ms = pcmk__auto_watchdog_timeout();
 208     }
 209 
 210     stonith_watchdog_timeout_ms = timeout_ms;
 211 }
 212 
 213 /*!
 214  * \internal
 215  * \brief Update all STONITH device definitions based on current CIB
 216  */
 217 static void
 218 cib_devices_update(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220     GHashTableIter iter;
 221     stonith_device_t *device = NULL;
 222 
 223     crm_info("Updating devices to version %s.%s.%s",
 224              crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN),
 225              crm_element_value(local_cib, XML_ATTR_GENERATION),
 226              crm_element_value(local_cib, XML_ATTR_NUMUPDATES));
 227 
 228     g_hash_table_iter_init(&iter, device_list);
 229     while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
 230         if (device->cib_registered) {
 231             device->dirty = TRUE;
 232         }
 233     }
 234 
 235     /* have list repopulated if cib has a watchdog-fencing-resource
 236        TODO: keep a cached list for queries happening while we are refreshing
 237      */
 238     g_list_free_full(stonith_watchdog_targets, free);
 239     stonith_watchdog_targets = NULL;
 240 
 241     fenced_scheduler_run(local_cib);
 242 
 243     g_hash_table_iter_init(&iter, device_list);
 244     while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
 245         if (device->dirty) {
 246             g_hash_table_iter_remove(&iter);
 247         }
 248     }
 249 }
 250 
 251 static void
 252 update_cib_stonith_devices_v1(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 253 {
 254     const char *reason = "none";
 255     gboolean needs_update = FALSE;
 256     xmlXPathObjectPtr xpath_obj = NULL;
 257 
 258     /* process new constraints */
 259     xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_CONS_TAG_RSC_LOCATION);
 260     if (numXpathResults(xpath_obj) > 0) {
 261         int max = numXpathResults(xpath_obj), lpc = 0;
 262 
 263         /* Safest and simplest to always recompute */
 264         needs_update = TRUE;
 265         reason = "new location constraint";
 266 
 267         for (lpc = 0; lpc < max; lpc++) {
 268             xmlNode *match = getXpathResult(xpath_obj, lpc);
 269 
 270             crm_log_xml_trace(match, "new constraint");
 271         }
 272     }
 273     freeXpathObject(xpath_obj);
 274 
 275     /* process deletions */
 276     xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_CIB_TAG_RESOURCE);
 277     if (numXpathResults(xpath_obj) > 0) {
 278         remove_cib_device(xpath_obj);
 279     }
 280     freeXpathObject(xpath_obj);
 281 
 282     /* process additions */
 283     xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_RESOURCE);
 284     if (numXpathResults(xpath_obj) > 0) {
 285         int max = numXpathResults(xpath_obj), lpc = 0;
 286 
 287         for (lpc = 0; lpc < max; lpc++) {
 288             const char *rsc_id = NULL;
 289             const char *standard = NULL;
 290             xmlNode *match = getXpathResult(xpath_obj, lpc);
 291 
 292             rsc_id = crm_element_value(match, XML_ATTR_ID);
 293             standard = crm_element_value(match, XML_AGENT_ATTR_CLASS);
 294 
 295             if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
 296                 continue;
 297             }
 298 
 299             crm_trace("Fencing resource %s was added or modified", rsc_id);
 300             reason = "new resource";
 301             needs_update = TRUE;
 302         }
 303     }
 304     freeXpathObject(xpath_obj);
 305 
 306     if(needs_update) {
 307         crm_info("Updating device list from CIB: %s", reason);
 308         cib_devices_update();
 309     }
 310 }
 311 
 312 static void
 313 update_cib_stonith_devices_v2(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 314 {
 315     xmlNode *change = NULL;
 316     char *reason = NULL;
 317     bool needs_update = FALSE;
 318     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 319 
 320     for (change = pcmk__xml_first_child(patchset); change != NULL;
 321          change = pcmk__xml_next(change)) {
 322         const char *op = crm_element_value(change, XML_DIFF_OP);
 323         const char *xpath = crm_element_value(change, XML_DIFF_PATH);
 324         const char *shortpath = NULL;
 325 
 326         if ((op == NULL) ||
 327             (strcmp(op, "move") == 0) ||
 328             strstr(xpath, "/"XML_CIB_TAG_STATUS)) {
 329             continue;
 330         } else if (pcmk__str_eq(op, "delete", pcmk__str_casei) && strstr(xpath, "/"XML_CIB_TAG_RESOURCE)) {
 331             const char *rsc_id = NULL;
 332             char *search = NULL;
 333             char *mutable = NULL;
 334 
 335             if (strstr(xpath, XML_TAG_ATTR_SETS) ||
 336                 strstr(xpath, XML_TAG_META_SETS)) {
 337                 needs_update = TRUE;
 338                 pcmk__str_update(&reason,
 339                                  "(meta) attribute deleted from resource");
 340                 break;
 341             }
 342             pcmk__str_update(&mutable, xpath);
 343             rsc_id = strstr(mutable, "primitive[@" XML_ATTR_ID "=\'");
 344             if (rsc_id != NULL) {
 345                 rsc_id += strlen("primitive[@" XML_ATTR_ID "=\'");
 346                 search = strchr(rsc_id, '\'');
 347             }
 348             if (search != NULL) {
 349                 *search = 0;
 350                 stonith_device_remove(rsc_id, true);
 351                 /* watchdog_device_update called afterwards
 352                    to fall back to implicit definition if needed */
 353             } else {
 354                 crm_warn("Ignoring malformed CIB update (resource deletion)");
 355             }
 356             free(mutable);
 357 
 358         } else if (strstr(xpath, "/"XML_CIB_TAG_RESOURCES) ||
 359                    strstr(xpath, "/"XML_CIB_TAG_CONSTRAINTS) ||
 360                    strstr(xpath, "/"XML_CIB_TAG_RSCCONFIG)) {
 361             shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath);
 362             reason = crm_strdup_printf("%s %s", op, shortpath+1);
 363             needs_update = TRUE;
 364             break;
 365         }
 366     }
 367 
 368     if(needs_update) {
 369         crm_info("Updating device list from CIB: %s", reason);
 370         cib_devices_update();
 371     } else {
 372         crm_trace("No updates for device list found in CIB");
 373     }
 374     free(reason);
 375 }
 376 
 377 static void
 378 update_cib_stonith_devices(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380     int format = 1;
 381     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 382 
 383     CRM_ASSERT(patchset);
 384     crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
 385     switch(format) {
 386         case 1:
 387             update_cib_stonith_devices_v1(event, msg);
 388             break;
 389         case 2:
 390             update_cib_stonith_devices_v2(event, msg);
 391             break;
 392         default:
 393             crm_warn("Unknown patch format: %d", format);
 394     }
 395 }
 396 
 397 static void
 398 watchdog_device_update(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400     if (stonith_watchdog_timeout_ms > 0) {
 401         if (!g_hash_table_lookup(device_list, STONITH_WATCHDOG_ID) &&
 402             !stonith_watchdog_targets) {
 403             /* getting here watchdog-fencing enabled, no device there yet
 404                and reason isn't stonith_watchdog_targets preventing that
 405              */
 406             int rc;
 407             xmlNode *xml;
 408 
 409             xml = create_device_registration_xml(
 410                     STONITH_WATCHDOG_ID,
 411                     st_namespace_internal,
 412                     STONITH_WATCHDOG_AGENT,
 413                     NULL, /* stonith_device_register will add our
 414                              own name as PCMK_STONITH_HOST_LIST param
 415                              so we can skip that here
 416                            */
 417                     NULL);
 418             rc = stonith_device_register(xml, TRUE);
 419             free_xml(xml);
 420             if (rc != pcmk_ok) {
 421                 rc = pcmk_legacy2rc(rc);
 422                 exit_code = CRM_EX_FATAL;
 423                 crm_crit("Cannot register watchdog pseudo fence agent: %s",
 424                          pcmk_rc_str(rc));
 425                 stonith_shutdown(0);
 426             }
 427         }
 428 
 429     } else if (g_hash_table_lookup(device_list, STONITH_WATCHDOG_ID) != NULL) {
 430         /* be silent if no device - todo parameter to stonith_device_remove */
 431         stonith_device_remove(STONITH_WATCHDOG_ID, true);
 432     }
 433 }
 434 
 435 /*!
 436  * \internal
 437  * \brief Query the full CIB
 438  *
 439  * \return Standard Pacemaker return code
 440  */
 441 static int
 442 fenced_query_cib(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 443 {
 444     int rc = pcmk_ok;
 445 
 446     crm_trace("Re-requesting full CIB");
 447     rc = cib_api->cmds->query(cib_api, NULL, &local_cib,
 448                               cib_scope_local|cib_sync_call);
 449     rc = pcmk_legacy2rc(rc);
 450     if (rc == pcmk_rc_ok) {
 451         CRM_ASSERT(local_cib != NULL);
 452     } else {
 453         crm_err("Couldn't retrieve the CIB: %s " CRM_XS " rc=%d",
 454                 pcmk_rc_str(rc), rc);
 455     }
 456     return rc;
 457 }
 458 
 459 static void
 460 remove_fencing_topology(xmlXPathObjectPtr xpathObj)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462     int max = numXpathResults(xpathObj), lpc = 0;
 463 
 464     for (lpc = 0; lpc < max; lpc++) {
 465         xmlNode *match = getXpathResult(xpathObj, lpc);
 466 
 467         CRM_LOG_ASSERT(match != NULL);
 468         if (match && crm_element_value(match, XML_DIFF_MARKER)) {
 469             /* Deletion */
 470             int index = 0;
 471             char *target = stonith_level_key(match, fenced_target_by_unknown);
 472 
 473             crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
 474             if (target == NULL) {
 475                 crm_err("Invalid fencing target in element %s", ID(match));
 476 
 477             } else if (index <= 0) {
 478                 crm_err("Invalid level for %s in element %s", target, ID(match));
 479 
 480             } else {
 481                 topology_remove_helper(target, index);
 482             }
 483             /* } else { Deal with modifications during the 'addition' stage */
 484         }
 485     }
 486 }
 487 
 488 static void
 489 update_fencing_topology(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 490 {
 491     int format = 1;
 492     const char *xpath;
 493     xmlXPathObjectPtr xpathObj = NULL;
 494     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 495 
 496     CRM_ASSERT(patchset);
 497     crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
 498 
 499     if(format == 1) {
 500         /* Process deletions (only) */
 501         xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_FENCING_LEVEL;
 502         xpathObj = xpath_search(msg, xpath);
 503 
 504         remove_fencing_topology(xpathObj);
 505         freeXpathObject(xpathObj);
 506 
 507         /* Process additions and changes */
 508         xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL;
 509         xpathObj = xpath_search(msg, xpath);
 510 
 511         register_fencing_topology(xpathObj);
 512         freeXpathObject(xpathObj);
 513 
 514     } else if(format == 2) {
 515         xmlNode *change = NULL;
 516         int add[] = { 0, 0, 0 };
 517         int del[] = { 0, 0, 0 };
 518 
 519         xml_patch_versions(patchset, add, del);
 520 
 521         for (change = pcmk__xml_first_child(patchset); change != NULL;
 522              change = pcmk__xml_next(change)) {
 523             const char *op = crm_element_value(change, XML_DIFF_OP);
 524             const char *xpath = crm_element_value(change, XML_DIFF_PATH);
 525 
 526             if(op == NULL) {
 527                 continue;
 528 
 529             } else if(strstr(xpath, "/" XML_TAG_FENCING_LEVEL) != NULL) {
 530                 /* Change to a specific entry */
 531 
 532                 crm_trace("Handling %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath);
 533                 if(strcmp(op, "move") == 0) {
 534                     continue;
 535 
 536                 } else if(strcmp(op, "create") == 0) {
 537                     add_topology_level(change->children);
 538 
 539                 } else if(strcmp(op, "modify") == 0) {
 540                     xmlNode *match = first_named_child(change, XML_DIFF_RESULT);
 541 
 542                     if(match) {
 543                         remove_topology_level(match->children);
 544                         add_topology_level(match->children);
 545                     }
 546 
 547                 } else if(strcmp(op, "delete") == 0) {
 548                     /* Nuclear option, all we have is the path and an id... not enough to remove a specific entry */
 549                     crm_info("Re-initializing fencing topology after %s operation %d.%d.%d for %s",
 550                              op, add[0], add[1], add[2], xpath);
 551                     fencing_topology_init();
 552                     return;
 553                 }
 554 
 555             } else if (strstr(xpath, "/" XML_TAG_FENCING_TOPOLOGY) != NULL) {
 556                 /* Change to the topology in general */
 557                 crm_info("Re-initializing fencing topology after top-level %s operation  %d.%d.%d for %s",
 558                          op, add[0], add[1], add[2], xpath);
 559                 fencing_topology_init();
 560                 return;
 561 
 562             } else if (strstr(xpath, "/" XML_CIB_TAG_CONFIGURATION)) {
 563                 /* Changes to the whole config section, possibly including the topology as a whild */
 564                 if(first_named_child(change, XML_TAG_FENCING_TOPOLOGY) == NULL) {
 565                     crm_trace("Nothing for us in %s operation %d.%d.%d for %s.",
 566                               op, add[0], add[1], add[2], xpath);
 567 
 568                 } else if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) {
 569                     crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s.",
 570                              op, add[0], add[1], add[2], xpath);
 571                     fencing_topology_init();
 572                     return;
 573                 }
 574 
 575             } else {
 576                 crm_trace("Nothing for us in %s operation %d.%d.%d for %s",
 577                           op, add[0], add[1], add[2], xpath);
 578             }
 579         }
 580 
 581     } else {
 582         crm_warn("Unknown patch format: %d", format);
 583     }
 584 }
 585 
 586 static void
 587 update_cib_cache_cb(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 588 {
 589     long timeout_ms_saved = stonith_watchdog_timeout_ms;
 590     bool need_full_refresh = false;
 591 
 592     if(!have_cib_devices) {
 593         crm_trace("Skipping updates until we get a full dump");
 594         return;
 595 
 596     } else if(msg == NULL) {
 597         crm_trace("Missing %s update", event);
 598         return;
 599     }
 600 
 601     /* Maintain a local copy of the CIB so that we have full access
 602      * to device definitions, location constraints, and node attributes
 603      */
 604     if (local_cib != NULL) {
 605         int rc = pcmk_ok;
 606         xmlNode *patchset = NULL;
 607 
 608         crm_element_value_int(msg, F_CIB_RC, &rc);
 609         if (rc != pcmk_ok) {
 610             return;
 611         }
 612 
 613         patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 614         rc = xml_apply_patchset(local_cib, patchset, TRUE);
 615         switch (rc) {
 616             case pcmk_ok:
 617             case -pcmk_err_old_data:
 618                 break;
 619             case -pcmk_err_diff_resync:
 620             case -pcmk_err_diff_failed:
 621                 crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc);
 622                 free_xml(local_cib);
 623                 local_cib = NULL;
 624                 break;
 625             default:
 626                 crm_warn("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc);
 627                 free_xml(local_cib);
 628                 local_cib = NULL;
 629         }
 630     }
 631 
 632     if (local_cib == NULL) {
 633         if (fenced_query_cib() != pcmk_rc_ok) {
 634             return;
 635         }
 636         need_full_refresh = true;
 637     }
 638 
 639     pcmk__refresh_node_caches_from_cib(local_cib);
 640     update_stonith_watchdog_timeout_ms(local_cib);
 641 
 642     if (timeout_ms_saved != stonith_watchdog_timeout_ms) {
 643         need_full_refresh = true;
 644     }
 645 
 646     if (need_full_refresh) {
 647         fencing_topology_init();
 648         cib_devices_update();
 649     } else {
 650         // Partial refresh
 651         update_fencing_topology(event, msg);
 652         update_cib_stonith_devices(event, msg);
 653     }
 654 
 655     watchdog_device_update();
 656 }
 657 
 658 static void
 659 init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 660 {
 661     crm_info("Updating device list from CIB");
 662     have_cib_devices = TRUE;
 663     local_cib = copy_xml(output);
 664 
 665     pcmk__refresh_node_caches_from_cib(local_cib);
 666     update_stonith_watchdog_timeout_ms(local_cib);
 667 
 668     fencing_topology_init();
 669     cib_devices_update();
 670     watchdog_device_update();
 671 }
 672 
 673 static void
 674 cib_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 675 {
 676     if (stonith_shutdown_flag) {
 677         crm_info("Connection to the CIB manager closed");
 678         return;
 679     } else {
 680         crm_crit("Lost connection to the CIB manager, shutting down");
 681     }
 682     if (cib_api) {
 683         cib_api->cmds->signoff(cib_api);
 684     }
 685     stonith_shutdown(0);
 686 }
 687 
 688 /*!
 689  * \internal
 690  * \brief Disconnect from CIB manager
 691  */
 692 void
 693 fenced_cib_cleanup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 694 {
 695     if (cib_api != NULL) {
 696         cib_api->cmds->del_notify_callback(cib_api, T_CIB_DIFF_NOTIFY,
 697                                            update_cib_cache_cb);
 698         cib__clean_up_connection(&cib_api);
 699     }
 700     free_xml(local_cib);
 701     local_cib = NULL;
 702 }
 703 
 704 void
 705 setup_cib(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 706 {
 707     int rc, retries = 0;
 708 
 709     cib_api = cib_new();
 710     if (cib_api == NULL) {
 711         crm_err("No connection to the CIB manager");
 712         return;
 713     }
 714 
 715     do {
 716         sleep(retries);
 717         rc = cib_api->cmds->signon(cib_api, CRM_SYSTEM_STONITHD, cib_command);
 718     } while (rc == -ENOTCONN && ++retries < 5);
 719 
 720     if (rc != pcmk_ok) {
 721         crm_err("Could not connect to the CIB manager: %s (%d)", pcmk_strerror(rc), rc);
 722 
 723     } else if (pcmk_ok !=
 724                cib_api->cmds->add_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, update_cib_cache_cb)) {
 725         crm_err("Could not set CIB notification callback");
 726 
 727     } else {
 728         rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local);
 729         cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL, "init_cib_cache_cb",
 730                                          init_cib_cache_cb);
 731         cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy);
 732         crm_info("Watching for fencing topology changes");
 733     }
 734 }

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