pacemaker  2.1.0-7c3f660
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pe_output.c
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 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>
13 #include <crm/cib/util.h>
14 #include <crm/msg_xml.h>
15 #include <crm/pengine/internal.h>
16 
17 /* Never display node attributes whose name starts with one of these prefixes */
18 #define FILTER_STR { PCMK__FAIL_COUNT_PREFIX, PCMK__LAST_FAILURE_PREFIX, \
19  "shutdown", "terminate", "standby", "probe_complete", \
20  "#", NULL }
21 
22 static int
23 compare_attribute(gconstpointer a, gconstpointer b)
24 {
25  int rc;
26 
27  rc = strcmp((const char *)a, (const char *)b);
28 
29  return rc;
30 }
31 
46 static gboolean
47 add_extra_info(pe_node_t *node, GList *rsc_list, pe_working_set_t *data_set,
48  const char *attrname, int *expected_score)
49 {
50  GList *gIter = NULL;
51 
52  for (gIter = rsc_list; gIter != NULL; gIter = gIter->next) {
53  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
54  const char *type = g_hash_table_lookup(rsc->meta, "type");
55  const char *name = NULL;
56  GHashTable *params = NULL;
57 
58  if (rsc->children != NULL) {
59  if (add_extra_info(node, rsc->children, data_set, attrname,
60  expected_score)) {
61  return TRUE;
62  }
63  }
64 
65  if (!pcmk__strcase_any_of(type, "ping", "pingd", NULL)) {
66  continue;
67  }
68 
69  params = pe_rsc_params(rsc, node, data_set);
70  name = g_hash_table_lookup(params, "name");
71 
72  if (name == NULL) {
73  name = "pingd";
74  }
75 
76  /* To identify the resource with the attribute name. */
77  if (pcmk__str_eq(name, attrname, pcmk__str_casei)) {
78  int host_list_num = 0;
79  const char *hosts = g_hash_table_lookup(params, "host_list");
80  const char *multiplier = g_hash_table_lookup(params, "multiplier");
81  int multiplier_i;
82 
83  if (hosts) {
84  char **host_list = g_strsplit(hosts, " ", 0);
85  host_list_num = g_strv_length(host_list);
86  g_strfreev(host_list);
87  }
88 
89  if ((multiplier == NULL)
90  || (pcmk__scan_min_int(multiplier, &multiplier_i,
91  INT_MIN) != pcmk_rc_ok)) {
92  /* The ocf:pacemaker:ping resource agent defaults multiplier to
93  * 1. The agent currently does not handle invalid text, but it
94  * should, and this would be a reasonable choice ...
95  */
96  multiplier_i = 1;
97  }
98  *expected_score = host_list_num * multiplier_i;
99 
100  return TRUE;
101  }
102  }
103  return FALSE;
104 }
105 
106 static GList *
107 filter_attr_list(GList *attr_list, char *name)
108 {
109  int i;
110  const char *filt_str[] = FILTER_STR;
111 
112  CRM_CHECK(name != NULL, return attr_list);
113 
114  /* filtering automatic attributes */
115  for (i = 0; filt_str[i] != NULL; i++) {
116  if (g_str_has_prefix(name, filt_str[i])) {
117  return attr_list;
118  }
119  }
120 
121  return g_list_insert_sorted(attr_list, name, compare_attribute);
122 }
123 
124 static GList *
125 get_operation_list(xmlNode *rsc_entry) {
126  GList *op_list = NULL;
127  xmlNode *rsc_op = NULL;
128 
129  for (rsc_op = pcmk__xe_first_child(rsc_entry); rsc_op != NULL;
130  rsc_op = pcmk__xe_next(rsc_op)) {
131  const char *task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
132  const char *interval_ms_s = crm_element_value(rsc_op,
134  const char *op_rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC);
135  int op_rc_i;
136 
137  pcmk__scan_min_int(op_rc, &op_rc_i, 0);
138 
139  /* Display 0-interval monitors as "probe" */
140  if (pcmk__str_eq(task, CRMD_ACTION_STATUS, pcmk__str_casei)
141  && pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches | pcmk__str_casei)) {
142  task = "probe";
143  }
144 
145  /* Ignore notifies and some probes */
146  if (pcmk__str_eq(task, CRMD_ACTION_NOTIFY, pcmk__str_casei) || (pcmk__str_eq(task, "probe", pcmk__str_casei) && (op_rc_i == 7))) {
147  continue;
148  }
149 
150  if (pcmk__str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, pcmk__str_none)) {
151  op_list = g_list_append(op_list, rsc_op);
152  }
153  }
154 
155  op_list = g_list_sort(op_list, sort_op_by_callid);
156  return op_list;
157 }
158 
159 static void
160 add_dump_node(gpointer key, gpointer value, gpointer user_data)
161 {
162  xmlNodePtr node = user_data;
163  pcmk_create_xml_text_node(node, (const char *) key, (const char *) value);
164 }
165 
166 static void
167 append_dump_text(gpointer key, gpointer value, gpointer user_data)
168 {
169  char **dump_text = user_data;
170  char *new_text = crm_strdup_printf("%s %s=%s",
171  *dump_text, (char *)key, (char *)value);
172 
173  free(*dump_text);
174  *dump_text = new_text;
175 }
176 
177 static char *
178 failed_action_string(xmlNodePtr xml_op) {
179  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
180  int rc;
181  int status;
182  const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
183 
184  time_t last_change = 0;
185 
188  &status, 0);
189 
191  &last_change) == pcmk_ok) {
192  crm_time_t *crm_when = crm_time_new(NULL);
193  char *time_s = NULL;
194  char *buf = NULL;
195 
196  crm_time_set_timet(crm_when, &last_change);
198 
199  buf = crm_strdup_printf("%s on %s '%s' (%d): call=%s, status='%s', "
200  "exitreason='%s', " XML_RSC_OP_LAST_CHANGE
201  "='%s', queued=%sms, exec=%sms",
202  op_key ? op_key : ID(xml_op),
204  services_ocf_exitcode_str(rc), rc,
206  services_lrm_status_str(status),
207  exit_reason ? exit_reason : "none",
208  time_s,
211 
212  crm_time_free(crm_when);
213  free(time_s);
214  return buf;
215  } else {
216  return crm_strdup_printf("%s on %s '%s' (%d): call=%s, status=%s, exitreason='%s'",
217  op_key ? op_key : ID(xml_op),
219  services_ocf_exitcode_str(rc), rc,
221  services_lrm_status_str(status),
222  exit_reason ? exit_reason : "none");
223  }
224 }
225 
226 static const char *
227 get_cluster_stack(pe_working_set_t *data_set)
228 {
229  xmlNode *stack = get_xpath_object("//nvpair[@name='cluster-infrastructure']",
230  data_set->input, LOG_DEBUG);
231  return stack? crm_element_value(stack, XML_NVPAIR_ATTR_VALUE) : "unknown";
232 }
233 
234 static char *
235 last_changed_string(const char *last_written, const char *user,
236  const char *client, const char *origin) {
237  if (last_written != NULL || user != NULL || client != NULL || origin != NULL) {
238  return crm_strdup_printf("%s%s%s%s%s%s%s",
239  last_written ? last_written : "",
240  user ? " by " : "",
241  user ? user : "",
242  client ? " via " : "",
243  client ? client : "",
244  origin ? " on " : "",
245  origin ? origin : "");
246  } else {
247  return strdup("");
248  }
249 }
250 
251 static char *
252 op_history_string(xmlNode *xml_op, const char *task, const char *interval_ms_s,
253  int rc, gboolean print_timing) {
254  const char *call = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
255  char *interval_str = NULL;
256  char *buf = NULL;
257 
258  if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
259  char *pair = pcmk__format_nvpair("interval", interval_ms_s, "ms");
260  interval_str = crm_strdup_printf(" %s", pair);
261  free(pair);
262  }
263 
264  if (print_timing) {
265  char *last_change_str = NULL;
266  char *exec_str = NULL;
267  char *queue_str = NULL;
268 
269  const char *value = NULL;
270 
271  time_t epoch = 0;
272 
273  if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE, &epoch) == pcmk_ok)
274  && (epoch > 0)) {
275  char *time = pcmk__format_named_time(XML_RSC_OP_LAST_CHANGE, epoch);
276 
277  last_change_str = crm_strdup_printf(" %s", time);
278  free(time);
279  }
280 
281  value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
282  if (value) {
283  char *pair = pcmk__format_nvpair(XML_RSC_OP_T_EXEC, value, "ms");
284  exec_str = crm_strdup_printf(" %s", pair);
285  free(pair);
286  }
287 
288  value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
289  if (value) {
290  char *pair = pcmk__format_nvpair(XML_RSC_OP_T_QUEUE, value, "ms");
291  queue_str = crm_strdup_printf(" %s", pair);
292  free(pair);
293  }
294 
295  buf = crm_strdup_printf("(%s) %s:%s%s%s%s rc=%d (%s)", call, task,
296  interval_str ? interval_str : "",
297  last_change_str ? last_change_str : "",
298  exec_str ? exec_str : "",
299  queue_str ? queue_str : "",
300  rc, services_ocf_exitcode_str(rc));
301 
302  if (last_change_str) {
303  free(last_change_str);
304  }
305 
306  if (exec_str) {
307  free(exec_str);
308  }
309 
310  if (queue_str) {
311  free(queue_str);
312  }
313  } else {
314  buf = crm_strdup_printf("(%s) %s%s%s", call, task,
315  interval_str ? ":" : "",
316  interval_str ? interval_str : "");
317  }
318 
319  if (interval_str) {
320  free(interval_str);
321  }
322 
323  return buf;
324 }
325 
326 static char *
327 resource_history_string(pe_resource_t *rsc, const char *rsc_id, gboolean all,
328  int failcount, time_t last_failure) {
329  char *buf = NULL;
330 
331  if (rsc == NULL) {
332  buf = crm_strdup_printf("%s: orphan", rsc_id);
333  } else if (all || failcount || last_failure > 0) {
334  char *failcount_s = NULL;
335  char *lastfail_s = NULL;
336 
337  if (failcount > 0) {
338  failcount_s = crm_strdup_printf(" %s=%d", PCMK__FAIL_COUNT_PREFIX,
339  failcount);
340  } else {
341  failcount_s = strdup("");
342  }
343  if (last_failure > 0) {
344  lastfail_s = crm_strdup_printf(" %s='%s'",
346  pcmk__epoch2str(&last_failure));
347  }
348 
349  buf = crm_strdup_printf("%s: migration-threshold=%d%s%s",
350  rsc_id, rsc->migration_threshold, failcount_s,
351  lastfail_s? lastfail_s : "");
352  free(failcount_s);
353  free(lastfail_s);
354  } else {
355  buf = crm_strdup_printf("%s:", rsc_id);
356  }
357 
358  return buf;
359 }
360 
361 PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "gboolean", "gboolean", "gboolean",
362  "gboolean", "gboolean", "gboolean")
363 int
364 pe__cluster_summary(pcmk__output_t *out, va_list args) {
365  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
366  gboolean print_clone_detail = va_arg(args, gboolean);
367  gboolean show_stack = va_arg(args, gboolean);
368  gboolean show_dc = va_arg(args, gboolean);
369  gboolean show_times = va_arg(args, gboolean);
370  gboolean show_counts = va_arg(args, gboolean);
371  gboolean show_options = va_arg(args, gboolean);
372 
373  int rc = pcmk_rc_no_output;
374  const char *stack_s = get_cluster_stack(data_set);
375 
376  if (show_stack) {
377  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
378  out->message(out, "cluster-stack", stack_s);
379  }
380 
381  /* Always print DC if none, even if not requested */
382  if (data_set->dc_node == NULL || show_dc) {
383  xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
384  data_set->input, LOG_DEBUG);
385  const char *dc_version_s = dc_version?
387  : NULL;
388  const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
389  char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, print_clone_detail) : NULL;
390 
391  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
392  out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
393  free(dc_name);
394  }
395 
396  if (show_times) {
397  const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
398  const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
399  const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
400  const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
401 
402  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
403  out->message(out, "cluster-times", last_written, user, client, origin);
404  }
405 
406  if (show_counts) {
407  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
408  out->message(out, "cluster-counts", g_list_length(data_set->nodes),
409  data_set->ninstances, data_set->disabled_resources,
410  data_set->blocked_resources);
411  }
412 
413  if (show_options) {
414  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
415  out->message(out, "cluster-options", data_set);
416  }
417 
418  PCMK__OUTPUT_LIST_FOOTER(out, rc);
419 
420  if (out->message(out, "maint-mode", data_set->flags) == pcmk_rc_ok) {
421  rc = pcmk_rc_ok;
422  }
423 
424  return rc;
425 }
426 
427 PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "gboolean", "gboolean", "gboolean",
428  "gboolean", "gboolean", "gboolean")
429 static int
430 cluster_summary_html(pcmk__output_t *out, va_list args) {
431  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
432  gboolean print_clone_detail = va_arg(args, gboolean);
433  gboolean show_stack = va_arg(args, gboolean);
434  gboolean show_dc = va_arg(args, gboolean);
435  gboolean show_times = va_arg(args, gboolean);
436  gboolean show_counts = va_arg(args, gboolean);
437  gboolean show_options = va_arg(args, gboolean);
438 
439  int rc = pcmk_rc_no_output;
440  const char *stack_s = get_cluster_stack(data_set);
441 
442  if (show_stack) {
443  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
444  out->message(out, "cluster-stack", stack_s);
445  }
446 
447  /* Always print DC if none, even if not requested */
448  if (data_set->dc_node == NULL || show_dc) {
449  xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
450  data_set->input, LOG_DEBUG);
451  const char *dc_version_s = dc_version?
453  : NULL;
454  const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
455  char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, print_clone_detail) : NULL;
456 
457  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
458  out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
459  free(dc_name);
460  }
461 
462  if (show_times) {
463  const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
464  const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
465  const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
466  const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
467 
468  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
469  out->message(out, "cluster-times", last_written, user, client, origin);
470  }
471 
472  if (show_counts) {
473  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
474  out->message(out, "cluster-counts", g_list_length(data_set->nodes),
475  data_set->ninstances, data_set->disabled_resources,
476  data_set->blocked_resources);
477  }
478 
479  if (show_options) {
480  /* Kind of a hack - close the list we may have opened earlier in this
481  * function so we can put all the options into their own list. We
482  * only want to do this on HTML output, though.
483  */
484  PCMK__OUTPUT_LIST_FOOTER(out, rc);
485 
486  out->begin_list(out, NULL, NULL, "Config Options");
487  out->message(out, "cluster-options", data_set);
488  }
489 
490  PCMK__OUTPUT_LIST_FOOTER(out, rc);
491 
492  if (out->message(out, "maint-mode", data_set->flags) == pcmk_rc_ok) {
493  rc = pcmk_rc_ok;
494  }
495 
496  return rc;
497 }
498 
499 char *
500 pe__node_display_name(pe_node_t *node, bool print_detail)
501 {
502  char *node_name;
503  const char *node_host = NULL;
504  const char *node_id = NULL;
505  int name_len;
506 
507  CRM_ASSERT((node != NULL) && (node->details != NULL) && (node->details->uname != NULL));
508 
509  /* Host is displayed only if this is a guest node */
510  if (pe__is_guest_node(node)) {
511  pe_node_t *host_node = pe__current_node(node->details->remote_rsc);
512 
513  if (host_node && host_node->details) {
514  node_host = host_node->details->uname;
515  }
516  if (node_host == NULL) {
517  node_host = ""; /* so we at least get "uname@" to indicate guest */
518  }
519  }
520 
521  /* Node ID is displayed if different from uname and detail is requested */
522  if (print_detail && !pcmk__str_eq(node->details->uname, node->details->id, pcmk__str_casei)) {
523  node_id = node->details->id;
524  }
525 
526  /* Determine name length */
527  name_len = strlen(node->details->uname) + 1;
528  if (node_host) {
529  name_len += strlen(node_host) + 1; /* "@node_host" */
530  }
531  if (node_id) {
532  name_len += strlen(node_id) + 3; /* + " (node_id)" */
533  }
534 
535  /* Allocate and populate display name */
536  node_name = malloc(name_len);
537  CRM_ASSERT(node_name != NULL);
538  strcpy(node_name, node->details->uname);
539  if (node_host) {
540  strcat(node_name, "@");
541  strcat(node_name, node_host);
542  }
543  if (node_id) {
544  strcat(node_name, " (");
545  strcat(node_name, node_id);
546  strcat(node_name, ")");
547  }
548  return node_name;
549 }
550 
551 int
552 pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name
553  , size_t pairs_count, ...)
554 {
555  xmlNodePtr xml_node = NULL;
556  va_list args;
557 
558  CRM_ASSERT(tag_name != NULL);
559 
560  xml_node = pcmk__output_xml_peek_parent(out);
561  CRM_ASSERT(xml_node != NULL);
562  xml_node = is_list
563  ? create_xml_node(xml_node, tag_name)
564  : xmlNewChild(xml_node, NULL, (pcmkXmlStr) tag_name, NULL);
565 
566  va_start(args, pairs_count);
567  while(pairs_count--) {
568  const char *param_name = va_arg(args, const char *);
569  const char *param_value = va_arg(args, const char *);
570  if (param_name && param_value) {
571  crm_xml_add(xml_node, param_name, param_value);
572  }
573  };
574  va_end(args);
575 
576  if (is_list) {
577  pcmk__output_xml_push_parent(out, xml_node);
578  }
579  return pcmk_rc_ok;
580 }
581 
582 static const char *
583 role_desc(enum rsc_role_e role)
584 {
585  if (role == RSC_ROLE_PROMOTED) {
586 #ifdef PCMK__COMPAT_2_0
587  return "as " RSC_ROLE_PROMOTED_LEGACY_S " ";
588 #else
589  return "in " RSC_ROLE_PROMOTED_S " role ";
590 #endif
591  }
592  return "";
593 }
594 
595 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "gboolean")
596 static int
597 ban_html(pcmk__output_t *out, va_list args) {
598  pe_node_t *pe_node = va_arg(args, pe_node_t *);
599  pe__location_t *location = va_arg(args, pe__location_t *);
600  gboolean print_clone_detail = va_arg(args, gboolean);
601 
602  char *node_name = pe__node_display_name(pe_node, print_clone_detail);
603  char *buf = crm_strdup_printf("%s\tprevents %s from running %son %s",
604  location->id, location->rsc_lh->id,
605  role_desc(location->role_filter), node_name);
606 
607  pcmk__output_create_html_node(out, "li", NULL, NULL, buf);
608 
609  free(node_name);
610  free(buf);
611  return pcmk_rc_ok;
612 }
613 
614 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "gboolean")
615 int
616 pe__ban_text(pcmk__output_t *out, va_list args) {
617  pe_node_t *pe_node = va_arg(args, pe_node_t *);
618  pe__location_t *location = va_arg(args, pe__location_t *);
619  gboolean print_clone_detail = va_arg(args, gboolean);
620 
621  char *node_name = pe__node_display_name(pe_node, print_clone_detail);
622  out->list_item(out, NULL, "%s\tprevents %s from running %son %s",
623  location->id, location->rsc_lh->id,
624  role_desc(location->role_filter), node_name);
625 
626  free(node_name);
627  return pcmk_rc_ok;
628 }
629 
630 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "gboolean")
631 static int
632 ban_xml(pcmk__output_t *out, va_list args) {
633  pe_node_t *pe_node = va_arg(args, pe_node_t *);
634  pe__location_t *location = va_arg(args, pe__location_t *);
635  gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
636 
637  const char *promoted_only = pcmk__btoa(location->role_filter == RSC_ROLE_PROMOTED);
638  char *weight_s = pcmk__itoa(pe_node->weight);
639 
640  pcmk__output_create_xml_node(out, "ban",
641  "id", location->id,
642  "resource", location->rsc_lh->id,
643  "node", pe_node->details->uname,
644  "weight", weight_s,
645  "promoted-only", promoted_only,
646  /* This is a deprecated alias for
647  * promoted_only. Removing it will break
648  * backward compatibility of the API schema,
649  * which will require an API schema major
650  * version bump.
651  */
652  "master_only", promoted_only,
653  NULL);
654 
655  free(weight_s);
656  return pcmk_rc_ok;
657 }
658 
659 PCMK__OUTPUT_ARGS("ban-list", "pe_working_set_t *", "const char *", "GList *",
660  "gboolean", "gboolean")
661 static int
662 ban_list(pcmk__output_t *out, va_list args) {
663  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
664  const char *prefix = va_arg(args, const char *);
665  GList *only_rsc = va_arg(args, GList *);
666  gboolean print_clone_detail = va_arg(args, gboolean);
667  gboolean print_spacer = va_arg(args, gboolean);
668 
669  GList *gIter, *gIter2;
670  int rc = pcmk_rc_no_output;
671 
672  /* Print each ban */
673  for (gIter = data_set->placement_constraints; gIter != NULL; gIter = gIter->next) {
674  pe__location_t *location = gIter->data;
675 
676  if (prefix != NULL && !g_str_has_prefix(location->id, prefix)) {
677  continue;
678  }
679 
680  if (!pcmk__str_in_list(only_rsc, rsc_printable_id(location->rsc_lh)) &&
681  !pcmk__str_in_list(only_rsc, rsc_printable_id(uber_parent(location->rsc_lh)))) {
682  continue;
683  }
684 
685  for (gIter2 = location->node_list_rh; gIter2 != NULL; gIter2 = gIter2->next) {
686  pe_node_t *node = (pe_node_t *) gIter2->data;
687 
688  if (node->weight < 0) {
689  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Negative Location Constraints");
690  out->message(out, "ban", node, location, print_clone_detail);
691  }
692  }
693  }
694 
695  PCMK__OUTPUT_LIST_FOOTER(out, rc);
696  return rc;
697 }
698 
699 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
700 static int
701 cluster_counts_html(pcmk__output_t *out, va_list args) {
702  unsigned int nnodes = va_arg(args, unsigned int);
703  int nresources = va_arg(args, int);
704  int ndisabled = va_arg(args, int);
705  int nblocked = va_arg(args, int);
706 
707  xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "li", NULL);
708  xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "li", NULL);
709 
710  char *nnodes_str = crm_strdup_printf("%d node%s configured",
711  nnodes, pcmk__plural_s(nnodes));
712 
713  pcmk_create_html_node(nodes_node, "span", NULL, NULL, nnodes_str);
714  free(nnodes_str);
715 
716  if (ndisabled && nblocked) {
717  char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
718  nresources, pcmk__plural_s(nresources),
719  ndisabled);
720  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
721  free(s);
722 
723  pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
724 
725  s = crm_strdup_printf(", %d ", nblocked);
726  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
727  free(s);
728 
729  pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
730  pcmk_create_html_node(resources_node, "span", NULL, NULL,
731  " from further action due to failure)");
732  } else if (ndisabled && !nblocked) {
733  char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
734  nresources, pcmk__plural_s(nresources),
735  ndisabled);
736  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
737  free(s);
738 
739  pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
740  pcmk_create_html_node(resources_node, "span", NULL, NULL, ")");
741  } else if (!ndisabled && nblocked) {
742  char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
743  nresources, pcmk__plural_s(nresources),
744  nblocked);
745  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
746  free(s);
747 
748  pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
749  pcmk_create_html_node(resources_node, "span", NULL, NULL,
750  " from further action due to failure)");
751  } else {
752  char *s = crm_strdup_printf("%d resource instance%s configured",
753  nresources, pcmk__plural_s(nresources));
754  pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
755  free(s);
756  }
757 
758  return pcmk_rc_ok;
759 }
760 
761 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
762 int
764  unsigned int nnodes = va_arg(args, unsigned int);
765  int nresources = va_arg(args, int);
766  int ndisabled = va_arg(args, int);
767  int nblocked = va_arg(args, int);
768 
769  out->list_item(out, NULL, "%d node%s configured",
770  nnodes, pcmk__plural_s(nnodes));
771 
772  if (ndisabled && nblocked) {
773  out->list_item(out, NULL, "%d resource instance%s configured "
774  "(%d DISABLED, %d BLOCKED from "
775  "further action due to failure)",
776  nresources, pcmk__plural_s(nresources), ndisabled,
777  nblocked);
778  } else if (ndisabled && !nblocked) {
779  out->list_item(out, NULL, "%d resource instance%s configured "
780  "(%d DISABLED)",
781  nresources, pcmk__plural_s(nresources), ndisabled);
782  } else if (!ndisabled && nblocked) {
783  out->list_item(out, NULL, "%d resource instance%s configured "
784  "(%d BLOCKED from further action "
785  "due to failure)",
786  nresources, pcmk__plural_s(nresources), nblocked);
787  } else {
788  out->list_item(out, NULL, "%d resource instance%s configured",
789  nresources, pcmk__plural_s(nresources));
790  }
791 
792  return pcmk_rc_ok;
793 }
794 
795 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
796 static int
797 cluster_counts_xml(pcmk__output_t *out, va_list args) {
798  unsigned int nnodes = va_arg(args, unsigned int);
799  int nresources = va_arg(args, int);
800  int ndisabled = va_arg(args, int);
801  int nblocked = va_arg(args, int);
802 
803  xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "nodes_configured", NULL);
804  xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "resources_configured", NULL);
805 
806  char *s = pcmk__itoa(nnodes);
807  crm_xml_add(nodes_node, "number", s);
808  free(s);
809 
810  s = pcmk__itoa(nresources);
811  crm_xml_add(resources_node, "number", s);
812  free(s);
813 
814  s = pcmk__itoa(ndisabled);
815  crm_xml_add(resources_node, "disabled", s);
816  free(s);
817 
818  s = pcmk__itoa(nblocked);
819  crm_xml_add(resources_node, "blocked", s);
820  free(s);
821 
822  return pcmk_rc_ok;
823 }
824 
825 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
826 static int
827 cluster_dc_html(pcmk__output_t *out, va_list args) {
828  pe_node_t *dc = va_arg(args, pe_node_t *);
829  const char *quorum = va_arg(args, const char *);
830  const char *dc_version_s = va_arg(args, const char *);
831  char *dc_name = va_arg(args, char *);
832 
833  xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
834 
835  pcmk_create_html_node(node, "span", NULL, "bold", "Current DC: ");
836 
837  if (dc) {
838  if (crm_is_true(quorum)) {
839  char *buf = crm_strdup_printf("%s (version %s) - partition with quorum",
840  dc_name, dc_version_s ? dc_version_s : "unknown");
841  pcmk_create_html_node(node, "span", NULL, NULL, buf);
842  free(buf);
843  } else {
844  char *buf = crm_strdup_printf("%s (version %s) - partition",
845  dc_name, dc_version_s ? dc_version_s : "unknown");
846  pcmk_create_html_node(node, "span", NULL, NULL, buf);
847  free(buf);
848 
849  pcmk_create_html_node(node, "span", NULL, "warning", "WITHOUT");
850  pcmk_create_html_node(node, "span", NULL, NULL, "quorum");
851  }
852  } else {
853  pcmk_create_html_node(node ,"span", NULL, "warning", "NONE");
854  }
855 
856  return pcmk_rc_ok;
857 }
858 
859 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
860 int
861 pe__cluster_dc_text(pcmk__output_t *out, va_list args) {
862  pe_node_t *dc = va_arg(args, pe_node_t *);
863  const char *quorum = va_arg(args, const char *);
864  const char *dc_version_s = va_arg(args, const char *);
865  char *dc_name = va_arg(args, char *);
866 
867  if (dc) {
868  out->list_item(out, "Current DC", "%s (version %s) - partition %s quorum",
869  dc_name, dc_version_s ? dc_version_s : "unknown",
870  crm_is_true(quorum) ? "with" : "WITHOUT");
871  } else {
872  out->list_item(out, "Current DC", "NONE");
873  }
874 
875  return pcmk_rc_ok;
876 }
877 
878 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
879 static int
880 cluster_dc_xml(pcmk__output_t *out, va_list args) {
881  pe_node_t *dc = va_arg(args, pe_node_t *);
882  const char *quorum = va_arg(args, const char *);
883  const char *dc_version_s = va_arg(args, const char *);
884  char *dc_name G_GNUC_UNUSED = va_arg(args, char *);
885 
886  if (dc) {
887  pcmk__output_create_xml_node(out, "current_dc",
888  "present", "true",
889  "version", dc_version_s ? dc_version_s : "",
890  "name", dc->details->uname,
891  "id", dc->details->id,
892  "with_quorum", pcmk__btoa(crm_is_true(quorum)),
893  NULL);
894  } else {
895  pcmk__output_create_xml_node(out, "current_dc",
896  "present", "false",
897  NULL);
898  }
899 
900  return pcmk_rc_ok;
901 }
902 
903 PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long int")
904 int
906  unsigned long long flags = va_arg(args, unsigned long long);
907 
909  pcmk__formatted_printf(out, "\n *** Resource management is DISABLED ***\n");
910  pcmk__formatted_printf(out, " The cluster will not attempt to start, stop or recover services\n");
911  return pcmk_rc_ok;
912  } else if (pcmk_is_set(flags, pe_flag_stop_everything)) {
913  pcmk__formatted_printf(out, "\n *** Resource management is DISABLED ***\n");
914  pcmk__formatted_printf(out, " The cluster will keep all resources stopped\n");
915  return pcmk_rc_ok;
916  } else {
917  return pcmk_rc_no_output;
918  }
919 }
920 
921 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
922 static int
923 cluster_options_html(pcmk__output_t *out, va_list args) {
924  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
925 
926  out->list_item(out, NULL, "STONITH of failed nodes %s",
927  pcmk_is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
928 
929  out->list_item(out, NULL, "Cluster is %s",
930  pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
931 
932  switch (data_set->no_quorum_policy) {
933  case no_quorum_freeze:
934  out->list_item(out, NULL, "No quorum policy: Freeze resources");
935  break;
936 
937  case no_quorum_stop:
938  out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
939  break;
940 
941  case no_quorum_demote:
942  out->list_item(out, NULL, "No quorum policy: Demote promotable "
943  "resources and stop all other resources");
944  break;
945 
946  case no_quorum_ignore:
947  out->list_item(out, NULL, "No quorum policy: Ignore");
948  break;
949 
950  case no_quorum_suicide:
951  out->list_item(out, NULL, "No quorum policy: Suicide");
952  break;
953  }
954 
955  if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
956  xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
957 
958  pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
959  pcmk_create_html_node(node, "span", NULL, "bold", "DISABLED");
960  pcmk_create_html_node(node, "span", NULL, NULL,
961  " (the cluster will not attempt to start, stop, or recover services)");
962  } else if (pcmk_is_set(data_set->flags, pe_flag_stop_everything)) {
963  xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
964 
965  pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
966  pcmk_create_html_node(node, "span", NULL, "bold", "STOPPED");
967  pcmk_create_html_node(node, "span", NULL, NULL,
968  " (the cluster will keep all resources stopped)");
969  } else {
970  out->list_item(out, NULL, "Resource management: enabled");
971  }
972 
973  return pcmk_rc_ok;
974 }
975 
976 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
977 static int
978 cluster_options_log(pcmk__output_t *out, va_list args) {
979  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
980 
981  if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
982  return out->info(out, "Resource management is DISABLED. The cluster will not attempt to start, stop or recover services.");
983  } else if (pcmk_is_set(data_set->flags, pe_flag_stop_everything)) {
984  return out->info(out, "Resource management is DISABLED. The cluster has stopped all resources.");
985  } else {
986  return pcmk_rc_no_output;
987  }
988 }
989 
990 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
991 int
993  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
994 
995  out->list_item(out, NULL, "STONITH of failed nodes %s",
996  pcmk_is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
997 
998  out->list_item(out, NULL, "Cluster is %s",
999  pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
1000 
1001  switch (data_set->no_quorum_policy) {
1002  case no_quorum_freeze:
1003  out->list_item(out, NULL, "No quorum policy: Freeze resources");
1004  break;
1005 
1006  case no_quorum_stop:
1007  out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
1008  break;
1009 
1010  case no_quorum_demote:
1011  out->list_item(out, NULL, "No quorum policy: Demote promotable "
1012  "resources and stop all other resources");
1013  break;
1014 
1015  case no_quorum_ignore:
1016  out->list_item(out, NULL, "No quorum policy: Ignore");
1017  break;
1018 
1019  case no_quorum_suicide:
1020  out->list_item(out, NULL, "No quorum policy: Suicide");
1021  break;
1022  }
1023 
1024  return pcmk_rc_ok;
1025 }
1026 
1027 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
1028 static int
1029 cluster_options_xml(pcmk__output_t *out, va_list args) {
1030  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1031 
1032  const char *no_quorum_policy = NULL;
1033 
1034  switch (data_set->no_quorum_policy) {
1035  case no_quorum_freeze:
1036  no_quorum_policy = "freeze";
1037  break;
1038 
1039  case no_quorum_stop:
1040  no_quorum_policy = "stop";
1041  break;
1042 
1043  case no_quorum_demote:
1044  no_quorum_policy = "demote";
1045  break;
1046 
1047  case no_quorum_ignore:
1048  no_quorum_policy = "ignore";
1049  break;
1050 
1051  case no_quorum_suicide:
1052  no_quorum_policy = "suicide";
1053  break;
1054  }
1055 
1056  pcmk__output_create_xml_node(out, "cluster_options",
1057  "stonith-enabled", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)),
1058  "symmetric-cluster", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)),
1059  "no-quorum-policy", no_quorum_policy,
1060  "maintenance-mode", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)),
1061  "stop-all-resources", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_stop_everything)),
1062  NULL);
1063  return pcmk_rc_ok;
1064 }
1065 
1066 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1067 static int
1068 cluster_stack_html(pcmk__output_t *out, va_list args) {
1069  const char *stack_s = va_arg(args, const char *);
1070 
1071  xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
1072 
1073  pcmk_create_html_node(node, "span", NULL, "bold", "Stack: ");
1074  pcmk_create_html_node(node, "span", NULL, NULL, stack_s);
1075 
1076  return pcmk_rc_ok;
1077 }
1078 
1079 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1080 int
1082  const char *stack_s = va_arg(args, const char *);
1083 
1084  out->list_item(out, "Stack", "%s", stack_s);
1085  return pcmk_rc_ok;
1086 }
1087 
1088 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1089 static int
1090 cluster_stack_xml(pcmk__output_t *out, va_list args) {
1091  const char *stack_s = va_arg(args, const char *);
1092 
1093  pcmk__output_create_xml_node(out, "stack",
1094  "type", stack_s,
1095  NULL);
1096 
1097  return pcmk_rc_ok;
1098 }
1099 
1100 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1101 static int
1102 cluster_times_html(pcmk__output_t *out, va_list args) {
1103  const char *last_written = va_arg(args, const char *);
1104  const char *user = va_arg(args, const char *);
1105  const char *client = va_arg(args, const char *);
1106  const char *origin = va_arg(args, const char *);
1107 
1108  xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "li", NULL);
1109  xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "li", NULL);
1110 
1111  char *buf = last_changed_string(last_written, user, client, origin);
1112 
1113  pcmk_create_html_node(updated_node, "span", NULL, "bold", "Last updated: ");
1114  pcmk_create_html_node(updated_node, "span", NULL, NULL,
1115  pcmk__epoch2str(NULL));
1116 
1117  pcmk_create_html_node(changed_node, "span", NULL, "bold", "Last change: ");
1118  pcmk_create_html_node(changed_node, "span", NULL, NULL, buf);
1119 
1120  free(buf);
1121  return pcmk_rc_ok;
1122 }
1123 
1124 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1125 static int
1126 cluster_times_xml(pcmk__output_t *out, va_list args) {
1127  const char *last_written = va_arg(args, const char *);
1128  const char *user = va_arg(args, const char *);
1129  const char *client = va_arg(args, const char *);
1130  const char *origin = va_arg(args, const char *);
1131 
1132  pcmk__output_create_xml_node(out, "last_update",
1133  "time", pcmk__epoch2str(NULL),
1134  NULL);
1135  pcmk__output_create_xml_node(out, "last_change",
1136  "time", last_written ? last_written : "",
1137  "user", user ? user : "",
1138  "client", client ? client : "",
1139  "origin", origin ? origin : "",
1140  NULL);
1141 
1142  return pcmk_rc_ok;
1143 }
1144 
1145 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1146 int
1148  const char *last_written = va_arg(args, const char *);
1149  const char *user = va_arg(args, const char *);
1150  const char *client = va_arg(args, const char *);
1151  const char *origin = va_arg(args, const char *);
1152 
1153  char *buf = last_changed_string(last_written, user, client, origin);
1154 
1155  out->list_item(out, "Last updated", "%s", pcmk__epoch2str(NULL));
1156  out->list_item(out, "Last change", " %s", buf);
1157 
1158  free(buf);
1159  return pcmk_rc_ok;
1160 }
1161 
1162 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
1163 int
1165  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1166 
1167  char *s = failed_action_string(xml_op);
1168 
1169  out->list_item(out, NULL, "%s", s);
1170  free(s);
1171  return pcmk_rc_ok;
1172 }
1173 
1174 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
1175 static int
1176 failed_action_xml(pcmk__output_t *out, va_list args) {
1177  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1178 
1179  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
1180  int rc;
1181  int status;
1182  const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
1183 
1184  time_t epoch = 0;
1185  char *rc_s = NULL;
1186  char *reason_s = crm_xml_escape(exit_reason ? exit_reason : "none");
1187  xmlNodePtr node = NULL;
1188 
1191  &status, 0);
1192 
1193  rc_s = pcmk__itoa(rc);
1194  node = pcmk__output_create_xml_node(out, "failure",
1195  (op_key == NULL)? "id" : "op_key",
1196  (op_key == NULL)? ID(xml_op) : op_key,
1197  "node", crm_element_value(xml_op, XML_ATTR_UNAME),
1198  "exitstatus", services_ocf_exitcode_str(rc),
1199  "exitreason", reason_s,
1200  "exitcode", rc_s,
1201  "call", crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
1202  "status", services_lrm_status_str(status),
1203  NULL);
1204  free(rc_s);
1205 
1207  &epoch) == pcmk_ok) && (epoch > 0)) {
1208  guint interval_ms = 0;
1209  char *s = NULL;
1210  crm_time_t *crm_when = crm_time_new_undefined();
1211  char *rc_change = NULL;
1212 
1213  crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
1214  s = pcmk__itoa(interval_ms);
1215 
1216  crm_time_set_timet(crm_when, &epoch);
1218 
1219  pcmk__xe_set_props(node, XML_RSC_OP_LAST_CHANGE, rc_change,
1220  "queued", crm_element_value(xml_op, XML_RSC_OP_T_QUEUE),
1221  "exec", crm_element_value(xml_op, XML_RSC_OP_T_EXEC),
1222  "interval", s,
1223  "task", crm_element_value(xml_op, XML_LRM_ATTR_TASK),
1224  NULL);
1225 
1226  free(s);
1227  free(rc_change);
1228  crm_time_free(crm_when);
1229  }
1230 
1231  free(reason_s);
1232  return pcmk_rc_ok;
1233 }
1234 
1235 PCMK__OUTPUT_ARGS("failed-action-list", "pe_working_set_t *", "GList *",
1236  "GList *", "gboolean")
1237 static int
1238 failed_action_list(pcmk__output_t *out, va_list args) {
1239  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1240  GList *only_node = va_arg(args, GList *);
1241  GList *only_rsc = va_arg(args, GList *);
1242  gboolean print_spacer = va_arg(args, gboolean);
1243 
1244  xmlNode *xml_op = NULL;
1245  int rc = pcmk_rc_no_output;
1246 
1247  const char *id = NULL;
1248 
1249  if (xmlChildElementCount(data_set->failed) == 0) {
1250  return rc;
1251  }
1252 
1253  for (xml_op = pcmk__xml_first_child(data_set->failed); xml_op != NULL;
1254  xml_op = pcmk__xml_next(xml_op)) {
1255  char *rsc = NULL;
1256 
1257  if (!pcmk__str_in_list(only_node, crm_element_value(xml_op, XML_ATTR_UNAME))) {
1258  continue;
1259  }
1260 
1262  if (parse_op_key(id ? id : ID(xml_op), &rsc, NULL, NULL) == FALSE) {
1263  continue;
1264  }
1265 
1266  if (!pcmk__str_in_list(only_rsc, rsc)) {
1267  free(rsc);
1268  continue;
1269  }
1270 
1271  free(rsc);
1272 
1273  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Failed Resource Actions");
1274  out->message(out, "failed-action", xml_op);
1275  }
1276 
1277  PCMK__OUTPUT_LIST_FOOTER(out, rc);
1278  return rc;
1279 }
1280 
1281 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1282  "gboolean", "gboolean", "gboolean", "GList *", "GList *")
1283 int
1284 pe__node_html(pcmk__output_t *out, va_list args) {
1285  pe_node_t *node = va_arg(args, pe_node_t *);
1286  unsigned int print_opts = va_arg(args, unsigned int);
1287  gboolean full = va_arg(args, gboolean);
1288  const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1289  gboolean print_clone_detail = va_arg(args, gboolean);
1290  gboolean print_brief = va_arg(args, gboolean);
1291  gboolean group_by_node = va_arg(args, gboolean);
1292  GList *only_node = va_arg(args, GList *);
1293  GList *only_rsc = va_arg(args, GList *);
1294 
1295  char *node_name = pe__node_display_name(node, print_clone_detail);
1296  char *buf = crm_strdup_printf("Node: %s", node_name);
1297 
1298  if (full) {
1299  xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li", NULL);
1300 
1301  pcmk_create_html_node(item_node, "span", NULL, NULL, buf);
1302 
1303  if (node->details->standby_onfail && node->details->online) {
1304  pcmk_create_html_node(item_node, "span", NULL, "standby", " standby (on-fail)");
1305  } else if (node->details->standby && node->details->online) {
1306  char *s = crm_strdup_printf(" standby%s", node->details->running_rsc ? " (with active resources)" : "");
1307  pcmk_create_html_node(item_node, "span", NULL, " standby", s);
1308  free(s);
1309  } else if (node->details->standby) {
1310  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (standby)");
1311  } else if (node->details->maintenance && node->details->online) {
1312  pcmk_create_html_node(item_node, "span", NULL, "maint", " maintenance");
1313  } else if (node->details->maintenance) {
1314  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (maintenance)");
1315  } else if (node->details->online) {
1316  pcmk_create_html_node(item_node, "span", NULL, "online", " online");
1317  } else {
1318  pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE");
1319  }
1320  if (print_brief && group_by_node) {
1321  GList *rscs = pe__filter_rsc_list(node->details->running_rsc, only_rsc);
1322 
1323  if (rscs != NULL) {
1324  out->begin_list(out, NULL, NULL, NULL);
1325  pe__rscs_brief_output(out, rscs, print_opts | pe_print_rsconly, FALSE);
1326  out->end_list(out);
1327  }
1328 
1329  } else if (group_by_node) {
1330  GList *lpc2 = NULL;
1331 
1332  out->begin_list(out, NULL, NULL, NULL);
1333  for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) {
1334  pe_resource_t *rsc = (pe_resource_t *) lpc2->data;
1335  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly,
1336  rsc, only_node, only_rsc);
1337  }
1338  out->end_list(out);
1339  }
1340  } else {
1341  out->begin_list(out, NULL, NULL, "%s", buf);
1342  }
1343 
1344  free(buf);
1345  free(node_name);
1346  return pcmk_rc_ok;
1347 }
1348 
1349 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1350  "gboolean", "gboolean", "gboolean", "GList *", "GList *")
1351 int
1352 pe__node_text(pcmk__output_t *out, va_list args) {
1353  pe_node_t *node = va_arg(args, pe_node_t *);
1354  unsigned int print_opts = va_arg(args, unsigned int);
1355  gboolean full = va_arg(args, gboolean);
1356  const char *node_mode = va_arg(args, const char *);
1357  gboolean print_clone_detail = va_arg(args, gboolean);
1358  gboolean print_brief = va_arg(args, gboolean);
1359  gboolean group_by_node = va_arg(args, gboolean);
1360  GList *only_node = va_arg(args, GList *);
1361  GList *only_rsc = va_arg(args, GList *);
1362 
1363  if (full) {
1364  char *node_name = pe__node_display_name(node, print_clone_detail);
1365  char *buf = NULL;
1366 
1367  /* Print the node name and status */
1368  if (pe__is_guest_node(node)) {
1369  buf = crm_strdup_printf("GuestNode %s: %s", node_name, node_mode);
1370  } else if (pe__is_remote_node(node)) {
1371  buf = crm_strdup_printf("RemoteNode %s: %s", node_name, node_mode);
1372  } else {
1373  buf = crm_strdup_printf("Node %s: %s", node_name, node_mode);
1374  }
1375 
1376  /* If we're grouping by node, print its resources */
1377  if (group_by_node) {
1378  if (print_brief) {
1379  GList *rscs = pe__filter_rsc_list(node->details->running_rsc, only_rsc);
1380 
1381  if (rscs != NULL) {
1382  out->begin_list(out, NULL, NULL, "%s", buf);
1383  out->begin_list(out, NULL, NULL, "Resources");
1384 
1385  pe__rscs_brief_output(out, rscs, print_opts | pe_print_rsconly, FALSE);
1386 
1387  out->end_list(out);
1388  out->end_list(out);
1389  }
1390 
1391  } else {
1392  GList *gIter2 = NULL;
1393 
1394  out->begin_list(out, NULL, NULL, "%s", buf);
1395  out->begin_list(out, NULL, NULL, "Resources");
1396 
1397  for (gIter2 = node->details->running_rsc; gIter2 != NULL; gIter2 = gIter2->next) {
1398  pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1399  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly,
1400  rsc, only_node, only_rsc);
1401  }
1402 
1403  out->end_list(out);
1404  out->end_list(out);
1405  }
1406  } else {
1407  out->list_item(out, NULL, "%s", buf);
1408  }
1409 
1410  free(buf);
1411  free(node_name);
1412  } else {
1413  char *node_name = pe__node_display_name(node, print_clone_detail);
1414  out->begin_list(out, NULL, NULL, "Node: %s", node_name);
1415  free(node_name);
1416  }
1417 
1418  return pcmk_rc_ok;
1419 }
1420 
1421 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1422  "gboolean", "gboolean", "gboolean", "GList *", "GList *")
1423 int
1424 pe__node_xml(pcmk__output_t *out, va_list args) {
1425  pe_node_t *node = va_arg(args, pe_node_t *);
1426  unsigned int print_opts = va_arg(args, unsigned int);
1427  gboolean full = va_arg(args, gboolean);
1428  const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1429  gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
1430  gboolean print_brief G_GNUC_UNUSED = va_arg(args, gboolean);
1431  gboolean group_by_node = va_arg(args, gboolean);
1432  GList *only_node = va_arg(args, GList *);
1433  GList *only_rsc = va_arg(args, GList *);
1434 
1435  if (full) {
1436  const char *node_type = "unknown";
1437  char *length_s = pcmk__itoa(g_list_length(node->details->running_rsc));
1438 
1439  switch (node->details->type) {
1440  case node_member:
1441  node_type = "member";
1442  break;
1443  case node_remote:
1444  node_type = "remote";
1445  break;
1446  case node_ping:
1447  node_type = "ping";
1448  break;
1449  }
1450  pe__name_and_nvpairs_xml(out, true, "node", 13,
1451  "name", node->details->uname,
1452  "id", node->details->id,
1453  "online", pcmk__btoa(node->details->online),
1454  "standby", pcmk__btoa(node->details->standby),
1455  "standby_onfail", pcmk__btoa(node->details->standby_onfail),
1456  "maintenance", pcmk__btoa(node->details->maintenance),
1457  "pending", pcmk__btoa(node->details->pending),
1458  "unclean", pcmk__btoa(node->details->unclean),
1459  "shutdown", pcmk__btoa(node->details->shutdown),
1460  "expected_up", pcmk__btoa(node->details->expected_up),
1461  "is_dc", pcmk__btoa(node->details->is_dc),
1462  "resources_running", length_s,
1463  "type", node_type);
1464 
1465  if (pe__is_guest_node(node)) {
1466  xmlNodePtr xml_node = pcmk__output_xml_peek_parent(out);
1467  crm_xml_add(xml_node, "id_as_resource", node->details->remote_rsc->container->id);
1468  }
1469 
1470  if (group_by_node) {
1471  GList *lpc = NULL;
1472 
1473  for (lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) {
1474  pe_resource_t *rsc = (pe_resource_t *) lpc->data;
1475  out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly,
1476  rsc, only_node, only_rsc);
1477  }
1478  }
1479 
1480  free(length_s);
1481 
1482  out->end_list(out);
1483  } else {
1484  pcmk__output_xml_create_parent(out, "node",
1485  "name", node->details->uname,
1486  NULL);
1487  }
1488 
1489  return pcmk_rc_ok;
1490 }
1491 
1492 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1493 int
1495  const char *name = va_arg(args, const char *);
1496  const char *value = va_arg(args, const char *);
1497  gboolean add_extra = va_arg(args, gboolean);
1498  int expected_score = va_arg(args, int);
1499 
1500  if (add_extra) {
1501  int v;
1502 
1503  if (value == NULL) {
1504  v = 0;
1505  } else {
1506  pcmk__scan_min_int(value, &v, INT_MIN);
1507  }
1508  if (v <= 0) {
1509  out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is lost", name, value);
1510  } else if (v < expected_score) {
1511  out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is degraded (Expected=%d)", name, value, expected_score);
1512  } else {
1513  out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1514  }
1515  } else {
1516  out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1517  }
1518 
1519  return pcmk_rc_ok;
1520 }
1521 
1522 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1523 static int
1524 node_attribute_html(pcmk__output_t *out, va_list args) {
1525  const char *name = va_arg(args, const char *);
1526  const char *value = va_arg(args, const char *);
1527  gboolean add_extra = va_arg(args, gboolean);
1528  int expected_score = va_arg(args, int);
1529 
1530  if (add_extra) {
1531  int v;
1532  char *s = crm_strdup_printf("%s: %s", name, value);
1533  xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li", NULL);
1534 
1535  if (value == NULL) {
1536  v = 0;
1537  } else {
1538  pcmk__scan_min_int(value, &v, INT_MIN);
1539  }
1540 
1541  pcmk_create_html_node(item_node, "span", NULL, NULL, s);
1542  free(s);
1543 
1544  if (v <= 0) {
1545  pcmk_create_html_node(item_node, "span", NULL, "bold", "(connectivity is lost)");
1546  } else if (v < expected_score) {
1547  char *buf = crm_strdup_printf("(connectivity is degraded -- expected %d", expected_score);
1548  pcmk_create_html_node(item_node, "span", NULL, "bold", buf);
1549  free(buf);
1550  }
1551  } else {
1552  out->list_item(out, NULL, "%s: %s", name, value);
1553  }
1554 
1555  return pcmk_rc_ok;
1556 }
1557 
1558 PCMK__OUTPUT_ARGS("node-and-op", "pe_working_set_t *", "xmlNodePtr")
1559 static int
1560 node_and_op(pcmk__output_t *out, va_list args) {
1561  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1562  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1563 
1564  pe_resource_t *rsc = NULL;
1565  gchar *node_str = NULL;
1566  char *last_change_str = NULL;
1567 
1568  const char *op_rsc = crm_element_value(xml_op, "resource");
1569  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
1570  int status;
1571  time_t last_change = 0;
1572 
1574  &status, 0);
1575 
1576  rsc = pe_find_resource(data_set->resources, op_rsc);
1577 
1578  if (rsc) {
1579  pe_node_t *node = pe__current_node(rsc);
1580  const char *target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
1581  int opts = pe_print_rsconly | pe_print_pending;
1582 
1583  if (node == NULL) {
1584  node = rsc->pending_node;
1585  }
1586 
1587  node_str = pcmk__native_output_string(rsc, rsc_printable_id(rsc), node,
1588  opts, target_role, false);
1589  } else {
1590  node_str = crm_strdup_printf("Unknown resource %s", op_rsc);
1591  }
1592 
1594  &last_change) == pcmk_ok) {
1595  last_change_str = crm_strdup_printf(", %s=%s, exec=%sms",
1597  pcmk__trim(ctime(&last_change)),
1599  }
1600 
1601  out->list_item(out, NULL, "%s: %s (node=%s, call=%s, rc=%s%s): %s",
1602  node_str, op_key ? op_key : ID(xml_op),
1606  last_change_str ? last_change_str : "",
1607  services_lrm_status_str(status));
1608 
1609  g_free(node_str);
1610  free(last_change_str);
1611  return pcmk_rc_ok;
1612 }
1613 
1614 PCMK__OUTPUT_ARGS("node-and-op", "pe_working_set_t *", "xmlNodePtr")
1615 static int
1616 node_and_op_xml(pcmk__output_t *out, va_list args) {
1617  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1618  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1619 
1620  pe_resource_t *rsc = NULL;
1621  const char *op_rsc = crm_element_value(xml_op, "resource");
1622  const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
1623  int status;
1624  time_t last_change = 0;
1625  xmlNode *node = NULL;
1626 
1628  &status, 0);
1629  node = pcmk__output_create_xml_node(out, "operation",
1630  "op", op_key ? op_key : ID(xml_op),
1631  "node", crm_element_value(xml_op, XML_ATTR_UNAME),
1632  "call", crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
1633  "rc", crm_element_value(xml_op, XML_LRM_ATTR_RC),
1634  "status", services_lrm_status_str(status),
1635  NULL);
1636 
1637  rsc = pe_find_resource(data_set->resources, op_rsc);
1638 
1639  if (rsc) {
1640  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1641  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1642  char *agent_tuple = NULL;
1643 
1644  agent_tuple = crm_strdup_printf("%s:%s:%s", class,
1646  kind);
1647 
1648  pcmk__xe_set_props(node, "rsc", rsc_printable_id(rsc),
1649  "agent", agent_tuple,
1650  NULL);
1651  free(agent_tuple);
1652  }
1653 
1655  &last_change) == pcmk_ok) {
1657  pcmk__trim(ctime(&last_change)),
1659  NULL);
1660  }
1661 
1662  return pcmk_rc_ok;
1663 }
1664 
1665 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1666 static int
1667 node_attribute_xml(pcmk__output_t *out, va_list args) {
1668  const char *name = va_arg(args, const char *);
1669  const char *value = va_arg(args, const char *);
1670  gboolean add_extra = va_arg(args, gboolean);
1671  int expected_score = va_arg(args, int);
1672 
1673  xmlNodePtr node = pcmk__output_create_xml_node(out, "attribute",
1674  "name", name,
1675  "value", value,
1676  NULL);
1677 
1678  if (add_extra) {
1679  char *buf = pcmk__itoa(expected_score);
1680  crm_xml_add(node, "expected", buf);
1681  free(buf);
1682  }
1683 
1684  return pcmk_rc_ok;
1685 }
1686 
1687 PCMK__OUTPUT_ARGS("node-attribute-list", "pe_working_set_t *", "unsigned int",
1688  "gboolean", "gboolean", "gboolean", "gboolean", "GList *",
1689  "GList *")
1690 static int
1691 node_attribute_list(pcmk__output_t *out, va_list args) {
1692  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1693  unsigned int print_opts = va_arg(args, unsigned int);
1694  gboolean print_spacer = va_arg(args, gboolean);
1695  gboolean print_clone_detail = va_arg(args, gboolean);
1696  gboolean print_brief = va_arg(args, gboolean);
1697  gboolean group_by_node = va_arg(args, gboolean);
1698  GList *only_node = va_arg(args, GList *);
1699  GList *only_rsc = va_arg(args, GList *);
1700 
1701  int rc = pcmk_rc_no_output;
1702 
1703  /* Display each node's attributes */
1704  for (GList *gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1705  pe_node_t *node = gIter->data;
1706 
1707  GList *attr_list = NULL;
1708  GHashTableIter iter;
1709  gpointer key;
1710 
1711  if (!node || !node->details || !node->details->online) {
1712  continue;
1713  }
1714 
1715  g_hash_table_iter_init(&iter, node->details->attrs);
1716  while (g_hash_table_iter_next (&iter, &key, NULL)) {
1717  attr_list = filter_attr_list(attr_list, key);
1718  }
1719 
1720  if (attr_list == NULL) {
1721  continue;
1722  }
1723 
1724  if (!pcmk__str_in_list(only_node, node->details->uname)) {
1725  continue;
1726  }
1727 
1728  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Node Attributes");
1729 
1730  out->message(out, "node", node, print_opts, FALSE, NULL,
1731  print_clone_detail, print_brief,
1732  group_by_node, only_node, only_rsc);
1733 
1734  for (GList *aIter = attr_list; aIter != NULL; aIter = aIter->next) {
1735  const char *name = aIter->data;
1736  const char *value = NULL;
1737  int expected_score = 0;
1738  gboolean add_extra = FALSE;
1739 
1740  value = pe_node_attribute_raw(node, name);
1741 
1742  add_extra = add_extra_info(node, node->details->running_rsc,
1743  data_set, name, &expected_score);
1744 
1745  /* Print attribute name and value */
1746  out->message(out, "node-attribute", name, value, add_extra,
1747  expected_score);
1748  }
1749 
1750  g_list_free(attr_list);
1751  out->end_list(out);
1752  }
1753 
1754  PCMK__OUTPUT_LIST_FOOTER(out, rc);
1755  return rc;
1756 }
1757 
1758 PCMK__OUTPUT_ARGS("node-capacity", "pe_node_t *", "const char *")
1759 static int
1760 node_capacity(pcmk__output_t *out, va_list args)
1761 {
1762  pe_node_t *node = va_arg(args, pe_node_t *);
1763  const char *comment = va_arg(args, const char *);
1764 
1765  char *dump_text = crm_strdup_printf("%s: %s capacity:",
1766  comment, node->details->uname);
1767 
1768  g_hash_table_foreach(node->details->utilization, append_dump_text, &dump_text);
1769  out->list_item(out, NULL, "%s", dump_text);
1770  free(dump_text);
1771 
1772  return pcmk_rc_ok;
1773 }
1774 
1775 PCMK__OUTPUT_ARGS("node-capacity", "pe_node_t *", "const char *")
1776 static int
1777 node_capacity_xml(pcmk__output_t *out, va_list args)
1778 {
1779  pe_node_t *node = va_arg(args, pe_node_t *);
1780  const char *comment = va_arg(args, const char *);
1781 
1782  xmlNodePtr xml_node = pcmk__output_create_xml_node(out, "capacity",
1783  "node", node->details->uname,
1784  "comment", comment,
1785  NULL);
1786  g_hash_table_foreach(node->details->utilization, add_dump_node, &xml_node);
1787 
1788  return pcmk_rc_ok;
1789 }
1790 
1791 PCMK__OUTPUT_ARGS("node-history-list", "pe_working_set_t *", "pe_node_t *", "xmlNodePtr",
1792  "GList *", "GList *", "gboolean", "unsigned int", "gboolean",
1793  "gboolean", "gboolean", "gboolean")
1794 static int
1795 node_history_list(pcmk__output_t *out, va_list args) {
1796  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1797  pe_node_t *node = va_arg(args, pe_node_t *);
1798  xmlNode *node_state = va_arg(args, xmlNode *);
1799  GList *only_node = va_arg(args, GList *);
1800  GList *only_rsc = va_arg(args, GList *);
1801  gboolean operations = va_arg(args, gboolean);
1802  unsigned int print_opts = va_arg(args, unsigned int);
1803  gboolean print_clone_detail = va_arg(args, gboolean);
1804  gboolean print_brief = va_arg(args, gboolean);
1805  gboolean group_by_node = va_arg(args, gboolean);
1806  gboolean print_timing = va_arg(args, gboolean);
1807 
1808  xmlNode *lrm_rsc = NULL;
1809  xmlNode *rsc_entry = NULL;
1810  int rc = pcmk_rc_no_output;
1811 
1812  lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
1813  lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
1814 
1815  /* Print history of each of the node's resources */
1816  for (rsc_entry = pcmk__xe_first_child(lrm_rsc); rsc_entry != NULL;
1817  rsc_entry = pcmk__xe_next(rsc_entry)) {
1818 
1819  const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
1820  pe_resource_t *rsc = pe_find_resource(data_set->resources, rsc_id);
1821 
1822  if (!pcmk__str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, pcmk__str_none)) {
1823  continue;
1824  }
1825 
1826  /* We can't use is_filtered here to filter group resources. For is_filtered,
1827  * we have to decide whether to check the parent or not. If we check the
1828  * parent, all elements of a group will always be printed because that's how
1829  * is_filtered works for groups. If we do not check the parent, sometimes
1830  * this will filter everything out.
1831  *
1832  * For other resource types, is_filtered is okay.
1833  */
1834  if (uber_parent(rsc)->variant == pe_group) {
1835  if (!pcmk__str_in_list(only_rsc, rsc_printable_id(rsc)) &&
1836  !pcmk__str_in_list(only_rsc, rsc_printable_id(uber_parent(rsc)))) {
1837  continue;
1838  }
1839  } else {
1840  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1841  continue;
1842  }
1843  }
1844 
1845  if (operations == FALSE) {
1846  time_t last_failure = 0;
1847  int failcount = pe_get_failcount(node, rsc, &last_failure, pe_fc_default,
1848  NULL, data_set);
1849 
1850  if (failcount <= 0) {
1851  continue;
1852  }
1853 
1854  if (rc == pcmk_rc_no_output) {
1855  rc = pcmk_rc_ok;
1856  out->message(out, "node", node, print_opts, FALSE, NULL,
1857  print_clone_detail, print_brief,
1858  group_by_node, only_node, only_rsc);
1859  }
1860 
1861  out->message(out, "resource-history", rsc, rsc_id, FALSE,
1862  failcount, last_failure, FALSE);
1863  } else {
1864  GList *op_list = get_operation_list(rsc_entry);
1865  pe_resource_t *rsc = pe_find_resource(data_set->resources,
1866  crm_element_value(rsc_entry, XML_ATTR_ID));
1867 
1868  if (op_list == NULL) {
1869  continue;
1870  }
1871 
1872  if (rc == pcmk_rc_no_output) {
1873  rc = pcmk_rc_ok;
1874  out->message(out, "node", node, print_opts, FALSE, NULL,
1875  print_clone_detail, print_brief,
1876  group_by_node, only_node, only_rsc);
1877  }
1878 
1879  out->message(out, "resource-operation-list", data_set, rsc, node,
1880  op_list, print_timing);
1881  }
1882  }
1883 
1884  PCMK__OUTPUT_LIST_FOOTER(out, rc);
1885  return rc;
1886 }
1887 
1888 PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int", "gboolean", "gboolean", "gboolean")
1889 static int
1890 node_list_html(pcmk__output_t *out, va_list args) {
1891  GList *nodes = va_arg(args, GList *);
1892  GList *only_node = va_arg(args, GList *);
1893  GList *only_rsc = va_arg(args, GList *);
1894  unsigned int print_opts = va_arg(args, unsigned int);
1895  gboolean print_clone_detail = va_arg(args, gboolean);
1896  gboolean print_brief = va_arg(args, gboolean);
1897  gboolean group_by_node = va_arg(args, gboolean);
1898 
1899  int rc = pcmk_rc_no_output;
1900 
1901  for (GList *gIter = nodes; gIter != NULL; gIter = gIter->next) {
1902  pe_node_t *node = (pe_node_t *) gIter->data;
1903 
1904  if (!pcmk__str_in_list(only_node, node->details->uname)) {
1905  continue;
1906  }
1907 
1908  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Node List");
1909 
1910  out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1911  print_brief, group_by_node, only_node, only_rsc);
1912  }
1913 
1914  PCMK__OUTPUT_LIST_FOOTER(out, rc);
1915  return rc;
1916 }
1917 
1918 PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int", "gboolean", "gboolean", "gboolean")
1919 int
1920 pe__node_list_text(pcmk__output_t *out, va_list args) {
1921  GList *nodes = va_arg(args, GList *);
1922  GList *only_node = va_arg(args, GList *);
1923  GList *only_rsc = va_arg(args, GList *);
1924  unsigned int print_opts = va_arg(args, unsigned int);
1925  gboolean print_clone_detail = va_arg(args, gboolean);
1926  gboolean print_brief = va_arg(args, gboolean);
1927  gboolean group_by_node = va_arg(args, gboolean);
1928 
1929  /* space-separated lists of node names */
1930  char *online_nodes = NULL;
1931  char *online_remote_nodes = NULL;
1932  char *online_guest_nodes = NULL;
1933  char *offline_nodes = NULL;
1934  char *offline_remote_nodes = NULL;
1935 
1936  size_t online_nodes_len = 0;
1937  size_t online_remote_nodes_len = 0;
1938  size_t online_guest_nodes_len = 0;
1939  size_t offline_nodes_len = 0;
1940  size_t offline_remote_nodes_len = 0;
1941 
1942  int rc = pcmk_rc_no_output;
1943 
1944  for (GList *gIter = nodes; gIter != NULL; gIter = gIter->next) {
1945  pe_node_t *node = (pe_node_t *) gIter->data;
1946  const char *node_mode = NULL;
1947  char *node_name = pe__node_display_name(node, print_clone_detail);
1948 
1949  if (!pcmk__str_in_list(only_node, node->details->uname)) {
1950  free(node_name);
1951  continue;
1952  }
1953 
1954  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Node List");
1955 
1956  /* Get node mode */
1957  if (node->details->unclean) {
1958  if (node->details->online) {
1959  node_mode = "UNCLEAN (online)";
1960 
1961  } else if (node->details->pending) {
1962  node_mode = "UNCLEAN (pending)";
1963 
1964  } else {
1965  node_mode = "UNCLEAN (offline)";
1966  }
1967 
1968  } else if (node->details->pending) {
1969  node_mode = "pending";
1970 
1971  } else if (node->details->standby_onfail && node->details->online) {
1972  node_mode = "standby (on-fail)";
1973 
1974  } else if (node->details->standby) {
1975  if (node->details->online) {
1976  if (node->details->running_rsc) {
1977  node_mode = "standby (with active resources)";
1978  } else {
1979  node_mode = "standby";
1980  }
1981  } else {
1982  node_mode = "OFFLINE (standby)";
1983  }
1984 
1985  } else if (node->details->maintenance) {
1986  if (node->details->online) {
1987  node_mode = "maintenance";
1988  } else {
1989  node_mode = "OFFLINE (maintenance)";
1990  }
1991 
1992  } else if (node->details->online) {
1993  node_mode = "online";
1994  if (group_by_node == FALSE) {
1995  if (pe__is_guest_node(node)) {
1996  pcmk__add_word(&online_guest_nodes,
1997  &online_guest_nodes_len, node_name);
1998  } else if (pe__is_remote_node(node)) {
1999  pcmk__add_word(&online_remote_nodes,
2000  &online_remote_nodes_len, node_name);
2001  } else {
2002  pcmk__add_word(&online_nodes, &online_nodes_len, node_name);
2003  }
2004  free(node_name);
2005  continue;
2006  }
2007 
2008  } else {
2009  node_mode = "OFFLINE";
2010  if (group_by_node == FALSE) {
2011  if (pe__is_remote_node(node)) {
2012  pcmk__add_word(&offline_remote_nodes,
2013  &offline_remote_nodes_len, node_name);
2014  } else if (pe__is_guest_node(node)) {
2015  /* ignore offline guest nodes */
2016  } else {
2017  pcmk__add_word(&offline_nodes,
2018  &offline_nodes_len, node_name);
2019  }
2020  free(node_name);
2021  continue;
2022  }
2023  }
2024 
2025  /* If we get here, node is in bad state, or we're grouping by node */
2026  out->message(out, "node", node, print_opts, TRUE, node_mode, print_clone_detail,
2027  print_brief, group_by_node, only_node, only_rsc);
2028  free(node_name);
2029  }
2030 
2031  /* If we're not grouping by node, summarize nodes by status */
2032  if (online_nodes) {
2033  out->list_item(out, "Online", "[ %s ]", online_nodes);
2034  free(online_nodes);
2035  }
2036  if (offline_nodes) {
2037  out->list_item(out, "OFFLINE", "[ %s ]", offline_nodes);
2038  free(offline_nodes);
2039  }
2040  if (online_remote_nodes) {
2041  out->list_item(out, "RemoteOnline", "[ %s ]", online_remote_nodes);
2042  free(online_remote_nodes);
2043  }
2044  if (offline_remote_nodes) {
2045  out->list_item(out, "RemoteOFFLINE", "[ %s ]", offline_remote_nodes);
2046  free(offline_remote_nodes);
2047  }
2048  if (online_guest_nodes) {
2049  out->list_item(out, "GuestOnline", "[ %s ]", online_guest_nodes);
2050  free(online_guest_nodes);
2051  }
2052 
2053  PCMK__OUTPUT_LIST_FOOTER(out, rc);
2054  return rc;
2055 }
2056 
2057 PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int", "gboolean", "gboolean", "gboolean")
2058 static int
2059 node_list_xml(pcmk__output_t *out, va_list args) {
2060  GList *nodes = va_arg(args, GList *);
2061  GList *only_node = va_arg(args, GList *);
2062  GList *only_rsc = va_arg(args, GList *);
2063  unsigned int print_opts = va_arg(args, unsigned int);
2064  gboolean print_clone_detail = va_arg(args, gboolean);
2065  gboolean print_brief = va_arg(args, gboolean);
2066  gboolean group_by_node = va_arg(args, gboolean);
2067 
2068  out->begin_list(out, NULL, NULL, "nodes");
2069  for (GList *gIter = nodes; gIter != NULL; gIter = gIter->next) {
2070  pe_node_t *node = (pe_node_t *) gIter->data;
2071 
2072  if (!pcmk__str_in_list(only_node, node->details->uname)) {
2073  continue;
2074  }
2075 
2076  out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
2077  print_brief, group_by_node, only_node, only_rsc);
2078  }
2079  out->end_list(out);
2080 
2081  return pcmk_rc_ok;
2082 }
2083 
2084 PCMK__OUTPUT_ARGS("node-summary", "pe_working_set_t *", "GList *", "GList *",
2085  "gboolean", "unsigned int", "gboolean", "gboolean", "gboolean",
2086  "gboolean", "gboolean")
2087 static int
2088 node_summary(pcmk__output_t *out, va_list args) {
2089  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2090  GList *only_node = va_arg(args, GList *);
2091  GList *only_rsc = va_arg(args, GList *);
2092  gboolean operations = va_arg(args, gboolean);
2093  unsigned int print_opts = va_arg(args, unsigned int);
2094  gboolean print_clone_detail = va_arg(args, gboolean);
2095  gboolean print_brief = va_arg(args, gboolean);
2096  gboolean group_by_node = va_arg(args, gboolean);
2097  gboolean print_timing = va_arg(args, gboolean);
2098  gboolean print_spacer = va_arg(args, gboolean);
2099 
2100  xmlNode *node_state = NULL;
2101  xmlNode *cib_status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
2102  int rc = pcmk_rc_no_output;
2103 
2104  if (xmlChildElementCount(cib_status) == 0) {
2105  return rc;
2106  }
2107 
2108  /* Print each node in the CIB status */
2109  for (node_state = pcmk__xe_first_child(cib_status); node_state != NULL;
2110  node_state = pcmk__xe_next(node_state)) {
2111  pe_node_t *node;
2112 
2113  if (!pcmk__str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, pcmk__str_none)) {
2114  continue;
2115  }
2116 
2117  node = pe_find_node_id(data_set->nodes, ID(node_state));
2118 
2119  if (!node || !node->details || !node->details->online) {
2120  continue;
2121  }
2122 
2123  if (!pcmk__str_in_list(only_node, node->details->uname)) {
2124  continue;
2125  }
2126 
2127  PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, operations ? "Operations" : "Migration Summary");
2128 
2129  out->message(out, "node-history-list", data_set, node, node_state,
2130  only_node, only_rsc, operations, print_opts,
2131  print_clone_detail, print_brief, group_by_node, print_timing);
2132  }
2133 
2134  PCMK__OUTPUT_LIST_FOOTER(out, rc);
2135  return rc;
2136 }
2137 
2138 PCMK__OUTPUT_ARGS("node-weight", "pe_resource_t *", "const char *", "const char *", "char *")
2139 static int
2140 node_weight(pcmk__output_t *out, va_list args)
2141 {
2142  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2143  const char *prefix = va_arg(args, const char *);
2144  const char *uname = va_arg(args, const char *);
2145  char *score = va_arg(args, char *);
2146 
2147  if (rsc) {
2148  out->list_item(out, NULL, "%s: %s allocation score on %s: %s",
2149  prefix, rsc->id, uname, score);
2150  } else {
2151  out->list_item(out, NULL, "%s: %s = %s", prefix, uname, score);
2152  }
2153 
2154  return pcmk_rc_ok;
2155 }
2156 
2157 PCMK__OUTPUT_ARGS("node-weight", "pe_resource_t *", "const char *", "const char *", "char *")
2158 static int
2159 node_weight_xml(pcmk__output_t *out, va_list args)
2160 {
2161  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2162  const char *prefix = va_arg(args, const char *);
2163  const char *uname = va_arg(args, const char *);
2164  char *score = va_arg(args, char *);
2165 
2166  xmlNodePtr node = pcmk__output_create_xml_node(out, "node_weight",
2167  "function", prefix,
2168  "node", uname,
2169  "score", score,
2170  NULL);
2171 
2172  if (rsc) {
2173  crm_xml_add(node, "id", rsc->id);
2174  }
2175 
2176  return pcmk_rc_ok;
2177 }
2178 
2179 PCMK__OUTPUT_ARGS("op-history", "xmlNodePtr", "const char *", "const char *", "int", "gboolean")
2180 int
2182  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
2183  const char *task = va_arg(args, const char *);
2184  const char *interval_ms_s = va_arg(args, const char *);
2185  int rc = va_arg(args, int);
2186  gboolean print_timing = va_arg(args, gboolean);
2187 
2188  char *buf = op_history_string(xml_op, task, interval_ms_s, rc, print_timing);
2189 
2190  out->list_item(out, NULL, "%s", buf);
2191 
2192  free(buf);
2193  return pcmk_rc_ok;
2194 }
2195 
2196 PCMK__OUTPUT_ARGS("op-history", "xmlNodePtr", "const char *", "const char *", "int", "gboolean")
2197 static int
2198 op_history_xml(pcmk__output_t *out, va_list args) {
2199  xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
2200  const char *task = va_arg(args, const char *);
2201  const char *interval_ms_s = va_arg(args, const char *);
2202  int rc = va_arg(args, int);
2203  gboolean print_timing = va_arg(args, gboolean);
2204 
2205  char *rc_s = pcmk__itoa(rc);
2206  xmlNodePtr node = pcmk__output_create_xml_node(out, "operation_history",
2207  "call", crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
2208  "task", task,
2209  "rc", rc_s,
2210  "rc_text", services_ocf_exitcode_str(rc),
2211  NULL);
2212  free(rc_s);
2213 
2214  if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
2215  char *s = crm_strdup_printf("%sms", interval_ms_s);
2216  crm_xml_add(node, "interval", s);
2217  free(s);
2218  }
2219 
2220  if (print_timing) {
2221  const char *value = NULL;
2222  time_t epoch = 0;
2223 
2225  &epoch) == pcmk_ok) && (epoch > 0)) {
2227  }
2228 
2229  value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
2230  if (value) {
2231  char *s = crm_strdup_printf("%sms", value);
2232  crm_xml_add(node, XML_RSC_OP_T_EXEC, s);
2233  free(s);
2234  }
2235  value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
2236  if (value) {
2237  char *s = crm_strdup_printf("%sms", value);
2238  crm_xml_add(node, XML_RSC_OP_T_QUEUE, s);
2239  free(s);
2240  }
2241  }
2242 
2243  return pcmk_rc_ok;
2244 }
2245 
2246 PCMK__OUTPUT_ARGS("promotion-score", "pe_resource_t *", "pe_node_t *", "char *")
2247 static int
2248 promotion_score(pcmk__output_t *out, va_list args)
2249 {
2250  pe_resource_t *child_rsc = va_arg(args, pe_resource_t *);
2251  pe_node_t *chosen = va_arg(args, pe_node_t *);
2252  char *score = va_arg(args, char *);
2253 
2254  out->list_item(out, NULL, "%s promotion score on %s: %s",
2255  child_rsc->id,
2256  chosen? chosen->details->uname : "none",
2257  score);
2258  return pcmk_rc_ok;
2259 }
2260 
2261 PCMK__OUTPUT_ARGS("promotion-score", "pe_resource_t *", "pe_node_t *", "char *")
2262 static int
2263 promotion_score_xml(pcmk__output_t *out, va_list args)
2264 {
2265  pe_resource_t *child_rsc = va_arg(args, pe_resource_t *);
2266  pe_node_t *chosen = va_arg(args, pe_node_t *);
2267  char *score = va_arg(args, char *);
2268 
2269  xmlNodePtr node = pcmk__output_create_xml_node(out, "promotion_score",
2270  "id", child_rsc->id,
2271  "score", score,
2272  NULL);
2273 
2274  if (chosen) {
2275  crm_xml_add(node, "node", chosen->details->uname);
2276  }
2277 
2278  return pcmk_rc_ok;
2279 }
2280 
2281 PCMK__OUTPUT_ARGS("resource-config", "pe_resource_t *", "gboolean")
2282 static int
2283 resource_config(pcmk__output_t *out, va_list args) {
2284  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2285  gboolean raw = va_arg(args, gboolean);
2286 
2287  char *rsc_xml = NULL;
2288 
2289  if (raw) {
2290  rsc_xml = dump_xml_formatted(rsc->orig_xml ? rsc->orig_xml : rsc->xml);
2291  } else {
2292  rsc_xml = dump_xml_formatted(rsc->xml);
2293  }
2294 
2295  pcmk__formatted_printf(out, "Resource XML:\n");
2296  out->output_xml(out, "xml", rsc_xml);
2297 
2298  free(rsc_xml);
2299  return pcmk_rc_ok;
2300 }
2301 
2302 PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
2303 int
2305  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2306  const char *rsc_id = va_arg(args, const char *);
2307  gboolean all = va_arg(args, gboolean);
2308  int failcount = va_arg(args, int);
2309  time_t last_failure = va_arg(args, int);
2310  gboolean as_header = va_arg(args, gboolean);
2311 
2312  char *buf = resource_history_string(rsc, rsc_id, all, failcount, last_failure);
2313 
2314  if (as_header) {
2315  out->begin_list(out, NULL, NULL, "%s", buf);
2316  } else {
2317  out->list_item(out, NULL, "%s", buf);
2318  }
2319 
2320  free(buf);
2321  return pcmk_rc_ok;
2322 }
2323 
2324 PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
2325 static int
2326 resource_history_xml(pcmk__output_t *out, va_list args) {
2327  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2328  const char *rsc_id = va_arg(args, const char *);
2329  gboolean all = va_arg(args, gboolean);
2330  int failcount = va_arg(args, int);
2331  time_t last_failure = va_arg(args, int);
2332  gboolean as_header = va_arg(args, gboolean);
2333 
2334  xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource_history",
2335  "id", rsc_id,
2336  NULL);
2337 
2338  if (rsc == NULL) {
2339  crm_xml_add(node, "orphan", "true");
2340  } else if (all || failcount || last_failure > 0) {
2341  char *migration_s = pcmk__itoa(rsc->migration_threshold);
2342 
2343  pcmk__xe_set_props(node, "orphan", "false",
2344  "migration-threshold", migration_s,
2345  NULL);
2346  free(migration_s);
2347 
2348  if (failcount > 0) {
2349  char *s = pcmk__itoa(failcount);
2350 
2352  free(s);
2353  }
2354 
2355  if (last_failure > 0) {
2356  crm_xml_add(node, PCMK__LAST_FAILURE_PREFIX, pcmk__epoch2str(&last_failure));
2357  }
2358  }
2359 
2360  if (as_header == FALSE) {
2362  }
2363 
2364  return pcmk_rc_ok;
2365 }
2366 
2367 static void
2368 print_resource_header(pcmk__output_t *out, gboolean group_by_node,
2369  gboolean inactive_resources)
2370 {
2371  if (group_by_node) {
2372  /* Active resources have already been printed by node */
2373  out->begin_list(out, NULL, NULL, "Inactive Resources");
2374  } else if (inactive_resources) {
2375  out->begin_list(out, NULL, NULL, "Full List of Resources");
2376  } else {
2377  out->begin_list(out, NULL, NULL, "Active Resources");
2378  }
2379 }
2380 
2381 
2382 PCMK__OUTPUT_ARGS("resource-list", "pe_working_set_t *", "unsigned int", "gboolean",
2383  "gboolean", "gboolean", "gboolean", "GList *", "GList *", "gboolean")
2384 static int
2385 resource_list(pcmk__output_t *out, va_list args)
2386 {
2387  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2388  unsigned int print_opts = va_arg(args, unsigned int);
2389  gboolean group_by_node = va_arg(args, gboolean);
2390  gboolean inactive_resources = va_arg(args, gboolean);
2391  gboolean brief_output = va_arg(args, gboolean);
2392  gboolean print_summary = va_arg(args, gboolean);
2393  GList *only_node = va_arg(args, GList *);
2394  GList *only_rsc = va_arg(args, GList *);
2395  gboolean print_spacer = va_arg(args, gboolean);
2396 
2397  GList *rsc_iter;
2398  int rc = pcmk_rc_no_output;
2399  bool printed_header = false;
2400 
2401  /* If we already showed active resources by node, and
2402  * we're not showing inactive resources, we have nothing to do
2403  */
2404  if (group_by_node && !inactive_resources) {
2405  return rc;
2406  }
2407 
2408  /* If we haven't already printed resources grouped by node,
2409  * and brief output was requested, print resource summary */
2410  if (brief_output && !group_by_node) {
2411  GList *rscs = pe__filter_rsc_list(data_set->resources, only_rsc);
2412 
2413  PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2414  print_resource_header(out, group_by_node, inactive_resources);
2415  printed_header = true;
2416 
2417  rc = pe__rscs_brief_output(out, rscs, print_opts, inactive_resources);
2418  g_list_free(rscs);
2419  }
2420 
2421  /* For each resource, display it if appropriate */
2422  for (rsc_iter = data_set->resources; rsc_iter != NULL; rsc_iter = rsc_iter->next) {
2423  pe_resource_t *rsc = (pe_resource_t *) rsc_iter->data;
2424  int x;
2425 
2426  /* Complex resources may have some sub-resources active and some inactive */
2427  gboolean is_active = rsc->fns->active(rsc, TRUE);
2428  gboolean partially_active = rsc->fns->active(rsc, FALSE);
2429 
2430  /* Skip inactive orphans (deleted but still in CIB) */
2431  if (pcmk_is_set(rsc->flags, pe_rsc_orphan) && !is_active) {
2432  continue;
2433 
2434  /* Skip active resources if we already displayed them by node */
2435  } else if (group_by_node) {
2436  if (is_active) {
2437  continue;
2438  }
2439 
2440  /* Skip primitives already counted in a brief summary */
2441  } else if (brief_output && (rsc->variant == pe_native)) {
2442  continue;
2443 
2444  /* Skip resources that aren't at least partially active,
2445  * unless we're displaying inactive resources
2446  */
2447  } else if (!partially_active && !inactive_resources) {
2448  continue;
2449 
2450  } else if (partially_active && !pe__rsc_running_on_any_node_in_list(rsc, only_node)) {
2451  continue;
2452  }
2453 
2454  if (!printed_header) {
2455  PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2456  print_resource_header(out, group_by_node, inactive_resources);
2457  printed_header = true;
2458  }
2459 
2460  /* Print this resource */
2461  x = out->message(out, crm_map_element_name(rsc->xml), print_opts, rsc,
2462  only_node, only_rsc);
2463  if (x == pcmk_rc_ok) {
2464  rc = pcmk_rc_ok;
2465  }
2466  }
2467 
2468  if (print_summary && rc != pcmk_rc_ok) {
2469  if (!printed_header) {
2470  PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2471  print_resource_header(out, group_by_node, inactive_resources);
2472  printed_header = true;
2473  }
2474 
2475  if (group_by_node) {
2476  out->list_item(out, NULL, "No inactive resources");
2477  } else if (inactive_resources) {
2478  out->list_item(out, NULL, "No resources");
2479  } else {
2480  out->list_item(out, NULL, "No active resources");
2481  }
2482  }
2483 
2484  if (printed_header) {
2485  out->end_list(out);
2486  }
2487 
2488  return rc;
2489 }
2490 
2491 PCMK__OUTPUT_ARGS("resource-operation-list", "pe_working_set_t *", "pe_resource_t *",
2492  "pe_node_t *", "GList *", "gboolean")
2493 static int
2494 resource_operation_list(pcmk__output_t *out, va_list args)
2495 {
2496  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2497  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2498  pe_node_t *node = va_arg(args, pe_node_t *);
2499  GList *op_list = va_arg(args, GList *);
2500  gboolean print_timing = va_arg(args, gboolean);
2501 
2502  GList *gIter = NULL;
2503  int rc = pcmk_rc_no_output;
2504 
2505  /* Print each operation */
2506  for (gIter = op_list; gIter != NULL; gIter = gIter->next) {
2507  xmlNode *xml_op = (xmlNode *) gIter->data;
2508  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
2509  const char *interval_ms_s = crm_element_value(xml_op,
2511  const char *op_rc = crm_element_value(xml_op, XML_LRM_ATTR_RC);
2512  int op_rc_i;
2513 
2514  pcmk__scan_min_int(op_rc, &op_rc_i, 0);
2515 
2516  /* Display 0-interval monitors as "probe" */
2517  if (pcmk__str_eq(task, CRMD_ACTION_STATUS, pcmk__str_casei)
2518  && pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches | pcmk__str_casei)) {
2519  task = "probe";
2520  }
2521 
2522  /* If this is the first printed operation, print heading for resource */
2523  if (rc == pcmk_rc_no_output) {
2524  time_t last_failure = 0;
2525  int failcount = pe_get_failcount(node, rsc, &last_failure, pe_fc_default,
2526  NULL, data_set);
2527 
2528  out->message(out, "resource-history", rsc, rsc_printable_id(rsc), TRUE,
2529  failcount, last_failure, TRUE);
2530  rc = pcmk_rc_ok;
2531  }
2532 
2533  /* Print the operation */
2534  out->message(out, "op-history", xml_op, task, interval_ms_s,
2535  op_rc_i, print_timing);
2536  }
2537 
2538  /* Free the list we created (no need to free the individual items) */
2539  g_list_free(op_list);
2540 
2541  PCMK__OUTPUT_LIST_FOOTER(out, rc);
2542  return rc;
2543 }
2544 
2545 PCMK__OUTPUT_ARGS("resource-util", "pe_resource_t *", "pe_node_t *", "const char *")
2546 static int
2547 resource_util(pcmk__output_t *out, va_list args)
2548 {
2549  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2550  pe_node_t *node = va_arg(args, pe_node_t *);
2551  const char *fn = va_arg(args, const char *);
2552 
2553  char *dump_text = crm_strdup_printf("%s: %s utilization on %s:",
2554  fn, rsc->id, node->details->uname);
2555 
2556  g_hash_table_foreach(rsc->utilization, append_dump_text, &dump_text);
2557  out->list_item(out, NULL, "%s", dump_text);
2558  free(dump_text);
2559 
2560  return pcmk_rc_ok;
2561 }
2562 
2563 PCMK__OUTPUT_ARGS("resource-util", "pe_resource_t *", "pe_node_t *", "const char *")
2564 static int
2565 resource_util_xml(pcmk__output_t *out, va_list args)
2566 {
2567  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2568  pe_node_t *node = va_arg(args, pe_node_t *);
2569  const char *fn = va_arg(args, const char *);
2570 
2571  xmlNodePtr xml_node = pcmk__output_create_xml_node(out, "utilization",
2572  "resource", rsc->id,
2573  "node", node->details->uname,
2574  "function", fn,
2575  NULL);
2576  g_hash_table_foreach(rsc->utilization, add_dump_node, &xml_node);
2577 
2578  return pcmk_rc_ok;
2579 }
2580 
2581 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2582 static int
2583 ticket_html(pcmk__output_t *out, va_list args) {
2584  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
2585 
2586  if (ticket->last_granted > -1) {
2587  char *time = pcmk__format_named_time("last-granted",
2588  ticket->last_granted);
2589 
2590  out->list_item(out, NULL, "%s:\t%s%s %s", ticket->id,
2591  ticket->granted ? "granted" : "revoked",
2592  ticket->standby ? " [standby]" : "",
2593  time);
2594  free(time);
2595  } else {
2596  out->list_item(out, NULL, "%s:\t%s%s", ticket->id,
2597  ticket->granted ? "granted" : "revoked",
2598  ticket->standby ? " [standby]" : "");
2599  }
2600 
2601  return pcmk_rc_ok;
2602 }
2603 
2604 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2605 int
2606 pe__ticket_text(pcmk__output_t *out, va_list args) {
2607  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
2608 
2609  if (ticket->last_granted > -1) {
2610  char *time = pcmk__format_named_time("last-granted",
2611  ticket->last_granted);
2612 
2613  out->list_item(out, ticket->id, "%s%s %s",
2614  ticket->granted ? "granted" : "revoked",
2615  ticket->standby ? " [standby]" : "",
2616  time);
2617  free(time);
2618  } else {
2619  out->list_item(out, ticket->id, "%s%s",
2620  ticket->granted ? "granted" : "revoked",
2621  ticket->standby ? " [standby]" : "");
2622  }
2623 
2624  return pcmk_rc_ok;
2625 }
2626 
2627 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2628 static int
2629 ticket_xml(pcmk__output_t *out, va_list args) {
2630  pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
2631 
2632  xmlNodePtr node = NULL;
2633 
2634  node = pcmk__output_create_xml_node(out, "ticket",
2635  "id", ticket->id,
2636  "status", ticket->granted ? "granted" : "revoked",
2637  "standby", pcmk__btoa(ticket->standby),
2638  NULL);
2639 
2640  if (ticket->last_granted > -1) {
2641  crm_xml_add(node, "last-granted", pcmk__epoch2str(&ticket->last_granted));
2642  }
2643 
2644  return pcmk_rc_ok;
2645 }
2646 
2647 PCMK__OUTPUT_ARGS("ticket-list", "pe_working_set_t *", "gboolean")
2648 static int
2649 ticket_list(pcmk__output_t *out, va_list args) {
2650  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2651  gboolean print_spacer = va_arg(args, gboolean);
2652 
2653  GHashTableIter iter;
2654  gpointer key, value;
2655 
2656  if (g_hash_table_size(data_set->tickets) == 0) {
2657  return pcmk_rc_no_output;
2658  }
2659 
2660  PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2661 
2662  /* Print section heading */
2663  out->begin_list(out, NULL, NULL, "Tickets");
2664 
2665  /* Print each ticket */
2666  g_hash_table_iter_init(&iter, data_set->tickets);
2667  while (g_hash_table_iter_next(&iter, &key, &value)) {
2668  pe_ticket_t *ticket = (pe_ticket_t *) value;
2669  out->message(out, "ticket", ticket);
2670  }
2671 
2672  /* Close section */
2673  out->end_list(out);
2674  return pcmk_rc_ok;
2675 }
2676 
2677 static pcmk__message_entry_t fmt_functions[] = {
2678  { "ban", "html", ban_html },
2679  { "ban", "log", pe__ban_text },
2680  { "ban", "text", pe__ban_text },
2681  { "ban", "xml", ban_xml },
2682  { "ban-list", "default", ban_list },
2683  { "bundle", "xml", pe__bundle_xml },
2684  { "bundle", "html", pe__bundle_html },
2685  { "bundle", "text", pe__bundle_text },
2686  { "bundle", "log", pe__bundle_text },
2687  { "clone", "xml", pe__clone_xml },
2688  { "clone", "html", pe__clone_html },
2689  { "clone", "text", pe__clone_text },
2690  { "clone", "log", pe__clone_text },
2691  { "cluster-counts", "html", cluster_counts_html },
2692  { "cluster-counts", "log", pe__cluster_counts_text },
2693  { "cluster-counts", "text", pe__cluster_counts_text },
2694  { "cluster-counts", "xml", cluster_counts_xml },
2695  { "cluster-dc", "html", cluster_dc_html },
2696  { "cluster-dc", "log", pe__cluster_dc_text },
2697  { "cluster-dc", "text", pe__cluster_dc_text },
2698  { "cluster-dc", "xml", cluster_dc_xml },
2699  { "cluster-options", "html", cluster_options_html },
2700  { "cluster-options", "log", cluster_options_log },
2701  { "cluster-options", "text", pe__cluster_options_text },
2702  { "cluster-options", "xml", cluster_options_xml },
2703  { "cluster-summary", "default", pe__cluster_summary },
2704  { "cluster-summary", "html", cluster_summary_html },
2705  { "cluster-stack", "html", cluster_stack_html },
2706  { "cluster-stack", "log", pe__cluster_stack_text },
2707  { "cluster-stack", "text", pe__cluster_stack_text },
2708  { "cluster-stack", "xml", cluster_stack_xml },
2709  { "cluster-times", "html", cluster_times_html },
2710  { "cluster-times", "log", pe__cluster_times_text },
2711  { "cluster-times", "text", pe__cluster_times_text },
2712  { "cluster-times", "xml", cluster_times_xml },
2713  { "failed-action", "default", pe__failed_action_text },
2714  { "failed-action", "xml", failed_action_xml },
2715  { "failed-action-list", "default", failed_action_list },
2716  { "group", "xml", pe__group_xml },
2717  { "group", "html", pe__group_html },
2718  { "group", "text", pe__group_text },
2719  { "group", "log", pe__group_text },
2720  { "maint-mode", "text", pe__cluster_maint_mode_text },
2721  { "node", "html", pe__node_html },
2722  { "node", "log", pe__node_text },
2723  { "node", "text", pe__node_text },
2724  { "node", "xml", pe__node_xml },
2725  { "node-and-op", "default", node_and_op },
2726  { "node-and-op", "xml", node_and_op_xml },
2727  { "node-capacity", "default", node_capacity },
2728  { "node-capacity", "xml", node_capacity_xml },
2729  { "node-history-list", "default", node_history_list },
2730  { "node-list", "html", node_list_html },
2731  { "node-list", "log", pe__node_list_text },
2732  { "node-list", "text", pe__node_list_text },
2733  { "node-list", "xml", node_list_xml },
2734  { "node-weight", "default", node_weight },
2735  { "node-weight", "xml", node_weight_xml },
2736  { "node-attribute", "html", node_attribute_html },
2737  { "node-attribute", "log", pe__node_attribute_text },
2738  { "node-attribute", "text", pe__node_attribute_text },
2739  { "node-attribute", "xml", node_attribute_xml },
2740  { "node-attribute-list", "default", node_attribute_list },
2741  { "node-summary", "default", node_summary },
2742  { "op-history", "default", pe__op_history_text },
2743  { "op-history", "xml", op_history_xml },
2744  { "primitive", "xml", pe__resource_xml },
2745  { "primitive", "html", pe__resource_html },
2746  { "primitive", "text", pe__resource_text },
2747  { "primitive", "log", pe__resource_text },
2748  { "promotion-score", "default", promotion_score },
2749  { "promotion-score", "xml", promotion_score_xml },
2750  { "resource-config", "default", resource_config },
2751  { "resource-history", "default", pe__resource_history_text },
2752  { "resource-history", "xml", resource_history_xml },
2753  { "resource-list", "default", resource_list },
2754  { "resource-operation-list", "default", resource_operation_list },
2755  { "resource-util", "default", resource_util },
2756  { "resource-util", "xml", resource_util_xml },
2757  { "ticket", "html", ticket_html },
2758  { "ticket", "log", pe__ticket_text },
2759  { "ticket", "text", pe__ticket_text },
2760  { "ticket", "xml", ticket_xml },
2761  { "ticket-list", "default", ticket_list },
2762 
2763  { NULL, NULL, NULL }
2764 };
2765 
2766 void
2768  pcmk__register_messages(out, fmt_functions);
2769 }
2770 
2771 void
2772 pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
2773 {
2774  if (node == NULL) {
2775  crm_trace("<NULL>");
2776  return;
2777  }
2778 
2779  CRM_ASSERT(node->details);
2780  crm_trace("%sNode %s: (weight=%d, fixed=%s)",
2781  node->details->online ? "" : "Unavailable/Unclean ",
2782  node->details->uname, node->weight, node->fixed ? "True" : "False");
2783 
2784  if (details) {
2785  char *pe_mutable = strdup("\t\t");
2786  GList *gIter = node->details->running_rsc;
2787  GList *all = NULL;
2788 
2789  all = g_list_prepend(all, strdup("*"));
2790 
2791  crm_trace("\t\t===Node Attributes");
2792  g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable);
2793  free(pe_mutable);
2794 
2795  crm_trace("\t\t=== Resources");
2796 
2797  for (; gIter != NULL; gIter = gIter->next) {
2798  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2799 
2800  out->message(out, crm_map_element_name(rsc->xml),
2801  pe_print_pending, rsc, all, all);
2802  }
2803 
2804  g_list_free_full(all, free);
2805  }
2806 }
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition: iso8601.c:117
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:317
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:446
#define XML_ATTR_UPDATE_ORIG
Definition: msg_xml.h:136
enum rsc_role_e role_filter
Definition: internal.h:171
xmlNode * orig_xml
Definition: pe_types.h:323
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:149
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: operations.c:185
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...)
Definition: output_xml.c:465
int pe__cluster_maint_mode_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:905
#define XML_ATTR_UPDATE_CLIENT
Definition: msg_xml.h:137
xmlNode * failed
Definition: pe_types.h:165
GHashTable * attrs
Definition: pe_types.h:234
gboolean fixed
Definition: pe_types.h:242
int pe__failed_action_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1164
int pe__ticket_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:2606
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:127
#define crm_time_log_timeofday
Definition: iso8601.h:67
int pe__cluster_summary(pcmk__output_t *out, va_list args)
pe_resource_t * container
Definition: pe_types.h:379
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:929
#define XML_ATTR_TYPE
Definition: msg_xml.h:132
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define FILTER_STR
Definition: pe_output.c:18
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, long options, gboolean print_all)
Definition: native.c:1262
GList * children
Definition: pe_types.h:376
#define pe_flag_symmetric_cluster
Definition: pe_types.h:95
gboolean standby
Definition: pe_types.h:459
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition: cib_utils.c:146
xmlNode * xml
Definition: pe_types.h:322
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:881
int pe__cluster_options_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:992
#define pe_flag_maintenance_mode
Definition: pe_types.h:96
xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: xml.c:733
#define XML_ATTR_UPDATE_USER
Definition: msg_xml.h:138
pe_resource_t * remote_rsc
Definition: pe_types.h:230
#define CRMD_ACTION_NOTIFY
Definition: crm.h:187
GHashTable * meta
Definition: pe_types.h:372
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:319
resource_object_functions_t * fns
Definition: pe_types.h:331
#define XML_LRM_TAG_RESOURCE
Definition: msg_xml.h:264
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:324
int pe__cluster_times_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1147
int pe__cluster_counts_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:763
xmlNodePtr pcmk__output_xml_peek_parent(pcmk__output_t *out)
Definition: output_xml.c:527
int(* message)(pcmk__output_t *out, const char *message_id,...)
gboolean pending
Definition: pe_types.h:216
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: utils.c:1632
#define RSC_ROLE_PROMOTED_LEGACY_S
Definition: common.h:116
void pcmk__xe_set_props(xmlNodePtr node,...)
Definition: xml.c:2972
pe_resource_t * pe_find_resource(GList *rsc_list, const char *id_rh)
Definition: status.c:382
int pe__ban_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:616
enum crm_ais_msg_types type
Definition: cpg.c:48
#define XML_CIB_TAG_LRM
Definition: msg_xml.h:262
pe_resource_t * rsc_lh
Definition: internal.h:170
int migration_threshold
Definition: pe_types.h:343
GHashTable * tickets
Definition: pe_types.h:152
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:417
int pe__resource_text(pcmk__output_t *out, va_list args)
Definition: native.c:999
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:320
char * pcmk__format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:304
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
int pe__group_text(pcmk__output_t *out, va_list args)
Definition: group.c:291
#define PCMK__LAST_FAILURE_PREFIX
Definition: internal.h:319
char * pe__node_display_name(pe_node_t *node, bool print_detail)
Definition: pe_output.c:500
int pe__bundle_html(pcmk__output_t *out, va_list args)
Definition: bundle.c:1597
int pe__op_history_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:2181
void void void pcmk__formatted_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
GList * resources
Definition: pe_types.h:158
GList * nodes
Definition: pe_types.h:157
#define pe_flag_stop_everything
Definition: pe_types.h:105
int pe__clone_html(pcmk__output_t *out, va_list args)
Definition: clone.c:668
int pe__node_list_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1920
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition: utils.c:2412
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:285
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
gboolean is_dc
Definition: pe_types.h:221
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:298
bool pe__is_remote_node(const pe_node_t *node)
Definition: remote.c:25
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:297
int weight
Definition: pe_types.h:241
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:623
int pe__bundle_text(pcmk__output_t *out, va_list args)
Definition: bundle.c:1739
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:903
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition: output_xml.c:495
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
#define XML_ATTR_ID
Definition: msg_xml.h:129
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:530
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:198
bool pe__is_guest_node(const pe_node_t *node)
Definition: remote.c:33
#define PCMK__OUTPUT_ARGS(ARGS...)
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:552
xmlNode * pcmk_create_xml_text_node(xmlNode *parent, const char *name, const char *content)
Definition: xml.c:721
int pe__group_html(pcmk__output_t *out, va_list args)
Definition: group.c:236
#define crm_trace(fmt, args...)
Definition: logging.h:356
int pe__clone_xml(pcmk__output_t *out, va_list args)
Definition: clone.c:610
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition: iso8601.c:1255
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
int blocked_resources
Definition: pe_types.h:182
struct pe_node_shared_s * details
Definition: pe_types.h:244
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:267
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:118
unsigned long long flags
Definition: pe_types.h:347
const char * uname
Definition: pe_types.h:209
GHashTable * pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Definition: complex.c:457
#define XML_ATTR_UNAME
Definition: msg_xml.h:151
int pe__resource_history_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:2304
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
char * dump_xml_formatted(xmlNode *msg)
Definition: xml.c:2006
#define pe_flag_stonith_enabled
Definition: pe_types.h:98
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:651
const char * pe_node_attribute_raw(pe_node_t *node, const char *name)
Definition: common.c:635
#define PCMK__FAIL_COUNT_PREFIX
Definition: internal.h:318
time_t last_granted
Definition: pe_types.h:458
GHashTable * utilization
Definition: pe_types.h:374
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:233
gboolean standby
Definition: pe_types.h:214
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:315
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:2767
gboolean expected_up
Definition: pe_types.h:220
#define crm_time_log_with_timezone
Definition: iso8601.h:68
enum pe_obj_types variant
Definition: pe_types.h:329
int pe__cluster_dc_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:861
xmlNode * input
Definition: pe_types.h:137
gboolean granted
Definition: pe_types.h:457
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:511
#define RSC_ROLE_PROMOTED_S
Definition: common.h:114
const char * pcmk__epoch2str(time_t *when)
Definition: iso8601.c:1715
const char * id
Definition: pe_types.h:208
char * id
Definition: pe_types.h:456
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:900
const xmlChar * pcmkXmlStr
Definition: xml.h:51
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
Definition: status.c:418
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
GList * running_rsc
Definition: pe_types.h:231
pe_node_t * dc_node
Definition: pe_types.h:142
int pe__bundle_xml(pcmk__output_t *out, va_list args)
Definition: bundle.c:1474
gboolean(* is_filtered)(pe_resource_t *, GList *, gboolean)
Definition: pe_types.h:57
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
int pe__clone_text(pcmk__output_t *out, va_list args)
Definition: clone.c:908
pe_node_t * pending_node
Definition: pe_types.h:382
int pe__node_text(pcmk__output_t *out, va_list args)
#define XML_LRM_TAG_RESOURCES
Definition: msg_xml.h:263
#define CRM_ASSERT(expr)
Definition: results.h:42
int disabled_resources
Definition: pe_types.h:183
const char * rsc_printable_id(pe_resource_t *rsc)
Definition: utils.c:1911
#define XML_CIB_ATTR_WRITTEN
Definition: msg_xml.h:126
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:93
int pe__cluster_stack_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1081
bool pe__rsc_running_on_any_node_in_list(pe_resource_t *rsc, GList *node_list)
Definition: utils.c:2393
node_type
Definition: pe_types.h:70
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:295
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:309
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:378
int pe__node_attribute_text(pcmk__output_t *out, va_list args)
Definition: pe_output.c:1494
GHashTable * utilization
Definition: pe_types.h:235
gboolean shutdown
Definition: pe_types.h:219
char uname[MAX_NAME]
Definition: cpg.c:50
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:307
int pe__resource_html(pcmk__output_t *out, va_list args)
Definition: native.c:975
#define pcmk__plural_s(i)
rsc_role_e
Possible roles that a resource can be in.
Definition: common.h:92
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:143
gboolean maintenance
Definition: pe_types.h:222
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:308
#define pcmk_ok
Definition: results.h:67
GList * placement_constraints
Definition: pe_types.h:159
gchar * pcmk__native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node, long options, const char *target_role, bool show_nodes)
Definition: native.c:544
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:179
int pe__node_html(pcmk__output_t *out, va_list args)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:31
gboolean crm_is_true(const char *s)
Definition: strings.c:415
char * pcmk__trim(char *str)
Definition: strings.c:455
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:265
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:52
unsigned long long flags
Definition: pe_types.h:146
#define ID(x)
Definition: msg_xml.h:456
void pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
Definition: pe_output.c:2772
char * crm_xml_escape(const char *text)
Definition: xml.c:1335
gboolean standby_onfail
Definition: pe_types.h:215
void print_str_str(gpointer key, gpointer value, gpointer user_data)
Definition: utils.c:1330
char * name
Definition: pcmk_fence.c:31
gboolean unclean
Definition: pe_types.h:217
enum node_type type
Definition: pe_types.h:210
#define pe_rsc_orphan
Definition: pe_types.h:248
#define crm_time_log_date
Definition: iso8601.h:66
xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name,...)
Definition: output_xml.c:432
gboolean online
Definition: pe_types.h:213
uint64_t flags
Definition: remote.c:149
int pe_get_failcount(pe_node_t *node, pe_resource_t *rsc, time_t *last_failure, uint32_t flags, xmlNode *xml_op, pe_working_set_t *data_set)
Definition: failcounts.c:251
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:266
char * id
Definition: pe_types.h:320
#define CRMD_ACTION_STATUS
Definition: crm.h:190
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:141