pacemaker  2.1.4-dc6eb4362
Scalable High-Availability cluster resource manager
pcmk_output.c
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2022 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 <stdint.h>
21 
22 static char *
23 colocations_header(pe_resource_t *rsc, pcmk__colocation_t *cons,
24  gboolean dependents) {
25  char *score = NULL;
26  char *retval = NULL;
27 
28  score = score2char(cons->score);
29  if (cons->primary_role > RSC_ROLE_STARTED) {
30  retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
31  rsc->id, score, 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, score, cons->id);
36  }
37 
38  free(score);
39  return retval;
40 }
41 
42 static void
43 colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
44  pcmk__colocation_t *cons) {
45  char *score = NULL;
46  xmlNodePtr node = NULL;
47 
48  score = score2char(cons->score);
50  "id", cons->id,
51  "rsc", cons->dependent->id,
52  "with-rsc", cons->primary->id,
53  "score", score,
54  NULL);
55 
56  if (cons->node_attribute) {
57  xmlSetProp(node, (pcmkXmlStr) "node-attribute", (pcmkXmlStr) cons->node_attribute);
58  }
59 
60  if (cons->dependent_role != RSC_ROLE_UNKNOWN) {
61  xmlSetProp(node, (pcmkXmlStr) "rsc-role",
63  }
64 
65  if (cons->primary_role != RSC_ROLE_UNKNOWN) {
66  xmlSetProp(node, (pcmkXmlStr) "with-rsc-role",
68  }
69 
70  free(score);
71 }
72 
73 static int
74 do_locations_list_xml(pcmk__output_t *out, pe_resource_t *rsc, bool add_header)
75 {
76  GList *lpc = NULL;
77  GList *list = rsc->rsc_location;
78  int rc = pcmk_rc_no_output;
79 
80  for (lpc = list; lpc != NULL; lpc = lpc->next) {
81  pe__location_t *cons = lpc->data;
82 
83  GList *lpc2 = NULL;
84 
85  for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
86  pe_node_t *node = (pe_node_t *) lpc2->data;
87  char *score = score2char(node->weight);
88 
89  if (add_header) {
90  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
91  }
92 
94  "node", node->details->uname,
95  "rsc", rsc->id,
96  "id", cons->id,
97  "score", score,
98  NULL);
99  free(score);
100  }
101  }
102 
103  if (add_header) {
104  PCMK__OUTPUT_LIST_FOOTER(out, rc);
105  }
106 
107  return rc;
108 }
109 
110 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
111  "pe_node_t *", "pe_node_t *", "pe_action_t *",
112  "pe_action_t *")
113 static int
114 rsc_action_item(pcmk__output_t *out, va_list args)
115 {
116  const char *change = va_arg(args, const char *);
117  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
118  pe_node_t *origin = va_arg(args, pe_node_t *);
119  pe_node_t *destination = va_arg(args, pe_node_t *);
120  pe_action_t *action = va_arg(args, pe_action_t *);
121  pe_action_t *source = va_arg(args, pe_action_t *);
122 
123  int len = 0;
124  char *reason = NULL;
125  char *details = NULL;
126  bool same_host = FALSE;
127  bool same_role = FALSE;
128  bool need_role = FALSE;
129 
130  static int rsc_width = 5;
131  static int detail_width = 5;
132 
134  CRM_ASSERT(destination != NULL || origin != NULL);
135 
136  if(source == NULL) {
137  source = action;
138  }
139 
140  len = strlen(rsc->id);
141  if(len > rsc_width) {
142  rsc_width = len + 2;
143  }
144 
145  if ((rsc->role > RSC_ROLE_STARTED)
146  || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
147  need_role = TRUE;
148  }
149 
150  if(origin != NULL && destination != NULL && origin->details == destination->details) {
151  same_host = TRUE;
152  }
153 
154  if(rsc->role == rsc->next_role) {
155  same_role = TRUE;
156  }
157 
158  if (need_role && (origin == NULL)) {
159  /* Starting and promoting a promotable clone instance */
160  details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), destination->details->uname);
161 
162  } else if (origin == NULL) {
163  /* Starting a resource */
164  details = crm_strdup_printf("%s", destination->details->uname);
165 
166  } else if (need_role && (destination == NULL)) {
167  /* Stopping a promotable clone instance */
168  details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
169 
170  } else if (destination == NULL) {
171  /* Stopping a resource */
172  details = crm_strdup_printf("%s", origin->details->uname);
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), origin->details->uname);
177 
178  } else if (same_role && same_host) {
179  /* Recovering or Restarting a normal resource */
180  details = crm_strdup_printf("%s", origin->details->uname);
181 
182  } else if (need_role && same_role) {
183  /* Moving a promotable clone instance */
184  details = crm_strdup_printf("%s -> %s %s", origin->details->uname, destination->details->uname, role2text(rsc->role));
185 
186  } else if (same_role) {
187  /* Moving a normal resource */
188  details = crm_strdup_printf("%s -> %s", origin->details->uname, destination->details->uname);
189 
190  } else if (same_host) {
191  /* Promoting or demoting a promotable clone instance */
192  details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), origin->details->uname);
193 
194  } else {
195  /* Moving and promoting/demoting */
196  details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role), origin->details->uname, role2text(rsc->next_role), destination->details->uname);
197  }
198 
199  len = strlen(details);
200  if(len > detail_width) {
201  detail_width = len;
202  }
203 
204  if(source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
205  reason = crm_strdup_printf("due to %s (blocked)", source->reason);
206 
207  } else if(source->reason) {
208  reason = crm_strdup_printf("due to %s", source->reason);
209 
210  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
211  reason = strdup("blocked");
212 
213  }
214 
215  out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s", change, rsc_width,
216  rsc->id, detail_width, details, reason ? " " : "", reason ? reason : "");
217 
218  free(details);
219  free(reason);
220  return pcmk_rc_ok;
221 }
222 
223 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
224  "pe_node_t *", "pe_node_t *", "pe_action_t *",
225  "pe_action_t *")
226 static int
227 rsc_action_item_xml(pcmk__output_t *out, va_list args)
228 {
229  const char *change = va_arg(args, const char *);
230  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
231  pe_node_t *origin = va_arg(args, pe_node_t *);
232  pe_node_t *destination = va_arg(args, pe_node_t *);
233  pe_action_t *action = va_arg(args, pe_action_t *);
234  pe_action_t *source = va_arg(args, pe_action_t *);
235 
236  char *change_str = NULL;
237 
238  bool same_host = FALSE;
239  bool same_role = FALSE;
240  bool need_role = FALSE;
241  xmlNode *xml = NULL;
242 
244  CRM_ASSERT(destination != NULL || origin != NULL);
245 
246  if (source == NULL) {
247  source = action;
248  }
249 
250  if ((rsc->role > RSC_ROLE_STARTED)
251  || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
252  need_role = TRUE;
253  }
254 
255  if(origin != NULL && destination != NULL && origin->details == destination->details) {
256  same_host = TRUE;
257  }
258 
259  if(rsc->role == rsc->next_role) {
260  same_role = TRUE;
261  }
262 
263  change_str = g_ascii_strdown(change, -1);
264  xml = pcmk__output_create_xml_node(out, "rsc_action",
265  "action", change_str,
266  "resource", rsc->id,
267  NULL);
268  g_free(change_str);
269 
270  if (need_role && (origin == NULL)) {
271  /* Starting and promoting a promotable clone instance */
272  pcmk__xe_set_props(xml,
273  "role", role2text(rsc->role),
274  "next-role", role2text(rsc->next_role),
275  "dest", destination->details->uname,
276  NULL);
277 
278  } else if (origin == NULL) {
279  /* Starting a resource */
280  crm_xml_add(xml, "node", destination->details->uname);
281 
282  } else if (need_role && (destination == NULL)) {
283  /* Stopping a promotable clone instance */
284  pcmk__xe_set_props(xml,
285  "role", role2text(rsc->role),
286  "node", origin->details->uname,
287  NULL);
288 
289  } else if (destination == NULL) {
290  /* Stopping a resource */
291  crm_xml_add(xml, "node", origin->details->uname);
292 
293  } else if (need_role && same_role && same_host) {
294  /* Recovering, restarting or re-promoting a promotable clone instance */
295  pcmk__xe_set_props(xml,
296  "role", role2text(rsc->role),
297  "source", origin->details->uname,
298  NULL);
299 
300  } else if (same_role && same_host) {
301  /* Recovering or Restarting a normal resource */
302  crm_xml_add(xml, "source", origin->details->uname);
303 
304  } else if (need_role && same_role) {
305  /* Moving a promotable clone instance */
306  pcmk__xe_set_props(xml,
307  "source", origin->details->uname,
308  "dest", destination->details->uname,
309  "role", role2text(rsc->role),
310  NULL);
311 
312  } else if (same_role) {
313  /* Moving a normal resource */
314  pcmk__xe_set_props(xml,
315  "source", origin->details->uname,
316  "dest", destination->details->uname,
317  NULL);
318 
319  } else if (same_host) {
320  /* Promoting or demoting a promotable clone instance */
321  pcmk__xe_set_props(xml,
322  "role", role2text(rsc->role),
323  "next-role", role2text(rsc->next_role),
324  "source", origin->details->uname,
325  NULL);
326 
327  } else {
328  /* Moving and promoting/demoting */
329  pcmk__xe_set_props(xml,
330  "role", role2text(rsc->role),
331  "source", origin->details->uname,
332  "next-role", role2text(rsc->next_role),
333  "dest", destination->details->uname,
334  NULL);
335  }
336 
337  if (source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
338  pcmk__xe_set_props(xml,
339  "reason", source->reason,
340  "blocked", "true",
341  NULL);
342 
343  } else if(source->reason) {
344  crm_xml_add(xml, "reason", source->reason);
345 
346  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
347  pcmk__xe_set_bool_attr(xml, "blocked", true);
348 
349  }
350 
351  return pcmk_rc_ok;
352 }
353 
354 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
355 static int
356 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
357  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
358  gboolean recursive = va_arg(args, gboolean);
359 
360  int rc = pcmk_rc_no_output;
361 
362  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
363  return rc;
364  }
365 
367  for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
368  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
369  char *hdr = NULL;
370 
371  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources %s is colocated with", rsc->id);
372 
374  out->list_item(out, NULL, "%s (id=%s - loop)",
375  cons->primary->id, cons->id);
376  continue;
377  }
378 
379  hdr = colocations_header(cons->primary, cons, FALSE);
380  out->list_item(out, NULL, "%s", hdr);
381  free(hdr);
382 
383  /* Empty list header just for indentation of information about this resource. */
384  out->begin_list(out, NULL, NULL, NULL);
385 
386  out->message(out, "locations-list", cons->primary);
387  if (recursive) {
388  out->message(out, "rsc-is-colocated-with-list",
389  cons->primary, recursive);
390  }
391 
392  out->end_list(out);
393  }
394 
395  PCMK__OUTPUT_LIST_FOOTER(out, rc);
396  return rc;
397 }
398 
399 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
400 static int
401 rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
402  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
403  gboolean recursive = va_arg(args, gboolean);
404 
405  int rc = pcmk_rc_no_output;
406 
407  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
408  return rc;
409  }
410 
412  for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
413  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
414 
416  colocations_xml_node(out, cons->primary, cons);
417  continue;
418  }
419 
420  colocations_xml_node(out, cons->primary, cons);
421  do_locations_list_xml(out, cons->primary, false);
422 
423  if (recursive) {
424  out->message(out, "rsc-is-colocated-with-list",
425  cons->primary, recursive);
426  }
427  }
428 
429  return rc;
430 }
431 
432 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
433 static int
434 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
435  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
436  gboolean recursive = va_arg(args, gboolean);
437 
438  int rc = pcmk_rc_no_output;
439 
440  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
441  return rc;
442  }
443 
445  for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
446  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
447  char *hdr = NULL;
448 
449  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
450 
452  out->list_item(out, NULL, "%s (id=%s - loop)",
453  cons->dependent->id, cons->id);
454  continue;
455  }
456 
457  hdr = colocations_header(cons->dependent, cons, TRUE);
458  out->list_item(out, NULL, "%s", hdr);
459  free(hdr);
460 
461  /* Empty list header just for indentation of information about this resource. */
462  out->begin_list(out, NULL, NULL, NULL);
463 
464  out->message(out, "locations-list", cons->dependent);
465  if (recursive) {
466  out->message(out, "rscs-colocated-with-list",
467  cons->dependent, recursive);
468  }
469 
470  out->end_list(out);
471  }
472 
473  PCMK__OUTPUT_LIST_FOOTER(out, rc);
474  return rc;
475 }
476 
477 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
478 static int
479 rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
480  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
481  gboolean recursive = va_arg(args, gboolean);
482 
483  int rc = pcmk_rc_no_output;
484 
485  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
486  return rc;
487  }
488 
490  for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
491  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
492 
494  colocations_xml_node(out, cons->dependent, cons);
495  continue;
496  }
497 
498  colocations_xml_node(out, cons->dependent, cons);
499  do_locations_list_xml(out, cons->dependent, false);
500 
501  if (recursive) {
502  out->message(out, "rscs-colocated-with-list",
503  cons->dependent, recursive);
504  }
505  }
506 
507  return rc;
508 }
509 
510 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
511 static int
512 locations_list(pcmk__output_t *out, va_list args) {
513  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
514 
515  GList *lpc = NULL;
516  GList *list = rsc->rsc_location;
517  int rc = pcmk_rc_no_output;
518 
519  for (lpc = list; lpc != NULL; lpc = lpc->next) {
520  pe__location_t *cons = lpc->data;
521 
522  GList *lpc2 = NULL;
523 
524  for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
525  pe_node_t *node = (pe_node_t *) lpc2->data;
526  char *score = score2char(node->weight);
527 
528  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Locations");
529  out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
530  node->details->uname, score, cons->id, rsc->id);
531  free(score);
532  }
533  }
534 
535  PCMK__OUTPUT_LIST_FOOTER(out, rc);
536  return rc;
537 }
538 
539 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
540 static int
541 locations_list_xml(pcmk__output_t *out, va_list args) {
542  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
543  return do_locations_list_xml(out, rsc, true);
544 }
545 
546 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
547 static int
548 stacks_and_constraints(pcmk__output_t *out, va_list args) {
549  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
550  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
551  gboolean recursive = va_arg(args, gboolean);
552 
554 
555  // Constraints apply to group/clone, not member/instance
556  rsc = uber_parent(rsc);
557 
558  out->message(out, "locations-list", rsc);
559 
561  out->message(out, "rscs-colocated-with-list", rsc, recursive);
562 
564  out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
565  return pcmk_rc_ok;
566 }
567 
568 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
569 static int
570 stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
571  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
572  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
573  gboolean recursive = va_arg(args, gboolean);
574 
576 
577  // Constraints apply to group/clone, not member/instance
578  rsc = uber_parent(rsc);
579 
580  pcmk__output_xml_create_parent(out, "constraints", NULL);
581  do_locations_list_xml(out, rsc, false);
582 
584  out->message(out, "rscs-colocated-with-list", rsc, recursive);
585 
587  out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
588 
590  return pcmk_rc_ok;
591 }
592 
593 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
594 static int
595 health_text(pcmk__output_t *out, va_list args)
596 {
597  const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
598  const char *host_from = va_arg(args, const char *);
599  const char *fsa_state = va_arg(args, const char *);
600  const char *result = va_arg(args, const char *);
601 
602  if (!out->is_quiet(out)) {
603  return out->info(out, "Controller on %s in state %s: %s", crm_str(host_from),
604  crm_str(fsa_state), crm_str(result));
605  } else if (fsa_state != NULL) {
606  pcmk__formatted_printf(out, "%s\n", fsa_state);
607  return pcmk_rc_ok;
608  }
609 
610  return pcmk_rc_no_output;
611 }
612 
613 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
614 static int
615 health_xml(pcmk__output_t *out, va_list args)
616 {
617  const char *sys_from = va_arg(args, const char *);
618  const char *host_from = va_arg(args, const char *);
619  const char *fsa_state = va_arg(args, const char *);
620  const char *result = va_arg(args, const char *);
621 
622  pcmk__output_create_xml_node(out, crm_str(sys_from),
623  "node_name", crm_str(host_from),
624  "state", crm_str(fsa_state),
625  "result", crm_str(result),
626  NULL);
627  return pcmk_rc_ok;
628 }
629 
630 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
631 static int
632 pacemakerd_health_text(pcmk__output_t *out, va_list args)
633 {
634  const char *sys_from = va_arg(args, const char *);
635  const char *state = va_arg(args, const char *);
636  const char *last_updated = va_arg(args, const char *);
637 
638  if (!out->is_quiet(out)) {
639  return out->info(out, "Status of %s: '%s' %s %s", crm_str(sys_from),
640  crm_str(state), (!pcmk__str_empty(last_updated))?
641  "last updated":"", crm_str(last_updated));
642  } else {
643  pcmk__formatted_printf(out, "%s\n", crm_str(state));
644  return pcmk_rc_ok;
645  }
646 
647  return pcmk_rc_no_output;
648 }
649 
650 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
651 static int
652 pacemakerd_health_xml(pcmk__output_t *out, va_list args)
653 {
654  const char *sys_from = va_arg(args, const char *);
655  const char *state = va_arg(args, const char *);
656  const char *last_updated = va_arg(args, const char *);
657 
658  pcmk__output_create_xml_node(out, crm_str(sys_from),
659  "state", crm_str(state),
660  "last_updated", crm_str(last_updated),
661  NULL);
662  return pcmk_rc_ok;
663 }
664 
665 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
666 static int
667 profile_default(pcmk__output_t *out, va_list args) {
668  const char *xml_file = va_arg(args, const char *);
669  clock_t start = va_arg(args, clock_t);
670  clock_t end = va_arg(args, clock_t);
671 
672  out->list_item(out, NULL, "Testing %s ... %.2f secs", xml_file,
673  (end - start) / (float) CLOCKS_PER_SEC);
674 
675  return pcmk_rc_ok;
676 }
677 
678 PCMK__OUTPUT_ARGS("profile", "const char *", "clock_t", "clock_t")
679 static int
680 profile_xml(pcmk__output_t *out, va_list args) {
681  const char *xml_file = va_arg(args, const char *);
682  clock_t start = va_arg(args, clock_t);
683  clock_t end = va_arg(args, clock_t);
684 
685  char *duration = pcmk__ftoa((end - start) / (float) CLOCKS_PER_SEC);
686 
687  pcmk__output_create_xml_node(out, "timing",
688  "file", xml_file,
689  "duration", duration,
690  NULL);
691 
692  free(duration);
693  return pcmk_rc_ok;
694 }
695 
696 PCMK__OUTPUT_ARGS("dc", "const char *")
697 static int
698 dc_text(pcmk__output_t *out, va_list args)
699 {
700  const char *dc = va_arg(args, const char *);
701 
702  if (!out->is_quiet(out)) {
703  return out->info(out, "Designated Controller is: %s", crm_str(dc));
704  } else if (dc != NULL) {
705  pcmk__formatted_printf(out, "%s\n", dc);
706  return pcmk_rc_ok;
707  }
708 
709  return pcmk_rc_no_output;
710 }
711 
712 PCMK__OUTPUT_ARGS("dc", "const char *")
713 static int
714 dc_xml(pcmk__output_t *out, va_list args)
715 {
716  const char *dc = va_arg(args, const char *);
717 
719  "node_name", crm_str(dc),
720  NULL);
721  return pcmk_rc_ok;
722 }
723 
724 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
725 static int
726 crmadmin_node_text(pcmk__output_t *out, va_list args)
727 {
728  const char *type = va_arg(args, const char *);
729  const char *name = va_arg(args, const char *);
730  const char *id = va_arg(args, const char *);
731  gboolean BASH_EXPORT = va_arg(args, gboolean);
732 
733  if (out->is_quiet(out)) {
734  pcmk__formatted_printf(out, "%s\n", crm_str(name));
735  return pcmk_rc_ok;
736  } else if (BASH_EXPORT) {
737  return out->info(out, "export %s=%s", crm_str(name), crm_str(id));
738  } else {
739  return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
740  crm_str(name), crm_str(id));
741  }
742 }
743 
744 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
745 static int
746 crmadmin_node_xml(pcmk__output_t *out, va_list args)
747 {
748  const char *type = va_arg(args, const char *);
749  const char *name = va_arg(args, const char *);
750  const char *id = va_arg(args, const char *);
751 
752  pcmk__output_create_xml_node(out, "node",
753  "type", type ? type : "cluster",
754  "name", crm_str(name),
755  "id", crm_str(id),
756  NULL);
757  return pcmk_rc_ok;
758 }
759 
760 PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
761  "guint", "op_digest_cache_t *")
762 static int
763 digests_text(pcmk__output_t *out, va_list args)
764 {
765  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
766  pe_node_t *node = va_arg(args, pe_node_t *);
767  const char *task = va_arg(args, const char *);
768  guint interval_ms = va_arg(args, guint);
769  op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
770 
771  char *action_desc = NULL;
772  const char *rsc_desc = "unknown resource";
773  const char *node_desc = "unknown node";
774 
775  if (interval_ms != 0) {
776  action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
777  ((task == NULL)? "unknown" : task));
778  } else if (pcmk__str_eq(task, "monitor", pcmk__str_none)) {
779  action_desc = strdup("probe action");
780  } else {
781  action_desc = crm_strdup_printf("%s action",
782  ((task == NULL)? "unknown" : task));
783  }
784  if ((rsc != NULL) && (rsc->id != NULL)) {
785  rsc_desc = rsc->id;
786  }
787  if ((node != NULL) && (node->details->uname != NULL)) {
788  node_desc = node->details->uname;
789  }
790  out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
791  rsc_desc, action_desc, node_desc);
792  free(action_desc);
793 
794  if (digests == NULL) {
795  out->list_item(out, NULL, "none");
796  out->end_list(out);
797  return pcmk_rc_ok;
798  }
799  if (digests->digest_all_calc != NULL) {
800  out->list_item(out, NULL, "%s (all parameters)",
801  digests->digest_all_calc);
802  }
803  if (digests->digest_secure_calc != NULL) {
804  out->list_item(out, NULL, "%s (non-private parameters)",
805  digests->digest_secure_calc);
806  }
807  if (digests->digest_restart_calc != NULL) {
808  out->list_item(out, NULL, "%s (non-reloadable parameters)",
809  digests->digest_restart_calc);
810  }
811  out->end_list(out);
812  return pcmk_rc_ok;
813 }
814 
815 static void
816 add_digest_xml(xmlNode *parent, const char *type, const char *digest,
817  xmlNode *digest_source)
818 {
819  if (digest != NULL) {
820  xmlNodePtr digest_xml = create_xml_node(parent, "digest");
821 
822  crm_xml_add(digest_xml, "type", ((type == NULL)? "unspecified" : type));
823  crm_xml_add(digest_xml, "hash", digest);
824  if (digest_source != NULL) {
825  add_node_copy(digest_xml, digest_source);
826  }
827  }
828 }
829 
830 PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
831  "guint", "op_digest_cache_t *")
832 static int
833 digests_xml(pcmk__output_t *out, va_list args)
834 {
835  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
836  pe_node_t *node = va_arg(args, pe_node_t *);
837  const char *task = va_arg(args, const char *);
838  guint interval_ms = va_arg(args, guint);
839  op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
840 
841  char *interval_s = crm_strdup_printf("%ums", interval_ms);
842  xmlNode *xml = NULL;
843 
844  xml = pcmk__output_create_xml_node(out, "digests",
845  "resource", crm_str(rsc->id),
846  "node", crm_str(node->details->uname),
847  "task", crm_str(task),
848  "interval", interval_s,
849  NULL);
850  free(interval_s);
851  if (digests != NULL) {
852  add_digest_xml(xml, "all", digests->digest_all_calc,
853  digests->params_all);
854  add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
855  digests->params_secure);
856  add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
857  digests->params_restart);
858  }
859  return pcmk_rc_ok;
860 }
861 
862 #define STOP_SANITY_ASSERT(lineno) do { \
863  if(current && current->details->unclean) { \
864  /* It will be a pseudo op */ \
865  } else if(stop == NULL) { \
866  crm_err("%s:%d: No stop action exists for %s", \
867  __func__, lineno, rsc->id); \
868  CRM_ASSERT(stop != NULL); \
869  } else if (pcmk_is_set(stop->flags, pe_action_optional)) { \
870  crm_err("%s:%d: Action %s is still optional", \
871  __func__, lineno, stop->uuid); \
872  CRM_ASSERT(!pcmk_is_set(stop->flags, pe_action_optional)); \
873  } \
874  } while(0)
875 
876 PCMK__OUTPUT_ARGS("rsc-action", "pe_resource_t *", "pe_node_t *", "pe_node_t *")
877 static int
878 rsc_action_default(pcmk__output_t *out, va_list args)
879 {
880  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
881  pe_node_t *current = va_arg(args, pe_node_t *);
882  pe_node_t *next = va_arg(args, pe_node_t *);
883 
884  GList *possible_matches = NULL;
885  char *key = NULL;
886  int rc = pcmk_rc_no_output;
887  bool moving = false;
888 
889  pe_node_t *start_node = NULL;
890  pe_action_t *start = NULL;
891  pe_action_t *stop = NULL;
892  pe_action_t *promote = NULL;
893  pe_action_t *demote = NULL;
894 
895  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)
896  || (current == NULL && next == NULL)) {
897  pe_rsc_info(rsc, "Leave %s\t(%s%s)",
898  rsc->id, role2text(rsc->role),
899  !pcmk_is_set(rsc->flags, pe_rsc_managed)? " unmanaged" : "");
900  return rc;
901  }
902 
903  moving = (current != NULL) && (next != NULL)
904  && (current->details != next->details);
905 
906  possible_matches = pe__resource_actions(rsc, next, RSC_START, FALSE);
907  if (possible_matches) {
908  start = possible_matches->data;
909  g_list_free(possible_matches);
910  }
911 
912  if ((start == NULL) || !pcmk_is_set(start->flags, pe_action_runnable)) {
913  start_node = NULL;
914  } else {
915  start_node = current;
916  }
917  possible_matches = pe__resource_actions(rsc, start_node, RSC_STOP, FALSE);
918  if (possible_matches) {
919  stop = possible_matches->data;
920  g_list_free(possible_matches);
921  } else if (pcmk_is_set(rsc->flags, pe_rsc_stop_unexpected)) {
922  /* The resource is multiply active with multiple-active set to
923  * stop_unexpected, and not stopping on its current node, but it should
924  * be stopping elsewhere.
925  */
926  possible_matches = pe__resource_actions(rsc, NULL, RSC_STOP, FALSE);
927  if (possible_matches != NULL) {
928  stop = possible_matches->data;
929  g_list_free(possible_matches);
930  }
931  }
932 
933  possible_matches = pe__resource_actions(rsc, next, RSC_PROMOTE, FALSE);
934  if (possible_matches) {
935  promote = possible_matches->data;
936  g_list_free(possible_matches);
937  }
938 
939  possible_matches = pe__resource_actions(rsc, next, RSC_DEMOTE, FALSE);
940  if (possible_matches) {
941  demote = possible_matches->data;
942  g_list_free(possible_matches);
943  }
944 
945  if (rsc->role == rsc->next_role) {
946  pe_action_t *migrate_op = NULL;
947 
948  CRM_CHECK(next != NULL, return rc);
949 
950  possible_matches = pe__resource_actions(rsc, next, RSC_MIGRATED, FALSE);
951  if (possible_matches) {
952  migrate_op = possible_matches->data;
953  }
954 
955  if ((migrate_op != NULL) && (current != NULL)
956  && pcmk_is_set(migrate_op->flags, pe_action_runnable)) {
957  rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
958  next, start, NULL);
959 
960  } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
961  rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
962  next, start, NULL);
963 
964  } else if (start == NULL || pcmk_is_set(start->flags, pe_action_optional)) {
965  if ((demote != NULL) && (promote != NULL)
966  && !pcmk_is_set(demote->flags, pe_action_optional)
967  && !pcmk_is_set(promote->flags, pe_action_optional)) {
968  rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
969  current, next, promote, demote);
970  } else {
971  pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
972  role2text(rsc->role), next->details->uname);
973  }
974 
975  } else if (!pcmk_is_set(start->flags, pe_action_runnable)) {
976  rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
977  NULL, stop, (stop && stop->reason)? stop : start);
978  STOP_SANITY_ASSERT(__LINE__);
979 
980  } else if (moving && current) {
981  rc = out->message(out, "rsc-action-item", pcmk_is_set(rsc->flags, pe_rsc_failed)? "Recover" : "Move",
982  rsc, current, next, stop, NULL);
983 
984  } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
985  rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
986  NULL, stop, NULL);
987  STOP_SANITY_ASSERT(__LINE__);
988 
989  } else {
990  rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
991  next, start, NULL);
992  /* STOP_SANITY_ASSERT(__LINE__); False positive for migrate-fail-7 */
993  }
994 
995  g_list_free(possible_matches);
996  return rc;
997  }
998 
999  if(stop
1000  && (rsc->next_role == RSC_ROLE_STOPPED
1001  || (start && !pcmk_is_set(start->flags, pe_action_runnable)))) {
1002 
1003  GList *gIter = NULL;
1004 
1005  key = stop_key(rsc);
1006  for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
1007  pe_node_t *node = (pe_node_t *) gIter->data;
1008  pe_action_t *stop_op = NULL;
1009 
1010  possible_matches = find_actions(rsc->actions, key, node);
1011  if (possible_matches) {
1012  stop_op = possible_matches->data;
1013  g_list_free(possible_matches);
1014  }
1015 
1016  if (stop_op && (stop_op->flags & pe_action_runnable)) {
1017  STOP_SANITY_ASSERT(__LINE__);
1018  }
1019 
1020  if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
1021  stop_op, (stop_op && stop_op->reason)? stop_op : start) == pcmk_rc_ok) {
1022  rc = pcmk_rc_ok;
1023  }
1024  }
1025 
1026  free(key);
1027 
1028  } else if ((stop != NULL)
1029  && pcmk_all_flags_set(rsc->flags, pe_rsc_failed|pe_rsc_stop)) {
1030  /* 'stop' may be NULL if the failure was ignored */
1031  rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
1032  next, stop, start);
1033  STOP_SANITY_ASSERT(__LINE__);
1034 
1035  } else if (moving) {
1036  rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
1037  stop, NULL);
1038  STOP_SANITY_ASSERT(__LINE__);
1039 
1040  } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
1041  rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
1042  start, NULL);
1043 
1044  } else if (stop != NULL && !pcmk_is_set(stop->flags, pe_action_optional)) {
1045  rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1046  next, start, NULL);
1047  STOP_SANITY_ASSERT(__LINE__);
1048 
1049  } else if (rsc->role == RSC_ROLE_PROMOTED) {
1050  CRM_LOG_ASSERT(current != NULL);
1051  rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1052  next, demote, NULL);
1053 
1054  } else if (rsc->next_role == RSC_ROLE_PROMOTED) {
1055  CRM_LOG_ASSERT(next);
1056  rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1057  next, promote, NULL);
1058 
1059  } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role > RSC_ROLE_STOPPED) {
1060  rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1061  start, NULL);
1062  }
1063 
1064  return rc;
1065 }
1066 
1067 PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1068 static int
1069 node_action(pcmk__output_t *out, va_list args)
1070 {
1071  char *task = va_arg(args, char *);
1072  char *node_name = va_arg(args, char *);
1073  char *reason = va_arg(args, char *);
1074 
1075  if (task == NULL) {
1076  return pcmk_rc_no_output;
1077  } else if (reason) {
1078  out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1079  } else {
1080  crm_notice(" * %s %s", task, node_name);
1081  }
1082 
1083  return pcmk_rc_ok;
1084 }
1085 
1086 PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1087 static int
1088 node_action_xml(pcmk__output_t *out, va_list args)
1089 {
1090  char *task = va_arg(args, char *);
1091  char *node_name = va_arg(args, char *);
1092  char *reason = va_arg(args, char *);
1093 
1094  if (task == NULL) {
1095  return pcmk_rc_no_output;
1096  } else if (reason) {
1097  pcmk__output_create_xml_node(out, "node_action",
1098  "task", task,
1099  "node", node_name,
1100  "reason", reason,
1101  NULL);
1102  } else {
1103  crm_notice(" * %s %s", task, node_name);
1104  }
1105 
1106  return pcmk_rc_ok;
1107 }
1108 
1109 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1110 static int
1111 inject_cluster_action(pcmk__output_t *out, va_list args)
1112 {
1113  const char *node = va_arg(args, const char *);
1114  const char *task = va_arg(args, const char *);
1115  xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1116 
1117  if (out->is_quiet(out)) {
1118  return pcmk_rc_no_output;
1119  }
1120 
1121  if(rsc) {
1122  out->list_item(out, NULL, "Cluster action: %s for %s on %s", task, ID(rsc), node);
1123  } else {
1124  out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1125  }
1126 
1127  return pcmk_rc_ok;
1128 }
1129 
1130 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1131 static int
1132 inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1133 {
1134  const char *node = va_arg(args, const char *);
1135  const char *task = va_arg(args, const char *);
1136  xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1137 
1138  xmlNodePtr xml_node = NULL;
1139 
1140  if (out->is_quiet(out)) {
1141  return pcmk_rc_no_output;
1142  }
1143 
1144  xml_node = pcmk__output_create_xml_node(out, "cluster_action",
1145  "task", task,
1146  "node", node,
1147  NULL);
1148 
1149  if (rsc) {
1150  crm_xml_add(xml_node, "id", ID(rsc));
1151  }
1152 
1153  return pcmk_rc_ok;
1154 }
1155 
1156 PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1157 static int
1158 inject_fencing_action(pcmk__output_t *out, va_list args)
1159 {
1160  char *target = va_arg(args, char *);
1161  const char *op = va_arg(args, const char *);
1162 
1163  if (out->is_quiet(out)) {
1164  return pcmk_rc_no_output;
1165  }
1166 
1167  out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1168  return pcmk_rc_ok;
1169 }
1170 
1171 PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1172 static int
1173 inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1174 {
1175  char *target = va_arg(args, char *);
1176  const char *op = va_arg(args, const char *);
1177 
1178  if (out->is_quiet(out)) {
1179  return pcmk_rc_no_output;
1180  }
1181 
1182  pcmk__output_create_xml_node(out, "fencing_action",
1183  "target", target,
1184  "op", op,
1185  NULL);
1186  return pcmk_rc_ok;
1187 }
1188 
1189 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1190 static int
1191 inject_attr(pcmk__output_t *out, va_list args)
1192 {
1193  const char *name = va_arg(args, const char *);
1194  const char *value = va_arg(args, const char *);
1195  xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1196 
1197  xmlChar *node_path = NULL;
1198 
1199  if (out->is_quiet(out)) {
1200  return pcmk_rc_no_output;
1201  }
1202 
1203  node_path = xmlGetNodePath(cib_node);
1204 
1205  out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1206  name, value, node_path, ID(cib_node));
1207 
1208  free(node_path);
1209  return pcmk_rc_ok;
1210 }
1211 
1212 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1213 static int
1214 inject_attr_xml(pcmk__output_t *out, va_list args)
1215 {
1216  const char *name = va_arg(args, const char *);
1217  const char *value = va_arg(args, const char *);
1218  xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1219 
1220  xmlChar *node_path = NULL;
1221 
1222  if (out->is_quiet(out)) {
1223  return pcmk_rc_no_output;
1224  }
1225 
1226  node_path = xmlGetNodePath(cib_node);
1227 
1228  pcmk__output_create_xml_node(out, "inject_attr",
1229  "name", name,
1230  "value", value,
1231  "node_path", node_path,
1232  "cib_node", ID(cib_node),
1233  NULL);
1234  free(node_path);
1235  return pcmk_rc_ok;
1236 }
1237 
1238 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1239 static int
1240 inject_spec(pcmk__output_t *out, va_list args)
1241 {
1242  const char *spec = va_arg(args, const char *);
1243 
1244  if (out->is_quiet(out)) {
1245  return pcmk_rc_no_output;
1246  }
1247 
1248  out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1249  return pcmk_rc_ok;
1250 }
1251 
1252 PCMK__OUTPUT_ARGS("inject-spec", "const char *")
1253 static int
1254 inject_spec_xml(pcmk__output_t *out, va_list args)
1255 {
1256  const char *spec = va_arg(args, const char *);
1257 
1258  if (out->is_quiet(out)) {
1259  return pcmk_rc_no_output;
1260  }
1261 
1262  pcmk__output_create_xml_node(out, "inject_spec",
1263  "spec", spec,
1264  NULL);
1265  return pcmk_rc_ok;
1266 }
1267 
1268 PCMK__OUTPUT_ARGS("inject-modify-config", "char *", "char *")
1269 static int
1270 inject_modify_config(pcmk__output_t *out, va_list args)
1271 {
1272  char *quorum = va_arg(args, char *);
1273  char *watchdog = va_arg(args, char *);
1274 
1275  if (out->is_quiet(out)) {
1276  return pcmk_rc_no_output;
1277  }
1278 
1279  out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1280 
1281  if (quorum) {
1282  out->list_item(out, NULL, "Setting quorum: %s", quorum);
1283  }
1284 
1285  if (watchdog) {
1286  out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1287  }
1288 
1289  return pcmk_rc_ok;
1290 }
1291 
1292 PCMK__OUTPUT_ARGS("inject-modify-config", "char *", "char *")
1293 static int
1294 inject_modify_config_xml(pcmk__output_t *out, va_list args)
1295 {
1296  char *quorum = va_arg(args, char *);
1297  char *watchdog = va_arg(args, char *);
1298 
1299  xmlNodePtr node = NULL;
1300 
1301  if (out->is_quiet(out)) {
1302  return pcmk_rc_no_output;
1303  }
1304 
1305  node = pcmk__output_xml_create_parent(out, "modifications", NULL);
1306 
1307  if (quorum) {
1308  crm_xml_add(node, "quorum", quorum);
1309  }
1310 
1311  if (watchdog) {
1312  crm_xml_add(node, "watchdog", watchdog);
1313  }
1314 
1315  return pcmk_rc_ok;
1316 }
1317 
1318 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1319 static int
1320 inject_modify_node(pcmk__output_t *out, va_list args)
1321 {
1322  const char *action = va_arg(args, const char *);
1323  char *node = va_arg(args, char *);
1324 
1325  if (out->is_quiet(out)) {
1326  return pcmk_rc_no_output;
1327  }
1328 
1329  if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1330  out->list_item(out, NULL, "Bringing node %s online", node);
1331  return pcmk_rc_ok;
1332  } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1333  out->list_item(out, NULL, "Taking node %s offline", node);
1334  return pcmk_rc_ok;
1335  } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1336  out->list_item(out, NULL, "Failing node %s", node);
1337  return pcmk_rc_ok;
1338  }
1339 
1340  return pcmk_rc_no_output;
1341 }
1342 
1343 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1344 static int
1345 inject_modify_node_xml(pcmk__output_t *out, va_list args)
1346 {
1347  const char *action = va_arg(args, const char *);
1348  char *node = va_arg(args, char *);
1349 
1350  if (out->is_quiet(out)) {
1351  return pcmk_rc_no_output;
1352  }
1353 
1354  pcmk__output_create_xml_node(out, "modify_node",
1355  "action", action,
1356  "node", node,
1357  NULL);
1358  return pcmk_rc_ok;
1359 }
1360 
1361 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1362 static int
1363 inject_modify_ticket(pcmk__output_t *out, va_list args)
1364 {
1365  const char *action = va_arg(args, const char *);
1366  char *ticket = va_arg(args, char *);
1367 
1368  if (out->is_quiet(out)) {
1369  return pcmk_rc_no_output;
1370  }
1371 
1372  if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1373  out->list_item(out, NULL, "Making ticket %s standby", ticket);
1374  } else {
1375  out->list_item(out, NULL, "%s ticket %s", action, ticket);
1376  }
1377 
1378  return pcmk_rc_ok;
1379 }
1380 
1381 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1382 static int
1383 inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1384 {
1385  const char *action = va_arg(args, const char *);
1386  char *ticket = va_arg(args, char *);
1387 
1388  if (out->is_quiet(out)) {
1389  return pcmk_rc_no_output;
1390  }
1391 
1392  pcmk__output_create_xml_node(out, "modify_ticket",
1393  "action", action,
1394  "ticket", ticket,
1395  NULL);
1396  return pcmk_rc_ok;
1397 }
1398 
1399 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1400 static int
1401 inject_pseudo_action(pcmk__output_t *out, va_list args)
1402 {
1403  const char *node = va_arg(args, const char *);
1404  const char *task = va_arg(args, const char *);
1405 
1406  if (out->is_quiet(out)) {
1407  return pcmk_rc_no_output;
1408  }
1409 
1410  out->list_item(out, NULL, "Pseudo action: %s%s%s", task, node ? " on " : "",
1411  node ? node : "");
1412  return pcmk_rc_ok;
1413 }
1414 
1415 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1416 static int
1417 inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1418 {
1419  const char *node = va_arg(args, const char *);
1420  const char *task = va_arg(args, const char *);
1421 
1422  xmlNodePtr xml_node = NULL;
1423 
1424  if (out->is_quiet(out)) {
1425  return pcmk_rc_no_output;
1426  }
1427 
1428  xml_node = pcmk__output_create_xml_node(out, "pseudo_action",
1429  "task", task,
1430  NULL);
1431  if (node) {
1432  crm_xml_add(xml_node, "node", node);
1433  }
1434 
1435  return pcmk_rc_ok;
1436 }
1437 
1438 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1439 static int
1440 inject_rsc_action(pcmk__output_t *out, va_list args)
1441 {
1442  const char *rsc = va_arg(args, const char *);
1443  const char *operation = va_arg(args, const char *);
1444  char *node = va_arg(args, char *);
1445  guint interval_ms = va_arg(args, guint);
1446 
1447  if (out->is_quiet(out)) {
1448  return pcmk_rc_no_output;
1449  }
1450 
1451  if (interval_ms) {
1452  out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1453  rsc, operation, interval_ms, node);
1454  } else {
1455  out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1456  rsc, operation, node);
1457  }
1458 
1459  return pcmk_rc_ok;
1460 }
1461 
1462 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1463 static int
1464 inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1465 {
1466  const char *rsc = va_arg(args, const char *);
1467  const char *operation = va_arg(args, const char *);
1468  char *node = va_arg(args, char *);
1469  guint interval_ms = va_arg(args, guint);
1470 
1471  xmlNodePtr xml_node = NULL;
1472 
1473  if (out->is_quiet(out)) {
1474  return pcmk_rc_no_output;
1475  }
1476 
1477  xml_node = pcmk__output_create_xml_node(out, "rsc_action",
1478  "resource", rsc,
1479  "op", operation,
1480  "node", node,
1481  NULL);
1482 
1483  if (interval_ms) {
1484  char *interval_s = pcmk__itoa(interval_ms);
1485 
1486  crm_xml_add(xml_node, "interval", interval_s);
1487  free(interval_s);
1488  }
1489 
1490  return pcmk_rc_ok;
1491 }
1492 
1493 #define CHECK_RC(retcode, retval) \
1494  if (retval == pcmk_rc_ok) { \
1495  retcode = pcmk_rc_ok; \
1496  }
1497 
1498 PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *", "crm_exit_t", "stonith_history_t *",
1499  "gboolean", "uint32_t", "uint32_t", "const char *", "GList *", "GList *")
1500 int
1501 pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
1502 {
1503  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1504  crm_exit_t history_rc = va_arg(args, crm_exit_t);
1505  stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1506  gboolean fence_history = va_arg(args, gboolean);
1507  uint32_t section_opts = va_arg(args, uint32_t);
1508  uint32_t show_opts = va_arg(args, uint32_t);
1509  const char *prefix = va_arg(args, const char *);
1510  GList *unames = va_arg(args, GList *);
1511  GList *resources = va_arg(args, GList *);
1512 
1513  int rc = pcmk_rc_no_output;
1514  bool already_printed_failure = false;
1515 
1516  CHECK_RC(rc, out->message(out, "cluster-summary", data_set,
1517  section_opts, show_opts));
1518 
1519  if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1520  CHECK_RC(rc, out->message(out, "node-list", data_set->nodes, unames,
1521  resources, show_opts, rc == pcmk_rc_ok));
1522  }
1523 
1524  /* Print resources section, if needed */
1525  if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1526  CHECK_RC(rc, out->message(out, "resource-list", data_set, show_opts,
1527  TRUE, unames, resources, rc == pcmk_rc_ok));
1528  }
1529 
1530  /* print Node Attributes section if requested */
1531  if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1532  CHECK_RC(rc, out->message(out, "node-attribute-list", data_set,
1533  show_opts, rc == pcmk_rc_ok, unames, resources));
1534  }
1535 
1536  /* If requested, print resource operations (which includes failcounts)
1537  * or just failcounts
1538  */
1539  if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1540  CHECK_RC(rc, out->message(out, "node-summary", data_set, unames,
1541  resources, section_opts, show_opts, rc == pcmk_rc_ok));
1542  }
1543 
1544  /* If there were any failed actions, print them */
1545  if (pcmk_is_set(section_opts, pcmk_section_failures)
1547 
1548  CHECK_RC(rc, out->message(out, "failed-action-list", data_set, unames,
1549  resources, show_opts, rc == pcmk_rc_ok));
1550  }
1551 
1552  /* Print failed stonith actions */
1553  if (pcmk_is_set(section_opts, pcmk_section_fence_failed) && fence_history) {
1554  if (history_rc == 0) {
1556  GINT_TO_POINTER(st_failed));
1557 
1558  if (hp) {
1559  CHECK_RC(rc, out->message(out, "failed-fencing-list", stonith_history, unames,
1560  section_opts, rc == pcmk_rc_ok));
1561  }
1562  } else {
1563  PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1564  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1565  out->list_item(out, NULL, "Failed to get fencing history: %s",
1566  crm_exit_str(history_rc));
1567  out->end_list(out);
1568 
1569  already_printed_failure = true;
1570  }
1571  }
1572 
1573  /* Print tickets if requested */
1574  if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1575  CHECK_RC(rc, out->message(out, "ticket-list", data_set, rc == pcmk_rc_ok));
1576  }
1577 
1578  /* Print negative location constraints if requested */
1579  if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1580  CHECK_RC(rc, out->message(out, "ban-list", data_set, prefix, resources,
1581  show_opts, rc == pcmk_rc_ok));
1582  }
1583 
1584  /* Print stonith history */
1585  if (fence_history && pcmk_any_flags_set(section_opts, pcmk_section_fencing_all)) {
1586  if (history_rc != 0) {
1587  if (!already_printed_failure) {
1588  PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
1589  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1590  out->list_item(out, NULL, "Failed to get fencing history: %s",
1591  crm_exit_str(history_rc));
1592  out->end_list(out);
1593  }
1594  } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1596  GINT_TO_POINTER(st_failed));
1597 
1598  if (hp) {
1599  CHECK_RC(rc, out->message(out, "fencing-list", hp, unames,
1600  section_opts, rc == pcmk_rc_ok));
1601  }
1602  } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1604 
1605  if (hp) {
1606  CHECK_RC(rc, out->message(out, "pending-fencing-list", hp, unames,
1607  section_opts, rc == pcmk_rc_ok));
1608  }
1609  }
1610  }
1611 
1612  return rc;
1613 }
1614 
1615 PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *", "crm_exit_t", "stonith_history_t *",
1616  "gboolean", "uint32_t", "uint32_t", "const char *", "GList *", "GList *")
1617 static int
1618 cluster_status_xml(pcmk__output_t *out, va_list args)
1619 {
1620  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1621  crm_exit_t history_rc = va_arg(args, crm_exit_t);
1622  stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1623  gboolean fence_history = va_arg(args, gboolean);
1624  uint32_t section_opts = va_arg(args, uint32_t);
1625  uint32_t show_opts = va_arg(args, uint32_t);
1626  const char *prefix = va_arg(args, const char *);
1627  GList *unames = va_arg(args, GList *);
1628  GList *resources = va_arg(args, GList *);
1629 
1630  out->message(out, "cluster-summary", data_set, section_opts, show_opts);
1631 
1632  /*** NODES ***/
1633  if (pcmk_is_set(section_opts, pcmk_section_nodes)) {
1634  out->message(out, "node-list", data_set->nodes, unames, resources,
1635  show_opts, FALSE);
1636  }
1637 
1638  /* Print resources section, if needed */
1639  if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1640  /* XML output always displays full details. */
1641  uint32_t full_show_opts = show_opts & ~pcmk_show_brief;
1642 
1643  out->message(out, "resource-list", data_set, full_show_opts,
1644  FALSE, unames, resources, FALSE);
1645  }
1646 
1647  /* print Node Attributes section if requested */
1648  if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1649  out->message(out, "node-attribute-list", data_set, show_opts, FALSE,
1650  unames, resources);
1651  }
1652 
1653  /* If requested, print resource operations (which includes failcounts)
1654  * or just failcounts
1655  */
1656  if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1657  out->message(out, "node-summary", data_set, unames,
1658  resources, section_opts, show_opts, FALSE);
1659  }
1660 
1661  /* If there were any failed actions, print them */
1662  if (pcmk_is_set(section_opts, pcmk_section_failures)
1664 
1665  out->message(out, "failed-action-list", data_set, unames, resources,
1666  show_opts, FALSE);
1667  }
1668 
1669  /* Print stonith history */
1670  if (pcmk_is_set(section_opts, pcmk_section_fencing_all) && fence_history) {
1671  out->message(out, "full-fencing-list", history_rc, stonith_history,
1672  unames, section_opts, FALSE);
1673  }
1674 
1675  /* Print tickets if requested */
1676  if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1677  out->message(out, "ticket-list", data_set, FALSE);
1678  }
1679 
1680  /* Print negative location constraints if requested */
1681  if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1682  out->message(out, "ban-list", data_set, prefix, resources, show_opts,
1683  FALSE);
1684  }
1685 
1686  return pcmk_rc_ok;
1687 }
1688 
1689 PCMK__OUTPUT_ARGS("cluster-status", "pe_working_set_t *", "crm_exit_t", "stonith_history_t *",
1690  "gboolean", "uint32_t", "uint32_t", "const char *", "GList *",
1691  "GList *")
1692 static int
1693 cluster_status_html(pcmk__output_t *out, va_list args)
1694 {
1695  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1696  crm_exit_t history_rc = va_arg(args, crm_exit_t);
1697  stonith_history_t *stonith_history = va_arg(args, stonith_history_t *);
1698  gboolean fence_history = va_arg(args, gboolean);
1699  uint32_t section_opts = va_arg(args, uint32_t);
1700  uint32_t show_opts = va_arg(args, uint32_t);
1701  const char *prefix = va_arg(args, const char *);
1702  GList *unames = va_arg(args, GList *);
1703  GList *resources = va_arg(args, GList *);
1704  bool already_printed_failure = false;
1705 
1706  out->message(out, "cluster-summary", data_set, section_opts, show_opts);
1707 
1708  /*** NODE LIST ***/
1709  if (pcmk_is_set(section_opts, pcmk_section_nodes) && unames) {
1710  out->message(out, "node-list", data_set->nodes, unames, resources,
1711  show_opts, FALSE);
1712  }
1713 
1714  /* Print resources section, if needed */
1715  if (pcmk_is_set(section_opts, pcmk_section_resources)) {
1716  out->message(out, "resource-list", data_set, show_opts, TRUE, unames,
1717  resources, FALSE);
1718  }
1719 
1720  /* print Node Attributes section if requested */
1721  if (pcmk_is_set(section_opts, pcmk_section_attributes)) {
1722  out->message(out, "node-attribute-list", data_set, show_opts, FALSE,
1723  unames, resources);
1724  }
1725 
1726  /* If requested, print resource operations (which includes failcounts)
1727  * or just failcounts
1728  */
1729  if (pcmk_any_flags_set(section_opts, pcmk_section_operations | pcmk_section_failcounts)) {
1730  out->message(out, "node-summary", data_set, unames,
1731  resources, section_opts, show_opts, FALSE);
1732  }
1733 
1734  /* If there were any failed actions, print them */
1735  if (pcmk_is_set(section_opts, pcmk_section_failures)
1737 
1738  out->message(out, "failed-action-list", data_set, unames, resources,
1739  show_opts, FALSE);
1740  }
1741 
1742  /* Print failed stonith actions */
1743  if (pcmk_is_set(section_opts, pcmk_section_fence_failed) && fence_history) {
1744  if (history_rc == 0) {
1746  GINT_TO_POINTER(st_failed));
1747 
1748  if (hp) {
1749  out->message(out, "failed-fencing-list", stonith_history, unames,
1750  section_opts, FALSE);
1751  }
1752  } else {
1753  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1754  out->list_item(out, NULL, "Failed to get fencing history: %s",
1755  crm_exit_str(history_rc));
1756  out->end_list(out);
1757  }
1758  }
1759 
1760  /* Print stonith history */
1761  if (fence_history && pcmk_any_flags_set(section_opts, pcmk_section_fencing_all)) {
1762  if (history_rc != 0) {
1763  if (!already_printed_failure) {
1764  out->begin_list(out, NULL, NULL, "Failed Fencing Actions");
1765  out->list_item(out, NULL, "Failed to get fencing history: %s",
1766  crm_exit_str(history_rc));
1767  out->end_list(out);
1768  }
1769  } else if (pcmk_is_set(section_opts, pcmk_section_fence_worked)) {
1771  GINT_TO_POINTER(st_failed));
1772 
1773  if (hp) {
1774  out->message(out, "fencing-list", hp, unames, section_opts, FALSE);
1775  }
1776  } else if (pcmk_is_set(section_opts, pcmk_section_fence_pending)) {
1778 
1779  if (hp) {
1780  out->message(out, "pending-fencing-list", hp, unames,
1781  section_opts, FALSE);
1782  }
1783  }
1784  }
1785 
1786  /* Print tickets if requested */
1787  if (pcmk_is_set(section_opts, pcmk_section_tickets)) {
1788  out->message(out, "ticket-list", data_set, FALSE);
1789  }
1790 
1791  /* Print negative location constraints if requested */
1792  if (pcmk_is_set(section_opts, pcmk_section_bans)) {
1793  out->message(out, "ban-list", data_set, prefix, resources, show_opts,
1794  FALSE);
1795  }
1796 
1797  return pcmk_rc_ok;
1798 }
1799 
1800 PCMK__OUTPUT_ARGS("attribute", "char *", "char *", "char *", "char *")
1801 static int
1802 attribute_default(pcmk__output_t *out, va_list args)
1803 {
1804  char *scope = va_arg(args, char *);
1805  char *instance = va_arg(args, char *);
1806  char *name = va_arg(args, char *);
1807  char *value = va_arg(args, char *);
1808  char *host = va_arg(args, char *);
1809 
1810  GString *s = g_string_sized_new(50);
1811 
1812  if (!pcmk__str_empty(scope)) {
1813  g_string_append_printf(s, "scope=\"%s\" ", scope);
1814  }
1815 
1816  if (!pcmk__str_empty(instance)) {
1817  g_string_append_printf(s, "id=\"%s\" ", instance);
1818  }
1819 
1820  g_string_append_printf(s, "name=\"%s\" ", name);
1821 
1822  if (!pcmk__str_empty(host)) {
1823  g_string_append_printf(s, "host=\"%s\" ", host);
1824  }
1825 
1826  g_string_append_printf(s, "value=\"%s\"", value ? value : "");
1827 
1828  out->info(out, "%s", s->str);
1829  g_string_free(s, TRUE);
1830 
1831  return pcmk_rc_ok;
1832 }
1833 
1834 PCMK__OUTPUT_ARGS("attribute", "char *", "char *", "char *", "char *")
1835 static int
1836 attribute_xml(pcmk__output_t *out, va_list args)
1837 {
1838  char *scope = va_arg(args, char *);
1839  char *instance = va_arg(args, char *);
1840  char *name = va_arg(args, char *);
1841  char *value = va_arg(args, char *);
1842  char *host = va_arg(args, char *);
1843 
1844  xmlNodePtr node = NULL;
1845 
1846  node = pcmk__output_create_xml_node(out, "attribute",
1847  "name", name,
1848  "value", value ? value : "",
1849  NULL);
1850 
1851  if (!pcmk__str_empty(scope)) {
1852  crm_xml_add(node, "scope", scope);
1853  }
1854 
1855  if (!pcmk__str_empty(instance)) {
1856  crm_xml_add(node, "id", instance);
1857  }
1858 
1859  if (!pcmk__str_empty(host)) {
1860  crm_xml_add(node, "host", host);
1861  }
1862 
1863  return pcmk_rc_ok;
1864 }
1865 
1866 static pcmk__message_entry_t fmt_functions[] = {
1867  { "attribute", "default", attribute_default },
1868  { "attribute", "xml", attribute_xml },
1869  { "cluster-status", "default", pcmk__cluster_status_text },
1870  { "cluster-status", "html", cluster_status_html },
1871  { "cluster-status", "xml", cluster_status_xml },
1872  { "crmadmin-node", "default", crmadmin_node_text },
1873  { "crmadmin-node", "xml", crmadmin_node_xml },
1874  { "dc", "default", dc_text },
1875  { "dc", "xml", dc_xml },
1876  { "digests", "default", digests_text },
1877  { "digests", "xml", digests_xml },
1878  { "health", "default", health_text },
1879  { "health", "xml", health_xml },
1880  { "inject-attr", "default", inject_attr },
1881  { "inject-attr", "xml", inject_attr_xml },
1882  { "inject-cluster-action", "default", inject_cluster_action },
1883  { "inject-cluster-action", "xml", inject_cluster_action_xml },
1884  { "inject-fencing-action", "default", inject_fencing_action },
1885  { "inject-fencing-action", "xml", inject_fencing_action_xml },
1886  { "inject-modify-config", "default", inject_modify_config },
1887  { "inject-modify-config", "xml", inject_modify_config_xml },
1888  { "inject-modify-node", "default", inject_modify_node },
1889  { "inject-modify-node", "xml", inject_modify_node_xml },
1890  { "inject-modify-ticket", "default", inject_modify_ticket },
1891  { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
1892  { "inject-pseudo-action", "default", inject_pseudo_action },
1893  { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
1894  { "inject-rsc-action", "default", inject_rsc_action },
1895  { "inject-rsc-action", "xml", inject_rsc_action_xml },
1896  { "inject-spec", "default", inject_spec },
1897  { "inject-spec", "xml", inject_spec_xml },
1898  { "locations-list", "default", locations_list },
1899  { "locations-list", "xml", locations_list_xml },
1900  { "node-action", "default", node_action },
1901  { "node-action", "xml", node_action_xml },
1902  { "pacemakerd-health", "default", pacemakerd_health_text },
1903  { "pacemakerd-health", "xml", pacemakerd_health_xml },
1904  { "profile", "default", profile_default, },
1905  { "profile", "xml", profile_xml },
1906  { "rsc-action", "default", rsc_action_default },
1907  { "rsc-action-item", "default", rsc_action_item },
1908  { "rsc-action-item", "xml", rsc_action_item_xml },
1909  { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
1910  { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
1911  { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
1912  { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
1913  { "stacks-constraints", "default", stacks_and_constraints },
1914  { "stacks-constraints", "xml", stacks_and_constraints_xml },
1915 
1916  { NULL, NULL, NULL }
1917 };
1918 
1919 void
1921  pcmk__register_messages(out, fmt_functions);
1922 }
pcmk__cpg_host_t host
Definition: cpg.c:49
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define RSC_STOP
Definition: crm.h:204
#define crm_notice(fmt, args...)
Definition: logging.h:360
xmlNode * failed
Definition: pe_types.h:172
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:2288
GList * rsc_cons
Definition: pe_types.h:371
Control output from tools.
const char * name
Definition: cib.c:24
enum rsc_role_e role
Definition: pe_types.h:384
GList * find_actions(GList *input, const char *key, const pe_node_t *on_node)
Definition: utils.c:1571
#define pe_rsc_stop
Definition: pe_types.h:271
enum rsc_role_e next_role
Definition: pe_types.h:385
xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition: output_xml.c:433
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:323
#define CHECK_RC(retcode, retval)
Definition: pcmk_output.c:1493
pe_resource_t * dependent
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition: nvpair.c:954
#define XML_CONS_TAG_RSC_DEPEND
Definition: msg_xml.h:351
enum crm_exit_e crm_exit_t
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:210
xmlNode * params_restart
Definition: internal.h:483
GList * rsc_cons_lhs
Definition: pe_types.h:370
enum crm_ais_msg_types type
Definition: cpg.c:48
#define RSC_START
Definition: crm.h:201
#define pe_rsc_stop_unexpected
Definition: pe_types.h:286
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:1920
char * reason
Definition: pe_types.h:431
const char * action
Definition: pcmk_fence.c:29
bool stonith__event_state_pending(stonith_history_t *history, void *user_data)
Definition: st_client.c:2302
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:49
void void void pcmk__formatted_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
GList * nodes
Definition: pe_types.h:164
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
const char * role2text(enum rsc_role_e role)
Definition: common.c:454
int weight
Definition: pe_types.h:249
const char * crm_exit_str(crm_exit_t exit_code)
Definition: results.c:506
#define pe_rsc_failed
Definition: pe_types.h:276
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:913
char * digest_all_calc
Definition: internal.h:484
pe_resource_t * primary
#define stop_key(rsc)
Definition: internal.h:378
#define XML_CONS_TAG_RSC_LOCATION
Definition: msg_xml.h:353
char * digest_secure_calc
Definition: internal.h:485
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:122
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:674
struct pe_node_shared_s * details
Definition: pe_types.h:252
unsigned long long flags
Definition: pe_types.h:362
const char * uname
Definition: pe_types.h:216
pe_working_set_t * data_set
void pcmk__unpack_constraints(pe_working_set_t *data_set)
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition: output_xml.c:466
GList * actions
Definition: pe_types.h:373
#define pcmk_section_fencing_all
Definition: output.h:46
int pcmk__cluster_status_text(pcmk__output_t *out, va_list args)
#define pe_rsc_allocating
Definition: pe_types.h:267
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:2028
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:512
Function and executable result codes.
xmlNode * params_all
Definition: internal.h:481
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition: xml.c:2974
const xmlChar * pcmkXmlStr
Definition: xml.h:52
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
const char * target
Definition: pcmk_fence.c:28
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
pcmk__action_result_t result
Definition: pcmk_fence.c:34
#define STOP_SANITY_ASSERT(lineno)
Definition: pcmk_output.c:862
#define CRM_ASSERT(expr)
Definition: results.h:42
#define pe_rsc_reload
Definition: pe_types.h:272
#define RSC_PROMOTE
Definition: crm.h:207
Fencing aka. STONITH.
This structure contains everything that makes up a single output formatter.
xmlNode * params_secure
Definition: internal.h:482
void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
Definition: utils.c:2030
GList * rsc_location
Definition: pe_types.h:372
#define crm_str(x)
Definition: logging.h:384
GList * running_on
Definition: pe_types.h:380
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:145
enum pe_action_flags flags
Definition: pe_types.h:433
const char * node_attribute
#define ID(x)
Definition: msg_xml.h:460
const char * parent
Definition: cib.c:25
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
Definition: utils.c:1644
bool stonith__event_state_eq(stonith_history_t *history, void *user_data)
Definition: st_client.c:2308
PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *", "pe_node_t *", "pe_node_t *", "pe_action_t *", "pe_action_t *")
Definition: pcmk_output.c:110
char * digest_restart_calc
Definition: internal.h:486
#define pe_rsc_managed
Definition: pe_types.h:257
bool stonith__event_state_neq(stonith_history_t *history, void *user_data)
Definition: st_client.c:2314
#define RSC_DEMOTE
Definition: crm.h:209
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:20
char * score2char(int score)
Return the string equivalent of an integer score.
Definition: scores.c:114
char * id
Definition: pe_types.h:336
#define RSC_MIGRATED
Definition: crm.h:199