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