pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_output.c
Go to the documentation of this file.
1/*
2 * Copyright 2019-2021 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 General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11#include <crm/common/output.h>
12#include <crm/common/results.h>
13#include <crm/msg_xml.h>
14#include <crm/stonith-ng.h>
17#include <libxml/tree.h>
18#include <pacemaker-internal.h>
19
20static char *
21colocations_header(pe_resource_t *rsc, pcmk__colocation_t *cons,
22 gboolean dependents) {
23 char *score = NULL;
24 char *retval = NULL;
25
26 score = score2char(cons->score);
27 if (cons->role_rh > RSC_ROLE_STARTED) {
28 retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
29 rsc->id, score, dependents ? "needs" : "with",
30 role2text(cons->role_rh), cons->id);
31 } else {
32 retval = crm_strdup_printf("%s (score=%s, id=%s)",
33 rsc->id, score, cons->id);
34 }
35
36 free(score);
37 return retval;
38}
39
40static void
41colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
42 pcmk__colocation_t *cons) {
43 char *score = NULL;
44 xmlNodePtr node = NULL;
45
46 score = score2char(cons->score);
48 "id", cons->id,
49 "rsc", cons->rsc_lh->id,
50 "with-rsc", cons->rsc_rh->id,
51 "score", score,
52 NULL);
53
54 if (cons->node_attribute) {
55 xmlSetProp(node, (pcmkXmlStr) "node-attribute", (pcmkXmlStr) cons->node_attribute);
56 }
57
58 if (cons->role_lh != RSC_ROLE_UNKNOWN) {
59 xmlSetProp(node, (pcmkXmlStr) "rsc-role", (pcmkXmlStr) role2text(cons->role_lh));
60 }
61
62 if (cons->role_rh != RSC_ROLE_UNKNOWN) {
63 xmlSetProp(node, (pcmkXmlStr) "with-rsc-role", (pcmkXmlStr) role2text(cons->role_rh));
64 }
65
66 free(score);
67}
68
69static int
70do_locations_list_xml(pcmk__output_t *out, pe_resource_t *rsc, bool add_header)
71{
72 GList *lpc = NULL;
73 GList *list = rsc->rsc_location;
75
76 for (lpc = list; lpc != NULL; lpc = lpc->next) {
77 pe__location_t *cons = lpc->data;
78
79 GList *lpc2 = NULL;
80
81 for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
82 pe_node_t *node = (pe_node_t *) lpc2->data;
83 char *score = score2char(node->weight);
84
85 if (add_header) {
86 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
87 }
88
90 "node", node->details->uname,
91 "rsc", rsc->id,
92 "id", cons->id,
93 "score", score,
94 NULL);
95 free(score);
96 }
97 }
98
99 if (add_header) {
101 }
102
103 return rc;
104}
105
106PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
107 "pe_node_t *", "pe_node_t *", "pe_action_t *",
108 "pe_action_t *")
109static int
110rsc_action_item(pcmk__output_t *out, va_list args)
111{
112 const char *change = va_arg(args, const char *);
113 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
114 pe_node_t *origin = va_arg(args, pe_node_t *);
115 pe_node_t *destination = va_arg(args, pe_node_t *);
116 pe_action_t *action = va_arg(args, pe_action_t *);
117 pe_action_t *source = va_arg(args, pe_action_t *);
118
119 int len = 0;
120 char *reason = NULL;
121 char *details = NULL;
122 bool same_host = FALSE;
123 bool same_role = FALSE;
124 bool need_role = FALSE;
125
126 static int rsc_width = 5;
127 static int detail_width = 5;
128
130 CRM_ASSERT(destination != NULL || origin != NULL);
131
132 if(source == NULL) {
133 source = action;
134 }
135
136 len = strlen(rsc->id);
137 if(len > rsc_width) {
138 rsc_width = len + 2;
139 }
140
141 if ((rsc->role > RSC_ROLE_STARTED)
142 || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
143 need_role = TRUE;
144 }
145
146 if(origin != NULL && destination != NULL && origin->details == destination->details) {
147 same_host = TRUE;
148 }
149
150 if(rsc->role == rsc->next_role) {
151 same_role = TRUE;
152 }
153
154 if (need_role && (origin == NULL)) {
155 /* Starting and promoting a promotable clone instance */
156 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), destination->details->uname);
157
158 } else if (origin == NULL) {
159 /* Starting a resource */
160 details = crm_strdup_printf("%s", destination->details->uname);
161
162 } else if (need_role && (destination == NULL)) {
163 /* Stopping a promotable clone instance */
164 details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
165
166 } else if (destination == NULL) {
167 /* Stopping a resource */
168 details = crm_strdup_printf("%s", origin->details->uname);
169
170 } else if (need_role && same_role && same_host) {
171 /* Recovering, restarting or re-promoting a promotable clone instance */
172 details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
173
174 } else if (same_role && same_host) {
175 /* Recovering or Restarting a normal resource */
176 details = crm_strdup_printf("%s", origin->details->uname);
177
178 } else if (need_role && same_role) {
179 /* Moving a promotable clone instance */
180 details = crm_strdup_printf("%s -> %s %s", origin->details->uname, destination->details->uname, role2text(rsc->role));
181
182 } else if (same_role) {
183 /* Moving a normal resource */
184 details = crm_strdup_printf("%s -> %s", origin->details->uname, destination->details->uname);
185
186 } else if (same_host) {
187 /* Promoting or demoting a promotable clone instance */
188 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), origin->details->uname);
189
190 } else {
191 /* Moving and promoting/demoting */
192 details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role), origin->details->uname, role2text(rsc->next_role), destination->details->uname);
193 }
194
195 len = strlen(details);
196 if(len > detail_width) {
197 detail_width = len;
198 }
199
200 if(source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
201 reason = crm_strdup_printf("due to %s (blocked)", source->reason);
202
203 } else if(source->reason) {
204 reason = crm_strdup_printf("due to %s", source->reason);
205
206 } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
207 reason = strdup("blocked");
208
209 }
210
211 out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s", change, rsc_width,
212 rsc->id, detail_width, details, reason ? " " : "", reason ? reason : "");
213
214 free(details);
215 free(reason);
216 return pcmk_rc_ok;
217}
218
219PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
220 "pe_node_t *", "pe_node_t *", "pe_action_t *",
221 "pe_action_t *")
222static int
223rsc_action_item_xml(pcmk__output_t *out, va_list args)
224{
225 const char *change = va_arg(args, const char *);
226 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
227 pe_node_t *origin = va_arg(args, pe_node_t *);
228 pe_node_t *destination = va_arg(args, pe_node_t *);
229 pe_action_t *action = va_arg(args, pe_action_t *);
230 pe_action_t *source = va_arg(args, pe_action_t *);
231
232 char *change_str = NULL;
233
234 bool same_host = FALSE;
235 bool same_role = FALSE;
236 bool need_role = FALSE;
237 xmlNode *xml = NULL;
238
240 CRM_ASSERT(destination != NULL || origin != NULL);
241
242 if (source == NULL) {
243 source = action;
244 }
245
246 if ((rsc->role > RSC_ROLE_STARTED)
247 || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
248 need_role = TRUE;
249 }
250
251 if(origin != NULL && destination != NULL && origin->details == destination->details) {
252 same_host = TRUE;
253 }
254
255 if(rsc->role == rsc->next_role) {
256 same_role = TRUE;
257 }
258
259 change_str = g_ascii_strdown(change, -1);
260 xml = pcmk__output_create_xml_node(out, "rsc_action",
261 "action", change_str,
262 "resource", rsc->id,
263 NULL);
264 g_free(change_str);
265
266 if (need_role && (origin == NULL)) {
267 /* Starting and promoting a promotable clone instance */
269 "role", role2text(rsc->role),
270 "next-role", role2text(rsc->next_role),
271 "dest", destination->details->uname,
272 NULL);
273
274 } else if (origin == NULL) {
275 /* Starting a resource */
276 crm_xml_add(xml, "node", destination->details->uname);
277
278 } else if (need_role && (destination == NULL)) {
279 /* Stopping a promotable clone instance */
281 "role", role2text(rsc->role),
282 "node", origin->details->uname,
283 NULL);
284
285 } else if (destination == NULL) {
286 /* Stopping a resource */
287 crm_xml_add(xml, "node", origin->details->uname);
288
289 } else if (need_role && same_role && same_host) {
290 /* Recovering, restarting or re-promoting a promotable clone instance */
292 "role", role2text(rsc->role),
293 "source", origin->details->uname,
294 NULL);
295
296 } else if (same_role && same_host) {
297 /* Recovering or Restarting a normal resource */
298 crm_xml_add(xml, "source", origin->details->uname);
299
300 } else if (need_role && same_role) {
301 /* Moving a promotable clone instance */
303 "source", origin->details->uname,
304 "dest", destination->details->uname,
305 "role", role2text(rsc->role),
306 NULL);
307
308 } else if (same_role) {
309 /* Moving a normal resource */
311 "source", origin->details->uname,
312 "dest", destination->details->uname,
313 NULL);
314
315 } else if (same_host) {
316 /* Promoting or demoting a promotable clone instance */
318 "role", role2text(rsc->role),
319 "next-role", role2text(rsc->next_role),
320 "source", origin->details->uname,
321 NULL);
322
323 } else {
324 /* Moving and promoting/demoting */
326 "role", role2text(rsc->role),
327 "source", origin->details->uname,
328 "next-role", role2text(rsc->next_role),
329 "dest", destination->details->uname,
330 NULL);
331 }
332
333 if (source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
335 "reason", source->reason,
336 "blocked", "true",
337 NULL);
338
339 } else if(source->reason) {
340 crm_xml_add(xml, "reason", source->reason);
341
342 } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
343 crm_xml_add(xml, "blocked", "true");
344
345 }
346
347 return pcmk_rc_ok;
348}
349
350PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
351static int
352rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
353 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
354 gboolean recursive = va_arg(args, gboolean);
355
356 int rc = pcmk_rc_no_output;
357
359 return rc;
360 }
361
363 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
364 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
365 char *hdr = NULL;
366
367 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources %s is colocated with", rsc->id);
368
370 out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_rh->id, cons->id);
371 continue;
372 }
373
374 hdr = colocations_header(cons->rsc_rh, cons, FALSE);
375 out->list_item(out, NULL, "%s", hdr);
376 free(hdr);
377
378 /* Empty list header just for indentation of information about this resource. */
379 out->begin_list(out, NULL, NULL, NULL);
380
381 out->message(out, "locations-list", cons->rsc_rh);
382 if (recursive) {
383 out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
384 }
385
386 out->end_list(out);
387 }
388
390 return rc;
391}
392
393PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
394static int
395rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
396 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
397 gboolean recursive = va_arg(args, gboolean);
398
399 int rc = pcmk_rc_no_output;
400
402 return rc;
403 }
404
406 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
407 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
408
410 colocations_xml_node(out, cons->rsc_rh, cons);
411 continue;
412 }
413
414 colocations_xml_node(out, cons->rsc_rh, cons);
415 do_locations_list_xml(out, cons->rsc_rh, false);
416
417 if (recursive) {
418 out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
419 }
420 }
421
422 return rc;
423}
424
425PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
426static int
427rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
428 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
429 gboolean recursive = va_arg(args, gboolean);
430
431 int rc = pcmk_rc_no_output;
432
434 return rc;
435 }
436
438 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
439 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
440 char *hdr = NULL;
441
442 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
443
445 out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_lh->id, cons->id);
446 continue;
447 }
448
449 hdr = colocations_header(cons->rsc_lh, cons, TRUE);
450 out->list_item(out, NULL, "%s", hdr);
451 free(hdr);
452
453 /* Empty list header just for indentation of information about this resource. */
454 out->begin_list(out, NULL, NULL, NULL);
455
456 out->message(out, "locations-list", cons->rsc_lh);
457 if (recursive) {
458 out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
459 }
460
461 out->end_list(out);
462 }
463
465 return rc;
466}
467
468PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
469static int
470rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
471 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
472 gboolean recursive = va_arg(args, gboolean);
473
474 int rc = pcmk_rc_no_output;
475
477 return rc;
478 }
479
481 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
482 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
483
485 colocations_xml_node(out, cons->rsc_lh, cons);
486 continue;
487 }
488
489 colocations_xml_node(out, cons->rsc_lh, cons);
490 do_locations_list_xml(out, cons->rsc_lh, false);
491
492 if (recursive) {
493 out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
494 }
495 }
496
497 return rc;
498}
499
500PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
501static int
502locations_list(pcmk__output_t *out, va_list args) {
503 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
504
505 GList *lpc = NULL;
506 GList *list = rsc->rsc_location;
507 int rc = pcmk_rc_no_output;
508
509 for (lpc = list; lpc != NULL; lpc = lpc->next) {
510 pe__location_t *cons = lpc->data;
511
512 GList *lpc2 = NULL;
513
514 for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
515 pe_node_t *node = (pe_node_t *) lpc2->data;
516 char *score = score2char(node->weight);
517
518 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Locations");
519 out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
520 node->details->uname, score, cons->id, rsc->id);
521 free(score);
522 }
523 }
524
526 return rc;
527}
528
529PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
530static int
531locations_list_xml(pcmk__output_t *out, va_list args) {
532 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
533 return do_locations_list_xml(out, rsc, true);
534}
535
536PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
537static int
538stacks_and_constraints(pcmk__output_t *out, va_list args) {
539 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
540 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
541 gboolean recursive = va_arg(args, gboolean);
542
543 xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
544 data_set->input);
545
546 unpack_constraints(cib_constraints, data_set);
547
548 // Constraints apply to group/clone, not member/instance
549 rsc = uber_parent(rsc);
550
551 out->message(out, "locations-list", rsc);
552
554 out->message(out, "rscs-colocated-with-list", rsc, recursive);
555
557 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
558 return pcmk_rc_ok;
559}
560
561PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
562static int
563stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
564 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
565 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
566 gboolean recursive = va_arg(args, gboolean);
567
568 xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
569 data_set->input);
570
571 unpack_constraints(cib_constraints, data_set);
572
573 // Constraints apply to group/clone, not member/instance
574 rsc = uber_parent(rsc);
575
576 pcmk__output_xml_create_parent(out, "constraints", NULL);
577 do_locations_list_xml(out, rsc, false);
578
580 out->message(out, "rscs-colocated-with-list", rsc, recursive);
581
583 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
584
586 return pcmk_rc_ok;
587}
588
589PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
590static int
591health_text(pcmk__output_t *out, va_list args)
592{
593 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
594 const char *host_from = va_arg(args, const char *);
595 const char *fsa_state = va_arg(args, const char *);
596 const char *result = va_arg(args, const char *);
597
598 if (!out->is_quiet(out)) {
599 return out->info(out, "Controller on %s in state %s: %s", crm_str(host_from),
600 crm_str(fsa_state), crm_str(result));
601 } else if (fsa_state != NULL) {
602 pcmk__formatted_printf(out, "%s\n", fsa_state);
603 return pcmk_rc_ok;
604 }
605
606 return pcmk_rc_no_output;
607}
608
609PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
610static int
611health_xml(pcmk__output_t *out, va_list args)
612{
613 const char *sys_from = va_arg(args, const char *);
614 const char *host_from = va_arg(args, const char *);
615 const char *fsa_state = va_arg(args, const char *);
616 const char *result = va_arg(args, const char *);
617
619 "node_name", crm_str(host_from),
620 "state", crm_str(fsa_state),
621 "result", crm_str(result),
622 NULL);
623 return pcmk_rc_ok;
624}
625
626PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
627static int
628pacemakerd_health_text(pcmk__output_t *out, va_list args)
629{
630 const char *sys_from = va_arg(args, const char *);
631 const char *state = va_arg(args, const char *);
632 const char *last_updated = va_arg(args, const char *);
633
634 if (!out->is_quiet(out)) {
635 return out->info(out, "Status of %s: '%s' %s %s", crm_str(sys_from),
636 crm_str(state), (!pcmk__str_empty(last_updated))?
637 "last updated":"", crm_str(last_updated));
638 } else {
639 pcmk__formatted_printf(out, "%s\n", crm_str(state));
640 return pcmk_rc_ok;
641 }
642
643 return pcmk_rc_no_output;
644}
645
646PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
647static int
648pacemakerd_health_xml(pcmk__output_t *out, va_list args)
649{
650 const char *sys_from = va_arg(args, const char *);
651 const char *state = va_arg(args, const char *);
652 const char *last_updated = va_arg(args, const char *);
653
655 "state", crm_str(state),
656 "last_updated", crm_str(last_updated),
657 NULL);
658 return pcmk_rc_ok;
659}
660
661PCMK__OUTPUT_ARGS("dc", "const char *")
662static int
663dc_text(pcmk__output_t *out, va_list args)
664{
665 const char *dc = va_arg(args, const char *);
666
667 if (!out->is_quiet(out)) {
668 return out->info(out, "Designated Controller is: %s", crm_str(dc));
669 } else if (dc != NULL) {
670 pcmk__formatted_printf(out, "%s\n", dc);
671 return pcmk_rc_ok;
672 }
673
674 return pcmk_rc_no_output;
675}
676
677PCMK__OUTPUT_ARGS("dc", "const char *")
678static int
679dc_xml(pcmk__output_t *out, va_list args)
680{
681 const char *dc = va_arg(args, const char *);
682
684 "node_name", crm_str(dc),
685 NULL);
686 return pcmk_rc_ok;
687}
688
689PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
690static int
691crmadmin_node_text(pcmk__output_t *out, va_list args)
692{
693 const char *type = va_arg(args, const char *);
694 const char *name = va_arg(args, const char *);
695 const char *id = va_arg(args, const char *);
696 gboolean BASH_EXPORT = va_arg(args, gboolean);
697
698 if (out->is_quiet(out)) {
699 pcmk__formatted_printf(out, "%s\n", crm_str(name));
700 return pcmk_rc_ok;
701 } else if (BASH_EXPORT) {
702 return out->info(out, "export %s=%s", crm_str(name), crm_str(id));
703 } else {
704 return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
706 }
707}
708
709PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
710static int
711crmadmin_node_xml(pcmk__output_t *out, va_list args)
712{
713 const char *type = va_arg(args, const char *);
714 const char *name = va_arg(args, const char *);
715 const char *id = va_arg(args, const char *);
716
718 "type", type ? type : "cluster",
719 "name", crm_str(name),
720 "id", crm_str(id),
721 NULL);
722 return pcmk_rc_ok;
723}
724
725PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
726 "guint", "op_digest_cache_t *")
727static int
728digests_text(pcmk__output_t *out, va_list args)
729{
730 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
731 pe_node_t *node = va_arg(args, pe_node_t *);
732 const char *task = va_arg(args, const char *);
733 guint interval_ms = va_arg(args, guint);
734 op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
735
736 char *action_desc = NULL;
737 const char *rsc_desc = "unknown resource";
738 const char *node_desc = "unknown node";
739
740 if (interval_ms != 0) {
741 action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
742 ((task == NULL)? "unknown" : task));
743 } else if (pcmk__str_eq(task, "monitor", pcmk__str_none)) {
744 action_desc = strdup("probe action");
745 } else {
746 action_desc = crm_strdup_printf("%s action",
747 ((task == NULL)? "unknown" : task));
748 }
749 if ((rsc != NULL) && (rsc->id != NULL)) {
750 rsc_desc = rsc->id;
751 }
752 if ((node != NULL) && (node->details->uname != NULL)) {
753 node_desc = node->details->uname;
754 }
755 out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
756 rsc_desc, action_desc, node_desc);
757 free(action_desc);
758
759 if (digests == NULL) {
760 out->list_item(out, NULL, "none");
761 out->end_list(out);
762 return pcmk_rc_ok;
763 }
764 if (digests->digest_all_calc != NULL) {
765 out->list_item(out, NULL, "%s (all parameters)",
766 digests->digest_all_calc);
767 }
768 if (digests->digest_secure_calc != NULL) {
769 out->list_item(out, NULL, "%s (non-private parameters)",
770 digests->digest_secure_calc);
771 }
772 if (digests->digest_restart_calc != NULL) {
773 out->list_item(out, NULL, "%s (non-reloadable parameters)",
774 digests->digest_restart_calc);
775 }
776 out->end_list(out);
777 return pcmk_rc_ok;
778}
779
780static void
781add_digest_xml(xmlNode *parent, const char *type, const char *digest,
782 xmlNode *digest_source)
783{
784 if (digest != NULL) {
785 xmlNodePtr digest_xml = create_xml_node(parent, "digest");
786
787 crm_xml_add(digest_xml, "type", ((type == NULL)? "unspecified" : type));
788 crm_xml_add(digest_xml, "hash", digest);
789 if (digest_source != NULL) {
790 add_node_copy(digest_xml, digest_source);
791 }
792 }
793}
794
795PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
796 "guint", "op_digest_cache_t *")
797static int
798digests_xml(pcmk__output_t *out, va_list args)
799{
800 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
801 pe_node_t *node = va_arg(args, pe_node_t *);
802 const char *task = va_arg(args, const char *);
803 guint interval_ms = va_arg(args, guint);
804 op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
805
806 char *interval_s = crm_strdup_printf("%ums", interval_ms);
807 xmlNode *xml = NULL;
808
809 xml = pcmk__output_create_xml_node(out, "digests",
810 "resource", crm_str(rsc->id),
811 "node", crm_str(node->details->uname),
812 "task", crm_str(task),
813 "interval", interval_s,
814 NULL);
815 free(interval_s);
816 if (digests != NULL) {
817 add_digest_xml(xml, "all", digests->digest_all_calc,
818 digests->params_all);
819 add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
820 digests->params_secure);
821 add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
822 digests->params_restart);
823 }
824 return pcmk_rc_ok;
825}
826
827#define STOP_SANITY_ASSERT(lineno) do { \
828 if(current && current->details->unclean) { \
829 /* It will be a pseudo op */ \
830 } else if(stop == NULL) { \
831 crm_err("%s:%d: No stop action exists for %s", \
832 __func__, lineno, rsc->id); \
833 CRM_ASSERT(stop != NULL); \
834 } else if (pcmk_is_set(stop->flags, pe_action_optional)) { \
835 crm_err("%s:%d: Action %s is still optional", \
836 __func__, lineno, stop->uuid); \
837 CRM_ASSERT(!pcmk_is_set(stop->flags, pe_action_optional)); \
838 } \
839 } while(0)
840
841PCMK__OUTPUT_ARGS("rsc-action", "pe_resource_t *", "pe_node_t *", "pe_node_t *",
842 "gboolean")
843static int
844rsc_action_default(pcmk__output_t *out, va_list args)
845{
846 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
847 pe_node_t *current = va_arg(args, pe_node_t *);
848 pe_node_t *next = va_arg(args, pe_node_t *);
849 gboolean moving = va_arg(args, gboolean);
850
851 GList *possible_matches = NULL;
852 char *key = NULL;
853 int rc = pcmk_rc_no_output;
854
855 pe_node_t *start_node = NULL;
856 pe_action_t *start = NULL;
857 pe_action_t *stop = NULL;
858 pe_action_t *promote = NULL;
859 pe_action_t *demote = NULL;
860
862 || (current == NULL && next == NULL)) {
863 pe_rsc_info(rsc, "Leave %s\t(%s%s)",
864 rsc->id, role2text(rsc->role),
865 !pcmk_is_set(rsc->flags, pe_rsc_managed)? " unmanaged" : "");
866 return rc;
867 }
868
869 if (current != NULL && next != NULL && !pcmk__str_eq(current->details->id, next->details->id, pcmk__str_casei)) {
870 moving = TRUE;
871 }
872
873 possible_matches = pe__resource_actions(rsc, next, RSC_START, FALSE);
874 if (possible_matches) {
875 start = possible_matches->data;
876 g_list_free(possible_matches);
877 }
878
879 if ((start == NULL) || !pcmk_is_set(start->flags, pe_action_runnable)) {
880 start_node = NULL;
881 } else {
882 start_node = current;
883 }
884 possible_matches = pe__resource_actions(rsc, start_node, RSC_STOP, FALSE);
885 if (possible_matches) {
886 stop = possible_matches->data;
887 g_list_free(possible_matches);
888 }
889
890 possible_matches = pe__resource_actions(rsc, next, RSC_PROMOTE, FALSE);
891 if (possible_matches) {
892 promote = possible_matches->data;
893 g_list_free(possible_matches);
894 }
895
896 possible_matches = pe__resource_actions(rsc, next, RSC_DEMOTE, FALSE);
897 if (possible_matches) {
898 demote = possible_matches->data;
899 g_list_free(possible_matches);
900 }
901
902 if (rsc->role == rsc->next_role) {
903 pe_action_t *migrate_op = NULL;
904
905 possible_matches = pe__resource_actions(rsc, next, RSC_MIGRATED, FALSE);
906 if (possible_matches) {
907 migrate_op = possible_matches->data;
908 }
909
910 CRM_CHECK(next != NULL,);
911 if (next == NULL) {
912 } else if ((migrate_op != NULL) && (current != NULL)
913 && pcmk_is_set(migrate_op->flags, pe_action_runnable)) {
914 rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
915 next, start, NULL);
916
917 } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
918 rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
919 next, start, NULL);
920
921 } else if (start == NULL || pcmk_is_set(start->flags, pe_action_optional)) {
922 if ((demote != NULL) && (promote != NULL)
924 && !pcmk_is_set(promote->flags, pe_action_optional)) {
925 rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
926 current, next, promote, demote);
927 } else {
928 pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
929 role2text(rsc->role), next->details->uname);
930 }
931
932 } else if (!pcmk_is_set(start->flags, pe_action_runnable)) {
933 rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
934 NULL, stop, (stop && stop->reason)? stop : start);
935 STOP_SANITY_ASSERT(__LINE__);
936
937 } else if (moving && current) {
938 rc = out->message(out, "rsc-action-item", pcmk_is_set(rsc->flags, pe_rsc_failed)? "Recover" : "Move",
939 rsc, current, next, stop, NULL);
940
941 } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
942 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
943 NULL, stop, NULL);
944 STOP_SANITY_ASSERT(__LINE__);
945
946 } else {
947 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
948 next, start, NULL);
949 /* STOP_SANITY_ASSERT(__LINE__); False positive for migrate-fail-7 */
950 }
951
952 g_list_free(possible_matches);
953 return rc;
954 }
955
956 if(stop
957 && (rsc->next_role == RSC_ROLE_STOPPED
958 || (start && !pcmk_is_set(start->flags, pe_action_runnable)))) {
959
960 GList *gIter = NULL;
961
962 key = stop_key(rsc);
963 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
964 pe_node_t *node = (pe_node_t *) gIter->data;
965 pe_action_t *stop_op = NULL;
966
967 possible_matches = find_actions(rsc->actions, key, node);
968 if (possible_matches) {
969 stop_op = possible_matches->data;
970 g_list_free(possible_matches);
971 }
972
973 if (stop_op && (stop_op->flags & pe_action_runnable)) {
974 STOP_SANITY_ASSERT(__LINE__);
975 }
976
977 if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
978 stop_op, (stop_op && stop_op->reason)? stop_op : start) == pcmk_rc_ok) {
979 rc = pcmk_rc_ok;
980 }
981 }
982
983 free(key);
984
985 } else if ((stop != NULL)
986 && pcmk_all_flags_set(rsc->flags, pe_rsc_failed|pe_rsc_stop)) {
987 /* 'stop' may be NULL if the failure was ignored */
988 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
989 next, stop, start);
990 STOP_SANITY_ASSERT(__LINE__);
991
992 } else if (moving) {
993 rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
994 stop, NULL);
995 STOP_SANITY_ASSERT(__LINE__);
996
997 } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
998 rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
999 start, NULL);
1000
1001 } else if (stop != NULL && !pcmk_is_set(stop->flags, pe_action_optional)) {
1002 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1003 next, start, NULL);
1004 STOP_SANITY_ASSERT(__LINE__);
1005
1006 } else if (rsc->role == RSC_ROLE_PROMOTED) {
1007 CRM_LOG_ASSERT(current != NULL);
1008 rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1009 next, demote, NULL);
1010
1011 } else if (rsc->next_role == RSC_ROLE_PROMOTED) {
1012 CRM_LOG_ASSERT(next);
1013 rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1014 next, promote, NULL);
1015
1016 } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role > RSC_ROLE_STOPPED) {
1017 rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1018 start, NULL);
1019 }
1020
1021 return rc;
1022}
1023
1024PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1025static int
1026node_action(pcmk__output_t *out, va_list args)
1027{
1028 char *task = va_arg(args, char *);
1029 char *node_name = va_arg(args, char *);
1030 char *reason = va_arg(args, char *);
1031
1032 if (task == NULL) {
1033 return pcmk_rc_no_output;
1034 } else if (reason) {
1035 out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1036 } else {
1037 crm_notice(" * %s %s\n", task, node_name);
1038 }
1039
1040 return pcmk_rc_ok;
1041}
1042
1043PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1044static int
1045node_action_xml(pcmk__output_t *out, va_list args)
1046{
1047 char *task = va_arg(args, char *);
1048 char *node_name = va_arg(args, char *);
1049 char *reason = va_arg(args, char *);
1050
1051 if (task == NULL) {
1052 return pcmk_rc_no_output;
1053 } else if (reason) {
1054 pcmk__output_create_xml_node(out, "node_action",
1055 "task", task,
1056 "node", node_name,
1057 "reason", reason,
1058 NULL);
1059 } else {
1060 crm_notice(" * %s %s\n", task, node_name);
1061 }
1062
1063 return pcmk_rc_ok;
1064}
1065
1066PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1067static int
1068inject_cluster_action(pcmk__output_t *out, va_list args)
1069{
1070 const char *node = va_arg(args, const char *);
1071 const char *task = va_arg(args, const char *);
1072 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1073
1074 if (out->is_quiet(out)) {
1075 return pcmk_rc_no_output;
1076 }
1077
1078 if(rsc) {
1079 out->list_item(out, NULL, "Cluster action: %s for %s on %s", task, ID(rsc), node);
1080 } else {
1081 out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1082 }
1083
1084 return pcmk_rc_ok;
1085}
1086
1087PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1088static int
1089inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1090{
1091 const char *node = va_arg(args, const char *);
1092 const char *task = va_arg(args, const char *);
1093 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1094
1095 xmlNodePtr xml_node = NULL;
1096
1097 if (out->is_quiet(out)) {
1098 return pcmk_rc_no_output;
1099 }
1100
1101 xml_node = pcmk__output_create_xml_node(out, "cluster_action",
1102 "task", task,
1103 "node", node,
1104 NULL);
1105
1106 if (rsc) {
1107 crm_xml_add(xml_node, "id", ID(rsc));
1108 }
1109
1110 return pcmk_rc_ok;
1111}
1112
1113PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1114static int
1115inject_fencing_action(pcmk__output_t *out, va_list args)
1116{
1117 char *target = va_arg(args, char *);
1118 const char *op = va_arg(args, const char *);
1119
1120 if (out->is_quiet(out)) {
1121 return pcmk_rc_no_output;
1122 }
1123
1124 out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1125 return pcmk_rc_ok;
1126}
1127
1128PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1129static int
1130inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1131{
1132 char *target = va_arg(args, char *);
1133 const char *op = va_arg(args, const char *);
1134
1135 if (out->is_quiet(out)) {
1136 return pcmk_rc_no_output;
1137 }
1138
1139 pcmk__output_create_xml_node(out, "fencing_action",
1140 "target", target,
1141 "op", op,
1142 NULL);
1143 return pcmk_rc_ok;
1144}
1145
1146PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1147static int
1148inject_attr(pcmk__output_t *out, va_list args)
1149{
1150 const char *name = va_arg(args, const char *);
1151 const char *value = va_arg(args, const char *);
1152 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1153
1154 xmlChar *node_path = NULL;
1155
1156 if (out->is_quiet(out)) {
1157 return pcmk_rc_no_output;
1158 }
1159
1160 node_path = xmlGetNodePath(cib_node);
1161
1162 out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1163 name, value, node_path, ID(cib_node));
1164
1165 free(node_path);
1166 return pcmk_rc_ok;
1167}
1168
1169PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1170static int
1171inject_attr_xml(pcmk__output_t *out, va_list args)
1172{
1173 const char *name = va_arg(args, const char *);
1174 const char *value = va_arg(args, const char *);
1175 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1176
1177 xmlChar *node_path = NULL;
1178
1179 if (out->is_quiet(out)) {
1180 return pcmk_rc_no_output;
1181 }
1182
1183 node_path = xmlGetNodePath(cib_node);
1184
1185 pcmk__output_create_xml_node(out, "inject_attr",
1186 "name", name,
1187 "value", value,
1188 "node_path", node_path,
1189 "cib_node", ID(cib_node),
1190 NULL);
1191 free(node_path);
1192 return pcmk_rc_ok;
1193}
1194
1195PCMK__OUTPUT_ARGS("inject-spec", "char *")
1196static int
1197inject_spec(pcmk__output_t *out, va_list args)
1198{
1199 char *spec = va_arg(args, char *);
1200
1201 if (out->is_quiet(out)) {
1202 return pcmk_rc_no_output;
1203 }
1204
1205 out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1206 return pcmk_rc_ok;
1207}
1208
1209PCMK__OUTPUT_ARGS("inject-spec", "char *")
1210static int
1211inject_spec_xml(pcmk__output_t *out, va_list args)
1212{
1213 char *spec = va_arg(args, char *);
1214
1215 if (out->is_quiet(out)) {
1216 return pcmk_rc_no_output;
1217 }
1218
1219 pcmk__output_create_xml_node(out, "inject_spec",
1220 "spec", spec,
1221 NULL);
1222 return pcmk_rc_ok;
1223}
1224
1225PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1226static int
1227inject_modify_config(pcmk__output_t *out, va_list args)
1228{
1229 const char *quorum = va_arg(args, const char *);
1230 const char *watchdog = va_arg(args, const char *);
1231
1232 if (out->is_quiet(out)) {
1233 return pcmk_rc_no_output;
1234 }
1235
1236 out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1237
1238 if (quorum) {
1239 out->list_item(out, NULL, "Setting quorum: %s", quorum);
1240 }
1241
1242 if (watchdog) {
1243 out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1244 }
1245
1246 return pcmk_rc_ok;
1247}
1248
1249PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1250static int
1251inject_modify_config_xml(pcmk__output_t *out, va_list args)
1252{
1253 const char *quorum = va_arg(args, const char *);
1254 const char *watchdog = va_arg(args, const char *);
1255
1256 xmlNodePtr node = NULL;
1257
1258 if (out->is_quiet(out)) {
1259 return pcmk_rc_no_output;
1260 }
1261
1262 node = pcmk__output_xml_create_parent(out, "modifications", NULL);
1263
1264 if (quorum) {
1265 crm_xml_add(node, "quorum", quorum);
1266 }
1267
1268 if (watchdog) {
1269 crm_xml_add(node, "watchdog", watchdog);
1270 }
1271
1272 return pcmk_rc_ok;
1273}
1274
1275PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1276static int
1277inject_modify_node(pcmk__output_t *out, va_list args)
1278{
1279 const char *action = va_arg(args, const char *);
1280 char *node = va_arg(args, char *);
1281
1282 if (out->is_quiet(out)) {
1283 return pcmk_rc_no_output;
1284 }
1285
1286 if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1287 out->list_item(out, NULL, "Bringing node %s online", node);
1288 return pcmk_rc_ok;
1289 } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1290 out->list_item(out, NULL, "Taking node %s offline", node);
1291 return pcmk_rc_ok;
1292 } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1293 out->list_item(out, NULL, "Failing node %s", node);
1294 return pcmk_rc_ok;
1295 }
1296
1297 return pcmk_rc_no_output;
1298}
1299
1300PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1301static int
1302inject_modify_node_xml(pcmk__output_t *out, va_list args)
1303{
1304 const char *action = va_arg(args, const char *);
1305 char *node = va_arg(args, char *);
1306
1307 if (out->is_quiet(out)) {
1308 return pcmk_rc_no_output;
1309 }
1310
1311 pcmk__output_create_xml_node(out, "modify_node",
1312 "action", action,
1313 "node", node,
1314 NULL);
1315 return pcmk_rc_ok;
1316}
1317
1318PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1319static int
1320inject_modify_ticket(pcmk__output_t *out, va_list args)
1321{
1322 const char *action = va_arg(args, const char *);
1323 char *ticket = va_arg(args, char *);
1324
1325 if (out->is_quiet(out)) {
1326 return pcmk_rc_no_output;
1327 }
1328
1329 if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1330 out->list_item(out, NULL, "Making ticket %s standby", ticket);
1331 } else {
1332 out->list_item(out, NULL, "%s ticket %s", action, ticket);
1333 }
1334
1335 return pcmk_rc_ok;
1336}
1337
1338PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1339static int
1340inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1341{
1342 const char *action = va_arg(args, const char *);
1343 char *ticket = va_arg(args, char *);
1344
1345 if (out->is_quiet(out)) {
1346 return pcmk_rc_no_output;
1347 }
1348
1349 pcmk__output_create_xml_node(out, "modify_ticket",
1350 "action", action,
1351 "ticket", ticket,
1352 NULL);
1353 return pcmk_rc_ok;
1354}
1355
1356PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1357static int
1358inject_pseudo_action(pcmk__output_t *out, va_list args)
1359{
1360 const char *node = va_arg(args, const char *);
1361 const char *task = va_arg(args, const char *);
1362
1363 if (out->is_quiet(out)) {
1364 return pcmk_rc_no_output;
1365 }
1366
1367 out->list_item(out, NULL, "Pseudo action: %s%s%s", task, node ? " on " : "",
1368 node ? node : "");
1369 return pcmk_rc_ok;
1370}
1371
1372PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1373static int
1374inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1375{
1376 const char *node = va_arg(args, const char *);
1377 const char *task = va_arg(args, const char *);
1378
1379 xmlNodePtr xml_node = NULL;
1380
1381 if (out->is_quiet(out)) {
1382 return pcmk_rc_no_output;
1383 }
1384
1385 xml_node = pcmk__output_create_xml_node(out, "pseudo_action",
1386 "task", task,
1387 NULL);
1388 if (node) {
1389 crm_xml_add(xml_node, "node", node);
1390 }
1391
1392 return pcmk_rc_ok;
1393}
1394
1395PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1396static int
1397inject_rsc_action(pcmk__output_t *out, va_list args)
1398{
1399 const char *rsc = va_arg(args, const char *);
1400 const char *operation = va_arg(args, const char *);
1401 char *node = va_arg(args, char *);
1402 guint interval_ms = va_arg(args, guint);
1403
1404 if (out->is_quiet(out)) {
1405 return pcmk_rc_no_output;
1406 }
1407
1408 if (interval_ms) {
1409 out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1410 rsc, operation, interval_ms, node);
1411 } else {
1412 out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1413 rsc, operation, node);
1414 }
1415
1416 return pcmk_rc_ok;
1417}
1418
1419PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1420static int
1421inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1422{
1423 const char *rsc = va_arg(args, const char *);
1424 const char *operation = va_arg(args, const char *);
1425 char *node = va_arg(args, char *);
1426 guint interval_ms = va_arg(args, guint);
1427
1428 xmlNodePtr xml_node = NULL;
1429
1430 if (out->is_quiet(out)) {
1431 return pcmk_rc_no_output;
1432 }
1433
1434 xml_node = pcmk__output_create_xml_node(out, "rsc_action",
1435 "resource", rsc,
1436 "op", operation,
1437 "node", node,
1438 NULL);
1439
1440 if (interval_ms) {
1441 char *interval_s = pcmk__itoa(interval_ms);
1442
1443 crm_xml_add(xml_node, "interval", interval_s);
1444 free(interval_s);
1445 }
1446
1447 return pcmk_rc_ok;
1448}
1449
1450#define CHECK_RC(retcode, retval) \
1451 if (retval == pcmk_rc_ok) { \
1452 retcode = pcmk_rc_ok; \
1453 }
1454
1455PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *", "crm_exit_t", "stonith_history_t *",
1456 "gboolean", "unsigned int", "unsigned int", "const char *", "GList *",
1457 "GList *")
1458int
1459pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
1460{
1461 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1462 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1463 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1464 gboolean fence_history = va_arg(args, gboolean);
1465 unsigned int section_opts = va_arg(args, unsigned int);
1466 unsigned int show_opts = va_arg(args, unsigned int);
1467 const char *prefix = va_arg(args, const char *);
1468 GList *unames = va_arg(args, GList *);
1469 GList *resources = va_arg(args, GList *);
1470
1471 int rc = pcmk_rc_no_output;
1472 bool already_printed_failure = false;
1473
1474 CHECK_RC(rc, out->message(out, "cluster-summary", data_set,
1475 section_opts, show_opts));
1476
1477 if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1479 CHECK_RC(rc, out->message(out, "node-list", data_set->nodes, unames,
1480 resources, show_opts));
1481 }
1482
1483 /* Print resources section, if needed */
1484 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1485 CHECK_RC(rc, out->message(out, "resource-list", data_set, show_opts,
1486 TRUE, unames, resources, rc == pcmk_rc_ok));
1487 }
1488
1489 /* print Node Attributes section if requested */
1490 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1491 CHECK_RC(rc, out->message(out, "node-attribute-list", data_set,
1492 show_opts, rc == pcmk_rc_ok, unames, resources));
1493 }
1494
1495 /* If requested, print resource operations (which includes failcounts)
1496 * or just failcounts
1497 */
1498 if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1499 CHECK_RC(rc, out->message(out, "node-summary", data_set, unames,
1500 resources, section_opts, show_opts, rc == pcmk_rc_ok));
1501 }
1502
1503 /* If there were any failed actions, print them */
1504 if (pcmk_is_set(section_opts, pcmk_section_failures)
1505 && xml_has_children(data_set->failed)) {
1506
1507 CHECK_RC(rc, out->message(out, "failed-action-list", data_set, unames,
1508 resources, rc == pcmk_rc_ok));
1509 }
1510
1511 /* Print failed stonith actions */
1512 if (pcmk_is_set(section_opts, pcmk_section_fence_failed) && fence_history) {
1513 if (history_rc == 0) {
1515 GINT_TO_POINTER(st_failed));
1516
1517 if (hp) {
1518 CHECK_RC(rc, out->message(out, "failed-fencing-list", stonith_history, unames,
1519 section_opts, rc == pcmk_rc_ok));
1520 }
1521 } else {
1523 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1524 out->list_item(out, NULL, "Failed to get fencing history: %s",
1525 crm_exit_str(history_rc));
1526 out->end_list(out);
1527
1528 already_printed_failure = true;
1529 }
1530 }
1531
1532 /* Print tickets if requested */
1533 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1534 CHECK_RC(rc, out->message(out, "ticket-list", data_set, rc == pcmk_rc_ok));
1535 }
1536
1537 /* Print negative location constraints if requested */
1538 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1539 CHECK_RC(rc, out->message(out, "ban-list", data_set, prefix, resources,
1540 show_opts, rc == pcmk_rc_ok));
1541 }
1542
1543 /* Print stonith history */
1544 if (fence_history && pcmk_any_flags_set(section_opts, pcmk_section_fencing_all)) {
1545 if (history_rc != 0) {
1546 if (!already_printed_failure) {
1548 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1549 out->list_item(out, NULL, "Failed to get fencing history: %s",
1550 crm_exit_str(history_rc));
1551 out->end_list(out);
1552 }
1553 } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1555 GINT_TO_POINTER(st_failed));
1556
1557 if (hp) {
1558 CHECK_RC(rc, out->message(out, "fencing-list", hp, unames,
1559 section_opts, rc == pcmk_rc_ok));
1560 }
1561 } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1563
1564 if (hp) {
1565 CHECK_RC(rc, out->message(out, "pending-fencing-list", hp, unames,
1566 section_opts, rc == pcmk_rc_ok));
1567 }
1568 }
1569 }
1570
1571 return rc;
1572}
1573
1574PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *", "crm_exit_t", "stonith_history_t *",
1575 "gboolean", "unsigned int", "unsigned int", "const char *", "GList *",
1576 "GList *")
1577static int
1578cluster_status_xml(pcmk__output_t *out, va_list args)
1579{
1580 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1581 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1582 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1583 gboolean fence_history = va_arg(args, gboolean);
1584 unsigned int section_opts = va_arg(args, unsigned int);
1585 unsigned int show_opts = va_arg(args, unsigned int);
1586 const char *prefix = va_arg(args, const char *);
1587 GList *unames = va_arg(args, GList *);
1588 GList *resources = va_arg(args, GList *);
1589
1590 out->message(out, "cluster-summary", data_set, section_opts, show_opts);
1591
1592 /*** NODES ***/
1593 if (pcmk_is_set(section_opts, pcmk_section_nodes)) {
1594 out->message(out, "node-list", data_set->nodes, unames, resources, show_opts);
1595 }
1596
1597 /* Print resources section, if needed */
1598 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1599 /* XML output always displays full details. */
1600 unsigned int full_show_opts = show_opts & ~pcmk_show_brief;
1601
1602 out->message(out, "resource-list", data_set, full_show_opts,
1603 FALSE, unames, resources, FALSE);
1604 }
1605
1606 /* print Node Attributes section if requested */
1607 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1608 out->message(out, "node-attribute-list", data_set, show_opts, FALSE,
1609 unames, resources);
1610 }
1611
1612 /* If requested, print resource operations (which includes failcounts)
1613 * or just failcounts
1614 */
1615 if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1616 out->message(out, "node-summary", data_set, unames,
1617 resources, section_opts, show_opts, FALSE);
1618 }
1619
1620 /* If there were any failed actions, print them */
1621 if (pcmk_is_set(section_opts, pcmk_section_failures)
1622 && xml_has_children(data_set->failed)) {
1623
1624 out->message(out, "failed-action-list", data_set, unames, resources,
1625 FALSE);
1626 }
1627
1628 /* Print stonith history */
1629 if (pcmk_is_set(section_opts, pcmk_section_fencing_all) && fence_history) {
1630 out->message(out, "full-fencing-list", history_rc, stonith_history,
1631 unames, section_opts, FALSE);
1632 }
1633
1634 /* Print tickets if requested */
1635 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1636 out->message(out, "ticket-list", data_set, FALSE);
1637 }
1638
1639 /* Print negative location constraints if requested */
1640 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1641 out->message(out, "ban-list", data_set, prefix, resources, show_opts,
1642 FALSE);
1643 }
1644
1645 return pcmk_rc_ok;
1646}
1647
1648PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *", "crm_exit_t", "stonith_history_t *",
1649 "gboolean", "unsigned int", "unsigned int", "const char *", "GList *",
1650 "GList *")
1651static int
1652cluster_status_html(pcmk__output_t *out, va_list args)
1653{
1654 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1655 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1656 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1657 gboolean fence_history = va_arg(args, gboolean);
1658 unsigned int section_opts = va_arg(args, unsigned int);
1659 unsigned int show_opts = va_arg(args, unsigned int);
1660 const char *prefix = va_arg(args, const char *);
1661 GList *unames = va_arg(args, GList *);
1662 GList *resources = va_arg(args, GList *);
1663 bool already_printed_failure = false;
1664
1665 out->message(out, "cluster-summary", data_set, section_opts, show_opts);
1666
1667 /*** NODE LIST ***/
1668 if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1669 out->message(out, "node-list", data_set->nodes, unames, resources, show_opts);
1670 }
1671
1672 /* Print resources section, if needed */
1673 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1674 out->message(out, "resource-list", data_set, show_opts, TRUE, unames,
1675 resources, FALSE);
1676 }
1677
1678 /* print Node Attributes section if requested */
1679 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1680 out->message(out, "node-attribute-list", data_set, show_opts, FALSE,
1681 unames, resources);
1682 }
1683
1684 /* If requested, print resource operations (which includes failcounts)
1685 * or just failcounts
1686 */
1687 if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1688 out->message(out, "node-summary", data_set, unames,
1689 resources, section_opts, show_opts, FALSE);
1690 }
1691
1692 /* If there were any failed actions, print them */
1693 if (pcmk_is_set(section_opts, pcmk_section_failures)
1694 && xml_has_children(data_set->failed)) {
1695
1696 out->message(out, "failed-action-list", data_set, unames, resources,
1697 FALSE);
1698 }
1699
1700 /* Print failed stonith actions */
1701 if (pcmk_is_set(section_opts, pcmk_section_fence_failed) && fence_history) {
1702 if (history_rc == 0) {
1704 GINT_TO_POINTER(st_failed));
1705
1706 if (hp) {
1707 out->message(out, "failed-fencing-list", stonith_history, unames,
1708 section_opts, FALSE);
1709 }
1710 } else {
1711 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1712 out->list_item(out, NULL, "Failed to get fencing history: %s",
1713 crm_exit_str(history_rc));
1714 out->end_list(out);
1715 }
1716 }
1717
1718 /* Print stonith history */
1719 if (fence_history && pcmk_any_flags_set(section_opts, pcmk_section_fencing_all)) {
1720 if (history_rc != 0) {
1721 if (!already_printed_failure) {
1722 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1723 out->list_item(out, NULL, "Failed to get fencing history: %s",
1724 crm_exit_str(history_rc));
1725 out->end_list(out);
1726 }
1727 } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1729 GINT_TO_POINTER(st_failed));
1730
1731 if (hp) {
1732 out->message(out, "fencing-list", hp, unames, section_opts, FALSE);
1733 }
1734 } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1736
1737 if (hp) {
1738 out->message(out, "pending-fencing-list", hp, unames,
1739 section_opts, FALSE);
1740 }
1741 }
1742 }
1743
1744 /* Print tickets if requested */
1745 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1746 out->message(out, "ticket-list", data_set, FALSE);
1747 }
1748
1749 /* Print negative location constraints if requested */
1750 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1751 out->message(out, "ban-list", data_set, prefix, resources, show_opts,
1752 FALSE);
1753 }
1754
1755 return pcmk_rc_ok;
1756}
1757
1758static pcmk__message_entry_t fmt_functions[] = {
1759 { "cluster-status", "default", pcmk__cluster_status_text },
1760 { "cluster-status", "html", cluster_status_html },
1761 { "cluster-status", "xml", cluster_status_xml },
1762 { "crmadmin-node", "default", crmadmin_node_text },
1763 { "crmadmin-node", "xml", crmadmin_node_xml },
1764 { "dc", "default", dc_text },
1765 { "dc", "xml", dc_xml },
1766 { "digests", "default", digests_text },
1767 { "digests", "xml", digests_xml },
1768 { "health", "default", health_text },
1769 { "health", "xml", health_xml },
1770 { "inject-attr", "default", inject_attr },
1771 { "inject-attr", "xml", inject_attr_xml },
1772 { "inject-cluster-action", "default", inject_cluster_action },
1773 { "inject-cluster-action", "xml", inject_cluster_action_xml },
1774 { "inject-fencing-action", "default", inject_fencing_action },
1775 { "inject-fencing-action", "xml", inject_fencing_action_xml },
1776 { "inject-modify-config", "default", inject_modify_config },
1777 { "inject-modify-config", "xml", inject_modify_config_xml },
1778 { "inject-modify-node", "default", inject_modify_node },
1779 { "inject-modify-node", "xml", inject_modify_node_xml },
1780 { "inject-modify-ticket", "default", inject_modify_ticket },
1781 { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
1782 { "inject-pseudo-action", "default", inject_pseudo_action },
1783 { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
1784 { "inject-rsc-action", "default", inject_rsc_action },
1785 { "inject-rsc-action", "xml", inject_rsc_action_xml },
1786 { "inject-spec", "default", inject_spec },
1787 { "inject-spec", "xml", inject_spec_xml },
1788 { "locations-list", "default", locations_list },
1789 { "locations-list", "xml", locations_list_xml },
1790 { "node-action", "default", node_action },
1791 { "node-action", "xml", node_action_xml },
1792 { "pacemakerd-health", "default", pacemakerd_health_text },
1793 { "pacemakerd-health", "xml", pacemakerd_health_xml },
1794 { "rsc-action", "default", rsc_action_default },
1795 { "rsc-action-item", "default", rsc_action_item },
1796 { "rsc-action-item", "xml", rsc_action_item_xml },
1797 { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
1798 { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
1799 { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
1800 { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
1801 { "stacks-constraints", "default", stacks_and_constraints },
1802 { "stacks-constraints", "xml", stacks_and_constraints_xml },
1803
1804 { NULL, NULL, NULL }
1805};
1806
1807void
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition cib_utils.c:146
char * score2char(int score)
Definition utils.c:117
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:114
const char * role2text(enum rsc_role_e role)
Definition common.c:459
@ RSC_ROLE_STARTED
Definition common.h:95
@ RSC_ROLE_STOPPED
Definition common.h:94
@ RSC_ROLE_PROMOTED
Definition common.h:97
@ RSC_ROLE_UNKNOWN
Definition common.h:93
@ RSC_ROLE_UNPROMOTED
Definition common.h:96
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition complex.c:903
enum crm_ais_msg_types type
Definition cpg.c:3
uint32_t id
Definition cpg.c:0
#define RSC_PROMOTE
Definition crm.h:207
#define RSC_DEMOTE
Definition crm.h:209
#define RSC_START
Definition crm.h:201
#define RSC_STOP
Definition crm.h:204
#define RSC_MIGRATED
Definition crm.h:199
bool stonith__event_state_pending(stonith_history_t *history, void *user_data)
Definition st_client.c:2639
bool stonith__event_state_neq(stonith_history_t *history, void *user_data)
Definition st_client.c:2651
bool stonith__event_state_eq(stonith_history_t *history, void *user_data)
Definition st_client.c:2645
stonith_history_t * stonith__first_matching_event(stonith_history_t *history, bool(*matching_fn)(stonith_history_t *, void *), void *user_data)
Definition st_client.c:2625
#define crm_str(x)
Definition logging.h:376
#define CRM_LOG_ASSERT(expr)
Definition logging.h:202
#define crm_notice(fmt, args...)
Definition logging.h:352
#define CRM_CHECK(expr, failure_action)
Definition logging.h:218
#define ID(x)
Definition msg_xml.h:456
#define XML_CONS_TAG_RSC_LOCATION
Definition msg_xml.h:347
#define XML_CONS_TAG_RSC_DEPEND
Definition msg_xml.h:345
#define XML_CIB_TAG_CONSTRAINTS
Definition msg_xml.h:183
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:324
Control output from tools.
@ pcmk_section_nodes
Definition output.h:32
@ pcmk_section_operations
Definition output.h:36
@ pcmk_section_attributes
Definition output.h:34
@ pcmk_section_fence_worked
Definition output.h:39
@ pcmk_section_fence_pending
Definition output.h:38
@ pcmk_section_bans
Definition output.h:41
@ pcmk_section_failures
Definition output.h:42
@ pcmk_section_tickets
Definition output.h:40
@ pcmk_section_failcounts
Definition output.h:35
@ pcmk_section_resources
Definition output.h:33
@ pcmk_section_fence_failed
Definition output.h:37
#define pcmk_section_fencing_all
Definition output.h:45
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition output_xml.c:511
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition output.c:145
xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition output_xml.c:432
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition output_xml.c:465
void void void pcmk__formatted_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define PCMK__OUTPUT_ARGS(ARGS...)
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
char * name
Definition pcmk_fence.c:31
const char * action
Definition pcmk_fence.c:30
int rc
Definition pcmk_fence.c:35
const char * target
Definition pcmk_fence.c:29
void pcmk__register_lib_messages(pcmk__output_t *out)
#define CHECK_RC(retcode, retval)
#define STOP_SANITY_ASSERT(lineno)
int pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
#define pe_rsc_managed
Definition pe_types.h:249
#define pe_rsc_allocating
Definition pe_types.h:259
#define pe_rsc_reload
Definition pe_types.h:263
@ pe_action_optional
Definition pe_types.h:294
@ pe_action_runnable
Definition pe_types.h:293
#define pe_rsc_stop
Definition pe_types.h:262
#define pe_rsc_failed
Definition pe_types.h:267
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
Definition utils.c:1546
GList * find_actions(GList *input, const char *key, const pe_node_t *on_node)
Definition utils.c:1458
void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
Definition utils.c:1935
#define stop_key(rsc)
Definition internal.h:376
#define pe__set_resource_flags(resource, flags_to_set)
Definition internal.h:47
#define pe_rsc_info(rsc, fmt, args...)
Definition internal.h:18
Function and executable result codes.
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk_rc_no_output
Definition results.h:112
@ pcmk_rc_ok
Definition results.h:142
const char * crm_exit_str(crm_exit_t exit_code)
Definition results.c:526
enum crm_exit_e crm_exit_t
Fencing aka. STONITH.
@ st_failed
Definition stonith-ng.h:77
@ pcmk__str_none
@ pcmk__str_casei
char * digest_all_calc
Definition internal.h:482
xmlNode * params_secure
Definition internal.h:480
char * digest_secure_calc
Definition internal.h:483
char * digest_restart_calc
Definition internal.h:484
xmlNode * params_restart
Definition internal.h:481
xmlNode * params_all
Definition internal.h:479
pe_resource_t * rsc_lh
const char * node_attribute
pe_resource_t * rsc_rh
This structure contains everything that makes up a single output formatter.
char * reason
Definition pe_types.h:418
enum pe_action_flags flags
Definition pe_types.h:420
struct pe_node_shared_s * details
Definition pe_types.h:244
const char * id
Definition pe_types.h:208
const char * uname
Definition pe_types.h:209
GList * running_on
Definition pe_types.h:367
GList * actions
Definition pe_types.h:360
GList * rsc_location
Definition pe_types.h:359
GList * rsc_cons
Definition pe_types.h:358
GList * rsc_cons_lhs
Definition pe_types.h:357
unsigned long long flags
Definition pe_types.h:349
enum rsc_role_e next_role
Definition pe_types.h:372
enum rsc_role_e role
Definition pe_types.h:371
xmlNode * input
Definition pe_types.h:137
xmlNode * failed
Definition pe_types.h:165
gboolean xml_has_children(const xmlNode *root)
Definition xml.c:2027
const xmlChar * pcmkXmlStr
Definition xml.h:51
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition xml.c:674
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition xml.c:696
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition xml.c:2972