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