pacemaker  2.0.5-ba59be712
Scalable High-Availability cluster resource manager
st_output.c
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2020 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>
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", "stonith_history_t *", "GListPtr", "gboolean", "gboolean")
33 int
35  stonith_history_t *history = va_arg(args, stonith_history_t *);
36  GListPtr only_node = 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_node, hp->target)) {
48  continue;
49  }
50 
51  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Failed Fencing Actions");
52  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
53  out->increment_list(out);
54  }
55 
57  return rc;
58 }
59 
60 PCMK__OUTPUT_ARGS("fencing-history", "stonith_history_t *", "GListPtr", "gboolean", "gboolean")
61 int
62 stonith__history(pcmk__output_t *out, va_list args) {
63  stonith_history_t *history = va_arg(args, stonith_history_t *);
64  GListPtr only_node = va_arg(args, GListPtr);
65  gboolean full_history = va_arg(args, gboolean);
66  gboolean print_spacer = va_arg(args, gboolean);
67 
68  int rc = pcmk_rc_no_output;
69 
70  for (stonith_history_t *hp = history; hp; hp = hp->next) {
71  if (!pcmk__str_in_list(only_node, hp->target)) {
72  continue;
73  }
74 
75  if (hp->state != st_failed) {
76  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
77  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
78  out->increment_list(out);
79  }
80  }
81 
83  return rc;
84 }
85 
86 PCMK__OUTPUT_ARGS("full-fencing-history", "crm_exit_t", "stonith_history_t *", "GListPtr", "gboolean", "gboolean")
87 int
89  crm_exit_t history_rc G_GNUC_UNUSED = va_arg(args, crm_exit_t);
90  stonith_history_t *history = va_arg(args, stonith_history_t *);
91  GListPtr only_node = va_arg(args, GListPtr);
92  gboolean full_history = va_arg(args, gboolean);
93  gboolean print_spacer = va_arg(args, gboolean);
94 
95  int rc = pcmk_rc_no_output;
96 
97  for (stonith_history_t *hp = history; hp; hp = hp->next) {
98  if (!pcmk__str_in_list(only_node, hp->target)) {
99  continue;
100  }
101 
102  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
103  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
104  out->increment_list(out);
105  }
106 
108  return rc;
109 }
110 
111 PCMK__OUTPUT_ARGS("full-fencing-history", "crm_exit_t", "stonith_history_t *", "GListPtr", "gboolean", "gboolean")
112 int
114  crm_exit_t history_rc = va_arg(args, crm_exit_t);
115  stonith_history_t *history = va_arg(args, stonith_history_t *);
116  GListPtr only_node = va_arg(args, GListPtr);
117  gboolean full_history = va_arg(args, gboolean);
118  gboolean print_spacer G_GNUC_UNUSED = va_arg(args, gboolean);
119 
120  int rc = pcmk_rc_no_output;
121 
122  if (history_rc == 0) {
123  for (stonith_history_t *hp = history; hp; hp = hp->next) {
124  if (!pcmk__str_in_list(only_node, hp->target)) {
125  continue;
126  }
127 
128  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Fencing History");
129  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
130  out->increment_list(out);
131  }
132 
134  } else {
135  xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_history");
136  char *rc_s = crm_itoa(history_rc);
137 
138  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) rc_s);
139  free(rc_s);
140 
141  rc = pcmk_rc_ok;
142  }
143 
144  return rc;
145 }
146 
147 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
148 int
150  const char *target = va_arg(args, const char *);
151  time_t when = va_arg(args, time_t);
152 
153  if (when) {
154  char *buf = crm_strdup_printf("Node %s last fenced at: %s", target, ctime(&when));
155  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
156  free(buf);
157  return pcmk_rc_ok;
158  } else {
159  return pcmk_rc_no_output;
160  }
161 }
162 
163 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
164 int
166  const char *target = va_arg(args, const char *);
167  time_t when = va_arg(args, time_t);
168 
169  if (when) {
170  pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
171  } else {
172  pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
173  }
174 
175  return pcmk_rc_ok;
176 }
177 
178 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
179 int
181  const char *target = va_arg(args, const char *);
182  time_t when = va_arg(args, time_t);
183 
184  if (when) {
185  xmlNodePtr node = pcmk__output_create_xml_node(out, "last-fenced");
186  char *buf = time_t_string(when);
187 
188  xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) target);
189  xmlSetProp(node, (pcmkXmlStr) "when", (pcmkXmlStr) buf);
190 
191  free(buf);
192  return pcmk_rc_ok;
193  } else {
194  return pcmk_rc_no_output;
195  }
196 }
197 
198 PCMK__OUTPUT_ARGS("pending-fencing-actions", "stonith_history_t *", "GListPtr", "gboolean", "gboolean")
199 int
201  stonith_history_t *history = va_arg(args, stonith_history_t *);
202  GListPtr only_node = va_arg(args, GListPtr);
203  gboolean full_history = va_arg(args, gboolean);
204  gboolean print_spacer = va_arg(args, gboolean);
205 
206  int rc = pcmk_rc_no_output;
207 
208  for (stonith_history_t *hp = history; hp; hp = hp->next) {
209  if (!pcmk__str_in_list(only_node, hp->target)) {
210  continue;
211  }
212 
213  /* Skip the rest of the history after we see a failed/done action */
214  if ((hp->state == st_failed) || (hp->state == st_done)) {
215  break;
216  }
217 
218  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Pending Fencing Actions");
219  out->message(out, "stonith-event", hp, full_history, stonith__later_succeeded(hp, history));
220  out->increment_list(out);
221  }
222 
224  return rc;
225 }
226 
227 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "gboolean", "gboolean")
228 int
229 stonith__event_html(pcmk__output_t *out, va_list args) {
230  stonith_history_t *event = va_arg(args, stonith_history_t *);
231  gboolean full_history = va_arg(args, gboolean);
232  gboolean later_succeeded = va_arg(args, gboolean);
233 
234  switch(event->state) {
235  case st_done: {
236  char *completed_s = time_t_string(event->completed);
237 
238  out->list_item(out, "successful-stonith-event",
239  "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'",
240  stonith_action_str(event->action), event->target,
241  event->delegate ? event->delegate : "",
242  event->client, event->origin,
243  full_history ? "completed" : "last-successful",
244  completed_s);
245  free(completed_s);
246  break;
247  }
248 
249  case st_failed: {
250  char *failed_s = time_t_string(event->completed);
251 
252  out->list_item(out, "failed-stonith-event",
253  "%s of %s failed : delegate=%s, client=%s, origin=%s, %s='%s' %s",
254  stonith_action_str(event->action), event->target,
255  event->delegate ? event->delegate : "",
256  event->client, event->origin,
257  full_history ? "completed" : "last-failed",
258  failed_s,
259  later_succeeded ? "(a later attempt succeeded)" : "");
260  free(failed_s);
261  break;
262  }
263 
264  default:
265  out->list_item(out, "pending-stonith-event",
266  "%s of %s pending: client=%s, origin=%s",
267  stonith_action_str(event->action), event->target,
268  event->client, event->origin);
269  break;
270  }
271 
272  return pcmk_rc_ok;
273 }
274 
275 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "gboolean", "gboolean")
276 int
277 stonith__event_text(pcmk__output_t *out, va_list args) {
278  stonith_history_t *event = va_arg(args, stonith_history_t *);
279  gboolean full_history = va_arg(args, gboolean);
280  gboolean later_succeeded = va_arg(args, gboolean);
281 
282  char *buf = time_t_string(event->completed);
283 
284  switch (event->state) {
285  case st_failed:
286  pcmk__indented_printf(out, "%s of %s failed: delegate=%s, client=%s, origin=%s, %s='%s' %s\n",
287  stonith_action_str(event->action), event->target,
288  event->delegate ? event->delegate : "",
289  event->client, event->origin,
290  full_history ? "completed" : "last-failed", buf,
291  later_succeeded ? "(a later attempt succeeded)" : "");
292  break;
293 
294  case st_done:
295  pcmk__indented_printf(out, "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'\n",
296  stonith_action_str(event->action), event->target,
297  event->delegate ? event->delegate : "",
298  event->client, event->origin,
299  full_history ? "completed" : "last-successful", buf);
300  break;
301 
302  default:
303  pcmk__indented_printf(out, "%s of %s pending: client=%s, origin=%s\n",
304  stonith_action_str(event->action), event->target,
305  event->client, event->origin);
306  break;
307  }
308 
309  free(buf);
310  return pcmk_rc_ok;
311 }
312 
313 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "gboolean", "gboolean")
314 int
315 stonith__event_xml(pcmk__output_t *out, va_list args) {
316  xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_event");
317  stonith_history_t *event = va_arg(args, stonith_history_t *);
318  gboolean full_history G_GNUC_UNUSED = va_arg(args, gboolean);
319  gboolean later_succeeded G_GNUC_UNUSED = va_arg(args, gboolean);
320 
321  char *buf = NULL;
322 
323  switch (event->state) {
324  case st_failed:
325  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "failed");
326  break;
327 
328  case st_done:
329  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "success");
330  break;
331 
332  default: {
333  char *state = crm_itoa(event->state);
334  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "pending");
335  xmlSetProp(node, (pcmkXmlStr) "extended-status", (pcmkXmlStr) state);
336  free(state);
337  break;
338  }
339  }
340 
341  if (event->delegate != NULL) {
342  xmlSetProp(node, (pcmkXmlStr) "delegate", (pcmkXmlStr) event->delegate);
343  }
344 
345  xmlSetProp(node, (pcmkXmlStr) "action", (pcmkXmlStr) event->action);
346  xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) event->target);
347  xmlSetProp(node, (pcmkXmlStr) "client", (pcmkXmlStr) event->client);
348  xmlSetProp(node, (pcmkXmlStr) "origin", (pcmkXmlStr) event->origin);
349 
350  if (event->state == st_failed || event->state == st_done) {
351  buf = time_t_string(event->completed);
352  xmlSetProp(node, (pcmkXmlStr) "completed", (pcmkXmlStr) buf);
353  free(buf);
354  }
355 
356  return pcmk_rc_ok;
357 }
358 
359 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
360 int
362  const char *agent = va_arg(args, const char *);
363  const char *device = va_arg(args, const char *);
364  char *output = va_arg(args, char *);
365  char *error_output = va_arg(args, char *);
366  int rc = va_arg(args, int);
367 
368  if (device) {
369  char *buf = crm_strdup_printf("Validation of %s on %s %s", agent, device,
370  rc ? "failed" : "succeeded");
371  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
372  free(buf);
373  } else {
374  char *buf = crm_strdup_printf("Validation of %s %s", agent,
375  rc ? "failed" : "succeeded");
376  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
377  free(buf);
378  }
379 
380  out->subprocess_output(out, rc, output, error_output);
381  return rc;
382 }
383 
384 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
385 int
387  const char *agent = va_arg(args, const char *);
388  const char *device = va_arg(args, const char *);
389  char *output = va_arg(args, char *);
390  char *error_output = va_arg(args, char *);
391  int rc = va_arg(args, int);
392 
393  if (device) {
394  pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
395  rc ? "failed" : "succeeded");
396  } else {
397  pcmk__indented_printf(out, "Validation of %s %s\n", agent,
398  rc ? "failed" : "succeeded");
399  }
400 
401  if (output) {
402  puts(output);
403  }
404 
405  if (error_output) {
406  puts(error_output);
407  }
408 
409  return rc;
410 }
411 
412 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "char *", "char *", "int")
413 int
415  xmlNodePtr node = pcmk__output_create_xml_node(out, "validate");
416 
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  xmlSetProp(node, (pcmkXmlStr) "agent", (pcmkXmlStr) agent);
424  if (device != NULL) {
425  xmlSetProp(node, (pcmkXmlStr) "device", (pcmkXmlStr) device);
426  }
427  xmlSetProp(node, (pcmkXmlStr) "valid", (pcmkXmlStr) pcmk__btoa(rc));
428 
429  pcmk__output_xml_push_parent(out, node);
430  out->subprocess_output(out, rc, output, error_output);
432 
433  return rc;
434 }
435 
436 static pcmk__message_entry_t fmt_functions[] = {
437  { "failed-fencing-history", "default", stonith__failed_history },
438  { "fencing-history", "default", stonith__history },
439  { "full-fencing-history", "default", stonith__full_history },
440  { "full-fencing-history", "xml", stonith__full_history_xml },
441  { "last-fenced", "html", stonith__last_fenced_html },
442  { "last-fenced", "log", stonith__last_fenced_text },
443  { "last-fenced", "text", stonith__last_fenced_text },
444  { "last-fenced", "xml", stonith__last_fenced_xml },
445  { "pending-fencing-actions", "default", stonith__pending_actions },
446  { "stonith-event", "html", stonith__event_html },
447  { "stonith-event", "log", stonith__event_text },
448  { "stonith-event", "text", stonith__event_text },
449  { "stonith-event", "xml", stonith__event_xml },
450  { "validate", "html", stonith__validate_agent_html },
451  { "validate", "log", stonith__validate_agent_text },
452  { "validate", "text", stonith__validate_agent_text },
453  { "validate", "xml", stonith__validate_agent_xml },
454 
455  { NULL, NULL, NULL }
456 };
457 
458 void
460  pcmk__register_messages(out, fmt_functions);
461 }
int stonith__validate_agent_text(pcmk__output_t *out, va_list args)
Definition: st_output.c:386
struct stonith_history_s * next
Definition: stonith-ng.h:106
int stonith__event_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:315
int stonith__full_history(pcmk__output_t *out, va_list args)
Definition: st_output.c:88
#define crm_time_log_timeofday
Definition: iso8601.h:67
struct crm_time_s crm_time_t
Definition: iso8601.h:32
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:794
int stonith__event_html(pcmk__output_t *out, va_list args)
Definition: st_output.c:229
enum crm_exit_e crm_exit_t
int stonith__last_fenced_text(pcmk__output_t *out, va_list args)
Definition: st_output.c:165
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:407
int stonith__validate_agent_html(pcmk__output_t *out, va_list args)
Definition: st_output.c:361
Formatted output for pacemaker tools.
int rc
Definition: pcmk_fence.c:35
int stonith__history(pcmk__output_t *out, va_list args)
Definition: st_output.c:62
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition: output_xml.c:448
const char * stonith_action_str(const char *action)
Turn stonith action into a more readable string.
Definition: st_client.c:2392
Utility functions.
#define PCMK__OUTPUT_ARGS(ARGS...)
int stonith__event_text(pcmk__output_t *out, va_list args)
Definition: st_output.c:277
int stonith__pending_actions(pcmk__output_t *out, va_list args)
Definition: st_output.c:200
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition: iso8601.c:1255
void stonith__register_messages(pcmk__output_t *out)
Definition: st_output.c:459
gboolean stonith__later_succeeded(stonith_history_t *event, stonith_history_t *top_history)
Definition: st_client.c:2540
Wrappers for and extensions to libxml2.
void pcmk__indented_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
ISO_8601 Date handling.
int stonith__full_history_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:113
int stonith__validate_agent_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:414
int stonith__last_fenced_xml(pcmk__output_t *out, va_list args)
Definition: st_output.c:180
#define crm_time_log_with_timezone
Definition: iso8601.h:68
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:458
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition: iso8601.c:497
const xmlChar * pcmkXmlStr
Definition: xml.h:51
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
const char * target
Definition: pcmk_fence.c:29
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:93
Fencing aka. STONITH.
This structure contains everything that makes up a single output formatter.
int stonith__last_fenced_html(pcmk__output_t *out, va_list args)
Definition: st_output.c:149
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:145
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name)
Definition: output_xml.c:432
int stonith__failed_history(pcmk__output_t *out, va_list args)
Definition: st_output.c:34
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
GList * GListPtr
Definition: crm.h:214
#define crm_time_log_date
Definition: iso8601.h:66
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:141