pacemaker  2.0.4-2deceaa3ae
Scalable High-Availability cluster resource manager
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_demote:
733  out->list_item(out, NULL, "No quorum policy: Demote promotable "
734  "resources and stop all other resources");
735  break;
736 
737  case no_quorum_ignore:
738  out->list_item(out, NULL, "No quorum policy: Ignore");
739  break;
740 
741  case no_quorum_suicide:
742  out->list_item(out, NULL, "No quorum policy: Suicide");
743  break;
744  }
745 
746  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
747  xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
748 
749  pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
750  pcmk_create_html_node(node, "span", NULL, "bold", "DISABLED");
751  pcmk_create_html_node(node, "span", NULL, NULL,
752  " (the cluster will not attempt to start, stop, or recover services)");
753  } else {
754  out->list_item(out, NULL, "Resource management: enabled");
755  }
756 
757  return pcmk_rc_ok;
758 }
759 
760 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
761 int
763  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
764 
765  if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
766  out->info(out, "Resource management is DISABLED. The cluster will not attempt to start, stop or recover services.");
767  return pcmk_rc_ok;
768  } else {
769  return pcmk_rc_no_output;
770  }
771 }
772 
773 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
774 int
776  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
777 
778  out->list_item(out, NULL, "STONITH of failed nodes %s",
779  is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
780 
781  out->list_item(out, NULL, "Cluster is %s",
782  is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
783 
784  switch (data_set->no_quorum_policy) {
785  case no_quorum_freeze:
786  out->list_item(out, NULL, "No quorum policy: Freeze resources");
787  break;
788 
789  case no_quorum_stop:
790  out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
791  break;
792 
793  case no_quorum_demote:
794  out->list_item(out, NULL, "No quorum policy: Demote promotable "
795  "resources and stop all other resources");
796  break;
797 
798  case no_quorum_ignore:
799  out->list_item(out, NULL, "No quorum policy: Ignore");
800  break;
801 
802  case no_quorum_suicide:
803  out->list_item(out, NULL, "No quorum policy: Suicide");
804  break;
805  }
806 
807  return pcmk_rc_ok;
808 }
809 
810 PCMK__OUTPUT_ARGS("cluster-options", "struct pe_working_set_t *")
811 int
813  xmlNodePtr node = pcmk__output_create_xml_node(out, "cluster_options");
814  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
815 
816  xmlSetProp(node, (pcmkXmlStr) "stonith-enabled",
817  (pcmkXmlStr) (is_set(data_set->flags, pe_flag_stonith_enabled) ? "true" : "false"));
818  xmlSetProp(node, (pcmkXmlStr) "symmetric-cluster",
819  (pcmkXmlStr) (is_set(data_set->flags, pe_flag_symmetric_cluster) ? "true" : "false"));
820 
821  switch (data_set->no_quorum_policy) {
822  case no_quorum_freeze:
823  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "freeze");
824  break;
825 
826  case no_quorum_stop:
827  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "stop");
828  break;
829 
830  case no_quorum_demote:
831  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "demote");
832  break;
833 
834  case no_quorum_ignore:
835  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "ignore");
836  break;
837 
838  case no_quorum_suicide:
839  xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "suicide");
840  break;
841  }
842 
843  xmlSetProp(node, (pcmkXmlStr) "maintenance-mode",
844  (pcmkXmlStr) (is_set(data_set->flags, pe_flag_maintenance_mode) ? "true" : "false"));
845 
846  return pcmk_rc_ok;
847 }
848 
849 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
850 int
852  xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
853  const char *stack_s = va_arg(args, const char *);
854 
855  pcmk_create_html_node(node, "span", NULL, "bold", "Stack: ");
856  pcmk_create_html_node(node, "span", NULL, NULL, stack_s);
857 
858  return pcmk_rc_ok;
859 }
860 
861 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
862 int
864  const char *stack_s = va_arg(args, const char *);
865  out->list_item(out, "Stack", "%s", stack_s);
866  return pcmk_rc_ok;
867 }
868 
869 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
870 int
872  xmlNodePtr node = pcmk__output_create_xml_node(out, "stack");
873  const char *stack_s = va_arg(args, const char *);
874 
875  xmlSetProp(node, (pcmkXmlStr) "type", (pcmkXmlStr) stack_s);
876 
877  return pcmk_rc_ok;
878 }
879 
880 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
881 int
883  xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "li");
884  xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "li");
885 
886  const char *last_written = va_arg(args, const char *);
887  const char *user = va_arg(args, const char *);
888  const char *client = va_arg(args, const char *);
889  const char *origin = va_arg(args, const char *);
890 
891  char *buf = last_changed_string(last_written, user, client, origin);
892 
893  pcmk_create_html_node(updated_node, "span", NULL, "bold", "Last updated: ");
894  pcmk_create_html_node(updated_node, "span", NULL, NULL,
895  pcmk__epoch2str(NULL));
896 
897  pcmk_create_html_node(changed_node, "span", NULL, "bold", "Last change: ");
898  pcmk_create_html_node(changed_node, "span", NULL, NULL, buf);
899 
900  free(buf);
901  return pcmk_rc_ok;
902 }
903 
904 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
905 int
907  xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "last_update");
908  xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "last_change");
909 
910  const char *last_written = va_arg(args, const char *);
911  const char *user = va_arg(args, const char *);
912  const char *client = va_arg(args, const char *);
913  const char *origin = va_arg(args, const char *);
914 
915  xmlSetProp(updated_node, (pcmkXmlStr) "time",
916  (pcmkXmlStr) pcmk__epoch2str(NULL));
917  xmlSetProp(changed_node, (pcmkXmlStr) "time", (pcmkXmlStr) (last_written ? last_written : ""));
918  xmlSetProp(changed_node, (pcmkXmlStr) "user", (pcmkXmlStr) (user ? user : ""));
919  xmlSetProp(changed_node, (pcmkXmlStr) "client", (pcmkXmlStr) (client ? client : ""));
920  xmlSetProp(changed_node, (pcmkXmlStr) "origin", (pcmkXmlStr) (origin ? origin : ""));
921 
922  return pcmk_rc_ok;
923 }
924 
925 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
926 int
928  const char *last_written = va_arg(args, const char *);
929  const char *user = va_arg(args, const char *);
930  const char *client = va_arg(args, const char *);
931  const char *origin = va_arg(args, const char *);
932 
933  char *buf = last_changed_string(last_written, user, client, origin);
934 
935  out->list_item(out, "Last updated", "%s", pcmk__epoch2str(NULL));
936  out->list_item(out, "Last change", " %s", buf);
937 
938  free(buf);
939  return pcmk_rc_ok;
940 }
941 
942 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
943 int
945  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
946  char *s = failed_action_string(xml_op);
947 
948  out->list_item(out, NULL, "%s", s);
949  free(s);
950  return pcmk_rc_ok;
951 }
952 
953 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
954 int
956  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
957 
958  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
959  const char *last = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
960  int rc = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_RC), "0");
961  int status = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS), "0");
962  const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
963 
964  char *rc_s = crm_itoa(rc);
965  char *reason_s = crm_xml_escape(exit_reason ? exit_reason : "none");
966  xmlNodePtr node = pcmk__output_create_xml_node(out, "failure");
967 
968  xmlSetProp(node, (pcmkXmlStr) (op_key ? "op_key" : "id"),
969  (pcmkXmlStr) (op_key ? op_key : "id"));
970  xmlSetProp(node, (pcmkXmlStr) "node",
972  xmlSetProp(node, (pcmkXmlStr) "exitstatus",
973  (pcmkXmlStr) services_ocf_exitcode_str(rc));
974  xmlSetProp(node, (pcmkXmlStr) "exitreason", (pcmkXmlStr) reason_s);
975  xmlSetProp(node, (pcmkXmlStr) "exitcode", (pcmkXmlStr) rc_s);
976  xmlSetProp(node, (pcmkXmlStr) "call",
978  xmlSetProp(node, (pcmkXmlStr) "status",
979  (pcmkXmlStr) services_lrm_status_str(status));
980 
981  if (last) {
982  guint interval_ms = 0;
983  char *s = NULL;
984  time_t when = crm_parse_int(last, "0");
985  crm_time_t *crm_when = crm_time_new(NULL);
986  char *rc_change = NULL;
987 
988  crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
989  s = crm_itoa(interval_ms);
990 
991  crm_time_set_timet(crm_when, &when);
993 
994  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_CHANGE, (pcmkXmlStr) rc_change);
995  xmlSetProp(node, (pcmkXmlStr) "queued",
997  xmlSetProp(node, (pcmkXmlStr) "exec",
999  xmlSetProp(node, (pcmkXmlStr) "interval", (pcmkXmlStr) s);
1000  xmlSetProp(node, (pcmkXmlStr) "task",
1002 
1003  free(s);
1004  free(rc_change);
1005  crm_time_free(crm_when);
1006  }
1007 
1008  free(reason_s);
1009  free(rc_s);
1010  return pcmk_rc_ok;
1011 }
1012 
1013 PCMK__OUTPUT_ARGS("node", "struct pe_node_t *", "unsigned int", "gboolean", "const char *", "gboolean", "gboolean", "gboolean", "GListPtr")
1014 int
1015 pe__node_html(pcmk__output_t *out, va_list args) {
1016  pe_node_t *node = va_arg(args, pe_node_t *);
1017  unsigned int print_opts = va_arg(args, unsigned int);
1018  gboolean full = va_arg(args, gboolean);
1019  const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1020  gboolean print_clone_detail = va_arg(args, gboolean);
1021  gboolean print_brief = va_arg(args, gboolean);
1022  gboolean group_by_node = va_arg(args, gboolean);
1023  GListPtr only_show = va_arg(args, GListPtr);
1024 
1025  char *node_name = pe__node_display_name(node, print_clone_detail);
1026  char *buf = crm_strdup_printf("Node: %s", node_name);
1027 
1028  if (full) {
1029  xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li");
1030 
1031  pcmk_create_html_node(item_node, "span", NULL, NULL, buf);
1032 
1033  if (node->details->standby_onfail && node->details->online) {
1034  pcmk_create_html_node(item_node, "span", NULL, "standby", " standby (on-fail)");
1035  } else if (node->details->standby && node->details->online) {
1036  char *s = crm_strdup_printf(" standby%s", node->details->running_rsc ? " (with active resources)" : "");
1037  pcmk_create_html_node(item_node, "span", NULL, " standby", s);
1038  free(s);
1039  } else if (node->details->standby) {
1040  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (standby)");
1041  } else if (node->details->maintenance && node->details->online) {
1042  pcmk_create_html_node(item_node, "span", NULL, "maint", " maintenance");
1043  } else if (node->details->maintenance) {
1044  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (maintenance)");
1045  } else if (node->details->online) {
1046  pcmk_create_html_node(item_node, "span", NULL, "online", " online");
1047  } else {
1048  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE");
1049  }
1050  if (print_brief && group_by_node) {
1051  out->begin_list(out, NULL, NULL, NULL);
1052  pe__rscs_brief_output(out, node->details->running_rsc, print_opts | pe_print_rsconly,
1053  FALSE);
1054  out->end_list(out);
1055 
1056  } else if (group_by_node) {
1057  GListPtr lpc2 = NULL;
1058 
1059  out->begin_list(out, NULL, NULL, NULL);
1060  for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) {
1061  pe_resource_t *rsc = (pe_resource_t *) lpc2->data;
1062  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly, rsc, only_show);
1063  }
1064  out->end_list(out);
1065  }
1066  } else {
1067  out->begin_list(out, NULL, NULL, "%s", buf);
1068  }
1069 
1070  free(buf);
1071  free(node_name);
1072  return pcmk_rc_ok;
1073 }
1074 
1075 PCMK__OUTPUT_ARGS("node", "struct pe_node_t *", "unsigned int", "gboolean", "const char *", "gboolean", "gboolean", "gboolean", "GListPtr")
1076 int
1077 pe__node_text(pcmk__output_t *out, va_list args) {
1078  pe_node_t *node = va_arg(args, pe_node_t *);
1079  unsigned int print_opts = va_arg(args, unsigned int);
1080  gboolean full = va_arg(args, gboolean);
1081  const char *node_mode = va_arg(args, const char *);
1082  gboolean print_clone_detail = va_arg(args, gboolean);
1083  gboolean print_brief = va_arg(args, gboolean);
1084  gboolean group_by_node = va_arg(args, gboolean);
1085  GListPtr only_show = va_arg(args, GListPtr);
1086 
1087  if (full) {
1088  char *node_name = pe__node_display_name(node, print_clone_detail);
1089  char *buf = NULL;
1090 
1091  /* Print the node name and status */
1092  if (pe__is_guest_node(node)) {
1093  buf = crm_strdup_printf("GuestNode %s: %s", node_name, node_mode);
1094  } else if (pe__is_remote_node(node)) {
1095  buf = crm_strdup_printf("RemoteNode %s: %s", node_name, node_mode);
1096  } else {
1097  buf = crm_strdup_printf("Node %s: %s", node_name, node_mode);
1098  }
1099 
1100  /* If we're grouping by node, print its resources */
1101  if (group_by_node) {
1102  out->begin_list(out, NULL, NULL, "%s", buf);
1103  out->begin_list(out, NULL, NULL, "Resources");
1104 
1105  if (print_brief) {
1107  print_opts | pe_print_rsconly, FALSE);
1108  } else {
1109  GListPtr gIter2 = NULL;
1110 
1111  for (gIter2 = node->details->running_rsc; gIter2 != NULL; gIter2 = gIter2->next) {
1112  pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1113  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly, rsc, only_show);
1114  }
1115  }
1116 
1117  out->end_list(out);
1118  out->end_list(out);
1119  } else {
1120  out->list_item(out, NULL, "%s", buf);
1121  }
1122 
1123  free(buf);
1124  free(node_name);
1125  } else {
1126  out->begin_list(out, NULL, NULL, "Node: %s", pe__node_display_name(node, print_clone_detail));
1127  }
1128 
1129  return pcmk_rc_ok;
1130 }
1131 
1132 PCMK__OUTPUT_ARGS("node", "struct pe_node_t *", "unsigned int", "gboolean", "const char *", "gboolean", "gboolean", "gboolean", "GListPtr")
1133 int
1134 pe__node_xml(pcmk__output_t *out, va_list args) {
1135  pe_node_t *node = va_arg(args, pe_node_t *);
1136  unsigned int print_opts = va_arg(args, unsigned int);
1137  gboolean full = va_arg(args, gboolean);
1138  const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1139  gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
1140  gboolean print_brief G_GNUC_UNUSED = va_arg(args, gboolean);
1141  gboolean group_by_node = va_arg(args, gboolean);
1142  GListPtr only_show = va_arg(args, GListPtr);
1143 
1144  if (full) {
1145  const char *node_type = "unknown";
1146  char *length_s = crm_itoa(g_list_length(node->details->running_rsc));
1147 
1148  switch (node->details->type) {
1149  case node_member:
1150  node_type = "member";
1151  break;
1152  case node_remote:
1153  node_type = "remote";
1154  break;
1155  case node_ping:
1156  node_type = "ping";
1157  break;
1158  }
1159  pe__name_and_nvpairs_xml(out, true, "node", 13,
1160  "name", node->details->uname,
1161  "id", node->details->id,
1162  "online", node->details->online ? "true" : "false",
1163  "standby", node->details->standby ? "true" : "false",
1164  "standby_onfail", node->details->standby_onfail ? "true" : "false",
1165  "maintenance", node->details->maintenance ? "true" : "false",
1166  "pending", node->details->pending ? "true" : "false",
1167  "unclean", node->details->unclean ? "true" : "false",
1168  "shutdown", node->details->shutdown ? "true" : "false",
1169  "expected_up", node->details->expected_up ? "true" : "false",
1170  "is_dc", node->details->is_dc ? "true" : "false",
1171  "resources_running", length_s,
1172  "type", node_type);
1173 
1174  if (pe__is_guest_node(node)) {
1175  xmlNodePtr xml_node = pcmk__output_xml_peek_parent(out);
1176  xmlSetProp(xml_node, (pcmkXmlStr) "id_as_resource",
1178  }
1179 
1180  if (group_by_node) {
1181  GListPtr lpc = NULL;
1182 
1183  for (lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) {
1184  pe_resource_t *rsc = (pe_resource_t *) lpc->data;
1185  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly, rsc, only_show);
1186  }
1187  }
1188 
1189  free(length_s);
1190 
1191  out->end_list(out);
1192  } else {
1193  xmlNodePtr parent = pcmk__output_xml_create_parent(out, "node");
1194  xmlSetProp(parent, (pcmkXmlStr) "name", (pcmkXmlStr) node->details->uname);
1195  }
1196 
1197  return pcmk_rc_ok;
1198 }
1199 
1200 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1201 int
1203  const char *name = va_arg(args, const char *);
1204  const char *value = va_arg(args, const char *);
1205  gboolean add_extra = va_arg(args, gboolean);
1206  int expected_score = va_arg(args, int);
1207 
1208 
1209  if (add_extra) {
1210  int v = crm_parse_int(value, "0");
1211 
1212  if (v <= 0) {
1213  out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is lost", name, value);
1214  } else if (v < expected_score) {
1215  out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is degraded (Expected=%d)", name, value, expected_score);
1216  } else {
1217  out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1218  }
1219  } else {
1220  out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1221  }
1222 
1223  return pcmk_rc_ok;
1224 }
1225 
1226 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1227 int
1229  const char *name = va_arg(args, const char *);
1230  const char *value = va_arg(args, const char *);
1231  gboolean add_extra = va_arg(args, gboolean);
1232  int expected_score = va_arg(args, int);
1233 
1234  if (add_extra) {
1235  int v = crm_parse_int(value, "0");
1236  char *s = crm_strdup_printf("%s: %s", name, value);
1237  xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li");
1238 
1239  pcmk_create_html_node(item_node, "span", NULL, NULL, s);
1240  free(s);
1241 
1242  if (v <= 0) {
1243  pcmk_create_html_node(item_node, "span", NULL, "bold", "(connectivity is lost)");
1244  } else if (v < expected_score) {
1245  char *buf = crm_strdup_printf("(connectivity is degraded -- expected %d", expected_score);
1246  pcmk_create_html_node(item_node, "span", NULL, "bold", buf);
1247  free(buf);
1248  }
1249  } else {
1250  out->list_item(out, NULL, "%s: %s", name, value);
1251  }
1252 
1253  return pcmk_rc_ok;
1254 }
1255 
1256 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1257 int
1259  const char *name = va_arg(args, const char *);
1260  const char *value = va_arg(args, const char *);
1261  gboolean add_extra = va_arg(args, gboolean);
1262  int expected_score = va_arg(args, int);
1263 
1264  xmlNodePtr node = pcmk__output_create_xml_node(out, "attribute");
1265  xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) name);
1266  xmlSetProp(node, (pcmkXmlStr) "value", (pcmkXmlStr) value);
1267 
1268  if (add_extra) {
1269  char *buf = crm_itoa(expected_score);
1270  xmlSetProp(node, (pcmkXmlStr) "expected", (pcmkXmlStr) buf);
1271  free(buf);
1272  }
1273 
1274  return pcmk_rc_ok;
1275 }
1276 
1277 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1278 int
1279 pe__node_list_html(pcmk__output_t *out, va_list args) {
1280  GListPtr nodes = va_arg(args, GListPtr);
1281  GListPtr only_show = va_arg(args, GListPtr);
1282  unsigned int print_opts = va_arg(args, unsigned int);
1283  gboolean print_clone_detail = va_arg(args, gboolean);
1284  gboolean print_brief = va_arg(args, gboolean);
1285  gboolean group_by_node = va_arg(args, gboolean);
1286 
1287  gboolean printed_header = FALSE;
1288 
1289  for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1290  pe_node_t *node = (pe_node_t *) gIter->data;
1291 
1292  if (!pcmk__str_in_list(only_show, node->details->uname)) {
1293  continue;
1294  }
1295 
1296  if (printed_header == FALSE) {
1297  printed_header = TRUE;
1298  out->begin_list(out, NULL, NULL, "Node List");
1299  }
1300 
1301  out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1302  print_brief, group_by_node, only_show);
1303  }
1304 
1305  if (printed_header == TRUE) {
1306  out->end_list(out);
1307  }
1308 
1309  return pcmk_rc_ok;
1310 }
1311 
1312 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1313 int
1314 pe__node_list_text(pcmk__output_t *out, va_list args) {
1315  GListPtr nodes = va_arg(args, GListPtr);
1316  GListPtr only_show = va_arg(args, GListPtr);
1317  unsigned int print_opts = va_arg(args, unsigned int);
1318  gboolean print_clone_detail = va_arg(args, gboolean);
1319  gboolean print_brief = va_arg(args, gboolean);
1320  gboolean group_by_node = va_arg(args, gboolean);
1321 
1322  /* space-separated lists of node names */
1323  char *online_nodes = NULL;
1324  char *online_remote_nodes = NULL;
1325  char *online_guest_nodes = NULL;
1326  char *offline_nodes = NULL;
1327  char *offline_remote_nodes = NULL;
1328 
1329  int rc = pcmk_rc_no_output;
1330  gboolean printed_header = FALSE;
1331 
1332  for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1333  pe_node_t *node = (pe_node_t *) gIter->data;
1334  const char *node_mode = NULL;
1335  char *node_name = pe__node_display_name(node, print_clone_detail);
1336 
1337  if (!pcmk__str_in_list(only_show, node->details->uname)) {
1338  free(node_name);
1339  continue;
1340  }
1341 
1342  if (printed_header == FALSE) {
1343  out->begin_list(out, NULL, NULL, "Node List");
1344  rc = pcmk_rc_ok;
1345  printed_header = TRUE;
1346  }
1347 
1348  /* Get node mode */
1349  if (node->details->unclean) {
1350  if (node->details->online) {
1351  node_mode = "UNCLEAN (online)";
1352 
1353  } else if (node->details->pending) {
1354  node_mode = "UNCLEAN (pending)";
1355 
1356  } else {
1357  node_mode = "UNCLEAN (offline)";
1358  }
1359 
1360  } else if (node->details->pending) {
1361  node_mode = "pending";
1362 
1363  } else if (node->details->standby_onfail && node->details->online) {
1364  node_mode = "standby (on-fail)";
1365 
1366  } else if (node->details->standby) {
1367  if (node->details->online) {
1368  if (node->details->running_rsc) {
1369  node_mode = "standby (with active resources)";
1370  } else {
1371  node_mode = "standby";
1372  }
1373  } else {
1374  node_mode = "OFFLINE (standby)";
1375  }
1376 
1377  } else if (node->details->maintenance) {
1378  if (node->details->online) {
1379  node_mode = "maintenance";
1380  } else {
1381  node_mode = "OFFLINE (maintenance)";
1382  }
1383 
1384  } else if (node->details->online) {
1385  node_mode = "online";
1386  if (group_by_node == FALSE) {
1387  if (pe__is_guest_node(node)) {
1388  online_guest_nodes = pcmk__add_word(online_guest_nodes,
1389  node_name);
1390  } else if (pe__is_remote_node(node)) {
1391  online_remote_nodes = pcmk__add_word(online_remote_nodes,
1392  node_name);
1393  } else {
1394  online_nodes = pcmk__add_word(online_nodes, node_name);
1395  }
1396  free(node_name);
1397  continue;
1398  }
1399 
1400  } else {
1401  node_mode = "OFFLINE";
1402  if (group_by_node == FALSE) {
1403  if (pe__is_remote_node(node)) {
1404  offline_remote_nodes = pcmk__add_word(offline_remote_nodes,
1405  node_name);
1406  } else if (pe__is_guest_node(node)) {
1407  /* ignore offline guest nodes */
1408  } else {
1409  offline_nodes = pcmk__add_word(offline_nodes, node_name);
1410  }
1411  free(node_name);
1412  continue;
1413  }
1414  }
1415 
1416  /* If we get here, node is in bad state, or we're grouping by node */
1417  out->message(out, "node", node, print_opts, TRUE, node_mode, print_clone_detail,
1418  print_brief, group_by_node, only_show);
1419  free(node_name);
1420  }
1421 
1422  /* If we're not grouping by node, summarize nodes by status */
1423  if (online_nodes) {
1424  out->list_item(out, "Online", "[%s ]", online_nodes);
1425  free(online_nodes);
1426  }
1427  if (offline_nodes) {
1428  out->list_item(out, "OFFLINE", "[%s ]", offline_nodes);
1429  free(offline_nodes);
1430  }
1431  if (online_remote_nodes) {
1432  out->list_item(out, "RemoteOnline", "[%s ]", online_remote_nodes);
1433  free(online_remote_nodes);
1434  }
1435  if (offline_remote_nodes) {
1436  out->list_item(out, "RemoteOFFLINE", "[%s ]", offline_remote_nodes);
1437  free(offline_remote_nodes);
1438  }
1439  if (online_guest_nodes) {
1440  out->list_item(out, "GuestOnline", "[%s ]", online_guest_nodes);
1441  free(online_guest_nodes);
1442  }
1443 
1444  if (printed_header == TRUE) {
1445  out->end_list(out);
1446  }
1447 
1448  return rc;
1449 }
1450 
1451 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1452 int
1453 pe__node_list_xml(pcmk__output_t *out, va_list args) {
1454  GListPtr nodes = va_arg(args, GListPtr);
1455  GListPtr only_show = va_arg(args, GListPtr);
1456  unsigned int print_opts = va_arg(args, unsigned int);
1457  gboolean print_clone_detail = va_arg(args, gboolean);
1458  gboolean print_brief = va_arg(args, gboolean);
1459  gboolean group_by_node = va_arg(args, gboolean);
1460 
1461  out->begin_list(out, NULL, NULL, "nodes");
1462  for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1463  pe_node_t *node = (pe_node_t *) gIter->data;
1464 
1465  if (!pcmk__str_in_list(only_show, node->details->uname)) {
1466  continue;
1467  }
1468 
1469  out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1470  print_brief, group_by_node, only_show);
1471  }
1472  out->end_list(out);
1473 
1474  return pcmk_rc_ok;
1475 }
1476 
1477 PCMK__OUTPUT_ARGS("op-history", "struct xmlNode *", "const char *", "const char *", "int", "gboolean")
1478 int
1480  xmlNode *xml_op = va_arg(args, xmlNode *);
1481  const char *task = va_arg(args, const char *);
1482  const char *interval_ms_s = va_arg(args, const char *);
1483  int rc = va_arg(args, int);
1484  gboolean print_timing = va_arg(args, gboolean);
1485 
1486  char *buf = op_history_string(xml_op, task, interval_ms_s, rc, print_timing);
1487 
1488  out->list_item(out, NULL, "%s", buf);
1489 
1490  free(buf);
1491  return pcmk_rc_ok;
1492 }
1493 
1494 PCMK__OUTPUT_ARGS("op-history", "struct xmlNode *", "const char *", "const char *", "int", "gboolean")
1495 int
1496 pe__op_history_xml(pcmk__output_t *out, va_list args) {
1497  xmlNode *xml_op = va_arg(args, xmlNode *);
1498  const char *task = va_arg(args, const char *);
1499  const char *interval_ms_s = va_arg(args, const char *);
1500  int rc = va_arg(args, int);
1501  gboolean print_timing = va_arg(args, gboolean);
1502 
1503  char *rc_s = NULL;
1504 
1505  xmlNodePtr node = pcmk__output_create_xml_node(out, "operation_history");
1506 
1507  xmlSetProp(node, (pcmkXmlStr) "call",
1509  xmlSetProp(node, (pcmkXmlStr) "task", (pcmkXmlStr) task);
1510 
1511  if (interval_ms_s && safe_str_neq(interval_ms_s, "0")) {
1512  char *s = crm_strdup_printf("%sms", interval_ms_s);
1513  xmlSetProp(node, (pcmkXmlStr) "interval", (pcmkXmlStr) s);
1514  free(s);
1515  }
1516 
1517  if (print_timing) {
1518  const char *value = NULL;
1519 
1520  value = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
1521  if (value) {
1522  time_t int_value = (time_t) crm_parse_int(value, NULL);
1523  if (int_value > 0) {
1524  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_CHANGE,
1525  (pcmkXmlStr) pcmk__epoch2str(&int_value));
1526  }
1527  }
1528 
1529  value = crm_element_value(xml_op, XML_RSC_OP_LAST_RUN);
1530  if (value) {
1531  time_t int_value = (time_t) crm_parse_int(value, NULL);
1532  if (int_value > 0) {
1533  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_RUN,
1534  (pcmkXmlStr) pcmk__epoch2str(&int_value));
1535  }
1536  }
1537 
1538  value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
1539  if (value) {
1540  char *s = crm_strdup_printf("%sms", value);
1541  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_T_EXEC, (pcmkXmlStr) s);
1542  free(s);
1543  }
1544  value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
1545  if (value) {
1546  char *s = crm_strdup_printf("%sms", value);
1547  xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_T_QUEUE, (pcmkXmlStr) s);
1548  free(s);
1549  }
1550  }
1551 
1552  rc_s = crm_itoa(rc);
1553  xmlSetProp(node, (pcmkXmlStr) "rc", (pcmkXmlStr) rc_s);
1554  xmlSetProp(node, (pcmkXmlStr) "rc_text", (pcmkXmlStr) services_ocf_exitcode_str(rc));
1555  free(rc_s);
1556  return pcmk_rc_ok;
1557 }
1558 
1559 PCMK__OUTPUT_ARGS("resource-history", "struct pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
1560 int
1562  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1563  const char *rsc_id = va_arg(args, const char *);
1564  gboolean all = va_arg(args, gboolean);
1565  int failcount = va_arg(args, int);
1566  time_t last_failure = va_arg(args, int);
1567  gboolean as_header = va_arg(args, gboolean);
1568 
1569  char *buf = resource_history_string(rsc, rsc_id, all, failcount, last_failure);
1570 
1571  if (as_header) {
1572  out->begin_list(out, NULL, NULL, "%s", buf);
1573  } else {
1574  out->list_item(out, NULL, "%s", buf);
1575  }
1576 
1577  free(buf);
1578  return pcmk_rc_ok;
1579 }
1580 
1581 PCMK__OUTPUT_ARGS("resource-history", "struct pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
1582 int
1584  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1585  const char *rsc_id = va_arg(args, const char *);
1586  gboolean all = va_arg(args, gboolean);
1587  int failcount = va_arg(args, int);
1588  time_t last_failure = va_arg(args, int);
1589  gboolean as_header = va_arg(args, gboolean);
1590 
1591  xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource_history");
1592  xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) rsc_id);
1593 
1594  if (rsc == NULL) {
1595  xmlSetProp(node, (pcmkXmlStr) "orphan", (pcmkXmlStr) "true");
1596  } else if (all || failcount || last_failure > 0) {
1597  char *migration_s = crm_itoa(rsc->migration_threshold);
1598 
1599  xmlSetProp(node, (pcmkXmlStr) "orphan", (pcmkXmlStr) "false");
1600  xmlSetProp(node, (pcmkXmlStr) "migration-threshold",
1601  (pcmkXmlStr) migration_s);
1602  free(migration_s);
1603 
1604  if (failcount > 0) {
1605  char *s = crm_itoa(failcount);
1606 
1607  xmlSetProp(node, (pcmkXmlStr) PCMK__FAIL_COUNT_PREFIX,
1608  (pcmkXmlStr) s);
1609  free(s);
1610  }
1611 
1612  if (last_failure > 0) {
1613  xmlSetProp(node, (pcmkXmlStr) PCMK__LAST_FAILURE_PREFIX,
1614  (pcmkXmlStr) pcmk__epoch2str(&last_failure));
1615  }
1616  }
1617 
1618  if (as_header == FALSE) {
1620  }
1621 
1622  return pcmk_rc_ok;
1623 }
1624 
1625 PCMK__OUTPUT_ARGS("ticket", "struct pe_ticket_t *")
1626 int
1627 pe__ticket_html(pcmk__output_t *out, va_list args) {
1628  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1629 
1630  if (ticket->last_granted > -1) {
1631  char *time = pcmk_format_named_time("last-granted", ticket->last_granted);
1632  out->list_item(out, NULL, "%s:\t%s%s %s", ticket->id,
1633  ticket->granted ? "granted" : "revoked",
1634  ticket->standby ? " [standby]" : "",
1635  time);
1636  free(time);
1637  } else {
1638  out->list_item(out, NULL, "%s:\t%s%s", ticket->id,
1639  ticket->granted ? "granted" : "revoked",
1640  ticket->standby ? " [standby]" : "");
1641  }
1642 
1643  return pcmk_rc_ok;
1644 }
1645 
1646 PCMK__OUTPUT_ARGS("ticket", "struct pe_ticket_t *")
1647 int
1648 pe__ticket_text(pcmk__output_t *out, va_list args) {
1649  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1650 
1651  if (ticket->last_granted > -1) {
1652  char *time = pcmk_format_named_time("last-granted", ticket->last_granted);
1653  out->list_item(out, ticket->id, "\t%s%s %s",
1654  ticket->granted ? "granted" : "revoked",
1655  ticket->standby ? " [standby]" : "",
1656  time);
1657  free(time);
1658  } else {
1659  out->list_item(out, ticket->id, "\t%s%s",
1660  ticket->granted ? "granted" : "revoked",
1661  ticket->standby ? " [standby]" : "");
1662  }
1663 
1664  return pcmk_rc_ok;
1665 }
1666 
1667 PCMK__OUTPUT_ARGS("ticket", "struct pe_ticket_t *")
1668 int
1669 pe__ticket_xml(pcmk__output_t *out, va_list args) {
1670  xmlNodePtr node = NULL;
1671 
1672  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1673 
1674  node = pcmk__output_create_xml_node(out, "ticket");
1675  xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) ticket->id);
1676  xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) (ticket->granted ? "granted" : "revoked"));
1677  xmlSetProp(node, (pcmkXmlStr) "standby", (pcmkXmlStr) (ticket->standby ? "true" : "false"));
1678 
1679  if (ticket->last_granted > -1) {
1680  xmlSetProp(node, (pcmkXmlStr) "last-granted",
1682  }
1683 
1684  return pcmk_rc_ok;
1685 }
1686 
1687 static pcmk__message_entry_t fmt_functions[] = {
1688  { "ban", "html", pe__ban_html },
1689  { "ban", "log", pe__ban_text },
1690  { "ban", "text", pe__ban_text },
1691  { "ban", "xml", pe__ban_xml },
1692  { "bundle", "xml", pe__bundle_xml },
1693  { "bundle", "html", pe__bundle_html },
1694  { "bundle", "text", pe__bundle_text },
1695  { "bundle", "log", pe__bundle_text },
1696  { "clone", "xml", pe__clone_xml },
1697  { "clone", "html", pe__clone_html },
1698  { "clone", "text", pe__clone_text },
1699  { "clone", "log", pe__clone_text },
1700  { "cluster-counts", "html", pe__cluster_counts_html },
1701  { "cluster-counts", "log", pe__cluster_counts_text },
1702  { "cluster-counts", "text", pe__cluster_counts_text },
1703  { "cluster-counts", "xml", pe__cluster_counts_xml },
1704  { "cluster-dc", "html", pe__cluster_dc_html },
1705  { "cluster-dc", "log", pe__cluster_dc_text },
1706  { "cluster-dc", "text", pe__cluster_dc_text },
1707  { "cluster-dc", "xml", pe__cluster_dc_xml },
1708  { "cluster-options", "html", pe__cluster_options_html },
1709  { "cluster-options", "log", pe__cluster_options_log },
1710  { "cluster-options", "text", pe__cluster_options_text },
1711  { "cluster-options", "xml", pe__cluster_options_xml },
1712  { "cluster-summary", "html", pe__cluster_summary_html },
1713  { "cluster-summary", "log", pe__cluster_summary },
1714  { "cluster-summary", "text", pe__cluster_summary },
1715  { "cluster-summary", "xml", pe__cluster_summary },
1716  { "cluster-stack", "html", pe__cluster_stack_html },
1717  { "cluster-stack", "log", pe__cluster_stack_text },
1718  { "cluster-stack", "text", pe__cluster_stack_text },
1719  { "cluster-stack", "xml", pe__cluster_stack_xml },
1720  { "cluster-times", "html", pe__cluster_times_html },
1721  { "cluster-times", "log", pe__cluster_times_text },
1722  { "cluster-times", "text", pe__cluster_times_text },
1723  { "cluster-times", "xml", pe__cluster_times_xml },
1724  { "failed-action", "html", pe__failed_action_text },
1725  { "failed-action", "log", pe__failed_action_text },
1726  { "failed-action", "text", pe__failed_action_text },
1727  { "failed-action", "xml", pe__failed_action_xml },
1728  { "group", "xml", pe__group_xml },
1729  { "group", "html", pe__group_html },
1730  { "group", "text", pe__group_text },
1731  { "group", "log", pe__group_text },
1732  /* maint-mode only exists for text and log. Other formatters output it as
1733  * part of the cluster-options handler.
1734  */
1735  { "maint-mode", "log", pe__cluster_maint_mode_text },
1736  { "maint-mode", "text", pe__cluster_maint_mode_text },
1737  { "node", "html", pe__node_html },
1738  { "node", "log", pe__node_text },
1739  { "node", "text", pe__node_text },
1740  { "node", "xml", pe__node_xml },
1741  { "node-list", "html", pe__node_list_html },
1742  { "node-list", "log", pe__node_list_text },
1743  { "node-list", "text", pe__node_list_text },
1744  { "node-list", "xml", pe__node_list_xml },
1745  { "node-attribute", "html", pe__node_attribute_html },
1746  { "node-attribute", "log", pe__node_attribute_text },
1747  { "node-attribute", "text", pe__node_attribute_text },
1748  { "node-attribute", "xml", pe__node_attribute_xml },
1749  { "op-history", "html", pe__op_history_text },
1750  { "op-history", "log", pe__op_history_text },
1751  { "op-history", "text", pe__op_history_text },
1752  { "op-history", "xml", pe__op_history_xml },
1753  { "primitive", "xml", pe__resource_xml },
1754  { "primitive", "html", pe__resource_html },
1755  { "primitive", "text", pe__resource_text },
1756  { "primitive", "log", pe__resource_text },
1757  { "resource-history", "html", pe__resource_history_text },
1758  { "resource-history", "log", pe__resource_history_text },
1759  { "resource-history", "text", pe__resource_history_text },
1760  { "resource-history", "xml", pe__resource_history_xml },
1761  { "ticket", "html", pe__ticket_html },
1762  { "ticket", "log", pe__ticket_text },
1763  { "ticket", "text", pe__ticket_text },
1764  { "ticket", "xml", pe__ticket_xml },
1765 
1766  { NULL, NULL, NULL }
1767 };
1768 
1769 void
1771  pcmk__register_messages(out, fmt_functions);
1772 }
1773 
1774 void
1775 pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
1776 {
1777  if (node == NULL) {
1778  crm_trace("<NULL>");
1779  return;
1780  }
1781 
1782  CRM_ASSERT(node->details);
1783  crm_trace("%sNode %s: (weight=%d, fixed=%s)",
1784  node->details->online ? "" : "Unavailable/Unclean ",
1785  node->details->uname, node->weight, node->fixed ? "True" : "False");
1786 
1787  if (details) {
1788  char *pe_mutable = strdup("\t\t");
1789  GListPtr gIter = node->details->running_rsc;
1790  GListPtr unames = NULL;
1791 
1792  unames = g_list_prepend(unames, strdup("*"));
1793 
1794  crm_trace("\t\t===Node Attributes");
1795  g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable);
1796  free(pe_mutable);
1797 
1798  crm_trace("\t\t=== Resources");
1799 
1800  for (; gIter != NULL; gIter = gIter->next) {
1801  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1802 
1803  out->message(out, crm_map_element_name(rsc->xml),
1804  pe_print_pending, rsc, unames);
1805  }
1806 
1807  g_list_free_full(unames, free);
1808  }
1809 }
pe_ticket_s::last_granted
time_t last_granted
Definition: pe_types.h:439
GListPtr
GList * GListPtr
Definition: crm.h:215
pe__node_attribute_html
int pe__node_attribute_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1228
pe_working_set_s::input
xmlNode * input
Definition: pe_types.h:127
pe__clone_html
int pe__clone_html(pcmk__output_t *out, va_list args)
Definition: clone.c:619
XML_RSC_OP_T_EXEC
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:282
XML_LRM_ATTR_TASK_KEY
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:261
rc
int rc
Definition: pcmk_fence.c:34
XML_LRM_ATTR_OPSTATUS
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:270
pe__location_constraint_s::rsc_lh
pe_resource_t * rsc_lh
Definition: internal.h:56
SUMMARY_HEADER
#define SUMMARY_HEADER(rc, out)
Definition: pe_output.c:15
XML_ATTR_UPDATE_USER
#define XML_ATTR_UPDATE_USER
Definition: msg_xml.h:105
pe__cluster_counts_text
int pe__cluster_counts_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:565
pe_node_shared_s::expected_up
gboolean expected_up
Definition: pe_types.h:208
pcmk__plural_s
#define pcmk__plural_s(i)
Definition: internal.h:198
no_quorum_freeze
@ no_quorum_freeze
Definition: pe_types.h:61
pcmk__add_word
char * pcmk__add_word(char *list, const char *word)
Definition: strings.c:517
pe_working_set_s::nodes
GListPtr nodes
Definition: pe_types.h:147
msg_xml.h
XML_ATTR_UPDATE_CLIENT
#define XML_ATTR_UPDATE_CLIENT
Definition: msg_xml.h:104
pe__cluster_counts_xml
int pe__cluster_counts_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:599
pe__cluster_options_text
int pe__cluster_options_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:775
pe_node_shared_s::remote_rsc
pe_resource_t * remote_rsc
Definition: pe_types.h:218
pe_working_set_s::disabled_resources
int disabled_resources
Definition: pe_types.h:173
RSC_ROLE_MASTER
@ RSC_ROLE_MASTER
Definition: common.h:93
pe_working_set_s::blocked_resources
int blocked_resources
Definition: pe_types.h:172
pe_ticket_s::granted
gboolean granted
Definition: pe_types.h:438
create_xml_node
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1976
crm_time_log_timeofday
#define crm_time_log_timeofday
Definition: iso8601.h:65
pe__node_list_text
int pe__node_list_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1314
pe_resource_s::id
char * id
Definition: pe_types.h:307
pe__cluster_times_text
int pe__cluster_times_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:927
pe__clone_xml
int pe__clone_xml(pcmk__output_t *out, va_list args)
Definition: clone.c:575
pe__cluster_dc_xml
int pe__cluster_dc_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:682
pe_node_shared_s::running_rsc
GListPtr running_rsc
Definition: pe_types.h:219
pe__location_constraint_s::id
char * id
Definition: internal.h:55
get_xpath_object
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:211
pcmk__output_create_xml_node
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name)
Definition: output_xml.c:378
pe__cluster_maint_mode_text
int pe__cluster_maint_mode_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:705
pe_node_s::weight
int weight
Definition: pe_types.h:229
pe__cluster_summary
int pe__cluster_summary(pcmk__output_t *out, va_list args)
pe_node_s::details
struct pe_node_shared_s * details
Definition: pe_types.h:232
pe__cluster_stack_text
int pe__cluster_stack_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:863
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:400
pe_node_shared_s::id
const char * id
Definition: pe_types.h:196
pe_working_set_s::dc_node
pe_node_t * dc_node
Definition: pe_types.h:132
internal.h
crm_element_value_ms
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
crm_trace
#define crm_trace(fmt, args...)
Definition: logging.h:369
XML_NVPAIR_ATTR_VALUE
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:340
pe_node_shared_s::pending
gboolean pending
Definition: pe_types.h:204
node_remote
@ node_remote
Definition: pe_types.h:71
XML_ATTR_UNAME
#define XML_ATTR_UNAME
Definition: msg_xml.h:118
pe_ticket_s
Definition: pe_types.h:436
pe__group_xml
int pe__group_xml(pcmk__output_t *out, va_list args)
Definition: group.c:182
pe__bundle_text
int pe__bundle_text(pcmk__output_t *out, va_list args)
Definition: bundle.c:1694
pe__ban_html
int pe__ban_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:445
pcmk__output_xml_peek_parent
xmlNodePtr pcmk__output_xml_peek_parent(pcmk__output_t *out)
Definition: output_xml.c:414
pe__node_display_name
char * pe__node_display_name(pe_node_t *node, bool print_detail)
Definition: pe_output.c:361
pe_node_shared_s::standby_onfail
gboolean standby_onfail
Definition: pe_types.h:203
pe__resource_html
int pe__resource_html(pcmk__output_t *out, va_list args)
Definition: native.c:1112
XML_LRM_ATTR_RC
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:271
pcmk__output_s::message
int(* message)(pcmk__output_t *out, const char *message_id,...)
Definition: output.h:311
pe_node_shared_s::is_dc
gboolean is_dc
Definition: pe_types.h:209
crm_is_true
gboolean crm_is_true(const char *s)
Definition: strings.c:278
pe__cluster_counts_html
int pe__cluster_counts_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:503
pe__resource_history_text
int pe__resource_history_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1561
PCMK__LAST_FAILURE_PREFIX
#define PCMK__LAST_FAILURE_PREFIX
Definition: internal.h:229
pe__group_text
int pe__group_text(pcmk__output_t *out, va_list args)
Definition: group.c:244
ID
#define ID(x)
Definition: msg_xml.h:418
pcmk__output_xml_push_parent
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition: output_xml.c:394
pe__cluster_options_xml
int pe__cluster_options_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:812
pe_ticket_s::id
char * id
Definition: pe_types.h:437
pe__ban_xml
int pe__ban_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:482
crm_xml_escape
char * crm_xml_escape(const char *text)
Definition: xml.c:2653
XML_RSC_OP_T_QUEUE
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:283
pcmkXmlStr
const xmlChar * pcmkXmlStr
Definition: xml.h:51
pcmk_create_html_node
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
pe__cluster_dc_html
int pe__cluster_dc_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:629
pe_node_shared_s::shutdown
gboolean shutdown
Definition: pe_types.h:207
pe_resource_s::xml
xmlNode * xml
Definition: pe_types.h:309
XML_RSC_OP_LAST_RUN
#define XML_RSC_OP_LAST_RUN
Definition: msg_xml.h:281
pe__location_constraint_s::role_filter
enum rsc_role_e role_filter
Definition: internal.h:57
crm_time_log_with_timezone
#define crm_time_log_with_timezone
Definition: iso8601.h:66
pe__bundle_html
int pe__bundle_html(pcmk__output_t *out, va_list args)
Definition: bundle.c:1594
pe__cluster_dc_text
int pe__cluster_dc_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:663
pe__is_remote_node
gboolean pe__is_remote_node(pe_node_t *node)
Definition: remote.c:36
crm_time_set_timet
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition: iso8601.c:1255
pe__node_attribute_text
int pe__node_attribute_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1202
pe_print_rsconly
@ pe_print_rsconly
Definition: common.h:112
XML_LRM_ATTR_TASK
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:260
PCMK__FAIL_COUNT_PREFIX
#define PCMK__FAIL_COUNT_PREFIX
Definition: internal.h:228
pe_node_s::fixed
gboolean fixed
Definition: pe_types.h:230
crm_strdup_printf
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
pe__register_messages
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:1770
pe__cluster_summary_html
int pe__cluster_summary_html(pcmk__output_t *out, va_list args)
XML_CIB_ATTR_WRITTEN
#define XML_CIB_ATTR_WRITTEN
Definition: msg_xml.h:93
pe__resource_xml
int pe__resource_xml(pcmk__output_t *out, va_list args)
Definition: native.c:1043
pcmk__output_xml_create_parent
void void xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name)
Definition: output_xml.c:361
pe_node_shared_s::standby
gboolean standby
Definition: pe_types.h:202
pe__ticket_xml
int pe__ticket_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1669
XML_RSC_OP_LAST_CHANGE
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:280
no_quorum_demote
@ no_quorum_demote
Definition: pe_types.h:65
pe__bundle_xml
int pe__bundle_xml(pcmk__output_t *out, va_list args)
Definition: bundle.c:1498
pe_working_set_s
Definition: pe_types.h:126
node_member
@ node_member
Definition: pe_types.h:70
crm_element_value
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
pe__group_html
int pe__group_html(pcmk__output_t *out, va_list args)
Definition: group.c:219
no_quorum_ignore
@ no_quorum_ignore
Definition: pe_types.h:63
pe__node_list_xml
int pe__node_list_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1453
pcmk__str_in_list
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:660
pe__rscs_brief_output
int pe__rscs_brief_output(pcmk__output_t *out, GListPtr rsc_list, long options, gboolean print_all)
Definition: native.c:1385
pe__cluster_stack_html
int pe__cluster_stack_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:851
pe__failed_action_text
int pe__failed_action_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:944
pcmk_format_nvpair
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:281
pe_resource_s::container
pe_resource_t * container
Definition: pe_types.h:366
pe__output_node
void pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
Definition: pe_output.c:1775
pe__ticket_text
int pe__ticket_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1648
crm_time_as_string
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition: iso8601.c:497
pcmk__output_s
This structure contains everything that makes up a single output formatter.
Definition: output.h:153
crm_parse_int
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:126
XML_LRM_ATTR_EXIT_REASON
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:278
pe__node_xml
int pe__node_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1134
pcmk__message_entry_s
Definition: output.h:73
pe__cluster_times_xml
int pe__cluster_times_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:906
pe_ticket_s::standby
gboolean standby
Definition: pe_types.h:440
pe__cluster_options_html
int pe__cluster_options_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:714
safe_str_neq
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:263
pe__failed_action_xml
int pe__failed_action_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:955
pe_flag_maintenance_mode
#define pe_flag_maintenance_mode
Definition: pe_types.h:94
pcmk__register_messages
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:140
pe__cluster_options_log
int pe__cluster_options_log(pcmk__output_t *out, va_list args)
Definition: pe_output.c:762
XML_ATTR_UPDATE_ORIG
#define XML_ATTR_UPDATE_ORIG
Definition: msg_xml.h:103
pe__clone_text
int pe__clone_text(pcmk__output_t *out, va_list args)
Definition: clone.c:828
pe__node_attribute_xml
int pe__node_attribute_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1258
pe__resource_text
int pe__resource_text(pcmk__output_t *out, va_list args)
Definition: native.c:1131
CRM_ASSERT
#define CRM_ASSERT(expr)
Definition: results.h:42
pe__op_history_text
int pe__op_history_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1479
print_str_str
void print_str_str(gpointer key, gpointer value, gpointer user_data)
Definition: utils.c:1412
pcmk_rc_ok
@ pcmk_rc_ok
Definition: results.h:141
pe_resource_s::migration_threshold
int migration_threshold
Definition: pe_types.h:330
crm_time_new
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:93
iso8601_internal.h
XML_LRM_ATTR_INTERVAL_MS
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:258
pe__ban_text
int pe__ban_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:465
pe__node_text
int pe__node_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1077
no_quorum_suicide
@ no_quorum_suicide
Definition: pe_types.h:64
pe__ticket_html
int pe__ticket_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1627
pcmk__epoch2str
const char * pcmk__epoch2str(time_t *when)
Definition: iso8601.c:1715
pe__name_and_nvpairs_xml
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
crm_time_free
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:141
pe_print_pending
@ pe_print_pending
Definition: common.h:117
pe_flag_stonith_enabled
#define pe_flag_stonith_enabled
Definition: pe_types.h:96
pe_node_shared_s::maintenance
gboolean maintenance
Definition: pe_types.h:210
pe__cluster_times_html
int pe__cluster_times_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:882
pe__is_guest_node
gboolean pe__is_guest_node(pe_node_t *node)
Definition: remote.c:47
pe_resource_s
Definition: pe_types.h:306
pe_working_set_s::flags
unsigned long long flags
Definition: pe_types.h:136
pe_node_shared_s::unclean
gboolean unclean
Definition: pe_types.h:205
pe__location_constraint_s
Definition: internal.h:54
pcmk__output_xml_pop_parent
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:404
pe__cluster_stack_xml
int pe__cluster_stack_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:871
crm_time_log_date
#define crm_time_log_date
Definition: iso8601.h:64
pe_working_set_s::ninstances
int ninstances
Definition: pe_types.h:178
pe_working_set_s::no_quorum_policy
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:139
crm_element_value_epoch
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
pe_flag_symmetric_cluster
#define pe_flag_symmetric_cluster
Definition: pe_types.h:93
XML_LRM_ATTR_CALLID
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:272
pcmk_rc_no_output
@ pcmk_rc_no_output
Definition: results.h:111
pe_node_shared_s::type
enum node_type type
Definition: pe_types.h:198
pe_node_shared_s::online
gboolean online
Definition: pe_types.h:201
pe_node_shared_s::uname
const char * uname
Definition: pe_types.h:197
no_quorum_stop
@ no_quorum_stop
Definition: pe_types.h:62
PCMK__OUTPUT_ARGS
PCMK__OUTPUT_ARGS("cluster-summary", "struct pe_working_set_t *", "gboolean", "gboolean", "gboolean", "gboolean", "gboolean", "gboolean")
Definition: pe_output.c:214
crm_internal.h
pe__op_history_xml
int pe__op_history_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1496
pe_node_s
Definition: pe_types.h:228
name
char * name
Definition: pcmk_fence.c:30
pe__resource_history_xml
int pe__resource_history_xml(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1583
pe__node_html
int pe__node_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1015
pcmk_format_named_time
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:297
pe__node_list_html
int pe__node_list_html(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1279
pcmk_ok
#define pcmk_ok
Definition: results.h:67
node_type
node_type
Definition: pe_types.h:68
crm_time_t
struct crm_time_s crm_time_t
Definition: iso8601.h:32
node_ping
@ node_ping
Definition: pe_types.h:69
pe_node_shared_s::attrs
GHashTable * attrs
Definition: pe_types.h:222
XML_ATTR_HAVE_QUORUM
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:85