This source file includes following definitions.
- cib_get_generation
- cib_version_details
- cib_diff_version_details
- get_object_path
- get_object_parent
- get_object_root
- createEmptyCib
- cib_acl_enabled
- cib_perform_op
- cib_create_op
- cib_native_callback
- cib_native_notify
- cib_metadata
- verify_cib_options
- cib_pref
- cib_read_config
- cib_internal_config_changed
- cib_internal_op
- cib_apply_patch_event
- cib__signon_query
1
2
3
4
5
6
7
8
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>
24 #include <crm/common/xml_internal.h>
25 #include <crm/pengine/rules.h>
26
27 struct config_root_s {
28 const char *name;
29 const char *parent;
30 const char *path;
31 };
32
33
34
35
36
37
38
39 static struct config_root_s known_paths[] = {
40 { NULL, NULL, "//cib" },
41 { XML_TAG_CIB, NULL, "//cib" },
42 { XML_CIB_TAG_STATUS, "/cib", "//cib/status" },
43 { XML_CIB_TAG_CONFIGURATION, "/cib", "//cib/configuration" },
44 { XML_CIB_TAG_CRMCONFIG, "/cib/configuration", "//cib/configuration/crm_config" },
45 { XML_CIB_TAG_NODES, "/cib/configuration", "//cib/configuration/nodes" },
46 { XML_CIB_TAG_RESOURCES, "/cib/configuration", "//cib/configuration/resources" },
47 { XML_CIB_TAG_CONSTRAINTS, "/cib/configuration", "//cib/configuration/constraints" },
48 { XML_CIB_TAG_OPCONFIG, "/cib/configuration", "//cib/configuration/op_defaults" },
49 { XML_CIB_TAG_RSCCONFIG, "/cib/configuration", "//cib/configuration/rsc_defaults" },
50 { XML_CIB_TAG_ACLS, "/cib/configuration", "//cib/configuration/acls" },
51 { XML_TAG_FENCING_TOPOLOGY, "/cib/configuration", "//cib/configuration/fencing-topology" },
52 { XML_CIB_TAG_TAGS, "/cib/configuration", "//cib/configuration/tags" },
53 { XML_CIB_TAG_ALERTS, "/cib/configuration", "//cib/configuration/alerts" },
54 { XML_CIB_TAG_SECTION_ALL, NULL, "//cib" },
55 };
56
57
58 xmlNode *
59 cib_get_generation(cib_t * cib)
60 {
61 xmlNode *the_cib = NULL;
62 xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
63
64 cib->cmds->query(cib, NULL, &the_cib, cib_scope_local | cib_sync_call);
65 if (the_cib != NULL) {
66 copy_in_properties(generation, the_cib);
67 free_xml(the_cib);
68 }
69
70 return generation;
71 }
72
73 gboolean
74 cib_version_details(xmlNode * cib, int *admin_epoch, int *epoch, int *updates)
75 {
76 *epoch = -1;
77 *updates = -1;
78 *admin_epoch = -1;
79
80 if (cib == NULL) {
81 return FALSE;
82
83 } else {
84 crm_element_value_int(cib, XML_ATTR_GENERATION, epoch);
85 crm_element_value_int(cib, XML_ATTR_NUMUPDATES, updates);
86 crm_element_value_int(cib, XML_ATTR_GENERATION_ADMIN, admin_epoch);
87 }
88 return TRUE;
89 }
90
91 gboolean
92 cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates,
93 int *_admin_epoch, int *_epoch, int *_updates)
94 {
95 int add[] = { 0, 0, 0 };
96 int del[] = { 0, 0, 0 };
97
98 xml_patch_versions(diff, add, del);
99
100 *admin_epoch = add[0];
101 *epoch = add[1];
102 *updates = add[2];
103
104 *_admin_epoch = del[0];
105 *_epoch = del[1];
106 *_updates = del[2];
107
108 return TRUE;
109 }
110
111
112
113
114
115 const char *
116 get_object_path(const char *object_type)
117 {
118 int lpc = 0;
119 int max = PCMK__NELEM(known_paths);
120
121 for (; lpc < max; lpc++) {
122 if ((object_type == NULL && known_paths[lpc].name == NULL)
123 || pcmk__str_eq(object_type, known_paths[lpc].name, pcmk__str_casei)) {
124 return known_paths[lpc].path;
125 }
126 }
127 return NULL;
128 }
129
130 const char *
131 get_object_parent(const char *object_type)
132 {
133 int lpc = 0;
134 int max = PCMK__NELEM(known_paths);
135
136 for (; lpc < max; lpc++) {
137 if (pcmk__str_eq(object_type, known_paths[lpc].name, pcmk__str_casei)) {
138 return known_paths[lpc].parent;
139 }
140 }
141 return NULL;
142 }
143
144 xmlNode *
145 get_object_root(const char *object_type, xmlNode * the_root)
146 {
147 const char *xpath = get_object_path(object_type);
148
149 if (xpath == NULL) {
150 return the_root;
151 }
152
153 return get_xpath_object(xpath, the_root, LOG_TRACE);
154 }
155
156
157
158
159
160
161
162
163
164 xmlNode *
165 createEmptyCib(int cib_epoch)
166 {
167 xmlNode *cib_root = NULL, *config = NULL;
168
169 cib_root = create_xml_node(NULL, XML_TAG_CIB);
170 crm_xml_add(cib_root, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
171 crm_xml_add(cib_root, XML_ATTR_VALIDATION, xml_latest_schema());
172
173 crm_xml_add_int(cib_root, XML_ATTR_GENERATION, cib_epoch);
174 crm_xml_add_int(cib_root, XML_ATTR_NUMUPDATES, 0);
175 crm_xml_add_int(cib_root, XML_ATTR_GENERATION_ADMIN, 0);
176
177 config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
178 create_xml_node(cib_root, XML_CIB_TAG_STATUS);
179
180 create_xml_node(config, XML_CIB_TAG_CRMCONFIG);
181 create_xml_node(config, XML_CIB_TAG_NODES);
182 create_xml_node(config, XML_CIB_TAG_RESOURCES);
183 create_xml_node(config, XML_CIB_TAG_CONSTRAINTS);
184
185 #if PCMK__RESOURCE_STICKINESS_DEFAULT != 0
186 {
187 xmlNode *rsc_defaults = create_xml_node(config, XML_CIB_TAG_RSCCONFIG);
188 xmlNode *meta = create_xml_node(rsc_defaults, XML_TAG_META_SETS);
189 xmlNode *nvpair = create_xml_node(meta, XML_CIB_TAG_NVPAIR);
190
191 crm_xml_add(meta, XML_ATTR_ID, "build-resource-defaults");
192 crm_xml_add(nvpair, XML_ATTR_ID, "build-" XML_RSC_ATTR_STICKINESS);
193 crm_xml_add(nvpair, XML_NVPAIR_ATTR_NAME, XML_RSC_ATTR_STICKINESS);
194 crm_xml_add_int(nvpair, XML_NVPAIR_ATTR_VALUE,
195 PCMK__RESOURCE_STICKINESS_DEFAULT);
196 }
197 #endif
198 return cib_root;
199 }
200
201 static bool
202 cib_acl_enabled(xmlNode *xml, const char *user)
203 {
204 bool rc = FALSE;
205
206 if(pcmk_acl_required(user)) {
207 const char *value = NULL;
208 GHashTable *options = pcmk__strkey_table(free, free);
209
210 cib_read_config(options, xml);
211 value = cib_pref(options, "enable-acl");
212 rc = crm_is_true(value);
213 g_hash_table_destroy(options);
214 }
215
216 crm_trace("CIB ACL is %s", rc ? "enabled" : "disabled");
217 return rc;
218 }
219
220 int
221 cib_perform_op(const char *op, int call_options, cib_op_t * fn, gboolean is_query,
222 const char *section, xmlNode * req, xmlNode * input,
223 gboolean manage_counters, gboolean * config_changed,
224 xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff, xmlNode ** output)
225 {
226 int rc = pcmk_ok;
227 gboolean check_schema = TRUE;
228 xmlNode *top = NULL;
229 xmlNode *scratch = NULL;
230 xmlNode *local_diff = NULL;
231
232 const char *new_version = NULL;
233 static struct qb_log_callsite *diff_cs = NULL;
234 const char *user = crm_element_value(req, F_CIB_USER);
235 bool with_digest = FALSE;
236
237 crm_trace("Begin %s%s%s op",
238 (pcmk_is_set(call_options, cib_dryrun)? "dry run of " : ""),
239 (is_query? "read-only " : ""), op);
240
241 CRM_CHECK(output != NULL, return -ENOMSG);
242 CRM_CHECK(result_cib != NULL, return -ENOMSG);
243 CRM_CHECK(config_changed != NULL, return -ENOMSG);
244
245 if(output) {
246 *output = NULL;
247 }
248
249 *result_cib = NULL;
250 *config_changed = FALSE;
251
252 if (fn == NULL) {
253 return -EINVAL;
254 }
255
256 if (is_query) {
257 xmlNode *cib_ro = current_cib;
258 xmlNode *cib_filtered = NULL;
259
260 if(cib_acl_enabled(cib_ro, user)) {
261 if(xml_acl_filtered_copy(user, current_cib, current_cib, &cib_filtered)) {
262 if (cib_filtered == NULL) {
263 crm_debug("Pre-filtered the entire cib");
264 return -EACCES;
265 }
266 cib_ro = cib_filtered;
267 crm_log_xml_trace(cib_ro, "filtered");
268 }
269 }
270
271 rc = (*fn) (op, call_options, section, req, input, cib_ro, result_cib, output);
272
273 if(output == NULL || *output == NULL) {
274
275
276 } else if(cib_filtered == *output) {
277 cib_filtered = NULL;
278
279 } else if(*output == current_cib) {
280
281
282 } else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
283
284 *output = copy_xml(*output);
285
286 } else if((*output)->doc == current_cib->doc) {
287
288 *output = copy_xml(*output);
289 }
290
291 free_xml(cib_filtered);
292 return rc;
293 }
294
295
296 if (pcmk_is_set(call_options, cib_zero_copy)) {
297
298
299 scratch = current_cib;
300
301
302 current_cib = create_xml_node(NULL, (const char *)scratch->name);
303 copy_in_properties(current_cib, scratch);
304 top = current_cib;
305
306 xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
307 rc = (*fn) (op, call_options, section, req, input, scratch, &scratch, output);
308
309 } else {
310 scratch = copy_xml(current_cib);
311 xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
312 rc = (*fn) (op, call_options, section, req, input, current_cib, &scratch, output);
313
314 if(scratch && xml_tracking_changes(scratch) == FALSE) {
315 crm_trace("Inferring changes after %s op", op);
316 xml_track_changes(scratch, user, current_cib, cib_acl_enabled(current_cib, user));
317 xml_calculate_changes(current_cib, scratch);
318 }
319 CRM_CHECK(current_cib != scratch, return -EINVAL);
320 }
321
322 xml_acl_disable(scratch);
323
324 if (rc == pcmk_ok && scratch == NULL) {
325 rc = -EINVAL;
326 goto done;
327
328 } else if(rc == pcmk_ok && xml_acl_denied(scratch)) {
329 crm_trace("ACL rejected part or all of the proposed changes");
330 rc = -EACCES;
331 goto done;
332
333 } else if (rc != pcmk_ok) {
334 goto done;
335 }
336
337 if (scratch) {
338 new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION);
339
340 if (new_version && compare_version(new_version, CRM_FEATURE_SET) > 0) {
341 crm_err("Discarding update with feature set '%s' greater than our own '%s'",
342 new_version, CRM_FEATURE_SET);
343 rc = -EPROTONOSUPPORT;
344 goto done;
345 }
346 }
347
348 if (current_cib) {
349 int old = 0;
350 int new = 0;
351
352 crm_element_value_int(scratch, XML_ATTR_GENERATION_ADMIN, &new);
353 crm_element_value_int(current_cib, XML_ATTR_GENERATION_ADMIN, &old);
354
355 if (old > new) {
356 crm_err("%s went backwards: %d -> %d (Opts: 0x%x)",
357 XML_ATTR_GENERATION_ADMIN, old, new, call_options);
358 crm_log_xml_warn(req, "Bad Op");
359 crm_log_xml_warn(input, "Bad Data");
360 rc = -pcmk_err_old_data;
361
362 } else if (old == new) {
363 crm_element_value_int(scratch, XML_ATTR_GENERATION, &new);
364 crm_element_value_int(current_cib, XML_ATTR_GENERATION, &old);
365 if (old > new) {
366 crm_err("%s went backwards: %d -> %d (Opts: 0x%x)",
367 XML_ATTR_GENERATION, old, new, call_options);
368 crm_log_xml_warn(req, "Bad Op");
369 crm_log_xml_warn(input, "Bad Data");
370 rc = -pcmk_err_old_data;
371 }
372 }
373 }
374
375 crm_trace("Massaging CIB contents");
376 pcmk__strip_xml_text(scratch);
377 fix_plus_plus_recursive(scratch);
378
379 if (pcmk_is_set(call_options, cib_zero_copy)) {
380
381
382
383
384
385 local_diff = xml_create_patchset(2, current_cib, scratch, (bool*)config_changed, manage_counters);
386
387 } else {
388 static time_t expires = 0;
389 time_t tm_now = time(NULL);
390
391 if (expires < tm_now) {
392 expires = tm_now + 60;
393 with_digest = TRUE;
394 }
395
396 local_diff = xml_create_patchset(0, current_cib, scratch, (bool*)config_changed, manage_counters);
397 }
398
399 xml_log_changes(LOG_TRACE, __func__, scratch);
400 xml_accept_changes(scratch);
401
402 if (diff_cs == NULL) {
403 diff_cs = qb_log_callsite_get(__PRETTY_FUNCTION__, __FILE__, "diff-validation", LOG_DEBUG, __LINE__, crm_trace_nonlog);
404 }
405
406 if(local_diff) {
407 patchset_process_digest(local_diff, current_cib, scratch, with_digest);
408
409 xml_log_patchset(LOG_INFO, __func__, local_diff);
410 crm_log_xml_trace(local_diff, "raw patch");
411 }
412
413 if (!pcmk_is_set(call_options, cib_zero_copy)
414 && local_diff
415 && crm_is_callsite_active(diff_cs, LOG_TRACE, 0)) {
416
417
418 int test_rc, format = 1;
419 xmlNode * c = copy_xml(current_cib);
420
421 crm_element_value_int(local_diff, "format", &format);
422 test_rc = xml_apply_patchset(c, local_diff, manage_counters);
423
424 if(test_rc != pcmk_ok) {
425 save_xml_to_file(c, "PatchApply:calculated", NULL);
426 save_xml_to_file(current_cib, "PatchApply:input", NULL);
427 save_xml_to_file(scratch, "PatchApply:actual", NULL);
428 save_xml_to_file(local_diff, "PatchApply:diff", NULL);
429 crm_err("v%d patchset error, patch failed to apply: %s (%d)", format, pcmk_strerror(test_rc), test_rc);
430 }
431 free_xml(c);
432 }
433
434 if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
435
436
437
438
439 check_schema = FALSE;
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453
454 if (*config_changed && !pcmk_is_set(call_options, cib_no_mtime)) {
455 const char *schema = crm_element_value(scratch, XML_ATTR_VALIDATION);
456
457 pcmk__xe_add_last_written(scratch);
458 if (schema) {
459 static int minimum_schema = 0;
460 int current_schema = get_schema_version(schema);
461
462 if (minimum_schema == 0) {
463 minimum_schema = get_schema_version("pacemaker-1.2");
464 }
465
466
467 if (current_schema >= minimum_schema) {
468 const char *origin = crm_element_value(req, F_ORIG);
469
470 CRM_LOG_ASSERT(origin != NULL);
471 crm_xml_replace(scratch, XML_ATTR_UPDATE_ORIG, origin);
472 crm_xml_replace(scratch, XML_ATTR_UPDATE_CLIENT,
473 crm_element_value(req, F_CIB_CLIENTNAME));
474 crm_xml_replace(scratch, XML_ATTR_UPDATE_USER, crm_element_value(req, F_CIB_USER));
475 }
476 }
477 }
478
479 crm_trace("Perform validation: %s", pcmk__btoa(check_schema));
480 if ((rc == pcmk_ok) && check_schema && !validate_xml(scratch, NULL, TRUE)) {
481 const char *current_schema = crm_element_value(scratch,
482 XML_ATTR_VALIDATION);
483
484 crm_warn("Updated CIB does not validate against %s schema",
485 crm_str(current_schema));
486 rc = -pcmk_err_schema_validation;
487 }
488
489 done:
490
491 *result_cib = scratch;
492 if(rc != pcmk_ok && cib_acl_enabled(current_cib, user)) {
493 if(xml_acl_filtered_copy(user, current_cib, scratch, result_cib)) {
494 if (*result_cib == NULL) {
495 crm_debug("Pre-filtered the entire cib result");
496 }
497 free_xml(scratch);
498 }
499 }
500
501 if(diff) {
502 *diff = local_diff;
503 } else {
504 free_xml(local_diff);
505 }
506
507 free_xml(top);
508 crm_trace("Done");
509 return rc;
510 }
511
512 xmlNode *
513 cib_create_op(int call_id, const char *token, const char *op, const char *host, const char *section,
514 xmlNode * data, int call_options, const char *user_name)
515 {
516 xmlNode *op_msg = create_xml_node(NULL, "cib_command");
517
518 CRM_CHECK(op_msg != NULL, return NULL);
519 CRM_CHECK(token != NULL, return NULL);
520
521 crm_xml_add(op_msg, F_XML_TAGNAME, "cib_command");
522
523 crm_xml_add(op_msg, F_TYPE, T_CIB);
524 crm_xml_add(op_msg, F_CIB_CALLBACK_TOKEN, token);
525 crm_xml_add(op_msg, F_CIB_OPERATION, op);
526 crm_xml_add(op_msg, F_CIB_HOST, host);
527 crm_xml_add(op_msg, F_CIB_SECTION, section);
528 crm_xml_add_int(op_msg, F_CIB_CALLID, call_id);
529 if (user_name) {
530 crm_xml_add(op_msg, F_CIB_USER, user_name);
531 }
532 crm_trace("Sending call options: %.8lx, %d", (long)call_options, call_options);
533 crm_xml_add_int(op_msg, F_CIB_CALLOPTS, call_options);
534
535 if (data != NULL) {
536 add_message_xml(op_msg, F_CIB_CALLDATA, data);
537 }
538
539 if (call_options & cib_inhibit_bcast) {
540 CRM_CHECK((call_options & cib_scope_local), return NULL);
541 }
542 return op_msg;
543 }
544
545 void
546 cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc)
547 {
548 xmlNode *output = NULL;
549 cib_callback_client_t *blob = NULL;
550
551 if (msg != NULL) {
552 crm_element_value_int(msg, F_CIB_RC, &rc);
553 crm_element_value_int(msg, F_CIB_CALLID, &call_id);
554 output = get_message_xml(msg, F_CIB_CALLDATA);
555 }
556
557 blob = cib__lookup_id(call_id);
558
559 if (blob == NULL) {
560 crm_trace("No callback found for call %d", call_id);
561 }
562
563 if (cib == NULL) {
564 crm_debug("No cib object supplied");
565 }
566
567 if (rc == -pcmk_err_diff_resync) {
568
569 rc = pcmk_ok;
570 }
571
572 if (blob && blob->callback && (rc == pcmk_ok || blob->only_success == FALSE)) {
573 crm_trace("Invoking callback %s for call %d", crm_str(blob->id), call_id);
574 blob->callback(msg, call_id, rc, output, blob->user_data);
575
576 } else if (cib && cib->op_callback == NULL && rc != pcmk_ok) {
577 crm_warn("CIB command failed: %s", pcmk_strerror(rc));
578 crm_log_xml_debug(msg, "Failed CIB Update");
579 }
580
581
582 if (blob) {
583 remove_cib_op_callback(call_id, FALSE);
584 }
585
586 if (cib && cib->op_callback != NULL) {
587 crm_trace("Invoking global callback for call %d", call_id);
588 cib->op_callback(msg, call_id, rc, output);
589 }
590 crm_trace("OP callback activated for %d", call_id);
591 }
592
593 void
594 cib_native_notify(gpointer data, gpointer user_data)
595 {
596 xmlNode *msg = user_data;
597 cib_notify_client_t *entry = data;
598 const char *event = NULL;
599
600 if (msg == NULL) {
601 crm_warn("Skipping callback - NULL message");
602 return;
603 }
604
605 event = crm_element_value(msg, F_SUBTYPE);
606
607 if (entry == NULL) {
608 crm_warn("Skipping callback - NULL callback client");
609 return;
610
611 } else if (entry->callback == NULL) {
612 crm_warn("Skipping callback - NULL callback");
613 return;
614
615 } else if (!pcmk__str_eq(entry->event, event, pcmk__str_casei)) {
616 crm_trace("Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event);
617 return;
618 }
619
620 crm_trace("Invoking callback for %p/%s event...", entry, event);
621 entry->callback(event, msg);
622 crm_trace("Callback invoked...");
623 }
624
625 static pcmk__cluster_option_t cib_opts[] = {
626
627
628
629
630
631 {
632 "enable-acl", NULL, "boolean", NULL,
633 "false", pcmk__valid_boolean,
634 "Enable Access Control Lists (ACLs) for the CIB",
635 NULL
636 },
637 {
638 "cluster-ipc-limit", NULL, "integer", NULL,
639 "500", pcmk__valid_positive_number,
640 "Maximum IPC message backlog before disconnecting a cluster daemon",
641 "Raise this if log has \"Evicting client\" messages for cluster daemon"
642 " PIDs (a good value is the number of resources in the cluster"
643 " multiplied by the number of nodes)."
644 },
645 };
646
647 void
648 cib_metadata(void)
649 {
650 pcmk__print_option_metadata("pacemaker-based",
651 "Cluster Information Base manager options",
652 "Cluster options used by Pacemaker's "
653 "Cluster Information Base manager",
654 cib_opts, PCMK__NELEM(cib_opts));
655 }
656
657 void
658 verify_cib_options(GHashTable * options)
659 {
660 pcmk__validate_cluster_options(options, cib_opts, PCMK__NELEM(cib_opts));
661 }
662
663 const char *
664 cib_pref(GHashTable * options, const char *name)
665 {
666 return pcmk__cluster_option(options, cib_opts, PCMK__NELEM(cib_opts),
667 name);
668 }
669
670 gboolean
671 cib_read_config(GHashTable * options, xmlNode * current_cib)
672 {
673 xmlNode *config = NULL;
674 crm_time_t *now = NULL;
675
676 if (options == NULL || current_cib == NULL) {
677 return FALSE;
678 }
679
680 now = crm_time_new(NULL);
681
682 g_hash_table_remove_all(options);
683
684 config = get_object_root(XML_CIB_TAG_CRMCONFIG, current_cib);
685 if (config) {
686 pe_unpack_nvpairs(current_cib, config, XML_CIB_TAG_PROPSET, NULL,
687 options, CIB_OPTIONS_FIRST, TRUE, now, NULL);
688 }
689
690 verify_cib_options(options);
691
692 crm_time_free(now);
693
694 return TRUE;
695 }
696
697
698 #define XPATH_CONFIG_CHANGE \
699 "//" XML_CIB_TAG_CRMCONFIG " | " \
700 "//" XML_DIFF_CHANGE "[contains(@" XML_DIFF_PATH ",'/" XML_CIB_TAG_CRMCONFIG "/')]"
701
702 gboolean
703 cib_internal_config_changed(xmlNode *diff)
704 {
705 gboolean changed = FALSE;
706
707 if (diff) {
708 xmlXPathObject *xpathObj = xpath_search(diff, XPATH_CONFIG_CHANGE);
709
710 if (numXpathResults(xpathObj) > 0) {
711 changed = TRUE;
712 }
713 freeXpathObject(xpathObj);
714 }
715 return changed;
716 }
717
718 int
719 cib_internal_op(cib_t * cib, const char *op, const char *host,
720 const char *section, xmlNode * data,
721 xmlNode ** output_data, int call_options, const char *user_name)
722 {
723 int (*delegate) (cib_t * cib, const char *op, const char *host,
724 const char *section, xmlNode * data,
725 xmlNode ** output_data, int call_options, const char *user_name) =
726 cib->delegate_fn;
727
728 if(user_name == NULL) {
729 user_name = getenv("CIB_user");
730 }
731
732 return delegate(cib, op, host, section, data, output_data, call_options, user_name);
733 }
734
735
736
737
738
739
740
741
742
743
744
745
746 int
747 cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output,
748 int level)
749 {
750 int rc = pcmk_err_generic;
751
752 xmlNode *diff = NULL;
753
754 CRM_ASSERT(event);
755 CRM_ASSERT(input);
756 CRM_ASSERT(output);
757
758 crm_element_value_int(event, F_CIB_RC, &rc);
759 diff = get_message_xml(event, F_CIB_UPDATE_RESULT);
760
761 if (rc < pcmk_ok || diff == NULL) {
762 return rc;
763 }
764
765 if (level > LOG_CRIT) {
766 xml_log_patchset(level, "Config update", diff);
767 }
768
769 if (input != NULL) {
770 rc = cib_process_diff(NULL, cib_none, NULL, event, diff, input, output,
771 NULL);
772
773 if (rc != pcmk_ok) {
774 crm_debug("Update didn't apply: %s (%d) %p",
775 pcmk_strerror(rc), rc, *output);
776
777 if (rc == -pcmk_err_old_data) {
778 crm_trace("Masking error, we already have the supplied update");
779 return pcmk_ok;
780 }
781 free_xml(*output);
782 *output = NULL;
783 return rc;
784 }
785 }
786 return rc;
787 }
788
789 int
790 cib__signon_query(cib_t **cib, xmlNode **cib_object)
791 {
792 int rc = pcmk_rc_ok;
793 cib_t *cib_conn = NULL;
794
795 if (cib == NULL) {
796 cib_conn = cib_new();
797 } else {
798 *cib = cib_new();
799 cib_conn = *cib;
800 }
801
802 if (cib_conn == NULL) {
803 return ENOMEM;
804 }
805
806 rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
807 rc = pcmk_legacy2rc(rc);
808
809 if (rc == pcmk_rc_ok) {
810 rc = cib_conn->cmds->query(cib_conn, NULL, cib_object, cib_scope_local | cib_sync_call);
811 rc = pcmk_legacy2rc(rc);
812 }
813
814 if (cib == NULL) {
815 cib_conn->cmds->signoff(cib_conn);
816 cib_delete(cib_conn);
817 cib_conn = NULL;
818 }
819
820 if (cib_object == NULL) {
821 return pcmk_rc_no_input;
822 } else {
823 return rc;
824 }
825 }