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