pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
st_output.c
Go to the documentation of this file.
1/*
2 * Copyright 2019-2021 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11#include <stdarg.h>
12
13#include <crm/stonith-ng.h>
14#include <crm/common/iso8601.h>
15#include <crm/common/util.h>
16#include <crm/common/xml.h>
17#include <crm/common/output.h>
22
23static char *
24time_t_string(time_t when) {
25 crm_time_t *crm_when = crm_time_new(NULL);
26 char *buf = NULL;
27
28 crm_time_set_timet(crm_when, &when);
30 crm_time_free(crm_when);
31 return buf;
32}
33
34PCMK__OUTPUT_ARGS("failed-fencing-list", "stonith_history_t *", "GList *",
35 "unsigned int", "gboolean")
36int
37stonith__failed_history(pcmk__output_t *out, va_list args) {
38 stonith_history_t *history = va_arg(args, stonith_history_t *);
39 GList *only_node = va_arg(args, GList *);
40 unsigned int section_opts = va_arg(args, unsigned int);
41 gboolean print_spacer = va_arg(args, gboolean);
42
44
45 for (stonith_history_t *hp = history; hp; hp = hp->next) {
46 if (hp->state != st_failed) {
47 continue;
48 }
49
50 if (!pcmk__str_in_list(only_node, hp->target, pcmk__str_casei)) {
51 continue;
52 }
53
54 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Failed Fencing Actions");
55 out->message(out, "stonith-event", hp, pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
56 stonith__later_succeeded(hp, history));
57 out->increment_list(out);
58 }
59
61 return rc;
62}
63
64PCMK__OUTPUT_ARGS("fencing-list", "stonith_history_t *", "GList *", "unsigned int", "gboolean")
65int
66stonith__history(pcmk__output_t *out, va_list args) {
67 stonith_history_t *history = va_arg(args, stonith_history_t *);
68 GList *only_node = va_arg(args, GList *);
69 unsigned int section_opts = va_arg(args, unsigned int);
70 gboolean print_spacer = va_arg(args, gboolean);
71
73
74 for (stonith_history_t *hp = history; hp; hp = hp->next) {
75 if (!pcmk__str_in_list(only_node, hp->target, pcmk__str_casei)) {
76 continue;
77 }
78
79 if (hp->state != st_failed) {
80 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
81 out->message(out, "stonith-event", hp, pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
82 stonith__later_succeeded(hp, history));
83 out->increment_list(out);
84 }
85 }
86
88 return rc;
89}
90
91PCMK__OUTPUT_ARGS("full-fencing-list", "crm_exit_t", "stonith_history_t *", "GList *",
92 "unsigned int", "gboolean")
93int
94stonith__full_history(pcmk__output_t *out, va_list args) {
95 crm_exit_t history_rc G_GNUC_UNUSED = va_arg(args, crm_exit_t);
96 stonith_history_t *history = va_arg(args, stonith_history_t *);
97 GList *only_node = va_arg(args, GList *);
98 unsigned int section_opts = va_arg(args, unsigned int);
99 gboolean print_spacer = va_arg(args, gboolean);
100
101 int rc = pcmk_rc_no_output;
102
103 for (stonith_history_t *hp = history; hp; hp = hp->next) {
104 if (!pcmk__str_in_list(only_node, hp->target, pcmk__str_casei)) {
105 continue;
106 }
107
108 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
109 out->message(out, "stonith-event", hp, pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
110 stonith__later_succeeded(hp, history));
111 out->increment_list(out);
112 }
113
115 return rc;
116}
117
118PCMK__OUTPUT_ARGS("full-fencing-list", "crm_exit_t", "stonith_history_t *", "GList *",
119 "unsigned int", "gboolean")
120static int
121full_history_xml(pcmk__output_t *out, va_list args) {
122 crm_exit_t history_rc = va_arg(args, crm_exit_t);
123 stonith_history_t *history = va_arg(args, stonith_history_t *);
124 GList *only_node = va_arg(args, GList *);
125 unsigned int section_opts = va_arg(args, unsigned int);
126 gboolean print_spacer G_GNUC_UNUSED = va_arg(args, gboolean);
127
128 int rc = pcmk_rc_no_output;
129
130 if (history_rc == 0) {
131 for (stonith_history_t *hp = history; hp; hp = hp->next) {
132 if (!pcmk__str_in_list(only_node, hp->target, pcmk__str_casei)) {
133 continue;
134 }
135
136 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Fencing History");
137 out->message(out, "stonith-event", hp, pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
138 stonith__later_succeeded(hp, history));
139 out->increment_list(out);
140 }
141
143 } else {
144 char *rc_s = pcmk__itoa(history_rc);
145
146 pcmk__output_create_xml_node(out, "fence_history",
147 "status", rc_s,
148 NULL);
149 free(rc_s);
150
151 rc = pcmk_rc_ok;
152 }
153
154 return rc;
155}
156
157PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
158static int
159last_fenced_html(pcmk__output_t *out, va_list args) {
160 const char *target = va_arg(args, const char *);
161 time_t when = va_arg(args, time_t);
162
163 if (when) {
164 char *buf = crm_strdup_printf("Node %s last fenced at: %s", target, ctime(&when));
165 pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
166 free(buf);
167 return pcmk_rc_ok;
168 } else {
169 return pcmk_rc_no_output;
170 }
171}
172
173PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
174static int
175last_fenced_text(pcmk__output_t *out, va_list args) {
176 const char *target = va_arg(args, const char *);
177 time_t when = va_arg(args, time_t);
178
179 if (when) {
180 pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
181 } else {
182 pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
183 }
184
185 return pcmk_rc_ok;
186}
187
188PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
189static int
190last_fenced_xml(pcmk__output_t *out, va_list args) {
191 const char *target = va_arg(args, const char *);
192 time_t when = va_arg(args, time_t);
193
194 if (when) {
195 char *buf = time_t_string(when);
196
197 pcmk__output_create_xml_node(out, "last-fenced",
198 "target", target,
199 "when", buf,
200 NULL);
201
202 free(buf);
203 return pcmk_rc_ok;
204 } else {
205 return pcmk_rc_no_output;
206 }
207}
208
209PCMK__OUTPUT_ARGS("pending-fencing-list", "stonith_history_t *", "GList *",
210 "unsigned int", "gboolean")
211int
212stonith__pending_actions(pcmk__output_t *out, va_list args) {
213 stonith_history_t *history = va_arg(args, stonith_history_t *);
214 GList *only_node = va_arg(args, GList *);
215 unsigned int section_opts = va_arg(args, unsigned int);
216 gboolean print_spacer = va_arg(args, gboolean);
217
218 int rc = pcmk_rc_no_output;
219
220 for (stonith_history_t *hp = history; hp; hp = hp->next) {
221 if (!pcmk__str_in_list(only_node, hp->target, pcmk__str_casei)) {
222 continue;
223 }
224
225 /* Skip the rest of the history after we see a failed/done action */
226 if ((hp->state == st_failed) || (hp->state == st_done)) {
227 break;
228 }
229
230 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Pending Fencing Actions");
231 out->message(out, "stonith-event", hp, pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
232 stonith__later_succeeded(hp, history));
233 out->increment_list(out);
234 }
235
237 return rc;
238}
239
240PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "gboolean", "gboolean")
241static int
242stonith_event_html(pcmk__output_t *out, va_list args) {
243 stonith_history_t *event = va_arg(args, stonith_history_t *);
244 gboolean full_history = va_arg(args, gboolean);
245 gboolean later_succeeded = va_arg(args, gboolean);
246
247 switch(event->state) {
248 case st_done: {
249 char *completed_s = time_t_string(event->completed);
250
251 out->list_item(out, "successful-stonith-event",
252 "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'",
253 stonith_action_str(event->action), event->target,
254 event->delegate ? event->delegate : "",
255 event->client, event->origin,
256 full_history ? "completed" : "last-successful",
257 completed_s);
258 free(completed_s);
259 break;
260 }
261
262 case st_failed: {
263 char *failed_s = time_t_string(event->completed);
264
265 out->list_item(out, "failed-stonith-event",
266 "%s of %s failed : delegate=%s, client=%s, origin=%s, %s='%s' %s",
267 stonith_action_str(event->action), event->target,
268 event->delegate ? event->delegate : "",
269 event->client, event->origin,
270 full_history ? "completed" : "last-failed",
271 failed_s,
272 later_succeeded ? "(a later attempt succeeded)" : "");
273 free(failed_s);
274 break;
275 }
276
277 default:
278 out->list_item(out, "pending-stonith-event",
279 "%s of %s pending: client=%s, origin=%s",
280 stonith_action_str(event->action), event->target,
281 event->client, event->origin);
282 break;
283 }
284
285 return pcmk_rc_ok;
286}
287
288PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "gboolean", "gboolean")
289static int
290stonith_event_text(pcmk__output_t *out, va_list args) {
291 stonith_history_t *event = va_arg(args, stonith_history_t *);
292 gboolean full_history = va_arg(args, gboolean);
293 gboolean later_succeeded = va_arg(args, gboolean);
294
295 char *buf = time_t_string(event->completed);
296
297 switch (event->state) {
298 case st_failed:
299 pcmk__indented_printf(out, "%s of %s failed: delegate=%s, client=%s, origin=%s, %s='%s' %s\n",
300 stonith_action_str(event->action), event->target,
301 event->delegate ? event->delegate : "",
302 event->client, event->origin,
303 full_history ? "completed" : "last-failed", buf,
304 later_succeeded ? "(a later attempt succeeded)" : "");
305 break;
306
307 case st_done:
308 pcmk__indented_printf(out, "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'\n",
309 stonith_action_str(event->action), event->target,
310 event->delegate ? event->delegate : "",
311 event->client, event->origin,
312 full_history ? "completed" : "last-successful", buf);
313 break;
314
315 default:
316 pcmk__indented_printf(out, "%s of %s pending: client=%s, origin=%s\n",
317 stonith_action_str(event->action), event->target,
318 event->client, event->origin);
319 break;
320 }
321
322 free(buf);
323 return pcmk_rc_ok;
324}
325
326PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "gboolean", "gboolean")
327static int
328stonith_event_xml(pcmk__output_t *out, va_list args) {
329 stonith_history_t *event = va_arg(args, stonith_history_t *);
330 gboolean full_history G_GNUC_UNUSED = va_arg(args, gboolean);
331 gboolean later_succeeded G_GNUC_UNUSED = va_arg(args, gboolean);
332
333 char *buf = NULL;
334
335 xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_event",
336 "action", event->action,
337 "target", event->target,
338 "client", event->client,
339 "origin", event->origin,
340 NULL);
341
342 switch (event->state) {
343 case st_failed:
344 crm_xml_add(node, "status", "failed");
345 break;
346
347 case st_done:
348 crm_xml_add(node, "status", "success");
349 break;
350
351 default: {
352 char *state = pcmk__itoa(event->state);
353 pcmk__xe_set_props(node, "status", "pending",
354 "extended-status", state,
355 NULL);
356 free(state);
357 break;
358 }
359 }
360
361 if (event->delegate != NULL) {
362 crm_xml_add(node, "delegate", event->delegate);
363 }
364
365 if (event->state == st_failed || event->state == st_done) {
366 buf = time_t_string(event->completed);
367 crm_xml_add(node, "completed", buf);
368 free(buf);
369 }
370
371 return pcmk_rc_ok;
372}
373
374PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
375static int
376validate_agent_html(pcmk__output_t *out, va_list args) {
377 const char *agent = va_arg(args, const char *);
378 const char *device = va_arg(args, const char *);
379 char *output = va_arg(args, char *);
380 char *error_output = va_arg(args, char *);
381 int rc = va_arg(args, int);
382
383 if (device) {
384 char *buf = crm_strdup_printf("Validation of %s on %s %s", agent, device,
385 rc ? "failed" : "succeeded");
386 pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
387 free(buf);
388 } else {
389 char *buf = crm_strdup_printf("Validation of %s %s", agent,
390 rc ? "failed" : "succeeded");
391 pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
392 free(buf);
393 }
394
395 out->subprocess_output(out, rc, output, error_output);
396 return rc;
397}
398
399PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
400static int
401validate_agent_text(pcmk__output_t *out, va_list args) {
402 const char *agent = va_arg(args, const char *);
403 const char *device = va_arg(args, const char *);
404 char *output = va_arg(args, char *);
405 char *error_output = va_arg(args, char *);
406 int rc = va_arg(args, int);
407
408 if (device) {
409 pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
410 rc ? "failed" : "succeeded");
411 } else {
412 pcmk__indented_printf(out, "Validation of %s %s\n", agent,
413 rc ? "failed" : "succeeded");
414 }
415
416 out->subprocess_output(out, rc, output, error_output);
417 return rc;
418}
419
420PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
421static int
422validate_agent_xml(pcmk__output_t *out, va_list args) {
423 const char *agent = va_arg(args, const char *);
424 const char *device = va_arg(args, const char *);
425 char *output = va_arg(args, char *);
426 char *error_output = va_arg(args, char *);
427 int rc = va_arg(args, int);
428
429 xmlNodePtr node = pcmk__output_create_xml_node(out, "validate",
430 "agent", agent,
431 "valid", pcmk__btoa(rc),
432 NULL);
433
434 if (device != NULL) {
435 crm_xml_add(node, "device", device);
436 }
437
439 out->subprocess_output(out, rc, output, error_output);
441
442 return rc;
443}
444
445static pcmk__message_entry_t fmt_functions[] = {
446 { "failed-fencing-list", "default", stonith__failed_history },
447 { "fencing-list", "default", stonith__history },
448 { "full-fencing-list", "default", stonith__full_history },
449 { "full-fencing-list", "xml", full_history_xml },
450 { "last-fenced", "html", last_fenced_html },
451 { "last-fenced", "log", last_fenced_text },
452 { "last-fenced", "text", last_fenced_text },
453 { "last-fenced", "xml", last_fenced_xml },
454 { "pending-fencing-list", "default", stonith__pending_actions },
455 { "stonith-event", "html", stonith_event_html },
456 { "stonith-event", "log", stonith_event_text },
457 { "stonith-event", "text", stonith_event_text },
458 { "stonith-event", "xml", stonith_event_xml },
459 { "validate", "html", validate_agent_html },
460 { "validate", "log", validate_agent_text },
461 { "validate", "text", validate_agent_text },
462 { "validate", "xml", validate_agent_xml },
463
464 { NULL, NULL, NULL }
465};
466
467void
Utility functions.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int stonith__pending_actions(pcmk__output_t *out, va_list args)
gboolean stonith__later_succeeded(stonith_history_t *event, stonith_history_t *top_history)
Definition st_client.c:2529
int stonith__failed_history(pcmk__output_t *out, va_list args)
int stonith__full_history(pcmk__output_t *out, va_list args)
ISO_8601 Date handling.
#define crm_time_log_timeofday
Definition iso8601.h:67
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition iso8601.c:497
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:141
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition iso8601.c:1255
#define crm_time_log_with_timezone
Definition iso8601.h:68
#define crm_time_log_date
Definition iso8601.h:66
crm_time_t * crm_time_new(const char *string)
Definition iso8601.c:93
struct crm_time_s crm_time_t
Definition iso8601.h:32
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:324
Control output from tools.
#define pcmk_section_fencing_all
Definition output.h:45
Formatted output for pacemaker tools.
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition output_xml.c:511
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition output.c:145
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
void pcmk__indented_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition output_xml.c:465
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition output_xml.c:495
#define PCMK__OUTPUT_ARGS(ARGS...)
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
int rc
Definition pcmk_fence.c:35
const char * target
Definition pcmk_fence.c:29
@ pcmk_rc_no_output
Definition results.h:112
@ pcmk_rc_ok
Definition results.h:142
enum crm_exit_e crm_exit_t
int stonith__history(pcmk__output_t *out, va_list args)
Definition st_output.c:66
void stonith__register_messages(pcmk__output_t *out)
Definition st_output.c:468
Fencing aka. STONITH.
const char * stonith_action_str(const char *action)
Turn stonith action into a more readable string.
Definition st_client.c:2381
@ st_failed
Definition stonith-ng.h:77
@ st_done
Definition stonith-ng.h:75
@ pcmk__str_casei
gboolean pcmk__str_in_list(GList *lst, const gchar *s, uint32_t flags)
Definition strings.c:895
This structure contains everything that makes up a single output formatter.
struct stonith_history_s * next
Definition stonith-ng.h:112
Wrappers for and extensions to libxml2.
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition xml.c:2972