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