pacemaker  2.0.3-4b1f869f0f
Scalable High-Availability cluster resource manager
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 <stdarg.h>
11 
12 #include <crm/stonith-ng.h>
13 #include <crm/common/iso8601.h>
14 #include <crm/common/output.h>
15 #include <crm/common/util.h>
16 #include <crm/common/xml.h>
17 #include <crm/fencing/internal.h>
18 
19 static char *
20 time_t_string(time_t when) {
21  crm_time_t *crm_when = crm_time_new(NULL);
22  char *buf = NULL;
23 
24  crm_time_set_timet(crm_when, &when);
26  crm_time_free(crm_when);
27  return buf;
28 }
29 
30 static int
31 last_fenced_html(pcmk__output_t *out, va_list args) {
32  const char *target = va_arg(args, const char *);
33  time_t when = va_arg(args, time_t);
34 
35  if (when) {
36  char *buf = crm_strdup_printf("Node %s last fenced at: %s", target, ctime(&when));
37  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
38  free(buf);
39  }
40 
41  return 0;
42 }
43 
44 static int
45 last_fenced_text(pcmk__output_t *out, va_list args) {
46  const char *target = va_arg(args, const char *);
47  time_t when = va_arg(args, time_t);
48 
49  if (when) {
50  pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
51  } else {
52  pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
53  }
54 
55  return 0;
56 }
57 
58 static int
59 last_fenced_xml(pcmk__output_t *out, va_list args) {
60  const char *target = va_arg(args, const char *);
61  time_t when = va_arg(args, time_t);
62 
63  if (when) {
64  xmlNodePtr node = pcmk__output_create_xml_node(out, "last-fenced");
65  char *buf = time_t_string(when);
66 
67  xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) target);
68  xmlSetProp(node, (pcmkXmlStr) "when", (pcmkXmlStr) buf);
69 
70  free(buf);
71  }
72 
73  return 0;
74 }
75 
76 static int
77 stonith_event_html(pcmk__output_t *out, va_list args) {
78  stonith_history_t *event = va_arg(args, stonith_history_t *);
79  int full_history = va_arg(args, int);
80  gboolean later_succeeded = va_arg(args, gboolean);
81 
82  switch(event->state) {
83  case st_done: {
84  char *completed_s = time_t_string(event->completed);
85 
86  out->list_item(out, "successful-stonith-event",
87  "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'",
88  stonith_action_str(event->action), event->target,
89  event->delegate ? event->delegate : "",
90  event->client, event->origin,
91  full_history ? "completed" : "last-successful",
92  completed_s);
93  free(completed_s);
94  break;
95  }
96 
97  case st_failed: {
98  char *failed_s = time_t_string(event->completed);
99 
100  out->list_item(out, "failed-stonith-event",
101  "%s of %s failed : delegate=%s, client=%s, origin=%s, %s='%s' %s",
102  stonith_action_str(event->action), event->target,
103  event->delegate ? event->delegate : "",
104  event->client, event->origin,
105  full_history ? "completed" : "last-failed",
106  failed_s,
107  later_succeeded ? "(a later attempt succeeded)" : "");
108  free(failed_s);
109  break;
110  }
111 
112  default:
113  out->list_item(out, "pending-stonith-event",
114  "%s of %s pending: client=%s, origin=%s",
115  stonith_action_str(event->action), event->target,
116  event->client, event->origin);
117  break;
118  }
119 
120  return 0;
121 }
122 
123 static int
124 stonith_event_text(pcmk__output_t *out, va_list args) {
125  stonith_history_t *event = va_arg(args, stonith_history_t *);
126  int full_history = va_arg(args, int);
127  gboolean later_succeeded = va_arg(args, gboolean);
128 
129  char *buf = time_t_string(event->completed);
130 
131  switch (event->state) {
132  case st_failed:
133  pcmk__indented_printf(out, "%s of %s failed: delegate=%s, client=%s, origin=%s, %s='%s' %s\n",
134  stonith_action_str(event->action), event->target,
135  event->delegate ? event->delegate : "",
136  event->client, event->origin,
137  full_history ? "completed" : "last-failed", buf,
138  later_succeeded ? "(a later attempt succeeded)" : "");
139  break;
140 
141  case st_done:
142  pcmk__indented_printf(out, "%s of %s successful: delegate=%s, client=%s, origin=%s, %s='%s'\n",
143  stonith_action_str(event->action), event->target,
144  event->delegate ? event->delegate : "",
145  event->client, event->origin,
146  full_history ? "completed" : "last-successful", buf);
147  break;
148 
149  default:
150  pcmk__indented_printf(out, "%s of %s pending: client=%s, origin=%s\n",
151  stonith_action_str(event->action), event->target,
152  event->client, event->origin);
153  break;
154  }
155 
156  free(buf);
157  return 0;
158 }
159 
160 static int
161 stonith_event_xml(pcmk__output_t *out, va_list args) {
162  xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_event");
163  stonith_history_t *event = va_arg(args, stonith_history_t *);
164 
165  char *buf = NULL;
166 
167  switch (event->state) {
168  case st_failed:
169  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "failed");
170  break;
171 
172  case st_done:
173  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "success");
174  break;
175 
176  default: {
177  char *state = crm_itoa(event->state);
178  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "pending");
179  xmlSetProp(node, (pcmkXmlStr) "extended-status", (pcmkXmlStr) state);
180  free(state);
181  break;
182  }
183  }
184 
185  if (event->delegate != NULL) {
186  xmlSetProp(node, (pcmkXmlStr) "delegate", (pcmkXmlStr) event->delegate);
187  }
188 
189  xmlSetProp(node, (pcmkXmlStr) "action", (pcmkXmlStr) event->action);
190  xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) event->target);
191  xmlSetProp(node, (pcmkXmlStr) "client", (pcmkXmlStr) event->client);
192  xmlSetProp(node, (pcmkXmlStr) "origin", (pcmkXmlStr) event->origin);
193 
194  if (event->state == st_failed || event->state == st_done) {
195  buf = time_t_string(event->completed);
196  xmlSetProp(node, (pcmkXmlStr) "completed", (pcmkXmlStr) buf);
197  free(buf);
198  }
199 
200  return 0;
201 }
202 
203 static int
204 validate_agent_html(pcmk__output_t *out, va_list args) {
205  const char *agent = va_arg(args, const char *);
206  const char *device = va_arg(args, const char *);
207  const char *output = va_arg(args, const char *);
208  const char *error_output = va_arg(args, const char *);
209  int rc = va_arg(args, int);
210 
211  if (device) {
212  char *buf = crm_strdup_printf("Validation of %s on %s %s", agent, device,
213  rc ? "failed" : "succeeded");
214  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
215  free(buf);
216  } else {
217  char *buf = crm_strdup_printf("Validation of %s %s", agent,
218  rc ? "failed" : "succeeded");
219  pcmk__output_create_html_node(out, "div", NULL, NULL, buf);
220  free(buf);
221  }
222 
223  out->subprocess_output(out, rc, output, error_output);
224  return rc;
225 }
226 
227 static int
228 validate_agent_text(pcmk__output_t *out, va_list args) {
229  const char *agent = va_arg(args, const char *);
230  const char *device = va_arg(args, const char *);
231  const char *output = va_arg(args, const char *);
232  const char *error_output = va_arg(args, const char *);
233  int rc = va_arg(args, int);
234 
235  if (device) {
236  pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
237  rc ? "failed" : "succeeded");
238  } else {
239  pcmk__indented_printf(out, "Validation of %s %s\n", agent,
240  rc ? "failed" : "succeeded");
241  }
242 
243  if (output) {
244  puts(output);
245  }
246 
247  if (error_output) {
248  puts(error_output);
249  }
250 
251  return rc;
252 }
253 
254 static int
255 validate_agent_xml(pcmk__output_t *out, va_list args) {
256  xmlNodePtr node = pcmk__output_create_xml_node(out, "validate");
257 
258  const char *agent = va_arg(args, const char *);
259  const char *device = va_arg(args, const char *);
260  const char *output = va_arg(args, const char *);
261  const char *error_output = va_arg(args, const char *);
262  int rc = va_arg(args, int);
263 
264  xmlSetProp(node, (pcmkXmlStr) "agent", (pcmkXmlStr) agent);
265  if (device != NULL) {
266  xmlSetProp(node, (pcmkXmlStr) "device", (pcmkXmlStr) device);
267  }
268  xmlSetProp(node, (pcmkXmlStr) "valid", (pcmkXmlStr) (rc ? "false" : "true"));
269 
270  pcmk__output_xml_push_parent(out, node);
271  out->subprocess_output(out, rc, output, error_output);
273 
274  return rc;
275 }
276 
277 static pcmk__message_entry_t fmt_functions[] = {
278  { "last-fenced", "html", last_fenced_html },
279  { "last-fenced", "text", last_fenced_text },
280  { "last-fenced", "xml", last_fenced_xml },
281  { "stonith-event", "html", stonith_event_html },
282  { "stonith-event", "text", stonith_event_text },
283  { "stonith-event", "xml", stonith_event_xml },
284  { "validate", "html", validate_agent_html },
285  { "validate", "text", validate_agent_text },
286  { "validate", "xml", validate_agent_xml },
287 
288  { NULL, NULL, NULL }
289 };
290 
291 void
293  pcmk__register_messages(out, fmt_functions);
294 }
st_failed
Definition: stonith-ng.h:71
pcmk__output_s::subprocess_output
void(* subprocess_output)(pcmk__output_t *out, int exit_status, const char *proc_stdout, const char *proc_stderr)
Definition: output.h:319
crm_time_log_timeofday
#define crm_time_log_timeofday
Definition: iso8601.h:65
pcmk__output_create_xml_node
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name)
Definition: output_xml.c:358
st_done
Definition: stonith-ng.h:69
pcmk__output_s::list_item
void(*) void(* list_item)(pcmk__output_t *out, const char *name, const char *format,...) G_GNUC_PRINTF(3
Definition: output.h:402
pcmk__output_create_html_node
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:381
internal.h
xml.h
Wrappers for and extensions to libxml2.
stonith__register_messages
void stonith__register_messages(pcmk__output_t *out)
Definition: st_output.c:292
pcmk__output_xml_push_parent
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition: output_xml.c:374
stonith_action_str
const char * stonith_action_str(const char *action)
Turn stonith action into a more readable string.
Definition: st_client.c:2376
crm_time_log_with_timezone
#define crm_time_log_with_timezone
Definition: iso8601.h:66
crm_time_set_timet
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition: iso8601.c:1257
stonith_history_s
Definition: stonith-ng.h:98
crm_strdup_printf
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
pcmk__indented_printf
void pcmk__indented_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
iso8601.h
ISO_8601 Date handling.
pcmk__output_s
This structure contains everything that makes up a single output formatter.
Definition: output.h:150
pcmk__message_entry_s
Definition: output.h:73
pcmkXmlStr
const typedef xmlChar * pcmkXmlStr
Definition: xml.h:51
stonith-ng.h
Fencing aka. STONITH.
pcmk__register_messages
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:133
crm_time_as_string
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition: iso8601.c:501
crm_time_new
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:96
crm_time_free
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:144
pcmk__output_xml_pop_parent
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:384
crm_time_log_date
#define crm_time_log_date
Definition: iso8601.h:64
util.h
Utility functions.
output.h
Formatted output for pacemaker tools.
crm_time_t
struct crm_time_s crm_time_t
Definition: iso8601.h:32