This source file includes following definitions.
- node_has_attr
- add_topology_level
- topology_remove_helper
- remove_topology_level
- register_fencing_topology
- fencing_topology_init
- remove_cib_device
- update_stonith_watchdog_timeout_ms
- cib_devices_update
- update_cib_stonith_devices_v1
- update_cib_stonith_devices_v2
- update_cib_stonith_devices
- watchdog_device_update
- fenced_query_cib
- remove_fencing_topology
- update_fencing_topology
- update_cib_cache_cb
- init_cib_cache_cb
- cib_connection_destroy
- fenced_cib_cleanup
- setup_cib
1
2
3
4
5
6
7
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/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
33
34
35
36
37
38
39
40
41 gboolean
42 node_has_attr(const char *node, const char *name, const char *value)
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
51
52
53
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 = 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)
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_config_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)
86 {
87 char *desc = NULL;
88 pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
89 xmlNode *data = pcmk__xe_create(NULL, PCMK_XE_FENCING_LEVEL);
90
91 crm_xml_add(data, PCMK__XA_ST_ORIGIN, __func__);
92 crm_xml_add_int(data, PCMK_XA_INDEX, level);
93 crm_xml_add(data, PCMK_XA_TARGET, node);
94
95 fenced_unregister_level(data, &desc, &result);
96 fenced_send_config_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)
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, PCMK_XA_INDEX, &index);
112 topology_remove_helper(key, index);
113 free(key);
114 }
115
116 static void
117 register_fencing_topology(xmlXPathObjectPtr xpathObj)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 void
149 fencing_topology_init(void)
150 {
151 xmlXPathObjectPtr xpathObj = NULL;
152 const char *xpath = "//" PCMK_XE_FENCING_LEVEL;
153
154 crm_trace("Full topology refresh");
155 free_topology_list();
156 init_topology_list();
157
158
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)
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, PCMK_XA_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, PCMK_XA_ID);
185
186 stonith_device_remove(rsc_id, true);
187 }
188 }
189
190 #define XPATH_WATCHDOG_TIMEOUT "//" PCMK_XE_NVPAIR \
191 "[@" PCMK_XA_NAME "='" \
192 PCMK_OPT_STONITH_WATCHDOG_TIMEOUT "']"
193
194 static void
195 update_stonith_watchdog_timeout_ms(xmlNode *cib)
196 {
197 long long timeout_ms = 0;
198 xmlNode *stonith_watchdog_xml = NULL;
199 const char *value = NULL;
200
201 stonith_watchdog_xml = get_xpath_object(XPATH_WATCHDOG_TIMEOUT, cib,
202 LOG_NEVER);
203 if (stonith_watchdog_xml) {
204 value = crm_element_value(stonith_watchdog_xml, PCMK_XA_VALUE);
205 }
206 if (value) {
207 timeout_ms = crm_get_msec(value);
208 }
209
210 if (timeout_ms < 0) {
211 timeout_ms = pcmk__auto_stonith_watchdog_timeout();
212 }
213
214 stonith_watchdog_timeout_ms = timeout_ms;
215 }
216
217
218
219
220
221 static void
222 cib_devices_update(void)
223 {
224 GHashTableIter iter;
225 stonith_device_t *device = NULL;
226
227 crm_info("Updating devices to version %s.%s.%s",
228 crm_element_value(local_cib, PCMK_XA_ADMIN_EPOCH),
229 crm_element_value(local_cib, PCMK_XA_EPOCH),
230 crm_element_value(local_cib, PCMK_XA_NUM_UPDATES));
231
232 g_hash_table_iter_init(&iter, device_list);
233 while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
234 if (device->cib_registered) {
235 device->dirty = TRUE;
236 }
237 }
238
239
240
241
242 g_list_free_full(stonith_watchdog_targets, free);
243 stonith_watchdog_targets = NULL;
244
245 fenced_scheduler_run(local_cib);
246
247 g_hash_table_iter_init(&iter, device_list);
248 while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
249 if (device->dirty) {
250 g_hash_table_iter_remove(&iter);
251 }
252 }
253 }
254
255 static void
256 update_cib_stonith_devices_v1(const char *event, xmlNode * msg)
257 {
258 const char *reason = "none";
259 gboolean needs_update = FALSE;
260 xmlXPathObjectPtr xpath_obj = NULL;
261
262
263 xpath_obj = xpath_search(msg,
264 "//" PCMK__XE_CIB_UPDATE_RESULT
265 "//" PCMK_XE_RSC_LOCATION);
266 if (numXpathResults(xpath_obj) > 0) {
267 int max = numXpathResults(xpath_obj), lpc = 0;
268
269
270 needs_update = TRUE;
271 reason = "new location constraint";
272
273 for (lpc = 0; lpc < max; lpc++) {
274 xmlNode *match = getXpathResult(xpath_obj, lpc);
275
276 crm_log_xml_trace(match, "new constraint");
277 }
278 }
279 freeXpathObject(xpath_obj);
280
281
282 xpath_obj = xpath_search(msg,
283 "//" PCMK__XE_CIB_UPDATE_RESULT
284 "//" PCMK__XE_DIFF_REMOVED
285 "//" PCMK_XE_PRIMITIVE);
286 if (numXpathResults(xpath_obj) > 0) {
287 remove_cib_device(xpath_obj);
288 }
289 freeXpathObject(xpath_obj);
290
291
292 xpath_obj = xpath_search(msg,
293 "//" PCMK__XE_CIB_UPDATE_RESULT
294 "//" PCMK__XE_DIFF_ADDED
295 "//" PCMK_XE_PRIMITIVE);
296 if (numXpathResults(xpath_obj) > 0) {
297 int max = numXpathResults(xpath_obj), lpc = 0;
298
299 for (lpc = 0; lpc < max; lpc++) {
300 const char *rsc_id = NULL;
301 const char *standard = NULL;
302 xmlNode *match = getXpathResult(xpath_obj, lpc);
303
304 rsc_id = crm_element_value(match, PCMK_XA_ID);
305 standard = crm_element_value(match, PCMK_XA_CLASS);
306
307 if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
308 continue;
309 }
310
311 crm_trace("Fencing resource %s was added or modified", rsc_id);
312 reason = "new resource";
313 needs_update = TRUE;
314 }
315 }
316 freeXpathObject(xpath_obj);
317
318 if(needs_update) {
319 crm_info("Updating device list from CIB: %s", reason);
320 cib_devices_update();
321 }
322 }
323
324 static void
325 update_cib_stonith_devices_v2(const char *event, xmlNode * msg)
326 {
327 xmlNode *change = NULL;
328 char *reason = NULL;
329 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT,
330 NULL, NULL);
331 xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
332
333 for (change = pcmk__xe_first_child(patchset, NULL, NULL, NULL);
334 change != NULL; change = pcmk__xe_next(change)) {
335
336 const char *op = crm_element_value(change, PCMK_XA_OPERATION);
337 const char *xpath = crm_element_value(change, PCMK_XA_PATH);
338 const char *shortpath = NULL;
339
340 if (pcmk__str_eq(op, PCMK_VALUE_MOVE, pcmk__str_null_matches)
341 || (strstr(xpath, "/" PCMK_XE_STATUS) != NULL)) {
342 continue;
343 }
344
345 if (pcmk__str_eq(op, PCMK_VALUE_DELETE, pcmk__str_none)
346 && (strstr(xpath, "/" PCMK_XE_PRIMITIVE) != NULL)) {
347 const char *rsc_id = NULL;
348 char *search = NULL;
349 char *mutable = NULL;
350
351 if ((strstr(xpath, PCMK_XE_INSTANCE_ATTRIBUTES) != NULL)
352 || (strstr(xpath, PCMK_XE_META_ATTRIBUTES) != NULL)) {
353
354 reason = pcmk__str_copy("(meta) attribute deleted from "
355 "resource");
356 break;
357 }
358 mutable = pcmk__str_copy(xpath);
359 rsc_id = strstr(mutable, PCMK_XE_PRIMITIVE "[@" PCMK_XA_ID "=\'");
360 if (rsc_id != NULL) {
361 rsc_id += strlen(PCMK_XE_PRIMITIVE "[@" PCMK_XA_ID "=\'");
362 search = strchr(rsc_id, '\'');
363 }
364 if (search != NULL) {
365 *search = 0;
366 stonith_device_remove(rsc_id, true);
367
368
369 } else {
370 crm_warn("Ignoring malformed CIB update (resource deletion)");
371 }
372 free(mutable);
373
374 } else if (strstr(xpath, "/" PCMK_XE_RESOURCES)
375 || strstr(xpath, "/" PCMK_XE_CONSTRAINTS)
376 || strstr(xpath, "/" PCMK_XE_RSC_DEFAULTS)) {
377 shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath);
378 reason = crm_strdup_printf("%s %s", op, shortpath+1);
379 break;
380 }
381 }
382
383 if (reason != NULL) {
384 crm_info("Updating device list from CIB: %s", reason);
385 cib_devices_update();
386 free(reason);
387 } else {
388 crm_trace("No updates for device list found in CIB");
389 }
390 }
391
392 static void
393 update_cib_stonith_devices(const char *event, xmlNode * msg)
394 {
395 int format = 1;
396 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT,
397 NULL, NULL);
398 xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
399
400 CRM_ASSERT(patchset);
401 crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
402 switch(format) {
403 case 1:
404 update_cib_stonith_devices_v1(event, msg);
405 break;
406 case 2:
407 update_cib_stonith_devices_v2(event, msg);
408 break;
409 default:
410 crm_warn("Unknown patch format: %d", format);
411 }
412 }
413
414 static void
415 watchdog_device_update(void)
416 {
417 if (stonith_watchdog_timeout_ms > 0) {
418 if (!g_hash_table_lookup(device_list, STONITH_WATCHDOG_ID) &&
419 !stonith_watchdog_targets) {
420
421
422
423 int rc;
424 xmlNode *xml;
425
426 xml = create_device_registration_xml(
427 STONITH_WATCHDOG_ID,
428 st_namespace_internal,
429 STONITH_WATCHDOG_AGENT,
430 NULL,
431
432
433
434 NULL);
435 rc = stonith_device_register(xml, TRUE);
436 free_xml(xml);
437 if (rc != pcmk_ok) {
438 rc = pcmk_legacy2rc(rc);
439 exit_code = CRM_EX_FATAL;
440 crm_crit("Cannot register watchdog pseudo fence agent: %s",
441 pcmk_rc_str(rc));
442 stonith_shutdown(0);
443 }
444 }
445
446 } else if (g_hash_table_lookup(device_list, STONITH_WATCHDOG_ID) != NULL) {
447
448 stonith_device_remove(STONITH_WATCHDOG_ID, true);
449 }
450 }
451
452
453
454
455
456
457
458 static int
459 fenced_query_cib(void)
460 {
461 int rc = pcmk_ok;
462
463 crm_trace("Re-requesting full CIB");
464 rc = cib_api->cmds->query(cib_api, NULL, &local_cib,
465 cib_scope_local|cib_sync_call);
466 rc = pcmk_legacy2rc(rc);
467 if (rc == pcmk_rc_ok) {
468 CRM_ASSERT(local_cib != NULL);
469 } else {
470 crm_err("Couldn't retrieve the CIB: %s " CRM_XS " rc=%d",
471 pcmk_rc_str(rc), rc);
472 }
473 return rc;
474 }
475
476 static void
477 remove_fencing_topology(xmlXPathObjectPtr xpathObj)
478 {
479 int max = numXpathResults(xpathObj), lpc = 0;
480
481 for (lpc = 0; lpc < max; lpc++) {
482 xmlNode *match = getXpathResult(xpathObj, lpc);
483
484 CRM_LOG_ASSERT(match != NULL);
485 if (match && crm_element_value(match, PCMK__XA_CRM_DIFF_MARKER)) {
486
487 int index = 0;
488 char *target = stonith_level_key(match, fenced_target_by_unknown);
489
490 crm_element_value_int(match, PCMK_XA_INDEX, &index);
491 if (target == NULL) {
492 crm_err("Invalid fencing target in element %s",
493 pcmk__xe_id(match));
494
495 } else if (index <= 0) {
496 crm_err("Invalid level for %s in element %s",
497 target, pcmk__xe_id(match));
498
499 } else {
500 topology_remove_helper(target, index);
501 }
502
503 }
504 }
505 }
506
507 static void
508 update_fencing_topology(const char *event, xmlNode * msg)
509 {
510 int format = 1;
511 const char *xpath;
512 xmlXPathObjectPtr xpathObj = NULL;
513 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT,
514 NULL, NULL);
515 xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
516
517 CRM_ASSERT(patchset);
518 crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
519
520 if(format == 1) {
521
522 xpath = "//" PCMK__XE_CIB_UPDATE_RESULT
523 "//" PCMK__XE_DIFF_REMOVED
524 "//" PCMK_XE_FENCING_LEVEL;
525 xpathObj = xpath_search(msg, xpath);
526
527 remove_fencing_topology(xpathObj);
528 freeXpathObject(xpathObj);
529
530
531 xpath = "//" PCMK__XE_CIB_UPDATE_RESULT
532 "//" PCMK__XE_DIFF_ADDED
533 "//" PCMK_XE_FENCING_LEVEL;
534 xpathObj = xpath_search(msg, xpath);
535
536 register_fencing_topology(xpathObj);
537 freeXpathObject(xpathObj);
538
539 } else if(format == 2) {
540 xmlNode *change = NULL;
541 int add[] = { 0, 0, 0 };
542 int del[] = { 0, 0, 0 };
543
544 xml_patch_versions(patchset, add, del);
545
546 for (change = pcmk__xe_first_child(patchset, NULL, NULL, NULL);
547 change != NULL; change = pcmk__xe_next(change)) {
548
549 const char *op = crm_element_value(change, PCMK_XA_OPERATION);
550 const char *xpath = crm_element_value(change, PCMK_XA_PATH);
551
552 if(op == NULL) {
553 continue;
554
555 } else if(strstr(xpath, "/" PCMK_XE_FENCING_LEVEL) != NULL) {
556
557
558 crm_trace("Handling %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath);
559 if (strcmp(op, PCMK_VALUE_MOVE) == 0) {
560 continue;
561
562 } else if (strcmp(op, PCMK_VALUE_CREATE) == 0) {
563 add_topology_level(change->children);
564
565 } else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) {
566 xmlNode *match = pcmk__xe_first_child(change,
567 PCMK_XE_CHANGE_RESULT,
568 NULL, NULL);
569
570 if(match) {
571 remove_topology_level(match->children);
572 add_topology_level(match->children);
573 }
574
575 } else if (strcmp(op, PCMK_VALUE_DELETE) == 0) {
576
577 crm_info("Re-initializing fencing topology after %s operation %d.%d.%d for %s",
578 op, add[0], add[1], add[2], xpath);
579 fencing_topology_init();
580 return;
581 }
582
583 } else if (strstr(xpath, "/" PCMK_XE_FENCING_TOPOLOGY) != NULL) {
584
585 crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s",
586 op, add[0], add[1], add[2], xpath);
587 fencing_topology_init();
588 return;
589
590 } else if (strstr(xpath, "/" PCMK_XE_CONFIGURATION)) {
591
592 if (pcmk__xe_first_child(change, PCMK_XE_FENCING_TOPOLOGY, NULL,
593 NULL) == NULL) {
594 crm_trace("Nothing for us in %s operation %d.%d.%d for %s.",
595 op, add[0], add[1], add[2], xpath);
596
597 } else if (pcmk__str_any_of(op,
598 PCMK_VALUE_DELETE,
599 PCMK_VALUE_CREATE, NULL)) {
600 crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s.",
601 op, add[0], add[1], add[2], xpath);
602 fencing_topology_init();
603 return;
604 }
605
606 } else {
607 crm_trace("Nothing for us in %s operation %d.%d.%d for %s",
608 op, add[0], add[1], add[2], xpath);
609 }
610 }
611
612 } else {
613 crm_warn("Unknown patch format: %d", format);
614 }
615 }
616
617 static void
618 update_cib_cache_cb(const char *event, xmlNode * msg)
619 {
620 long long timeout_ms_saved = stonith_watchdog_timeout_ms;
621 bool need_full_refresh = false;
622
623 if(!have_cib_devices) {
624 crm_trace("Skipping updates until we get a full dump");
625 return;
626
627 } else if(msg == NULL) {
628 crm_trace("Missing %s update", event);
629 return;
630 }
631
632
633
634
635 if (local_cib != NULL) {
636 int rc = pcmk_ok;
637 xmlNode *wrapper = NULL;
638 xmlNode *patchset = NULL;
639
640 crm_element_value_int(msg, PCMK__XA_CIB_RC, &rc);
641 if (rc != pcmk_ok) {
642 return;
643 }
644
645 wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, NULL,
646 NULL);
647 patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
648
649 rc = xml_apply_patchset(local_cib, patchset, TRUE);
650 switch (rc) {
651 case pcmk_ok:
652 case -pcmk_err_old_data:
653 break;
654 case -pcmk_err_diff_resync:
655 case -pcmk_err_diff_failed:
656 crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc);
657 free_xml(local_cib);
658 local_cib = NULL;
659 break;
660 default:
661 crm_warn("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc);
662 free_xml(local_cib);
663 local_cib = NULL;
664 }
665 }
666
667 if (local_cib == NULL) {
668 if (fenced_query_cib() != pcmk_rc_ok) {
669 return;
670 }
671 need_full_refresh = true;
672 }
673
674 pcmk__refresh_node_caches_from_cib(local_cib);
675 update_stonith_watchdog_timeout_ms(local_cib);
676
677 if (timeout_ms_saved != stonith_watchdog_timeout_ms) {
678 need_full_refresh = true;
679 }
680
681 if (need_full_refresh) {
682 fencing_topology_init();
683 cib_devices_update();
684 } else {
685
686 update_fencing_topology(event, msg);
687 update_cib_stonith_devices(event, msg);
688 }
689
690 watchdog_device_update();
691 }
692
693 static void
694 init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
695 {
696 crm_info("Updating device list from CIB");
697 have_cib_devices = TRUE;
698 local_cib = pcmk__xml_copy(NULL, output);
699
700 pcmk__refresh_node_caches_from_cib(local_cib);
701 update_stonith_watchdog_timeout_ms(local_cib);
702
703 fencing_topology_init();
704 cib_devices_update();
705 watchdog_device_update();
706 }
707
708 static void
709 cib_connection_destroy(gpointer user_data)
710 {
711 if (stonith_shutdown_flag) {
712 crm_info("Connection to the CIB manager closed");
713 return;
714 } else {
715 crm_crit("Lost connection to the CIB manager, shutting down");
716 }
717 if (cib_api) {
718 cib_api->cmds->signoff(cib_api);
719 }
720 stonith_shutdown(0);
721 }
722
723
724
725
726
727 void
728 fenced_cib_cleanup(void)
729 {
730 if (cib_api != NULL) {
731 cib_api->cmds->del_notify_callback(cib_api, PCMK__VALUE_CIB_DIFF_NOTIFY,
732 update_cib_cache_cb);
733 cib__clean_up_connection(&cib_api);
734 }
735 free_xml(local_cib);
736 local_cib = NULL;
737 }
738
739 void
740 setup_cib(void)
741 {
742 int rc, retries = 0;
743
744 cib_api = cib_new();
745 if (cib_api == NULL) {
746 crm_err("No connection to the CIB manager");
747 return;
748 }
749
750 do {
751 sleep(retries);
752 rc = cib_api->cmds->signon(cib_api, CRM_SYSTEM_STONITHD, cib_command);
753 } while (rc == -ENOTCONN && ++retries < 5);
754
755 if (rc != pcmk_ok) {
756 crm_err("Could not connect to the CIB manager: %s (%d)", pcmk_strerror(rc), rc);
757 return;
758 }
759
760 rc = cib_api->cmds->add_notify_callback(cib_api,
761 PCMK__VALUE_CIB_DIFF_NOTIFY,
762 update_cib_cache_cb);
763 if (rc != pcmk_ok) {
764 crm_err("Could not set CIB notification callback");
765 return;
766 }
767
768 rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local);
769 cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL,
770 "init_cib_cache_cb", init_cib_cache_cb);
771 cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy);
772 crm_info("Watching for fencing topology changes");
773 }