pacemaker 2.1.4-dc6eb4362e
Scalable High-Availability cluster resource manager
cib_utils.c
Go to the documentation of this file.
1/*
2 * Original copyright 2004 International Business Machines
3 * Later changes copyright 2008-2022 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>
22#include <crm/msg_xml.h>
23#include <crm/common/xml.h>
25#include <crm/pengine/rules.h>
26
27xmlNode *
29{
30 xmlNode *the_cib = NULL;
31 xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
32
33 cib->cmds->query(cib, NULL, &the_cib, cib_scope_local | cib_sync_call);
34 if (the_cib != NULL) {
35 copy_in_properties(generation, the_cib);
36 free_xml(the_cib);
37 }
38
39 return generation;
40}
41
42gboolean
43cib_version_details(xmlNode * cib, int *admin_epoch, int *epoch, int *updates)
44{
45 *epoch = -1;
46 *updates = -1;
47 *admin_epoch = -1;
48
49 if (cib == NULL) {
50 return FALSE;
51
52 } else {
56 }
57 return TRUE;
58}
59
60gboolean
61cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates,
62 int *_admin_epoch, int *_epoch, int *_updates)
63{
64 int add[] = { 0, 0, 0 };
65 int del[] = { 0, 0, 0 };
66
67 xml_patch_versions(diff, add, del);
68
69 *admin_epoch = add[0];
70 *epoch = add[1];
71 *updates = add[2];
72
73 *_admin_epoch = del[0];
74 *_epoch = del[1];
75 *_updates = del[2];
76
77 return TRUE;
78}
79
88xmlNode *
89createEmptyCib(int cib_epoch)
90{
91 xmlNode *cib_root = NULL, *config = NULL;
92
93 cib_root = create_xml_node(NULL, XML_TAG_CIB);
96
97 crm_xml_add_int(cib_root, XML_ATTR_GENERATION, cib_epoch);
100
101 config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
103
108
109#if PCMK__RESOURCE_STICKINESS_DEFAULT != 0
110 {
111 xmlNode *rsc_defaults = create_xml_node(config, XML_CIB_TAG_RSCCONFIG);
112 xmlNode *meta = create_xml_node(rsc_defaults, XML_TAG_META_SETS);
113 xmlNode *nvpair = create_xml_node(meta, XML_CIB_TAG_NVPAIR);
114
115 crm_xml_add(meta, XML_ATTR_ID, "build-resource-defaults");
120 }
121#endif
122 return cib_root;
123}
124
125static bool
126cib_acl_enabled(xmlNode *xml, const char *user)
127{
128 bool rc = FALSE;
129
130 if(pcmk_acl_required(user)) {
131 const char *value = NULL;
132 GHashTable *options = pcmk__strkey_table(free, free);
133
134 cib_read_config(options, xml);
135 value = cib_pref(options, "enable-acl");
136 rc = crm_is_true(value);
137 g_hash_table_destroy(options);
138 }
139
140 crm_trace("CIB ACL is %s", rc ? "enabled" : "disabled");
141 return rc;
142}
143
144int
145cib_perform_op(const char *op, int call_options, cib_op_t * fn, gboolean is_query,
146 const char *section, xmlNode * req, xmlNode * input,
147 gboolean manage_counters, gboolean * config_changed,
148 xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff, xmlNode ** output)
149{
150 int rc = pcmk_ok;
151 gboolean check_schema = TRUE;
152 xmlNode *top = NULL;
153 xmlNode *scratch = NULL;
154 xmlNode *local_diff = NULL;
155
156 const char *new_version = NULL;
157 static struct qb_log_callsite *diff_cs = NULL;
158 const char *user = crm_element_value(req, F_CIB_USER);
159 bool with_digest = FALSE;
160
161 crm_trace("Begin %s%s%s op",
162 (pcmk_is_set(call_options, cib_dryrun)? "dry run of " : ""),
163 (is_query? "read-only " : ""), op);
164
165 CRM_CHECK(output != NULL, return -ENOMSG);
166 CRM_CHECK(result_cib != NULL, return -ENOMSG);
167 CRM_CHECK(config_changed != NULL, return -ENOMSG);
168
169 if(output) {
170 *output = NULL;
171 }
172
173 *result_cib = NULL;
174 *config_changed = FALSE;
175
176 if (fn == NULL) {
177 return -EINVAL;
178 }
179
180 if (is_query) {
181 xmlNode *cib_ro = current_cib;
182 xmlNode *cib_filtered = NULL;
183
184 if(cib_acl_enabled(cib_ro, user)) {
185 if(xml_acl_filtered_copy(user, current_cib, current_cib, &cib_filtered)) {
186 if (cib_filtered == NULL) {
187 crm_debug("Pre-filtered the entire cib");
188 return -EACCES;
189 }
190 cib_ro = cib_filtered;
191 crm_log_xml_trace(cib_ro, "filtered");
192 }
193 }
194
195 rc = (*fn) (op, call_options, section, req, input, cib_ro, result_cib, output);
196
197 if(output == NULL || *output == NULL) {
198 /* nothing */
199
200 } else if(cib_filtered == *output) {
201 cib_filtered = NULL; /* Let them have this copy */
202
203 } else if(*output == current_cib) {
204 /* They already know not to free it */
205
206 } else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
207 /* We're about to free the document of which *output is a part */
208 *output = copy_xml(*output);
209
210 } else if((*output)->doc == current_cib->doc) {
211 /* Give them a copy they can free */
212 *output = copy_xml(*output);
213 }
214
215 free_xml(cib_filtered);
216 return rc;
217 }
218
219
220 if (pcmk_is_set(call_options, cib_zero_copy)) {
221 /* Conditional on v2 patch style */
222
223 scratch = current_cib;
224
225 /* Create a shallow copy of current_cib for the version details */
226 current_cib = create_xml_node(NULL, (const char *)scratch->name);
227 copy_in_properties(current_cib, scratch);
228 top = current_cib;
229
230 xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
231 rc = (*fn) (op, call_options, section, req, input, scratch, &scratch, output);
232
233 } else {
234 scratch = copy_xml(current_cib);
235 xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
236 rc = (*fn) (op, call_options, section, req, input, current_cib, &scratch, output);
237
238 if(scratch && xml_tracking_changes(scratch) == FALSE) {
239 crm_trace("Inferring changes after %s op", op);
240 xml_track_changes(scratch, user, current_cib, cib_acl_enabled(current_cib, user));
241 xml_calculate_changes(current_cib, scratch);
242 }
243 CRM_CHECK(current_cib != scratch, return -EINVAL);
244 }
245
246 xml_acl_disable(scratch); /* Allow the system to make any additional changes */
247
248 if (rc == pcmk_ok && scratch == NULL) {
249 rc = -EINVAL;
250 goto done;
251
252 } else if(rc == pcmk_ok && xml_acl_denied(scratch)) {
253 crm_trace("ACL rejected part or all of the proposed changes");
254 rc = -EACCES;
255 goto done;
256
257 } else if (rc != pcmk_ok) {
258 goto done;
259 }
260
261 if (scratch) {
262 new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION);
263
264 if (new_version && compare_version(new_version, CRM_FEATURE_SET) > 0) {
265 crm_err("Discarding update with feature set '%s' greater than our own '%s'",
266 new_version, CRM_FEATURE_SET);
267 rc = -EPROTONOSUPPORT;
268 goto done;
269 }
270 }
271
272 if (current_cib) {
273 int old = 0;
274 int new = 0;
275
278
279 if (old > new) {
280 crm_err("%s went backwards: %d -> %d (Opts: %#x)",
281 XML_ATTR_GENERATION_ADMIN, old, new, call_options);
282 crm_log_xml_warn(req, "Bad Op");
283 crm_log_xml_warn(input, "Bad Data");
284 rc = -pcmk_err_old_data;
285
286 } else if (old == new) {
288 crm_element_value_int(current_cib, XML_ATTR_GENERATION, &old);
289 if (old > new) {
290 crm_err("%s went backwards: %d -> %d (Opts: %#x)",
291 XML_ATTR_GENERATION, old, new, call_options);
292 crm_log_xml_warn(req, "Bad Op");
293 crm_log_xml_warn(input, "Bad Data");
294 rc = -pcmk_err_old_data;
295 }
296 }
297 }
298
299 crm_trace("Massaging CIB contents");
300 pcmk__strip_xml_text(scratch);
302
303 if (pcmk_is_set(call_options, cib_zero_copy)) {
304 /* At this point, current_cib is just the 'cib' tag and its properties,
305 *
306 * The v1 format would barf on this, but we know the v2 patch
307 * format only needs it for the top-level version fields
308 */
309 local_diff = xml_create_patchset(2, current_cib, scratch, (bool*)config_changed, manage_counters);
310
311 } else {
312 static time_t expires = 0;
313 time_t tm_now = time(NULL);
314
315 if (expires < tm_now) {
316 expires = tm_now + 60; /* Validate clients are correctly applying v2-style diffs at most once a minute */
317 with_digest = TRUE;
318 }
319
320 local_diff = xml_create_patchset(0, current_cib, scratch, (bool*)config_changed, manage_counters);
321 }
322
323 xml_log_changes(LOG_TRACE, __func__, scratch);
324 xml_accept_changes(scratch);
325
326 if (diff_cs == NULL) {
327 diff_cs = qb_log_callsite_get(__PRETTY_FUNCTION__, __FILE__, "diff-validation", LOG_DEBUG, __LINE__, crm_trace_nonlog);
328 }
329
330 if(local_diff) {
331 patchset_process_digest(local_diff, current_cib, scratch, with_digest);
332
333 xml_log_patchset(LOG_INFO, __func__, local_diff);
334 crm_log_xml_trace(local_diff, "raw patch");
335 }
336
337 if (!pcmk_is_set(call_options, cib_zero_copy) // Original to compare against doesn't exist
338 && local_diff
339 && crm_is_callsite_active(diff_cs, LOG_TRACE, 0)) {
340
341 /* Validate the calculated patch set */
342 int test_rc, format = 1;
343 xmlNode * c = copy_xml(current_cib);
344
345 crm_element_value_int(local_diff, "format", &format);
346 test_rc = xml_apply_patchset(c, local_diff, manage_counters);
347
348 if(test_rc != pcmk_ok) {
349 save_xml_to_file(c, "PatchApply:calculated", NULL);
350 save_xml_to_file(current_cib, "PatchApply:input", NULL);
351 save_xml_to_file(scratch, "PatchApply:actual", NULL);
352 save_xml_to_file(local_diff, "PatchApply:diff", NULL);
353 crm_err("v%d patchset error, patch failed to apply: %s (%d)", format, pcmk_strerror(test_rc), test_rc);
354 }
355 free_xml(c);
356 }
357
358 if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
359 /* Throttle the amount of costly validation we perform due to status updates
360 * a) we don't really care whats in the status section
361 * b) we don't validate any of its contents at the moment anyway
362 */
363 check_schema = FALSE;
364 }
365
366 /* === scratch must not be modified after this point ===
367 * Exceptions, anything in:
368
369 static filter_t filter[] = {
370 { 0, XML_ATTR_ORIGIN },
371 { 0, XML_CIB_ATTR_WRITTEN },
372 { 0, XML_ATTR_UPDATE_ORIG },
373 { 0, XML_ATTR_UPDATE_CLIENT },
374 { 0, XML_ATTR_UPDATE_USER },
375 };
376 */
377
378 if (*config_changed && !pcmk_is_set(call_options, cib_no_mtime)) {
379 const char *schema = crm_element_value(scratch, XML_ATTR_VALIDATION);
380
382 if (schema) {
383 static int minimum_schema = 0;
384 int current_schema = get_schema_version(schema);
385
386 if (minimum_schema == 0) {
387 minimum_schema = get_schema_version("pacemaker-1.2");
388 }
389
390 /* Does the CIB support the "update-*" attributes... */
391 if (current_schema >= minimum_schema) {
392 const char *origin = crm_element_value(req, F_ORIG);
393
394 CRM_LOG_ASSERT(origin != NULL);
395 crm_xml_replace(scratch, XML_ATTR_UPDATE_ORIG, origin);
399 }
400 }
401 }
402
403 crm_trace("Perform validation: %s", pcmk__btoa(check_schema));
404 if ((rc == pcmk_ok) && check_schema && !validate_xml(scratch, NULL, TRUE)) {
405 const char *current_schema = crm_element_value(scratch,
407
408 crm_warn("Updated CIB does not validate against %s schema",
409 crm_str(current_schema));
411 }
412
413 done:
414
415 *result_cib = scratch;
416 if(rc != pcmk_ok && cib_acl_enabled(current_cib, user)) {
417 if(xml_acl_filtered_copy(user, current_cib, scratch, result_cib)) {
418 if (*result_cib == NULL) {
419 crm_debug("Pre-filtered the entire cib result");
420 }
421 free_xml(scratch);
422 }
423 }
424
425 if(diff) {
426 *diff = local_diff;
427 } else {
428 free_xml(local_diff);
429 }
430
431 free_xml(top);
432 crm_trace("Done");
433 return rc;
434}
435
436xmlNode *
437cib_create_op(int call_id, const char *token, const char *op, const char *host, const char *section,
438 xmlNode * data, int call_options, const char *user_name)
439{
440 xmlNode *op_msg = create_xml_node(NULL, "cib_command");
441
442 CRM_CHECK(op_msg != NULL, return NULL);
443 CRM_CHECK(token != NULL, return NULL);
444
445 crm_xml_add(op_msg, F_XML_TAGNAME, "cib_command");
446
447 crm_xml_add(op_msg, F_TYPE, T_CIB);
448 crm_xml_add(op_msg, F_CIB_CALLBACK_TOKEN, token);
449 crm_xml_add(op_msg, F_CIB_OPERATION, op);
450 crm_xml_add(op_msg, F_CIB_HOST, host);
451 crm_xml_add(op_msg, F_CIB_SECTION, section);
452 crm_xml_add_int(op_msg, F_CIB_CALLID, call_id);
453 if (user_name) {
454 crm_xml_add(op_msg, F_CIB_USER, user_name);
455 }
456 crm_trace("Sending call options: %.8lx, %d", (long)call_options, call_options);
457 crm_xml_add_int(op_msg, F_CIB_CALLOPTS, call_options);
458
459 if (data != NULL) {
461 }
462
463 if (call_options & cib_inhibit_bcast) {
464 CRM_CHECK((call_options & cib_scope_local), return NULL);
465 }
466 return op_msg;
467}
468
469void
470cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc)
471{
472 xmlNode *output = NULL;
473 cib_callback_client_t *blob = NULL;
474
475 if (msg != NULL) {
477 crm_element_value_int(msg, F_CIB_CALLID, &call_id);
478 output = get_message_xml(msg, F_CIB_CALLDATA);
479 }
480
481 blob = cib__lookup_id(call_id);
482
483 if (blob == NULL) {
484 crm_trace("No callback found for call %d", call_id);
485 }
486
487 if (cib == NULL) {
488 crm_debug("No cib object supplied");
489 }
490
491 if (rc == -pcmk_err_diff_resync) {
492 /* This is an internal value that clients do not and should not care about */
493 rc = pcmk_ok;
494 }
495
496 if (blob && blob->callback && (rc == pcmk_ok || blob->only_success == FALSE)) {
497 crm_trace("Invoking callback %s for call %d", crm_str(blob->id), call_id);
498 blob->callback(msg, call_id, rc, output, blob->user_data);
499
500 } else if (cib && cib->op_callback == NULL && rc != pcmk_ok) {
501 crm_warn("CIB command failed: %s", pcmk_strerror(rc));
502 crm_log_xml_debug(msg, "Failed CIB Update");
503 }
504
505 /* This may free user_data, so do it after the callback */
506 if (blob) {
507 remove_cib_op_callback(call_id, FALSE);
508 }
509
510 if (cib && cib->op_callback != NULL) {
511 crm_trace("Invoking global callback for call %d", call_id);
512 cib->op_callback(msg, call_id, rc, output);
513 }
514 crm_trace("OP callback activated for %d", call_id);
515}
516
517void
518cib_native_notify(gpointer data, gpointer user_data)
519{
520 xmlNode *msg = user_data;
521 cib_notify_client_t *entry = data;
522 const char *event = NULL;
523
524 if (msg == NULL) {
525 crm_warn("Skipping callback - NULL message");
526 return;
527 }
528
529 event = crm_element_value(msg, F_SUBTYPE);
530
531 if (entry == NULL) {
532 crm_warn("Skipping callback - NULL callback client");
533 return;
534
535 } else if (entry->callback == NULL) {
536 crm_warn("Skipping callback - NULL callback");
537 return;
538
539 } else if (!pcmk__str_eq(entry->event, event, pcmk__str_casei)) {
540 crm_trace("Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event);
541 return;
542 }
543
544 crm_trace("Invoking callback for %p/%s event...", entry, event);
545 entry->callback(event, msg);
546 crm_trace("Callback invoked...");
547}
548
549static pcmk__cluster_option_t cib_opts[] = {
550 /* name, legacy name, type, allowed values,
551 * default value, validator,
552 * short description,
553 * long description
554 */
555 {
556 "enable-acl", NULL, "boolean", NULL,
557 "false", pcmk__valid_boolean,
558 N_("Enable Access Control Lists (ACLs) for the CIB"),
559 NULL
560 },
561 {
562 "cluster-ipc-limit", NULL, "integer", NULL,
564 N_("Maximum IPC message backlog before disconnecting a cluster daemon"),
565 N_("Raise this if log has \"Evicting client\" messages for cluster daemon"
566 " PIDs (a good value is the number of resources in the cluster"
567 " multiplied by the number of nodes).")
568 },
569};
570
571void
573{
574 char *s = pcmk__format_option_metadata("pacemaker-based",
575 "Cluster Information Base manager options",
576 "Cluster options used by Pacemaker's "
577 "Cluster Information Base manager",
578 cib_opts, PCMK__NELEM(cib_opts));
579 printf("%s", s);
580 free(s);
581}
582
583void
584verify_cib_options(GHashTable * options)
585{
586 pcmk__validate_cluster_options(options, cib_opts, PCMK__NELEM(cib_opts));
587}
588
589const char *
590cib_pref(GHashTable * options, const char *name)
591{
592 return pcmk__cluster_option(options, cib_opts, PCMK__NELEM(cib_opts),
593 name);
594}
595
596gboolean
597cib_read_config(GHashTable * options, xmlNode * current_cib)
598{
599 xmlNode *config = NULL;
600 crm_time_t *now = NULL;
601
602 if (options == NULL || current_cib == NULL) {
603 return FALSE;
604 }
605
606 now = crm_time_new(NULL);
607
608 g_hash_table_remove_all(options);
609
610 config = pcmk_find_cib_element(current_cib, XML_CIB_TAG_CRMCONFIG);
611 if (config) {
612 pe_unpack_nvpairs(current_cib, config, XML_CIB_TAG_PROPSET, NULL,
613 options, CIB_OPTIONS_FIRST, TRUE, now, NULL);
614 }
615
616 verify_cib_options(options);
617
618 crm_time_free(now);
619
620 return TRUE;
621}
622
623/* v2 and v2 patch formats */
624#define XPATH_CONFIG_CHANGE \
625 "//" XML_CIB_TAG_CRMCONFIG " | " \
626 "//" XML_DIFF_CHANGE "[contains(@" XML_DIFF_PATH ",'/" XML_CIB_TAG_CRMCONFIG "/')]"
627
628gboolean
630{
631 gboolean changed = FALSE;
632
633 if (diff) {
634 xmlXPathObject *xpathObj = xpath_search(diff, XPATH_CONFIG_CHANGE);
635
636 if (numXpathResults(xpathObj) > 0) {
637 changed = TRUE;
638 }
639 freeXpathObject(xpathObj);
640 }
641 return changed;
642}
643
644int
645cib_internal_op(cib_t * cib, const char *op, const char *host,
646 const char *section, xmlNode * data,
647 xmlNode ** output_data, int call_options, const char *user_name)
648{
649 int (*delegate) (cib_t * cib, const char *op, const char *host,
650 const char *section, xmlNode * data,
651 xmlNode ** output_data, int call_options, const char *user_name) =
652 cib->delegate_fn;
653
654 if(user_name == NULL) {
655 user_name = getenv("CIB_user");
656 }
657
658 return delegate(cib, op, host, section, data, output_data, call_options, user_name);
659}
660
672int
673cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output,
674 int level)
675{
676 int rc = pcmk_err_generic;
677
678 xmlNode *diff = NULL;
679
680 CRM_ASSERT(event);
682 CRM_ASSERT(output);
683
684 crm_element_value_int(event, F_CIB_RC, &rc);
686
687 if (rc < pcmk_ok || diff == NULL) {
688 return rc;
689 }
690
691 if (level > LOG_CRIT) {
692 xml_log_patchset(level, "Config update", diff);
693 }
694
695 if (input != NULL) {
696 rc = cib_process_diff(NULL, cib_none, NULL, event, diff, input, output,
697 NULL);
698
699 if (rc != pcmk_ok) {
700 crm_debug("Update didn't apply: %s (%d) %p",
701 pcmk_strerror(rc), rc, *output);
702
703 if (rc == -pcmk_err_old_data) {
704 crm_trace("Masking error, we already have the supplied update");
705 return pcmk_ok;
706 }
707 free_xml(*output);
708 *output = NULL;
709 return rc;
710 }
711 }
712 return rc;
713}
714
715int
716cib__signon_query(cib_t **cib, xmlNode **cib_object)
717{
718 int rc = pcmk_rc_ok;
719 cib_t *cib_conn = NULL;
720
721 if (cib == NULL) {
722 cib_conn = cib_new();
723 } else {
724 *cib = cib_new();
725 cib_conn = *cib;
726 }
727
728 if (cib_conn == NULL) {
729 return ENOMEM;
730 }
731
732 rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
733 rc = pcmk_legacy2rc(rc);
734
735 if (rc == pcmk_rc_ok) {
736 rc = cib_conn->cmds->query(cib_conn, NULL, cib_object, cib_scope_local | cib_sync_call);
737 rc = pcmk_legacy2rc(rc);
738 }
739
740 if (cib == NULL) {
741 cib__clean_up_connection(&cib_conn);
742 }
743
744 if (cib_object == NULL) {
745 return pcmk_rc_no_input;
746 } else {
747 return rc;
748 }
749}
750
751int
753{
754 int rc;
755
756 if (*cib == NULL) {
757 return pcmk_rc_ok;
758 }
759
760 rc = (*cib)->cmds->signoff(*cib);
761 cib_delete(*cib);
762 *cib = NULL;
763 return pcmk_legacy2rc(rc);
764}
765
766// Deprecated functions kept only for backward API compatibility
767// LCOV_EXCL_START
768
769#include <crm/cib/util_compat.h>
770
771const char *
772get_object_path(const char *object_type)
773{
774 return pcmk_cib_xpath_for(object_type);
775}
776
777const char *
778get_object_parent(const char *object_type)
779{
780 return pcmk_cib_parent_name_for(object_type);
781}
782
783xmlNode *
784get_object_root(const char *object_type, xmlNode *the_root)
785{
786 return pcmk_find_cib_element(the_root, object_type);
787}
788
789// LCOV_EXCL_STOP
790// End deprecated API
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition: acl.c:683
bool xml_acl_denied(xmlNode *xml)
Definition: acl.c:576
void xml_acl_disable(xmlNode *xml)
Definition: acl.c:587
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:417
#define F_CIB_CALLID
Definition: internal.h:35
#define F_CIB_CALLOPTS
Definition: internal.h:34
#define F_CIB_USER
Definition: internal.h:57
#define F_CIB_OPERATION
Definition: internal.h:37
#define T_CIB
Definition: internal.h:63
#define F_CIB_HOST
Definition: internal.h:40
#define F_CIB_RC
Definition: internal.h:41
#define F_CIB_CLIENTNAME
Definition: internal.h:53
#define F_CIB_SECTION
Definition: internal.h:39
#define F_CIB_CALLDATA
Definition: internal.h:36
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:584
cib_callback_client_t * cib__lookup_id(int call_id)
Definition: cib_client.c:704
#define F_CIB_UPDATE_RESULT
Definition: internal.h:52
int(* cib_op_t)(const char *, int, const char *, xmlNode *, xmlNode *, xmlNode *, xmlNode **, xmlNode **)
Definition: internal.h:122
#define F_CIB_CALLBACK_TOKEN
Definition: internal.h:50
Deprecated Pacemaker configuration utilities.
const char * name
Definition: cib.c:24
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition: cib_client.c:451
cib_t * cib_new(void)
Definition: cib_client.c:292
void remove_cib_op_callback(int call_id, gboolean all_callbacks)
Definition: cib_client.c:666
@ cib_command
Definition: cib_types.h:43
@ cib_scope_local
Definition: cib_types.h:59
@ cib_none
Definition: cib_types.h:50
@ cib_sync_call
Definition: cib_types.h:61
@ cib_dryrun
Definition: cib_types.h:60
@ cib_no_mtime
Definition: cib_types.h:62
@ cib_zero_copy
Definition: cib_types.h:63
@ cib_inhibit_bcast
Definition: cib_types.h:66
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:673
int cib__clean_up_connection(cib_t **cib)
Definition: cib_utils.c:752
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
Definition: cib_utils.c:470
void verify_cib_options(GHashTable *options)
Definition: cib_utils.c:584
int cib__signon_query(cib_t **cib, xmlNode **cib_object)
Definition: cib_utils.c:716
#define XPATH_CONFIG_CHANGE
Definition: cib_utils.c:624
const char * cib_pref(GHashTable *options, const char *name)
Definition: cib_utils.c:590
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:645
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:61
const char * get_object_path(const char *object_type)
Definition: cib_utils.c:772
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
Definition: cib_utils.c:43
xmlNode * cib_get_generation(cib_t *cib)
Definition: cib_utils.c:28
int cib_perform_op(const char *op, int call_options, cib_op_t *fn, gboolean is_query, const char *section, xmlNode *req, xmlNode *input, gboolean manage_counters, gboolean *config_changed, xmlNode *current_cib, xmlNode **result_cib, xmlNode **diff, xmlNode **output)
Definition: cib_utils.c:145
const char * get_object_parent(const char *object_type)
Definition: cib_utils.c:778
xmlNode * cib_create_op(int call_id, const char *token, const char *op, const char *host, const char *section, xmlNode *data, int call_options, const char *user_name)
Definition: cib_utils.c:437
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
Definition: cib_utils.c:89
gboolean cib_internal_config_changed(xmlNode *diff)
Definition: cib_utils.c:629
gboolean cib_read_config(GHashTable *options, xmlNode *current_cib)
Definition: cib_utils.c:597
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition: cib_utils.c:784
void cib_metadata(void)
Definition: cib_utils.c:572
void cib_native_notify(gpointer data, gpointer user_data)
Definition: cib_utils.c:518
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:131
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
Definition: cib.c:153
const char * pcmk_cib_xpath_for(const char *element_name)
Get the XPath needed to find a specified CIB element name.
Definition: cib.c:110
#define PCMK__NELEM(a)
Definition: internal.h:42
int compare_version(const char *version1, const char *version2)
Definition: utils.c:160
gboolean crm_is_true(const char *s)
Definition: strings.c:416
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:122
#define PCMK__RESOURCE_STICKINESS_DEFAULT
Definition: config.h:546
pcmk__cpg_host_t host
Definition: cpg.c:4
char data[0]
Definition: cpg.c:10
A dumping ground.
#define CRM_FEATURE_SET
Definition: crm.h:69
char * crm_system_name
Definition: utils.c:54
#define N_(String)
Definition: crm_internal.h:48
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:140
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:92
struct crm_time_s crm_time_t
Definition: iso8601.h:32
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
Definition: logging.c:635
#define crm_str(x)
Definition: logging.h:384
#define crm_warn(fmt, args...)
Definition: logging.h:359
#define crm_log_xml_debug(xml, text)
Definition: logging.h:371
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:210
unsigned int crm_trace_nonlog
Definition: logging.c:46
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define crm_debug(fmt, args...)
Definition: logging.h:363
#define crm_err(fmt, args...)
Definition: logging.h:358
#define crm_log_xml_trace(xml, text)
Definition: logging.h:372
#define crm_log_xml_warn(xml, text)
Definition: logging.h:368
#define crm_trace(fmt, args...)
Definition: logging.h:364
#define LOG_TRACE
Definition: logging.h:37
#define F_SUBTYPE
Definition: msg_xml.h:65
#define XML_CIB_TAG_GENERATION_TUPPLE
Definition: msg_xml.h:402
#define XML_TAG_CIB
Definition: msg_xml.h:115
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:186
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:118
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:384
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:192
#define F_XML_TAGNAME
Definition: msg_xml.h:77
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:190
#define XML_RSC_ATTR_STICKINESS
Definition: msg_xml.h:242
#define XML_ATTR_ID
Definition: msg_xml.h:135
#define XML_CIB_TAG_CONSTRAINTS
Definition: msg_xml.h:189
#define F_ORIG
Definition: msg_xml.h:57
#define XML_TAG_META_SETS
Definition: msg_xml.h:210
#define XML_ATTR_UPDATE_CLIENT
Definition: msg_xml.h:143
#define XML_CIB_TAG_CONFIGURATION
Definition: msg_xml.h:184
#define F_TYPE
Definition: msg_xml.h:69
#define XML_CIB_TAG_PROPSET
Definition: msg_xml.h:208
#define XML_ATTR_VALIDATION
Definition: msg_xml.h:120
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:383
#define XML_ATTR_GENERATION_ADMIN
Definition: msg_xml.h:127
#define XML_ATTR_NUMUPDATES
Definition: msg_xml.h:128
#define CIB_OPTIONS_FIRST
Definition: msg_xml.h:88
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:187
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:206
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:185
#define XML_ATTR_UPDATE_ORIG
Definition: msg_xml.h:142
#define XML_ATTR_UPDATE_USER
Definition: msg_xml.h:144
#define XML_ATTR_GENERATION
Definition: msg_xml.h:126
xmlNode * input
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:565
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:431
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Replace an XML attribute with specified name and (possibly NULL) value.
Definition: nvpair.c:380
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:323
char * pcmk__format_option_metadata(const char *name, const char *desc_short, const char *desc_long, pcmk__cluster_option_t *option_list, int len)
Definition: options.c:607
bool pcmk__valid_boolean(const char *value)
Definition: options.c:376
const char * pcmk__cluster_option(GHashTable *options, pcmk__cluster_option_t *option_list, int len, const char *name)
Definition: options.c:538
void pcmk__validate_cluster_options(GHashTable *options, pcmk__cluster_option_t *option_list, int len)
Definition: options.c:683
bool pcmk__valid_positive_number(const char *value)
Definition: options.c:398
const char * pcmk_strerror(int rc)
Definition: results.c:58
#define pcmk_err_old_data
Definition: results.h:75
#define pcmk_err_generic
Definition: results.h:71
#define CRM_ASSERT(expr)
Definition: results.h:42
#define pcmk_err_schema_validation
Definition: results.h:73
@ pcmk_rc_no_input
Definition: results.h:115
@ pcmk_rc_ok
Definition: results.h:146
#define pcmk_ok
Definition: results.h:68
#define pcmk_err_diff_resync
Definition: results.h:77
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:428
void pe_unpack_nvpairs(xmlNode *top, 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:628
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:611
@ pcmk__str_casei
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
Definition: cib_types.h:73
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:92
const char * id
Definition: internal.h:96
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
Definition: internal.h:95
gboolean only_success
Definition: internal.h:98
const char * event
Definition: internal.h:87
void(* callback)(const char *event, xmlNode *msg)
Definition: internal.h:90
void * delegate_fn
Definition: cib_types.h:142
cib_api_operations_t * cmds
Definition: cib_types.h:147
void(* op_callback)(const xmlNode *msg, int call_id, int rc, xmlNode *output)
Definition: cib_types.h:145
Wrappers for and extensions to libxml2.
void xml_log_changes(uint8_t level, const char *function, xmlNode *xml)
Definition: xml.c:385
int get_schema_version(const char *name)
Definition: schemas.c:1024
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:139
void fix_plus_plus_recursive(xmlNode *target)
Definition: xml.c:541
void xml_accept_changes(xmlNode *xml)
Definition: xml.c:420
void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest)
Definition: patchset.c:426
bool xml_patch_versions(xmlNode *patchset, int add[3], int del[3])
Definition: patchset.c:801
const char * xml_latest_schema(void)
Definition: schemas.c:112
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
Definition: patchset.c:1325
void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml)
Definition: xml.c:2378
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:39
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
Definition: messages.c:162
bool xml_tracking_changes(xmlNode *xml)
Definition: xml.c:290
void xml_track_changes(xmlNode *xml, const char *user, xmlNode *acl_source, bool enforce_acls)
Definition: xml.c:275
void free_xml(xmlNode *child)
Definition: xml.c:824
void copy_in_properties(xmlNode *target, xmlNode *src)
Definition: xml.c:520
gboolean validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
Definition: schemas.c:698
xmlNode * get_message_xml(xmlNode *msg, const char *field)
Definition: messages.c:154
xmlNode * xml_create_patchset(int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version)
Definition: patchset.c:369
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:830
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
void xml_log_patchset(uint8_t level, const char *function, xmlNode *xml)
Definition: patchset.c:457
void save_xml_to_file(xmlNode *xml, const char *desc, const char *filename)
Definition: xml.c:2056
const char * pcmk__xe_add_last_written(xmlNode *xe)
Definition: xml.c:1115
void pcmk__strip_xml_text(xmlNode *xml)
Definition: xml.c:1017