pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
pcmk_output.c
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2023 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 General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 #include <crm/common/output.h>
12 #include <crm/common/results.h>
13 #include <crm/msg_xml.h>
14 #include <crm/stonith-ng.h>
15 #include <crm/fencing/internal.h>
16 #include <crm/pengine/internal.h>
17 #include <libxml/tree.h>
18 #include <pacemaker-internal.h>
19 
20 #include <inttypes.h>
21 #include <stdint.h>
22 
23 static char *
24 colocations_header(pcmk_resource_t *rsc, pcmk__colocation_t *cons,
25  bool dependents) {
26  char *retval = NULL;
27 
28  if (cons->primary_role > pcmk_role_started) {
29  retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
30  rsc->id, pcmk_readable_score(cons->score),
31  (dependents? "needs" : "with"),
32  role2text(cons->primary_role), cons->id);
33  } else {
34  retval = crm_strdup_printf("%s (score=%s, id=%s)",
35  rsc->id, pcmk_readable_score(cons->score),
36  cons->id);
37  }
38  return retval;
39 }
40 
41 static void
42 colocations_xml_node(pcmk__output_t *out, pcmk_resource_t *rsc,
43  pcmk__colocation_t *cons) {
44  xmlNodePtr node = NULL;
45 
47  "id", cons->id,
48  "rsc", cons->dependent->id,
49  "with-rsc", cons->primary->id,
50  "score",
52  NULL);
53 
54  if (cons->node_attribute) {
55  xmlSetProp(node, (pcmkXmlStr) "node-attribute",
56  (pcmkXmlStr) cons->node_attribute);
57  }
58 
59  if (cons->dependent_role != pcmk_role_unknown) {
60  xmlSetProp(node, (pcmkXmlStr) "rsc-role",
62  }
63 
64  if (cons->primary_role != pcmk_role_unknown) {
65  xmlSetProp(node, (pcmkXmlStr) "with-rsc-role",
67  }
68 }
69 
70 static int
71 do_locations_list_xml(pcmk__output_t *out, pcmk_resource_t *rsc,
72  bool add_header)
73 {
74  GList *lpc = NULL;
75  GList *list = rsc->rsc_location;
76  int rc = pcmk_rc_no_output;
77 
78  for (lpc = list; lpc != NULL; lpc = lpc->next) {
79  pe__location_t *cons = lpc->data;
80 
81  GList *lpc2 = NULL;
82 
83  for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
84  pcmk_node_t *node = (pcmk_node_t *) lpc2->data;
85 
86  if (add_header) {
87  PCMK__OUTPUT_LIST_HEADER(out, false, rc, "locations");
88  }
89 
91  "node", node->details->uname,
92  "rsc", rsc->id,
93  "id", cons->id,
94  "score",
96  NULL);
97  }
98  }
99 
100  if (add_header) {
101  PCMK__OUTPUT_LIST_FOOTER(out, rc);
102  }
103 
104  return rc;
105 }
106 
107 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pcmk_resource_t *",
108  "pcmk_node_t *", "pcmk_node_t *", "pcmk_action_t *",
109  "pcmk_action_t *")
110 static int
111 rsc_action_item(pcmk__output_t *out, va_list args)
112 {
113  const char *change = va_arg(args, const char *);
114  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
115  pcmk_node_t *origin = va_arg(args, pcmk_node_t *);
116  pcmk_node_t *destination = va_arg(args, pcmk_node_t *);
117  pcmk_action_t *action = va_arg(args, pcmk_action_t *);
118  pcmk_action_t *source = va_arg(args, pcmk_action_t *);
119 
120  int len = 0;
121  char *reason = NULL;
122  char *details = NULL;
123  bool same_host = false;
124  bool same_role = false;
125  bool need_role = false;
126 
127  static int rsc_width = 5;
128  static int detail_width = 5;
129 
131  CRM_ASSERT(destination != NULL || origin != NULL);
132 
133  if (source == NULL) {
134  source = action;
135  }
136 
137  len = strlen(rsc->id);
138  if (len > rsc_width) {
139  rsc_width = len + 2;
140  }
141 
142  if ((rsc->role > pcmk_role_started)
143  || (rsc->next_role > pcmk_role_unpromoted)) {
144  need_role = true;
145  }
146 
147  if (pe__same_node(origin, destination)) {
148  same_host = true;
149  }
150 
151  if (rsc->role == rsc->next_role) {
152  same_role = true;
153  }
154 
155  if (need_role && (origin == NULL)) {
156  /* Starting and promoting a promotable clone instance */
157  details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role),
158  role2text(rsc->next_role),
159  pe__node_name(destination));
160 
161  } else if (origin == NULL) {
162  /* Starting a resource */
163  details = crm_strdup_printf("%s", pe__node_name(destination));
164 
165  } else if (need_role && (destination == NULL)) {
166  /* Stopping a promotable clone instance */
167  details = crm_strdup_printf("%s %s", role2text(rsc->role),
168  pe__node_name(origin));
169 
170  } else if (destination == NULL) {
171  /* Stopping a resource */
172  details = crm_strdup_printf("%s", pe__node_name(origin));
173 
174  } else if (need_role && same_role && same_host) {
175  /* Recovering, restarting or re-promoting a promotable clone instance */
176  details = crm_strdup_printf("%s %s", role2text(rsc->role),
177  pe__node_name(origin));
178 
179  } else if (same_role && same_host) {
180  /* Recovering or Restarting a normal resource */
181  details = crm_strdup_printf("%s", pe__node_name(origin));
182 
183  } else if (need_role && same_role) {
184  /* Moving a promotable clone instance */
185  details = crm_strdup_printf("%s -> %s %s", pe__node_name(origin),
186  pe__node_name(destination),
187  role2text(rsc->role));
188 
189  } else if (same_role) {
190  /* Moving a normal resource */
191  details = crm_strdup_printf("%s -> %s", pe__node_name(origin),
192  pe__node_name(destination));
193 
194  } else if (same_host) {
195  /* Promoting or demoting a promotable clone instance */
196  details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role),
197  role2text(rsc->next_role),
198  pe__node_name(origin));
199 
200  } else {
201  /* Moving and promoting/demoting */
202  details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role),
203  pe__node_name(origin),
204  role2text(rsc->next_role),
205  pe__node_name(destination));
206  }
207 
208  len = strlen(details);
209  if (len > detail_width) {
210  detail_width = len;
211  }
212 
213  if ((source->reason != NULL)
214  && !pcmk_is_set(action->flags, pcmk_action_runnable)) {
215  reason = crm_strdup_printf("due to %s (blocked)", source->reason);
216 
217  } else if (source->reason) {
218  reason = crm_strdup_printf("due to %s", source->reason);
219 
220  } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
221  reason = strdup("blocked");
222 
223  }
224 
225  out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s",
226  change, rsc_width, rsc->id, detail_width, details,
227  ((reason == NULL)? "" : " "), pcmk__s(reason, ""));
228 
229  free(details);
230  free(reason);
231  return pcmk_rc_ok;
232 }
233 
234 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pcmk_resource_t *",
235  "pcmk_node_t *", "pcmk_node_t *", "pcmk_action_t *",
236  "pcmk_action_t *")
237 static int
238 rsc_action_item_xml(pcmk__output_t *out, va_list args)
239 {
240  const char *change = va_arg(args, const char *);
241  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
242  pcmk_node_t *origin = va_arg(args, pcmk_node_t *);
243  pcmk_node_t *destination = va_arg(args, pcmk_node_t *);
244  pcmk_action_t *action = va_arg(args, pcmk_action_t *);
245  pcmk_action_t *source = va_arg(args, pcmk_action_t *);
246 
247  char *change_str = NULL;
248 
249  bool same_host = false;
250  bool same_role = false;
251  bool need_role = false;
252  xmlNode *xml = NULL;
253 
255  CRM_ASSERT(destination != NULL || origin != NULL);
256 
257  if (source == NULL) {
258  source = action;
259  }
260 
261  if ((rsc->role > pcmk_role_started)
262  || (rsc->next_role > pcmk_role_unpromoted)) {
263  need_role = true;
264  }
265 
266  if (pe__same_node(origin, destination)) {
267  same_host = true;
268  }
269 
270  if (rsc->role == rsc->next_role) {
271  same_role = true;
272  }
273 
274  change_str = g_ascii_strdown(change, -1);
275  xml = pcmk__output_create_xml_node(out, "rsc_action",
276  "action", change_str,
277  "resource", rsc->id,
278  NULL);
279  g_free(change_str);
280 
281  if (need_role && (origin == NULL)) {
282  /* Starting and promoting a promotable clone instance */
283  pcmk__xe_set_props(xml,
284  "role", role2text(rsc->role),
285  "next-role", role2text(rsc->next_role),
286  "dest", destination->details->uname,
287  NULL);
288 
289  } else if (origin == NULL) {
290  /* Starting a resource */
291  crm_xml_add(xml, "node", destination->details->uname);
292 
293  } else if (need_role && (destination == NULL)) {
294  /* Stopping a promotable clone instance */
295  pcmk__xe_set_props(xml,
296  "role", role2text(rsc->role),
297  "node", origin->details->uname,
298  NULL);
299 
300  } else if (destination == NULL) {
301  /* Stopping a resource */
302  crm_xml_add(xml, "node", origin->details->uname);
303 
304  } else if (need_role && same_role && same_host) {
305  /* Recovering, restarting or re-promoting a promotable clone instance */
306  pcmk__xe_set_props(xml,
307  "role", role2text(rsc->role),
308  "source", origin->details->uname,
309  NULL);
310 
311  } else if (same_role && same_host) {
312  /* Recovering or Restarting a normal resource */
313  crm_xml_add(xml, "source", origin->details->uname);
314 
315  } else if (need_role && same_role) {
316  /* Moving a promotable clone instance */
317  pcmk__xe_set_props(xml,
318  "source", origin->details->uname,
319  "dest", destination->details->uname,
320  "role", role2text(rsc->role),
321  NULL);
322 
323  } else if (same_role) {
324  /* Moving a normal resource */
325  pcmk__xe_set_props(xml,
326  "source", origin->details->uname,
327  "dest", destination->details->uname,
328  NULL);
329 
330  } else if (same_host) {
331  /* Promoting or demoting a promotable clone instance */
332  pcmk__xe_set_props(xml,
333  "role", role2text(rsc->role),
334  "next-role", role2text(rsc->next_role),
335  "source", origin->details->uname,
336  NULL);
337 
338  } else {
339  /* Moving and promoting/demoting */
340  pcmk__xe_set_props(xml,
341  "role", role2text(rsc->role),
342  "source", origin->details->uname,
343  "next-role", role2text(rsc->next_role),
344  "dest", destination->details->uname,
345  NULL);
346  }
347 
348  if ((source->reason != NULL)
349  && !pcmk_is_set(action->flags, pcmk_action_runnable)) {
350  pcmk__xe_set_props(xml,
351  "reason", source->reason,
352  "blocked", "true",
353  NULL);
354 
355  } else if (source->reason != NULL) {
356  crm_xml_add(xml, "reason", source->reason);
357 
358  } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
359  pcmk__xe_set_bool_attr(xml, "blocked", true);
360 
361  }
362 
363  return pcmk_rc_ok;
364 }
365 
366 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pcmk_resource_t *", "bool")
367 static int
368 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
369  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
370  bool recursive = va_arg(args, int);
371 
372  int rc = pcmk_rc_no_output;
373 
375  return rc;
376  }
377 
378  /* We're listing constraints explicitly involving rsc, so use rsc->rsc_cons
379  * directly rather than rsc->cmds->this_with_colocations().
380  */
382  for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
383  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
384  char *hdr = NULL;
385 
386  PCMK__OUTPUT_LIST_HEADER(out, false, rc,
387  "Resources %s is colocated with", rsc->id);
388 
390  out->list_item(out, NULL, "%s (id=%s - loop)",
391  cons->primary->id, cons->id);
392  continue;
393  }
394 
395  hdr = colocations_header(cons->primary, cons, false);
396  out->list_item(out, NULL, "%s", hdr);
397  free(hdr);
398 
399  // Empty list header for indentation of information about this resource
400  out->begin_list(out, NULL, NULL, NULL);
401 
402  out->message(out, "locations-list", cons->primary);
403  if (recursive) {
404  out->message(out, "rsc-is-colocated-with-list",
405  cons->primary, recursive);
406  }
407 
408  out->end_list(out);
409  }
410 
411  PCMK__OUTPUT_LIST_FOOTER(out, rc);
412  return rc;
413 }
414 
415 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pcmk_resource_t *", "bool")
416 static int
417 rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
418  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
419  bool recursive = va_arg(args, int);
420 
421  int rc = pcmk_rc_no_output;
422 
424  return rc;
425  }
426 
427  /* We're listing constraints explicitly involving rsc, so use rsc->rsc_cons
428  * directly rather than rsc->cmds->this_with_colocations().
429  */
431  for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
432  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
433 
435  colocations_xml_node(out, cons->primary, cons);
436  continue;
437  }
438 
439  colocations_xml_node(out, cons->primary, cons);
440  do_locations_list_xml(out, cons->primary, false);
441 
442  if (recursive) {
443  out->message(out, "rsc-is-colocated-with-list",
444  cons->primary, recursive);
445  }
446  }
447 
448  return rc;
449 }
450 
451 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pcmk_resource_t *", "bool")
452 static int
453 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
454  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
455  bool recursive = va_arg(args, int);
456 
457  int rc = pcmk_rc_no_output;
458 
460  return rc;
461  }
462 
463  /* We're listing constraints explicitly involving rsc, so use
464  * rsc->rsc_cons_lhs directly rather than
465  * rsc->cmds->with_this_colocations().
466  */
468  for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
469  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
470  char *hdr = NULL;
471 
472  PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Resources colocated with %s",
473  rsc->id);
474 
476  out->list_item(out, NULL, "%s (id=%s - loop)",
477  cons->dependent->id, cons->id);
478  continue;
479  }
480 
481  hdr = colocations_header(cons->dependent, cons, true);
482  out->list_item(out, NULL, "%s", hdr);
483  free(hdr);
484 
485  // Empty list header for indentation of information about this resource
486  out->begin_list(out, NULL, NULL, NULL);
487 
488  out->message(out, "locations-list", cons->dependent);
489  if (recursive) {
490  out->message(out, "rscs-colocated-with-list",
491  cons->dependent, recursive);
492  }
493 
494  out->end_list(out);
495  }
496 
497  PCMK__OUTPUT_LIST_FOOTER(out, rc);
498  return rc;
499 }
500 
501 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pcmk_resource_t *", "bool")
502 static int
503 rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
504  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
505  bool recursive = va_arg(args, int);
506 
507  int rc = pcmk_rc_no_output;
508 
510  return rc;
511  }
512 
513  /* We're listing constraints explicitly involving rsc, so use
514  * rsc->rsc_cons_lhs directly rather than
515  * rsc->cmds->with_this_colocations().
516  */
518  for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
519  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
520 
522  colocations_xml_node(out, cons->dependent, cons);
523  continue;
524  }
525 
526  colocations_xml_node(out, cons->dependent, cons);
527  do_locations_list_xml(out, cons->dependent, false);
528 
529  if (recursive) {
530  out->message(out, "rscs-colocated-with-list",
531  cons->dependent, recursive);
532  }
533  }
534 
535  return rc;
536 }
537 
538 PCMK__OUTPUT_ARGS("locations-list", "pcmk_resource_t *")
539 static int
540 locations_list(pcmk__output_t *out, va_list args) {
541  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
542 
543  GList *lpc = NULL;
544  GList *list = rsc->rsc_location;
545  int rc = pcmk_rc_no_output;
546 
547  for (lpc = list; lpc != NULL; lpc = lpc->next) {
548  pe__location_t *cons = lpc->data;
549 
550  GList *lpc2 = NULL;
551 
552  for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
553  pcmk_node_t *node = (pcmk_node_t *) lpc2->data;
554 
555  PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Locations");
556  out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
557  pe__node_name(node),
558  pcmk_readable_score(node->weight), cons->id,
559  rsc->id);
560  }
561  }
562 
563  PCMK__OUTPUT_LIST_FOOTER(out, rc);
564  return rc;
565 }
566 
567 PCMK__OUTPUT_ARGS("locations-list", "pcmk_resource_t *")
568 static int
569 locations_list_xml(pcmk__output_t *out, va_list args) {
570  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
571  return do_locations_list_xml(out, rsc, true);
572 }
573 
574 PCMK__OUTPUT_ARGS("locations-and-colocations", "pcmk_resource_t *",
575  "bool", "bool")
576 static int
577 locations_and_colocations(pcmk__output_t *out, va_list args)
578 {
579  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
580  bool recursive = va_arg(args, int);
581  bool force = va_arg(args, int);
582 
584 
585  // Constraints apply to group/clone, not member/instance
586  if (!force) {
587  rsc = uber_parent(rsc);
588  }
589 
590  out->message(out, "locations-list", rsc);
591 
593  out->message(out, "rscs-colocated-with-list", rsc, recursive);
594 
596  out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
597  return pcmk_rc_ok;
598 }
599 
600 PCMK__OUTPUT_ARGS("locations-and-colocations", "pcmk_resource_t *",
601  "bool", "bool")
602 static int
603 locations_and_colocations_xml(pcmk__output_t *out, va_list args)
604 {
605  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
606  bool recursive = va_arg(args, int);
607  bool force = va_arg(args, int);
608 
610 
611  // Constraints apply to group/clone, not member/instance
612  if (!force) {
613  rsc = uber_parent(rsc);
614  }
615 
616  pcmk__output_xml_create_parent(out, "constraints", NULL);
617  do_locations_list_xml(out, rsc, false);
618 
620  out->message(out, "rscs-colocated-with-list", rsc, recursive);
621 
623  out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
624 
626  return pcmk_rc_ok;
627 }
628 
629 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *",
630  "const char *")
631 static int
632 health(pcmk__output_t *out, va_list args)
633 {
634  const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
635  const char *host_from = va_arg(args, const char *);
636  const char *fsa_state = va_arg(args, const char *);
637  const char *result = va_arg(args, const char *);
638 
639  return out->info(out, "Controller on %s in state %s: %s",
640  pcmk__s(host_from, "unknown node"),
641  pcmk__s(fsa_state, "unknown"),
642  pcmk__s(result, "unknown result"));
643 }
644 
645 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *",
646  "const char *")
647 static int
648 health_text(pcmk__output_t *out, va_list args)
649 {
650  if (!out->is_quiet(out)) {
651  return health(out, args);
652  } else {
653  const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
654  const char *host_from G_GNUC_UNUSED = va_arg(args, const char *);
655  const char *fsa_state = va_arg(args, const char *);
656  const char *result G_GNUC_UNUSED = va_arg(args, const char *);
657 
658  if (fsa_state != NULL) {
659  pcmk__formatted_printf(out, "%s\n", fsa_state);
660  return pcmk_rc_ok;
661  }
662  }
663 
664  return pcmk_rc_no_output;
665 }
666 
667 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *",
668  "const char *")
669 static int
670 health_xml(pcmk__output_t *out, va_list args)
671 {
672  const char *sys_from = va_arg(args, const char *);
673  const char *host_from = va_arg(args, const char *);
674  const char *fsa_state = va_arg(args, const char *);
675  const char *result = va_arg(args, const char *);
676 
677  pcmk__output_create_xml_node(out, pcmk__s(sys_from, ""),
678  "node_name", pcmk__s(host_from, ""),
679  "state", pcmk__s(fsa_state, ""),
680  "result", pcmk__s(result, ""),
681  NULL);
682  return pcmk_rc_ok;
683 }
684 
685 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
686  "enum pcmk_pacemakerd_state", "const char *", "time_t")
687 static int
688 pacemakerd_health(pcmk__output_t *out, va_list args)
689 {
690  const char *sys_from = va_arg(args, const char *);
691  enum pcmk_pacemakerd_state state =
692  (enum pcmk_pacemakerd_state) va_arg(args, int);
693  const char *state_s = va_arg(args, const char *);
694  time_t last_updated = va_arg(args, time_t);
695 
696  char *last_updated_s = NULL;
697  int rc = pcmk_rc_ok;
698 
699  if (sys_from == NULL) {
700  if (state == pcmk_pacemakerd_state_remote) {
701  sys_from = "pacemaker-remoted";
702  } else {
703  sys_from = CRM_SYSTEM_MCP;
704  }
705  }
706 
707  if (state_s == NULL) {
708  state_s = pcmk__pcmkd_state_enum2friendly(state);
709  }
710 
711  if (last_updated != 0) {
712  last_updated_s = pcmk__epoch2str(&last_updated,
716  }
717 
718  rc = out->info(out, "Status of %s: '%s' (last updated %s)",
719  sys_from, state_s,
720  pcmk__s(last_updated_s, "at unknown time"));
721 
722  free(last_updated_s);
723  return rc;
724 }
725 
726 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
727  "enum pcmk_pacemakerd_state", "const char *", "time_t")
728 static int
729 pacemakerd_health_html(pcmk__output_t *out, va_list args)
730 {
731  const char *sys_from = va_arg(args, const char *);
732  enum pcmk_pacemakerd_state state =
733  (enum pcmk_pacemakerd_state) va_arg(args, int);
734  const char *state_s = va_arg(args, const char *);
735  time_t last_updated = va_arg(args, time_t);
736 
737  char *last_updated_s = NULL;
738  char *msg = NULL;
739 
740  if (sys_from == NULL) {
741  if (state == pcmk_pacemakerd_state_remote) {
742  sys_from = "pacemaker-remoted";
743  } else {
744  sys_from = CRM_SYSTEM_MCP;
745  }
746  }
747 
748  if (state_s == NULL) {
749  state_s = pcmk__pcmkd_state_enum2friendly(state);
750  }
751 
752  if (last_updated != 0) {
753  last_updated_s = pcmk__epoch2str(&last_updated,
757  }
758 
759  msg = crm_strdup_printf("Status of %s: '%s' (last updated %s)",
760  sys_from, state_s,
761  pcmk__s(last_updated_s, "at unknown time"));
762  pcmk__output_create_html_node(out, "li", NULL, NULL, msg);
763 
764  free(msg);
765  free(last_updated_s);
766  return pcmk_rc_ok;
767 }
768 
769 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
770  "enum pcmk_pacemakerd_state", "const char *", "time_t")
771 static int
772 pacemakerd_health_text(pcmk__output_t *out, va_list args)
773 {
774  if (!out->is_quiet(out)) {
775  return pacemakerd_health(out, args);
776  } else {
777  const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
778  enum pcmk_pacemakerd_state state =
779  (enum pcmk_pacemakerd_state) va_arg(args, int);
780  const char *state_s = va_arg(args, const char *);
781  time_t last_updated G_GNUC_UNUSED = va_arg(args, time_t);
782 
783  if (state_s == NULL) {
785  }
786  pcmk__formatted_printf(out, "%s\n", state_s);
787  return pcmk_rc_ok;
788  }
789 }
790 
791 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *",
792  "enum pcmk_pacemakerd_state", "const char *", "time_t")
793 static int
794 pacemakerd_health_xml(pcmk__output_t *out, va_list args)
795 {
796  const char *sys_from = va_arg(args, const char *);
797  enum pcmk_pacemakerd_state state =
798  (enum pcmk_pacemakerd_state) va_arg(args, int);
799  const char *state_s = va_arg(args, const char *);
800  time_t last_updated = va_arg(args, time_t);
801 
802  char *last_updated_s = NULL;
803 
804  if (sys_from == NULL) {
805  if (state == pcmk_pacemakerd_state_remote) {
806  sys_from = "pacemaker-remoted";
807  } else {
808  sys_from = CRM_SYSTEM_MCP;
809  }
810  }
811 
812  if (state_s == NULL) {
814  }
815 
816  if (last_updated != 0) {
817  last_updated_s = pcmk__epoch2str(&last_updated,
821  }
822 
823  pcmk__output_create_xml_node(out, "pacemakerd",
824  "sys_from", sys_from,
825  "state", state_s,
826  "last_updated", last_updated_s,
827  NULL);
828  free(last_updated_s);
829  return pcmk_rc_ok;
830 }
831 
832 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
833 static int
834 profile_default(pcmk__output_t *out, va_list args) {
835  const char *xml_file = va_arg(args, const char *);
836  clock_t start = va_arg(args, clock_t);
837  clock_t end = va_arg(args, clock_t);
838 
839  out->list_item(out, NULL, "Testing %s ... %.2f secs", xml_file,
840  (end - start) / (float) CLOCKS_PER_SEC);
841 
842  return pcmk_rc_ok;
843 }
844 
845 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
846 static int
847 profile_xml(pcmk__output_t *out, va_list args) {
848  const char *xml_file = va_arg(args, const char *);
849  clock_t start = va_arg(args, clock_t);
850  clock_t end = va_arg(args, clock_t);
851 
852  char *duration = pcmk__ftoa((end - start) / (float) CLOCKS_PER_SEC);
853 
854  pcmk__output_create_xml_node(out, "timing",
855  "file", xml_file,
856  "duration", duration,
857  NULL);
858 
859  free(duration);
860  return pcmk_rc_ok;
861 }
862 
863 PCMK__OUTPUT_ARGS("dc", "const char *")
864 static int
865 dc(pcmk__output_t *out, va_list args)
866 {
867  const char *dc = va_arg(args, const char *);
868 
869  return out->info(out, "Designated Controller is: %s",
870  pcmk__s(dc, "not yet elected"));
871 }
872 
873 PCMK__OUTPUT_ARGS("dc", "const char *")
874 static int
875 dc_text(pcmk__output_t *out, va_list args)
876 {
877  if (!out->is_quiet(out)) {
878  return dc(out, args);
879  } else {
880  const char *dc = va_arg(args, const char *);
881 
882  if (dc != NULL) {
883  pcmk__formatted_printf(out, "%s\n", pcmk__s(dc, ""));
884  return pcmk_rc_ok;
885  }
886  }
887 
888  return pcmk_rc_no_output;
889 }
890 
891 PCMK__OUTPUT_ARGS("dc", "const char *")
892 static int
893 dc_xml(pcmk__output_t *out, va_list args)
894 {
895  const char *dc = va_arg(args, const char *);
896 
898  "node_name", pcmk__s(dc, ""),
899  NULL);
900  return pcmk_rc_ok;
901 }
902 
903 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *",
904  "const char *", "bool")
905 static int
906 crmadmin_node(pcmk__output_t *out, va_list args)
907 {
908  const char *type = va_arg(args, const char *);
909  const char *name = va_arg(args, const char *);
910  const char *id = va_arg(args, const char *);
911  bool bash_export = va_arg(args, int);
912 
913  if (bash_export) {
914  return out->info(out, "export %s=%s",
915  pcmk__s(name, "<null>"), pcmk__s(id, ""));
916  } else {
917  return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
918  pcmk__s(name, "<null>"), pcmk__s(id, "<null>"));
919  }
920 }
921 
922 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *",
923  "const char *", "bool")
924 static int
925 crmadmin_node_text(pcmk__output_t *out, va_list args)
926 {
927  if (!out->is_quiet(out)) {
928  return crmadmin_node(out, args);
929  } else {
930  const char *type G_GNUC_UNUSED = va_arg(args, const char *);
931  const char *name = va_arg(args, const char *);
932  const char *id G_GNUC_UNUSED = va_arg(args, const char *);
933  bool bash_export G_GNUC_UNUSED = va_arg(args, int);
934 
935  pcmk__formatted_printf(out, "%s\n", pcmk__s(name, "<null>"));
936  return pcmk_rc_ok;
937  }
938 }
939 
940 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *",
941  "const char *", "bool")
942 static int
943 crmadmin_node_xml(pcmk__output_t *out, va_list args)
944 {
945  const char *type = va_arg(args, const char *);
946  const char *name = va_arg(args, const char *);
947  const char *id = va_arg(args, const char *);
948  bool bash_export G_GNUC_UNUSED = va_arg(args, int);
949 
950  pcmk__output_create_xml_node(out, "node",
951  "type", type ? type : "cluster",
952  "name", pcmk__s(name, ""),
953  "id", pcmk__s(id, ""),
954  NULL);
955  return pcmk_rc_ok;
956 }
957 
958 PCMK__OUTPUT_ARGS("digests", "const pcmk_resource_t *", "const pcmk_node_t *",
959  "const char *", "guint", "const op_digest_cache_t *")
960 static int
961 digests_text(pcmk__output_t *out, va_list args)
962 {
963  const pcmk_resource_t *rsc = va_arg(args, const pcmk_resource_t *);
964  const pcmk_node_t *node = va_arg(args, const pcmk_node_t *);
965  const char *task = va_arg(args, const char *);
966  guint interval_ms = va_arg(args, guint);
967  const op_digest_cache_t *digests = va_arg(args, const op_digest_cache_t *);
968 
969  char *action_desc = NULL;
970  const char *rsc_desc = "unknown resource";
971  const char *node_desc = "unknown node";
972 
973  if (interval_ms != 0) {
974  action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
975  ((task == NULL)? "unknown" : task));
976  } else if (pcmk__str_eq(task, PCMK_ACTION_MONITOR, pcmk__str_none)) {
977  action_desc = strdup("probe action");
978  } else {
979  action_desc = crm_strdup_printf("%s action",
980  ((task == NULL)? "unknown" : task));
981  }
982  if ((rsc != NULL) && (rsc->id != NULL)) {
983  rsc_desc = rsc->id;
984  }
985  if ((node != NULL) && (node->details->uname != NULL)) {
986  node_desc = node->details->uname;
987  }
988  out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
989  rsc_desc, action_desc, node_desc);
990  free(action_desc);
991 
992  if (digests == NULL) {
993  out->list_item(out, NULL, "none");
994  out->end_list(out);
995  return pcmk_rc_ok;
996  }
997  if (digests->digest_all_calc != NULL) {
998  out->list_item(out, NULL, "%s (all parameters)",
999  digests->digest_all_calc);
1000  }
1001  if (digests->digest_secure_calc != NULL) {
1002  out->list_item(out, NULL, "%s (non-private parameters)",
1003  digests->digest_secure_calc);
1004  }
1005  if (digests->digest_restart_calc != NULL) {
1006  out->list_item(out, NULL, "%s (non-reloadable parameters)",
1007  digests->digest_restart_calc);
1008  }
1009  out->end_list(out);
1010  return pcmk_rc_ok;
1011 }
1012 
1013 static void
1014 add_digest_xml(xmlNode *parent, const char *type, const char *digest,
1015  xmlNode *digest_source)
1016 {
1017  if (digest != NULL) {
1018  xmlNodePtr digest_xml = create_xml_node(parent, "digest");
1019 
1020  crm_xml_add(digest_xml, "type", ((type == NULL)? "unspecified" : type));
1021  crm_xml_add(digest_xml, "hash", digest);
1022  if (digest_source != NULL) {
1023  add_node_copy(digest_xml, digest_source);
1024  }
1025  }
1026 }
1027 
1028 PCMK__OUTPUT_ARGS("digests", "const pcmk_resource_t *", "const pcmk_node_t *",
1029  "const char *", "guint", "const op_digest_cache_t *")
1030 static int
1031 digests_xml(pcmk__output_t *out, va_list args)
1032 {
1033  const pcmk_resource_t *rsc = va_arg(args, const pcmk_resource_t *);
1034  const pcmk_node_t *node = va_arg(args, const pcmk_node_t *);
1035  const char *task = va_arg(args, const char *);
1036  guint interval_ms = va_arg(args, guint);
1037  const op_digest_cache_t *digests = va_arg(args, const op_digest_cache_t *);
1038 
1039  char *interval_s = crm_strdup_printf("%ums", interval_ms);
1040  xmlNode *xml = NULL;
1041 
1042  xml = pcmk__output_create_xml_node(out, "digests",
1043  "resource", pcmk__s(rsc->id, ""),
1044  "node",
1045  pcmk__s(node->details->uname, ""),
1046  "task", pcmk__s(task, ""),
1047  "interval", interval_s,
1048  NULL);
1049  free(interval_s);
1050  if (digests != NULL) {
1051  add_digest_xml(xml, "all", digests->digest_all_calc,
1052  digests->params_all);
1053  add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
1054  digests->params_secure);
1055  add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
1056  digests->params_restart);
1057  }
1058  return pcmk_rc_ok;
1059 }
1060 
1061 #define STOP_SANITY_ASSERT(lineno) do { \
1062  if ((current != NULL) && current->details->unclean) { \
1063  /* It will be a pseudo op */ \
1064  } else if (stop == NULL) { \
1065  crm_err("%s:%d: No stop action exists for %s", \
1066  __func__, lineno, rsc->id); \
1067  CRM_ASSERT(stop != NULL); \
1068  } else if (pcmk_is_set(stop->flags, pcmk_action_optional)) { \
1069  crm_err("%s:%d: Action %s is still optional", \
1070  __func__, lineno, stop->uuid); \
1071  CRM_ASSERT(!pcmk_is_set(stop->flags, pcmk_action_optional));\
1072  } \
1073  } while (0)
1074 
1075 PCMK__OUTPUT_ARGS("rsc-action", "pcmk_resource_t *", "pcmk_node_t *",
1076  "pcmk_node_t *")
1077 static int
1078 rsc_action_default(pcmk__output_t *out, va_list args)
1079 {
1080  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
1081  pcmk_node_t *current = va_arg(args, pcmk_node_t *);
1082  pcmk_node_t *next = va_arg(args, pcmk_node_t *);
1083 
1084  GList *possible_matches = NULL;
1085  char *key = NULL;
1086  int rc = pcmk_rc_no_output;
1087  bool moving = false;
1088 
1089  pcmk_node_t *start_node = NULL;
1090  pcmk_action_t *start = NULL;
1091  pcmk_action_t *stop = NULL;
1092  pcmk_action_t *promote = NULL;
1093  pcmk_action_t *demote = NULL;
1094  pcmk_action_t *reason_op = NULL;
1095 
1096  if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)
1097  || (current == NULL && next == NULL)) {
1098  const bool managed = pcmk_is_set(rsc->flags, pcmk_rsc_managed);
1099 
1100  pe_rsc_info(rsc, "Leave %s\t(%s%s)",
1101  rsc->id, role2text(rsc->role),
1102  (managed? "" : " unmanaged"));
1103  return rc;
1104  }
1105 
1106  moving = (current != NULL) && (next != NULL)
1107  && !pe__same_node(current, next);
1108 
1109  possible_matches = pe__resource_actions(rsc, next, PCMK_ACTION_START,
1110  false);
1111  if (possible_matches) {
1112  start = possible_matches->data;
1113  g_list_free(possible_matches);
1114  }
1115 
1116  if ((start == NULL)
1117  || !pcmk_is_set(start->flags, pcmk_action_runnable)) {
1118  start_node = NULL;
1119  } else {
1120  start_node = current;
1121  }
1122  possible_matches = pe__resource_actions(rsc, start_node, PCMK_ACTION_STOP,
1123  false);
1124  if (possible_matches) {
1125  stop = possible_matches->data;
1126  g_list_free(possible_matches);
1127  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_stop_unexpected)) {
1128  /* The resource is multiply active with multiple-active set to
1129  * stop_unexpected, and not stopping on its current node, but it should
1130  * be stopping elsewhere.
1131  */
1132  possible_matches = pe__resource_actions(rsc, NULL, PCMK_ACTION_STOP,
1133  false);
1134  if (possible_matches != NULL) {
1135  stop = possible_matches->data;
1136  g_list_free(possible_matches);
1137  }
1138  }
1139 
1140  possible_matches = pe__resource_actions(rsc, next, PCMK_ACTION_PROMOTE,
1141  false);
1142  if (possible_matches) {
1143  promote = possible_matches->data;
1144  g_list_free(possible_matches);
1145  }
1146 
1147  possible_matches = pe__resource_actions(rsc, next, PCMK_ACTION_DEMOTE,
1148  false);
1149  if (possible_matches) {
1150  demote = possible_matches->data;
1151  g_list_free(possible_matches);
1152  }
1153 
1154  if (rsc->role == rsc->next_role) {
1155  pcmk_action_t *migrate_op = NULL;
1156 
1157  CRM_CHECK(next != NULL, return rc);
1158 
1159  possible_matches = pe__resource_actions(rsc, next,
1161  false);
1162  if (possible_matches) {
1163  migrate_op = possible_matches->data;
1164  }
1165 
1166  if ((migrate_op != NULL) && (current != NULL)
1167  && pcmk_is_set(migrate_op->flags, pcmk_action_runnable)) {
1168  rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
1169  next, start, NULL);
1170 
1171  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_reload)) {
1172  rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
1173  next, start, NULL);
1174 
1175  } else if ((start == NULL)
1176  || pcmk_is_set(start->flags, pcmk_action_optional)) {
1177  if ((demote != NULL) && (promote != NULL)
1178  && !pcmk_is_set(demote->flags, pcmk_action_optional)
1179  && !pcmk_is_set(promote->flags, pcmk_action_optional)) {
1180  rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
1181  current, next, promote, demote);
1182  } else {
1183  pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
1184  role2text(rsc->role), pe__node_name(next));
1185  }
1186 
1187  } else if (!pcmk_is_set(start->flags, pcmk_action_runnable)) {
1188  if ((stop == NULL) || (stop->reason == NULL)) {
1189  reason_op = start;
1190  } else {
1191  reason_op = stop;
1192  }
1193  rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
1194  NULL, stop, reason_op);
1195  STOP_SANITY_ASSERT(__LINE__);
1196 
1197  } else if (moving && current) {
1198  const bool failed = pcmk_is_set(rsc->flags, pcmk_rsc_failed);
1199 
1200  rc = out->message(out, "rsc-action-item",
1201  (failed? "Recover" : "Move"), rsc, current, next,
1202  stop, NULL);
1203 
1204  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
1205  rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1206  NULL, stop, NULL);
1207  STOP_SANITY_ASSERT(__LINE__);
1208 
1209  } else {
1210  rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1211  next, start, NULL);
1212 #if 0
1213  /* @TODO This can be reached in situations that should really be
1214  * "Start" (see for example the migrate-fail-7 regression test)
1215  */
1216  STOP_SANITY_ASSERT(__LINE__);
1217 #endif
1218  }
1219 
1220  g_list_free(possible_matches);
1221  return rc;
1222  }
1223 
1224  if ((stop != NULL)
1225  && ((rsc->next_role == pcmk_role_stopped)
1226  || ((start != NULL)
1227  && !pcmk_is_set(start->flags, pcmk_action_runnable)))) {
1228 
1229  key = stop_key(rsc);
1230  for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
1231  pcmk_node_t *node = iter->data;
1232  pcmk_action_t *stop_op = NULL;
1233 
1234  reason_op = start;
1235  possible_matches = find_actions(rsc->actions, key, node);
1236  if (possible_matches) {
1237  stop_op = possible_matches->data;
1238  g_list_free(possible_matches);
1239  }
1240 
1241  if (stop_op != NULL) {
1242  if (pcmk_is_set(stop_op->flags, pcmk_action_runnable)) {
1243  STOP_SANITY_ASSERT(__LINE__);
1244  }
1245  if (stop_op->reason != NULL) {
1246  reason_op = stop_op;
1247  }
1248  }
1249 
1250  if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
1251  stop_op, reason_op) == pcmk_rc_ok) {
1252  rc = pcmk_rc_ok;
1253  }
1254  }
1255 
1256  free(key);
1257 
1258  } else if ((stop != NULL)
1259  && pcmk_all_flags_set(rsc->flags,
1261  /* 'stop' may be NULL if the failure was ignored */
1262  rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1263  next, stop, start);
1264  STOP_SANITY_ASSERT(__LINE__);
1265 
1266  } else if (moving) {
1267  rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
1268  stop, NULL);
1269  STOP_SANITY_ASSERT(__LINE__);
1270 
1271  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_reload)) {
1272  rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
1273  start, NULL);
1274 
1275  } else if ((stop != NULL)
1276  && !pcmk_is_set(stop->flags, pcmk_action_optional)) {
1277  rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1278  next, start, NULL);
1279  STOP_SANITY_ASSERT(__LINE__);
1280 
1281  } else if (rsc->role == pcmk_role_promoted) {
1282  CRM_LOG_ASSERT(current != NULL);
1283  rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1284  next, demote, NULL);
1285 
1286  } else if (rsc->next_role == pcmk_role_promoted) {
1287  CRM_LOG_ASSERT(next);
1288  rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1289  next, promote, NULL);
1290 
1291  } else if ((rsc->role == pcmk_role_stopped)
1292  && (rsc->next_role > pcmk_role_stopped)) {
1293  rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1294  start, NULL);
1295  }
1296 
1297  return rc;
1298 }
1299 
1300 PCMK__OUTPUT_ARGS("node-action", "const char *", "const char *", "const char *")
1301 static int
1302 node_action(pcmk__output_t *out, va_list args)
1303 {
1304  const char *task = va_arg(args, const char *);
1305  const char *node_name = va_arg(args, const char *);
1306  const char *reason = va_arg(args, const char *);
1307 
1308  if (task == NULL) {
1309  return pcmk_rc_no_output;
1310  } else if (reason) {
1311  out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1312  } else {
1313  crm_notice(" * %s %s", task, node_name);
1314  }
1315 
1316  return pcmk_rc_ok;
1317 }
1318 
1319 PCMK__OUTPUT_ARGS("node-action", "const char *", "const char *", "const char *")
1320 static int
1321 node_action_xml(pcmk__output_t *out, va_list args)
1322 {
1323  const char *task = va_arg(args, const char *);
1324  const char *node_name = va_arg(args, const char *);
1325  const char *reason = va_arg(args, const char *);
1326 
1327  if (task == NULL) {
1328  return pcmk_rc_no_output;
1329  } else if (reason) {
1330  pcmk__output_create_xml_node(out, "node_action",
1331  "task", task,
1332  "node", node_name,
1333  "reason", reason,
1334  NULL);
1335  } else {
1336  crm_notice(" * %s %s", task, node_name);
1337  }
1338 
1339  return pcmk_rc_ok;
1340 }
1341 
1342 PCMK__OUTPUT_ARGS("node-info", "uint32_t", "const char *", "const char *",
1343  "const char *", "bool", "bool")
1344 static int
1345 node_info_default(pcmk__output_t *out, va_list args)
1346 {
1347  uint32_t node_id = va_arg(args, uint32_t);
1348  const char *node_name = va_arg(args, const char *);
1349  const char *uuid = va_arg(args, const char *);
1350  const char *state = va_arg(args, const char *);
1351  bool have_quorum = (bool) va_arg(args, int);
1352  bool is_remote = (bool) va_arg(args, int);
1353 
1354  return out->info(out,
1355  "Node %" PRIu32 ": %s "
1356  "(uuid=%s, state=%s, have_quorum=%s, is_remote=%s)",
1357  node_id, pcmk__s(node_name, "unknown"),
1358  pcmk__s(uuid, "unknown"), pcmk__s(state, "unknown"),
1359  pcmk__btoa(have_quorum), pcmk__btoa(is_remote));
1360 }
1361 
1362 PCMK__OUTPUT_ARGS("node-info", "uint32_t", "const char *", "const char *",
1363  "const char *", "bool", "bool")
1364 static int
1365 node_info_xml(pcmk__output_t *out, va_list args)
1366 {
1367  uint32_t node_id = va_arg(args, uint32_t);
1368  const char *node_name = va_arg(args, const char *);
1369  const char *uuid = va_arg(args, const char *);
1370  const char *state = va_arg(args, const char *);
1371  bool have_quorum = (bool) va_arg(args, int);
1372  bool is_remote = (bool) va_arg(args, int);
1373 
1374  char *id_s = crm_strdup_printf("%" PRIu32, node_id);
1375 
1376  pcmk__output_create_xml_node(out, "node-info",
1377  "nodeid", id_s,
1378  XML_ATTR_UNAME, node_name,
1379  XML_ATTR_ID, uuid,
1380  PCMK__XA_CRMD, state,
1381  XML_ATTR_HAVE_QUORUM, pcmk__btoa(have_quorum),
1382  XML_NODE_IS_REMOTE, pcmk__btoa(is_remote),
1383  NULL);
1384  free(id_s);
1385  return pcmk_rc_ok;
1386 }
1387 
1388 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *",
1389  "xmlNodePtr")
1390 static int
1391 inject_cluster_action(pcmk__output_t *out, va_list args)
1392 {
1393  const char *node = va_arg(args, const char *);
1394  const char *task = va_arg(args, const char *);
1395  xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1396 
1397  if (out->is_quiet(out)) {
1398  return pcmk_rc_no_output;
1399  }
1400 
1401  if (rsc != NULL) {
1402  out->list_item(out, NULL, "Cluster action: %s for %s on %s",
1403  task, ID(rsc), node);
1404  } else {
1405  out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1406  }
1407 
1408  return pcmk_rc_ok;
1409 }
1410 
1411 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *",
1412  "xmlNodePtr")
1413 static int
1414 inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1415 {
1416  const char *node = va_arg(args, const char *);
1417  const char *task = va_arg(args, const char *);
1418  xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1419 
1420  xmlNodePtr xml_node = NULL;
1421 
1422  if (out->is_quiet(out)) {
1423  return pcmk_rc_no_output;
1424  }
1425 
1426  xml_node = pcmk__output_create_xml_node(out, "cluster_action",
1427  "task", task,
1428  "node", node,
1429  NULL);
1430 
1431  if (rsc) {
1432  crm_xml_add(xml_node, "id", ID(rsc));
1433  }
1434 
1435  return pcmk_rc_ok;
1436 }
1437 
1438 PCMK__OUTPUT_ARGS("inject-fencing-action", "const char *", "const char *")
1439 static int
1440 inject_fencing_action(pcmk__output_t *out, va_list args)
1441 {
1442  const char *target = va_arg(args, const char *);
1443  const char *op = va_arg(args, const char *);
1444 
1445  if (out->is_quiet(out)) {
1446  return pcmk_rc_no_output;
1447  }
1448 
1449  out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1450  return pcmk_rc_ok;
1451 }
1452 
1453 PCMK__OUTPUT_ARGS("inject-fencing-action", "const char *", "const char *")
1454 static int
1455 inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1456 {
1457  const char *target = va_arg(args, const char *);
1458  const char *op = va_arg(args, const char *);
1459 
1460  if (out->is_quiet(out)) {
1461  return pcmk_rc_no_output;
1462  }
1463 
1464  pcmk__output_create_xml_node(out, "fencing_action",
1465  "target", target,
1466  "op", op,
1467  NULL);
1468  return pcmk_rc_ok;
1469 }
1470 
1471 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1472 static int
1473 inject_attr(pcmk__output_t *out, va_list args)
1474 {
1475  const char *name = va_arg(args, const char *);
1476  const char *value = va_arg(args, const char *);
1477  xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1478 
1479  xmlChar *node_path = NULL;
1480 
1481  if (out->is_quiet(out)) {
1482  return pcmk_rc_no_output;
1483  }
1484 
1485  node_path = xmlGetNodePath(cib_node);
1486 
1487  out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1488  name, value, node_path, ID(cib_node));
1489 
1490  free(node_path);
1491  return pcmk_rc_ok;
1492 }
1493 
1494 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1495 static int
1496 inject_attr_xml(pcmk__output_t *out, va_list args)
1497 {
1498  const char *name = va_arg(args, const char *);
1499  const char *value = va_arg(args, const char *);
1500  xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1501 
1502  xmlChar *node_path = NULL;
1503 
1504  if (out->is_quiet(out)) {
1505  return pcmk_rc_no_output;
1506  }
1507 
1508  node_path = xmlGetNodePath(cib_node);
1509 
1510  pcmk__output_create_xml_node(out, "inject_attr",
1511  "name", name,
1512  "value", value,
1513  "node_path", node_path,
1514  "cib_node", ID(cib_node),
1515  NULL);
1516  free(node_path);
1517  return pcmk_rc_ok;
1518 }
1519 
1520 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1521 static int
1522 inject_spec(pcmk__output_t *out, va_list args)
1523 {
1524  const char *spec = va_arg(args, const char *);
1525 
1526  if (out->is_quiet(out)) {
1527  return pcmk_rc_no_output;
1528  }
1529 
1530  out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1531  return pcmk_rc_ok;
1532 }
1533 
1534 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1535 static int
1536 inject_spec_xml(pcmk__output_t *out, va_list args)
1537 {
1538  const char *spec = va_arg(args, const char *);
1539 
1540  if (out->is_quiet(out)) {
1541  return pcmk_rc_no_output;
1542  }
1543 
1544  pcmk__output_create_xml_node(out, "inject_spec",
1545  "spec", spec,
1546  NULL);
1547  return pcmk_rc_ok;
1548 }
1549 
1550 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1551 static int
1552 inject_modify_config(pcmk__output_t *out, va_list args)
1553 {
1554  const char *quorum = va_arg(args, const char *);
1555  const char *watchdog = va_arg(args, const char *);
1556 
1557  if (out->is_quiet(out)) {
1558  return pcmk_rc_no_output;
1559  }
1560 
1561  out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1562 
1563  if (quorum) {
1564  out->list_item(out, NULL, "Setting quorum: %s", quorum);
1565  }
1566 
1567  if (watchdog) {
1568  out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1569  }
1570 
1571  return pcmk_rc_ok;
1572 }
1573 
1574 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1575 static int
1576 inject_modify_config_xml(pcmk__output_t *out, va_list args)
1577 {
1578  const char *quorum = va_arg(args, const char *);
1579  const char *watchdog = va_arg(args, const char *);
1580 
1581  xmlNodePtr node = NULL;
1582 
1583  if (out->is_quiet(out)) {
1584  return pcmk_rc_no_output;
1585  }
1586 
1587  node = pcmk__output_xml_create_parent(out, "modifications", NULL);
1588 
1589  if (quorum) {
1590  crm_xml_add(node, "quorum", quorum);
1591  }
1592 
1593  if (watchdog) {
1594  crm_xml_add(node, "watchdog", watchdog);
1595  }
1596 
1597  return pcmk_rc_ok;
1598 }
1599 
1600 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "const char *")
1601 static int
1602 inject_modify_node(pcmk__output_t *out, va_list args)
1603 {
1604  const char *action = va_arg(args, const char *);
1605  const char *node = va_arg(args, const char *);
1606 
1607  if (out->is_quiet(out)) {
1608  return pcmk_rc_no_output;
1609  }
1610 
1611  if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1612  out->list_item(out, NULL, "Bringing node %s online", node);
1613  return pcmk_rc_ok;
1614  } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1615  out->list_item(out, NULL, "Taking node %s offline", node);
1616  return pcmk_rc_ok;
1617  } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1618  out->list_item(out, NULL, "Failing node %s", node);
1619  return pcmk_rc_ok;
1620  }
1621 
1622  return pcmk_rc_no_output;
1623 }
1624 
1625 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "const char *")
1626 static int
1627 inject_modify_node_xml(pcmk__output_t *out, va_list args)
1628 {
1629  const char *action = va_arg(args, const char *);
1630  const char *node = va_arg(args, const char *);
1631 
1632  if (out->is_quiet(out)) {
1633  return pcmk_rc_no_output;
1634  }
1635 
1636  pcmk__output_create_xml_node(out, "modify_node",
1637  "action", action,
1638  "node", node,
1639  NULL);
1640  return pcmk_rc_ok;
1641 }
1642 
1643 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "const char *")
1644 static int
1645 inject_modify_ticket(pcmk__output_t *out, va_list args)
1646 {
1647  const char *action = va_arg(args, const char *);
1648  const char *ticket = va_arg(args, const char *);
1649 
1650  if (out->is_quiet(out)) {
1651  return pcmk_rc_no_output;
1652  }
1653 
1654  if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1655  out->list_item(out, NULL, "Making ticket %s standby", ticket);
1656  } else {
1657  out->list_item(out, NULL, "%s ticket %s", action, ticket);
1658  }
1659 
1660  return pcmk_rc_ok;
1661 }
1662 
1663 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "const char *")
1664 static int
1665 inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1666 {
1667  const char *action = va_arg(args, const char *);
1668  const char *ticket = va_arg(args, const char *);
1669 
1670  if (out->is_quiet(out)) {
1671  return pcmk_rc_no_output;
1672  }
1673 
1674  pcmk__output_create_xml_node(out, "modify_ticket",
1675  "action", action,
1676  "ticket", ticket,
1677  NULL);
1678  return pcmk_rc_ok;
1679 }
1680 
1681 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1682 static int
1683 inject_pseudo_action(pcmk__output_t *out, va_list args)
1684 {
1685  const char *node = va_arg(args, const char *);
1686  const char *task = va_arg(args, const char *);
1687 
1688  if (out->is_quiet(out)) {
1689  return pcmk_rc_no_output;
1690  }
1691 
1692  out->list_item(out, NULL, "Pseudo action: %s%s%s",
1693  task, ((node == NULL)? "" : " on "), pcmk__s(node, ""));
1694  return pcmk_rc_ok;
1695 }
1696 
1697 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1698 static int
1699 inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1700 {
1701  const char *node = va_arg(args, const char *);
1702  const char *task = va_arg(args, const char *);
1703 
1704  xmlNodePtr xml_node = NULL;
1705 
1706  if (out->is_quiet(out)) {
1707  return pcmk_rc_no_output;
1708  }
1709 
1710  xml_node = pcmk__output_create_xml_node(out, "pseudo_action",
1711  "task", task,
1712  NULL);
1713  if (node) {
1714  crm_xml_add(xml_node, "node", node);
1715  }
1716 
1717  return pcmk_rc_ok;
1718 }
1719 
1720 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *",
1721  "const char *", "guint")
1722 static int
1723 inject_rsc_action(pcmk__output_t *out, va_list args)
1724 {
1725  const char *rsc = va_arg(args, const char *);
1726  const char *operation = va_arg(args, const char *);
1727  const char *node = va_arg(args, const char *);
1728  guint interval_ms = va_arg(args, guint);
1729 
1730  if (out->is_quiet(out)) {
1731  return pcmk_rc_no_output;
1732  }
1733 
1734  if (interval_ms) {
1735  out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1736  rsc, operation, interval_ms, node);
1737  } else {
1738  out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1739  rsc, operation, node);
1740  }
1741 
1742  return pcmk_rc_ok;
1743 }
1744 
1745 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *",
1746  "const char *", "guint")
1747 static int
1748 inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1749 {
1750  const char *rsc = va_arg(args, const char *);
1751  const char *operation = va_arg(args, const char *);
1752  const char *node = va_arg(args, const char *);
1753  guint interval_ms = va_arg(args, guint);
1754 
1755  xmlNodePtr xml_node = NULL;
1756 
1757  if (out->is_quiet(out)) {
1758  return pcmk_rc_no_output;
1759  }
1760 
1761  xml_node = pcmk__output_create_xml_node(out, "rsc_action",
1762  "resource", rsc,
1763  "op", operation,
1764  "node", node,
1765  NULL);
1766 
1767  if (interval_ms) {
1768  char *interval_s = pcmk__itoa(interval_ms);
1769 
1770  crm_xml_add(xml_node, "interval", interval_s);
1771  free(interval_s);
1772  }
1773 
1774  return pcmk_rc_ok;
1775 }
1776 
1777 #define CHECK_RC(retcode, retval) \
1778  if (retval == pcmk_rc_ok) { \
1779  retcode = pcmk_rc_ok; \
1780  }
1781 
1782 PCMK__OUTPUT_ARGS("cluster-status", "pcmk_scheduler_t *",
1783  "enum pcmk_pacemakerd_state", "crm_exit_t",
1784  "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1785  "uint32_t", "const char *", "GList *", "GList *")
1786 int
1787 pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
1788 {
1789  pcmk_scheduler_t *scheduler = va_arg(args, pcmk_scheduler_t *);
1790  enum pcmk_pacemakerd_state pcmkd_state =
1791  (enum pcmk_pacemakerd_state) va_arg(args, int);
1792  crm_exit_t history_rc = va_arg(args, crm_exit_t);
1793  stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1794  enum pcmk__fence_history fence_history = va_arg(args, int);
1795  uint32_t section_opts = va_arg(args, uint32_t);
1796  uint32_t show_opts = va_arg(args, uint32_t);
1797  const char *prefix = va_arg(args, const char *);
1798  GList *unames = va_arg(args, GList *);
1799  GList *resources = va_arg(args, GList *);
1800 
1801  int rc = pcmk_rc_no_output;
1802  bool already_printed_failure = false;
1803 
1804  CHECK_RC(rc, out->message(out, "cluster-summary", scheduler, pcmkd_state,
1805  section_opts, show_opts));
1806 
1807  if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1808  CHECK_RC(rc, out->message(out, "node-list", scheduler->nodes, unames,
1809  resources, show_opts, rc == pcmk_rc_ok));
1810  }
1811 
1812  /* Print resources section, if needed */
1813  if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1814  CHECK_RC(rc, out->message(out, "resource-list", scheduler, show_opts,
1815  true, unames, resources, rc == pcmk_rc_ok));
1816  }
1817 
1818  /* print Node Attributes section if requested */
1819  if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1820  CHECK_RC(rc, out->message(out, "node-attribute-list", scheduler,
1821  show_opts, (rc == pcmk_rc_ok), unames,
1822  resources));
1823  }
1824 
1825  /* If requested, print resource operations (which includes failcounts)
1826  * or just failcounts
1827  */
1828  if (pcmk_any_flags_set(section_opts,
1830  CHECK_RC(rc, out->message(out, "node-summary", scheduler, unames,
1831  resources, section_opts, show_opts,
1832  (rc == pcmk_rc_ok)));
1833  }
1834 
1835  /* If there were any failed actions, print them */
1836  if (pcmk_is_set(section_opts, pcmk_section_failures)
1837  && (scheduler->failed != NULL)
1838  && (scheduler->failed->children != NULL)) {
1839 
1840  CHECK_RC(rc, out->message(out, "failed-action-list", scheduler, unames,
1841  resources, show_opts, rc == pcmk_rc_ok));
1842  }
1843 
1844  /* Print failed stonith actions */
1845  if (pcmk_is_set(section_opts, pcmk_section_fence_failed) &&
1846  fence_history != pcmk__fence_history_none) {
1847  if (history_rc == 0) {
1848  stonith_history_t *hp = NULL;
1849 
1850  hp = stonith__first_matching_event(stonith_history,
1852  GINT_TO_POINTER(st_failed));
1853  if (hp) {
1854  CHECK_RC(rc, out->message(out, "failed-fencing-list",
1855  stonith_history, unames, section_opts,
1856  show_opts, rc == pcmk_rc_ok));
1857  }
1858  } else {
1859  PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1860  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1861  out->list_item(out, NULL, "Failed to get fencing history: %s",
1862  crm_exit_str(history_rc));
1863  out->end_list(out);
1864 
1865  already_printed_failure = true;
1866  }
1867  }
1868 
1869  /* Print tickets if requested */
1870  if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1871  CHECK_RC(rc, out->message(out, "ticket-list", scheduler,
1872  (rc == pcmk_rc_ok)));
1873  }
1874 
1875  /* Print negative location constraints if requested */
1876  if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1877  CHECK_RC(rc, out->message(out, "ban-list", scheduler, prefix, resources,
1878  show_opts, rc == pcmk_rc_ok));
1879  }
1880 
1881  /* Print stonith history */
1882  if (pcmk_any_flags_set(section_opts, pcmk_section_fencing_all) &&
1883  fence_history != pcmk__fence_history_none) {
1884  if (history_rc != 0) {
1885  if (!already_printed_failure) {
1886  PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1887  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1888  out->list_item(out, NULL, "Failed to get fencing history: %s",
1889  crm_exit_str(history_rc));
1890  out->end_list(out);
1891  }
1892  } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1893  stonith_history_t *hp = NULL;
1894 
1895  hp = stonith__first_matching_event(stonith_history,
1897  GINT_TO_POINTER(st_failed));
1898  if (hp) {
1899  CHECK_RC(rc, out->message(out, "fencing-list", hp, unames,
1900  section_opts, show_opts,
1901  rc == pcmk_rc_ok));
1902  }
1903  } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1904  stonith_history_t *hp = NULL;
1905 
1906  hp = stonith__first_matching_event(stonith_history,
1908  NULL);
1909  if (hp) {
1910  CHECK_RC(rc, out->message(out, "pending-fencing-list", hp,
1911  unames, section_opts, show_opts,
1912  rc == pcmk_rc_ok));
1913  }
1914  }
1915  }
1916 
1917  return rc;
1918 }
1919 
1920 PCMK__OUTPUT_ARGS("cluster-status", "pcmk_scheduler_t *",
1921  "enum pcmk_pacemakerd_state", "crm_exit_t",
1922  "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
1923  "uint32_t", "const char *", "GList *", "GList *")
1924 static int
1925 cluster_status_xml(pcmk__output_t *out, va_list args)
1926 {
1927  pcmk_scheduler_t *scheduler = va_arg(args, pcmk_scheduler_t *);
1928  enum pcmk_pacemakerd_state pcmkd_state =
1929  (enum pcmk_pacemakerd_state) va_arg(args, int);
1930  crm_exit_t history_rc = va_arg(args, crm_exit_t);
1931  stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1932  enum pcmk__fence_history fence_history = va_arg(args, int);
1933  uint32_t section_opts = va_arg(args, uint32_t);
1934  uint32_t show_opts = va_arg(args, uint32_t);
1935  const char *prefix = va_arg(args, const char *);
1936  GList *unames = va_arg(args, GList *);
1937  GList *resources = va_arg(args, GList *);
1938 
1939  out->message(out, "cluster-summary", scheduler, pcmkd_state, section_opts,
1940  show_opts);
1941 
1942  /*** NODES ***/
1943  if (pcmk_is_set(section_opts, pcmk_section_nodes)) {
1944  out->message(out, "node-list", scheduler->nodes, unames, resources,
1945  show_opts, false);
1946  }
1947 
1948  /* Print resources section, if needed */
1949  if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1950  /* XML output always displays full details. */
1951  uint32_t full_show_opts = show_opts & ~pcmk_show_brief;
1952 
1953  out->message(out, "resource-list", scheduler, full_show_opts,
1954  false, unames, resources, false);
1955  }
1956 
1957  /* print Node Attributes section if requested */
1958  if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1959  out->message(out, "node-attribute-list", scheduler, show_opts, false,
1960  unames, resources);
1961  }
1962 
1963  /* If requested, print resource operations (which includes failcounts)
1964  * or just failcounts
1965  */
1966  if (pcmk_any_flags_set(section_opts,
1968  out->message(out, "node-summary", scheduler, unames,
1969  resources, section_opts, show_opts, false);
1970  }
1971 
1972  /* If there were any failed actions, print them */
1973  if (pcmk_is_set(section_opts, pcmk_section_failures)
1974  && (scheduler->failed != NULL)
1975  && (scheduler->failed->children != NULL)) {
1976 
1977  out->message(out, "failed-action-list", scheduler, unames, resources,
1978  show_opts, false);
1979  }
1980 
1981  /* Print stonith history */
1982  if (pcmk_is_set(section_opts, pcmk_section_fencing_all) &&
1983  fence_history != pcmk__fence_history_none) {
1984  out->message(out, "full-fencing-list", history_rc, stonith_history,
1985  unames, section_opts, show_opts, false);
1986  }
1987 
1988  /* Print tickets if requested */
1989  if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1990  out->message(out, "ticket-list", scheduler, false);
1991  }
1992 
1993  /* Print negative location constraints if requested */
1994  if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1995  out->message(out, "ban-list", scheduler, prefix, resources, show_opts,
1996  false);
1997  }
1998 
1999  return pcmk_rc_ok;
2000 }
2001 
2002 PCMK__OUTPUT_ARGS("cluster-status", "pcmk_scheduler_t *",
2003  "enum pcmk_pacemakerd_state", "crm_exit_t",
2004  "stonith_history_t *", "enum pcmk__fence_history", "uint32_t",
2005  "uint32_t", "const char *", "GList *", "GList *")
2006 static int
2007 cluster_status_html(pcmk__output_t *out, va_list args)
2008 {
2009  pcmk_scheduler_t *scheduler = va_arg(args, pcmk_scheduler_t *);
2010  enum pcmk_pacemakerd_state pcmkd_state =
2011  (enum pcmk_pacemakerd_state) va_arg(args, int);
2012  crm_exit_t history_rc = va_arg(args, crm_exit_t);
2013  stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
2014  enum pcmk__fence_history fence_history = va_arg(args, int);
2015  uint32_t section_opts = va_arg(args, uint32_t);
2016  uint32_t show_opts = va_arg(args, uint32_t);
2017  const char *prefix = va_arg(args, const char *);
2018  GList *unames = va_arg(args, GList *);
2019  GList *resources = va_arg(args, GList *);
2020  bool already_printed_failure = false;
2021 
2022  out->message(out, "cluster-summary", scheduler, pcmkd_state, section_opts,
2023  show_opts);
2024 
2025  /*** NODE LIST ***/
2026  if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
2027  out->message(out, "node-list", scheduler->nodes, unames, resources,
2028  show_opts, false);
2029  }
2030 
2031  /* Print resources section, if needed */
2032  if (pcmk_is_set(section_opts, pcmk_section_resources)) {
2033  out->message(out, "resource-list", scheduler, show_opts, true, unames,
2034  resources, false);
2035  }
2036 
2037  /* print Node Attributes section if requested */
2038  if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
2039  out->message(out, "node-attribute-list", scheduler, show_opts, false,
2040  unames, resources);
2041  }
2042 
2043  /* If requested, print resource operations (which includes failcounts)
2044  * or just failcounts
2045  */
2046  if (pcmk_any_flags_set(section_opts,
2048  out->message(out, "node-summary", scheduler, unames,
2049  resources, section_opts, show_opts, false);
2050  }
2051 
2052  /* If there were any failed actions, print them */
2053  if (pcmk_is_set(section_opts, pcmk_section_failures)
2054  && (scheduler->failed != NULL)
2055  && (scheduler->failed->children != NULL)) {
2056 
2057  out->message(out, "failed-action-list", scheduler, unames, resources,
2058  show_opts, false);
2059  }
2060 
2061  /* Print failed stonith actions */
2062  if (pcmk_is_set(section_opts, pcmk_section_fence_failed) &&
2063  fence_history != pcmk__fence_history_none) {
2064  if (history_rc == 0) {
2065  stonith_history_t *hp = NULL;
2066 
2067  hp = stonith__first_matching_event(stonith_history,
2069  GINT_TO_POINTER(st_failed));
2070  if (hp) {
2071  out->message(out, "failed-fencing-list", stonith_history,
2072  unames, section_opts, show_opts, false);
2073  }
2074  } else {
2075  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
2076  out->list_item(out, NULL, "Failed to get fencing history: %s",
2077  crm_exit_str(history_rc));
2078  out->end_list(out);
2079  }
2080  }
2081 
2082  /* Print stonith history */
2083  if (pcmk_any_flags_set(section_opts, pcmk_section_fencing_all) &&
2084  fence_history != pcmk__fence_history_none) {
2085  if (history_rc != 0) {
2086  if (!already_printed_failure) {
2087  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
2088  out->list_item(out, NULL, "Failed to get fencing history: %s",
2089  crm_exit_str(history_rc));
2090  out->end_list(out);
2091  }
2092  } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
2093  stonith_history_t *hp = NULL;
2094 
2095  hp = stonith__first_matching_event(stonith_history,
2097  GINT_TO_POINTER(st_failed));
2098  if (hp) {
2099  out->message(out, "fencing-list", hp, unames, section_opts,
2100  show_opts, false);
2101  }
2102  } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
2103  stonith_history_t *hp = NULL;
2104 
2105  hp = stonith__first_matching_event(stonith_history,
2107  NULL);
2108  if (hp) {
2109  out->message(out, "pending-fencing-list", hp, unames,
2110  section_opts, show_opts, false);
2111  }
2112  }
2113  }
2114 
2115  /* Print tickets if requested */
2116  if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
2117  out->message(out, "ticket-list", scheduler, false);
2118  }
2119 
2120  /* Print negative location constraints if requested */
2121  if (pcmk_is_set(section_opts, pcmk_section_bans)) {
2122  out->message(out, "ban-list", scheduler, prefix, resources, show_opts,
2123  false);
2124  }
2125 
2126  return pcmk_rc_ok;
2127 }
2128 
2129 PCMK__OUTPUT_ARGS("attribute", "const char *", "const char *", "const char *",
2130  "const char *", "const char *")
2131 static int
2132 attribute_default(pcmk__output_t *out, va_list args)
2133 {
2134  const char *scope = va_arg(args, const char *);
2135  const char *instance = va_arg(args, const char *);
2136  const char *name = va_arg(args, const char *);
2137  const char *value = va_arg(args, const char *);
2138  const char *host = va_arg(args, const char *);
2139 
2140  GString *s = g_string_sized_new(50);
2141 
2142  if (!pcmk__str_empty(scope)) {
2143  pcmk__g_strcat(s, "scope=\"", scope, "\" ", NULL);
2144  }
2145 
2146  if (!pcmk__str_empty(instance)) {
2147  pcmk__g_strcat(s, "id=\"", instance, "\" ", NULL);
2148  }
2149 
2150  pcmk__g_strcat(s, "name=\"", pcmk__s(name, ""), "\" ", NULL);
2151 
2152  if (!pcmk__str_empty(host)) {
2153  pcmk__g_strcat(s, "host=\"", host, "\" ", NULL);
2154  }
2155 
2156  pcmk__g_strcat(s, "value=\"", pcmk__s(value, ""), "\"", NULL);
2157 
2158  out->info(out, "%s", s->str);
2159  g_string_free(s, TRUE);
2160 
2161  return pcmk_rc_ok;
2162 }
2163 
2164 PCMK__OUTPUT_ARGS("attribute", "const char *", "const char *", "const char *",
2165  "const char *", "const char *")
2166 static int
2167 attribute_xml(pcmk__output_t *out, va_list args)
2168 {
2169  const char *scope = va_arg(args, const char *);
2170  const char *instance = va_arg(args, const char *);
2171  const char *name = va_arg(args, const char *);
2172  const char *value = va_arg(args, const char *);
2173  const char *host = va_arg(args, const char *);
2174 
2175  xmlNodePtr node = NULL;
2176 
2177  node = pcmk__output_create_xml_node(out, "attribute",
2178  "name", name,
2179  "value", value ? value : "",
2180  NULL);
2181 
2182  if (!pcmk__str_empty(scope)) {
2183  crm_xml_add(node, "scope", scope);
2184  }
2185 
2186  if (!pcmk__str_empty(instance)) {
2187  crm_xml_add(node, "id", instance);
2188  }
2189 
2190  if (!pcmk__str_empty(host)) {
2191  crm_xml_add(node, "host", host);
2192  }
2193 
2194  return pcmk_rc_ok;
2195 }
2196 
2197 PCMK__OUTPUT_ARGS("rule-check", "const char *", "int", "const char *")
2198 static int
2199 rule_check_default(pcmk__output_t *out, va_list args)
2200 {
2201  const char *rule_id = va_arg(args, const char *);
2202  int result = va_arg(args, int);
2203  const char *error = va_arg(args, const char *);
2204 
2205  switch (result) {
2206  case pcmk_rc_within_range:
2207  return out->info(out, "Rule %s is still in effect", rule_id);
2208  case pcmk_rc_ok:
2209  return out->info(out, "Rule %s satisfies conditions", rule_id);
2210  case pcmk_rc_after_range:
2211  return out->info(out, "Rule %s is expired", rule_id);
2212  case pcmk_rc_before_range:
2213  return out->info(out, "Rule %s has not yet taken effect", rule_id);
2215  return out->info(out, "Rule %s does not satisfy conditions",
2216  rule_id);
2217  default:
2218  out->err(out,
2219  "Could not determine whether rule %s is in effect: %s",
2220  rule_id, ((error != NULL)? error : "unexpected error"));
2221  return pcmk_rc_ok;
2222  }
2223 }
2224 
2225 PCMK__OUTPUT_ARGS("rule-check", "const char *", "int", "const char *")
2226 static int
2227 rule_check_xml(pcmk__output_t *out, va_list args)
2228 {
2229  const char *rule_id = va_arg(args, const char *);
2230  int result = va_arg(args, int);
2231  const char *error = va_arg(args, const char *);
2232 
2233  char *rc_str = pcmk__itoa(pcmk_rc2exitc(result));
2234 
2235  pcmk__output_create_xml_node(out, "rule-check",
2236  "rule-id", rule_id,
2237  "rc", rc_str,
2238  NULL);
2239  free(rc_str);
2240 
2241  switch (result) {
2242  case pcmk_rc_within_range:
2243  case pcmk_rc_ok:
2244  case pcmk_rc_after_range:
2245  case pcmk_rc_before_range:
2247  return pcmk_rc_ok;
2248  default:
2249  out->err(out,
2250  "Could not determine whether rule %s is in effect: %s",
2251  rule_id, ((error != NULL)? error : "unexpected error"));
2252  return pcmk_rc_ok;
2253  }
2254 }
2255 
2256 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2257 static int
2258 result_code_none(pcmk__output_t *out, va_list args)
2259 {
2260  return pcmk_rc_no_output;
2261 }
2262 
2263 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2264 static int
2265 result_code_text(pcmk__output_t *out, va_list args)
2266 {
2267  int code = va_arg(args, int);
2268  const char *name = va_arg(args, const char *);
2269  const char *desc = va_arg(args, const char *);
2270 
2271  static int code_width = 0;
2272 
2273  if (out->is_quiet(out)) {
2274  /* If out->is_quiet(), don't print the code. Print name and/or desc in a
2275  * compact format for text output, or print nothing at all for none-type
2276  * output.
2277  */
2278  if ((name != NULL) && (desc != NULL)) {
2279  pcmk__formatted_printf(out, "%s - %s\n", name, desc);
2280 
2281  } else if ((name != NULL) || (desc != NULL)) {
2282  pcmk__formatted_printf(out, "%s\n", ((name != NULL)? name : desc));
2283  }
2284  return pcmk_rc_ok;
2285  }
2286 
2287  /* Get length of longest (most negative) standard Pacemaker return code
2288  * This should be longer than all the values of any other type of return
2289  * code.
2290  */
2291  if (code_width == 0) {
2292  long long most_negative = pcmk_rc_error - (long long) pcmk__n_rc + 1;
2293  code_width = (int) snprintf(NULL, 0, "%lld", most_negative);
2294  }
2295 
2296  if ((name != NULL) && (desc != NULL)) {
2297  static int name_width = 0;
2298 
2299  if (name_width == 0) {
2300  // Get length of longest standard Pacemaker return code name
2301  for (int lpc = 0; lpc < pcmk__n_rc; lpc++) {
2302  int len = (int) strlen(pcmk_rc_name(pcmk_rc_error - lpc));
2303  name_width = QB_MAX(name_width, len);
2304  }
2305  }
2306  return out->info(out, "% *d: %-*s %s", code_width, code, name_width,
2307  name, desc);
2308  }
2309 
2310  if ((name != NULL) || (desc != NULL)) {
2311  return out->info(out, "% *d: %s", code_width, code,
2312  ((name != NULL)? name : desc));
2313  }
2314 
2315  return out->info(out, "% *d", code_width, code);
2316 }
2317 
2318 PCMK__OUTPUT_ARGS("result-code", "int", "const char *", "const char *")
2319 static int
2320 result_code_xml(pcmk__output_t *out, va_list args)
2321 {
2322  int code = va_arg(args, int);
2323  const char *name = va_arg(args, const char *);
2324  const char *desc = va_arg(args, const char *);
2325 
2326  char *code_str = pcmk__itoa(code);
2327 
2328  pcmk__output_create_xml_node(out, "result-code",
2329  "code", code_str,
2331  XML_ATTR_DESC, desc,
2332  NULL);
2333  free(code_str);
2334  return pcmk_rc_ok;
2335 }
2336 
2337 static pcmk__message_entry_t fmt_functions[] = {
2338  { "attribute", "default", attribute_default },
2339  { "attribute", "xml", attribute_xml },
2340  { "cluster-status", "default", pcmk__cluster_status_text },
2341  { "cluster-status", "html", cluster_status_html },
2342  { "cluster-status", "xml", cluster_status_xml },
2343  { "crmadmin-node", "default", crmadmin_node },
2344  { "crmadmin-node", "text", crmadmin_node_text },
2345  { "crmadmin-node", "xml", crmadmin_node_xml },
2346  { "dc", "default", dc },
2347  { "dc", "text", dc_text },
2348  { "dc", "xml", dc_xml },
2349  { "digests", "default", digests_text },
2350  { "digests", "xml", digests_xml },
2351  { "health", "default", health },
2352  { "health", "text", health_text },
2353  { "health", "xml", health_xml },
2354  { "inject-attr", "default", inject_attr },
2355  { "inject-attr", "xml", inject_attr_xml },
2356  { "inject-cluster-action", "default", inject_cluster_action },
2357  { "inject-cluster-action", "xml", inject_cluster_action_xml },
2358  { "inject-fencing-action", "default", inject_fencing_action },
2359  { "inject-fencing-action", "xml", inject_fencing_action_xml },
2360  { "inject-modify-config", "default", inject_modify_config },
2361  { "inject-modify-config", "xml", inject_modify_config_xml },
2362  { "inject-modify-node", "default", inject_modify_node },
2363  { "inject-modify-node", "xml", inject_modify_node_xml },
2364  { "inject-modify-ticket", "default", inject_modify_ticket },
2365  { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
2366  { "inject-pseudo-action", "default", inject_pseudo_action },
2367  { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
2368  { "inject-rsc-action", "default", inject_rsc_action },
2369  { "inject-rsc-action", "xml", inject_rsc_action_xml },
2370  { "inject-spec", "default", inject_spec },
2371  { "inject-spec", "xml", inject_spec_xml },
2372  { "locations-list", "default", locations_list },
2373  { "locations-list", "xml", locations_list_xml },
2374  { "node-action", "default", node_action },
2375  { "node-action", "xml", node_action_xml },
2376  { "node-info", "default", node_info_default },
2377  { "node-info", "xml", node_info_xml },
2378  { "pacemakerd-health", "default", pacemakerd_health },
2379  { "pacemakerd-health", "html", pacemakerd_health_html },
2380  { "pacemakerd-health", "text", pacemakerd_health_text },
2381  { "pacemakerd-health", "xml", pacemakerd_health_xml },
2382  { "profile", "default", profile_default, },
2383  { "profile", "xml", profile_xml },
2384  { "result-code", "none", result_code_none },
2385  { "result-code", "text", result_code_text },
2386  { "result-code", "xml", result_code_xml },
2387  { "rsc-action", "default", rsc_action_default },
2388  { "rsc-action-item", "default", rsc_action_item },
2389  { "rsc-action-item", "xml", rsc_action_item_xml },
2390  { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
2391  { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
2392  { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
2393  { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
2394  { "rule-check", "default", rule_check_default },
2395  { "rule-check", "xml", rule_check_xml },
2396  { "locations-and-colocations", "default", locations_and_colocations },
2397  { "locations-and-colocations", "xml", locations_and_colocations_xml },
2398 
2399  { NULL, NULL, NULL }
2400 };
2401 
2402 void
2404  pcmk__register_messages(out, fmt_functions);
2405 }
pcmk__cpg_host_t host
Definition: cpg.c:49
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
#define crm_notice(fmt, args...)
Definition: logging.h:383
xmlNode * failed
History entries of failed actions.
Definition: scheduler.h:205
pcmk_scheduler_t * cluster
Cluster that resource is part of.
Definition: resources.h:412
stonith_history_t * stonith__first_matching_event(stonith_history_t *history, bool(*matching_fn)(stonith_history_t *, void *), void *user_data)
Definition: st_client.c:2368
GList * rsc_cons
Definition: resources.h:445
Whether action should not be executed.
Definition: actions.h:244
Control output from tools.
void pcmk__register_messages(pcmk__output_t *out, const pcmk__message_entry_t *table)
Definition: output.c:196
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition: scores.c:86
#define crm_time_log_timeofday
Definition: iso8601.h:68
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
Definition: complex.c:936
Stopped.
Definition: roles.h:29
const char * name
Definition: cib.c:26
pcmk__fence_history
Control how much of the fencing history is output.
Definition: pcmki_fence.h:18
enum rsc_role_e role
Resource&#39;s current role.
Definition: resources.h:468
const size_t pcmk__n_rc
Definition: results.c:331
enum rsc_role_e next_role
Resource&#39;s scheduled next role.
Definition: resources.h:469
Implementation of pcmk_action_t.
Definition: actions.h:390
#define PCMK_ACTION_MONITOR
Definition: actions.h:59
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition: results.c:702
xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition: output_xml.c:442
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:302
#define CHECK_RC(retcode, retval)
Definition: pcmk_output.c:1777
Promoted.
Definition: roles.h:32
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition: nvpair.c:872
#define XML_CONS_TAG_RSC_DEPEND
Definition: msg_xml.h:353
enum crm_exit_e crm_exit_t
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:222
xmlNode * params_restart
Definition: internal.h:458
GList * rsc_cons_lhs
Definition: resources.h:444
enum crm_ais_msg_types type
Definition: cpg.c:48
GList * pe__resource_actions(const pcmk_resource_t *rsc, const pcmk_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
Definition: pe_actions.c:1588
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:434
Implementation of pcmk_scheduler_t.
Definition: scheduler.h:172
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:2403
char * reason
Readable description of why action is needed.
Definition: actions.h:406
const char * action
Definition: pcmk_fence.c:30
bool stonith__event_state_pending(stonith_history_t *history, void *user_data)
Definition: st_client.c:2382
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:64
void void void pcmk__formatted_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define PCMK__XA_CRMD
Definition: crm_internal.h:84
#define CRM_SYSTEM_MCP
Definition: crm.h:109
GList * nodes
Nodes in cluster.
Definition: scheduler.h:195
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
const char * role2text(enum rsc_role_e role)
Definition: common.c:458
void pe__clear_resource_flags_on_all(pcmk_scheduler_t *scheduler, uint64_t flag)
Definition: utils.c:562
#define PCMK_ACTION_DEMOTE
Definition: actions.h:49
int weight
Node score for a given resource.
Definition: nodes.h:131
const char * crm_exit_str(crm_exit_t exit_code)
Definition: results.c:640
Implementation of pcmk_resource_t.
Definition: resources.h:399
void pcmk__unpack_constraints(pcmk_scheduler_t *scheduler)
#define XML_ATTR_ID
Definition: msg_xml.h:156
char * digest_all_calc
Definition: internal.h:459
#define stop_key(rsc)
Definition: internal.h:378
#define XML_CONS_TAG_RSC_LOCATION
Definition: msg_xml.h:355
Whether resource is considered failed.
Definition: resources.h:151
Whether resource must be stopped (instead of demoted) if it is failed.
Definition: resources.h:139
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1217
char * digest_secure_calc
Definition: internal.h:460
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
Whether resource is multiply active with recovery set to stop_unexpected.
Definition: resources.h:169
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:99
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:622
struct pe_node_shared_s * details
Basic node information.
Definition: nodes.h:134
#define XML_ATTR_NAME
Definition: msg_xml.h:157
#define PCMK_ACTION_START
Definition: actions.h:71
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:145
unsigned long long flags
Group of enum pcmk_rsc_flags.
Definition: resources.h:429
const char * uname
Node name in cluster.
Definition: nodes.h:68
Unpromoted.
Definition: roles.h:31
#define XML_ATTR_UNAME
Definition: msg_xml.h:178
PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pcmk_resource_t *", "pcmk_node_t *", "pcmk_node_t *", "pcmk_action_t *", "pcmk_action_t *")
Definition: pcmk_output.c:107
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:638
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition: output_xml.c:478
#define XML_ATTR_DESC
Definition: msg_xml.h:155
#define PCMK_ACTION_STOP
Definition: actions.h:74
GList * actions
Definition: resources.h:447
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:288
#define pcmk_section_fencing_all
Definition: output.h:46
int pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
#define crm_time_log_with_timezone
Definition: iso8601.h:69
Flag for non-scheduler code to use to detect recursion loops.
Definition: resources.h:154
Implementation of pcmk_node_t.
Definition: nodes.h:130
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:522
Function and executable result codes.
xmlNode * params_all
Definition: internal.h:456
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition: xml.c:2654
const xmlChar * pcmkXmlStr
Definition: xml.h:50
pcmk_resource_t * primary
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
const char * target
Definition: pcmk_fence.c:29
pcmk_pacemakerd_state
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
pcmk__action_result_t result
Definition: pcmk_fence.c:35
Whether action is runnable.
Definition: actions.h:241
const char * pcmk_rc_name(int rc)
Get a return code constant name as a string.
Definition: results.c:341
pcmk_scheduler_t * scheduler
const char * pcmk_pacemakerd_api_daemon_state_enum2text(enum pcmk_pacemakerd_state state)
#define STOP_SANITY_ASSERT(lineno)
Definition: pcmk_output.c:1061
GList * find_actions(GList *input, const char *key, const pcmk_node_t *on_node)
Definition: pe_actions.c:1515
#define CRM_ASSERT(expr)
Definition: results.h:42
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
Definition: iso8601.c:1858
#define PCMK_ACTION_MIGRATE_FROM
Definition: actions.h:57
Fencing aka. STONITH.
Started.
Definition: roles.h:30
This structure contains everything that makes up a single output formatter.
xmlNode * params_secure
Definition: internal.h:457
GList * rsc_location
Definition: resources.h:446
#define PCMK_ACTION_PROMOTE
Definition: actions.h:65
pcmk_resource_t * dependent
const char * pcmk__pcmkd_state_enum2friendly(enum pcmk_pacemakerd_state state)
GList * running_on
Nodes where resource may be active.
Definition: resources.h:460
enum pe_action_flags flags
Group of enum pe_action_flags.
Definition: actions.h:409
Whether a reload action has been scheduled for resource.
Definition: resources.h:142
const char * node_attribute
Resource role is unknown.
Definition: roles.h:28
#define ID(x)
Definition: msg_xml.h:474
const char * parent
Definition: cib.c:27
Whether resource is managed.
Definition: resources.h:106
bool stonith__event_state_eq(stonith_history_t *history, void *user_data)
Definition: st_client.c:2388
char * digest_restart_calc
Definition: internal.h:461
#define crm_time_log_date
Definition: iso8601.h:67
bool stonith__event_state_neq(stonith_history_t *history, void *user_data)
Definition: st_client.c:2394
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:35
char * id
Resource ID in configuration.
Definition: resources.h:400