This source file includes following definitions.
- colocations_header
- colocations_xml_node
- do_locations_list_xml
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- add_digest_xml
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- pcmk__register_lib_messages
1
2
3
4
5
6
7
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>
15 #include <crm/fencing/internal.h>
16 #include <crm/pengine/internal.h>
17 #include <libxml/tree.h>
18 #include <pacemaker-internal.h>
19
20 #include <inttypes.h>
21 #include <stdint.h>
22
23 static char *
24 colocations_header(pe_resource_t *rsc, pcmk__colocation_t *cons,
25 bool dependents) {
26 char *retval = NULL;
27
28 if (cons->primary_role > RSC_ROLE_STARTED) {
29 retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
30 rsc->id, pcmk_readable_score(cons->score),
31 (dependents? "needs" : "with"),
32 role2text(cons->primary_role), cons->id);
33 } else {
34 retval = crm_strdup_printf("%s (score=%s, id=%s)",
35 rsc->id, pcmk_readable_score(cons->score),
36 cons->id);
37 }
38 return retval;
39 }
40
41 static void
42 colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
43 pcmk__colocation_t *cons) {
44 xmlNodePtr node = NULL;
45
46 node = pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_DEPEND,
47 "id", cons->id,
48 "rsc", cons->dependent->id,
49 "with-rsc", cons->primary->id,
50 "score", pcmk_readable_score(cons->score),
51 NULL);
52
53 if (cons->node_attribute) {
54 xmlSetProp(node, (pcmkXmlStr) "node-attribute", (pcmkXmlStr) cons->node_attribute);
55 }
56
57 if (cons->dependent_role != RSC_ROLE_UNKNOWN) {
58 xmlSetProp(node, (pcmkXmlStr) "rsc-role",
59 (pcmkXmlStr) role2text(cons->dependent_role));
60 }
61
62 if (cons->primary_role != RSC_ROLE_UNKNOWN) {
63 xmlSetProp(node, (pcmkXmlStr) "with-rsc-role",
64 (pcmkXmlStr) role2text(cons->primary_role));
65 }
66 }
67
68 static int
69 do_locations_list_xml(pcmk__output_t *out, pe_resource_t *rsc, bool add_header)
70 {
71 GList *lpc = NULL;
72 GList *list = rsc->rsc_location;
73 int rc = pcmk_rc_no_output;
74
75 for (lpc = list; lpc != NULL; lpc = lpc->next) {
76 pe__location_t *cons = lpc->data;
77
78 GList *lpc2 = NULL;
79
80 for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
81 pe_node_t *node = (pe_node_t *) lpc2->data;
82
83 if (add_header) {
84 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "locations");
85 }
86
87 pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_LOCATION,
88 "node", node->details->uname,
89 "rsc", rsc->id,
90 "id", cons->id,
91 "score", pcmk_readable_score(node->weight),
92 NULL);
93 }
94 }
95
96 if (add_header) {
97 PCMK__OUTPUT_LIST_FOOTER(out, rc);
98 }
99
100 return rc;
101 }
102
103 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
104 "pe_node_t *", "pe_node_t *", "pe_action_t *",
105 "pe_action_t *")
106 static int
107 rsc_action_item(pcmk__output_t *out, va_list args)
108 {
109 const char *change = va_arg(args, const char *);
110 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
111 pe_node_t *origin = va_arg(args, pe_node_t *);
112 pe_node_t *destination = va_arg(args, pe_node_t *);
113 pe_action_t *action = va_arg(args, pe_action_t *);
114 pe_action_t *source = va_arg(args, pe_action_t *);
115
116 int len = 0;
117 char *reason = NULL;
118 char *details = NULL;
119 bool same_host = false;
120 bool same_role = false;
121 bool need_role = false;
122
123 static int rsc_width = 5;
124 static int detail_width = 5;
125
126 CRM_ASSERT(action);
127 CRM_ASSERT(destination != NULL || origin != NULL);
128
129 if(source == NULL) {
130 source = action;
131 }
132
133 len = strlen(rsc->id);
134 if(len > rsc_width) {
135 rsc_width = len + 2;
136 }
137
138 if ((rsc->role > RSC_ROLE_STARTED)
139 || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
140 need_role = true;
141 }
142
143 if(origin != NULL && destination != NULL && origin->details == destination->details) {
144 same_host = true;
145 }
146
147 if(rsc->role == rsc->next_role) {
148 same_role = true;
149 }
150
151 if (need_role && (origin == NULL)) {
152
153 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role),
154 role2text(rsc->next_role),
155 pe__node_name(destination));
156
157 } else if (origin == NULL) {
158
159 details = crm_strdup_printf("%s", pe__node_name(destination));
160
161 } else if (need_role && (destination == NULL)) {
162
163 details = crm_strdup_printf("%s %s", role2text(rsc->role),
164 pe__node_name(origin));
165
166 } else if (destination == NULL) {
167
168 details = crm_strdup_printf("%s", pe__node_name(origin));
169
170 } else if (need_role && same_role && same_host) {
171
172 details = crm_strdup_printf("%s %s", role2text(rsc->role),
173 pe__node_name(origin));
174
175 } else if (same_role && same_host) {
176
177 details = crm_strdup_printf("%s", pe__node_name(origin));
178
179 } else if (need_role && same_role) {
180
181 details = crm_strdup_printf("%s -> %s %s", pe__node_name(origin),
182 pe__node_name(destination),
183 role2text(rsc->role));
184
185 } else if (same_role) {
186
187 details = crm_strdup_printf("%s -> %s", pe__node_name(origin),
188 pe__node_name(destination));
189
190 } else if (same_host) {
191
192 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role),
193 role2text(rsc->next_role),
194 pe__node_name(origin));
195
196 } else {
197
198 details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role),
199 pe__node_name(origin),
200 role2text(rsc->next_role),
201 pe__node_name(destination));
202 }
203
204 len = strlen(details);
205 if(len > detail_width) {
206 detail_width = len;
207 }
208
209 if(source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
210 reason = crm_strdup_printf("due to %s (blocked)", source->reason);
211
212 } else if(source->reason) {
213 reason = crm_strdup_printf("due to %s", source->reason);
214
215 } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
216 reason = strdup("blocked");
217
218 }
219
220 out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s", change, rsc_width,
221 rsc->id, detail_width, details, reason ? " " : "", reason ? reason : "");
222
223 free(details);
224 free(reason);
225 return pcmk_rc_ok;
226 }
227
228 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
229 "pe_node_t *", "pe_node_t *", "pe_action_t *",
230 "pe_action_t *")
231 static int
232 rsc_action_item_xml(pcmk__output_t *out, va_list args)
233 {
234 const char *change = va_arg(args, const char *);
235 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
236 pe_node_t *origin = va_arg(args, pe_node_t *);
237 pe_node_t *destination = va_arg(args, pe_node_t *);
238 pe_action_t *action = va_arg(args, pe_action_t *);
239 pe_action_t *source = va_arg(args, pe_action_t *);
240
241 char *change_str = NULL;
242
243 bool same_host = false;
244 bool same_role = false;
245 bool need_role = false;
246 xmlNode *xml = NULL;
247
248 CRM_ASSERT(action);
249 CRM_ASSERT(destination != NULL || origin != NULL);
250
251 if (source == NULL) {
252 source = action;
253 }
254
255 if ((rsc->role > RSC_ROLE_STARTED)
256 || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
257 need_role = true;
258 }
259
260 if(origin != NULL && destination != NULL && origin->details == destination->details) {
261 same_host = true;
262 }
263
264 if(rsc->role == rsc->next_role) {
265 same_role = true;
266 }
267
268 change_str = g_ascii_strdown(change, -1);
269 xml = pcmk__output_create_xml_node(out, "rsc_action",
270 "action", change_str,
271 "resource", rsc->id,
272 NULL);
273 g_free(change_str);
274
275 if (need_role && (origin == NULL)) {
276
277 pcmk__xe_set_props(xml,
278 "role", role2text(rsc->role),
279 "next-role", role2text(rsc->next_role),
280 "dest", destination->details->uname,
281 NULL);
282
283 } else if (origin == NULL) {
284
285 crm_xml_add(xml, "node", destination->details->uname);
286
287 } else if (need_role && (destination == NULL)) {
288
289 pcmk__xe_set_props(xml,
290 "role", role2text(rsc->role),
291 "node", origin->details->uname,
292 NULL);
293
294 } else if (destination == NULL) {
295
296 crm_xml_add(xml, "node", origin->details->uname);
297
298 } else if (need_role && same_role && same_host) {
299
300 pcmk__xe_set_props(xml,
301 "role", role2text(rsc->role),
302 "source", origin->details->uname,
303 NULL);
304
305 } else if (same_role && same_host) {
306
307 crm_xml_add(xml, "source", origin->details->uname);
308
309 } else if (need_role && same_role) {
310
311 pcmk__xe_set_props(xml,
312 "source", origin->details->uname,
313 "dest", destination->details->uname,
314 "role", role2text(rsc->role),
315 NULL);
316
317 } else if (same_role) {
318
319 pcmk__xe_set_props(xml,
320 "source", origin->details->uname,
321 "dest", destination->details->uname,
322 NULL);
323
324 } else if (same_host) {
325
326 pcmk__xe_set_props(xml,
327 "role", role2text(rsc->role),
328 "next-role", role2text(rsc->next_role),
329 "source", origin->details->uname,
330 NULL);
331
332 } else {
333
334 pcmk__xe_set_props(xml,
335 "role", role2text(rsc->role),
336 "source", origin->details->uname,
337 "next-role", role2text(rsc->next_role),
338 "dest", destination->details->uname,
339 NULL);
340 }
341
342 if (source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
343 pcmk__xe_set_props(xml,
344 "reason", source->reason,
345 "blocked", "true",
346 NULL);
347
348 } else if(source->reason) {
349 crm_xml_add(xml, "reason", source->reason);
350
351 } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
352 pcmk__xe_set_bool_attr(xml, "blocked", true);
353
354 }
355
356 return pcmk_rc_ok;
357 }
358
359 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "bool")
360 static int
361 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
362 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
363 bool recursive = va_arg(args, int);
364
365 int rc = pcmk_rc_no_output;
366
367 if (pcmk_is_set(rsc->flags, pe_rsc_detect_loop)) {
368 return rc;
369 }
370
371
372
373
374 pe__set_resource_flags(rsc, pe_rsc_detect_loop);
375 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
376 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
377 char *hdr = NULL;
378
379 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Resources %s is colocated with", rsc->id);
380
381 if (pcmk_is_set(cons->primary->flags, pe_rsc_detect_loop)) {
382 out->list_item(out, NULL, "%s (id=%s - loop)",
383 cons->primary->id, cons->id);
384 continue;
385 }
386
387 hdr = colocations_header(cons->primary, cons, false);
388 out->list_item(out, NULL, "%s", hdr);
389 free(hdr);
390
391
392 out->begin_list(out, NULL, NULL, NULL);
393
394 out->message(out, "locations-list", cons->primary);
395 if (recursive) {
396 out->message(out, "rsc-is-colocated-with-list",
397 cons->primary, recursive);
398 }
399
400 out->end_list(out);
401 }
402
403 PCMK__OUTPUT_LIST_FOOTER(out, rc);
404 return rc;
405 }
406
407 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "bool")
408 static int
409 rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
410 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
411 bool recursive = va_arg(args, int);
412
413 int rc = pcmk_rc_no_output;
414
415 if (pcmk_is_set(rsc->flags, pe_rsc_detect_loop)) {
416 return rc;
417 }
418
419
420
421
422 pe__set_resource_flags(rsc, pe_rsc_detect_loop);
423 for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
424 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
425
426 if (pcmk_is_set(cons->primary->flags, pe_rsc_detect_loop)) {
427 colocations_xml_node(out, cons->primary, cons);
428 continue;
429 }
430
431 colocations_xml_node(out, cons->primary, cons);
432 do_locations_list_xml(out, cons->primary, false);
433
434 if (recursive) {
435 out->message(out, "rsc-is-colocated-with-list",
436 cons->primary, recursive);
437 }
438 }
439
440 return rc;
441 }
442
443 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "bool")
444 static int
445 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
446 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
447 bool recursive = va_arg(args, int);
448
449 int rc = pcmk_rc_no_output;
450
451 if (pcmk_is_set(rsc->flags, pe_rsc_detect_loop)) {
452 return rc;
453 }
454
455
456
457
458
459 pe__set_resource_flags(rsc, pe_rsc_detect_loop);
460 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
461 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
462 char *hdr = NULL;
463
464 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Resources colocated with %s", rsc->id);
465
466 if (pcmk_is_set(cons->dependent->flags, pe_rsc_detect_loop)) {
467 out->list_item(out, NULL, "%s (id=%s - loop)",
468 cons->dependent->id, cons->id);
469 continue;
470 }
471
472 hdr = colocations_header(cons->dependent, cons, true);
473 out->list_item(out, NULL, "%s", hdr);
474 free(hdr);
475
476
477 out->begin_list(out, NULL, NULL, NULL);
478
479 out->message(out, "locations-list", cons->dependent);
480 if (recursive) {
481 out->message(out, "rscs-colocated-with-list",
482 cons->dependent, recursive);
483 }
484
485 out->end_list(out);
486 }
487
488 PCMK__OUTPUT_LIST_FOOTER(out, rc);
489 return rc;
490 }
491
492 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "bool")
493 static int
494 rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
495 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
496 bool recursive = va_arg(args, int);
497
498 int rc = pcmk_rc_no_output;
499
500 if (pcmk_is_set(rsc->flags, pe_rsc_detect_loop)) {
501 return rc;
502 }
503
504
505
506
507
508 pe__set_resource_flags(rsc, pe_rsc_detect_loop);
509 for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
510 pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
511
512 if (pcmk_is_set(cons->dependent->flags, pe_rsc_detect_loop)) {
513 colocations_xml_node(out, cons->dependent, cons);
514 continue;
515 }
516
517 colocations_xml_node(out, cons->dependent, cons);
518 do_locations_list_xml(out, cons->dependent, false);
519
520 if (recursive) {
521 out->message(out, "rscs-colocated-with-list",
522 cons->dependent, recursive);
523 }
524 }
525
526 return rc;
527 }
528
529 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
530 static int
531 locations_list(pcmk__output_t *out, va_list args) {
532 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
533
534 GList *lpc = NULL;
535 GList *list = rsc->rsc_location;
536 int rc = pcmk_rc_no_output;
537
538 for (lpc = list; lpc != NULL; lpc = lpc->next) {
539 pe__location_t *cons = lpc->data;
540
541 GList *lpc2 = NULL;
542
543 for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
544 pe_node_t *node = (pe_node_t *) lpc2->data;
545
546 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Locations");
547 out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
548 pe__node_name(node),
549 pcmk_readable_score(node->weight), cons->id,
550 rsc->id);
551 }
552 }
553
554 PCMK__OUTPUT_LIST_FOOTER(out, rc);
555 return rc;
556 }
557
558 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
559 static int
560 locations_list_xml(pcmk__output_t *out, va_list args) {
561 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
562 return do_locations_list_xml(out, rsc, true);
563 }
564
565 PCMK__OUTPUT_ARGS("locations-and-colocations", "pe_resource_t *",
566 "pe_working_set_t *", "bool", "bool")
567 static int
568 locations_and_colocations(pcmk__output_t *out, va_list args)
569 {
570 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
571 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
572 bool recursive = va_arg(args, int);
573 bool force = va_arg(args, int);
574
575 pcmk__unpack_constraints(data_set);
576
577
578 if (!force) {
579 rsc = uber_parent(rsc);
580 }
581
582 out->message(out, "locations-list", rsc);
583
584 pe__clear_resource_flags_on_all(data_set, pe_rsc_detect_loop);
585 out->message(out, "rscs-colocated-with-list", rsc, recursive);
586
587 pe__clear_resource_flags_on_all(data_set, pe_rsc_detect_loop);
588 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
589 return pcmk_rc_ok;
590 }
591
592 PCMK__OUTPUT_ARGS("locations-and-colocations", "pe_resource_t *",
593 "pe_working_set_t *", "bool", "bool")
594 static int
595 locations_and_colocations_xml(pcmk__output_t *out, va_list args)
596 {
597 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
598 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
599 bool recursive = va_arg(args, int);
600 bool force = va_arg(args, int);
601
602 pcmk__unpack_constraints(data_set);
603
604
605 if (!force) {
606 rsc = uber_parent(rsc);
607 }
608
609 pcmk__output_xml_create_parent(out, "constraints", NULL);
610 do_locations_list_xml(out, rsc, false);
611
612 pe__clear_resource_flags_on_all(data_set, pe_rsc_detect_loop);
613 out->message(out, "rscs-colocated-with-list", rsc, recursive);
614
615 pe__clear_resource_flags_on_all(data_set, pe_rsc_detect_loop);
616 out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
617
618 pcmk__output_xml_pop_parent(out);
619 return pcmk_rc_ok;
620 }
621
622 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
623 static int
624 health(pcmk__output_t *out, va_list args)
625 {
626 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
627 const char *host_from = va_arg(args, const char *);
628 const char *fsa_state = va_arg(args, const char *);
629 const char *result = va_arg(args, const char *);
630
631 return out->info(out, "Controller on %s in state %s: %s",
632 pcmk__s(host_from, "unknown node"),
633 pcmk__s(fsa_state, "unknown"),
634 pcmk__s(result, "unknown result"));
635 }
636
637 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
638 static int
639 health_text(pcmk__output_t *out, va_list args)
640 {
641 if (!out->is_quiet(out)) {
642 return health(out, args);
643 } else {
644 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
645 const char *host_from G_GNUC_UNUSED = va_arg(args, const char *);
646 const char *fsa_state = va_arg(args, const char *);
647 const char *result G_GNUC_UNUSED = va_arg(args, const char *);
648
649 if (fsa_state != NULL) {
650 pcmk__formatted_printf(out, "%s\n", fsa_state);
651 return pcmk_rc_ok;
652 }
653 }
654
655 return pcmk_rc_no_output;
656 }
657
658 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
659 static int
660 health_xml(pcmk__output_t *out, va_list args)
661 {
662 const char *sys_from = va_arg(args, const char *);
663 const char *host_from = va_arg(args, const char *);
664 const char *fsa_state = va_arg(args, const char *);
665 const char *result = va_arg(args, const char *);
666
667 pcmk__output_create_xml_node(out, pcmk__s(sys_from, ""),
668 "node_name", pcmk__s(host_from, ""),
669 "state", pcmk__s(fsa_state, ""),
670 "result", pcmk__s(result, ""),
671 NULL);
672 return pcmk_rc_ok;
673 }
674
675 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
676 "enum pcmk_pacemakerd_state", "const char *", "time_t")
677 static int
678 pacemakerd_health(pcmk__output_t *out, va_list args)
679 {
680 const char *sys_from = va_arg(args, const char *);
681 enum pcmk_pacemakerd_state state =
682 (enum pcmk_pacemakerd_state) va_arg(args, int);
683 const char *state_s = va_arg(args, const char *);
684 time_t last_updated = va_arg(args, time_t);
685
686 char *last_updated_s = NULL;
687 int rc = pcmk_rc_ok;
688
689 if (sys_from == NULL) {
690 if (state == pcmk_pacemakerd_state_remote) {
691 sys_from = "pacemaker-remoted";
692 } else {
693 sys_from = CRM_SYSTEM_MCP;
694 }
695 }
696
697 if (state_s == NULL) {
698 state_s = pcmk__pcmkd_state_enum2friendly(state);
699 }
700
701 if (last_updated != 0) {
702 last_updated_s = pcmk__epoch2str(&last_updated,
703 crm_time_log_date
704 |crm_time_log_timeofday
705 |crm_time_log_with_timezone);
706 }
707
708 rc = out->info(out, "Status of %s: '%s' (last updated %s)",
709 sys_from, state_s,
710 pcmk__s(last_updated_s, "at unknown time"));
711
712 free(last_updated_s);
713 return rc;
714 }
715
716 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
717 "enum pcmk_pacemakerd_state", "const char *", "time_t")
718 static int
719 pacemakerd_health_html(pcmk__output_t *out, va_list args)
720 {
721 const char *sys_from = va_arg(args, const char *);
722 enum pcmk_pacemakerd_state state =
723 (enum pcmk_pacemakerd_state) va_arg(args, int);
724 const char *state_s = va_arg(args, const char *);
725 time_t last_updated = va_arg(args, time_t);
726
727 char *last_updated_s = NULL;
728 char *msg = NULL;
729
730 if (sys_from == NULL) {
731 if (state == pcmk_pacemakerd_state_remote) {
732 sys_from = "pacemaker-remoted";
733 } else {
734 sys_from = CRM_SYSTEM_MCP;
735 }
736 }
737
738 if (state_s == NULL) {
739 state_s = pcmk__pcmkd_state_enum2friendly(state);
740 }
741
742 if (last_updated != 0) {
743 last_updated_s = pcmk__epoch2str(&last_updated,
744 crm_time_log_date
745 |crm_time_log_timeofday
746 |crm_time_log_with_timezone);
747 }
748
749 msg = crm_strdup_printf("Status of %s: '%s' (last updated %s)",
750 sys_from, state_s,
751 pcmk__s(last_updated_s, "at unknown time"));
752 pcmk__output_create_html_node(out, "li", NULL, NULL, msg);
753
754 free(msg);
755 free(last_updated_s);
756 return pcmk_rc_ok;
757 }
758
759 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
760 "enum pcmk_pacemakerd_state", "const char *", "time_t")
761 static int
762 pacemakerd_health_text(pcmk__output_t *out, va_list args)
763 {
764 if (!out->is_quiet(out)) {
765 return pacemakerd_health(out, args);
766 } else {
767 const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
768 enum pcmk_pacemakerd_state state =
769 (enum pcmk_pacemakerd_state) va_arg(args, int);
770 const char *state_s = va_arg(args, const char *);
771 time_t last_updated G_GNUC_UNUSED = va_arg(args, time_t);
772
773 if (state_s == NULL) {
774 state_s = pcmk_pacemakerd_api_daemon_state_enum2text(state);
775 }
776 pcmk__formatted_printf(out, "%s\n", state_s);
777 return pcmk_rc_ok;
778 }
779 }
780
781 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
782 "enum pcmk_pacemakerd_state", "const char *", "time_t")
783 static int
784 pacemakerd_health_xml(pcmk__output_t *out, va_list args)
785 {
786 const char *sys_from = va_arg(args, const char *);
787 enum pcmk_pacemakerd_state state =
788 (enum pcmk_pacemakerd_state) va_arg(args, int);
789 const char *state_s = va_arg(args, const char *);
790 time_t last_updated = va_arg(args, time_t);
791
792 char *last_updated_s = NULL;
793
794 if (sys_from == NULL) {
795 if (state == pcmk_pacemakerd_state_remote) {
796 sys_from = "pacemaker-remoted";
797 } else {
798 sys_from = CRM_SYSTEM_MCP;
799 }
800 }
801
802 if (state_s == NULL) {
803 state_s = pcmk_pacemakerd_api_daemon_state_enum2text(state);
804 }
805
806 if (last_updated != 0) {
807 last_updated_s = pcmk__epoch2str(&last_updated,
808 crm_time_log_date
809 |crm_time_log_timeofday
810 |crm_time_log_with_timezone);
811 }
812
813 pcmk__output_create_xml_node(out, "pacemakerd",
814 "sys_from", sys_from,
815 "state", state_s,
816 "last_updated", last_updated_s,
817 NULL);
818 free(last_updated_s);
819 return pcmk_rc_ok;
820 }
821
822 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
823 static int
824 profile_default(pcmk__output_t *out, va_list args) {
825 const char *xml_file = va_arg(args, const char *);
826 clock_t start = va_arg(args, clock_t);
827 clock_t end = va_arg(args, clock_t);
828
829 out->list_item(out, NULL, "Testing %s ... %.2f secs", xml_file,
830 (end - start) / (float) CLOCKS_PER_SEC);
831
832 return pcmk_rc_ok;
833 }
834
835 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
836 static int
837 profile_xml(pcmk__output_t *out, va_list args) {
838 const char *xml_file = va_arg(args, const char *);
839 clock_t start = va_arg(args, clock_t);
840 clock_t end = va_arg(args, clock_t);
841
842 char *duration = pcmk__ftoa((end - start) / (float) CLOCKS_PER_SEC);
843
844 pcmk__output_create_xml_node(out, "timing",
845 "file", xml_file,
846 "duration", duration,
847 NULL);
848
849 free(duration);
850 return pcmk_rc_ok;
851 }
852
853 PCMK__OUTPUT_ARGS("dc", "const char *")
854 static int
855 dc(pcmk__output_t *out, va_list args)
856 {
857 const char *dc = va_arg(args, const char *);
858
859 return out->info(out, "Designated Controller is: %s",
860 pcmk__s(dc, "not yet elected"));
861 }
862
863 PCMK__OUTPUT_ARGS("dc", "const char *")
864 static int
865 dc_text(pcmk__output_t *out, va_list args)
866 {
867 if (!out->is_quiet(out)) {
868 return dc(out, args);
869 } else {
870 const char *dc = va_arg(args, const char *);
871
872 if (dc != NULL) {
873 pcmk__formatted_printf(out, "%s\n", pcmk__s(dc, ""));
874 return pcmk_rc_ok;
875 }
876 }
877
878 return pcmk_rc_no_output;
879 }
880
881 PCMK__OUTPUT_ARGS("dc", "const char *")
882 static int
883 dc_xml(pcmk__output_t *out, va_list args)
884 {
885 const char *dc = va_arg(args, const char *);
886
887 pcmk__output_create_xml_node(out, "dc",
888 "node_name", pcmk__s(dc, ""),
889 NULL);
890 return pcmk_rc_ok;
891 }
892
893 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "bool")
894 static int
895 crmadmin_node(pcmk__output_t *out, va_list args)
896 {
897 const char *type = va_arg(args, const char *);
898 const char *name = va_arg(args, const char *);
899 const char *id = va_arg(args, const char *);
900 bool bash_export = va_arg(args, int);
901
902 if (bash_export) {
903 return out->info(out, "export %s=%s",
904 pcmk__s(name, "<null>"), pcmk__s(id, ""));
905 } else {
906 return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
907 pcmk__s(name, "<null>"), pcmk__s(id, "<null>"));
908 }
909 }
910
911 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "bool")
912 static int
913 crmadmin_node_text(pcmk__output_t *out, va_list args)
914 {
915 if (!out->is_quiet(out)) {
916 return crmadmin_node(out, args);
917 } else {
918 const char *type G_GNUC_UNUSED = va_arg(args, const char *);
919 const char *name = va_arg(args, const char *);
920 const char *id G_GNUC_UNUSED = va_arg(args, const char *);
921 bool bash_export G_GNUC_UNUSED = va_arg(args, int);
922
923 pcmk__formatted_printf(out, "%s\n", pcmk__s(name, "<null>"));
924 return pcmk_rc_ok;
925 }
926 }
927
928 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "bool")
929 static int
930 crmadmin_node_xml(pcmk__output_t *out, va_list args)
931 {
932 const char *type = va_arg(args, const char *);
933 const char *name = va_arg(args, const char *);
934 const char *id = va_arg(args, const char *);
935 bool bash_export G_GNUC_UNUSED = va_arg(args, int);
936
937 pcmk__output_create_xml_node(out, "node",
938 "type", type ? type : "cluster",
939 "name", pcmk__s(name, ""),
940 "id", pcmk__s(id, ""),
941 NULL);
942 return pcmk_rc_ok;
943 }
944
945 PCMK__OUTPUT_ARGS("digests", "const pe_resource_t *", "const pe_node_t *",
946 "const char *", "guint", "const op_digest_cache_t *")
947 static int
948 digests_text(pcmk__output_t *out, va_list args)
949 {
950 const pe_resource_t *rsc = va_arg(args, const pe_resource_t *);
951 const pe_node_t *node = va_arg(args, const pe_node_t *);
952 const char *task = va_arg(args, const char *);
953 guint interval_ms = va_arg(args, guint);
954 const op_digest_cache_t *digests = va_arg(args, const op_digest_cache_t *);
955
956 char *action_desc = NULL;
957 const char *rsc_desc = "unknown resource";
958 const char *node_desc = "unknown node";
959
960 if (interval_ms != 0) {
961 action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
962 ((task == NULL)? "unknown" : task));
963 } else if (pcmk__str_eq(task, "monitor", pcmk__str_none)) {
964 action_desc = strdup("probe action");
965 } else {
966 action_desc = crm_strdup_printf("%s action",
967 ((task == NULL)? "unknown" : task));
968 }
969 if ((rsc != NULL) && (rsc->id != NULL)) {
970 rsc_desc = rsc->id;
971 }
972 if ((node != NULL) && (node->details->uname != NULL)) {
973 node_desc = node->details->uname;
974 }
975 out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
976 rsc_desc, action_desc, node_desc);
977 free(action_desc);
978
979 if (digests == NULL) {
980 out->list_item(out, NULL, "none");
981 out->end_list(out);
982 return pcmk_rc_ok;
983 }
984 if (digests->digest_all_calc != NULL) {
985 out->list_item(out, NULL, "%s (all parameters)",
986 digests->digest_all_calc);
987 }
988 if (digests->digest_secure_calc != NULL) {
989 out->list_item(out, NULL, "%s (non-private parameters)",
990 digests->digest_secure_calc);
991 }
992 if (digests->digest_restart_calc != NULL) {
993 out->list_item(out, NULL, "%s (non-reloadable parameters)",
994 digests->digest_restart_calc);
995 }
996 out->end_list(out);
997 return pcmk_rc_ok;
998 }
999
1000 static void
1001 add_digest_xml(xmlNode *parent, const char *type, const char *digest,
1002 xmlNode *digest_source)
1003 {
1004 if (digest != NULL) {
1005 xmlNodePtr digest_xml = create_xml_node(parent, "digest");
1006
1007 crm_xml_add(digest_xml, "type", ((type == NULL)? "unspecified" : type));
1008 crm_xml_add(digest_xml, "hash", digest);
1009 if (digest_source != NULL) {
1010 add_node_copy(digest_xml, digest_source);
1011 }
1012 }
1013 }
1014
1015 PCMK__OUTPUT_ARGS("digests", "const pe_resource_t *", "const pe_node_t *",
1016 "const char *", "guint", "const op_digest_cache_t *")
1017 static int
1018 digests_xml(pcmk__output_t *out, va_list args)
1019 {
1020 const pe_resource_t *rsc = va_arg(args, const pe_resource_t *);
1021 const pe_node_t *node = va_arg(args, const pe_node_t *);
1022 const char *task = va_arg(args, const char *);
1023 guint interval_ms = va_arg(args, guint);
1024 const op_digest_cache_t *digests = va_arg(args, const op_digest_cache_t *);
1025
1026 char *interval_s = crm_strdup_printf("%ums", interval_ms);
1027 xmlNode *xml = NULL;
1028
1029 xml = pcmk__output_create_xml_node(out, "digests",
1030 "resource", pcmk__s(rsc->id, ""),
1031 "node", pcmk__s(node->details->uname, ""),
1032 "task", pcmk__s(task, ""),
1033 "interval", interval_s,
1034 NULL);
1035 free(interval_s);
1036 if (digests != NULL) {
1037 add_digest_xml(xml, "all", digests->digest_all_calc,
1038 digests->params_all);
1039 add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
1040 digests->params_secure);
1041 add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
1042 digests->params_restart);
1043 }
1044 return pcmk_rc_ok;
1045 }
1046
1047 #define STOP_SANITY_ASSERT(lineno) do { \
1048 if(current && current->details->unclean) { \
1049 \
1050 } else if(stop == NULL) { \
1051 crm_err("%s:%d: No stop action exists for %s", \
1052 __func__, lineno, rsc->id); \
1053 CRM_ASSERT(stop != NULL); \
1054 } else if (pcmk_is_set(stop->flags, pe_action_optional)) { \
1055 crm_err("%s:%d: Action %s is still optional", \
1056 __func__, lineno, stop->uuid); \
1057 CRM_ASSERT(!pcmk_is_set(stop->flags, pe_action_optional)); \
1058 } \
1059 } while(0)
1060
1061 PCMK__OUTPUT_ARGS("rsc-action", "pe_resource_t *", "pe_node_t *", "pe_node_t *")
1062 static int
1063 rsc_action_default(pcmk__output_t *out, va_list args)
1064 {
1065 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1066 pe_node_t *current = va_arg(args, pe_node_t *);
1067 pe_node_t *next = va_arg(args, pe_node_t *);
1068
1069 GList *possible_matches = NULL;
1070 char *key = NULL;
1071 int rc = pcmk_rc_no_output;
1072 bool moving = false;
1073
1074 pe_node_t *start_node = NULL;
1075 pe_action_t *start = NULL;
1076 pe_action_t *stop = NULL;
1077 pe_action_t *promote = NULL;
1078 pe_action_t *demote = NULL;
1079
1080 if (!pcmk_is_set(rsc->flags, pe_rsc_managed)
1081 || (current == NULL && next == NULL)) {
1082 pe_rsc_info(rsc, "Leave %s\t(%s%s)",
1083 rsc->id, role2text(rsc->role),
1084 !pcmk_is_set(rsc->flags, pe_rsc_managed)? " unmanaged" : "");
1085 return rc;
1086 }
1087
1088 moving = (current != NULL) && (next != NULL)
1089 && (current->details != next->details);
1090
1091 possible_matches = pe__resource_actions(rsc, next, RSC_START, false);
1092 if (possible_matches) {
1093 start = possible_matches->data;
1094 g_list_free(possible_matches);
1095 }
1096
1097 if ((start == NULL) || !pcmk_is_set(start->flags, pe_action_runnable)) {
1098 start_node = NULL;
1099 } else {
1100 start_node = current;
1101 }
1102 possible_matches = pe__resource_actions(rsc, start_node, RSC_STOP, false);
1103 if (possible_matches) {
1104 stop = possible_matches->data;
1105 g_list_free(possible_matches);
1106 } else if (pcmk_is_set(rsc->flags, pe_rsc_stop_unexpected)) {
1107
1108
1109
1110
1111 possible_matches = pe__resource_actions(rsc, NULL, RSC_STOP, false);
1112 if (possible_matches != NULL) {
1113 stop = possible_matches->data;
1114 g_list_free(possible_matches);
1115 }
1116 }
1117
1118 possible_matches = pe__resource_actions(rsc, next, RSC_PROMOTE, false);
1119 if (possible_matches) {
1120 promote = possible_matches->data;
1121 g_list_free(possible_matches);
1122 }
1123
1124 possible_matches = pe__resource_actions(rsc, next, RSC_DEMOTE, false);
1125 if (possible_matches) {
1126 demote = possible_matches->data;
1127 g_list_free(possible_matches);
1128 }
1129
1130 if (rsc->role == rsc->next_role) {
1131 pe_action_t *migrate_op = NULL;
1132
1133 CRM_CHECK(next != NULL, return rc);
1134
1135 possible_matches = pe__resource_actions(rsc, next, RSC_MIGRATED, false);
1136 if (possible_matches) {
1137 migrate_op = possible_matches->data;
1138 }
1139
1140 if ((migrate_op != NULL) && (current != NULL)
1141 && pcmk_is_set(migrate_op->flags, pe_action_runnable)) {
1142 rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
1143 next, start, NULL);
1144
1145 } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
1146 rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
1147 next, start, NULL);
1148
1149 } else if (start == NULL || pcmk_is_set(start->flags, pe_action_optional)) {
1150 if ((demote != NULL) && (promote != NULL)
1151 && !pcmk_is_set(demote->flags, pe_action_optional)
1152 && !pcmk_is_set(promote->flags, pe_action_optional)) {
1153 rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
1154 current, next, promote, demote);
1155 } else {
1156 pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
1157 role2text(rsc->role), pe__node_name(next));
1158 }
1159
1160 } else if (!pcmk_is_set(start->flags, pe_action_runnable)) {
1161 rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
1162 NULL, stop, (stop && stop->reason)? stop : start);
1163 STOP_SANITY_ASSERT(__LINE__);
1164
1165 } else if (moving && current) {
1166 rc = out->message(out, "rsc-action-item", pcmk_is_set(rsc->flags, pe_rsc_failed)? "Recover" : "Move",
1167 rsc, current, next, stop, NULL);
1168
1169 } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
1170 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1171 NULL, stop, NULL);
1172 STOP_SANITY_ASSERT(__LINE__);
1173
1174 } else {
1175 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1176 next, start, NULL);
1177
1178 }
1179
1180 g_list_free(possible_matches);
1181 return rc;
1182 }
1183
1184 if(stop
1185 && (rsc->next_role == RSC_ROLE_STOPPED
1186 || (start && !pcmk_is_set(start->flags, pe_action_runnable)))) {
1187
1188 GList *gIter = NULL;
1189
1190 key = stop_key(rsc);
1191 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
1192 pe_node_t *node = (pe_node_t *) gIter->data;
1193 pe_action_t *stop_op = NULL;
1194
1195 possible_matches = find_actions(rsc->actions, key, node);
1196 if (possible_matches) {
1197 stop_op = possible_matches->data;
1198 g_list_free(possible_matches);
1199 }
1200
1201 if (stop_op && (stop_op->flags & pe_action_runnable)) {
1202 STOP_SANITY_ASSERT(__LINE__);
1203 }
1204
1205 if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
1206 stop_op, (stop_op && stop_op->reason)? stop_op : start) == pcmk_rc_ok) {
1207 rc = pcmk_rc_ok;
1208 }
1209 }
1210
1211 free(key);
1212
1213 } else if ((stop != NULL)
1214 && pcmk_all_flags_set(rsc->flags, pe_rsc_failed|pe_rsc_stop)) {
1215
1216 rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1217 next, stop, start);
1218 STOP_SANITY_ASSERT(__LINE__);
1219
1220 } else if (moving) {
1221 rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
1222 stop, NULL);
1223 STOP_SANITY_ASSERT(__LINE__);
1224
1225 } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
1226 rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
1227 start, NULL);
1228
1229 } else if (stop != NULL && !pcmk_is_set(stop->flags, pe_action_optional)) {
1230 rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1231 next, start, NULL);
1232 STOP_SANITY_ASSERT(__LINE__);
1233
1234 } else if (rsc->role == RSC_ROLE_PROMOTED) {
1235 CRM_LOG_ASSERT(current != NULL);
1236 rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1237 next, demote, NULL);
1238
1239 } else if (rsc->next_role == RSC_ROLE_PROMOTED) {
1240 CRM_LOG_ASSERT(next);
1241 rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1242 next, promote, NULL);
1243
1244 } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role > RSC_ROLE_STOPPED) {
1245 rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1246 start, NULL);
1247 }
1248
1249 return rc;
1250 }
1251
1252 PCMK__OUTPUT_ARGS("node-action", "const char *", "const char *", "const char *")
1253 static int
1254 node_action(pcmk__output_t *out, va_list args)
1255 {
1256 const char *task = va_arg(args, const char *);
1257 const char *node_name = va_arg(args, const char *);
1258 const char *reason = va_arg(args, const char *);
1259
1260 if (task == NULL) {
1261 return pcmk_rc_no_output;
1262 } else if (reason) {
1263 out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1264 } else {
1265 crm_notice(" * %s %s", task, node_name);
1266 }
1267
1268 return pcmk_rc_ok;
1269 }
1270
1271 PCMK__OUTPUT_ARGS("node-action", "const char *", "const char *", "const char *")
1272 static int
1273 node_action_xml(pcmk__output_t *out, va_list args)
1274 {
1275 const char *task = va_arg(args, const char *);
1276 const char *node_name = va_arg(args, const char *);
1277 const char *reason = va_arg(args, const char *);
1278
1279 if (task == NULL) {
1280 return pcmk_rc_no_output;
1281 } else if (reason) {
1282 pcmk__output_create_xml_node(out, "node_action",
1283 "task", task,
1284 "node", node_name,
1285 "reason", reason,
1286 NULL);
1287 } else {
1288 crm_notice(" * %s %s", task, node_name);
1289 }
1290
1291 return pcmk_rc_ok;
1292 }
1293
1294 PCMK__OUTPUT_ARGS("node-info", "int", "const char *", "const char *",
1295 "const char *", "bool", "bool")
1296 static int
1297 node_info_default(pcmk__output_t *out, va_list args)
1298 {
1299 int node_id = va_arg(args, int);
1300 const char *node_name = va_arg(args, const char *);
1301 const char *uuid = va_arg(args, const char *);
1302 const char *state = va_arg(args, const char *);
1303 bool have_quorum = (bool) va_arg(args, int);
1304 bool is_remote = (bool) va_arg(args, int);
1305
1306 return out->info(out,
1307 "Node %d: %s "
1308 "(uuid=%s, state=%s, have_quorum=%s, is_remote=%s)",
1309 node_id, pcmk__s(node_name, "unknown"),
1310 pcmk__s(uuid, "unknown"), pcmk__s(state, "unknown"),
1311 pcmk__btoa(have_quorum), pcmk__btoa(is_remote));
1312 }
1313
1314 PCMK__OUTPUT_ARGS("node-info", "int", "const char *", "const char *",
1315 "const char *", "bool", "bool")
1316 static int
1317 node_info_xml(pcmk__output_t *out, va_list args)
1318 {
1319 int node_id = va_arg(args, int);
1320 const char *node_name = va_arg(args, const char *);
1321 const char *uuid = va_arg(args, const char *);
1322 const char *state = va_arg(args, const char *);
1323 bool have_quorum = (bool) va_arg(args, int);
1324 bool is_remote = (bool) va_arg(args, int);
1325
1326 char *id_s = crm_strdup_printf("%d", node_id);
1327
1328 pcmk__output_create_xml_node(out, "node-info",
1329 "nodeid", id_s,
1330 XML_ATTR_UNAME, node_name,
1331 XML_ATTR_ID, uuid,
1332 XML_NODE_IS_PEER, state,
1333 XML_ATTR_HAVE_QUORUM, pcmk__btoa(have_quorum),
1334 XML_NODE_IS_REMOTE, pcmk__btoa(is_remote),
1335 NULL);
1336 free(id_s);
1337 return pcmk_rc_ok;
1338 }
1339
1340 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1341 static int
1342 inject_cluster_action(pcmk__output_t *out, va_list args)
1343 {
1344 const char *node = va_arg(args, const char *);
1345 const char *task = va_arg(args, const char *);
1346 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1347
1348 if (out->is_quiet(out)) {
1349 return pcmk_rc_no_output;
1350 }
1351
1352 if(rsc) {
1353 out->list_item(out, NULL, "Cluster action: %s for %s on %s", task, ID(rsc), node);
1354 } else {
1355 out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1356 }
1357
1358 return pcmk_rc_ok;
1359 }
1360
1361 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1362 static int
1363 inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1364 {
1365 const char *node = va_arg(args, const char *);
1366 const char *task = va_arg(args, const char *);
1367 xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1368
1369 xmlNodePtr xml_node = NULL;
1370
1371 if (out->is_quiet(out)) {
1372 return pcmk_rc_no_output;
1373 }
1374
1375 xml_node = pcmk__output_create_xml_node(out, "cluster_action",
1376 "task", task,
1377 "node", node,
1378 NULL);
1379
1380 if (rsc) {
1381 crm_xml_add(xml_node, "id", ID(rsc));
1382 }
1383
1384 return pcmk_rc_ok;
1385 }
1386
1387 PCMK__OUTPUT_ARGS("inject-fencing-action", "const char *", "const char *")
1388 static int
1389 inject_fencing_action(pcmk__output_t *out, va_list args)
1390 {
1391 const char *target = va_arg(args, const char *);
1392 const char *op = va_arg(args, const char *);
1393
1394 if (out->is_quiet(out)) {
1395 return pcmk_rc_no_output;
1396 }
1397
1398 out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1399 return pcmk_rc_ok;
1400 }
1401
1402 PCMK__OUTPUT_ARGS("inject-fencing-action", "const char *", "const char *")
1403 static int
1404 inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1405 {
1406 const char *target = va_arg(args, const char *);
1407 const char *op = va_arg(args, const char *);
1408
1409 if (out->is_quiet(out)) {
1410 return pcmk_rc_no_output;
1411 }
1412
1413 pcmk__output_create_xml_node(out, "fencing_action",
1414 "target", target,
1415 "op", op,
1416 NULL);
1417 return pcmk_rc_ok;
1418 }
1419
1420 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1421 static int
1422 inject_attr(pcmk__output_t *out, va_list args)
1423 {
1424 const char *name = va_arg(args, const char *);
1425 const char *value = va_arg(args, const char *);
1426 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1427
1428 xmlChar *node_path = NULL;
1429
1430 if (out->is_quiet(out)) {
1431 return pcmk_rc_no_output;
1432 }
1433
1434 node_path = xmlGetNodePath(cib_node);
1435
1436 out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1437 name, value, node_path, ID(cib_node));
1438
1439 free(node_path);
1440 return pcmk_rc_ok;
1441 }
1442
1443 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1444 static int
1445 inject_attr_xml(pcmk__output_t *out, va_list args)
1446 {
1447 const char *name = va_arg(args, const char *);
1448 const char *value = va_arg(args, const char *);
1449 xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1450
1451 xmlChar *node_path = NULL;
1452
1453 if (out->is_quiet(out)) {
1454 return pcmk_rc_no_output;
1455 }
1456
1457 node_path = xmlGetNodePath(cib_node);
1458
1459 pcmk__output_create_xml_node(out, "inject_attr",
1460 "name", name,
1461 "value", value,
1462 "node_path", node_path,
1463 "cib_node", ID(cib_node),
1464 NULL);
1465 free(node_path);
1466 return pcmk_rc_ok;
1467 }
1468
1469 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1470 static int
1471 inject_spec(pcmk__output_t *out, va_list args)
1472 {
1473 const char *spec = va_arg(args, const char *);
1474
1475 if (out->is_quiet(out)) {
1476 return pcmk_rc_no_output;
1477 }
1478
1479 out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1480 return pcmk_rc_ok;
1481 }
1482
1483 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1484 static int
1485 inject_spec_xml(pcmk__output_t *out, va_list args)
1486 {
1487 const char *spec = va_arg(args, const char *);
1488
1489 if (out->is_quiet(out)) {
1490 return pcmk_rc_no_output;
1491 }
1492
1493 pcmk__output_create_xml_node(out, "inject_spec",
1494 "spec", spec,
1495 NULL);
1496 return pcmk_rc_ok;
1497 }
1498
1499 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1500 static int
1501 inject_modify_config(pcmk__output_t *out, va_list args)
1502 {
1503 const char *quorum = va_arg(args, const char *);
1504 const char *watchdog = va_arg(args, const char *);
1505
1506 if (out->is_quiet(out)) {
1507 return pcmk_rc_no_output;
1508 }
1509
1510 out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1511
1512 if (quorum) {
1513 out->list_item(out, NULL, "Setting quorum: %s", quorum);
1514 }
1515
1516 if (watchdog) {
1517 out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1518 }
1519
1520 return pcmk_rc_ok;
1521 }
1522
1523 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1524 static int
1525 inject_modify_config_xml(pcmk__output_t *out, va_list args)
1526 {
1527 const char *quorum = va_arg(args, const char *);
1528 const char *watchdog = va_arg(args, const char *);
1529
1530 xmlNodePtr node = NULL;
1531
1532 if (out->is_quiet(out)) {
1533 return pcmk_rc_no_output;
1534 }
1535
1536 node = pcmk__output_xml_create_parent(out, "modifications", NULL);
1537
1538 if (quorum) {
1539 crm_xml_add(node, "quorum", quorum);
1540 }
1541
1542 if (watchdog) {
1543 crm_xml_add(node, "watchdog", watchdog);
1544 }
1545
1546 return pcmk_rc_ok;
1547 }
1548
1549 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "const char *")
1550 static int
1551 inject_modify_node(pcmk__output_t *out, va_list args)
1552 {
1553 const char *action = va_arg(args, const char *);
1554 const char *node = va_arg(args, const char *);
1555
1556 if (out->is_quiet(out)) {
1557 return pcmk_rc_no_output;
1558 }
1559
1560 if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1561 out->list_item(out, NULL, "Bringing node %s online", node);
1562 return pcmk_rc_ok;
1563 } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1564 out->list_item(out, NULL, "Taking node %s offline", node);
1565 return pcmk_rc_ok;
1566 } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1567 out->list_item(out, NULL, "Failing node %s", node);
1568 return pcmk_rc_ok;
1569 }
1570
1571 return pcmk_rc_no_output;
1572 }
1573
1574 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "const char *")
1575 static int
1576 inject_modify_node_xml(pcmk__output_t *out, va_list args)
1577 {
1578 const char *action = va_arg(args, const char *);
1579 const char *node = va_arg(args, const char *);
1580
1581 if (out->is_quiet(out)) {
1582 return pcmk_rc_no_output;
1583 }
1584
1585 pcmk__output_create_xml_node(out, "modify_node",
1586 "action", action,
1587 "node", node,
1588 NULL);
1589 return pcmk_rc_ok;
1590 }
1591
1592 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "const char *")
1593 static int
1594 inject_modify_ticket(pcmk__output_t *out, va_list args)
1595 {
1596 const char *action = va_arg(args, const char *);
1597 const char *ticket = va_arg(args, const char *);
1598
1599 if (out->is_quiet(out)) {
1600 return pcmk_rc_no_output;
1601 }
1602
1603 if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1604 out->list_item(out, NULL, "Making ticket %s standby", ticket);
1605 } else {
1606 out->list_item(out, NULL, "%s ticket %s", action, ticket);
1607 }
1608
1609 return pcmk_rc_ok;
1610 }
1611
1612 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "const char *")
1613 static int
1614 inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1615 {
1616 const char *action = va_arg(args, const char *);
1617 const char *ticket = va_arg(args, const char *);
1618
1619 if (out->is_quiet(out)) {
1620 return pcmk_rc_no_output;
1621 }
1622
1623 pcmk__output_create_xml_node(out, "modify_ticket",
1624 "action", action,
1625 "ticket", ticket,
1626 NULL);
1627 return pcmk_rc_ok;
1628 }
1629
1630 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1631 static int
1632 inject_pseudo_action(pcmk__output_t *out, va_list args)
1633 {
1634 const char *node = va_arg(args, const char *);
1635 const char *task = va_arg(args, const char *);
1636
1637 if (out->is_quiet(out)) {
1638 return pcmk_rc_no_output;
1639 }
1640
1641 out->list_item(out, NULL, "Pseudo action: %s%s%s", task, node ? " on " : "",
1642 node ? node : "");
1643 return pcmk_rc_ok;
1644 }
1645
1646 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1647 static int
1648 inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1649 {
1650 const char *node = va_arg(args, const char *);
1651 const char *task = va_arg(args, const char *);
1652
1653 xmlNodePtr xml_node = NULL;
1654
1655 if (out->is_quiet(out)) {
1656 return pcmk_rc_no_output;
1657 }
1658
1659 xml_node = pcmk__output_create_xml_node(out, "pseudo_action",
1660 "task", task,
1661 NULL);
1662 if (node) {
1663 crm_xml_add(xml_node, "node", node);
1664 }
1665
1666 return pcmk_rc_ok;
1667 }
1668
1669 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *",
1670 "const char *", "guint")
1671 static int
1672 inject_rsc_action(pcmk__output_t *out, va_list args)
1673 {
1674 const char *rsc = va_arg(args, const char *);
1675 const char *operation = va_arg(args, const char *);
1676 const char *node = va_arg(args, const char *);
1677 guint interval_ms = va_arg(args, guint);
1678
1679 if (out->is_quiet(out)) {
1680 return pcmk_rc_no_output;
1681 }
1682
1683 if (interval_ms) {
1684 out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1685 rsc, operation, interval_ms, node);
1686 } else {
1687 out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1688 rsc, operation, node);
1689 }
1690
1691 return pcmk_rc_ok;
1692 }
1693
1694 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *",
1695 "const char *", "guint")
1696 static int
1697 inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1698 {
1699 const char *rsc = va_arg(args, const char *);
1700 const char *operation = va_arg(args, const char *);
1701 const char *node = va_arg(args, const char *);
1702 guint interval_ms = va_arg(args, guint);
1703
1704 xmlNodePtr xml_node = NULL;
1705
1706 if (out->is_quiet(out)) {
1707 return pcmk_rc_no_output;
1708 }
1709
1710 xml_node = pcmk__output_create_xml_node(out, "rsc_action",
1711 "resource", rsc,
1712 "op", operation,
1713 "node", node,
1714 NULL);
1715
1716 if (interval_ms) {
1717 char *interval_s = pcmk__itoa(interval_ms);
1718
1719 crm_xml_add(xml_node, "interval", interval_s);
1720 free(interval_s);
1721 }
1722
1723 return pcmk_rc_ok;
1724 }
1725
1726 #define CHECK_RC(retcode, retval) \
1727 if (retval == pcmk_rc_ok) { \
1728 retcode = pcmk_rc_ok; \
1729 }
1730
1731 PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *",
1732 "enum pcmk_pacemakerd_state", "crm_exit_t",
1733 "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1734 "uint32_t", "const char *", "GList *", "GList *")
1735 int
1736 pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
1737 {
1738 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1739 enum pcmk_pacemakerd_state pcmkd_state =
1740 (enum pcmk_pacemakerd_state) va_arg(args, int);
1741 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1742 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1743 enum pcmk__fence_history fence_history = va_arg(args, int);
1744 uint32_t section_opts = va_arg(args, uint32_t);
1745 uint32_t show_opts = va_arg(args, uint32_t);
1746 const char *prefix = va_arg(args, const char *);
1747 GList *unames = va_arg(args, GList *);
1748 GList *resources = va_arg(args, GList *);
1749
1750 int rc = pcmk_rc_no_output;
1751 bool already_printed_failure = false;
1752
1753 CHECK_RC(rc, out->message(out, "cluster-summary", data_set, pcmkd_state,
1754 section_opts, show_opts));
1755
1756 if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1757 CHECK_RC(rc, out->message(out, "node-list", data_set->nodes, unames,
1758 resources, show_opts, rc == pcmk_rc_ok));
1759 }
1760
1761
1762 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1763 CHECK_RC(rc, out->message(out, "resource-list", data_set, show_opts,
1764 true, unames, resources, rc == pcmk_rc_ok));
1765 }
1766
1767
1768 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1769 CHECK_RC(rc, out->message(out, "node-attribute-list", data_set,
1770 show_opts, rc == pcmk_rc_ok, unames, resources));
1771 }
1772
1773
1774
1775
1776 if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1777 CHECK_RC(rc, out->message(out, "node-summary", data_set, unames,
1778 resources, section_opts, show_opts, rc == pcmk_rc_ok));
1779 }
1780
1781
1782 if (pcmk_is_set(section_opts, pcmk_section_failures)
1783 && xml_has_children(data_set->failed)) {
1784
1785 CHECK_RC(rc, out->message(out, "failed-action-list", data_set, unames,
1786 resources, show_opts, rc == pcmk_rc_ok));
1787 }
1788
1789
1790 if (pcmk_is_set(section_opts, pcmk_section_fence_failed) &&
1791 fence_history != pcmk__fence_history_none) {
1792 if (history_rc == 0) {
1793 stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_eq,
1794 GINT_TO_POINTER(st_failed));
1795
1796 if (hp) {
1797 CHECK_RC(rc, out->message(out, "failed-fencing-list",
1798 stonith_history, unames, section_opts,
1799 show_opts, rc == pcmk_rc_ok));
1800 }
1801 } else {
1802 PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1803 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1804 out->list_item(out, NULL, "Failed to get fencing history: %s",
1805 crm_exit_str(history_rc));
1806 out->end_list(out);
1807
1808 already_printed_failure = true;
1809 }
1810 }
1811
1812
1813 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1814 CHECK_RC(rc, out->message(out, "ticket-list", data_set, rc == pcmk_rc_ok));
1815 }
1816
1817
1818 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1819 CHECK_RC(rc, out->message(out, "ban-list", data_set, prefix, resources,
1820 show_opts, rc == pcmk_rc_ok));
1821 }
1822
1823
1824 if (pcmk_any_flags_set(section_opts, pcmk_section_fencing_all) &&
1825 fence_history != pcmk__fence_history_none) {
1826 if (history_rc != 0) {
1827 if (!already_printed_failure) {
1828 PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1829 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1830 out->list_item(out, NULL, "Failed to get fencing history: %s",
1831 crm_exit_str(history_rc));
1832 out->end_list(out);
1833 }
1834 } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1835 stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_neq,
1836 GINT_TO_POINTER(st_failed));
1837
1838 if (hp) {
1839 CHECK_RC(rc, out->message(out, "fencing-list", hp, unames,
1840 section_opts, show_opts,
1841 rc == pcmk_rc_ok));
1842 }
1843 } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1844 stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_pending, NULL);
1845
1846 if (hp) {
1847 CHECK_RC(rc, out->message(out, "pending-fencing-list", hp,
1848 unames, section_opts, show_opts,
1849 rc == pcmk_rc_ok));
1850 }
1851 }
1852 }
1853
1854 return rc;
1855 }
1856
1857 PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *",
1858 "enum pcmk_pacemakerd_state", "crm_exit_t",
1859 "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1860 "uint32_t", "const char *", "GList *", "GList *")
1861 static int
1862 cluster_status_xml(pcmk__output_t *out, va_list args)
1863 {
1864 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1865 enum pcmk_pacemakerd_state pcmkd_state =
1866 (enum pcmk_pacemakerd_state) va_arg(args, int);
1867 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1868 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1869 enum pcmk__fence_history fence_history = va_arg(args, int);
1870 uint32_t section_opts = va_arg(args, uint32_t);
1871 uint32_t show_opts = va_arg(args, uint32_t);
1872 const char *prefix = va_arg(args, const char *);
1873 GList *unames = va_arg(args, GList *);
1874 GList *resources = va_arg(args, GList *);
1875
1876 out->message(out, "cluster-summary", data_set, pcmkd_state, section_opts,
1877 show_opts);
1878
1879
1880 if (pcmk_is_set(section_opts, pcmk_section_nodes)) {
1881 out->message(out, "node-list", data_set->nodes, unames, resources,
1882 show_opts, false);
1883 }
1884
1885
1886 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1887
1888 uint32_t full_show_opts = show_opts & ~pcmk_show_brief;
1889
1890 out->message(out, "resource-list", data_set, full_show_opts,
1891 false, unames, resources, false);
1892 }
1893
1894
1895 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1896 out->message(out, "node-attribute-list", data_set, show_opts, false,
1897 unames, resources);
1898 }
1899
1900
1901
1902
1903 if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1904 out->message(out, "node-summary", data_set, unames,
1905 resources, section_opts, show_opts, false);
1906 }
1907
1908
1909 if (pcmk_is_set(section_opts, pcmk_section_failures)
1910 && xml_has_children(data_set->failed)) {
1911
1912 out->message(out, "failed-action-list", data_set, unames, resources,
1913 show_opts, false);
1914 }
1915
1916
1917 if (pcmk_is_set(section_opts, pcmk_section_fencing_all) &&
1918 fence_history != pcmk__fence_history_none) {
1919 out->message(out, "full-fencing-list", history_rc, stonith_history,
1920 unames, section_opts, show_opts, false);
1921 }
1922
1923
1924 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1925 out->message(out, "ticket-list", data_set, false);
1926 }
1927
1928
1929 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1930 out->message(out, "ban-list", data_set, prefix, resources, show_opts,
1931 false);
1932 }
1933
1934 return pcmk_rc_ok;
1935 }
1936
1937 PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *",
1938 "enum pcmk_pacemakerd_state", "crm_exit_t",
1939 "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1940 "uint32_t", "const char *", "GList *", "GList *")
1941 static int
1942 cluster_status_html(pcmk__output_t *out, va_list args)
1943 {
1944 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1945 enum pcmk_pacemakerd_state pcmkd_state =
1946 (enum pcmk_pacemakerd_state) va_arg(args, int);
1947 crm_exit_t history_rc = va_arg(args, crm_exit_t);
1948 stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1949 enum pcmk__fence_history fence_history = va_arg(args, int);
1950 uint32_t section_opts = va_arg(args, uint32_t);
1951 uint32_t show_opts = va_arg(args, uint32_t);
1952 const char *prefix = va_arg(args, const char *);
1953 GList *unames = va_arg(args, GList *);
1954 GList *resources = va_arg(args, GList *);
1955 bool already_printed_failure = false;
1956
1957 out->message(out, "cluster-summary", data_set, pcmkd_state, section_opts,
1958 show_opts);
1959
1960
1961 if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1962 out->message(out, "node-list", data_set->nodes, unames, resources,
1963 show_opts, false);
1964 }
1965
1966
1967 if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1968 out->message(out, "resource-list", data_set, show_opts, true, unames,
1969 resources, false);
1970 }
1971
1972
1973 if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1974 out->message(out, "node-attribute-list", data_set, show_opts, false,
1975 unames, resources);
1976 }
1977
1978
1979
1980
1981 if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1982 out->message(out, "node-summary", data_set, unames,
1983 resources, section_opts, show_opts, false);
1984 }
1985
1986
1987 if (pcmk_is_set(section_opts, pcmk_section_failures)
1988 && xml_has_children(data_set->failed)) {
1989
1990 out->message(out, "failed-action-list", data_set, unames, resources,
1991 show_opts, false);
1992 }
1993
1994
1995 if (pcmk_is_set(section_opts, pcmk_section_fence_failed) &&
1996 fence_history != pcmk__fence_history_none) {
1997 if (history_rc == 0) {
1998 stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_eq,
1999 GINT_TO_POINTER(st_failed));
2000
2001 if (hp) {
2002 out->message(out, "failed-fencing-list", stonith_history, unames,
2003 section_opts, show_opts, false);
2004 }
2005 } else {
2006 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
2007 out->list_item(out, NULL, "Failed to get fencing history: %s",
2008 crm_exit_str(history_rc));
2009 out->end_list(out);
2010 }
2011 }
2012
2013
2014 if (pcmk_any_flags_set(section_opts, pcmk_section_fencing_all) &&
2015 fence_history != pcmk__fence_history_none) {
2016 if (history_rc != 0) {
2017 if (!already_printed_failure) {
2018 out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
2019 out->list_item(out, NULL, "Failed to get fencing history: %s",
2020 crm_exit_str(history_rc));
2021 out->end_list(out);
2022 }
2023 } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
2024 stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_neq,
2025 GINT_TO_POINTER(st_failed));
2026
2027 if (hp) {
2028 out->message(out, "fencing-list", hp, unames, section_opts,
2029 show_opts, false);
2030 }
2031 } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
2032 stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_pending, NULL);
2033
2034 if (hp) {
2035 out->message(out, "pending-fencing-list", hp, unames,
2036 section_opts, show_opts, false);
2037 }
2038 }
2039 }
2040
2041
2042 if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
2043 out->message(out, "ticket-list", data_set, false);
2044 }
2045
2046
2047 if (pcmk_is_set(section_opts, pcmk_section_bans)) {
2048 out->message(out, "ban-list", data_set, prefix, resources, show_opts,
2049 false);
2050 }
2051
2052 return pcmk_rc_ok;
2053 }
2054
2055 PCMK__OUTPUT_ARGS("attribute", "const char *", "const char *", "const char *",
2056 "const char *", "const char *")
2057 static int
2058 attribute_default(pcmk__output_t *out, va_list args)
2059 {
2060 const char *scope = va_arg(args, const char *);
2061 const char *instance = va_arg(args, const char *);
2062 const char *name = va_arg(args, const char *);
2063 const char *value = va_arg(args, const char *);
2064 const char *host = va_arg(args, const char *);
2065
2066 GString *s = g_string_sized_new(50);
2067
2068 if (!pcmk__str_empty(scope)) {
2069 pcmk__g_strcat(s, "scope=\"", scope, "\" ", NULL);
2070 }
2071
2072 if (!pcmk__str_empty(instance)) {
2073 pcmk__g_strcat(s, "id=\"", instance, "\" ", NULL);
2074 }
2075
2076 pcmk__g_strcat(s, "name=\"", pcmk__s(name, ""), "\" ", NULL);
2077
2078 if (!pcmk__str_empty(host)) {
2079 pcmk__g_strcat(s, "host=\"", host, "\" ", NULL);
2080 }
2081
2082 pcmk__g_strcat(s, "value=\"", pcmk__s(value, ""), "\"", NULL);
2083
2084 out->info(out, "%s", s->str);
2085 g_string_free(s, TRUE);
2086
2087 return pcmk_rc_ok;
2088 }
2089
2090 PCMK__OUTPUT_ARGS("attribute", "const char *", "const char *", "const char *",
2091 "const char *", "const char *")
2092 static int
2093 attribute_xml(pcmk__output_t *out, va_list args)
2094 {
2095 const char *scope = va_arg(args, const char *);
2096 const char *instance = va_arg(args, const char *);
2097 const char *name = va_arg(args, const char *);
2098 const char *value = va_arg(args, const char *);
2099 const char *host = va_arg(args, const char *);
2100
2101 xmlNodePtr node = NULL;
2102
2103 node = pcmk__output_create_xml_node(out, "attribute",
2104 "name", name,
2105 "value", value ? value : "",
2106 NULL);
2107
2108 if (!pcmk__str_empty(scope)) {
2109 crm_xml_add(node, "scope", scope);
2110 }
2111
2112 if (!pcmk__str_empty(instance)) {
2113 crm_xml_add(node, "id", instance);
2114 }
2115
2116 if (!pcmk__str_empty(host)) {
2117 crm_xml_add(node, "host", host);
2118 }
2119
2120 return pcmk_rc_ok;
2121 }
2122
2123 PCMK__OUTPUT_ARGS("rule-check", "const char *", "int", "const char *")
2124 static int
2125 rule_check_default(pcmk__output_t *out, va_list args)
2126 {
2127 const char *rule_id = va_arg(args, const char *);
2128 int result = va_arg(args, int);
2129 const char *error = va_arg(args, const char *);
2130
2131 switch (result) {
2132 case pcmk_rc_within_range:
2133 return out->info(out, "Rule %s is still in effect", rule_id);
2134 case pcmk_rc_ok:
2135 return out->info(out, "Rule %s satisfies conditions", rule_id);
2136 case pcmk_rc_after_range:
2137 return out->info(out, "Rule %s is expired", rule_id);
2138 case pcmk_rc_before_range:
2139 return out->info(out, "Rule %s has not yet taken effect", rule_id);
2140 case pcmk_rc_op_unsatisfied:
2141 return out->info(out, "Rule %s does not satisfy conditions",
2142 rule_id);
2143 default:
2144 out->err(out,
2145 "Could not determine whether rule %s is in effect: %s",
2146 rule_id, ((error != NULL)? error : "unexpected error"));
2147 return pcmk_rc_ok;
2148 }
2149 }
2150
2151 PCMK__OUTPUT_ARGS("rule-check", "const char *", "int", "const char *")
2152 static int
2153 rule_check_xml(pcmk__output_t *out, va_list args)
2154 {
2155 const char *rule_id = va_arg(args, const char *);
2156 int result = va_arg(args, int);
2157 const char *error = va_arg(args, const char *);
2158
2159 char *rc_str = pcmk__itoa(pcmk_rc2exitc(result));
2160
2161 pcmk__output_create_xml_node(out, "rule-check",
2162 "rule-id", rule_id,
2163 "rc", rc_str,
2164 NULL);
2165 free(rc_str);
2166
2167 switch (result) {
2168 case pcmk_rc_within_range:
2169 case pcmk_rc_ok:
2170 case pcmk_rc_after_range:
2171 case pcmk_rc_before_range:
2172 case pcmk_rc_op_unsatisfied:
2173 return pcmk_rc_ok;
2174 default:
2175 out->err(out,
2176 "Could not determine whether rule %s is in effect: %s",
2177 rule_id, ((error != NULL)? error : "unexpected error"));
2178 return pcmk_rc_ok;
2179 }
2180 }
2181
2182 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2183 static int
2184 result_code_none(pcmk__output_t *out, va_list args)
2185 {
2186 return pcmk_rc_no_output;
2187 }
2188
2189 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2190 static int
2191 result_code_text(pcmk__output_t *out, va_list args)
2192 {
2193 int code = va_arg(args, int);
2194 const char *name = va_arg(args, const char *);
2195 const char *desc = va_arg(args, const char *);
2196
2197 static int code_width = 0;
2198
2199 if (out->is_quiet(out)) {
2200
2201
2202
2203
2204 if ((name != NULL) && (desc != NULL)) {
2205 pcmk__formatted_printf(out, "%s - %s\n", name, desc);
2206
2207 } else if ((name != NULL) || (desc != NULL)) {
2208 pcmk__formatted_printf(out, "%s\n", ((name != NULL)? name : desc));
2209 }
2210 return pcmk_rc_ok;
2211 }
2212
2213
2214
2215
2216
2217 if (code_width == 0) {
2218 long long most_negative = pcmk_rc_error - (long long) pcmk__n_rc + 1;
2219 code_width = (int) snprintf(NULL, 0, "%lld", most_negative);
2220 }
2221
2222 if ((name != NULL) && (desc != NULL)) {
2223 static int name_width = 0;
2224
2225 if (name_width == 0) {
2226
2227 for (int lpc = 0; lpc < pcmk__n_rc; lpc++) {
2228 int len = (int) strlen(pcmk_rc_name(pcmk_rc_error - lpc));
2229 name_width = QB_MAX(name_width, len);
2230 }
2231 }
2232 return out->info(out, "% *d: %-*s %s", code_width, code, name_width,
2233 name, desc);
2234 }
2235
2236 if ((name != NULL) || (desc != NULL)) {
2237 return out->info(out, "% *d: %s", code_width, code,
2238 ((name != NULL)? name : desc));
2239 }
2240
2241 return out->info(out, "% *d", code_width, code);
2242 }
2243
2244 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2245 static int
2246 result_code_xml(pcmk__output_t *out, va_list args)
2247 {
2248 int code = va_arg(args, int);
2249 const char *name = va_arg(args, const char *);
2250 const char *desc = va_arg(args, const char *);
2251
2252 char *code_str = pcmk__itoa(code);
2253
2254 pcmk__output_create_xml_node(out, "result-code",
2255 "code", code_str,
2256 XML_ATTR_NAME, name,
2257 XML_ATTR_DESC, desc,
2258 NULL);
2259 free(code_str);
2260 return pcmk_rc_ok;
2261 }
2262
2263 static pcmk__message_entry_t fmt_functions[] = {
2264 { "attribute", "default", attribute_default },
2265 { "attribute", "xml", attribute_xml },
2266 { "cluster-status", "default", pcmk__cluster_status_text },
2267 { "cluster-status", "html", cluster_status_html },
2268 { "cluster-status", "xml", cluster_status_xml },
2269 { "crmadmin-node", "default", crmadmin_node },
2270 { "crmadmin-node", "text", crmadmin_node_text },
2271 { "crmadmin-node", "xml", crmadmin_node_xml },
2272 { "dc", "default", dc },
2273 { "dc", "text", dc_text },
2274 { "dc", "xml", dc_xml },
2275 { "digests", "default", digests_text },
2276 { "digests", "xml", digests_xml },
2277 { "health", "default", health },
2278 { "health", "text", health_text },
2279 { "health", "xml", health_xml },
2280 { "inject-attr", "default", inject_attr },
2281 { "inject-attr", "xml", inject_attr_xml },
2282 { "inject-cluster-action", "default", inject_cluster_action },
2283 { "inject-cluster-action", "xml", inject_cluster_action_xml },
2284 { "inject-fencing-action", "default", inject_fencing_action },
2285 { "inject-fencing-action", "xml", inject_fencing_action_xml },
2286 { "inject-modify-config", "default", inject_modify_config },
2287 { "inject-modify-config", "xml", inject_modify_config_xml },
2288 { "inject-modify-node", "default", inject_modify_node },
2289 { "inject-modify-node", "xml", inject_modify_node_xml },
2290 { "inject-modify-ticket", "default", inject_modify_ticket },
2291 { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
2292 { "inject-pseudo-action", "default", inject_pseudo_action },
2293 { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
2294 { "inject-rsc-action", "default", inject_rsc_action },
2295 { "inject-rsc-action", "xml", inject_rsc_action_xml },
2296 { "inject-spec", "default", inject_spec },
2297 { "inject-spec", "xml", inject_spec_xml },
2298 { "locations-list", "default", locations_list },
2299 { "locations-list", "xml", locations_list_xml },
2300 { "node-action", "default", node_action },
2301 { "node-action", "xml", node_action_xml },
2302 { "node-info", "default", node_info_default },
2303 { "node-info", "xml", node_info_xml },
2304 { "pacemakerd-health", "default", pacemakerd_health },
2305 { "pacemakerd-health", "html", pacemakerd_health_html },
2306 { "pacemakerd-health", "text", pacemakerd_health_text },
2307 { "pacemakerd-health", "xml", pacemakerd_health_xml },
2308 { "profile", "default", profile_default, },
2309 { "profile", "xml", profile_xml },
2310 { "result-code", "none", result_code_none },
2311 { "result-code", "text", result_code_text },
2312 { "result-code", "xml", result_code_xml },
2313 { "rsc-action", "default", rsc_action_default },
2314 { "rsc-action-item", "default", rsc_action_item },
2315 { "rsc-action-item", "xml", rsc_action_item_xml },
2316 { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
2317 { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
2318 { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
2319 { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
2320 { "rule-check", "default", rule_check_default },
2321 { "rule-check", "xml", rule_check_xml },
2322 { "locations-and-colocations", "default", locations_and_colocations },
2323 { "locations-and-colocations", "xml", locations_and_colocations_xml },
2324
2325 { NULL, NULL, NULL }
2326 };
2327
2328 void
2329 pcmk__register_lib_messages(pcmk__output_t *out) {
2330 pcmk__register_messages(out, fmt_functions);
2331 }