pacemaker  2.1.0-7c3f660
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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/results.h>
12 #include <crm/msg_xml.h>
13 #include <crm/stonith-ng.h>
14 #include <crm/fencing/internal.h>
15 #include <crm/pengine/internal.h>
16 #include <libxml/tree.h>
17 #include <pacemaker-internal.h>
18 
19 static char *
20 colocations_header(pe_resource_t *rsc, pcmk__colocation_t *cons,
21  gboolean dependents) {
22  char *score = NULL;
23  char *retval = NULL;
24 
25  score = score2char(cons->score);
26  if (cons->role_rh > RSC_ROLE_STARTED) {
27  retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
28  rsc->id, score, dependents ? "needs" : "with",
29  role2text(cons->role_rh), cons->id);
30  } else {
31  retval = crm_strdup_printf("%s (score=%s, id=%s)",
32  rsc->id, score, cons->id);
33  }
34 
35  free(score);
36  return retval;
37 }
38 
39 static void
40 colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
41  pcmk__colocation_t *cons) {
42  char *score = NULL;
43  xmlNodePtr node = NULL;
44 
45  score = score2char(cons->score);
47  "id", cons->id,
48  "rsc", cons->rsc_lh->id,
49  "with-rsc", cons->rsc_rh->id,
50  "score", score,
51  NULL);
52 
53  if (cons->node_attribute) {
54  xmlSetProp(node, (pcmkXmlStr) "node-attribute", (pcmkXmlStr) cons->node_attribute);
55  }
56 
57  if (cons->role_lh != RSC_ROLE_UNKNOWN) {
58  xmlSetProp(node, (pcmkXmlStr) "rsc-role", (pcmkXmlStr) role2text(cons->role_lh));
59  }
60 
61  if (cons->role_rh != RSC_ROLE_UNKNOWN) {
62  xmlSetProp(node, (pcmkXmlStr) "with-rsc-role", (pcmkXmlStr) role2text(cons->role_rh));
63  }
64 
65  free(score);
66 }
67 
68 static int
69 do_locations_list_xml(pcmk__output_t *out, pe_resource_t *rsc, bool add_header)
70 {
71  GList *lpc = NULL;
72  GList *list = rsc->rsc_location;
73  int rc = pcmk_rc_no_output;
74 
75  for (lpc = list; lpc != NULL; lpc = lpc->next) {
76  pe__location_t *cons = lpc->data;
77 
78  GList *lpc2 = NULL;
79 
80  for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
81  pe_node_t *node = (pe_node_t *) lpc2->data;
82  char *score = score2char(node->weight);
83 
84  if (add_header) {
85  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
86  }
87 
89  "node", node->details->uname,
90  "rsc", rsc->id,
91  "id", cons->id,
92  "score", score,
93  NULL);
94  free(score);
95  }
96  }
97 
98  if (add_header) {
99  PCMK__OUTPUT_LIST_FOOTER(out, rc);
100  }
101 
102  return rc;
103 }
104 
105 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
106  "pe_node_t *", "pe_node_t *", "pe_action_t *",
107  "pe_action_t *")
108 static int
109 rsc_action_item(pcmk__output_t *out, va_list args)
110 {
111  const char *change = va_arg(args, const char *);
112  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
113  pe_node_t *origin = va_arg(args, pe_node_t *);
114  pe_node_t *destination = va_arg(args, pe_node_t *);
115  pe_action_t *action = va_arg(args, pe_action_t *);
116  pe_action_t *source = va_arg(args, pe_action_t *);
117 
118  int len = 0;
119  char *reason = NULL;
120  char *details = NULL;
121  bool same_host = FALSE;
122  bool same_role = FALSE;
123  bool need_role = FALSE;
124 
125  static int rsc_width = 5;
126  static int detail_width = 5;
127 
128  CRM_ASSERT(action);
129  CRM_ASSERT(destination != NULL || origin != NULL);
130 
131  if(source == NULL) {
132  source = action;
133  }
134 
135  len = strlen(rsc->id);
136  if(len > rsc_width) {
137  rsc_width = len + 2;
138  }
139 
140  if ((rsc->role > RSC_ROLE_STARTED)
141  || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
142  need_role = TRUE;
143  }
144 
145  if(origin != NULL && destination != NULL && origin->details == destination->details) {
146  same_host = TRUE;
147  }
148 
149  if(rsc->role == rsc->next_role) {
150  same_role = TRUE;
151  }
152 
153  if (need_role && (origin == NULL)) {
154  /* Starting and promoting a promotable clone instance */
155  details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), destination->details->uname);
156 
157  } else if (origin == NULL) {
158  /* Starting a resource */
159  details = crm_strdup_printf("%s", destination->details->uname);
160 
161  } else if (need_role && (destination == NULL)) {
162  /* Stopping a promotable clone instance */
163  details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
164 
165  } else if (destination == NULL) {
166  /* Stopping a resource */
167  details = crm_strdup_printf("%s", origin->details->uname);
168 
169  } else if (need_role && same_role && same_host) {
170  /* Recovering, restarting or re-promoting a promotable clone instance */
171  details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
172 
173  } else if (same_role && same_host) {
174  /* Recovering or Restarting a normal resource */
175  details = crm_strdup_printf("%s", origin->details->uname);
176 
177  } else if (need_role && same_role) {
178  /* Moving a promotable clone instance */
179  details = crm_strdup_printf("%s -> %s %s", origin->details->uname, destination->details->uname, role2text(rsc->role));
180 
181  } else if (same_role) {
182  /* Moving a normal resource */
183  details = crm_strdup_printf("%s -> %s", origin->details->uname, destination->details->uname);
184 
185  } else if (same_host) {
186  /* Promoting or demoting a promotable clone instance */
187  details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), origin->details->uname);
188 
189  } else {
190  /* Moving and promoting/demoting */
191  details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role), origin->details->uname, role2text(rsc->next_role), destination->details->uname);
192  }
193 
194  len = strlen(details);
195  if(len > detail_width) {
196  detail_width = len;
197  }
198 
199  if(source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
200  reason = crm_strdup_printf("due to %s (blocked)", source->reason);
201 
202  } else if(source->reason) {
203  reason = crm_strdup_printf("due to %s", source->reason);
204 
205  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
206  reason = strdup("blocked");
207 
208  }
209 
210  out->list_item(out, NULL, "%-8s %-*s ( %*s )%s%s", change, rsc_width,
211  rsc->id, detail_width, details, reason ? " " : "", reason ? reason : "");
212 
213  free(details);
214  free(reason);
215  return pcmk_rc_ok;
216 }
217 
218 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
219  "pe_node_t *", "pe_node_t *", "pe_action_t *",
220  "pe_action_t *")
221 static int
222 rsc_action_item_xml(pcmk__output_t *out, va_list args)
223 {
224  const char *change = va_arg(args, const char *);
225  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
226  pe_node_t *origin = va_arg(args, pe_node_t *);
227  pe_node_t *destination = va_arg(args, pe_node_t *);
228  pe_action_t *action = va_arg(args, pe_action_t *);
229  pe_action_t *source = va_arg(args, pe_action_t *);
230 
231  char *change_str = NULL;
232 
233  bool same_host = FALSE;
234  bool same_role = FALSE;
235  bool need_role = FALSE;
236  xmlNode *xml = NULL;
237 
238  CRM_ASSERT(action);
239  CRM_ASSERT(destination != NULL || origin != NULL);
240 
241  if (source == NULL) {
242  source = action;
243  }
244 
245  if ((rsc->role > RSC_ROLE_STARTED)
246  || (rsc->next_role > RSC_ROLE_UNPROMOTED)) {
247  need_role = TRUE;
248  }
249 
250  if(origin != NULL && destination != NULL && origin->details == destination->details) {
251  same_host = TRUE;
252  }
253 
254  if(rsc->role == rsc->next_role) {
255  same_role = TRUE;
256  }
257 
258  change_str = g_ascii_strdown(change, -1);
259  xml = pcmk__output_create_xml_node(out, "rsc_action",
260  "action", change_str,
261  "resource", rsc->id,
262  NULL);
263  g_free(change_str);
264 
265  if (need_role && (origin == NULL)) {
266  /* Starting and promoting a promotable clone instance */
267  pcmk__xe_set_props(xml,
268  "role", role2text(rsc->role),
269  "next-role", role2text(rsc->next_role),
270  "dest", destination->details->uname,
271  NULL);
272 
273  } else if (origin == NULL) {
274  /* Starting a resource */
275  crm_xml_add(xml, "node", destination->details->uname);
276 
277  } else if (need_role && (destination == NULL)) {
278  /* Stopping a promotable clone instance */
279  pcmk__xe_set_props(xml,
280  "role", role2text(rsc->role),
281  "node", origin->details->uname,
282  NULL);
283 
284  } else if (destination == NULL) {
285  /* Stopping a resource */
286  crm_xml_add(xml, "node", origin->details->uname);
287 
288  } else if (need_role && same_role && same_host) {
289  /* Recovering, restarting or re-promoting a promotable clone instance */
290  pcmk__xe_set_props(xml,
291  "role", role2text(rsc->role),
292  "source", origin->details->uname,
293  NULL);
294 
295  } else if (same_role && same_host) {
296  /* Recovering or Restarting a normal resource */
297  crm_xml_add(xml, "source", origin->details->uname);
298 
299  } else if (need_role && same_role) {
300  /* Moving a promotable clone instance */
301  pcmk__xe_set_props(xml,
302  "source", origin->details->uname,
303  "dest", destination->details->uname,
304  "role", role2text(rsc->role),
305  NULL);
306 
307  } else if (same_role) {
308  /* Moving a normal resource */
309  pcmk__xe_set_props(xml,
310  "source", origin->details->uname,
311  "dest", destination->details->uname,
312  NULL);
313 
314  } else if (same_host) {
315  /* Promoting or demoting a promotable clone instance */
316  pcmk__xe_set_props(xml,
317  "role", role2text(rsc->role),
318  "next-role", role2text(rsc->next_role),
319  "source", origin->details->uname,
320  NULL);
321 
322  } else {
323  /* Moving and promoting/demoting */
324  pcmk__xe_set_props(xml,
325  "role", role2text(rsc->role),
326  "source", origin->details->uname,
327  "next-role", role2text(rsc->next_role),
328  "dest", destination->details->uname,
329  NULL);
330  }
331 
332  if (source->reason && !pcmk_is_set(action->flags, pe_action_runnable)) {
333  pcmk__xe_set_props(xml,
334  "reason", source->reason,
335  "blocked", "true",
336  NULL);
337 
338  } else if(source->reason) {
339  crm_xml_add(xml, "reason", source->reason);
340 
341  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
342  crm_xml_add(xml, "blocked", "true");
343 
344  }
345 
346  return pcmk_rc_ok;
347 }
348 
349 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
350 static int
351 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
352  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
353  gboolean recursive = va_arg(args, gboolean);
354 
355  int rc = pcmk_rc_no_output;
356 
357  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
358  return rc;
359  }
360 
362  for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
363  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
364  char *hdr = NULL;
365 
366  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources %s is colocated with", rsc->id);
367 
368  if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
369  out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_rh->id, cons->id);
370  continue;
371  }
372 
373  hdr = colocations_header(cons->rsc_rh, cons, FALSE);
374  out->list_item(out, NULL, "%s", hdr);
375  free(hdr);
376 
377  /* Empty list header just for indentation of information about this resource. */
378  out->begin_list(out, NULL, NULL, NULL);
379 
380  out->message(out, "locations-list", cons->rsc_rh);
381  if (recursive) {
382  out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
383  }
384 
385  out->end_list(out);
386  }
387 
388  PCMK__OUTPUT_LIST_FOOTER(out, rc);
389  return rc;
390 }
391 
392 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
393 static int
394 rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
395  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
396  gboolean recursive = va_arg(args, gboolean);
397 
398  int rc = pcmk_rc_no_output;
399 
400  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
401  return rc;
402  }
403 
405  for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
406  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
407 
408  if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
409  colocations_xml_node(out, cons->rsc_rh, cons);
410  continue;
411  }
412 
413  colocations_xml_node(out, cons->rsc_rh, cons);
414  do_locations_list_xml(out, cons->rsc_rh, false);
415 
416  if (recursive) {
417  out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
418  }
419  }
420 
421  return rc;
422 }
423 
424 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
425 static int
426 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
427  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
428  gboolean recursive = va_arg(args, gboolean);
429 
430  int rc = pcmk_rc_no_output;
431 
432  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
433  return rc;
434  }
435 
437  for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
438  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
439  char *hdr = NULL;
440 
441  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
442 
443  if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
444  out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_lh->id, cons->id);
445  continue;
446  }
447 
448  hdr = colocations_header(cons->rsc_lh, cons, TRUE);
449  out->list_item(out, NULL, "%s", hdr);
450  free(hdr);
451 
452  /* Empty list header just for indentation of information about this resource. */
453  out->begin_list(out, NULL, NULL, NULL);
454 
455  out->message(out, "locations-list", cons->rsc_lh);
456  if (recursive) {
457  out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
458  }
459 
460  out->end_list(out);
461  }
462 
463  PCMK__OUTPUT_LIST_FOOTER(out, rc);
464  return rc;
465 }
466 
467 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
468 static int
469 rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
470  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
471  gboolean recursive = va_arg(args, gboolean);
472 
473  int rc = pcmk_rc_no_output;
474 
475  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
476  return rc;
477  }
478 
480  for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
481  pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
482 
483  if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
484  colocations_xml_node(out, cons->rsc_lh, cons);
485  continue;
486  }
487 
488  colocations_xml_node(out, cons->rsc_lh, cons);
489  do_locations_list_xml(out, cons->rsc_lh, false);
490 
491  if (recursive) {
492  out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
493  }
494  }
495 
496  return rc;
497 }
498 
499 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
500 static int
501 locations_list(pcmk__output_t *out, va_list args) {
502  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
503 
504  GList *lpc = NULL;
505  GList *list = rsc->rsc_location;
506  int rc = pcmk_rc_no_output;
507 
508  for (lpc = list; lpc != NULL; lpc = lpc->next) {
509  pe__location_t *cons = lpc->data;
510 
511  GList *lpc2 = NULL;
512 
513  for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
514  pe_node_t *node = (pe_node_t *) lpc2->data;
515  char *score = score2char(node->weight);
516 
517  PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Locations");
518  out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
519  node->details->uname, score, cons->id, rsc->id);
520  free(score);
521  }
522  }
523 
524  PCMK__OUTPUT_LIST_FOOTER(out, rc);
525  return rc;
526 }
527 
528 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
529 static int
530 locations_list_xml(pcmk__output_t *out, va_list args) {
531  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
532  return do_locations_list_xml(out, rsc, true);
533 }
534 
535 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
536 static int
537 stacks_and_constraints(pcmk__output_t *out, va_list args) {
538  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
539  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
540  gboolean recursive = va_arg(args, gboolean);
541 
542  xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
543  data_set->input);
544 
545  unpack_constraints(cib_constraints, data_set);
546 
547  // Constraints apply to group/clone, not member/instance
548  rsc = uber_parent(rsc);
549 
550  out->message(out, "locations-list", rsc);
551 
553  out->message(out, "rscs-colocated-with-list", rsc, recursive);
554 
556  out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
557  return pcmk_rc_ok;
558 }
559 
560 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
561 static int
562 stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
563  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
564  pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
565  gboolean recursive = va_arg(args, gboolean);
566 
567  xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
568  data_set->input);
569 
570  unpack_constraints(cib_constraints, data_set);
571 
572  // Constraints apply to group/clone, not member/instance
573  rsc = uber_parent(rsc);
574 
575  pcmk__output_xml_create_parent(out, "constraints", NULL);
576  do_locations_list_xml(out, rsc, false);
577 
579  out->message(out, "rscs-colocated-with-list", rsc, recursive);
580 
582  out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
583 
585  return pcmk_rc_ok;
586 }
587 
588 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
589 static int
590 health_text(pcmk__output_t *out, va_list args)
591 {
592  const char *sys_from G_GNUC_UNUSED = va_arg(args, const char *);
593  const char *host_from = va_arg(args, const char *);
594  const char *fsa_state = va_arg(args, const char *);
595  const char *result = va_arg(args, const char *);
596 
597  if (!out->is_quiet(out)) {
598  return out->info(out, "Controller on %s in state %s: %s", crm_str(host_from),
599  crm_str(fsa_state), crm_str(result));
600  } else if (fsa_state != NULL) {
601  pcmk__formatted_printf(out, "%s\n", fsa_state);
602  return pcmk_rc_ok;
603  }
604 
605  return pcmk_rc_no_output;
606 }
607 
608 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
609 static int
610 health_xml(pcmk__output_t *out, va_list args)
611 {
612  const char *sys_from = va_arg(args, const char *);
613  const char *host_from = va_arg(args, const char *);
614  const char *fsa_state = va_arg(args, const char *);
615  const char *result = va_arg(args, const char *);
616 
617  pcmk__output_create_xml_node(out, crm_str(sys_from),
618  "node_name", crm_str(host_from),
619  "state", crm_str(fsa_state),
620  "result", crm_str(result),
621  NULL);
622  return pcmk_rc_ok;
623 }
624 
625 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
626 static int
627 pacemakerd_health_text(pcmk__output_t *out, va_list args)
628 {
629  const char *sys_from = va_arg(args, const char *);
630  const char *state = va_arg(args, const char *);
631  const char *last_updated = va_arg(args, const char *);
632 
633  if (!out->is_quiet(out)) {
634  return out->info(out, "Status of %s: '%s' %s %s", crm_str(sys_from),
635  crm_str(state), (!pcmk__str_empty(last_updated))?
636  "last updated":"", crm_str(last_updated));
637  } else {
638  pcmk__formatted_printf(out, "%s\n", crm_str(state));
639  return pcmk_rc_ok;
640  }
641 
642  return pcmk_rc_no_output;
643 }
644 
645 PCMK__OUTPUT_ARGS("pacemakerd-health", "const char *", "const char *", "const char *")
646 static int
647 pacemakerd_health_xml(pcmk__output_t *out, va_list args)
648 {
649  const char *sys_from = va_arg(args, const char *);
650  const char *state = va_arg(args, const char *);
651  const char *last_updated = va_arg(args, const char *);
652 
653  pcmk__output_create_xml_node(out, crm_str(sys_from),
654  "state", crm_str(state),
655  "last_updated", crm_str(last_updated),
656  NULL);
657  return pcmk_rc_ok;
658 }
659 
660 PCMK__OUTPUT_ARGS("dc", "const char *")
661 static int
662 dc_text(pcmk__output_t *out, va_list args)
663 {
664  const char *dc = va_arg(args, const char *);
665 
666  if (!out->is_quiet(out)) {
667  return out->info(out, "Designated Controller is: %s", crm_str(dc));
668  } else if (dc != NULL) {
669  pcmk__formatted_printf(out, "%s\n", dc);
670  return pcmk_rc_ok;
671  }
672 
673  return pcmk_rc_no_output;
674 }
675 
676 PCMK__OUTPUT_ARGS("dc", "const char *")
677 static int
678 dc_xml(pcmk__output_t *out, va_list args)
679 {
680  const char *dc = va_arg(args, const char *);
681 
683  "node_name", crm_str(dc),
684  NULL);
685  return pcmk_rc_ok;
686 }
687 
688 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
689 static int
690 crmadmin_node_text(pcmk__output_t *out, va_list args)
691 {
692  const char *type = va_arg(args, const char *);
693  const char *name = va_arg(args, const char *);
694  const char *id = va_arg(args, const char *);
695  gboolean BASH_EXPORT = va_arg(args, gboolean);
696 
697  if (out->is_quiet(out)) {
698  pcmk__formatted_printf(out, "%s\n", crm_str(name));
699  return pcmk_rc_ok;
700  } else if (BASH_EXPORT) {
701  return out->info(out, "export %s=%s", crm_str(name), crm_str(id));
702  } else {
703  return out->info(out, "%s node: %s (%s)", type ? type : "cluster",
704  crm_str(name), crm_str(id));
705  }
706 }
707 
708 PCMK__OUTPUT_ARGS("crmadmin-node", "const char *", "const char *", "const char *", "gboolean")
709 static int
710 crmadmin_node_xml(pcmk__output_t *out, va_list args)
711 {
712  const char *type = va_arg(args, const char *);
713  const char *name = va_arg(args, const char *);
714  const char *id = va_arg(args, const char *);
715 
716  pcmk__output_create_xml_node(out, "node",
717  "type", type ? type : "cluster",
718  "name", crm_str(name),
719  "id", crm_str(id),
720  NULL);
721  return pcmk_rc_ok;
722 }
723 
724 PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
725  "guint", "op_digest_cache_t *")
726 static int
727 digests_text(pcmk__output_t *out, va_list args)
728 {
729  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
730  pe_node_t *node = va_arg(args, pe_node_t *);
731  const char *task = va_arg(args, const char *);
732  guint interval_ms = va_arg(args, guint);
733  op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
734 
735  char *action_desc = NULL;
736  const char *rsc_desc = "unknown resource";
737  const char *node_desc = "unknown node";
738 
739  if (interval_ms != 0) {
740  action_desc = crm_strdup_printf("%ums-interval %s action", interval_ms,
741  ((task == NULL)? "unknown" : task));
742  } else if (pcmk__str_eq(task, "monitor", pcmk__str_none)) {
743  action_desc = strdup("probe action");
744  } else {
745  action_desc = crm_strdup_printf("%s action",
746  ((task == NULL)? "unknown" : task));
747  }
748  if ((rsc != NULL) && (rsc->id != NULL)) {
749  rsc_desc = rsc->id;
750  }
751  if ((node != NULL) && (node->details->uname != NULL)) {
752  node_desc = node->details->uname;
753  }
754  out->begin_list(out, NULL, NULL, "Digests for %s %s on %s",
755  rsc_desc, action_desc, node_desc);
756  free(action_desc);
757 
758  if (digests == NULL) {
759  out->list_item(out, NULL, "none");
760  out->end_list(out);
761  return pcmk_rc_ok;
762  }
763  if (digests->digest_all_calc != NULL) {
764  out->list_item(out, NULL, "%s (all parameters)",
765  digests->digest_all_calc);
766  }
767  if (digests->digest_secure_calc != NULL) {
768  out->list_item(out, NULL, "%s (non-private parameters)",
769  digests->digest_secure_calc);
770  }
771  if (digests->digest_restart_calc != NULL) {
772  out->list_item(out, NULL, "%s (non-reloadable parameters)",
773  digests->digest_restart_calc);
774  }
775  out->end_list(out);
776  return pcmk_rc_ok;
777 }
778 
779 static void
780 add_digest_xml(xmlNode *parent, const char *type, const char *digest,
781  xmlNode *digest_source)
782 {
783  if (digest != NULL) {
784  xmlNodePtr digest_xml = create_xml_node(parent, "digest");
785 
786  crm_xml_add(digest_xml, "type", ((type == NULL)? "unspecified" : type));
787  crm_xml_add(digest_xml, "hash", digest);
788  if (digest_source != NULL) {
789  add_node_copy(digest_xml, digest_source);
790  }
791  }
792 }
793 
794 PCMK__OUTPUT_ARGS("digests", "pe_resource_t *", "pe_node_t *", "const char *",
795  "guint", "op_digest_cache_t *")
796 static int
797 digests_xml(pcmk__output_t *out, va_list args)
798 {
799  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
800  pe_node_t *node = va_arg(args, pe_node_t *);
801  const char *task = va_arg(args, const char *);
802  guint interval_ms = va_arg(args, guint);
803  op_digest_cache_t *digests = va_arg(args, op_digest_cache_t *);
804 
805  char *interval_s = crm_strdup_printf("%ums", interval_ms);
806  xmlNode *xml = NULL;
807 
808  xml = pcmk__output_create_xml_node(out, "digests",
809  "resource", crm_str(rsc->id),
810  "node", crm_str(node->details->uname),
811  "task", crm_str(task),
812  "interval", interval_s,
813  NULL);
814  free(interval_s);
815  if (digests != NULL) {
816  add_digest_xml(xml, "all", digests->digest_all_calc,
817  digests->params_all);
818  add_digest_xml(xml, "nonprivate", digests->digest_secure_calc,
819  digests->params_secure);
820  add_digest_xml(xml, "nonreloadable", digests->digest_restart_calc,
821  digests->params_restart);
822  }
823  return pcmk_rc_ok;
824 }
825 
826 #define STOP_SANITY_ASSERT(lineno) do { \
827  if(current && current->details->unclean) { \
828  /* It will be a pseudo op */ \
829  } else if(stop == NULL) { \
830  crm_err("%s:%d: No stop action exists for %s", \
831  __func__, lineno, rsc->id); \
832  CRM_ASSERT(stop != NULL); \
833  } else if (pcmk_is_set(stop->flags, pe_action_optional)) { \
834  crm_err("%s:%d: Action %s is still optional", \
835  __func__, lineno, stop->uuid); \
836  CRM_ASSERT(!pcmk_is_set(stop->flags, pe_action_optional)); \
837  } \
838  } while(0)
839 
840 PCMK__OUTPUT_ARGS("rsc-action", "pe_resource_t *", "pe_node_t *", "pe_node_t *",
841  "gboolean")
842 static int
843 rsc_action_default(pcmk__output_t *out, va_list args)
844 {
845  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
846  pe_node_t *current = va_arg(args, pe_node_t *);
847  pe_node_t *next = va_arg(args, pe_node_t *);
848  gboolean moving = va_arg(args, gboolean);
849 
850  GList *possible_matches = NULL;
851  char *key = NULL;
852  int rc = pcmk_rc_no_output;
853 
854  pe_node_t *start_node = NULL;
855  pe_action_t *start = NULL;
856  pe_action_t *stop = NULL;
857  pe_action_t *promote = NULL;
858  pe_action_t *demote = NULL;
859 
860  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)
861  || (current == NULL && next == NULL)) {
862  pe_rsc_info(rsc, "Leave %s\t(%s%s)",
863  rsc->id, role2text(rsc->role),
864  !pcmk_is_set(rsc->flags, pe_rsc_managed)? " unmanaged" : "");
865  return rc;
866  }
867 
868  if (current != NULL && next != NULL && !pcmk__str_eq(current->details->id, next->details->id, pcmk__str_casei)) {
869  moving = TRUE;
870  }
871 
872  possible_matches = pe__resource_actions(rsc, next, RSC_START, FALSE);
873  if (possible_matches) {
874  start = possible_matches->data;
875  g_list_free(possible_matches);
876  }
877 
878  if ((start == NULL) || !pcmk_is_set(start->flags, pe_action_runnable)) {
879  start_node = NULL;
880  } else {
881  start_node = current;
882  }
883  possible_matches = pe__resource_actions(rsc, start_node, RSC_STOP, FALSE);
884  if (possible_matches) {
885  stop = possible_matches->data;
886  g_list_free(possible_matches);
887  }
888 
889  possible_matches = pe__resource_actions(rsc, next, RSC_PROMOTE, FALSE);
890  if (possible_matches) {
891  promote = possible_matches->data;
892  g_list_free(possible_matches);
893  }
894 
895  possible_matches = pe__resource_actions(rsc, next, RSC_DEMOTE, FALSE);
896  if (possible_matches) {
897  demote = possible_matches->data;
898  g_list_free(possible_matches);
899  }
900 
901  if (rsc->role == rsc->next_role) {
902  pe_action_t *migrate_op = NULL;
903 
904  possible_matches = pe__resource_actions(rsc, next, RSC_MIGRATED, FALSE);
905  if (possible_matches) {
906  migrate_op = possible_matches->data;
907  }
908 
909  CRM_CHECK(next != NULL,);
910  if (next == NULL) {
911  } else if ((migrate_op != NULL) && (current != NULL)
912  && pcmk_is_set(migrate_op->flags, pe_action_runnable)) {
913  rc = out->message(out, "rsc-action-item", "Migrate", rsc, current,
914  next, start, NULL);
915 
916  } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
917  rc = out->message(out, "rsc-action-item", "Reload", rsc, current,
918  next, start, NULL);
919 
920  } else if (start == NULL || pcmk_is_set(start->flags, pe_action_optional)) {
921  if ((demote != NULL) && (promote != NULL)
922  && !pcmk_is_set(demote->flags, pe_action_optional)
923  && !pcmk_is_set(promote->flags, pe_action_optional)) {
924  rc = out->message(out, "rsc-action-item", "Re-promote", rsc,
925  current, next, promote, demote);
926  } else {
927  pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id,
928  role2text(rsc->role), next->details->uname);
929  }
930 
931  } else if (!pcmk_is_set(start->flags, pe_action_runnable)) {
932  rc = out->message(out, "rsc-action-item", "Stop", rsc, current,
933  NULL, stop, (stop && stop->reason)? stop : start);
934  STOP_SANITY_ASSERT(__LINE__);
935 
936  } else if (moving && current) {
937  rc = out->message(out, "rsc-action-item", pcmk_is_set(rsc->flags, pe_rsc_failed)? "Recover" : "Move",
938  rsc, current, next, stop, NULL);
939 
940  } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
941  rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
942  NULL, stop, NULL);
943  STOP_SANITY_ASSERT(__LINE__);
944 
945  } else {
946  rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
947  next, start, NULL);
948  /* STOP_SANITY_ASSERT(__LINE__); False positive for migrate-fail-7 */
949  }
950 
951  g_list_free(possible_matches);
952  return rc;
953  }
954 
955  if(stop
956  && (rsc->next_role == RSC_ROLE_STOPPED
957  || (start && !pcmk_is_set(start->flags, pe_action_runnable)))) {
958 
959  GList *gIter = NULL;
960 
961  key = stop_key(rsc);
962  for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
963  pe_node_t *node = (pe_node_t *) gIter->data;
964  pe_action_t *stop_op = NULL;
965 
966  possible_matches = find_actions(rsc->actions, key, node);
967  if (possible_matches) {
968  stop_op = possible_matches->data;
969  g_list_free(possible_matches);
970  }
971 
972  if (stop_op && (stop_op->flags & pe_action_runnable)) {
973  STOP_SANITY_ASSERT(__LINE__);
974  }
975 
976  if (out->message(out, "rsc-action-item", "Stop", rsc, node, NULL,
977  stop_op, (stop_op && stop_op->reason)? stop_op : start) == pcmk_rc_ok) {
978  rc = pcmk_rc_ok;
979  }
980  }
981 
982  free(key);
983 
984  } else if ((stop != NULL)
985  && pcmk_all_flags_set(rsc->flags, pe_rsc_failed|pe_rsc_stop)) {
986  /* 'stop' may be NULL if the failure was ignored */
987  rc = out->message(out, "rsc-action-item", "Recover", rsc, current,
988  next, stop, start);
989  STOP_SANITY_ASSERT(__LINE__);
990 
991  } else if (moving) {
992  rc = out->message(out, "rsc-action-item", "Move", rsc, current, next,
993  stop, NULL);
994  STOP_SANITY_ASSERT(__LINE__);
995 
996  } else if (pcmk_is_set(rsc->flags, pe_rsc_reload)) {
997  rc = out->message(out, "rsc-action-item", "Reload", rsc, current, next,
998  start, NULL);
999 
1000  } else if (stop != NULL && !pcmk_is_set(stop->flags, pe_action_optional)) {
1001  rc = out->message(out, "rsc-action-item", "Restart", rsc, current,
1002  next, start, NULL);
1003  STOP_SANITY_ASSERT(__LINE__);
1004 
1005  } else if (rsc->role == RSC_ROLE_PROMOTED) {
1006  CRM_LOG_ASSERT(current != NULL);
1007  rc = out->message(out, "rsc-action-item", "Demote", rsc, current,
1008  next, demote, NULL);
1009 
1010  } else if (rsc->next_role == RSC_ROLE_PROMOTED) {
1011  CRM_LOG_ASSERT(next);
1012  rc = out->message(out, "rsc-action-item", "Promote", rsc, current,
1013  next, promote, NULL);
1014 
1015  } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role > RSC_ROLE_STOPPED) {
1016  rc = out->message(out, "rsc-action-item", "Start", rsc, current, next,
1017  start, NULL);
1018  }
1019 
1020  return rc;
1021 }
1022 
1023 PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1024 static int
1025 node_action(pcmk__output_t *out, va_list args)
1026 {
1027  char *task = va_arg(args, char *);
1028  char *node_name = va_arg(args, char *);
1029  char *reason = va_arg(args, char *);
1030 
1031  if (task == NULL) {
1032  return pcmk_rc_no_output;
1033  } else if (reason) {
1034  out->list_item(out, NULL, "%s %s '%s'", task, node_name, reason);
1035  } else {
1036  crm_notice(" * %s %s\n", task, node_name);
1037  }
1038 
1039  return pcmk_rc_ok;
1040 }
1041 
1042 PCMK__OUTPUT_ARGS("node-action", "char *", "char *", "char *")
1043 static int
1044 node_action_xml(pcmk__output_t *out, va_list args)
1045 {
1046  char *task = va_arg(args, char *);
1047  char *node_name = va_arg(args, char *);
1048  char *reason = va_arg(args, char *);
1049 
1050  if (task == NULL) {
1051  return pcmk_rc_no_output;
1052  } else if (reason) {
1053  pcmk__output_create_xml_node(out, "node_action",
1054  "task", task,
1055  "node", node_name,
1056  "reason", reason,
1057  NULL);
1058  } else {
1059  crm_notice(" * %s %s\n", task, node_name);
1060  }
1061 
1062  return pcmk_rc_ok;
1063 }
1064 
1065 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1066 static int
1067 inject_cluster_action(pcmk__output_t *out, va_list args)
1068 {
1069  const char *node = va_arg(args, const char *);
1070  const char *task = va_arg(args, const char *);
1071  xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1072 
1073  if (out->is_quiet(out)) {
1074  return pcmk_rc_no_output;
1075  }
1076 
1077  if(rsc) {
1078  out->list_item(out, NULL, "Cluster action: %s for %s on %s", task, ID(rsc), node);
1079  } else {
1080  out->list_item(out, NULL, "Cluster action: %s on %s", task, node);
1081  }
1082 
1083  return pcmk_rc_ok;
1084 }
1085 
1086 PCMK__OUTPUT_ARGS("inject-cluster-action", "const char *", "const char *", "xmlNodePtr")
1087 static int
1088 inject_cluster_action_xml(pcmk__output_t *out, va_list args)
1089 {
1090  const char *node = va_arg(args, const char *);
1091  const char *task = va_arg(args, const char *);
1092  xmlNodePtr rsc = va_arg(args, xmlNodePtr);
1093 
1094  xmlNodePtr xml_node = NULL;
1095 
1096  if (out->is_quiet(out)) {
1097  return pcmk_rc_no_output;
1098  }
1099 
1100  xml_node = pcmk__output_create_xml_node(out, "cluster_action",
1101  "task", task,
1102  "node", node,
1103  NULL);
1104 
1105  if (rsc) {
1106  crm_xml_add(xml_node, "id", ID(rsc));
1107  }
1108 
1109  return pcmk_rc_ok;
1110 }
1111 
1112 PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1113 static int
1114 inject_fencing_action(pcmk__output_t *out, va_list args)
1115 {
1116  char *target = va_arg(args, char *);
1117  const char *op = va_arg(args, const char *);
1118 
1119  if (out->is_quiet(out)) {
1120  return pcmk_rc_no_output;
1121  }
1122 
1123  out->list_item(out, NULL, "Fencing %s (%s)", target, op);
1124  return pcmk_rc_ok;
1125 }
1126 
1127 PCMK__OUTPUT_ARGS("inject-fencing-action", "char *", "const char *")
1128 static int
1129 inject_fencing_action_xml(pcmk__output_t *out, va_list args)
1130 {
1131  char *target = va_arg(args, char *);
1132  const char *op = va_arg(args, const char *);
1133 
1134  if (out->is_quiet(out)) {
1135  return pcmk_rc_no_output;
1136  }
1137 
1138  pcmk__output_create_xml_node(out, "fencing_action",
1139  "target", target,
1140  "op", op,
1141  NULL);
1142  return pcmk_rc_ok;
1143 }
1144 
1145 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1146 static int
1147 inject_attr(pcmk__output_t *out, va_list args)
1148 {
1149  const char *name = va_arg(args, const char *);
1150  const char *value = va_arg(args, const char *);
1151  xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1152 
1153  xmlChar *node_path = NULL;
1154 
1155  if (out->is_quiet(out)) {
1156  return pcmk_rc_no_output;
1157  }
1158 
1159  node_path = xmlGetNodePath(cib_node);
1160 
1161  out->list_item(out, NULL, "Injecting attribute %s=%s into %s '%s'",
1162  name, value, node_path, ID(cib_node));
1163 
1164  free(node_path);
1165  return pcmk_rc_ok;
1166 }
1167 
1168 PCMK__OUTPUT_ARGS("inject-attr", "const char *", "const char *", "xmlNodePtr")
1169 static int
1170 inject_attr_xml(pcmk__output_t *out, va_list args)
1171 {
1172  const char *name = va_arg(args, const char *);
1173  const char *value = va_arg(args, const char *);
1174  xmlNodePtr cib_node = va_arg(args, xmlNodePtr);
1175 
1176  xmlChar *node_path = NULL;
1177 
1178  if (out->is_quiet(out)) {
1179  return pcmk_rc_no_output;
1180  }
1181 
1182  node_path = xmlGetNodePath(cib_node);
1183 
1184  pcmk__output_create_xml_node(out, "inject_attr",
1185  "name", name,
1186  "value", value,
1187  "node_path", node_path,
1188  "cib_node", ID(cib_node),
1189  NULL);
1190  free(node_path);
1191  return pcmk_rc_ok;
1192 }
1193 
1194 PCMK__OUTPUT_ARGS("inject-spec", "char *")
1195 static int
1196 inject_spec(pcmk__output_t *out, va_list args)
1197 {
1198  char *spec = va_arg(args, char *);
1199 
1200  if (out->is_quiet(out)) {
1201  return pcmk_rc_no_output;
1202  }
1203 
1204  out->list_item(out, NULL, "Injecting %s into the configuration", spec);
1205  return pcmk_rc_ok;
1206 }
1207 
1208 PCMK__OUTPUT_ARGS("inject-spec", "char *")
1209 static int
1210 inject_spec_xml(pcmk__output_t *out, va_list args)
1211 {
1212  char *spec = va_arg(args, char *);
1213 
1214  if (out->is_quiet(out)) {
1215  return pcmk_rc_no_output;
1216  }
1217 
1218  pcmk__output_create_xml_node(out, "inject_spec",
1219  "spec", spec,
1220  NULL);
1221  return pcmk_rc_ok;
1222 }
1223 
1224 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1225 static int
1226 inject_modify_config(pcmk__output_t *out, va_list args)
1227 {
1228  const char *quorum = va_arg(args, const char *);
1229  const char *watchdog = va_arg(args, const char *);
1230 
1231  if (out->is_quiet(out)) {
1232  return pcmk_rc_no_output;
1233  }
1234 
1235  out->begin_list(out, NULL, NULL, "Performing Requested Modifications");
1236 
1237  if (quorum) {
1238  out->list_item(out, NULL, "Setting quorum: %s", quorum);
1239  }
1240 
1241  if (watchdog) {
1242  out->list_item(out, NULL, "Setting watchdog: %s", watchdog);
1243  }
1244 
1245  return pcmk_rc_ok;
1246 }
1247 
1248 PCMK__OUTPUT_ARGS("inject-modify-config", "const char *", "const char *")
1249 static int
1250 inject_modify_config_xml(pcmk__output_t *out, va_list args)
1251 {
1252  const char *quorum = va_arg(args, const char *);
1253  const char *watchdog = va_arg(args, const char *);
1254 
1255  xmlNodePtr node = NULL;
1256 
1257  if (out->is_quiet(out)) {
1258  return pcmk_rc_no_output;
1259  }
1260 
1261  node = pcmk__output_xml_create_parent(out, "modifications", NULL);
1262 
1263  if (quorum) {
1264  crm_xml_add(node, "quorum", quorum);
1265  }
1266 
1267  if (watchdog) {
1268  crm_xml_add(node, "watchdog", watchdog);
1269  }
1270 
1271  return pcmk_rc_ok;
1272 }
1273 
1274 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1275 static int
1276 inject_modify_node(pcmk__output_t *out, va_list args)
1277 {
1278  const char *action = va_arg(args, const char *);
1279  char *node = va_arg(args, char *);
1280 
1281  if (out->is_quiet(out)) {
1282  return pcmk_rc_no_output;
1283  }
1284 
1285  if (pcmk__str_eq(action, "Online", pcmk__str_none)) {
1286  out->list_item(out, NULL, "Bringing node %s online", node);
1287  return pcmk_rc_ok;
1288  } else if (pcmk__str_eq(action, "Offline", pcmk__str_none)) {
1289  out->list_item(out, NULL, "Taking node %s offline", node);
1290  return pcmk_rc_ok;
1291  } else if (pcmk__str_eq(action, "Failing", pcmk__str_none)) {
1292  out->list_item(out, NULL, "Failing node %s", node);
1293  return pcmk_rc_ok;
1294  }
1295 
1296  return pcmk_rc_no_output;
1297 }
1298 
1299 PCMK__OUTPUT_ARGS("inject-modify-node", "const char *", "char *")
1300 static int
1301 inject_modify_node_xml(pcmk__output_t *out, va_list args)
1302 {
1303  const char *action = va_arg(args, const char *);
1304  char *node = va_arg(args, char *);
1305 
1306  if (out->is_quiet(out)) {
1307  return pcmk_rc_no_output;
1308  }
1309 
1310  pcmk__output_create_xml_node(out, "modify_node",
1311  "action", action,
1312  "node", node,
1313  NULL);
1314  return pcmk_rc_ok;
1315 }
1316 
1317 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1318 static int
1319 inject_modify_ticket(pcmk__output_t *out, va_list args)
1320 {
1321  const char *action = va_arg(args, const char *);
1322  char *ticket = va_arg(args, char *);
1323 
1324  if (out->is_quiet(out)) {
1325  return pcmk_rc_no_output;
1326  }
1327 
1328  if (pcmk__str_eq(action, "Standby", pcmk__str_none)) {
1329  out->list_item(out, NULL, "Making ticket %s standby", ticket);
1330  } else {
1331  out->list_item(out, NULL, "%s ticket %s", action, ticket);
1332  }
1333 
1334  return pcmk_rc_ok;
1335 }
1336 
1337 PCMK__OUTPUT_ARGS("inject-modify-ticket", "const char *", "char *")
1338 static int
1339 inject_modify_ticket_xml(pcmk__output_t *out, va_list args)
1340 {
1341  const char *action = va_arg(args, const char *);
1342  char *ticket = va_arg(args, char *);
1343 
1344  if (out->is_quiet(out)) {
1345  return pcmk_rc_no_output;
1346  }
1347 
1348  pcmk__output_create_xml_node(out, "modify_ticket",
1349  "action", action,
1350  "ticket", ticket,
1351  NULL);
1352  return pcmk_rc_ok;
1353 }
1354 
1355 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1356 static int
1357 inject_pseudo_action(pcmk__output_t *out, va_list args)
1358 {
1359  const char *node = va_arg(args, const char *);
1360  const char *task = va_arg(args, const char *);
1361 
1362  if (out->is_quiet(out)) {
1363  return pcmk_rc_no_output;
1364  }
1365 
1366  out->list_item(out, NULL, "Pseudo action: %s%s%s", task, node ? " on " : "",
1367  node ? node : "");
1368  return pcmk_rc_ok;
1369 }
1370 
1371 PCMK__OUTPUT_ARGS("inject-pseudo-action", "const char *", "const char *")
1372 static int
1373 inject_pseudo_action_xml(pcmk__output_t *out, va_list args)
1374 {
1375  const char *node = va_arg(args, const char *);
1376  const char *task = va_arg(args, const char *);
1377 
1378  xmlNodePtr xml_node = NULL;
1379 
1380  if (out->is_quiet(out)) {
1381  return pcmk_rc_no_output;
1382  }
1383 
1384  xml_node = pcmk__output_create_xml_node(out, "pseudo_action",
1385  "task", task,
1386  NULL);
1387  if (node) {
1388  crm_xml_add(xml_node, "node", node);
1389  }
1390 
1391  return pcmk_rc_ok;
1392 }
1393 
1394 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1395 static int
1396 inject_rsc_action(pcmk__output_t *out, va_list args)
1397 {
1398  const char *rsc = va_arg(args, const char *);
1399  const char *operation = va_arg(args, const char *);
1400  char *node = va_arg(args, char *);
1401  guint interval_ms = va_arg(args, guint);
1402 
1403  if (out->is_quiet(out)) {
1404  return pcmk_rc_no_output;
1405  }
1406 
1407  if (interval_ms) {
1408  out->list_item(out, NULL, "Resource action: %-15s %s=%u on %s",
1409  rsc, operation, interval_ms, node);
1410  } else {
1411  out->list_item(out, NULL, "Resource action: %-15s %s on %s",
1412  rsc, operation, node);
1413  }
1414 
1415  return pcmk_rc_ok;
1416 }
1417 
1418 PCMK__OUTPUT_ARGS("inject-rsc-action", "const char *", "const char *", "char *", "guint")
1419 static int
1420 inject_rsc_action_xml(pcmk__output_t *out, va_list args)
1421 {
1422  const char *rsc = va_arg(args, const char *);
1423  const char *operation = va_arg(args, const char *);
1424  char *node = va_arg(args, char *);
1425  guint interval_ms = va_arg(args, guint);
1426 
1427  xmlNodePtr xml_node = NULL;
1428 
1429  if (out->is_quiet(out)) {
1430  return pcmk_rc_no_output;
1431  }
1432 
1433  xml_node = pcmk__output_create_xml_node(out, "rsc_action",
1434  "resource", rsc,
1435  "op", operation,
1436  "node", node,
1437  NULL);
1438 
1439  if (interval_ms) {
1440  char *interval_s = pcmk__itoa(interval_ms);
1441 
1442  crm_xml_add(xml_node, "interval", interval_s);
1443  free(interval_s);
1444  }
1445 
1446  return pcmk_rc_ok;
1447 }
1448 
1449 static pcmk__message_entry_t fmt_functions[] = {
1450  { "crmadmin-node", "default", crmadmin_node_text },
1451  { "crmadmin-node", "xml", crmadmin_node_xml },
1452  { "dc", "default", dc_text },
1453  { "dc", "xml", dc_xml },
1454  { "digests", "default", digests_text },
1455  { "digests", "xml", digests_xml },
1456  { "health", "default", health_text },
1457  { "health", "xml", health_xml },
1458  { "inject-attr", "default", inject_attr },
1459  { "inject-attr", "xml", inject_attr_xml },
1460  { "inject-cluster-action", "default", inject_cluster_action },
1461  { "inject-cluster-action", "xml", inject_cluster_action_xml },
1462  { "inject-fencing-action", "default", inject_fencing_action },
1463  { "inject-fencing-action", "xml", inject_fencing_action_xml },
1464  { "inject-modify-config", "default", inject_modify_config },
1465  { "inject-modify-config", "xml", inject_modify_config_xml },
1466  { "inject-modify-node", "default", inject_modify_node },
1467  { "inject-modify-node", "xml", inject_modify_node_xml },
1468  { "inject-modify-ticket", "default", inject_modify_ticket },
1469  { "inject-modify-ticket", "xml", inject_modify_ticket_xml },
1470  { "inject-pseudo-action", "default", inject_pseudo_action },
1471  { "inject-pseudo-action", "xml", inject_pseudo_action_xml },
1472  { "inject-rsc-action", "default", inject_rsc_action },
1473  { "inject-rsc-action", "xml", inject_rsc_action_xml },
1474  { "inject-spec", "default", inject_spec },
1475  { "inject-spec", "xml", inject_spec_xml },
1476  { "locations-list", "default", locations_list },
1477  { "locations-list", "xml", locations_list_xml },
1478  { "node-action", "default", node_action },
1479  { "node-action", "xml", node_action_xml },
1480  { "pacemakerd-health", "default", pacemakerd_health_text },
1481  { "pacemakerd-health", "xml", pacemakerd_health_xml },
1482  { "rsc-action", "default", rsc_action_default },
1483  { "rsc-action-item", "default", rsc_action_item },
1484  { "rsc-action-item", "xml", rsc_action_item_xml },
1485  { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
1486  { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
1487  { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
1488  { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
1489  { "stacks-constraints", "default", stacks_and_constraints },
1490  { "stacks-constraints", "xml", stacks_and_constraints_xml },
1491 
1492  { NULL, NULL, NULL }
1493 };
1494 
1495 void
1497  pcmk__register_messages(out, fmt_functions);
1498 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
#define RSC_STOP
Definition: crm.h:204
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...)
Definition: output_xml.c:465
#define crm_notice(fmt, args...)
Definition: logging.h:352
pe_resource_t * rsc_lh
GList * rsc_cons
Definition: pe_types.h:356
enum rsc_role_e role
Definition: pe_types.h:369
#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:1452
#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:370
pe_resource_t * rsc_rh
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
void pcmk__xe_set_props(xmlNodePtr node,...)
Definition: xml.c:2972
gboolean unpack_constraints(xmlNode *xml_constraints, pe_working_set_t *data_set)
#define XML_CONS_TAG_RSC_DEPEND
Definition: msg_xml.h:345
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:202
xmlNode * params_restart
Definition: internal.h:499
GList * rsc_cons_lhs
Definition: pe_types.h:355
enum crm_ais_msg_types type
Definition: cpg.c:48
#define RSC_START
Definition: crm.h:201
char * reason
Definition: pe_types.h:416
const char * action
Definition: pcmk_fence.c:30
#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
const char * role2text(enum rsc_role_e role)
Definition: common.c:459
int weight
Definition: pe_types.h:241
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
#define PCMK__OUTPUT_ARGS(ARGS...)
char * digest_all_calc
Definition: internal.h:500
#define stop_key(rsc)
Definition: internal.h:394
#define XML_CONS_TAG_RSC_LOCATION
Definition: msg_xml.h:347
char * digest_secure_calc
Definition: internal.h:501
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:347
const char * uname
Definition: pe_types.h:209
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:1496
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
GList * actions
Definition: pe_types.h:358
#define pe_rsc_allocating
Definition: pe_types.h:259
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:497
const char * id
Definition: pe_types.h:208
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:826
#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:498
void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
Definition: utils.c:1929
GList * rsc_location
Definition: pe_types.h:357
#define crm_str(x)
Definition: logging.h:376
GList * running_on
Definition: pe_types.h:365
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:143
enum pe_action_flags flags
Definition: pe_types.h:418
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:1540
char * name
Definition: pcmk_fence.c:31
char * digest_restart_calc
Definition: internal.h:502
#define pe_rsc_managed
Definition: pe_types.h:249
xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name,...)
Definition: output_xml.c:432
#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:320
#define RSC_MIGRATED
Definition: crm.h:199