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