pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
cib_ops.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-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 Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdio.h>
13#include <unistd.h>
14#include <stdlib.h>
15#include <errno.h>
16#include <fcntl.h>
17#include <time.h>
18
19#include <sys/param.h>
20#include <sys/types.h>
21
22#include <glib.h>
23#include <libxml/tree.h>
24#include <libxml/xpath.h> // xmlXPathObject, etc.
25
26#include <crm/crm.h>
27#include <crm/cib/internal.h>
28
29#include <crm/common/xml.h>
31
32// @TODO: Free this via crm_exit() when libcib gets merged with libcrmcommon
33static GHashTable *operation_table = NULL;
34
35static const cib__operation_t cib_ops[] = {
36 {
39 },
40 {
45 },
46 {
51 },
52 {
58 },
59 {
64 },
65 {
70 },
71 {
77 },
78 {
81 },
82 {
87 },
88 {
90 },
91 {
93 },
94 {
95 // @COMPAT: Drop cib__op_attr_modifies when we drop legacy mode support
98 },
99 {
101 },
102 {
109 },
110 {
113 },
114 {
116 },
117 {
119 },
120 {
122 },
123 {
129 },
130 {
132 }
133};
134
144int
145cib__get_operation(const char *op, const cib__operation_t **operation)
146{
147 pcmk__assert((op != NULL) && (operation != NULL));
148
149 if (operation_table == NULL) {
150 operation_table = pcmk__strkey_table(NULL, NULL);
151
152 for (int lpc = 0; lpc < PCMK__NELEM(cib_ops); lpc++) {
153 const cib__operation_t *oper = &(cib_ops[lpc]);
154
155 g_hash_table_insert(operation_table, (gpointer) oper->name,
156 (gpointer) oper);
157 }
158 }
159
160 *operation = g_hash_table_lookup(operation_table, op);
161 if (*operation == NULL) {
162 crm_err("Operation %s is invalid", op);
163 return EINVAL;
164 }
165 return pcmk_rc_ok;
166}
167
168int
169cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
170 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
171{
172 xmlNode *obj_root = NULL;
173 int result = pcmk_ok;
174
175 crm_trace("Processing %s for %s section",
176 op, pcmk__s(section, "unspecified"));
177
178 if (options & cib_xpath) {
179 return cib_process_xpath(op, options, section, req, input,
180 existing_cib, result_cib, answer);
181 }
182
183 CRM_CHECK(*answer == NULL, pcmk__xml_free(*answer));
184 *answer = NULL;
185
186 if (pcmk__str_eq(PCMK__XE_ALL, section, pcmk__str_casei)) {
187 section = NULL;
188 }
189
190 obj_root = pcmk_find_cib_element(existing_cib, section);
191
192 if (obj_root == NULL) {
193 result = -ENXIO;
194
195 } else if (options & cib_no_children) {
196 xmlNode *shallow = pcmk__xe_create(*answer,
197 (const char *) obj_root->name);
198
199 pcmk__xe_copy_attrs(shallow, obj_root, pcmk__xaf_none);
200 *answer = shallow;
201
202 } else {
203 *answer = obj_root;
204 }
205
206 if (result == pcmk_ok && *answer == NULL) {
207 crm_err("Error creating query response");
208 result = -ENOMSG;
209 }
210
211 return result;
212}
213
214static int
215update_counter(xmlNode *xml_obj, const char *field, bool reset)
216{
217 char *new_value = NULL;
218 char *old_value = NULL;
219 int int_value = -1;
220
221 if (!reset && crm_element_value(xml_obj, field) != NULL) {
222 old_value = crm_element_value_copy(xml_obj, field);
223 }
224 if (old_value != NULL) {
225 int_value = atoi(old_value);
226 new_value = pcmk__itoa(++int_value);
227 } else {
228 new_value = pcmk__str_copy("1");
229 }
230
231 crm_trace("Update %s from %s to %s",
232 field, pcmk__s(old_value, "unset"), new_value);
233 crm_xml_add(xml_obj, field, new_value);
234
235 free(new_value);
236 free(old_value);
237
238 return pcmk_ok;
239}
240
241int
242cib_process_erase(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
243 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
244{
245 int result = pcmk_ok;
246
247 crm_trace("Processing \"%s\" event", op);
248
249 if (*result_cib != existing_cib) {
250 pcmk__xml_free(*result_cib);
251 }
252 *result_cib = createEmptyCib(0);
253 pcmk__xe_copy_attrs(*result_cib, existing_cib, pcmk__xaf_none);
254 update_counter(*result_cib, PCMK_XA_ADMIN_EPOCH, false);
255 *answer = NULL;
256
257 return result;
258}
259
260int
261cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
262 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
263 xmlNode ** answer)
264{
265 int rc = 0;
266 const char *max_schema = crm_element_value(req, PCMK__XA_CIB_SCHEMA_MAX);
267 const char *original_schema = NULL;
268 const char *new_schema = NULL;
269
270 *answer = NULL;
271 crm_trace("Processing \"%s\" event with max=%s", op, max_schema);
272
273 original_schema = crm_element_value(existing_cib, PCMK_XA_VALIDATE_WITH);
274 rc = pcmk__update_schema(result_cib, max_schema, true,
275 !pcmk_is_set(options, cib_verbose));
276 rc = pcmk_rc2legacy(rc);
277 new_schema = crm_element_value(*result_cib, PCMK_XA_VALIDATE_WITH);
278
279 if (pcmk__cmp_schemas_by_name(new_schema, original_schema) > 0) {
280 update_counter(*result_cib, PCMK_XA_ADMIN_EPOCH, false);
281 update_counter(*result_cib, PCMK_XA_EPOCH, true);
282 update_counter(*result_cib, PCMK_XA_NUM_UPDATES, true);
283 return pcmk_ok;
284 }
285
286 return rc;
287}
288
289int
290cib_process_bump(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
291 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
292{
293 int result = pcmk_ok;
294
295 crm_trace("Processing %s for epoch='%s'", op,
296 pcmk__s(crm_element_value(existing_cib, PCMK_XA_EPOCH), ""));
297
298 *answer = NULL;
299 update_counter(*result_cib, PCMK_XA_EPOCH, false);
300
301 return result;
302}
303
304int
305cib_process_replace(const char *op, int options, const char *section, xmlNode * req,
306 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
307 xmlNode ** answer)
308{
309 int result = pcmk_ok;
310
311 crm_trace("Processing %s for %s section",
312 op, pcmk__s(section, "unspecified"));
313
314 if (options & cib_xpath) {
315 return cib_process_xpath(op, options, section, req, input,
316 existing_cib, result_cib, answer);
317 }
318
319 *answer = NULL;
320
321 if (input == NULL) {
322 return -EINVAL;
323 }
324
325 if (pcmk__str_eq(PCMK__XE_ALL, section, pcmk__str_casei)) {
326 section = NULL;
327
328 } else if (pcmk__xe_is(input, section)) {
329 section = NULL;
330 }
331
332 if (pcmk__xe_is(input, PCMK_XE_CIB)) {
333 int updates = 0;
334 int epoch = 0;
335 int admin_epoch = 0;
336
337 int replace_updates = 0;
338 int replace_epoch = 0;
339 int replace_admin_epoch = 0;
340
341 const char *reason = NULL;
342 const char *peer = crm_element_value(req, PCMK__XA_SRC);
343 const char *digest = crm_element_value(req, PCMK__XA_DIGEST);
344
345 if (digest) {
346 char *digest_verify = pcmk__digest_xml(input, true);
347
348 if (!pcmk__str_eq(digest_verify, digest, pcmk__str_casei)) {
349 crm_err("Digest mis-match on replace from %s: %s vs. %s (expected)", peer,
350 digest_verify, digest);
351 reason = "digest mismatch";
352
353 } else {
354 crm_info("Digest matched on replace from %s: %s", peer, digest);
355 }
356 free(digest_verify);
357
358 } else {
359 crm_trace("No digest to verify");
360 }
361
362 cib_version_details(existing_cib, &admin_epoch, &epoch, &updates);
363 cib_version_details(input, &replace_admin_epoch, &replace_epoch, &replace_updates);
364
365 if (replace_admin_epoch < admin_epoch) {
366 reason = PCMK_XA_ADMIN_EPOCH;
367
368 } else if (replace_admin_epoch > admin_epoch) {
369 /* no more checks */
370
371 } else if (replace_epoch < epoch) {
372 reason = PCMK_XA_EPOCH;
373
374 } else if (replace_epoch > epoch) {
375 /* no more checks */
376
377 } else if (replace_updates < updates) {
378 reason = PCMK_XA_NUM_UPDATES;
379 }
380
381 if (reason != NULL) {
382 crm_info("Replacement %d.%d.%d from %s not applied to %d.%d.%d:"
383 " current %s is greater than the replacement",
384 replace_admin_epoch, replace_epoch,
385 replace_updates, peer, admin_epoch, epoch, updates, reason);
387 } else {
388 crm_info("Replaced %d.%d.%d with %d.%d.%d from %s",
389 admin_epoch, epoch, updates,
390 replace_admin_epoch, replace_epoch, replace_updates, peer);
391 }
392
393 if (*result_cib != existing_cib) {
394 pcmk__xml_free(*result_cib);
395 }
396 *result_cib = pcmk__xml_copy(NULL, input);
397
398 } else {
399 xmlNode *obj_root = NULL;
400
401 obj_root = pcmk_find_cib_element(*result_cib, section);
404 if (result != pcmk_ok) {
405 crm_trace("No matching object to replace");
406 }
407 }
408
409 return result;
410}
411
412static int
413delete_child(xmlNode *child, void *userdata)
414{
415 xmlNode *obj_root = userdata;
416
417 if (pcmk__xe_delete_match(obj_root, child) != pcmk_rc_ok) {
418 crm_trace("No matching object to delete: %s=%s",
419 child->name, pcmk__xe_id(child));
420 }
421
422 return pcmk_rc_ok;
423}
424
425int
426cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
427 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
428{
429 xmlNode *obj_root = NULL;
430
431 crm_trace("Processing \"%s\" event", op);
432
433 if (options & cib_xpath) {
434 return cib_process_xpath(op, options, section, req, input,
435 existing_cib, result_cib, answer);
436 }
437
438 if (input == NULL) {
439 crm_err("Cannot perform modification with no data");
440 return -EINVAL;
441 }
442
443 obj_root = pcmk_find_cib_element(*result_cib, section);
444 if (pcmk__xe_is(input, section)) {
445 pcmk__xe_foreach_child(input, NULL, delete_child, obj_root);
446 } else {
447 delete_child(input, obj_root);
448 }
449
450 return pcmk_ok;
451}
452
453int
454cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
455 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
456{
457 xmlNode *obj_root = NULL;
458 uint32_t flags = pcmk__xaf_none;
459
460 crm_trace("Processing \"%s\" event", op);
461
462 if (options & cib_xpath) {
463 return cib_process_xpath(op, options, section, req, input,
464 existing_cib, result_cib, answer);
465 }
466
467 if (input == NULL) {
468 crm_err("Cannot perform modification with no data");
469 return -EINVAL;
470 }
471
472 obj_root = pcmk_find_cib_element(*result_cib, section);
473 if (obj_root == NULL) {
474 xmlNode *tmp_section = NULL;
475 const char *path = pcmk_cib_parent_name_for(section);
476
477 if (path == NULL) {
478 return -EINVAL;
479 }
480
481 tmp_section = pcmk__xe_create(NULL, section);
482 cib_process_xpath(PCMK__CIB_REQUEST_CREATE, 0, path, NULL, tmp_section,
483 NULL, result_cib, answer);
484 pcmk__xml_free(tmp_section);
485
486 obj_root = pcmk_find_cib_element(*result_cib, section);
487 }
488
489 CRM_CHECK(obj_root != NULL, return -EINVAL);
490
491 if (pcmk_is_set(options, cib_score_update)) {
493 }
494
495 if (pcmk__xe_update_match(obj_root, input, flags) != pcmk_rc_ok) {
496 if (options & cib_can_create) {
497 pcmk__xml_copy(obj_root, input);
498 } else {
499 return -ENXIO;
500 }
501 }
502
503 return pcmk_ok;
504}
505
506static int
507add_cib_object(xmlNode * parent, xmlNode * new_obj)
508{
509 const char *object_name = NULL;
510 const char *object_id = NULL;
511
512 if ((parent == NULL) || (new_obj == NULL)) {
513 return -EINVAL;
514 }
515
516 object_name = (const char *) new_obj->name;
517 if (object_name == NULL) {
518 return -EINVAL;
519 }
520
521 object_id = pcmk__xe_id(new_obj);
522 if (pcmk__xe_first_child(parent, object_name,
523 ((object_id != NULL)? PCMK_XA_ID : NULL),
524 object_id)) {
525 return -EEXIST;
526 }
527
528 if (object_id != NULL) {
529 crm_trace("Processing creation of <%s " PCMK_XA_ID "='%s'>",
530 object_name, object_id);
531 } else {
532 crm_trace("Processing creation of <%s>", object_name);
533 }
534
535 /* @COMPAT PCMK__XA_REPLACE is deprecated since 2.1.6. Due to a legacy use
536 * case, PCMK__XA_REPLACE has special meaning and should not be included in
537 * the newly created object until we can break behavioral backward
538 * compatibility.
539 *
540 * At a compatibility break, drop this and drop the definition of
541 * PCMK__XA_REPLACE. Treat it like any other attribute.
542 */
544 (void *) PCMK__XA_REPLACE);
545
546 pcmk__xml_copy(parent, new_obj);
547 return pcmk_ok;
548}
549
550static bool
551update_results(xmlNode *failed, xmlNode *target, const char *operation,
552 int return_code)
553{
554 xmlNode *xml_node = NULL;
555 bool was_error = false;
556 const char *error_msg = NULL;
557
558 if (return_code != pcmk_ok) {
559 error_msg = pcmk_strerror(return_code);
560
561 was_error = true;
562 xml_node = pcmk__xe_create(failed, PCMK__XE_FAILED_UPDATE);
563 pcmk__xml_copy(xml_node, target);
564
565 crm_xml_add(xml_node, PCMK_XA_ID, pcmk__xe_id(target));
566 crm_xml_add(xml_node, PCMK_XA_OBJECT_TYPE, (const char *) target->name);
567 crm_xml_add(xml_node, PCMK_XA_OPERATION, operation);
568 crm_xml_add(xml_node, PCMK_XA_REASON, error_msg);
569
570 crm_warn("Action %s failed: %s (cde=%d)",
571 operation, error_msg, return_code);
572 }
573
574 return was_error;
575}
576
577int
578cib_process_create(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
579 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
580{
581 xmlNode *failed = NULL;
582 int result = pcmk_ok;
583 xmlNode *update_section = NULL;
584
585 crm_trace("Processing %s for %s section",
586 op, pcmk__s(section, "unspecified"));
587 if (pcmk__str_eq(PCMK__XE_ALL, section, pcmk__str_casei)) {
588 section = NULL;
589
590 } else if (pcmk__str_eq(section, PCMK_XE_CIB, pcmk__str_casei)) {
591 section = NULL;
592
593 } else if (pcmk__xe_is(input, PCMK_XE_CIB)) {
594 section = NULL;
595 }
596
597 CRM_CHECK(strcmp(op, PCMK__CIB_REQUEST_CREATE) == 0, return -EINVAL);
598
599 if (input == NULL) {
600 crm_err("Cannot perform modification with no data");
601 return -EINVAL;
602 }
603
604 if (section == NULL) {
605 return cib_process_modify(op, options, section, req, input, existing_cib, result_cib,
606 answer);
607 }
608
609 // @COMPAT Deprecated since 2.1.8
610 failed = pcmk__xe_create(NULL, PCMK__XE_FAILED);
611
612 update_section = pcmk_find_cib_element(*result_cib, section);
613 if (pcmk__xe_is(input, section)) {
614 xmlNode *a_child = NULL;
615
616 for (a_child = pcmk__xml_first_child(input); a_child != NULL;
617 a_child = pcmk__xml_next(a_child)) {
618 result = add_cib_object(update_section, a_child);
619 if (update_results(failed, a_child, op, result)) {
620 break;
621 }
622 }
623
624 } else {
625 result = add_cib_object(update_section, input);
626 update_results(failed, input, op, result);
627 }
628
629 if ((result == pcmk_ok) && (failed->children != NULL)) {
630 result = -EINVAL;
631 }
632
633 if (result != pcmk_ok) {
634 crm_log_xml_err(failed, "CIB Update failures");
635 *answer = failed;
636
637 } else {
638 pcmk__xml_free(failed);
639 }
640
641 return result;
642}
643
644int
645cib_process_diff(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
646 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
647{
648 const char *originator = NULL;
649
650 if (req != NULL) {
651 originator = crm_element_value(req, PCMK__XA_SRC);
652 }
653
654 crm_trace("Processing \"%s\" event from %s%s",
655 op, originator,
656 (pcmk_is_set(options, cib_force_diff)? " (global update)" : ""));
657
658 if (*result_cib != existing_cib) {
659 pcmk__xml_free(*result_cib);
660 }
661 *result_cib = pcmk__xml_copy(NULL, existing_cib);
662
663 return xml_apply_patchset(*result_cib, input, TRUE);
664}
665
666int
667cib_process_xpath(const char *op, int options, const char *section,
668 const xmlNode *req, xmlNode *input, xmlNode *existing_cib,
669 xmlNode **result_cib, xmlNode **answer)
670{
671 int num_results = 0;
672 int rc = pcmk_ok;
673 bool is_query = pcmk__str_eq(op, PCMK__CIB_REQUEST_QUERY, pcmk__str_none);
674 bool delete_multiple = pcmk_is_set(options, cib_multiple)
675 && pcmk__str_eq(op, PCMK__CIB_REQUEST_DELETE,
677 xmlXPathObject *xpathObj = NULL;
678
679 crm_trace("Processing \"%s\" event", op);
680
681 if (is_query) {
682 xpathObj = pcmk__xpath_search(existing_cib->doc, section);
683 } else {
684 xpathObj = pcmk__xpath_search((*result_cib)->doc, section);
685 }
686
687 num_results = pcmk__xpath_num_results(xpathObj);
688 if (num_results == 0) {
689 if (pcmk__str_eq(op, PCMK__CIB_REQUEST_DELETE, pcmk__str_none)) {
690 crm_debug("%s was already removed", section);
691
692 } else {
693 crm_debug("%s: %s does not exist", op, section);
694 rc = -ENXIO;
695 }
696 goto done;
697 }
698
699 if (is_query && (num_results > 1)) {
700 *answer = pcmk__xe_create(NULL, PCMK__XE_XPATH_QUERY);
701 }
702
703 for (int i = 0; i < num_results; i++) {
704 xmlNode *match = NULL;
705 xmlChar *path = NULL;
706
707 /* If we're deleting multiple nodes, go in reverse document order.
708 * If we go in forward order and the node set contains both a parent and
709 * its descendant, then deleting the parent frees the descendant before
710 * the loop reaches the descendant. This is a use-after-free error.
711 *
712 * @COMPAT cib_multiple is only ever used with delete operations. The
713 * correct order to process multiple nodes for operations other than
714 * query (forward) and delete (reverse) is less clear but likely should
715 * be reverse. If we ever replace the CIB public API with libpacemaker
716 * functions, revisit this. For now, we keep forward order for other
717 * operations to preserve backward compatibility, even though external
718 * callers of other ops with cib_multiple might segfault.
719 *
720 * For more info, see comment in xpath2.c:update_xpath_nodes() in
721 * libxml2.
722 */
723 if (delete_multiple) {
724 match = pcmk__xpath_result(xpathObj, num_results - 1 - i);
725 } else {
726 match = pcmk__xpath_result(xpathObj, i);
727 }
728
729 if (match == NULL) {
730 continue;
731 }
732
733 path = xmlGetNodePath(match);
734 crm_debug("Processing %s op for %s with %s", op, section, path);
735 free(path);
736
737 if (pcmk__str_eq(op, PCMK__CIB_REQUEST_DELETE, pcmk__str_none)) {
738 if (match == *result_cib) {
739 /* Attempting to delete the whole "/cib" */
740 crm_warn("Cannot perform %s for %s: The xpath is addressing the whole /cib", op, section);
741 rc = -EINVAL;
742 break;
743 }
744
745 pcmk__xml_free(match);
746 if ((options & cib_multiple) == 0) {
747 break;
748 }
749
750 } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_MODIFY, pcmk__str_none)) {
751 uint32_t flags = pcmk__xaf_none;
752
753 if (pcmk_is_set(options, cib_score_update)) {
755 }
756
758 rc = -ENXIO;
759 } else if ((options & cib_multiple) == 0) {
760 break;
761 }
762
763 } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_CREATE, pcmk__str_none)) {
764 pcmk__xml_copy(match, input);
765 break;
766
767 } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_QUERY, pcmk__str_none)) {
768
769 if (options & cib_no_children) {
770 xmlNode *shallow = pcmk__xe_create(*answer,
771 (const char *) match->name);
772
773 pcmk__xe_copy_attrs(shallow, match, pcmk__xaf_none);
774
775 if (*answer == NULL) {
776 *answer = shallow;
777 }
778
779 } else if (options & cib_xpath_address) {
780 char *path = NULL;
781 xmlNode *parent = match;
782
783 while (parent && parent->type == XML_ELEMENT_NODE) {
784 const char *id = crm_element_value(parent, PCMK_XA_ID);
785 char *new_path = NULL;
786
787 if (id) {
788 new_path = crm_strdup_printf("/%s[@" PCMK_XA_ID "='%s']"
789 "%s",
790 parent->name, id,
791 pcmk__s(path, ""));
792 } else {
793 new_path = crm_strdup_printf("/%s%s", parent->name,
794 pcmk__s(path, ""));
795 }
796 free(path);
797 path = new_path;
798 parent = parent->parent;
799 }
800 crm_trace("Got: %s", path);
801
802 if (*answer == NULL) {
803 *answer = pcmk__xe_create(NULL, PCMK__XE_XPATH_QUERY);
804 }
807 free(path);
808
809 } else if (*answer) {
810 pcmk__xml_copy(*answer, match);
811
812 } else {
813 *answer = match;
814 }
815
816 } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_REPLACE,
818 xmlNode *parent = match->parent;
819
820 pcmk__xml_free(match);
822
823 if ((options & cib_multiple) == 0) {
824 break;
825 }
826 }
827 }
828
829done:
830 xmlXPathFreeObject(xpathObj);
831 return rc;
832}
#define PCMK__CIB_REQUEST_SYNC_TO_ONE
Definition internal.h:27
#define PCMK__CIB_REQUEST_ABS_DELETE
Definition internal.h:38
#define PCMK__CIB_REQUEST_SYNC_TO_ALL
Definition internal.h:26
#define PCMK__CIB_REQUEST_PRIMARY
Definition internal.h:25
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
Definition internal.h:41
#define PCMK__CIB_REQUEST_IS_PRIMARY
Definition internal.h:28
@ cib__op_attr_none
No special attributes.
Definition internal.h:49
@ cib__op_attr_transaction
Supported in a transaction.
Definition internal.h:55
@ cib__op_attr_privileged
Requires privileges.
Definition internal.h:51
@ cib__op_attr_local
Must only be processed locally.
Definition internal.h:52
@ cib__op_attr_replaces
Replaces CIB.
Definition internal.h:53
@ cib__op_attr_modifies
Modifies CIB.
Definition internal.h:50
@ cib__op_attr_writes_through
Writes to disk on success.
Definition internal.h:54
#define PCMK__CIB_REQUEST_SECONDARY
Definition internal.h:24
#define PCMK__CIB_REQUEST_QUERY
Definition internal.h:30
#define PCMK__CIB_REQUEST_REPLACE
Definition internal.h:35
#define PCMK__CIB_REQUEST_DELETE
Definition internal.h:33
#define PCMK__CIB_REQUEST_APPLY_PATCH
Definition internal.h:36
#define PCMK__CIB_REQUEST_BUMP
Definition internal.h:29
#define PCMK__CIB_REQUEST_CREATE
Definition internal.h:31
#define PCMK__CIB_REQUEST_NOOP
Definition internal.h:39
#define PCMK__CIB_REQUEST_MODIFY
Definition internal.h:32
#define PCMK__CIB_REQUEST_SHUTDOWN
Definition internal.h:40
@ cib__op_create
Definition internal.h:67
@ cib__op_is_primary
Definition internal.h:70
@ cib__op_primary
Definition internal.h:74
@ cib__op_sync_all
Definition internal.h:79
@ cib__op_delete
Definition internal.h:68
@ cib__op_commit_transact
Definition internal.h:66
@ cib__op_apply_patch
Definition internal.h:64
@ cib__op_schemas
Definition internal.h:82
@ cib__op_bump
Definition internal.h:65
@ cib__op_erase
Definition internal.h:69
@ cib__op_abs_delete
Definition internal.h:63
@ cib__op_shutdown
Definition internal.h:78
@ cib__op_replace
Definition internal.h:76
@ cib__op_sync_one
Definition internal.h:80
@ cib__op_upgrade
Definition internal.h:81
@ cib__op_query
Definition internal.h:75
@ cib__op_noop
Definition internal.h:72
@ cib__op_modify
Definition internal.h:71
@ cib__op_ping
Definition internal.h:73
@ cib__op_secondary
Definition internal.h:77
#define PCMK__CIB_REQUEST_UPGRADE
Definition internal.h:37
#define PCMK__CIB_REQUEST_SCHEMAS
Definition internal.h:42
#define PCMK__CIB_REQUEST_ERASE
Definition internal.h:34
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
Definition cib_utils.c:27
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
Definition cib_utils.c:117
const char * parent
Definition cib.c:27
const char * path
Definition cib.c:28
int cib_process_delete(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:426
int cib_process_xpath(const char *op, int options, const char *section, const xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:667
int cib__get_operation(const char *op, const cib__operation_t **operation)
Definition cib_ops.c:145
int cib_process_query(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:169
int cib_process_modify(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:454
int cib_process_create(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:578
int cib_process_bump(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:290
int cib_process_replace(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:305
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:645
int cib_process_upgrade(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:261
int cib_process_erase(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
Definition cib_ops.c:242
@ cib_no_children
Definition cib_types.h:62
@ cib_score_update
Treat new attribute values as atomic score updates where possible.
Definition cib_types.h:109
@ cib_force_diff
Definition cib_types.h:116
@ cib_xpath
Definition cib_types.h:58
@ cib_verbose
Prefer stderr to logs.
Definition cib_types.h:57
@ cib_can_create
Definition cib_types.h:60
@ cib_multiple
Definition cib_types.h:59
@ cib_xpath_address
Definition cib_types.h:63
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
#define PCMK__NELEM(a)
Definition internal.h:50
uint64_t flags
Definition remote.c:3
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:80
A dumping ground.
#define CRM_OP_PING
Definition crm.h:112
char * pcmk__digest_xml(xmlNode *input, bool filter)
Definition digest.c:160
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_warn(fmt, args...)
Definition logging.h:360
#define crm_log_xml_err(xml, text)
Definition logging.h:373
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_debug(fmt, args...)
Definition logging.h:368
#define crm_err(fmt, args...)
Definition logging.h:357
#define crm_trace(fmt, args...)
Definition logging.h:370
xmlNode * input
pcmk__action_result_t result
Definition pcmk_fence.c:37
const char * target
Definition pcmk_fence.c:31
const char * pcmk_strerror(int rc)
Definition results.c:257
#define pcmk_err_old_data
Definition results.h:73
@ pcmk_rc_ok
Definition results.h:159
#define pcmk_ok
Definition results.h:65
int pcmk_rc2legacy(int rc)
Definition results.c:662
#define pcmk__assert(expr)
int pcmk__cmp_schemas_by_name(const char *schema1_name, const char *schema2_name)
Definition schemas.c:759
int pcmk__update_schema(xmlNode **xml, const char *max_schema_name, bool transform, bool to_logs)
Update CIB XML to latest schema that validates it.
Definition schemas.c:1144
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:685
@ pcmk__str_none
@ pcmk__str_casei
#define pcmk__str_copy(str)
const char * name
Definition internal.h:94
Wrappers for and extensions to libxml2.
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
Definition patchset.c:765
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml_element.c:43
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data)
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search)
int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition xml.c:832
@ pcmk__xaf_none
Flag has no effect.
@ pcmk__xaf_score_update
bool pcmk__xml_tree_foreach(xmlNode *xml, bool(*fn)(xmlNode *, void *), void *user_data)
Definition xml.c:87
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
#define PCMK_XE_CIB
Definition xml_names.h:79
#define PCMK_XA_VALIDATE_WITH
Definition xml_names.h:441
#define PCMK_XA_OBJECT_TYPE
Definition xml_names.h:344
#define PCMK_XA_EPOCH
Definition xml_names.h:268
#define PCMK_XA_OPERATION
Definition xml_names.h:349
#define PCMK_XA_REASON
Definition xml_names.h:371
#define PCMK_XA_ID
Definition xml_names.h:301
#define PCMK_XA_ADMIN_EPOCH
Definition xml_names.h:232
#define PCMK_XA_NUM_UPDATES
Definition xml_names.h:341
#define PCMK__XE_ALL
#define PCMK__XA_CIB_SCHEMA_MAX
#define PCMK__XA_REPLACE
#define PCMK__XE_FAILED
#define PCMK__XE_FAILED_UPDATE
#define PCMK__XA_DIGEST
#define PCMK__XE_XPATH_QUERY_PATH
#define PCMK__XE_XPATH_QUERY
#define PCMK__XA_SRC
xmlXPathObject * pcmk__xpath_search(xmlDoc *doc, const char *path)
Definition xpath.c:137
xmlNode * pcmk__xpath_result(xmlXPathObject *xpath_obj, int index)
Definition xpath.c:65