This source file includes following definitions.
- time_t_string
- state_str
- stonith__history_description
- 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
- stonith__register_messages
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <stdarg.h>
12 #include <stdint.h>
13
14 #include <crm/stonith-ng.h>
15 #include <crm/msg_xml.h>
16 #include <crm/common/iso8601.h>
17 #include <crm/common/util.h>
18 #include <crm/common/xml.h>
19 #include <crm/common/output.h>
20 #include <crm/common/output_internal.h>
21 #include <crm/common/xml_internal.h>
22 #include <crm/fencing/internal.h>
23 #include <crm/pengine/internal.h>
24
25 static char *
26 time_t_string(time_t when) {
27 crm_time_t *crm_when = crm_time_new(NULL);
28 char *buf = NULL;
29
30 crm_time_set_timet(crm_when, &when);
31 buf = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
32 crm_time_free(crm_when);
33 return buf;
34 }
35
36
37
38
39
40
41
42
43
44
45
46 static const char *
47 state_str(stonith_history_t *history)
48 {
49 switch (history->state) {
50 case st_failed: return "failed";
51 case st_done: return "successful";
52 default: return "pending";
53 }
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 gchar *
74 stonith__history_description(stonith_history_t *history, bool full_history,
75 const char *later_succeeded, uint32_t show_opts)
76 {
77 GString *str = g_string_sized_new(256);
78 char *completed_time = NULL;
79
80 if ((history->state == st_failed) || (history->state == st_done)) {
81 completed_time = time_t_string(history->completed);
82 }
83
84 pcmk__g_strcat(str,
85 stonith_action_str(history->action), " of ", history->target,
86 NULL);
87
88 if (!pcmk_is_set(show_opts, pcmk_show_failed_detail)) {
89
90 if (((history->state == st_failed) || (history->state == st_done))
91 && (history->delegate != NULL)) {
92
93 pcmk__g_strcat(str, " by ", history->delegate, NULL);
94 }
95 pcmk__g_strcat(str, " for ", history->client, "@", history->origin,
96 NULL);
97 if (!full_history) {
98 g_string_append(str, " last");
99 }
100 }
101
102 pcmk__add_word(&str, 0, state_str(history));
103
104
105 if ((history->state == st_failed) && (history->exit_reason != NULL)) {
106 pcmk__g_strcat(str, " (", history->exit_reason, ")", NULL);
107 }
108
109 if (pcmk_is_set(show_opts, pcmk_show_failed_detail)) {
110
111 g_string_append(str, ": ");
112
113
114 if (((history->state == st_failed) || (history->state == st_done))
115 && (history->delegate != NULL)) {
116
117 pcmk__g_strcat(str, "delegate=", history->delegate, ", ", NULL);
118 }
119
120
121 pcmk__g_strcat(str,
122 "client=", history->client, ", origin=", history->origin,
123 NULL);
124
125
126 if (completed_time != NULL) {
127 if (full_history) {
128 g_string_append(str, ", completed");
129 } else if (history->state == st_failed) {
130 g_string_append(str, ", last-failed");
131 } else {
132 g_string_append(str, ", last-successful");
133 }
134 pcmk__g_strcat(str, "='", completed_time, "'", NULL);
135 }
136 } else {
137 if (completed_time != NULL) {
138 pcmk__g_strcat(str, " at ", completed_time, NULL);
139 }
140 }
141
142 if ((history->state == st_failed) && (later_succeeded != NULL)) {
143 pcmk__g_strcat(str,
144 " (a later attempt from ", later_succeeded,
145 " succeeded)", NULL);
146 }
147
148 free(completed_time);
149 return g_string_free(str, FALSE);
150 }
151
152 PCMK__OUTPUT_ARGS("failed-fencing-list", "stonith_history_t *", "GList *",
153 "uint32_t", "uint32_t", "bool")
154 static int
155 failed_history(pcmk__output_t *out, va_list args)
156 {
157 stonith_history_t *history = va_arg(args, stonith_history_t *);
158 GList *only_node = va_arg(args, GList *);
159 uint32_t section_opts = va_arg(args, uint32_t);
160 uint32_t show_opts = va_arg(args, uint32_t);
161 bool print_spacer = va_arg(args, int);
162
163 int rc = pcmk_rc_no_output;
164
165 for (stonith_history_t *hp = history; hp; hp = hp->next) {
166 if (hp->state != st_failed) {
167 continue;
168 }
169
170 if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
171 continue;
172 }
173
174 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Failed Fencing Actions");
175 out->message(out, "stonith-event", hp,
176 pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
177 false, stonith__later_succeeded(hp, history), show_opts);
178 out->increment_list(out);
179 }
180
181 PCMK__OUTPUT_LIST_FOOTER(out, rc);
182 return rc;
183 }
184
185 PCMK__OUTPUT_ARGS("fencing-list", "stonith_history_t *", "GList *", "uint32_t",
186 "uint32_t", "bool")
187 static int
188 stonith_history(pcmk__output_t *out, va_list args)
189 {
190 stonith_history_t *history = va_arg(args, stonith_history_t *);
191 GList *only_node = va_arg(args, GList *);
192 uint32_t section_opts = va_arg(args, uint32_t);
193 uint32_t show_opts = va_arg(args, uint32_t);
194 bool print_spacer = va_arg(args, int);
195
196 int rc = pcmk_rc_no_output;
197
198 for (stonith_history_t *hp = history; hp; hp = hp->next) {
199 if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
200 continue;
201 }
202
203 if (hp->state != st_failed) {
204 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
205 out->message(out, "stonith-event", hp,
206 pcmk_all_flags_set(section_opts,
207 pcmk_section_fencing_all),
208 false, stonith__later_succeeded(hp, history), show_opts);
209 out->increment_list(out);
210 }
211 }
212
213 PCMK__OUTPUT_LIST_FOOTER(out, rc);
214 return rc;
215 }
216
217 PCMK__OUTPUT_ARGS("full-fencing-list", "crm_exit_t", "stonith_history_t *",
218 "GList *", "uint32_t", "uint32_t", "bool")
219 static int
220 full_history(pcmk__output_t *out, va_list args)
221 {
222 crm_exit_t history_rc G_GNUC_UNUSED = va_arg(args, crm_exit_t);
223 stonith_history_t *history = va_arg(args, stonith_history_t *);
224 GList *only_node = va_arg(args, GList *);
225 uint32_t section_opts = va_arg(args, uint32_t);
226 uint32_t show_opts = va_arg(args, uint32_t);
227 bool print_spacer = va_arg(args, int);
228
229 int rc = pcmk_rc_no_output;
230
231 for (stonith_history_t *hp = history; hp; hp = hp->next) {
232 if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
233 continue;
234 }
235
236 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
237 out->message(out, "stonith-event", hp,
238 pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
239 false, stonith__later_succeeded(hp, history), show_opts);
240 out->increment_list(out);
241 }
242
243 PCMK__OUTPUT_LIST_FOOTER(out, rc);
244 return rc;
245 }
246
247 PCMK__OUTPUT_ARGS("full-fencing-list", "crm_exit_t", "stonith_history_t *",
248 "GList *", "uint32_t", "uint32_t", "bool")
249 static int
250 full_history_xml(pcmk__output_t *out, va_list args)
251 {
252 crm_exit_t history_rc = va_arg(args, crm_exit_t);
253 stonith_history_t *history = va_arg(args, stonith_history_t *);
254 GList *only_node = va_arg(args, GList *);
255 uint32_t section_opts = va_arg(args, uint32_t);
256 uint32_t show_opts = va_arg(args, uint32_t);
257 bool print_spacer G_GNUC_UNUSED = va_arg(args, int);
258
259 int rc = pcmk_rc_no_output;
260
261 if (history_rc == 0) {
262 for (stonith_history_t *hp = history; hp; hp = hp->next) {
263 if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
264 continue;
265 }
266
267 PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Fencing History");
268 out->message(out, "stonith-event", hp,
269 pcmk_all_flags_set(section_opts,
270 pcmk_section_fencing_all),
271 false, stonith__later_succeeded(hp, history), show_opts);
272 out->increment_list(out);
273 }
274
275 PCMK__OUTPUT_LIST_FOOTER(out, rc);
276 } else {
277 char *rc_s = pcmk__itoa(history_rc);
278
279 pcmk__output_create_xml_node(out, "fence_history",
280 "status", rc_s,
281 NULL);
282 free(rc_s);
283
284 rc = pcmk_rc_ok;
285 }
286
287 return rc;
288 }
289
290 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
291 static int
292 last_fenced_html(pcmk__output_t *out, va_list args) {
293 const char *target = va_arg(args, const char *);
294 time_t when = va_arg(args, time_t);
295
296 if (when) {
297 char *buf = crm_strdup_printf("Node %s last fenced at: %s", target, ctime(&when));
298 pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
299 free(buf);
300 return pcmk_rc_ok;
301 } else {
302 return pcmk_rc_no_output;
303 }
304 }
305
306 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
307 static int
308 last_fenced_text(pcmk__output_t *out, va_list args) {
309 const char *target = va_arg(args, const char *);
310 time_t when = va_arg(args, time_t);
311
312 if (when) {
313 pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
314 } else {
315 pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
316 }
317
318 return pcmk_rc_ok;
319 }
320
321 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
322 static int
323 last_fenced_xml(pcmk__output_t *out, va_list args) {
324 const char *target = va_arg(args, const char *);
325 time_t when = va_arg(args, time_t);
326
327 if (when) {
328 char *buf = time_t_string(when);
329
330 pcmk__output_create_xml_node(out, "last-fenced",
331 "target", target,
332 "when", buf,
333 NULL);
334
335 free(buf);
336 return pcmk_rc_ok;
337 } else {
338 return pcmk_rc_no_output;
339 }
340 }
341
342 PCMK__OUTPUT_ARGS("pending-fencing-list", "stonith_history_t *", "GList *",
343 "uint32_t", "uint32_t", "bool")
344 static int
345 pending_actions(pcmk__output_t *out, va_list args)
346 {
347 stonith_history_t *history = va_arg(args, stonith_history_t *);
348 GList *only_node = va_arg(args, GList *);
349 uint32_t section_opts = va_arg(args, uint32_t);
350 uint32_t show_opts = va_arg(args, uint32_t);
351 bool print_spacer = va_arg(args, int);
352
353 int rc = pcmk_rc_no_output;
354
355 for (stonith_history_t *hp = history; hp; hp = hp->next) {
356 if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
357 continue;
358 }
359
360
361 if ((hp->state == st_failed) || (hp->state == st_done)) {
362 break;
363 }
364
365 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Pending Fencing Actions");
366 out->message(out, "stonith-event", hp,
367 pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
368 false, stonith__later_succeeded(hp, history), show_opts);
369 out->increment_list(out);
370 }
371
372 PCMK__OUTPUT_LIST_FOOTER(out, rc);
373 return rc;
374 }
375
376 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "bool", "bool",
377 "const char *", "uint32_t")
378 static int
379 stonith_event_html(pcmk__output_t *out, va_list args)
380 {
381 stonith_history_t *event = va_arg(args, stonith_history_t *);
382 bool full_history = va_arg(args, int);
383 bool completed_only G_GNUC_UNUSED = va_arg(args, int);
384 const char *succeeded = va_arg(args, const char *);
385 uint32_t show_opts = va_arg(args, uint32_t);
386
387 gchar *desc = stonith__history_description(event, full_history, succeeded,
388 show_opts);
389
390 switch(event->state) {
391 case st_done:
392 out->list_item(out, "successful-stonith-event", "%s", desc);
393 break;
394
395 case st_failed:
396 out->list_item(out, "failed-stonith-event", "%s", desc);
397 break;
398
399 default:
400 out->list_item(out, "pending-stonith-event", "%s", desc);
401 break;
402 }
403 g_free(desc);
404 return pcmk_rc_ok;
405 }
406
407 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "bool", "bool",
408 "const char *", "uint32_t")
409 static int
410 stonith_event_text(pcmk__output_t *out, va_list args)
411 {
412 stonith_history_t *event = va_arg(args, stonith_history_t *);
413 bool full_history = va_arg(args, int);
414 bool completed_only = va_arg(args, int);
415 const char *succeeded = va_arg(args, const char *);
416 uint32_t show_opts = va_arg(args, uint32_t);
417
418 if (completed_only) {
419 pcmk__formatted_printf(out, "%lld\n", (long long) event->completed);
420 } else {
421 gchar *desc = stonith__history_description(event, full_history, succeeded,
422 show_opts);
423
424 pcmk__indented_printf(out, "%s\n", desc);
425 g_free(desc);
426 }
427
428 return pcmk_rc_ok;
429 }
430
431 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "bool", "bool",
432 "const char *", "uint32_t")
433 static int
434 stonith_event_xml(pcmk__output_t *out, va_list args)
435 {
436 stonith_history_t *event = va_arg(args, stonith_history_t *);
437 bool full_history G_GNUC_UNUSED = va_arg(args, int);
438 bool completed_only G_GNUC_UNUSED = va_arg(args, int);
439 const char *succeeded G_GNUC_UNUSED = va_arg(args, const char *);
440 uint32_t show_opts G_GNUC_UNUSED = va_arg(args, uint32_t);
441
442 char *buf = NULL;
443
444 xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_event",
445 "action", event->action,
446 "target", event->target,
447 "client", event->client,
448 "origin", event->origin,
449 NULL);
450
451 switch (event->state) {
452 case st_failed:
453 pcmk__xe_set_props(node, "status", "failed",
454 XML_LRM_ATTR_EXIT_REASON, event->exit_reason,
455 NULL);
456 break;
457
458 case st_done:
459 crm_xml_add(node, "status", "success");
460 break;
461
462 default: {
463 char *state = pcmk__itoa(event->state);
464 pcmk__xe_set_props(node, "status", "pending",
465 "extended-status", state,
466 NULL);
467 free(state);
468 break;
469 }
470 }
471
472 if (event->delegate != NULL) {
473 crm_xml_add(node, "delegate", event->delegate);
474 }
475
476 if (event->state == st_failed || event->state == st_done) {
477 buf = time_t_string(event->completed);
478 crm_xml_add(node, "completed", buf);
479 free(buf);
480 }
481
482 return pcmk_rc_ok;
483 }
484
485 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
486 static int
487 validate_agent_html(pcmk__output_t *out, va_list args) {
488 const char *agent = va_arg(args, const char *);
489 const char *device = va_arg(args, const char *);
490 char *output = va_arg(args, char *);
491 char *error_output = va_arg(args, char *);
492 int rc = va_arg(args, int);
493
494 if (device) {
495 char *buf = crm_strdup_printf("Validation of %s on %s %s", agent, device,
496 rc ? "failed" : "succeeded");
497 pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
498 free(buf);
499 } else {
500 char *buf = crm_strdup_printf("Validation of %s %s", agent,
501 rc ? "failed" : "succeeded");
502 pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
503 free(buf);
504 }
505
506 out->subprocess_output(out, rc, output, error_output);
507 return rc;
508 }
509
510 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
511 static int
512 validate_agent_text(pcmk__output_t *out, va_list args) {
513 const char *agent = va_arg(args, const char *);
514 const char *device = va_arg(args, const char *);
515 char *output = va_arg(args, char *);
516 char *error_output = va_arg(args, char *);
517 int rc = va_arg(args, int);
518
519 if (device) {
520 pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
521 rc ? "failed" : "succeeded");
522 } else {
523 pcmk__indented_printf(out, "Validation of %s %s\n", agent,
524 rc ? "failed" : "succeeded");
525 }
526
527 out->subprocess_output(out, rc, output, error_output);
528 return rc;
529 }
530
531 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
532 static int
533 validate_agent_xml(pcmk__output_t *out, va_list args) {
534 const char *agent = va_arg(args, const char *);
535 const char *device = va_arg(args, const char *);
536 char *output = va_arg(args, char *);
537 char *error_output = va_arg(args, char *);
538 int rc = va_arg(args, int);
539
540 xmlNodePtr node = pcmk__output_create_xml_node(
541 out, "validate", "agent", agent, "valid", pcmk__btoa(rc == pcmk_ok),
542 NULL);
543
544 if (device != NULL) {
545 crm_xml_add(node, "device", device);
546 }
547
548 pcmk__output_xml_push_parent(out, node);
549 out->subprocess_output(out, rc, output, error_output);
550 pcmk__output_xml_pop_parent(out);
551
552 return rc;
553 }
554
555 static pcmk__message_entry_t fmt_functions[] = {
556 { "failed-fencing-list", "default", failed_history },
557 { "fencing-list", "default", stonith_history },
558 { "full-fencing-list", "default", full_history },
559 { "full-fencing-list", "xml", full_history_xml },
560 { "last-fenced", "html", last_fenced_html },
561 { "last-fenced", "log", last_fenced_text },
562 { "last-fenced", "text", last_fenced_text },
563 { "last-fenced", "xml", last_fenced_xml },
564 { "pending-fencing-list", "default", pending_actions },
565 { "stonith-event", "html", stonith_event_html },
566 { "stonith-event", "log", stonith_event_text },
567 { "stonith-event", "text", stonith_event_text },
568 { "stonith-event", "xml", stonith_event_xml },
569 { "validate", "html", validate_agent_html },
570 { "validate", "log", validate_agent_text },
571 { "validate", "text", validate_agent_text },
572 { "validate", "xml", validate_agent_xml },
573
574 { NULL, NULL, NULL }
575 };
576
577 void
578 stonith__register_messages(pcmk__output_t *out) {
579 pcmk__register_messages(out, fmt_functions);
580 }