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