pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
st_output.c
Go to the documentation of this file.
1 /*
2  * Copyright 2019 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/output.h>
16 #include <crm/common/util.h>
17 #include <crm/common/xml.h>
18 #include <crm/fencing/internal.h>
19 #include <crm/pengine/internal.h>
20 
21 static char *
22 time_t_string(time_t when) {
23  crm_time_t *crm_when = crm_time_new(NULL);
24  char *buf = NULL;
25 
26  crm_time_set_timet(crm_when, &when);
28  crm_time_free(crm_when);
29  return buf;
30 }
31 
32 PCMK__OUTPUT_ARGS("failed-fencing-history", "struct stonith_history_t *", "GListPtr", "gboolean", "gboolean")
33 int
35  stonith_history_t *history = va_arg(args, stonith_history_t *);
36  GListPtr only_show = va_arg(args, GListPtr);
37  gboolean full_history = va_arg(args, gboolean);
38  gboolean print_spacer = va_arg(args, gboolean);
39 
40  int rc = pcmk_rc_no_output;
41 
42  for (stonith_history_t *hp = history; hp; hp = hp->next) {
43  if (hp->state != st_failed) {
44  continue;
45  }
46 
47  if (!pcmk__str_in_list(only_show, hp->target)) {
48  continue;
49  }
50 
51  if (rc == pcmk_rc_no_output) {
52  if (print_spacer) {
53  out->info(out, "%s", "");
54  }
55 
56  rc = pcmk_rc_ok;
57  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
58  }
59 
60  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
61  out->increment_list(out);
62  }
63 
64  if (rc == pcmk_rc_ok) {
65  out->end_list(out);
66  }
67 
68  return rc;
69 }
70 
71 PCMK__OUTPUT_ARGS("fencing-history", "struct stonith_history_t *", "GListPtr", "gboolean", "gboolean")
72 int
73 stonith__history(pcmk__output_t *out, va_list args) {
74  stonith_history_t *history = va_arg(args, stonith_history_t *);
75  GListPtr only_show = va_arg(args, GListPtr);
76  gboolean full_history = va_arg(args, gboolean);
77  gboolean print_spacer = va_arg(args, gboolean);
78 
79  int rc = pcmk_rc_no_output;
80 
81  for (stonith_history_t *hp = history; hp; hp = hp->next) {
82  if (!pcmk__str_in_list(only_show, hp->target)) {
83  continue;
84  }
85 
86  if (hp->state != st_failed) {
87  /* Print the header the first time we have an event to print out to
88  * prevent printing headers with empty sections underneath.
89  */
90  if (rc == pcmk_rc_no_output) {
91  /* Add a blank line between this section and the one before it. */
92  if (print_spacer) {
93  out->info(out, "%s", "");
94  }
95 
96  rc = pcmk_rc_ok;
97  out->begin_list(out, NULL, NULL, "Fencing History");
98  }
99 
100  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
101  out->increment_list(out);
102  }
103  }
104 
105  if (rc == pcmk_rc_ok) {
106  out->end_list(out);
107  }
108 
109  return rc;
110 }
111 
112 PCMK__OUTPUT_ARGS("full-fencing-history", "crm_exit_t", "struct stonith_history_t *", "GListPtr", "gboolean", "gboolean")
113 int
115  crm_exit_t history_rc G_GNUC_UNUSED = va_arg(args, crm_exit_t);
116  stonith_history_t *history = va_arg(args, stonith_history_t *);
117  GListPtr only_show = va_arg(args, GListPtr);
118  gboolean full_history = va_arg(args, gboolean);
119  gboolean print_spacer = va_arg(args, gboolean);
120 
121  int rc = pcmk_rc_no_output;
122 
123  for (stonith_history_t *hp = history; hp; hp = hp->next) {
124  if (!pcmk__str_in_list(only_show, hp->target)) {
125  continue;
126  }
127 
128  if (rc == pcmk_rc_no_output) {
129  /* Add a blank line between this section and the one before it. */
130  if (print_spacer) {
131  out->info(out, "%s", "");
132  }
133 
134  rc = pcmk_rc_ok;
135  out->begin_list(out, NULL, NULL, "Fencing History");
136  }
137 
138  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
139  out->increment_list(out);
140  }
141 
142  if (rc == pcmk_rc_ok) {
143  out->end_list(out);
144  }
145 
146  return rc;
147 }
148 
149 PCMK__OUTPUT_ARGS("full-fencing-history", "crm_exit_t", "struct stonith_history_t *", "GListPtr", "gboolean", "gboolean")
150 int
152  crm_exit_t history_rc = va_arg(args, crm_exit_t);
153  stonith_history_t *history = va_arg(args, stonith_history_t *);
154  GListPtr only_show = va_arg(args, GListPtr);
155  gboolean full_history = va_arg(args, gboolean);
156  gboolean print_spacer G_GNUC_UNUSED = va_arg(args, gboolean);
157 
158  int rc = pcmk_rc_no_output;
159 
160  if (history_rc == 0) {
161  for (stonith_history_t *hp = history; hp; hp = hp->next) {
162  if (!pcmk__str_in_list(only_show, hp->target)) {
163  continue;
164  }
165 
166  if (rc == pcmk_rc_no_output) {
167  rc = pcmk_rc_ok;
168  out->begin_list(out, NULL, NULL, "Fencing History");
169  }
170 
171  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
172  out->increment_list(out);
173  }
174 
175  if (rc == pcmk_rc_ok) {
176  out->end_list(out);
177  }
178  } else {
179  xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_history");
180  char *rc_s = crm_itoa(history_rc);
181 
182  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) rc_s);
183  free(rc_s);
184 
185  rc = pcmk_rc_ok;
186  }
187 
188  return rc;
189 }
190 
191 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
192 int
194  const char *target = va_arg(args, const char *);
195  time_t when = va_arg(args, time_t);
196 
197  if (when) {
198  char *buf = crm_strdup_printf("Node %s last fenced at: %s", target, ctime(&when));
199  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
200  free(buf);
201  return pcmk_rc_ok;
202  } else {
203  return pcmk_rc_no_output;
204  }
205 }
206 
207 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
208 int
210  const char *target = va_arg(args, const char *);
211  time_t when = va_arg(args, time_t);
212 
213  if (when) {
214  pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
215  } else {
216  pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
217  }
218 
219  return pcmk_rc_ok;
220 }
221 
222 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
223 int
225  const char *target = va_arg(args, const char *);
226  time_t when = va_arg(args, time_t);
227 
228  if (when) {
229  xmlNodePtr node = pcmk__output_create_xml_node(out, "last-fenced");
230  char *buf = time_t_string(when);
231 
232  xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) target);
233  xmlSetProp(node, (pcmkXmlStr) "when", (pcmkXmlStr) buf);
234 
235  free(buf);
236  return pcmk_rc_ok;
237  } else {
238  return pcmk_rc_no_output;
239  }
240 }
241 
242 PCMK__OUTPUT_ARGS("pending-fencing-actions", "struct stonith_history_t *", "GListPtr", "gboolean", "gboolean")
243 int
245  stonith_history_t *history = va_arg(args, stonith_history_t *);
246  GListPtr only_show = va_arg(args, GListPtr);
247  gboolean full_history = va_arg(args, gboolean);
248  gboolean print_spacer = va_arg(args, gboolean);
249 
250  int rc = pcmk_rc_no_output;
251 
252  for (stonith_history_t *hp = history; hp; hp = hp->next) {
253  if (!pcmk__str_in_list(only_show, hp->target)) {
254  continue;
255  }
256 
257  /* Skip the rest of the history after we see a failed/done action */
258  if ((hp->state == st_failed) || (hp->state == st_done)) {
259  break;
260  }
261 
262  if (rc == pcmk_rc_no_output) {
263  if (print_spacer) {
264  out->info(out, "%s", "");
265  }
266 
267  rc = pcmk_rc_ok;
268  out->begin_list(out, NULL, NULL, "Pending Fencing Actions");
269  }
270 
271  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
272  out->increment_list(out);
273  }
274 
275  if (rc == pcmk_rc_ok) {
276  out->end_list(out);
277  }
278 
279  return rc;
280 }
281 
282 PCMK__OUTPUT_ARGS("stonith-event", "struct stonith_history_t *", "gboolean", "gboolean")
283 int
284 stonith__event_html(pcmk__output_t *out, va_list args) {
285  stonith_history_t *event = va_arg(args, stonith_history_t *);
286  gboolean full_history = va_arg(args, gboolean);
287  gboolean later_succeeded = va_arg(args, gboolean);
288 
289  switch(event->state) {
290  case st_done: {
291  char *completed_s = time_t_string(event->completed);
292 
293  out->list_item(out, "successful-stonith-event",
294  "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'",
295  stonith_action_str(event->action), event->target,
296  event->delegate ? event->delegate : "",
297  event->client, event->origin,
298  full_history ? "completed" : "last-successful",
299  completed_s);
300  free(completed_s);
301  break;
302  }
303 
304  case st_failed: {
305  char *failed_s = time_t_string(event->completed);
306 
307  out->list_item(out, "failed-stonith-event",
308  "%s of %s failed : delegate=%s, client=%s, origin=%s, %s='%s' %s",
309  stonith_action_str(event->action), event->target,
310  event->delegate ? event->delegate : "",
311  event->client, event->origin,
312  full_history ? "completed" : "last-failed",
313  failed_s,
314  later_succeeded ? "(a later attempt succeeded)" : "");
315  free(failed_s);
316  break;
317  }
318 
319  default:
320  out->list_item(out, "pending-stonith-event",
321  "%s of %s pending: client=%s, origin=%s",
322  stonith_action_str(event->action), event->target,
323  event->client, event->origin);
324  break;
325  }
326 
327  return pcmk_rc_ok;
328 }
329 
330 PCMK__OUTPUT_ARGS("stonith-event", "struct stonith_history_t *", "gboolean", "gboolean")
331 int
332 stonith__event_text(pcmk__output_t *out, va_list args) {
333  stonith_history_t *event = va_arg(args, stonith_history_t *);
334  gboolean full_history = va_arg(args, gboolean);
335  gboolean later_succeeded = va_arg(args, gboolean);
336 
337  char *buf = time_t_string(event->completed);
338 
339  switch (event->state) {
340  case st_failed:
341  pcmk__indented_printf(out, "%s of %s failed: delegate=%s, client=%s, origin=%s, %s='%s' %s\n",
342  stonith_action_str(event->action), event->target,
343  event->delegate ? event->delegate : "",
344  event->client, event->origin,
345  full_history ? "completed" : "last-failed", buf,
346  later_succeeded ? "(a later attempt succeeded)" : "");
347  break;
348 
349  case st_done:
350  pcmk__indented_printf(out, "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'\n",
351  stonith_action_str(event->action), event->target,
352  event->delegate ? event->delegate : "",
353  event->client, event->origin,
354  full_history ? "completed" : "last-successful", buf);
355  break;
356 
357  default:
358  pcmk__indented_printf(out, "%s of %s pending: client=%s, origin=%s\n",
359  stonith_action_str(event->action), event->target,
360  event->client, event->origin);
361  break;
362  }
363 
364  free(buf);
365  return pcmk_rc_ok;
366 }
367 
368 PCMK__OUTPUT_ARGS("stonith-event", "struct stonith_history_t *", "gboolean", "gboolean")
369 int
370 stonith__event_xml(pcmk__output_t *out, va_list args) {
371  xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_event");
372  stonith_history_t *event = va_arg(args, stonith_history_t *);
373  gboolean full_history G_GNUC_UNUSED = va_arg(args, gboolean);
374  gboolean later_succeeded G_GNUC_UNUSED = va_arg(args, gboolean);
375 
376  char *buf = NULL;
377 
378  switch (event->state) {
379  case st_failed:
380  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "failed");
381  break;
382 
383  case st_done:
384  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "success");
385  break;
386 
387  default: {
388  char *state = crm_itoa(event->state);
389  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "pending");
390  xmlSetProp(node, (pcmkXmlStr) "extended-status", (pcmkXmlStr) state);
391  free(state);
392  break;
393  }
394  }
395 
396  if (event->delegate != NULL) {
397  xmlSetProp(node, (pcmkXmlStr) "delegate", (pcmkXmlStr) event->delegate);
398  }
399 
400  xmlSetProp(node, (pcmkXmlStr) "action", (pcmkXmlStr) event->action);
401  xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) event->target);
402  xmlSetProp(node, (pcmkXmlStr) "client", (pcmkXmlStr) event->client);
403  xmlSetProp(node, (pcmkXmlStr) "origin", (pcmkXmlStr) event->origin);
404 
405  if (event->state == st_failed || event->state == st_done) {
406  buf = time_t_string(event->completed);
407  xmlSetProp(node, (pcmkXmlStr) "completed", (pcmkXmlStr) buf);
408  free(buf);
409  }
410 
411  return pcmk_rc_ok;
412 }
413 
414 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
415 int
417  const char *agent = va_arg(args, const char *);
418  const char *device = va_arg(args, const char *);
419  char *output = va_arg(args, char *);
420  char *error_output = va_arg(args, char *);
421  int rc = va_arg(args, int);
422 
423  if (device) {
424  char *buf = crm_strdup_printf("Validation of %s on %s %s", agent, device,
425  rc ? "failed" : "succeeded");
426  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
427  free(buf);
428  } else {
429  char *buf = crm_strdup_printf("Validation of %s %s", agent,
430  rc ? "failed" : "succeeded");
431  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
432  free(buf);
433  }
434 
435  out->subprocess_output(out, rc, output, error_output);
436  return rc;
437 }
438 
439 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
440 int
442  const char *agent = va_arg(args, const char *);
443  const char *device = va_arg(args, const char *);
444  char *output = va_arg(args, char *);
445  char *error_output = va_arg(args, char *);
446  int rc = va_arg(args, int);
447 
448  if (device) {
449  pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
450  rc ? "failed" : "succeeded");
451  } else {
452  pcmk__indented_printf(out, "Validation of %s %s\n", agent,
453  rc ? "failed" : "succeeded");
454  }
455 
456  if (output) {
457  puts(output);
458  }
459 
460  if (error_output) {
461  puts(error_output);
462  }
463 
464  return rc;
465 }
466 
467 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
468 int
470  xmlNodePtr node = pcmk__output_create_xml_node(out, "validate");
471 
472  const char *agent = va_arg(args, const char *);
473  const char *device = va_arg(args, const char *);
474  char *output = va_arg(args, char *);
475  char *error_output = va_arg(args, char *);
476  int rc = va_arg(args, int);
477 
478  xmlSetProp(node, (pcmkXmlStr) "agent", (pcmkXmlStr) agent);
479  if (device != NULL) {
480  xmlSetProp(node, (pcmkXmlStr) "device", (pcmkXmlStr) device);
481  }
482  xmlSetProp(node, (pcmkXmlStr) "valid", (pcmkXmlStr) (rc ? "false" : "true"));
483 
484  pcmk__output_xml_push_parent(out, node);
485  out->subprocess_output(out, rc, output, error_output);
487 
488  return rc;
489 }
490 
491 static pcmk__message_entry_t fmt_functions[] = {
492  { "failed-fencing-history", "html", stonith__failed_history },
493  { "failed-fencing-history", "log", stonith__failed_history },
494  { "failed-fencing-history", "text", stonith__failed_history },
495  { "failed-fencing-history", "xml", stonith__failed_history },
496  { "fencing-history", "html", stonith__history },
497  { "fencing-history", "log", stonith__history },
498  { "fencing-history", "text", stonith__history },
499  { "fencing-history", "xml", stonith__history },
500  { "full-fencing-history", "html", stonith__full_history },
501  { "full-fencing-history", "log", stonith__full_history },
502  { "full-fencing-history", "text", stonith__full_history },
503  { "full-fencing-history", "xml", stonith__full_history_xml },
504  { "last-fenced", "html", stonith__last_fenced_html },
505  { "last-fenced", "log", stonith__last_fenced_text },
506  { "last-fenced", "text", stonith__last_fenced_text },
507  { "last-fenced", "xml", stonith__last_fenced_xml },
508  { "pending-fencing-actions", "html", stonith__pending_actions },
509  { "pending-fencing-actions", "log", stonith__pending_actions },
510  { "pending-fencing-actions", "text", stonith__pending_actions },
511  { "pending-fencing-actions", "xml", stonith__pending_actions },
512  { "stonith-event", "html", stonith__event_html },
513  { "stonith-event", "log", stonith__event_text },
514  { "stonith-event", "text", stonith__event_text },
515  { "stonith-event", "xml", stonith__event_xml },
516  { "validate", "html", stonith__validate_agent_html },
517  { "validate", "log", stonith__validate_agent_text },
518  { "validate", "text", stonith__validate_agent_text },
519  { "validate", "xml", stonith__validate_agent_xml },
520 
521  { NULL, NULL, NULL }
522 };
523 
524 void
526  pcmk__register_messages(out, fmt_functions);
527 }
int stonith__last_fenced_text(pcmk__output_t *out, va_list args)
Definition: st_output.c:209
struct stonith_history_s * next
Definition: stonith-ng.h:106
Definition: output.h:73
int stonith__event_text(pcmk__output_t *out, va_list args)
Definition: st_output.c:332
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:660
Formatted output for pacemaker tools.
void stonith__register_messages(pcmk__output_t *out)
Definition: st_output.c:525
#define crm_time_log_timeofday
Definition: iso8601.h:65
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:397
struct crm_time_s crm_time_t
Definition: iso8601.h:32
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name)
Definition: output_xml.c:371
int stonith__full_history(pcmk__output_t *out, va_list args)
Definition: st_output.c:114
enum crm_exit_e crm_exit_t
int stonith__last_fenced_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:224
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: output_html.c:389
int rc
Definition: pcmk_fence.c:34
const char * stonith_action_str(const char *action)
Turn stonith action into a more readable string.
Definition: st_client.c:2399
Utility functions.
int stonith__validate_agent_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:469
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition: iso8601.c:1255
int stonith__full_history_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:151
gboolean stonith__later_succeeded(stonith_history_t *event, stonith_history_t *top_history)
Definition: st_client.c:2547
int stonith__validate_agent_html(pcmk__output_t *out, va_list args)
Definition: st_output.c:416
int stonith__event_html(pcmk__output_t *out, va_list args)
Definition: st_output.c:284
Wrappers for and extensions to libxml2.
ISO_8601 Date handling.
PCMK__OUTPUT_ARGS("cluster-summary","struct pe_working_set_t *","gboolean","gboolean","gboolean","gboolean","gboolean","gboolean")
Definition: pe_output.c:214
#define crm_time_log_with_timezone
Definition: iso8601.h:66
int stonith__history(pcmk__output_t *out, va_list args)
Definition: st_output.c:73
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:140
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition: iso8601.c:497
const xmlChar * pcmkXmlStr
Definition: xml.h:51
const char * target
Definition: pcmk_fence.c:28
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition: output_xml.c:387
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:93
void pcmk__indented_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
Fencing aka. STONITH.
This structure contains everything that makes up a single output formatter.
Definition: output.h:153
int stonith__event_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:370
int stonith__failed_history(pcmk__output_t *out, va_list args)
Definition: st_output.c:34
int stonith__validate_agent_text(pcmk__output_t *out, va_list args)
Definition: st_output.c:441
int stonith__pending_actions(pcmk__output_t *out, va_list args)
Definition: st_output.c:244
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
int stonith__last_fenced_html(pcmk__output_t *out, va_list args)
Definition: st_output.c:193
GList * GListPtr
Definition: crm.h:214
#define crm_time_log_date
Definition: iso8601.h:64
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:141