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