pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pe_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>
12 #include <crm/msg_xml.h>
13 #include <crm/pengine/internal.h>
14 
15 #define SUMMARY_HEADER(rc, out) do { \
16  if (rc == pcmk_rc_no_output) { \
17  out->begin_list(out, NULL, NULL, "Cluster Summary"); \
18  rc = pcmk_rc_ok; \
19  } \
20  } while (0)
21 
22 static char *
23 failed_action_string(xmlNodePtr xml_op) {
24  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
26  int status = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS), "0");
27  const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
28 
29  time_t last_change = 0;
30 
32  &last_change) == pcmk_ok) {
33  crm_time_t *crm_when = crm_time_new(NULL);
34  char *time_s = NULL;
35  char *buf = NULL;
36 
37  crm_time_set_timet(crm_when, &last_change);
39 
40  buf = crm_strdup_printf("%s on %s '%s' (%d): call=%s, status='%s', "
41  "exitreason='%s', " XML_RSC_OP_LAST_CHANGE
42  "='%s', queued=%sms, exec=%sms",
43  op_key ? op_key : ID(xml_op),
45  services_ocf_exitcode_str(rc), rc,
47  services_lrm_status_str(status),
48  exit_reason ? exit_reason : "none",
49  time_s,
52 
53  crm_time_free(crm_when);
54  free(time_s);
55  return buf;
56  } else {
57  return crm_strdup_printf("%s on %s '%s' (%d): call=%s, status=%s, exitreason='%s'",
58  op_key ? op_key : ID(xml_op),
60  services_ocf_exitcode_str(rc), rc,
62  services_lrm_status_str(status),
63  exit_reason ? exit_reason : "none");
64  }
65 }
66 
67 static const char *
68 get_cluster_stack(pe_working_set_t *data_set)
69 {
70  xmlNode *stack = get_xpath_object("//nvpair[@name='cluster-infrastructure']",
71  data_set->input, LOG_DEBUG);
72  return stack? crm_element_value(stack, XML_NVPAIR_ATTR_VALUE) : "unknown";
73 }
74 
75 static char *
76 last_changed_string(const char *last_written, const char *user,
77  const char *client, const char *origin) {
78  if (last_written != NULL || user != NULL || client != NULL || origin != NULL) {
79  return crm_strdup_printf("%s%s%s%s%s%s%s",
80  last_written ? last_written : "",
81  user ? " by " : "",
82  user ? user : "",
83  client ? " via " : "",
84  client ? client : "",
85  origin ? " on " : "",
86  origin ? origin : "");
87  } else {
88  return strdup("");
89  }
90 }
91 
92 static char *
93 op_history_string(xmlNode *xml_op, const char *task, const char *interval_ms_s,
94  int rc, gboolean print_timing) {
95  const char *call = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
96  char *interval_str = NULL;
97  char *buf = NULL;
98 
99  if (interval_ms_s && safe_str_neq(interval_ms_s, "0")) {
100  char *pair = pcmk_format_nvpair("interval", interval_ms_s, "ms");
101  interval_str = crm_strdup_printf(" %s", pair);
102  free(pair);
103  }
104 
105  if (print_timing) {
106  char *last_change_str = NULL;
107  char *last_run_str = NULL;
108  char *exec_str = NULL;
109  char *queue_str = NULL;
110 
111  const char *value = NULL;
112 
113  time_t epoch = 0;
114 
115  if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE, &epoch) == pcmk_ok)
116  && (epoch > 0)) {
117  char *time = pcmk_format_named_time(XML_RSC_OP_LAST_CHANGE, epoch);
118  last_change_str = crm_strdup_printf(" %s", time);
119  free(time);
120  }
121 
122  if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_RUN, &epoch) == pcmk_ok)
123  && (epoch > 0)) {
124  char *time = pcmk_format_named_time(XML_RSC_OP_LAST_RUN, epoch);
125  last_run_str = crm_strdup_printf(" %s", time);
126  free(time);
127  }
128 
129  value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
130  if (value) {
131  char *pair = pcmk_format_nvpair(XML_RSC_OP_T_EXEC, value, "ms");
132  exec_str = crm_strdup_printf(" %s", pair);
133  free(pair);
134  }
135 
136  value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
137  if (value) {
138  char *pair = pcmk_format_nvpair(XML_RSC_OP_T_QUEUE, value, "ms");
139  queue_str = crm_strdup_printf(" %s", pair);
140  free(pair);
141  }
142 
143  buf = crm_strdup_printf("(%s) %s:%s%s%s%s%s rc=%d (%s)", call, task,
144  interval_str ? interval_str : "",
145  last_change_str ? last_change_str : "",
146  last_run_str ? last_run_str : "",
147  exec_str ? exec_str : "",
148  queue_str ? queue_str : "",
149  rc, services_ocf_exitcode_str(rc));
150 
151  if (last_change_str) {
152  free(last_change_str);
153  }
154 
155  if (last_run_str) {
156  free(last_run_str);
157  }
158 
159  if (exec_str) {
160  free(exec_str);
161  }
162 
163  if (queue_str) {
164  free(queue_str);
165  }
166  } else {
167  buf = crm_strdup_printf("(%s) %s%s%s", call, task,
168  interval_str ? ":" : "",
169  interval_str ? interval_str : "");
170  }
171 
172  if (interval_str) {
173  free(interval_str);
174  }
175 
176  return buf;
177 }
178 
179 static char *
180 resource_history_string(pe_resource_t *rsc, const char *rsc_id, gboolean all,
181  int failcount, time_t last_failure) {
182  char *buf = NULL;
183 
184  if (rsc == NULL) {
185  buf = crm_strdup_printf("%s: orphan", rsc_id);
186  } else if (all || failcount || last_failure > 0) {
187  char *failcount_s = NULL;
188  char *lastfail_s = NULL;
189 
190  if (failcount > 0) {
191  failcount_s = crm_strdup_printf(" %s=%d", PCMK__FAIL_COUNT_PREFIX,
192  failcount);
193  } else {
194  failcount_s = strdup("");
195  }
196  if (last_failure > 0) {
197  lastfail_s = crm_strdup_printf(" %s='%s'",
199  pcmk__epoch2str(&last_failure));
200  }
201 
202  buf = crm_strdup_printf("%s: migration-threshold=%d%s%s",
203  rsc_id, rsc->migration_threshold, failcount_s,
204  lastfail_s? lastfail_s : "");
205  free(failcount_s);
206  free(lastfail_s);
207  } else {
208  buf = crm_strdup_printf("%s:", rsc_id);
209  }
210 
211  return buf;
212 }
213 
214 PCMK__OUTPUT_ARGS("cluster-summary", "struct pe_working_set_t *", "gboolean", "gboolean", "gboolean",
215  "gboolean", "gboolean", "gboolean")
216 int
217 pe__cluster_summary(pcmk__output_t *out, va_list args) {
218  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
219  gboolean print_clone_detail = va_arg(args, gboolean);
220  gboolean show_stack = va_arg(args, gboolean);
221  gboolean show_dc = va_arg(args, gboolean);
222  gboolean show_times = va_arg(args, gboolean);
223  gboolean show_counts = va_arg(args, gboolean);
224  gboolean show_options = va_arg(args, gboolean);
225  int rc = pcmk_rc_no_output;
226 
227  const char *stack_s = get_cluster_stack(data_set);
228 
229  if (show_stack) {
230  SUMMARY_HEADER(rc, out);
231  out->message(out, "cluster-stack", stack_s);
232  }
233 
234  /* Always print DC if none, even if not requested */
235  if (data_set->dc_node == NULL || show_dc) {
236  xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
237  data_set->input, LOG_DEBUG);
238  const char *dc_version_s = dc_version?
240  : NULL;
241  const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
242  char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, print_clone_detail) : NULL;
243 
244  SUMMARY_HEADER(rc, out);
245  out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
246  free(dc_name);
247  }
248 
249  if (show_times) {
250  const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
251  const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
252  const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
253  const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
254 
255  SUMMARY_HEADER(rc, out);
256  out->message(out, "cluster-times", last_written, user, client, origin);
257  }
258 
259  if (show_counts) {
260  SUMMARY_HEADER(rc, out);
261  out->message(out, "cluster-counts", g_list_length(data_set->nodes),
262  data_set->ninstances, data_set->disabled_resources,
263  data_set->blocked_resources);
264  }
265 
266  if (show_options) {
267  SUMMARY_HEADER(rc, out);
268  out->message(out, "cluster-options", data_set);
269  }
270 
271  if (rc == pcmk_rc_ok) {
272  out->end_list(out);
273  }
274 
275  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
276  out->message(out, "maint-mode");
277  rc = pcmk_rc_ok;
278  }
279 
280  return rc;
281 }
282 
283 PCMK__OUTPUT_ARGS("cluster-summary", "struct pe_working_set_t *", "gboolean", "gboolean", "gboolean",
284  "gboolean", "gboolean", "gboolean")
285 int
286 pe__cluster_summary_html(pcmk__output_t *out, va_list args) {
287  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
288  gboolean print_clone_detail = va_arg(args, gboolean);
289  gboolean show_stack = va_arg(args, gboolean);
290  gboolean show_dc = va_arg(args, gboolean);
291  gboolean show_times = va_arg(args, gboolean);
292  gboolean show_counts = va_arg(args, gboolean);
293  gboolean show_options = va_arg(args, gboolean);
294  int rc = pcmk_rc_no_output;
295 
296  const char *stack_s = get_cluster_stack(data_set);
297 
298  if (show_stack) {
299  SUMMARY_HEADER(rc, out);
300  out->message(out, "cluster-stack", stack_s);
301  }
302 
303  /* Always print DC if none, even if not requested */
304  if (data_set->dc_node == NULL || show_dc) {
305  xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
306  data_set->input, LOG_DEBUG);
307  const char *dc_version_s = dc_version?
309  : NULL;
310  const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
311  char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, print_clone_detail) : NULL;
312 
313  SUMMARY_HEADER(rc, out);
314  out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
315  free(dc_name);
316  }
317 
318  if (show_times) {
319  const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
320  const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
321  const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
322  const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
323 
324  SUMMARY_HEADER(rc, out);
325  out->message(out, "cluster-times", last_written, user, client, origin);
326  }
327 
328  if (show_counts) {
329  SUMMARY_HEADER(rc, out);
330  out->message(out, "cluster-counts", g_list_length(data_set->nodes),
331  data_set->ninstances, data_set->disabled_resources,
332  data_set->blocked_resources);
333  }
334 
335  if (show_options) {
336  /* Kind of a hack - close the list we may have opened earlier in this
337  * function so we can put all the options into their own list. We
338  * only want to do this on HTML output, though.
339  */
340  if (rc == pcmk_rc_ok) {
341  out->end_list(out);
342  }
343 
344  out->begin_list(out, NULL, NULL, "Config Options");
345  out->message(out, "cluster-options", data_set);
346  }
347 
348  if (rc == pcmk_rc_ok) {
349  out->end_list(out);
350  }
351 
352  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
353  out->message(out, "maint-mode");
354  rc = pcmk_rc_ok;
355  }
356 
357  return rc;
358 }
359 
360 char *
361 pe__node_display_name(pe_node_t *node, bool print_detail)
362 {
363  char *node_name;
364  const char *node_host = NULL;
365  const char *node_id = NULL;
366  int name_len;
367 
368  CRM_ASSERT((node != NULL) && (node->details != NULL) && (node->details->uname != NULL));
369 
370  /* Host is displayed only if this is a guest node */
371  if (pe__is_guest_node(node)) {
372  pe_node_t *host_node = pe__current_node(node->details->remote_rsc);
373 
374  if (host_node && host_node->details) {
375  node_host = host_node->details->uname;
376  }
377  if (node_host == NULL) {
378  node_host = ""; /* so we at least get "uname@" to indicate guest */
379  }
380  }
381 
382  /* Node ID is displayed if different from uname and detail is requested */
383  if (print_detail && safe_str_neq(node->details->uname, node->details->id)) {
384  node_id = node->details->id;
385  }
386 
387  /* Determine name length */
388  name_len = strlen(node->details->uname) + 1;
389  if (node_host) {
390  name_len += strlen(node_host) + 1; /* "@node_host" */
391  }
392  if (node_id) {
393  name_len += strlen(node_id) + 3; /* + " (node_id)" */
394  }
395 
396  /* Allocate and populate display name */
397  node_name = malloc(name_len);
398  CRM_ASSERT(node_name != NULL);
399  strcpy(node_name, node->details->uname);
400  if (node_host) {
401  strcat(node_name, "@");
402  strcat(node_name, node_host);
403  }
404  if (node_id) {
405  strcat(node_name, " (");
406  strcat(node_name, node_id);
407  strcat(node_name, ")");
408  }
409  return node_name;
410 }
411 
412 int
413 pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name
414  , size_t pairs_count, ...)
415 {
416  xmlNodePtr xml_node = NULL;
417  va_list args;
418 
419  CRM_ASSERT(tag_name != NULL);
420 
421  xml_node = pcmk__output_xml_peek_parent(out);
422  CRM_ASSERT(xml_node != NULL);
423  xml_node = is_list
424  ? create_xml_node(xml_node, tag_name)
425  : xmlNewChild(xml_node, NULL, (pcmkXmlStr) tag_name, NULL);
426 
427  va_start(args, pairs_count);
428  while(pairs_count--) {
429  const char *param_name = va_arg(args, const char *);
430  const char *param_value = va_arg(args, const char *);
431  if (param_name && param_value) {
432  xmlSetProp(xml_node, (pcmkXmlStr)param_name, (pcmkXmlStr)param_value);
433  }
434  };
435  va_end(args);
436 
437  if (is_list) {
438  pcmk__output_xml_push_parent(out, xml_node);
439  }
440  return pcmk_rc_ok;
441 }
442 
443 PCMK__OUTPUT_ARGS("ban", "struct pe_node_t *", "struct pe__location_t *", "gboolean")
444 int
445 pe__ban_html(pcmk__output_t *out, va_list args) {
446  pe_node_t *pe_node = va_arg(args, pe_node_t *);
447  pe__location_t *location = va_arg(args, pe__location_t *);
448  gboolean print_clone_detail = va_arg(args, gboolean);
449 
450  char *node_name = pe__node_display_name(pe_node, print_clone_detail);
451  char *buf = crm_strdup_printf("%s\tprevents %s from running %son %s",
452  location->id, location->rsc_lh->id,
453  location->role_filter == RSC_ROLE_MASTER ? "as Master " : "",
454  node_name);
455 
456  pcmk__output_create_html_node(out, "li", NULL, NULL, buf);
457 
458  free(node_name);
459  free(buf);
460  return pcmk_rc_ok;
461 }
462 
463 PCMK__OUTPUT_ARGS("ban", "struct pe_node_t *", "struct pe__location_t *", "gboolean")
464 int
465 pe__ban_text(pcmk__output_t *out, va_list args) {
466  pe_node_t *pe_node = va_arg(args, pe_node_t *);
467  pe__location_t *location = va_arg(args, pe__location_t *);
468  gboolean print_clone_detail = va_arg(args, gboolean);
469 
470  char *node_name = pe__node_display_name(pe_node, print_clone_detail);
471  out->list_item(out, NULL, "%s\tprevents %s from running %son %s",
472  location->id, location->rsc_lh->id,
473  location->role_filter == RSC_ROLE_MASTER ? "as Master " : "",
474  node_name);
475 
476  free(node_name);
477  return pcmk_rc_ok;
478 }
479 
480 PCMK__OUTPUT_ARGS("ban", "struct pe_node_t *", "struct pe__location_t *", "gboolean")
481 int
482 pe__ban_xml(pcmk__output_t *out, va_list args) {
483  xmlNodePtr node = pcmk__output_create_xml_node(out, "ban");
484  pe_node_t *pe_node = va_arg(args, pe_node_t *);
485  pe__location_t *location = va_arg(args, pe__location_t *);
486  gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
487 
488  char *weight_s = crm_itoa(pe_node->weight);
489 
490  xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) location->id);
491  xmlSetProp(node, (pcmkXmlStr) "resource", (pcmkXmlStr) location->rsc_lh->id);
492  xmlSetProp(node, (pcmkXmlStr) "node", (pcmkXmlStr) pe_node->details->uname);
493  xmlSetProp(node, (pcmkXmlStr) "weight", (pcmkXmlStr) weight_s);
494  xmlSetProp(node, (pcmkXmlStr) "master_only",
495  (pcmkXmlStr) (location->role_filter == RSC_ROLE_MASTER ? "true" : "false"));
496 
497  free(weight_s);
498  return pcmk_rc_ok;
499 }
500 
501 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
502 int
504  xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "li");
505  xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "li");
506 
507  unsigned int nnodes = va_arg(args, unsigned int);
508  int nresources = va_arg(args, int);
509  int ndisabled = va_arg(args, int);
510  int nblocked = va_arg(args, int);
511 
512  char *nnodes_str = crm_strdup_printf("%d node%s configured",
513  nnodes, pcmk__plural_s(nnodes));
514 
515  pcmk_create_html_node(nodes_node, "span", NULL, NULL, nnodes_str);
516  free(nnodes_str);
517 
518  if (ndisabled && nblocked) {
519  char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
520  nresources, pcmk__plural_s(nresources),
521  ndisabled);
522  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
523  free(s);
524 
525  pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
526 
527  s = crm_strdup_printf(", %d ", nblocked);
528  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
529  free(s);
530 
531  pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
532  pcmk_create_html_node(resources_node, "span", NULL, NULL,
533  " from further action due to failure)");
534  } else if (ndisabled && !nblocked) {
535  char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
536  nresources, pcmk__plural_s(nresources),
537  ndisabled);
538  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
539  free(s);
540 
541  pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
542  pcmk_create_html_node(resources_node, "span", NULL, NULL, ")");
543  } else if (!ndisabled && nblocked) {
544  char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
545  nresources, pcmk__plural_s(nresources),
546  nblocked);
547  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
548  free(s);
549 
550  pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
551  pcmk_create_html_node(resources_node, "span", NULL, NULL,
552  " from further action due to failure)");
553  } else {
554  char *s = crm_strdup_printf("%d resource instance%s configured",
555  nresources, pcmk__plural_s(nresources));
556  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
557  free(s);
558  }
559 
560  return pcmk_rc_ok;
561 }
562 
563 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
564 int
566  unsigned int nnodes = va_arg(args, unsigned int);
567  int nresources = va_arg(args, int);
568  int ndisabled = va_arg(args, int);
569  int nblocked = va_arg(args, int);
570 
571  out->list_item(out, NULL, "%d node%s configured",
572  nnodes, pcmk__plural_s(nnodes));
573 
574  if (ndisabled && nblocked) {
575  out->list_item(out, NULL, "%d resource instance%s configured "
576  "(%d DISABLED, %d BLOCKED from "
577  "further action due to failure)",
578  nresources, pcmk__plural_s(nresources), ndisabled,
579  nblocked);
580  } else if (ndisabled && !nblocked) {
581  out->list_item(out, NULL, "%d resource instance%s configured "
582  "(%d DISABLED)",
583  nresources, pcmk__plural_s(nresources), ndisabled);
584  } else if (!ndisabled && nblocked) {
585  out->list_item(out, NULL, "%d resource instance%s configured "
586  "(%d BLOCKED from further action "
587  "due to failure)",
588  nresources, pcmk__plural_s(nresources), nblocked);
589  } else {
590  out->list_item(out, NULL, "%d resource instance%s configured",
591  nresources, pcmk__plural_s(nresources));
592  }
593 
594  return pcmk_rc_ok;
595 }
596 
597 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
598 int
600  xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "nodes_configured");
601  xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "resources_configured");
602 
603  unsigned int nnodes = va_arg(args, unsigned int);
604  int nresources = va_arg(args, int);
605  int ndisabled = va_arg(args, int);
606  int nblocked = va_arg(args, int);
607 
608  char *s = crm_itoa(nnodes);
609  xmlSetProp(nodes_node, (pcmkXmlStr) "number", (pcmkXmlStr) s);
610  free(s);
611 
612  s = crm_itoa(nresources);
613  xmlSetProp(resources_node, (pcmkXmlStr) "number", (pcmkXmlStr) s);
614  free(s);
615 
616  s = crm_itoa(ndisabled);
617  xmlSetProp(resources_node, (pcmkXmlStr) "disabled", (pcmkXmlStr) s);
618  free(s);
619 
620  s = crm_itoa(nblocked);
621  xmlSetProp(resources_node, (pcmkXmlStr) "blocked", (pcmkXmlStr) s);
622  free(s);
623 
624  return pcmk_rc_ok;
625 }
626 
627 PCMK__OUTPUT_ARGS("cluster-dc", "struct pe_node_t *", "const char *", "const char *", "char *")
628 int
629 pe__cluster_dc_html(pcmk__output_t *out, va_list args) {
630  xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
631 
632  pe_node_t *dc = va_arg(args, pe_node_t *);
633  const char *quorum = va_arg(args, const char *);
634  const char *dc_version_s = va_arg(args, const char *);
635  char *dc_name = va_arg(args, char *);
636 
637  pcmk_create_html_node(node, "span", NULL, "bold", "Current DC: ");
638 
639  if (dc) {
640  if (crm_is_true(quorum)) {
641  char *buf = crm_strdup_printf("%s (version %s) - partition with quorum",
642  dc_name, dc_version_s ? dc_version_s : "unknown");
643  pcmk_create_html_node(node, "span", NULL, NULL, buf);
644  free(buf);
645  } else {
646  char *buf = crm_strdup_printf("%s (version %s) - partition",
647  dc_name, dc_version_s ? dc_version_s : "unknown");
648  pcmk_create_html_node(node, "span", NULL, NULL, buf);
649  free(buf);
650 
651  pcmk_create_html_node(node, "span", NULL, "warning", "WITHOUT");
652  pcmk_create_html_node(node, "span", NULL, NULL, "quorum");
653  }
654  } else {
655  pcmk_create_html_node(node ,"span", NULL, "warning", "NONE");
656  }
657 
658  return pcmk_rc_ok;
659 }
660 
661 PCMK__OUTPUT_ARGS("cluster-dc", "struct pe_node_t *", "const char *", "const char *", "char *")
662 int
663 pe__cluster_dc_text(pcmk__output_t *out, va_list args) {
664  pe_node_t *dc = va_arg(args, pe_node_t *);
665  const char *quorum = va_arg(args, const char *);
666  const char *dc_version_s = va_arg(args, const char *);
667  char *dc_name = va_arg(args, char *);
668 
669  if (dc) {
670  out->list_item(out, "Current DC", "%s (version %s) - partition %s quorum",
671  dc_name, dc_version_s ? dc_version_s : "unknown",
672  crm_is_true(quorum) ? "with" : "WITHOUT");
673  } else {
674  out->list_item(out, "Current DC", "NONE");
675  }
676 
677  return pcmk_rc_ok;
678 }
679 
680 PCMK__OUTPUT_ARGS("cluster-dc", "struct pe_node_t *", "const char *", "const char *", "char *")
681 int
682 pe__cluster_dc_xml(pcmk__output_t *out, va_list args) {
683  xmlNodePtr node = pcmk__output_create_xml_node(out, "current_dc");
684 
685  pe_node_t *dc = va_arg(args, pe_node_t *);
686  const char *quorum = va_arg(args, const char *);
687  const char *dc_version_s = va_arg(args, const char *);
688  char *dc_name G_GNUC_UNUSED = va_arg(args, char *);
689 
690  if (dc) {
691  xmlSetProp(node, (pcmkXmlStr) "present", (pcmkXmlStr) "true");
692  xmlSetProp(node, (pcmkXmlStr) "version", (pcmkXmlStr) (dc_version_s ? dc_version_s : ""));
693  xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) dc->details->uname);
694  xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) dc->details->id);
695  xmlSetProp(node, (pcmkXmlStr) "with_quorum", (pcmkXmlStr) (crm_is_true(quorum) ? "true" : "false"));
696  } else {
697  xmlSetProp(node, (pcmkXmlStr) "present", (pcmkXmlStr) "false");
698  }
699 
700  return pcmk_rc_ok;
701 }
702 
703 PCMK__OUTPUT_ARGS("maint-mode")
704 int
706  fprintf(out->dest, "\n *** Resource management is DISABLED ***");
707  fprintf(out->dest, "\n The cluster will not attempt to start, stop or recover services");
708  fprintf(out->dest, "\n");
709  return pcmk_rc_ok;
710 }
711 
712 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
713 int
715  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
716 
717  out->list_item(out, NULL, "STONITH of failed nodes %s",
718  is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
719 
720  out->list_item(out, NULL, "Cluster is %s",
721  is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
722 
723  switch (data_set->no_quorum_policy) {
724  case no_quorum_freeze:
725  out->list_item(out, NULL, "No quorum policy: Freeze resources");
726  break;
727 
728  case no_quorum_stop:
729  out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
730  break;
731 
732  case no_quorum_ignore:
733  out->list_item(out, NULL, "No quorum policy: Ignore");
734  break;
735 
736  case no_quorum_suicide:
737  out->list_item(out, NULL, "No quorum policy: Suicide");
738  break;
739  }
740 
741  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
742  xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
743 
744  pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
745  pcmk_create_html_node(node, "span", NULL, "bold", "DISABLED");
746  pcmk_create_html_node(node, "span", NULL, NULL,
747  " (the cluster will not attempt to start, stop, or recover services)");
748  } else {
749  out->list_item(out, NULL, "Resource management: enabled");
750  }
751 
752  return pcmk_rc_ok;
753 }
754 
755 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
756 int
758  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
759 
760  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
761  out->info(out, "Resource management is DISABLED. The cluster will not attempt to start, stop or recover services.");
762  return pcmk_rc_ok;
763  } else {
764  return pcmk_rc_no_output;
765  }
766 }
767 
768 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
769 int
771  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
772 
773  out->list_item(out, NULL, "STONITH of failed nodes %s",
774  is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
775 
776  out->list_item(out, NULL, "Cluster is %s",
777  is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
778 
779  switch (data_set->no_quorum_policy) {
780  case no_quorum_freeze:
781  out->list_item(out, NULL, "No quorum policy: Freeze resources");
782  break;
783 
784  case no_quorum_stop:
785  out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
786  break;
787 
788  case no_quorum_ignore:
789  out->list_item(out, NULL, "No quorum policy: Ignore");
790  break;
791 
792  case no_quorum_suicide:
793  out->list_item(out, NULL, "No quorum policy: Suicide");
794  break;
795  }
796 
797  return pcmk_rc_ok;
798 }
799 
800 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
801 int
803  xmlNodePtr node = pcmk__output_create_xml_node(out, "cluster_options");
804  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
805 
806  xmlSetProp(node, (pcmkXmlStr) "stonith-enabled",
807  (pcmkXmlStr) (is_set(data_set->flags, pe_flag_stonith_enabled) ? "true" : "false"));
808  xmlSetProp(node, (pcmkXmlStr) "symmetric-cluster",
809  (pcmkXmlStr) (is_set(data_set->flags, pe_flag_symmetric_cluster) ? "true" : "false"));
810 
811  switch (data_set->no_quorum_policy) {
812  case no_quorum_freeze:
813  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "freeze");
814  break;
815 
816  case no_quorum_stop:
817  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "stop");
818  break;
819 
820  case no_quorum_ignore:
821  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "ignore");
822  break;
823 
824  case no_quorum_suicide:
825  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "suicide");
826  break;
827  }
828 
829  xmlSetProp(node, (pcmkXmlStr) "maintenance-mode",
830  (pcmkXmlStr) (is_set(data_set->flags, pe_flag_maintenance_mode) ? "true" : "false"));
831 
832  return pcmk_rc_ok;
833 }
834 
835 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
836 int
838  xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
839  const char *stack_s = va_arg(args, const char *);
840 
841  pcmk_create_html_node(node, "span", NULL, "bold", "Stack: ");
842  pcmk_create_html_node(node, "span", NULL, NULL, stack_s);
843 
844  return pcmk_rc_ok;
845 }
846 
847 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
848 int
850  const char *stack_s = va_arg(args, const char *);
851  out->list_item(out, "Stack", "%s", stack_s);
852  return pcmk_rc_ok;
853 }
854 
855 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
856 int
858  xmlNodePtr node = pcmk__output_create_xml_node(out, "stack");
859  const char *stack_s = va_arg(args, const char *);
860 
861  xmlSetProp(node, (pcmkXmlStr) "type", (pcmkXmlStr) stack_s);
862 
863  return pcmk_rc_ok;
864 }
865 
866 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
867 int
869  xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "li");
870  xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "li");
871 
872  const char *last_written = va_arg(args, const char *);
873  const char *user = va_arg(args, const char *);
874  const char *client = va_arg(args, const char *);
875  const char *origin = va_arg(args, const char *);
876 
877  char *buf = last_changed_string(last_written, user, client, origin);
878 
879  pcmk_create_html_node(updated_node, "span", NULL, "bold", "Last updated: ");
880  pcmk_create_html_node(updated_node, "span", NULL, NULL,
881  pcmk__epoch2str(NULL));
882 
883  pcmk_create_html_node(changed_node, "span", NULL, "bold", "Last change: ");
884  pcmk_create_html_node(changed_node, "span", NULL, NULL, buf);
885 
886  free(buf);
887  return pcmk_rc_ok;
888 }
889 
890 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
891 int
893  xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "last_update");
894  xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "last_change");
895 
896  const char *last_written = va_arg(args, const char *);
897  const char *user = va_arg(args, const char *);
898  const char *client = va_arg(args, const char *);
899  const char *origin = va_arg(args, const char *);
900 
901  xmlSetProp(updated_node, (pcmkXmlStr) "time",
902  (pcmkXmlStr) pcmk__epoch2str(NULL));
903  xmlSetProp(changed_node, (pcmkXmlStr) "time", (pcmkXmlStr) (last_written ? last_written : ""));
904  xmlSetProp(changed_node, (pcmkXmlStr) "user", (pcmkXmlStr) (user ? user : ""));
905  xmlSetProp(changed_node, (pcmkXmlStr) "client", (pcmkXmlStr) (client ? client : ""));
906  xmlSetProp(changed_node, (pcmkXmlStr) "origin", (pcmkXmlStr) (origin ? origin : ""));
907 
908  return pcmk_rc_ok;
909 }
910 
911 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
912 int
914  const char *last_written = va_arg(args, const char *);
915  const char *user = va_arg(args, const char *);
916  const char *client = va_arg(args, const char *);
917  const char *origin = va_arg(args, const char *);
918 
919  char *buf = last_changed_string(last_written, user, client, origin);
920 
921  out->list_item(out, "Last updated", "%s", pcmk__epoch2str(NULL));
922  out->list_item(out, "Last change", " %s", buf);
923 
924  free(buf);
925  return pcmk_rc_ok;
926 }
927 
928 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
929 int
931  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
932  char *s = failed_action_string(xml_op);
933 
934  out->list_item(out, NULL, "%s", s);
935  free(s);
936  return pcmk_rc_ok;
937 }
938 
939 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
940 int
942  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
943 
944  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
945  const char *last = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
946  int rc = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_RC), "0");
947  int status = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS), "0");
948  const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
949 
950  char *rc_s = crm_itoa(rc);
951  char *reason_s = crm_xml_escape(exit_reason ? exit_reason : "none");
952  xmlNodePtr node = pcmk__output_create_xml_node(out, "failure");
953 
954  xmlSetProp(node, (pcmkXmlStr) (op_key ? "op_key" : "id"),
955  (pcmkXmlStr) (op_key ? op_key : "id"));
956  xmlSetProp(node, (pcmkXmlStr) "node",
958  xmlSetProp(node, (pcmkXmlStr) "exitstatus",
959  (pcmkXmlStr) services_ocf_exitcode_str(rc));
960  xmlSetProp(node, (pcmkXmlStr) "exitreason", (pcmkXmlStr) reason_s);
961  xmlSetProp(node, (pcmkXmlStr) "exitcode", (pcmkXmlStr) rc_s);
962  xmlSetProp(node, (pcmkXmlStr) "call",
964  xmlSetProp(node, (pcmkXmlStr) "status",
965  (pcmkXmlStr) services_lrm_status_str(status));
966 
967  if (last) {
968  guint interval_ms = 0;
969  char *s = NULL;
970  time_t when = crm_parse_int(last, "0");
971  crm_time_t *crm_when = crm_time_new(NULL);
972  char *rc_change = NULL;
973 
974  crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
975  s = crm_itoa(interval_ms);
976 
977  crm_time_set_timet(crm_when, &when);
979 
980  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_CHANGE, (pcmkXmlStr) rc_change);
981  xmlSetProp(node, (pcmkXmlStr) "queued",
983  xmlSetProp(node, (pcmkXmlStr) "exec",
985  xmlSetProp(node, (pcmkXmlStr) "interval", (pcmkXmlStr) s);
986  xmlSetProp(node, (pcmkXmlStr) "task",
988 
989  free(s);
990  free(rc_change);
991  crm_time_free(crm_when);
992  }
993 
994  free(reason_s);
995  free(rc_s);
996  return pcmk_rc_ok;
997 }
998 
999 PCMK__OUTPUT_ARGS("node", "struct pe_node_t *", "unsigned int", "gboolean", "const char *", "gboolean", "gboolean", "gboolean", "GListPtr")
1000 int
1001 pe__node_html(pcmk__output_t *out, va_list args) {
1002  pe_node_t *node = va_arg(args, pe_node_t *);
1003  unsigned int print_opts = va_arg(args, unsigned int);
1004  gboolean full = va_arg(args, gboolean);
1005  const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1006  gboolean print_clone_detail = va_arg(args, gboolean);
1007  gboolean print_brief = va_arg(args, gboolean);
1008  gboolean group_by_node = va_arg(args, gboolean);
1009  GListPtr only_show = va_arg(args, GListPtr);
1010 
1011  char *node_name = pe__node_display_name(node, print_clone_detail);
1012  char *buf = crm_strdup_printf("Node: %s", node_name);
1013 
1014  if (full) {
1015  xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li");
1016 
1017  pcmk_create_html_node(item_node, "span", NULL, NULL, buf);
1018 
1019  if (node->details->standby_onfail && node->details->online) {
1020  pcmk_create_html_node(item_node, "span", NULL, "standby", " standby (on-fail)");
1021  } else if (node->details->standby && node->details->online) {
1022  char *s = crm_strdup_printf(" standby%s", node->details->running_rsc ? " (with active resources)" : "");
1023  pcmk_create_html_node(item_node, "span", NULL, " standby", s);
1024  free(s);
1025  } else if (node->details->standby) {
1026  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (standby)");
1027  } else if (node->details->maintenance && node->details->online) {
1028  pcmk_create_html_node(item_node, "span", NULL, "maint", " maintenance");
1029  } else if (node->details->maintenance) {
1030  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (maintenance)");
1031  } else if (node->details->online) {
1032  pcmk_create_html_node(item_node, "span", NULL, "online", " online");
1033  } else {
1034  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE");
1035  }
1036  if (print_brief && group_by_node) {
1037  out->begin_list(out, NULL, NULL, NULL);
1038  pe__rscs_brief_output(out, node->details->running_rsc, print_opts | pe_print_rsconly,
1039  FALSE);
1040  out->end_list(out);
1041 
1042  } else if (group_by_node) {
1043  GListPtr lpc2 = NULL;
1044 
1045  out->begin_list(out, NULL, NULL, NULL);
1046  for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) {
1047  pe_resource_t *rsc = (pe_resource_t *) lpc2->data;
1048  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly, rsc, only_show);
1049  }
1050  out->end_list(out);
1051  }
1052  } else {
1053  out->begin_list(out, NULL, NULL, "%s", buf);
1054  }
1055 
1056  free(buf);
1057  free(node_name);
1058  return pcmk_rc_ok;
1059 }
1060 
1061 PCMK__OUTPUT_ARGS("node", "struct pe_node_t *", "unsigned int", "gboolean", "const char *", "gboolean", "gboolean", "gboolean", "GListPtr")
1062 int
1063 pe__node_text(pcmk__output_t *out, va_list args) {
1064  pe_node_t *node = va_arg(args, pe_node_t *);
1065  unsigned int print_opts = va_arg(args, unsigned int);
1066  gboolean full = va_arg(args, gboolean);
1067  const char *node_mode = va_arg(args, const char *);
1068  gboolean print_clone_detail = va_arg(args, gboolean);
1069  gboolean print_brief = va_arg(args, gboolean);
1070  gboolean group_by_node = va_arg(args, gboolean);
1071  GListPtr only_show = va_arg(args, GListPtr);
1072 
1073  if (full) {
1074  char *node_name = pe__node_display_name(node, print_clone_detail);
1075  char *buf = NULL;
1076 
1077  /* Print the node name and status */
1078  if (pe__is_guest_node(node)) {
1079  buf = crm_strdup_printf("GuestNode %s: %s", node_name, node_mode);
1080  } else if (pe__is_remote_node(node)) {
1081  buf = crm_strdup_printf("RemoteNode %s: %s", node_name, node_mode);
1082  } else {
1083  buf = crm_strdup_printf("Node %s: %s", node_name, node_mode);
1084  }
1085 
1086  /* If we're grouping by node, print its resources */
1087  if (group_by_node) {
1088  out->begin_list(out, NULL, NULL, "%s", buf);
1089  out->begin_list(out, NULL, NULL, "Resources");
1090 
1091  if (print_brief) {
1093  print_opts | pe_print_rsconly, FALSE);
1094  } else {
1095  GListPtr gIter2 = NULL;
1096 
1097  for (gIter2 = node->details->running_rsc; gIter2 != NULL; gIter2 = gIter2->next) {
1098  pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1099  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly, rsc, only_show);
1100  }
1101  }
1102 
1103  out->end_list(out);
1104  out->end_list(out);
1105  } else {
1106  out->list_item(out, NULL, "%s", buf);
1107  }
1108 
1109  free(buf);
1110  free(node_name);
1111  } else {
1112  out->begin_list(out, NULL, NULL, "Node: %s", pe__node_display_name(node, print_clone_detail));
1113  }
1114 
1115  return pcmk_rc_ok;
1116 }
1117 
1118 PCMK__OUTPUT_ARGS("node", "struct pe_node_t *", "unsigned int", "gboolean", "const char *", "gboolean", "gboolean", "gboolean", "GListPtr")
1119 int
1120 pe__node_xml(pcmk__output_t *out, va_list args) {
1121  pe_node_t *node = va_arg(args, pe_node_t *);
1122  unsigned int print_opts = va_arg(args, unsigned int);
1123  gboolean full = va_arg(args, gboolean);
1124  const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1125  gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
1126  gboolean print_brief G_GNUC_UNUSED = va_arg(args, gboolean);
1127  gboolean group_by_node = va_arg(args, gboolean);
1128  GListPtr only_show = va_arg(args, GListPtr);
1129 
1130  if (full) {
1131  const char *node_type = "unknown";
1132  char *length_s = crm_itoa(g_list_length(node->details->running_rsc));
1133 
1134  switch (node->details->type) {
1135  case node_member:
1136  node_type = "member";
1137  break;
1138  case node_remote:
1139  node_type = "remote";
1140  break;
1141  case node_ping:
1142  node_type = "ping";
1143  break;
1144  }
1145  pe__name_and_nvpairs_xml(out, true, "node", 13,
1146  "name", node->details->uname,
1147  "id", node->details->id,
1148  "online", node->details->online ? "true" : "false",
1149  "standby", node->details->standby ? "true" : "false",
1150  "standby_onfail", node->details->standby_onfail ? "true" : "false",
1151  "maintenance", node->details->maintenance ? "true" : "false",
1152  "pending", node->details->pending ? "true" : "false",
1153  "unclean", node->details->unclean ? "true" : "false",
1154  "shutdown", node->details->shutdown ? "true" : "false",
1155  "expected_up", node->details->expected_up ? "true" : "false",
1156  "is_dc", node->details->is_dc ? "true" : "false",
1157  "resources_running", length_s,
1158  "type", node_type);
1159 
1160  if (pe__is_guest_node(node)) {
1161  xmlNodePtr xml_node = pcmk__output_xml_peek_parent(out);
1162  xmlSetProp(xml_node, (pcmkXmlStr) "id_as_resource",
1164  }
1165 
1166  if (group_by_node) {
1167  GListPtr lpc = NULL;
1168 
1169  for (lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) {
1170  pe_resource_t *rsc = (pe_resource_t *) lpc->data;
1171  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly, rsc, only_show);
1172  }
1173  }
1174 
1175  free(length_s);
1176 
1177  out->end_list(out);
1178  } else {
1179  xmlNodePtr parent = pcmk__output_xml_create_parent(out, "node");
1180  xmlSetProp(parent, (pcmkXmlStr) "name", (pcmkXmlStr) node->details->uname);
1181  }
1182 
1183  return pcmk_rc_ok;
1184 }
1185 
1186 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1187 int
1189  const char *name = va_arg(args, const char *);
1190  const char *value = va_arg(args, const char *);
1191  gboolean add_extra = va_arg(args, gboolean);
1192  int expected_score = va_arg(args, int);
1193 
1194 
1195  if (add_extra) {
1196  int v = crm_parse_int(value, "0");
1197 
1198  if (v <= 0) {
1199  out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is lost", name, value);
1200  } else if (v < expected_score) {
1201  out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is degraded (Expected=%d)", name, value, expected_score);
1202  } else {
1203  out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1204  }
1205  } else {
1206  out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1207  }
1208 
1209  return pcmk_rc_ok;
1210 }
1211 
1212 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1213 int
1215  const char *name = va_arg(args, const char *);
1216  const char *value = va_arg(args, const char *);
1217  gboolean add_extra = va_arg(args, gboolean);
1218  int expected_score = va_arg(args, int);
1219 
1220  if (add_extra) {
1221  int v = crm_parse_int(value, "0");
1222  char *s = crm_strdup_printf("%s: %s", name, value);
1223  xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li");
1224 
1225  pcmk_create_html_node(item_node, "span", NULL, NULL, s);
1226  free(s);
1227 
1228  if (v <= 0) {
1229  pcmk_create_html_node(item_node, "span", NULL, "bold", "(connectivity is lost)");
1230  } else if (v < expected_score) {
1231  char *buf = crm_strdup_printf("(connectivity is degraded -- expected %d", expected_score);
1232  pcmk_create_html_node(item_node, "span", NULL, "bold", buf);
1233  free(buf);
1234  }
1235  } else {
1236  out->list_item(out, NULL, "%s: %s", name, value);
1237  }
1238 
1239  return pcmk_rc_ok;
1240 }
1241 
1242 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1243 int
1245  const char *name = va_arg(args, const char *);
1246  const char *value = va_arg(args, const char *);
1247  gboolean add_extra = va_arg(args, gboolean);
1248  int expected_score = va_arg(args, int);
1249 
1250  xmlNodePtr node = pcmk__output_create_xml_node(out, "attribute");
1251  xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) name);
1252  xmlSetProp(node, (pcmkXmlStr) "value", (pcmkXmlStr) value);
1253 
1254  if (add_extra) {
1255  char *buf = crm_itoa(expected_score);
1256  xmlSetProp(node, (pcmkXmlStr) "expected", (pcmkXmlStr) buf);
1257  free(buf);
1258  }
1259 
1260  return pcmk_rc_ok;
1261 }
1262 
1263 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1264 int
1265 pe__node_list_html(pcmk__output_t *out, va_list args) {
1266  GListPtr nodes = va_arg(args, GListPtr);
1267  GListPtr only_show = va_arg(args, GListPtr);
1268  unsigned int print_opts = va_arg(args, unsigned int);
1269  gboolean print_clone_detail = va_arg(args, gboolean);
1270  gboolean print_brief = va_arg(args, gboolean);
1271  gboolean group_by_node = va_arg(args, gboolean);
1272 
1273  gboolean printed_header = FALSE;
1274 
1275  for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1276  pe_node_t *node = (pe_node_t *) gIter->data;
1277 
1278  if (!pcmk__str_in_list(only_show, node->details->uname)) {
1279  continue;
1280  }
1281 
1282  if (printed_header == FALSE) {
1283  printed_header = TRUE;
1284  out->begin_list(out, NULL, NULL, "Node List");
1285  }
1286 
1287  out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1288  print_brief, group_by_node, only_show);
1289  }
1290 
1291  if (printed_header == TRUE) {
1292  out->end_list(out);
1293  }
1294 
1295  return pcmk_rc_ok;
1296 }
1297 
1298 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1299 int
1300 pe__node_list_text(pcmk__output_t *out, va_list args) {
1301  GListPtr nodes = va_arg(args, GListPtr);
1302  GListPtr only_show = va_arg(args, GListPtr);
1303  unsigned int print_opts = va_arg(args, unsigned int);
1304  gboolean print_clone_detail = va_arg(args, gboolean);
1305  gboolean print_brief = va_arg(args, gboolean);
1306  gboolean group_by_node = va_arg(args, gboolean);
1307 
1308  /* space-separated lists of node names */
1309  char *online_nodes = NULL;
1310  char *online_remote_nodes = NULL;
1311  char *online_guest_nodes = NULL;
1312  char *offline_nodes = NULL;
1313  char *offline_remote_nodes = NULL;
1314 
1315  int rc = pcmk_rc_no_output;
1316  gboolean printed_header = FALSE;
1317 
1318  for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1319  pe_node_t *node = (pe_node_t *) gIter->data;
1320  const char *node_mode = NULL;
1321  char *node_name = pe__node_display_name(node, print_clone_detail);
1322 
1323  if (!pcmk__str_in_list(only_show, node->details->uname)) {
1324  free(node_name);
1325  continue;
1326  }
1327 
1328  if (printed_header == FALSE) {
1329  out->begin_list(out, NULL, NULL, "Node List");
1330  rc = pcmk_rc_ok;
1331  printed_header = TRUE;
1332  }
1333 
1334  /* Get node mode */
1335  if (node->details->unclean) {
1336  if (node->details->online) {
1337  node_mode = "UNCLEAN (online)";
1338 
1339  } else if (node->details->pending) {
1340  node_mode = "UNCLEAN (pending)";
1341 
1342  } else {
1343  node_mode = "UNCLEAN (offline)";
1344  }
1345 
1346  } else if (node->details->pending) {
1347  node_mode = "pending";
1348 
1349  } else if (node->details->standby_onfail && node->details->online) {
1350  node_mode = "standby (on-fail)";
1351 
1352  } else if (node->details->standby) {
1353  if (node->details->online) {
1354  if (node->details->running_rsc) {
1355  node_mode = "standby (with active resources)";
1356  } else {
1357  node_mode = "standby";
1358  }
1359  } else {
1360  node_mode = "OFFLINE (standby)";
1361  }
1362 
1363  } else if (node->details->maintenance) {
1364  if (node->details->online) {
1365  node_mode = "maintenance";
1366  } else {
1367  node_mode = "OFFLINE (maintenance)";
1368  }
1369 
1370  } else if (node->details->online) {
1371  node_mode = "online";
1372  if (group_by_node == FALSE) {
1373  if (pe__is_guest_node(node)) {
1374  online_guest_nodes = pcmk__add_word(online_guest_nodes,
1375  node_name);
1376  } else if (pe__is_remote_node(node)) {
1377  online_remote_nodes = pcmk__add_word(online_remote_nodes,
1378  node_name);
1379  } else {
1380  online_nodes = pcmk__add_word(online_nodes, node_name);
1381  }
1382  free(node_name);
1383  continue;
1384  }
1385 
1386  } else {
1387  node_mode = "OFFLINE";
1388  if (group_by_node == FALSE) {
1389  if (pe__is_remote_node(node)) {
1390  offline_remote_nodes = pcmk__add_word(offline_remote_nodes,
1391  node_name);
1392  } else if (pe__is_guest_node(node)) {
1393  /* ignore offline guest nodes */
1394  } else {
1395  offline_nodes = pcmk__add_word(offline_nodes, node_name);
1396  }
1397  free(node_name);
1398  continue;
1399  }
1400  }
1401 
1402  /* If we get here, node is in bad state, or we're grouping by node */
1403  out->message(out, "node", node, print_opts, TRUE, node_mode, print_clone_detail,
1404  print_brief, group_by_node, only_show);
1405  free(node_name);
1406  }
1407 
1408  /* If we're not grouping by node, summarize nodes by status */
1409  if (online_nodes) {
1410  out->list_item(out, "Online", "[%s ]", online_nodes);
1411  free(online_nodes);
1412  }
1413  if (offline_nodes) {
1414  out->list_item(out, "OFFLINE", "[%s ]", offline_nodes);
1415  free(offline_nodes);
1416  }
1417  if (online_remote_nodes) {
1418  out->list_item(out, "RemoteOnline", "[%s ]", online_remote_nodes);
1419  free(online_remote_nodes);
1420  }
1421  if (offline_remote_nodes) {
1422  out->list_item(out, "RemoteOFFLINE", "[%s ]", offline_remote_nodes);
1423  free(offline_remote_nodes);
1424  }
1425  if (online_guest_nodes) {
1426  out->list_item(out, "GuestOnline", "[%s ]", online_guest_nodes);
1427  free(online_guest_nodes);
1428  }
1429 
1430  if (printed_header == TRUE) {
1431  out->end_list(out);
1432  }
1433 
1434  return rc;
1435 }
1436 
1437 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1438 int
1439 pe__node_list_xml(pcmk__output_t *out, va_list args) {
1440  GListPtr nodes = va_arg(args, GListPtr);
1441  GListPtr only_show = va_arg(args, GListPtr);
1442  unsigned int print_opts = va_arg(args, unsigned int);
1443  gboolean print_clone_detail = va_arg(args, gboolean);
1444  gboolean print_brief = va_arg(args, gboolean);
1445  gboolean group_by_node = va_arg(args, gboolean);
1446 
1447  out->begin_list(out, NULL, NULL, "nodes");
1448  for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1449  pe_node_t *node = (pe_node_t *) gIter->data;
1450 
1451  if (!pcmk__str_in_list(only_show, node->details->uname)) {
1452  continue;
1453  }
1454 
1455  out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1456  print_brief, group_by_node, only_show);
1457  }
1458  out->end_list(out);
1459 
1460  return pcmk_rc_ok;
1461 }
1462 
1463 PCMK__OUTPUT_ARGS("op-history", "struct xmlNode *", "const char *", "const char *", "int", "gboolean")
1464 int
1466  xmlNode *xml_op = va_arg(args, xmlNode *);
1467  const char *task = va_arg(args, const char *);
1468  const char *interval_ms_s = va_arg(args, const char *);
1469  int rc = va_arg(args, int);
1470  gboolean print_timing = va_arg(args, gboolean);
1471 
1472  char *buf = op_history_string(xml_op, task, interval_ms_s, rc, print_timing);
1473 
1474  out->list_item(out, NULL, "%s", buf);
1475 
1476  free(buf);
1477  return pcmk_rc_ok;
1478 }
1479 
1480 PCMK__OUTPUT_ARGS("op-history", "struct xmlNode *", "const char *", "const char *", "int", "gboolean")
1481 int
1482 pe__op_history_xml(pcmk__output_t *out, va_list args) {
1483  xmlNode *xml_op = va_arg(args, xmlNode *);
1484  const char *task = va_arg(args, const char *);
1485  const char *interval_ms_s = va_arg(args, const char *);
1486  int rc = va_arg(args, int);
1487  gboolean print_timing = va_arg(args, gboolean);
1488 
1489  char *rc_s = NULL;
1490 
1491  xmlNodePtr node = pcmk__output_create_xml_node(out, "operation_history");
1492 
1493  xmlSetProp(node, (pcmkXmlStr) "call",
1495  xmlSetProp(node, (pcmkXmlStr) "task", (pcmkXmlStr) task);
1496 
1497  if (interval_ms_s && safe_str_neq(interval_ms_s, "0")) {
1498  char *s = crm_strdup_printf("%sms", interval_ms_s);
1499  xmlSetProp(node, (pcmkXmlStr) "interval", (pcmkXmlStr) s);
1500  free(s);
1501  }
1502 
1503  if (print_timing) {
1504  const char *value = NULL;
1505 
1506  value = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
1507  if (value) {
1508  time_t int_value = (time_t) crm_parse_int(value, NULL);
1509  if (int_value > 0) {
1510  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_CHANGE,
1511  (pcmkXmlStr) pcmk__epoch2str(&int_value));
1512  }
1513  }
1514 
1515  value = crm_element_value(xml_op, XML_RSC_OP_LAST_RUN);
1516  if (value) {
1517  time_t int_value = (time_t) crm_parse_int(value, NULL);
1518  if (int_value > 0) {
1519  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_RUN,
1520  (pcmkXmlStr) pcmk__epoch2str(&int_value));
1521  }
1522  }
1523 
1524  value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
1525  if (value) {
1526  char *s = crm_strdup_printf("%sms", value);
1527  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_T_EXEC, (pcmkXmlStr) s);
1528  free(s);
1529  }
1530  value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
1531  if (value) {
1532  char *s = crm_strdup_printf("%sms", value);
1533  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_T_QUEUE, (pcmkXmlStr) s);
1534  free(s);
1535  }
1536  }
1537 
1538  rc_s = crm_itoa(rc);
1539  xmlSetProp(node, (pcmkXmlStr) "rc", (pcmkXmlStr) rc_s);
1540  xmlSetProp(node, (pcmkXmlStr) "rc_text", (pcmkXmlStr) services_ocf_exitcode_str(rc));
1541  free(rc_s);
1542  return pcmk_rc_ok;
1543 }
1544 
1545 PCMK__OUTPUT_ARGS("resource-history", "struct pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
1546 int
1548  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1549  const char *rsc_id = va_arg(args, const char *);
1550  gboolean all = va_arg(args, gboolean);
1551  int failcount = va_arg(args, int);
1552  time_t last_failure = va_arg(args, int);
1553  gboolean as_header = va_arg(args, gboolean);
1554 
1555  char *buf = resource_history_string(rsc, rsc_id, all, failcount, last_failure);
1556 
1557  if (as_header) {
1558  out->begin_list(out, NULL, NULL, "%s", buf);
1559  } else {
1560  out->list_item(out, NULL, "%s", buf);
1561  }
1562 
1563  free(buf);
1564  return pcmk_rc_ok;
1565 }
1566 
1567 PCMK__OUTPUT_ARGS("resource-history", "struct pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
1568 int
1570  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1571  const char *rsc_id = va_arg(args, const char *);
1572  gboolean all = va_arg(args, gboolean);
1573  int failcount = va_arg(args, int);
1574  time_t last_failure = va_arg(args, int);
1575  gboolean as_header = va_arg(args, gboolean);
1576 
1577  xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource_history");
1578  xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) rsc_id);
1579 
1580  if (rsc == NULL) {
1581  xmlSetProp(node, (pcmkXmlStr) "orphan", (pcmkXmlStr) "true");
1582  } else if (all || failcount || last_failure > 0) {
1583  char *migration_s = crm_itoa(rsc->migration_threshold);
1584 
1585  xmlSetProp(node, (pcmkXmlStr) "orphan", (pcmkXmlStr) "false");
1586  xmlSetProp(node, (pcmkXmlStr) "migration-threshold",
1587  (pcmkXmlStr) migration_s);
1588  free(migration_s);
1589 
1590  if (failcount > 0) {
1591  char *s = crm_itoa(failcount);
1592 
1593  xmlSetProp(node, (pcmkXmlStr) PCMK__FAIL_COUNT_PREFIX,
1594  (pcmkXmlStr) s);
1595  free(s);
1596  }
1597 
1598  if (last_failure > 0) {
1599  xmlSetProp(node, (pcmkXmlStr) PCMK__LAST_FAILURE_PREFIX,
1600  (pcmkXmlStr) pcmk__epoch2str(&last_failure));
1601  }
1602  }
1603 
1604  if (as_header == FALSE) {
1606  }
1607 
1608  return pcmk_rc_ok;
1609 }
1610 
1611 PCMK__OUTPUT_ARGS("ticket", "struct pe_ticket_t *")
1612 int
1613 pe__ticket_html(pcmk__output_t *out, va_list args) {
1614  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1615 
1616  if (ticket->last_granted > -1) {
1617  char *time = pcmk_format_named_time("last-granted", ticket->last_granted);
1618  out->list_item(out, NULL, "%s:\t%s%s %s", ticket->id,
1619  ticket->granted ? "granted" : "revoked",
1620  ticket->standby ? " [standby]" : "",
1621  time);
1622  free(time);
1623  } else {
1624  out->list_item(out, NULL, "%s:\t%s%s", ticket->id,
1625  ticket->granted ? "granted" : "revoked",
1626  ticket->standby ? " [standby]" : "");
1627  }
1628 
1629  return pcmk_rc_ok;
1630 }
1631 
1632 PCMK__OUTPUT_ARGS("ticket", "struct pe_ticket_t *")
1633 int
1634 pe__ticket_text(pcmk__output_t *out, va_list args) {
1635  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1636 
1637  if (ticket->last_granted > -1) {
1638  char *time = pcmk_format_named_time("last-granted", ticket->last_granted);
1639  out->list_item(out, ticket->id, "\t%s%s %s",
1640  ticket->granted ? "granted" : "revoked",
1641  ticket->standby ? " [standby]" : "",
1642  time);
1643  free(time);
1644  } else {
1645  out->list_item(out, ticket->id, "\t%s%s",
1646  ticket->granted ? "granted" : "revoked",
1647  ticket->standby ? " [standby]" : "");
1648  }
1649 
1650  return pcmk_rc_ok;
1651 }
1652 
1653 PCMK__OUTPUT_ARGS("ticket", "struct pe_ticket_t *")
1654 int
1655 pe__ticket_xml(pcmk__output_t *out, va_list args) {
1656  xmlNodePtr node = NULL;
1657 
1658  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1659 
1660  node = pcmk__output_create_xml_node(out, "ticket");
1661  xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) ticket->id);
1662  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) (ticket->granted ? "granted" : "revoked"));
1663  xmlSetProp(node, (pcmkXmlStr) "standby", (pcmkXmlStr) (ticket->standby ? "true" : "false"));
1664 
1665  if (ticket->last_granted > -1) {
1666  xmlSetProp(node, (pcmkXmlStr) "last-granted",
1668  }
1669 
1670  return pcmk_rc_ok;
1671 }
1672 
1673 static pcmk__message_entry_t fmt_functions[] = {
1674  { "ban", "html", pe__ban_html },
1675  { "ban", "log", pe__ban_text },
1676  { "ban", "text", pe__ban_text },
1677  { "ban", "xml", pe__ban_xml },
1678  { "bundle", "xml", pe__bundle_xml },
1679  { "bundle", "html", pe__bundle_html },
1680  { "bundle", "text", pe__bundle_text },
1681  { "bundle", "log", pe__bundle_text },
1682  { "clone", "xml", pe__clone_xml },
1683  { "clone", "html", pe__clone_html },
1684  { "clone", "text", pe__clone_text },
1685  { "clone", "log", pe__clone_text },
1686  { "cluster-counts", "html", pe__cluster_counts_html },
1687  { "cluster-counts", "log", pe__cluster_counts_text },
1688  { "cluster-counts", "text", pe__cluster_counts_text },
1689  { "cluster-counts", "xml", pe__cluster_counts_xml },
1690  { "cluster-dc", "html", pe__cluster_dc_html },
1691  { "cluster-dc", "log", pe__cluster_dc_text },
1692  { "cluster-dc", "text", pe__cluster_dc_text },
1693  { "cluster-dc", "xml", pe__cluster_dc_xml },
1694  { "cluster-options", "html", pe__cluster_options_html },
1695  { "cluster-options", "log", pe__cluster_options_log },
1696  { "cluster-options", "text", pe__cluster_options_text },
1697  { "cluster-options", "xml", pe__cluster_options_xml },
1698  { "cluster-summary", "html", pe__cluster_summary_html },
1699  { "cluster-summary", "log", pe__cluster_summary },
1700  { "cluster-summary", "text", pe__cluster_summary },
1701  { "cluster-summary", "xml", pe__cluster_summary },
1702  { "cluster-stack", "html", pe__cluster_stack_html },
1703  { "cluster-stack", "log", pe__cluster_stack_text },
1704  { "cluster-stack", "text", pe__cluster_stack_text },
1705  { "cluster-stack", "xml", pe__cluster_stack_xml },
1706  { "cluster-times", "html", pe__cluster_times_html },
1707  { "cluster-times", "log", pe__cluster_times_text },
1708  { "cluster-times", "text", pe__cluster_times_text },
1709  { "cluster-times", "xml", pe__cluster_times_xml },
1710  { "failed-action", "html", pe__failed_action_text },
1711  { "failed-action", "log", pe__failed_action_text },
1712  { "failed-action", "text", pe__failed_action_text },
1713  { "failed-action", "xml", pe__failed_action_xml },
1714  { "group", "xml", pe__group_xml },
1715  { "group", "html", pe__group_html },
1716  { "group", "text", pe__group_text },
1717  { "group", "log", pe__group_text },
1718  /* maint-mode only exists for text and log. Other formatters output it as
1719  * part of the cluster-options handler.
1720  */
1721  { "maint-mode", "log", pe__cluster_maint_mode_text },
1722  { "maint-mode", "text", pe__cluster_maint_mode_text },
1723  { "node", "html", pe__node_html },
1724  { "node", "log", pe__node_text },
1725  { "node", "text", pe__node_text },
1726  { "node", "xml", pe__node_xml },
1727  { "node-list", "html", pe__node_list_html },
1728  { "node-list", "log", pe__node_list_text },
1729  { "node-list", "text", pe__node_list_text },
1730  { "node-list", "xml", pe__node_list_xml },
1731  { "node-attribute", "html", pe__node_attribute_html },
1732  { "node-attribute", "log", pe__node_attribute_text },
1733  { "node-attribute", "text", pe__node_attribute_text },
1734  { "node-attribute", "xml", pe__node_attribute_xml },
1735  { "op-history", "html", pe__op_history_text },
1736  { "op-history", "log", pe__op_history_text },
1737  { "op-history", "text", pe__op_history_text },
1738  { "op-history", "xml", pe__op_history_xml },
1739  { "primitive", "xml", pe__resource_xml },
1740  { "primitive", "html", pe__resource_html },
1741  { "primitive", "text", pe__resource_text },
1742  { "primitive", "log", pe__resource_text },
1743  { "resource-history", "html", pe__resource_history_text },
1744  { "resource-history", "log", pe__resource_history_text },
1745  { "resource-history", "text", pe__resource_history_text },
1746  { "resource-history", "xml", pe__resource_history_xml },
1747  { "ticket", "html", pe__ticket_html },
1748  { "ticket", "log", pe__ticket_text },
1749  { "ticket", "text", pe__ticket_text },
1750  { "ticket", "xml", pe__ticket_xml },
1751 
1752  { NULL, NULL, NULL }
1753 };
1754 
1755 void
1757  pcmk__register_messages(out, fmt_functions);
1758 }
1759 
1760 void
1761 pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
1762 {
1763  if (node == NULL) {
1764  crm_trace("<NULL>");
1765  return;
1766  }
1767 
1768  CRM_ASSERT(node->details);
1769  crm_trace("%sNode %s: (weight=%d, fixed=%s)",
1770  node->details->online ? "" : "Unavailable/Unclean ",
1771  node->details->uname, node->weight, node->fixed ? "True" : "False");
1772 
1773  if (details) {
1774  char *pe_mutable = strdup("\t\t");
1775  GListPtr gIter = node->details->running_rsc;
1776  GListPtr unames = NULL;
1777 
1778  unames = g_list_prepend(unames, strdup("*"));
1779 
1780  crm_trace("\t\t===Node Attributes");
1781  g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable);
1782  free(pe_mutable);
1783 
1784  crm_trace("\t\t=== Resources");
1785 
1786  for (; gIter != NULL; gIter = gIter->next) {
1787  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1788 
1789  out->message(out, crm_map_element_name(rsc->xml),
1790  pe_print_pending, rsc, unames);
1791  }
1792 
1793  g_list_free_full(unames, free);
1794  }
1795 }
int pe__ticket_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1613
GListPtr nodes
Definition: pe_types.h:146
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:280
#define XML_ATTR_UPDATE_ORIG
Definition: msg_xml.h:103
enum rsc_role_e role_filter
Definition: internal.h:57
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:138
int pe__cluster_maint_mode_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:705
#define XML_ATTR_UPDATE_CLIENT
Definition: msg_xml.h:104
GHashTable * attrs
Definition: pe_types.h:221
Definition: output.h:73
gboolean fixed
Definition: pe_types.h:229
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:263
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:660
int pe__failed_action_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:930
int pe__ticket_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1634
#define crm_time_log_timeofday
Definition: iso8601.h:65
int pe__cluster_summary(pcmk__output_t *out, va_list args)
int pe__failed_action_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:941
pe_resource_t * container
Definition: pe_types.h:364
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
#define pe_flag_symmetric_cluster
Definition: pe_types.h:92
gboolean standby
Definition: pe_types.h:438
xmlNode * xml
Definition: pe_types.h:307
int pe__ban_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:482
int pe__cluster_options_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:770
int pe__cluster_options_log(pcmk__output_t *out, va_list args)
Definition: pe_output.c:757
#define pe_flag_maintenance_mode
Definition: pe_types.h:93
xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: xml.c:2013
#define XML_ATTR_UPDATE_USER
Definition: msg_xml.h:105
pe_resource_t * remote_rsc
Definition: pe_types.h:217
xmlNodePtr pcmk__output_xml_peek_parent(pcmk__output_t *out)
Definition: output_xml.c:407
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:282
int pe__cluster_times_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:913
int pe__cluster_counts_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:565
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:126
int(* message)(pcmk__output_t *out, const char *message_id,...)
Definition: output.h:311
gboolean pending
Definition: pe_types.h:203
int pe__cluster_dc_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:629
int pe__ban_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:465
pe_resource_t * rsc_lh
Definition: internal.h:56
int migration_threshold
Definition: pe_types.h:328
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:281
int pe__resource_text(pcmk__output_t *out, va_list args)
Definition: native.c:1131
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:283
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
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:211
int pe__group_text(pcmk__output_t *out, va_list args)
Definition: group.c:244
#define PCMK__LAST_FAILURE_PREFIX
Definition: internal.h:229
int pe__cluster_times_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:868
char * pe__node_display_name(pe_node_t *node, bool print_detail)
Definition: pe_output.c:361
int pe__bundle_html(pcmk__output_t *out, va_list args)
Definition: bundle.c:1594
int pe__op_history_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1465
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:297
gboolean pe__is_remote_node(pe_node_t *node)
Definition: remote.c:36
int pe__clone_html(pcmk__output_t *out, va_list args)
Definition: clone.c:619
int pe__node_list_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1300
gboolean is_dc
Definition: pe_types.h:208
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:261
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:260
int weight
Definition: pe_types.h:228
int rc
Definition: pcmk_fence.c:34
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:614
int pe__bundle_text(pcmk__output_t *out, va_list args)
Definition: bundle.c:1694
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name, size_t pairs_count,...)
Definition: pe_output.c:413
int pe__ticket_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1655
int pe__group_html(pcmk__output_t *out, va_list args)
Definition: group.c:219
#define crm_trace(fmt, args...)
Definition: logging.h:369
int pe__clone_xml(pcmk__output_t *out, va_list args)
Definition: clone.c:575
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition: iso8601.c:1255
int blocked_resources
Definition: pe_types.h:171
struct pe_node_shared_s * details
Definition: pe_types.h:231
int pe__node_attribute_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1214
#define pcmk__plural_s(i)
Definition: internal.h:198
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:85
const char * uname
Definition: pe_types.h:196
int pe__node_attribute_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1244
#define XML_ATTR_UNAME
Definition: msg_xml.h:118
int pe__cluster_times_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:892
int pe__resource_history_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1547
PCMK__OUTPUT_ARGS("cluster-summary","struct pe_working_set_t *","gboolean","gboolean","gboolean","gboolean","gboolean","gboolean")
Definition: pe_output.c:214
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1976
#define pe_flag_stonith_enabled
Definition: pe_types.h:95
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
Definition: nvpair.c:649
#define PCMK__FAIL_COUNT_PREFIX
Definition: internal.h:228
time_t last_granted
Definition: pe_types.h:437
int pe__node_list_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1265
int pe__cluster_summary_html(pcmk__output_t *out, va_list args)
gboolean standby
Definition: pe_types.h:201
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:278
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:1756
gboolean expected_up
Definition: pe_types.h:207
#define crm_time_log_with_timezone
Definition: iso8601.h:66
int pe__cluster_dc_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:663
xmlNode * input
Definition: pe_types.h:126
gboolean granted
Definition: pe_types.h:436
const char * pcmk__epoch2str(time_t *when)
Definition: iso8601.c:1715
int pe__cluster_counts_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:503
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:140
const char * id
Definition: pe_types.h:195
int pe__cluster_stack_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:837
char * id
Definition: pe_types.h:435
int pe__resource_history_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1569
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition: iso8601.c:497
int pe__resource_xml(pcmk__output_t *out, va_list args)
Definition: native.c:1043
int pe__cluster_options_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:714
const xmlChar * pcmkXmlStr
Definition: xml.h:51
int pe__cluster_options_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:802
GListPtr running_rsc
Definition: pe_types.h:218
pe_node_t * dc_node
Definition: pe_types.h:131
int pe__bundle_xml(pcmk__output_t *out, va_list args)
Definition: bundle.c:1498
gboolean pe__is_guest_node(pe_node_t *node)
Definition: remote.c:47
int pe__clone_text(pcmk__output_t *out, va_list args)
Definition: clone.c:828
int pe__node_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1063
#define CRM_ASSERT(expr)
Definition: results.h:42
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition: output_xml.c:387
int pe__ban_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:445
int disabled_resources
Definition: pe_types.h:172
#define XML_CIB_ATTR_WRITTEN
Definition: msg_xml.h:93
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:93
int pe__cluster_stack_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:849
node_type
Definition: pe_types.h:67
int pe__node_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1120
int pe__group_xml(pcmk__output_t *out, va_list args)
Definition: group.c:182
This structure contains everything that makes up a single output formatter.
Definition: output.h:153
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:258
char * pcmk__add_word(char *list, const char *word)
Definition: strings.c:517
void void xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name)
Definition: output_xml.c:354
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:272
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:340
int pe__node_attribute_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1188
gboolean shutdown
Definition: pe_types.h:206
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:270
int pe__resource_html(pcmk__output_t *out, va_list args)
Definition: native.c:1112
int pe__cluster_dc_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:682
gboolean maintenance
Definition: pe_types.h:209
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:271
#define pcmk_ok
Definition: results.h:67
#define SUMMARY_HEADER(rc, out)
Definition: pe_output.c:15
int pe__node_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1001
int pe__cluster_counts_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:599
gboolean crm_is_true(const char *s)
Definition: strings.c:278
#define XML_RSC_OP_LAST_RUN
Definition: msg_xml.h:281
unsigned long long flags
Definition: pe_types.h:135
#define ID(x)
Definition: msg_xml.h:418
void pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
Definition: pe_output.c:1761
char * crm_xml_escape(const char *text)
Definition: xml.c:2653
gboolean standby_onfail
Definition: pe_types.h:202
void print_str_str(gpointer key, gpointer value, gpointer user_data)
Definition: utils.c:1349
char * name
Definition: pcmk_fence.c:30
int pe__rscs_brief_output(pcmk__output_t *out, GListPtr rsc_list, long options, gboolean print_all)
Definition: native.c:1385
int pe__op_history_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1482
gboolean unclean
Definition: pe_types.h:204
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
int pe__node_list_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1439
GList * GListPtr
Definition: crm.h:214
enum node_type type
Definition: pe_types.h:197
int pe__cluster_stack_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:857
#define crm_time_log_date
Definition: iso8601.h:64
gboolean online
Definition: pe_types.h:200
char * id
Definition: pe_types.h:305
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:141