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