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