pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
cib_utils.c
Go to the documentation of this file.
1/*
2 * Original copyright 2004 International Business Machines
3 * Later changes copyright 2008-2024 the Pacemaker project contributors
4 *
5 * The version control history for this file may have further details.
6 *
7 * This source code is licensed under the GNU Lesser General Public License
8 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
9 */
10#include <crm_internal.h>
11#include <unistd.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <stdarg.h>
15#include <string.h>
16#include <sys/utsname.h>
17
18#include <glib.h>
19
20#include <crm/crm.h>
21#include <crm/cib/internal.h>
23#include <crm/common/xml.h>
25#include <crm/pengine/rules.h>
26
27gboolean
28cib_version_details(xmlNode * cib, int *admin_epoch, int *epoch, int *updates)
29{
30 *epoch = -1;
31 *updates = -1;
32 *admin_epoch = -1;
33
34 if (cib == NULL) {
35 return FALSE;
36
37 } else {
41 }
42 return TRUE;
43}
44
45gboolean
46cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates,
47 int *_admin_epoch, int *_epoch, int *_updates)
48{
49 int add[] = { 0, 0, 0 };
50 int del[] = { 0, 0, 0 };
51
52 xml_patch_versions(diff, add, del);
53
54 *admin_epoch = add[0];
55 *epoch = add[1];
56 *updates = add[2];
57
58 *_admin_epoch = del[0];
59 *_epoch = del[1];
60 *_updates = del[2];
61
62 return TRUE;
63}
64
74int
75cib__get_notify_patchset(const xmlNode *msg, const xmlNode **patchset)
76{
77 int rc = pcmk_err_generic;
78 xmlNode *wrapper = NULL;
79
80 CRM_ASSERT(patchset != NULL);
81 *patchset = NULL;
82
83 if (msg == NULL) {
84 crm_err("CIB diff notification received with no XML");
85 return ENOMSG;
86 }
87
88 if ((crm_element_value_int(msg, PCMK__XA_CIB_RC, &rc) != 0)
89 || (rc != pcmk_ok)) {
90
91 crm_warn("Ignore failed CIB update: %s " CRM_XS " rc=%d",
92 pcmk_strerror(rc), rc);
93 crm_log_xml_debug(msg, "failed");
94 return pcmk_legacy2rc(rc);
95 }
96
97 wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, NULL, NULL);
98 *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
99
100 if (*patchset == NULL) {
101 crm_err("CIB diff notification received with no patchset");
102 return ENOMSG;
103 }
104 return pcmk_rc_ok;
105}
106
107#define XPATH_DIFF_V1 "//" PCMK__XE_CIB_UPDATE_RESULT "//" PCMK__XE_DIFF_ADDED
108
119static bool
120element_in_patchset_v1(const xmlNode *patchset, const char *element)
121{
122 char *xpath = crm_strdup_printf(XPATH_DIFF_V1 "//%s",
123 pcmk__s(element, PCMK_XE_CIB));
124 xmlXPathObject *xpath_obj = xpath_search(patchset, xpath);
125
126 free(xpath);
127
128 if (xpath_obj == NULL) {
129 return false;
130 }
131 freeXpathObject(xpath_obj);
132 return true;
133}
134
146static bool
147element_in_patchset_v2(const xmlNode *patchset, const char *element)
148{
149 const char *element_xpath = pcmk__cib_abs_xpath_for(element);
150 const char *parent_xpath = pcmk_cib_parent_name_for(element);
151 char *element_regex = NULL;
152 bool rc = false;
153
154 CRM_CHECK(element_xpath != NULL, return false); // Unsupported element
155
156 // Matches if and only if element_xpath is part of a changed path
157 element_regex = crm_strdup_printf("^%s(/|$)", element_xpath);
158
159 for (const xmlNode *change = pcmk__xe_first_child(patchset, PCMK_XE_CHANGE,
160 NULL, NULL);
161 change != NULL; change = pcmk__xe_next_same(change)) {
162
163 const char *op = crm_element_value(change, PCMK__XA_CIB_OP);
164 const char *diff_xpath = crm_element_value(change, PCMK_XA_PATH);
165
166 if (pcmk__str_eq(diff_xpath, element_regex, pcmk__str_regex)) {
167 // Change to an existing element
168 rc = true;
169 break;
170 }
171
172 if (pcmk__str_eq(op, PCMK_VALUE_CREATE, pcmk__str_none)
173 && pcmk__str_eq(diff_xpath, parent_xpath, pcmk__str_none)
174 && pcmk__xe_is(pcmk__xe_first_child(change, NULL, NULL, NULL),
175 element)) {
176
177 // Newly added element
178 rc = true;
179 break;
180 }
181 }
182
183 free(element_regex);
184 return rc;
185}
186
198bool
199cib__element_in_patchset(const xmlNode *patchset, const char *element)
200{
201 int format = 1;
202
203 CRM_ASSERT(patchset != NULL);
204
205 crm_element_value_int(patchset, PCMK_XA_FORMAT, &format);
206 switch (format) {
207 case 1:
208 return element_in_patchset_v1(patchset, element);
209
210 case 2:
211 return element_in_patchset_v2(patchset, element);
212
213 default:
214 crm_warn("Unknown patch format: %d", format);
215 return false;
216 }
217}
218
227xmlNode *
228createEmptyCib(int cib_epoch)
229{
230 xmlNode *cib_root = NULL, *config = NULL;
231
232 cib_root = pcmk__xe_create(NULL, PCMK_XE_CIB);
235
236 crm_xml_add_int(cib_root, PCMK_XA_EPOCH, cib_epoch);
239
240 config = pcmk__xe_create(cib_root, PCMK_XE_CONFIGURATION);
242
247
248#if PCMK__RESOURCE_STICKINESS_DEFAULT != 0
249 {
250 xmlNode *rsc_defaults = pcmk__xe_create(config, PCMK_XE_RSC_DEFAULTS);
251 xmlNode *meta = pcmk__xe_create(rsc_defaults, PCMK_XE_META_ATTRIBUTES);
252 xmlNode *nvpair = pcmk__xe_create(meta, PCMK_XE_NVPAIR);
253
254 crm_xml_add(meta, PCMK_XA_ID, "build-resource-defaults");
259 }
260#endif
261 return cib_root;
262}
263
264static bool
265cib_acl_enabled(xmlNode *xml, const char *user)
266{
267 bool rc = FALSE;
268
269 if(pcmk_acl_required(user)) {
270 const char *value = NULL;
271 GHashTable *options = pcmk__strkey_table(free, free);
272
273 cib_read_config(options, xml);
275 rc = crm_is_true(value);
276 g_hash_table_destroy(options);
277 }
278
279 crm_trace("CIB ACL is %s", rc ? "enabled" : "disabled");
280 return rc;
281}
282
293static bool
294should_copy_cib(const char *op, const char *section, int call_options)
295{
296 if (pcmk_is_set(call_options, cib_dryrun)) {
297 // cib_dryrun implies a scratch copy by definition; no side effects
298 return true;
299 }
300
301 if (pcmk__str_eq(op, PCMK__CIB_REQUEST_COMMIT_TRANSACT, pcmk__str_none)) {
302 /* Commit-transaction must make a copy for atomicity. We must revert to
303 * the original CIB if the entire transaction cannot be applied
304 * successfully.
305 */
306 return true;
307 }
308
309 if (pcmk_is_set(call_options, cib_transaction)) {
310 /* If cib_transaction is set, then we're in the process of committing a
311 * transaction. The commit-transaction request already made a scratch
312 * copy, and we're accumulating changes in that copy.
313 */
314 return false;
315 }
316
317 if (pcmk__str_eq(section, PCMK_XE_STATUS, pcmk__str_none)) {
318 /* Copying large CIBs accounts for a huge percentage of our CIB usage,
319 * and this avoids some of it.
320 *
321 * @TODO: Is this safe? See discussion at
322 * https://github.com/ClusterLabs/pacemaker/pull/3094#discussion_r1211400690.
323 */
324 return false;
325 }
326
327 // Default behavior is to operate on a scratch copy
328 return true;
329}
330
331int
332cib_perform_op(cib_t *cib, const char *op, int call_options, cib__op_fn_t fn,
333 bool is_query, const char *section, xmlNode *req, xmlNode *input,
334 bool manage_counters, bool *config_changed, xmlNode **current_cib,
335 xmlNode **result_cib, xmlNode **diff, xmlNode **output)
336{
337 int rc = pcmk_ok;
338 bool check_schema = true;
339 bool make_copy = true;
340 xmlNode *top = NULL;
341 xmlNode *scratch = NULL;
342 xmlNode *patchset_cib = NULL;
343 xmlNode *local_diff = NULL;
344
345 const char *user = crm_element_value(req, PCMK__XA_CIB_USER);
346 bool with_digest = false;
347
348 crm_trace("Begin %s%s%s op",
349 (pcmk_is_set(call_options, cib_dryrun)? "dry run of " : ""),
350 (is_query? "read-only " : ""), op);
351
352 CRM_CHECK(output != NULL, return -ENOMSG);
353 CRM_CHECK(current_cib != NULL, return -ENOMSG);
354 CRM_CHECK(result_cib != NULL, return -ENOMSG);
355 CRM_CHECK(config_changed != NULL, return -ENOMSG);
356
357 if(output) {
358 *output = NULL;
359 }
360
361 *result_cib = NULL;
362 *config_changed = false;
363
364 if (fn == NULL) {
365 return -EINVAL;
366 }
367
368 if (is_query) {
369 xmlNode *cib_ro = *current_cib;
370 xmlNode *cib_filtered = NULL;
371
372 if (cib_acl_enabled(cib_ro, user)
373 && xml_acl_filtered_copy(user, *current_cib, *current_cib,
374 &cib_filtered)) {
375
376 if (cib_filtered == NULL) {
377 crm_debug("Pre-filtered the entire cib");
378 return -EACCES;
379 }
380 cib_ro = cib_filtered;
381 crm_log_xml_trace(cib_ro, "filtered");
382 }
383
384 rc = (*fn) (op, call_options, section, req, input, cib_ro, result_cib, output);
385
386 if(output == NULL || *output == NULL) {
387 /* nothing */
388
389 } else if(cib_filtered == *output) {
390 cib_filtered = NULL; /* Let them have this copy */
391
392 } else if (*output == *current_cib) {
393 /* They already know not to free it */
394
395 } else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
396 /* We're about to free the document of which *output is a part */
397 *output = pcmk__xml_copy(NULL, *output);
398
399 } else if ((*output)->doc == (*current_cib)->doc) {
400 /* Give them a copy they can free */
401 *output = pcmk__xml_copy(NULL, *output);
402 }
403
404 free_xml(cib_filtered);
405 return rc;
406 }
407
408 make_copy = should_copy_cib(op, section, call_options);
409
410 if (!make_copy) {
411 /* Conditional on v2 patch style */
412
413 scratch = *current_cib;
414
415 // Make a copy of the top-level element to store version details
416 top = pcmk__xe_create(NULL, (const char *) scratch->name);
417 pcmk__xe_copy_attrs(top, scratch, pcmk__xaf_none);
418 patchset_cib = top;
419
420 xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
421 rc = (*fn) (op, call_options, section, req, input, scratch, &scratch, output);
422
423 /* If scratch points to a new object now (for example, after an erase
424 * operation), then *current_cib should point to the same object.
425 */
426 *current_cib = scratch;
427
428 } else {
429 scratch = pcmk__xml_copy(NULL, *current_cib);
430 patchset_cib = *current_cib;
431
432 xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
433 rc = (*fn) (op, call_options, section, req, input, *current_cib,
434 &scratch, output);
435
436 if ((scratch != NULL) && !xml_tracking_changes(scratch)) {
437 crm_trace("Inferring changes after %s op", op);
438 xml_track_changes(scratch, user, *current_cib,
439 cib_acl_enabled(*current_cib, user));
440 xml_calculate_changes(*current_cib, scratch);
441 }
442 CRM_CHECK(*current_cib != scratch, return -EINVAL);
443 }
444
445 xml_acl_disable(scratch); /* Allow the system to make any additional changes */
446
447 if (rc == pcmk_ok && scratch == NULL) {
448 rc = -EINVAL;
449 goto done;
450
451 } else if(rc == pcmk_ok && xml_acl_denied(scratch)) {
452 crm_trace("ACL rejected part or all of the proposed changes");
453 rc = -EACCES;
454 goto done;
455
456 } else if (rc != pcmk_ok) {
457 goto done;
458 }
459
460 /* If the CIB is from a file, we don't need to check that the feature set is
461 * supported. All we care about in that case is the schema version, which
462 * is checked elsewhere.
463 */
464 if (scratch && (cib == NULL || cib->variant != cib_file)) {
465 const char *new_version = crm_element_value(scratch, PCMK_XA_CRM_FEATURE_SET);
466
467 rc = pcmk__check_feature_set(new_version);
468 if (rc != pcmk_rc_ok) {
469 pcmk__config_err("Discarding update with feature set '%s' greater than our own '%s'",
470 new_version, CRM_FEATURE_SET);
471 rc = pcmk_rc2legacy(rc);
472 goto done;
473 }
474 }
475
476 if (patchset_cib != NULL) {
477 int old = 0;
478 int new = 0;
479
481 crm_element_value_int(patchset_cib, PCMK_XA_ADMIN_EPOCH, &old);
482
483 if (old > new) {
484 crm_err("%s went backwards: %d -> %d (Opts: %#x)",
485 PCMK_XA_ADMIN_EPOCH, old, new, call_options);
486 crm_log_xml_warn(req, "Bad Op");
487 crm_log_xml_warn(input, "Bad Data");
488 rc = -pcmk_err_old_data;
489
490 } else if (old == new) {
491 crm_element_value_int(scratch, PCMK_XA_EPOCH, &new);
492 crm_element_value_int(patchset_cib, PCMK_XA_EPOCH, &old);
493 if (old > new) {
494 crm_err("%s went backwards: %d -> %d (Opts: %#x)",
495 PCMK_XA_EPOCH, old, new, call_options);
496 crm_log_xml_warn(req, "Bad Op");
497 crm_log_xml_warn(input, "Bad Data");
498 rc = -pcmk_err_old_data;
499 }
500 }
501 }
502
503 crm_trace("Massaging CIB contents");
504 pcmk__strip_xml_text(scratch);
505
506 if (!make_copy) {
507 /* At this point, patchset_cib is just the PCMK_XE_CIB tag and its
508 * properties.
509 *
510 * The v1 format would barf on this, but we know the v2 patch
511 * format only needs it for the top-level version fields
512 */
513 local_diff = xml_create_patchset(2, patchset_cib, scratch,
514 config_changed, manage_counters);
515
516 } else {
517 static time_t expires = 0;
518 time_t tm_now = time(NULL);
519
520 if (expires < tm_now) {
521 expires = tm_now + 60; /* Validate clients are correctly applying v2-style diffs at most once a minute */
522 with_digest = true;
523 }
524
525 local_diff = xml_create_patchset(0, patchset_cib, scratch,
526 config_changed, manage_counters);
527 }
528
530 xml_accept_changes(scratch);
531
532 if(local_diff) {
533 patchset_process_digest(local_diff, patchset_cib, scratch, with_digest);
534 pcmk__log_xml_patchset(LOG_INFO, local_diff);
535 crm_log_xml_trace(local_diff, "raw patch");
536 }
537
538 if (make_copy && (local_diff != NULL)) {
539 // Original to compare against doesn't exist
541 {
542 // Validate the calculated patch set
543 int test_rc = pcmk_ok;
544 int format = 1;
545 xmlNode *cib_copy = pcmk__xml_copy(NULL, patchset_cib);
546
547 crm_element_value_int(local_diff, PCMK_XA_FORMAT, &format);
548 test_rc = xml_apply_patchset(cib_copy, local_diff,
549 manage_counters);
550
551 if (test_rc != pcmk_ok) {
552 save_xml_to_file(cib_copy, "PatchApply:calculated", NULL);
553 save_xml_to_file(patchset_cib, "PatchApply:input", NULL);
554 save_xml_to_file(scratch, "PatchApply:actual", NULL);
555 save_xml_to_file(local_diff, "PatchApply:diff", NULL);
556 crm_err("v%d patchset error, patch failed to apply: %s "
557 "(%d)",
558 format, pcmk_rc_str(pcmk_legacy2rc(test_rc)),
559 test_rc);
560 }
561 free_xml(cib_copy);
562 },
563 {}
564 );
565 }
566
567 if (pcmk__str_eq(section, PCMK_XE_STATUS, pcmk__str_casei)) {
568 /* Throttle the amount of costly validation we perform due to status updates
569 * a) we don't really care whats in the status section
570 * b) we don't validate any of its contents at the moment anyway
571 */
572 check_schema = false;
573 }
574
575 /* === scratch must not be modified after this point ===
576 * Exceptions, anything in:
577
578 static filter_t filter[] = {
579 { 0, PCMK_XA_CRM_DEBUG_ORIGIN },
580 { 0, PCMK_XA_CIB_LAST_WRITTEN },
581 { 0, PCMK_XA_UPDATE_ORIGIN },
582 { 0, PCMK_XA_UPDATE_CLIENT },
583 { 0, PCMK_XA_UPDATE_USER },
584 };
585 */
586
587 if (*config_changed && !pcmk_is_set(call_options, cib_no_mtime)) {
588 const char *schema = crm_element_value(scratch, PCMK_XA_VALIDATE_WITH);
589
592
593 /* Make values of origin, client, and user in scratch match
594 * the ones in req (if the schema allows the attributes)
595 */
596 if (pcmk__cmp_schemas_by_name(schema, "pacemaker-1.2") >= 0) {
597 const char *origin = crm_element_value(req, PCMK__XA_SRC);
598 const char *client = crm_element_value(req,
600
601 if (origin != NULL) {
602 crm_xml_add(scratch, PCMK_XA_UPDATE_ORIGIN, origin);
603 } else {
605 }
606
607 if (client != NULL) {
608 crm_xml_add(scratch, PCMK_XA_UPDATE_CLIENT, user);
609 } else {
611 }
612
613 if (user != NULL) {
614 crm_xml_add(scratch, PCMK_XA_UPDATE_USER, user);
615 } else {
617 }
618 }
619 }
620
621 crm_trace("Perform validation: %s", pcmk__btoa(check_schema));
622 if ((rc == pcmk_ok) && check_schema
624 const char *current_schema = crm_element_value(scratch,
626
627 crm_warn("Updated CIB does not validate against %s schema",
628 pcmk__s(current_schema, "unspecified"));
630 }
631
632 done:
633
634 *result_cib = scratch;
635
636 /* @TODO: This may not work correctly with !make_copy, since we don't
637 * keep the original CIB.
638 */
639 if ((rc != pcmk_ok) && cib_acl_enabled(patchset_cib, user)
640 && xml_acl_filtered_copy(user, patchset_cib, scratch, result_cib)) {
641
642 if (*result_cib == NULL) {
643 crm_debug("Pre-filtered the entire cib result");
644 }
645 free_xml(scratch);
646 }
647
648 if(diff) {
649 *diff = local_diff;
650 } else {
651 free_xml(local_diff);
652 }
653
654 free_xml(top);
655 crm_trace("Done");
656 return rc;
657}
658
659int
660cib__create_op(cib_t *cib, const char *op, const char *host,
661 const char *section, xmlNode *data, int call_options,
662 const char *user_name, const char *client_name,
663 xmlNode **op_msg)
664{
665 CRM_CHECK((cib != NULL) && (op_msg != NULL), return -EPROTO);
666
667 *op_msg = pcmk__xe_create(NULL, PCMK__XE_CIB_COMMAND);
668
669 cib->call_id++;
670 if (cib->call_id < 1) {
671 cib->call_id = 1;
672 }
673
675 crm_xml_add(*op_msg, PCMK__XA_CIB_OP, op);
677 crm_xml_add(*op_msg, PCMK__XA_CIB_SECTION, section);
678 crm_xml_add(*op_msg, PCMK__XA_CIB_USER, user_name);
679 crm_xml_add(*op_msg, PCMK__XA_CIB_CLIENTNAME, client_name);
681
682 crm_trace("Sending call options: %.8lx, %d", (long)call_options, call_options);
683 crm_xml_add_int(*op_msg, PCMK__XA_CIB_CALLOPT, call_options);
684
685 if (data != NULL) {
686 xmlNode *wrapper = pcmk__xe_create(*op_msg, PCMK__XE_CIB_CALLDATA);
687
688 pcmk__xml_copy(wrapper, data);
689 }
690
691 if (pcmk_is_set(call_options, cib_inhibit_bcast)) {
693 free_xml(*op_msg); return -EPROTO);
694 }
695 return pcmk_ok;
696}
697
706static int
707validate_transaction_request(const xmlNode *request)
708{
709 const char *op = crm_element_value(request, PCMK__XA_CIB_OP);
710 const char *host = crm_element_value(request, PCMK__XA_CIB_HOST);
711 const cib__operation_t *operation = NULL;
712 int rc = cib__get_operation(op, &operation);
713
714 if (rc != pcmk_rc_ok) {
715 // cib__get_operation() logs error
716 return rc;
717 }
718
719 if (!pcmk_is_set(operation->flags, cib__op_attr_transaction)) {
720 crm_err("Operation %s is not supported in CIB transactions", op);
721 return EOPNOTSUPP;
722 }
723
724 if (host != NULL) {
725 crm_err("Operation targeting a specific node (%s) is not supported in "
726 "a CIB transaction",
727 host);
728 return EOPNOTSUPP;
729 }
730 return pcmk_rc_ok;
731}
732
742int
743cib__extend_transaction(cib_t *cib, xmlNode *request)
744{
745 int rc = pcmk_rc_ok;
746
747 CRM_ASSERT((cib != NULL) && (request != NULL));
748
749 rc = validate_transaction_request(request);
750
751 if ((rc == pcmk_rc_ok) && (cib->transaction == NULL)) {
753 }
754
755 if (rc == pcmk_rc_ok) {
756 pcmk__xml_copy(cib->transaction, request);
757
758 } else {
759 const char *op = crm_element_value(request, PCMK__XA_CIB_OP);
760 const char *client_id = NULL;
761
762 cib->cmds->client_id(cib, NULL, &client_id);
763 crm_err("Failed to add '%s' operation to transaction for client %s: %s",
764 op, pcmk__s(client_id, "(unidentified)"), pcmk_rc_str(rc));
765 crm_log_xml_info(request, "failed");
766 }
767 return pcmk_rc2legacy(rc);
768}
769
770void
771cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc)
772{
773 xmlNode *output = NULL;
774 cib_callback_client_t *blob = NULL;
775
776 if (msg != NULL) {
777 xmlNode *wrapper = NULL;
778
781 wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_CALLDATA, NULL, NULL);
782 output = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
783 }
784
785 blob = cib__lookup_id(call_id);
786
787 if (blob == NULL) {
788 crm_trace("No callback found for call %d", call_id);
789 }
790
791 if (cib == NULL) {
792 crm_debug("No cib object supplied");
793 }
794
795 if (rc == -pcmk_err_diff_resync) {
796 /* This is an internal value that clients do not and should not care about */
797 rc = pcmk_ok;
798 }
799
800 if (blob && blob->callback && (rc == pcmk_ok || blob->only_success == FALSE)) {
801 crm_trace("Invoking callback %s for call %d",
802 pcmk__s(blob->id, "without ID"), call_id);
803 blob->callback(msg, call_id, rc, output, blob->user_data);
804
805 } else if (cib && cib->op_callback == NULL && rc != pcmk_ok) {
806 crm_warn("CIB command failed: %s", pcmk_strerror(rc));
807 crm_log_xml_debug(msg, "Failed CIB Update");
808 }
809
810 /* This may free user_data, so do it after the callback */
811 if (blob) {
812 remove_cib_op_callback(call_id, FALSE);
813 }
814
815 if (cib && cib->op_callback != NULL) {
816 crm_trace("Invoking global callback for call %d", call_id);
817 cib->op_callback(msg, call_id, rc, output);
818 }
819 crm_trace("OP callback activated for %d", call_id);
820}
821
822void
823cib_native_notify(gpointer data, gpointer user_data)
824{
825 xmlNode *msg = user_data;
826 cib_notify_client_t *entry = data;
827 const char *event = NULL;
828
829 if (msg == NULL) {
830 crm_warn("Skipping callback - NULL message");
831 return;
832 }
833
834 event = crm_element_value(msg, PCMK__XA_SUBT);
835
836 if (entry == NULL) {
837 crm_warn("Skipping callback - NULL callback client");
838 return;
839
840 } else if (entry->callback == NULL) {
841 crm_warn("Skipping callback - NULL callback");
842 return;
843
844 } else if (!pcmk__str_eq(entry->event, event, pcmk__str_casei)) {
845 crm_trace("Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event);
846 return;
847 }
848
849 crm_trace("Invoking callback for %p/%s event...", entry, event);
850 entry->callback(event, msg);
851 crm_trace("Callback invoked...");
852}
853
854gboolean
855cib_read_config(GHashTable * options, xmlNode * current_cib)
856{
857 xmlNode *config = NULL;
858 crm_time_t *now = NULL;
859
860 if (options == NULL || current_cib == NULL) {
861 return FALSE;
862 }
863
864 now = crm_time_new(NULL);
865
866 g_hash_table_remove_all(options);
867
868 config = pcmk_find_cib_element(current_cib, PCMK_XE_CRM_CONFIG);
869 if (config) {
871 NULL, options, PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS, TRUE,
872 now, NULL);
873 }
874
876
877 crm_time_free(now);
878
879 return TRUE;
880}
881
882int
883cib_internal_op(cib_t * cib, const char *op, const char *host,
884 const char *section, xmlNode * data,
885 xmlNode ** output_data, int call_options, const char *user_name)
886{
887 int (*delegate) (cib_t * cib, const char *op, const char *host,
888 const char *section, xmlNode * data,
889 xmlNode ** output_data, int call_options, const char *user_name) =
890 cib->delegate_fn;
891
892 if(user_name == NULL) {
893 user_name = getenv("CIB_user");
894 }
895
896 return delegate(cib, op, host, section, data, output_data, call_options, user_name);
897}
898
910int
911cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output,
912 int level)
913{
914 int rc = pcmk_err_generic;
915
916 xmlNode *wrapper = NULL;
917 xmlNode *diff = NULL;
918
919 CRM_ASSERT(event);
921 CRM_ASSERT(output);
922
925 NULL);
926 diff = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
927
928 if (rc < pcmk_ok || diff == NULL) {
929 return rc;
930 }
931
932 if (level > LOG_CRIT) {
933 pcmk__log_xml_patchset(level, diff);
934 }
935
936 if (input != NULL) {
937 rc = cib_process_diff(NULL, cib_none, NULL, event, diff, input, output,
938 NULL);
939
940 if (rc != pcmk_ok) {
941 crm_debug("Update didn't apply: %s (%d) %p",
942 pcmk_strerror(rc), rc, *output);
943
944 if (rc == -pcmk_err_old_data) {
945 crm_trace("Masking error, we already have the supplied update");
946 return pcmk_ok;
947 }
948 free_xml(*output);
949 *output = NULL;
950 return rc;
951 }
952 }
953 return rc;
954}
955
956#define log_signon_query_err(out, fmt, args...) do { \
957 if (out != NULL) { \
958 out->err(out, fmt, ##args); \
959 } else { \
960 crm_err(fmt, ##args); \
961 } \
962 } while (0)
963
964int
965cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
966{
967 int rc = pcmk_rc_ok;
968 cib_t *cib_conn = NULL;
969
970 CRM_ASSERT(cib_object != NULL);
971
972 if (cib == NULL) {
973 cib_conn = cib_new();
974 } else {
975 if (*cib == NULL) {
976 *cib = cib_new();
977 }
978 cib_conn = *cib;
979 }
980
981 if (cib_conn == NULL) {
982 return ENOMEM;
983 }
984
985 if (cib_conn->state == cib_disconnected) {
986 rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
987 rc = pcmk_legacy2rc(rc);
988 }
989
990 if (rc != pcmk_rc_ok) {
991 log_signon_query_err(out, "Could not connect to the CIB: %s",
992 pcmk_rc_str(rc));
993 goto done;
994 }
995
996 if (out != NULL) {
997 out->transient(out, "Querying CIB...");
998 }
999 rc = cib_conn->cmds->query(cib_conn, NULL, cib_object,
1001 rc = pcmk_legacy2rc(rc);
1002
1003 if (rc != pcmk_rc_ok) {
1004 log_signon_query_err(out, "CIB query failed: %s", pcmk_rc_str(rc));
1005 }
1006
1007done:
1008 if (cib == NULL) {
1009 cib__clean_up_connection(&cib_conn);
1010 }
1011
1012 if ((rc == pcmk_rc_ok) && (*cib_object == NULL)) {
1013 return pcmk_rc_no_input;
1014 }
1015 return rc;
1016}
1017
1018int
1020 int attempts)
1021{
1022 int rc = pcmk_rc_ok;
1023
1024 crm_trace("Attempting connection to CIB manager (up to %d time%s)",
1025 attempts, pcmk__plural_s(attempts));
1026
1027 for (int remaining = attempts - 1; remaining >= 0; --remaining) {
1028 rc = cib->cmds->signon(cib, name, type);
1029
1030 if ((rc == pcmk_rc_ok)
1031 || (remaining == 0)
1032 || ((errno != EAGAIN) && (errno != EALREADY))) {
1033 break;
1034 }
1035
1036 // Retry after soft error (interrupted by signal, etc.)
1037 pcmk__sleep_ms((attempts - remaining) * 500);
1038 crm_debug("Re-attempting connection to CIB manager (%d attempt%s remaining)",
1039 remaining, pcmk__plural_s(remaining));
1040 }
1041
1042 return rc;
1043}
1044
1045int
1047{
1048 int rc;
1049
1050 if (*cib == NULL) {
1051 return pcmk_rc_ok;
1052 }
1053
1054 rc = (*cib)->cmds->signoff(*cib);
1055 cib_delete(*cib);
1056 *cib = NULL;
1057 return pcmk_legacy2rc(rc);
1058}
1059
1060// Deprecated functions kept only for backward API compatibility
1061// LCOV_EXCL_START
1062
1063#include <crm/cib/util_compat.h>
1064
1065xmlNode *
1067{
1068 xmlNode *the_cib = NULL;
1069 xmlNode *generation = pcmk__xe_create(NULL, PCMK__XE_GENERATION_TUPLE);
1070
1071 cib->cmds->query(cib, NULL, &the_cib, cib_scope_local | cib_sync_call);
1072 if (the_cib != NULL) {
1073 pcmk__xe_copy_attrs(generation, the_cib, pcmk__xaf_none);
1074 free_xml(the_cib);
1075 }
1076
1077 return generation;
1078}
1079
1080const char *
1081get_object_path(const char *object_type)
1082{
1083 return pcmk_cib_xpath_for(object_type);
1084}
1085
1086const char *
1087get_object_parent(const char *object_type)
1088{
1089 return pcmk_cib_parent_name_for(object_type);
1090}
1091
1092xmlNode *
1093get_object_root(const char *object_type, xmlNode *the_root)
1094{
1095 return pcmk_find_cib_element(the_root, object_type);
1096}
1097
1098const char *
1099cib_pref(GHashTable * options, const char *name)
1100{
1101 return pcmk__cluster_option(options, name);
1102}
1103
1104void
1106{
1107 pcmk__output_t *out = NULL;
1108 int rc = pcmk__output_new(&out, "text", NULL, NULL);
1109
1110 if (rc != pcmk_rc_ok) {
1111 crm_err("Unable to output metadata: %s", pcmk_rc_str(rc));
1112 return;
1113 }
1114
1115 pcmk__daemon_metadata(out, "pacemaker-based",
1116 "Cluster Information Base manager options",
1117 "Cluster options used by Pacemaker's Cluster "
1118 "Information Base manager",
1120
1121 out->finish(out, CRM_EX_OK, true, NULL);
1122 pcmk__output_free(out);
1123}
1124
1125// LCOV_EXCL_STOP
1126// End deprecated API
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
Definition acl.c:616
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition acl.c:754
void xml_acl_disable(xmlNode *xml)
Definition acl.c:627
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Copy ACL-allowed portions of specified XML.
Definition acl.c:445
int cib__get_operation(const char *op, const cib__operation_t **operation)
Definition cib_ops.c:144
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
Definition internal.h:34
@ cib__op_attr_transaction
Supported in a transaction.
Definition internal.h:49
int cib_process_diff(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:669
cib_callback_client_t * cib__lookup_id(int call_id)
Definition cib_client.c:838
int(* cib__op_fn_t)(const char *, int, const char *, xmlNode *, xmlNode *, xmlNode *, xmlNode **, xmlNode **)
Definition internal.h:85
Deprecated Pacemaker configuration utilities.
const char * name
Definition cib.c:26
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition cib_client.c:791
cib_t * cib_new(void)
Create a new CIB connection object.
Definition cib_client.c:616
void remove_cib_op_callback(int call_id, gboolean all_callbacks)
Definition cib_client.c:800
const char * pcmk__cib_abs_xpath_for(const char *element)
Definition cib.c:133
int pcmk__check_feature_set(const char *cib_version)
Definition cib.c:184
cib_conn_type
Definition cib_types.h:50
@ cib_command
Definition cib_types.h:51
@ cib_scope_local
Definition cib_types.h:90
@ cib_none
Definition cib_types.h:61
@ cib_transaction
Process request when the client commits the active transaction.
Definition cib_types.h:108
@ cib_sync_call
Definition cib_types.h:133
@ cib_dryrun
Definition cib_types.h:92
@ cib_no_mtime
Definition cib_types.h:135
@ cib_inhibit_bcast
Definition cib_types.h:150
@ cib_file
Definition cib_types.h:31
@ cib_disconnected
Definition cib_types.h:47
#define XPATH_DIFF_V1
Definition cib_utils.c:107
int cib__extend_transaction(cib_t *cib, xmlNode *request)
Definition cib_utils.c:743
int cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output, int level)
Apply a CIB update patch to a given CIB.
Definition cib_utils.c:911
int cib__clean_up_connection(cib_t **cib)
Definition cib_utils.c:1046
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
Definition cib_utils.c:771
int cib__get_notify_patchset(const xmlNode *msg, const xmlNode **patchset)
Definition cib_utils.c:75
int cib__signon_attempts(cib_t *cib, const char *name, enum cib_conn_type type, int attempts)
Definition cib_utils.c:1019
#define log_signon_query_err(out, fmt, args...)
Definition cib_utils.c:956
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition cib_utils.c:965
const char * cib_pref(GHashTable *options, const char *name)
Definition cib_utils.c:1099
int cib__create_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, int call_options, const char *user_name, const char *client_name, xmlNode **op_msg)
Definition cib_utils.c:660
int cib_internal_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, xmlNode **output_data, int call_options, const char *user_name)
Definition cib_utils.c:883
gboolean cib_diff_version_details(xmlNode *diff, int *admin_epoch, int *epoch, int *updates, int *_admin_epoch, int *_epoch, int *_updates)
Definition cib_utils.c:46
int cib_perform_op(cib_t *cib, const char *op, int call_options, cib__op_fn_t fn, bool is_query, const char *section, xmlNode *req, xmlNode *input, bool manage_counters, bool *config_changed, xmlNode **current_cib, xmlNode **result_cib, xmlNode **diff, xmlNode **output)
Definition cib_utils.c:332
const char * get_object_path(const char *object_type)
Definition cib_utils.c:1081
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
Definition cib_utils.c:28
xmlNode * cib_get_generation(cib_t *cib)
Definition cib_utils.c:1066
const char * get_object_parent(const char *object_type)
Definition cib_utils.c:1087
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
Definition cib_utils.c:228
gboolean cib_read_config(GHashTable *options, xmlNode *current_cib)
Definition cib_utils.c:855
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition cib_utils.c:1093
bool cib__element_in_patchset(const xmlNode *patchset, const char *element)
Definition cib_utils.c:199
void cib_metadata(void)
Definition cib_utils.c:1105
void cib_native_notify(gpointer data, gpointer user_data)
Definition cib_utils.c:823
const char * pcmk_cib_parent_name_for(const char *element_name)
Get the parent element name of a given CIB element name.
Definition cib.c:150
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
Definition cib.c:172
const char * pcmk_cib_xpath_for(const char *element_name)
Get the relative XPath needed to find a specified CIB element name.
Definition cib.c:112
void pcmk__sleep_ms(unsigned int ms)
Definition utils.c:471
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
gboolean crm_is_true(const char *s)
Definition strings.c:488
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
#define PCMK__RESOURCE_STICKINESS_DEFAULT
Definition config.h:568
pcmk__cpg_host_t host
Definition cpg.c:4
enum crm_ais_msg_types type
Definition cpg.c:3
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_FEATURE_SET
Definition crm.h:72
char * crm_system_name
Definition utils.c:50
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:150
crm_time_t * crm_time_new(const char *string)
Definition iso8601.c:112
struct crm_time_s crm_time_t
Definition iso8601.h:32
#define crm_log_xml_info(xml, text)
Definition logging.h:408
#define crm_warn(fmt, args...)
Definition logging.h:392
#define CRM_XS
Definition logging.h:56
#define crm_log_xml_debug(xml, text)
Definition logging.h:409
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_err(fmt, args...)
Definition logging.h:389
#define crm_log_xml_trace(xml, text)
Definition logging.h:410
#define crm_log_xml_warn(xml, text)
Definition logging.h:406
#define crm_trace(fmt, args...)
Definition logging.h:402
#define LOG_TRACE
Definition logging.h:38
#define pcmk__log_xml_patchset(level, patchset)
#define pcmk__config_err(fmt...)
#define pcmk__if_tracing(if_action, else_action)
#define pcmk__log_xml_changes(level, xml)
xmlNode * input
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition nvpair.c:482
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition nvpair.c:348
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:301
#define PCMK_META_RESOURCE_STICKINESS
Definition options.h:111
#define PCMK_OPT_ENABLE_ACL
Definition options.h:37
#define PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS
Definition options.h:137
#define PCMK_VALUE_CREATE
Definition options.h:139
@ pcmk__opt_based
In CIB manager metadata.
const char * pcmk__cluster_option(GHashTable *options, const char *name)
Definition options.c:1412
#define PCMK__VALUE_CIB
int pcmk__daemon_metadata(pcmk__output_t *out, const char *name, const char *short_desc, const char *long_desc, enum pcmk__opt_flags filter)
Definition options.c:1517
void pcmk__validate_cluster_options(GHashTable *options)
Definition options.c:1558
void pcmk__output_free(pcmk__output_t *out)
Definition output.c:30
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition output.c:113
void pe_unpack_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table.
Definition rules.c:270
const char * pcmk_strerror(int rc)
Definition results.c:149
#define pcmk_err_old_data
Definition results.h:77
#define pcmk_err_generic
Definition results.h:73
#define CRM_ASSERT(expr)
Definition results.h:42
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:501
@ CRM_EX_OK
Success.
Definition results.h:255
#define pcmk_err_schema_validation
Definition results.h:75
@ pcmk_rc_no_input
Definition results.h:130
@ pcmk_rc_no_transaction
Definition results.h:120
@ pcmk_rc_ok
Definition results.h:162
#define pcmk_ok
Definition results.h:69
int pcmk_rc2legacy(int rc)
Definition results.c:546
#define pcmk_err_diff_resync
Definition results.h:83
int pcmk_legacy2rc(int legacy_rc)
Definition results.c:559
const char * pcmk__highest_schema_name(void)
Definition schemas.c:97
bool pcmk__configured_schema_validates(xmlNode *xml)
Definition schemas.c:809
void pcmk__warn_if_schema_deprecated(const char *schema)
Definition schemas.c:1589
int pcmk__cmp_schemas_by_name(const char *schema1_name, const char *schema2_name)
Definition schemas.c:691
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:683
#define pcmk__plural_s(i)
@ pcmk__str_regex
@ pcmk__str_none
@ pcmk__str_casei
uint32_t flags
Group of enum cib__op_attr flags.
Definition internal.h:91
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
Definition cib_types.h:159
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition cib_types.h:198
int(* client_id)(const cib_t *cib, const char **async_id, const char **sync_id)
Get the given CIB connection's unique client identifier(s)
Definition cib_types.h:299
const char * id
Definition internal.h:104
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
Definition internal.h:103
const char * event
Definition internal.h:95
void(* callback)(const char *event, xmlNode *msg)
Definition internal.h:98
enum cib_state state
Definition cib_types.h:382
xmlNode * transaction
Definition cib_types.h:401
void * delegate_fn
Definition cib_types.h:390
cib_api_operations_t * cmds
Definition cib_types.h:399
enum cib_variant variant
Definition cib_types.h:385
int call_id
Definition cib_types.h:387
void(* op_callback)(const xmlNode *msg, int call_id, int rc, xmlNode *output)
Definition cib_types.h:395
This structure contains everything that makes up a single output formatter.
int(*) int(* transient)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
Wrappers for and extensions to libxml2.
bool xml_patch_versions(const xmlNode *patchset, int add[3], int del[3])
Definition patchset.c:788
void xml_accept_changes(xmlNode *xml)
Definition xml.c:402
void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest)
Definition patchset.c:386
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
Definition patchset.c:1330
void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml)
Definition xml.c:1549
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition xpath.c:39
bool xml_tracking_changes(xmlNode *xml)
Definition xml.c:318
void xml_track_changes(xmlNode *xml, const char *user, xmlNode *acl_source, bool enforce_acls)
Definition xml.c:303
void free_xml(xmlNode *child)
Definition xml.c:867
xmlNode * xml_create_patchset(int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version)
Definition patchset.c:328
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
Definition xpath.c:139
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
Definition xml.c:652
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition xml.c:883
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml.c:440
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition xml.c:2108
@ pcmk__xaf_none
Flag has no effect.
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
Definition xml.c:584
const char * pcmk__xe_add_last_written(xmlNode *xe)
Definition xml.c:959
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition xml.c:720
void pcmk__strip_xml_text(xmlNode *xml)
Definition xml.c:923
void save_xml_to_file(const xmlNode *xml, const char *desc, const char *filename)
Definition xml_io.c:734
#define PCMK_XE_CONSTRAINTS
Definition xml_names.h:89
#define PCMK_XE_CIB
Definition xml_names.h:79
#define PCMK_XE_STATUS
Definition xml_names.h:199
#define PCMK_XE_CHANGE
Definition xml_names.h:74
#define PCMK_XA_FORMAT
Definition xml_names.h:286
#define PCMK_XA_VALIDATE_WITH
Definition xml_names.h:436
#define PCMK_XA_UPDATE_ORIGIN
Definition xml_names.h:432
#define PCMK_XA_EPOCH
Definition xml_names.h:263
#define PCMK_XE_CRM_CONFIG
Definition xml_names.h:91
#define PCMK_XA_PATH
Definition xml_names.h:350
#define PCMK_XA_ID
Definition xml_names.h:296
#define PCMK_XE_RESOURCES
Definition xml_names.h:175
#define PCMK_XE_META_ATTRIBUTES
Definition xml_names.h:127
#define PCMK_XA_ADMIN_EPOCH
Definition xml_names.h:227
#define PCMK_XA_VALUE
Definition xml_names.h:437
#define PCMK_XA_CRM_FEATURE_SET
Definition xml_names.h:249
#define PCMK_XE_CONFIGURATION
Definition xml_names.h:87
#define PCMK_XE_CLUSTER_PROPERTY_SET
Definition xml_names.h:84
#define PCMK_XA_UPDATE_USER
Definition xml_names.h:433
#define PCMK_XE_NVPAIR
Definition xml_names.h:141
#define PCMK_XE_NODES
Definition xml_names.h:139
#define PCMK_XA_NUM_UPDATES
Definition xml_names.h:336
#define PCMK_XA_NAME
Definition xml_names.h:325
#define PCMK_XA_UPDATE_CLIENT
Definition xml_names.h:431
#define PCMK_XE_RSC_DEFAULTS
Definition xml_names.h:182
#define PCMK__XA_CIB_CALLOPT
#define PCMK__XA_CIB_OP
#define PCMK__XA_CIB_CALLID
#define PCMK__XA_CIB_USER
#define PCMK__XE_CIB_COMMAND
#define PCMK__XA_CIB_SECTION
#define PCMK__XA_CIB_RC
#define PCMK__XE_GENERATION_TUPLE
#define PCMK__XA_T
#define PCMK__XE_CIB_CALLDATA
#define PCMK__XA_SUBT
#define PCMK__XA_CIB_HOST
#define PCMK__XA_CIB_CLIENTNAME
#define PCMK__XE_CIB_UPDATE_RESULT
#define PCMK__XA_SRC