root/lib/pacemaker/pcmk_output.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. colocations_header
  2. colocations_xml_node
  3. do_locations_list_xml
  4. PCMK__OUTPUT_ARGS
  5. PCMK__OUTPUT_ARGS
  6. PCMK__OUTPUT_ARGS
  7. PCMK__OUTPUT_ARGS
  8. PCMK__OUTPUT_ARGS
  9. PCMK__OUTPUT_ARGS
  10. PCMK__OUTPUT_ARGS
  11. PCMK__OUTPUT_ARGS
  12. PCMK__OUTPUT_ARGS
  13. PCMK__OUTPUT_ARGS
  14. PCMK__OUTPUT_ARGS
  15. PCMK__OUTPUT_ARGS
  16. PCMK__OUTPUT_ARGS
  17. PCMK__OUTPUT_ARGS
  18. PCMK__OUTPUT_ARGS
  19. PCMK__OUTPUT_ARGS
  20. PCMK__OUTPUT_ARGS
  21. PCMK__OUTPUT_ARGS
  22. PCMK__OUTPUT_ARGS
  23. PCMK__OUTPUT_ARGS
  24. PCMK__OUTPUT_ARGS
  25. add_digest_xml
  26. PCMK__OUTPUT_ARGS
  27. PCMK__OUTPUT_ARGS
  28. PCMK__OUTPUT_ARGS
  29. PCMK__OUTPUT_ARGS
  30. PCMK__OUTPUT_ARGS
  31. PCMK__OUTPUT_ARGS
  32. PCMK__OUTPUT_ARGS
  33. PCMK__OUTPUT_ARGS
  34. PCMK__OUTPUT_ARGS
  35. PCMK__OUTPUT_ARGS
  36. PCMK__OUTPUT_ARGS
  37. PCMK__OUTPUT_ARGS
  38. PCMK__OUTPUT_ARGS
  39. PCMK__OUTPUT_ARGS
  40. PCMK__OUTPUT_ARGS
  41. PCMK__OUTPUT_ARGS
  42. PCMK__OUTPUT_ARGS
  43. PCMK__OUTPUT_ARGS
  44. PCMK__OUTPUT_ARGS
  45. PCMK__OUTPUT_ARGS
  46. PCMK__OUTPUT_ARGS
  47. PCMK__OUTPUT_ARGS
  48. PCMK__OUTPUT_ARGS
  49. PCMK__OUTPUT_ARGS
  50. PCMK__OUTPUT_ARGS
  51. pcmk__register_lib_messages

   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,
     /* [previous][next][first][last][top][bottom][index][help] */
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
  42                      pcmk__colocation_t *cons) {
  43     char *score = NULL;
  44     xmlNodePtr node = NULL;
  45 
  46     score = score2char(cons->score);
  47     node = pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_DEPEND,
  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",
  60                    (pcmkXmlStr) role2text(cons->dependent_role));
  61     }
  62 
  63     if (cons->primary_role != RSC_ROLE_UNKNOWN) {
  64         xmlSetProp(node, (pcmkXmlStr) "with-rsc-role",
  65                    (pcmkXmlStr) role2text(cons->primary_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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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 
  91             pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_LOCATION,
  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) {
 102         PCMK__OUTPUT_LIST_FOOTER(out, rc);
 103     }
 104 
 105     return rc;
 106 }
 107 
 108 PCMK__OUTPUT_ARGS("rsc-action-item", "const char *", "pe_resource_t *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 131     CRM_ASSERT(action);
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 241     CRM_ASSERT(action);
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 364     pe__set_resource_flags(rsc, pe_rsc_allocating);
 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 
 371         if (pcmk_is_set(cons->primary->flags, pe_rsc_allocating)) {
 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 
 393     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 394     return rc;
 395 }
 396 
 397 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 409     pe__set_resource_flags(rsc, pe_rsc_allocating);
 410     for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
 411         pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
 412 
 413         if (pcmk_is_set(cons->primary->flags, pe_rsc_allocating)) {
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 442     pe__set_resource_flags(rsc, pe_rsc_allocating);
 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 
 449         if (pcmk_is_set(cons->dependent->flags, pe_rsc_allocating)) {
 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 
 471     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 472     return rc;
 473 }
 474 
 475 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 487     pe__set_resource_flags(rsc, pe_rsc_allocating);
 488     for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
 489         pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data;
 490 
 491         if (pcmk_is_set(cons->dependent->flags, pe_rsc_allocating)) {
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 533     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 534     return rc;
 535 }
 536 
 537 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 558     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 559     out->message(out, "rscs-colocated-with-list", rsc, recursive);
 560 
 561     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 581     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 582     out->message(out, "rscs-colocated-with-list", rsc, recursive);
 583 
 584     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 585     out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
 586 
 587     pcmk__output_xml_pop_parent(out);
 588     return pcmk_rc_ok;
 589 }
 590 
 591 PCMK__OUTPUT_ARGS("health", "const char *", "const char *", "const char *", "const char *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 711 static int
 712 dc_xml(pcmk__output_t *out, va_list args)
 713 {
 714     const char *dc = va_arg(args, const char *);
 715 
 716     pcmk__output_create_xml_node(out, "dc",
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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")
     /* [previous][next][first][last][top][bottom][index][help] */
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")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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")
     /* [previous][next][first][last][top][bottom][index][help] */
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")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
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")
     /* [previous][next][first][last][top][bottom][index][help] */
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")
     /* [previous][next][first][last][top][bottom][index][help] */
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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
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) {
1546             stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_eq,
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 {
1554             PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
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) {
1579                 PCMK__OUTPUT_SPACER_IF(out, rc == pcmk_rc_ok);
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)) {
1586             stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_neq,
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)) {
1594             stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_pending, NULL);
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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
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) {
1737             stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_eq,
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)) {
1762             stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_neq,
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)) {
1769             stonith_history_t *hp = stonith__first_matching_event(stonith_history, stonith__event_state_pending, NULL);
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
1844 pcmk__register_lib_messages(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
1845     pcmk__register_messages(out, fmt_functions);
1846 }

/* [previous][next][first][last][top][bottom][index][help] */