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