root/lib/fencing/st_output.c

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

DEFINITIONS

This source file includes following definitions.
  1. timespec_string
  2. state_str
  3. stonith__history_description
  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. stonith__register_messages

   1 /*
   2  * Copyright 2019-2024 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 Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 #include <stdarg.h>
  12 #include <stdint.h>
  13 
  14 #include <crm/stonith-ng.h>
  15 #include <crm/common/iso8601.h>
  16 #include <crm/common/util.h>
  17 #include <crm/common/xml.h>
  18 #include <crm/common/output.h>
  19 #include <crm/common/output_internal.h>
  20 #include <crm/common/xml_internal.h>
  21 #include <crm/fencing/internal.h>
  22 #include <crm/pengine/internal.h>
  23 
  24 /*!
  25  * \internal
  26  * \brief Convert seconds and nanoseconds to a date/time/time-zone string
  27  *
  28  * \param[in] sec        Seconds
  29  * \param[in] nsec       Nanoseconds
  30  * \param[in] show_usec  Whether to show time in microseconds resolution (if
  31  *                       false, use seconds resolution)
  32  *
  33  * \return A string representation of \p sec and \nsec
  34  *
  35  * \note The caller is responsible for freeing the return value using \p free().
  36  */
  37 static char *
  38 timespec_string(time_t sec, long nsec, bool show_usec) {
     /* [previous][next][first][last][top][bottom][index][help] */
  39     const struct timespec ts = {
  40         .tv_sec = sec,
  41         .tv_nsec = nsec,
  42     };
  43 
  44     return pcmk__timespec2str(&ts,
  45                               crm_time_log_date
  46                               |crm_time_log_timeofday
  47                               |crm_time_log_with_timezone
  48                               |(show_usec? crm_time_usecs : 0));
  49 }
  50 
  51 /*!
  52  * \internal
  53  * \brief Return a status-friendly description of fence history entry state
  54  *
  55  * \param[in] history  Fence history entry to describe
  56  *
  57  * \return One-word description of history entry state
  58  * \note This is similar to stonith_op_state_str() except user-oriented (i.e.
  59  *       for cluster status) instead of developer-oriented (for debug logs).
  60  */
  61 static const char *
  62 state_str(const stonith_history_t *history)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64     switch (history->state) {
  65         case st_failed: return "failed";
  66         case st_done:   return "successful";
  67         default:        return "pending";
  68     }
  69 }
  70 
  71 /*!
  72  * \internal
  73  * \brief Create a description of a fencing history entry for status displays
  74  *
  75  * \param[in] history          Fencing history entry to describe
  76  * \param[in] full_history     Whether this is for full or condensed history
  77  * \param[in] later_succeeded  Node that a later equivalent attempt succeeded
  78  *                             from, or NULL if none
  79  * \param[in] show_opts        Flag group of pcmk_show_opt_e
  80  *
  81  * \return Newly created string with fencing history entry description
  82  *
  83  * \note The caller is responsible for freeing the return value with g_free().
  84  * \note This is similar to stonith__event_description(), except this is used
  85  *       for history entries (stonith_history_t) in status displays rather than
  86  *       event notifications (stonith_event_t) in log messages.
  87  */
  88 gchar *
  89 stonith__history_description(const stonith_history_t *history,
     /* [previous][next][first][last][top][bottom][index][help] */
  90                              bool full_history, const char *later_succeeded,
  91                              uint32_t show_opts)
  92 {
  93     GString *str = g_string_sized_new(256); // Generous starting size
  94     char *completed_time_s = NULL;
  95 
  96     if ((history->state == st_failed) || (history->state == st_done)) {
  97         completed_time_s = timespec_string(history->completed,
  98                                            history->completed_nsec, true);
  99     }
 100 
 101     pcmk__g_strcat(str,
 102                    stonith_action_str(history->action), " of ", history->target,
 103                    NULL);
 104 
 105     if (!pcmk_is_set(show_opts, pcmk_show_failed_detail)) {
 106         // More human-friendly
 107         if (((history->state == st_failed) || (history->state == st_done))
 108             && (history->delegate != NULL)) {
 109 
 110             pcmk__g_strcat(str, " by ", history->delegate, NULL);
 111         }
 112         pcmk__g_strcat(str, " for ", history->client, "@", history->origin,
 113                        NULL);
 114         if (!full_history) {
 115             g_string_append(str, " last"); // For example, "last failed at ..."
 116         }
 117     }
 118 
 119     pcmk__add_word(&str, 0, state_str(history));
 120 
 121     // For failed actions, add exit reason if available
 122     if ((history->state == st_failed) && (history->exit_reason != NULL)) {
 123         pcmk__g_strcat(str, " (", history->exit_reason, ")", NULL);
 124     }
 125 
 126     if (pcmk_is_set(show_opts, pcmk_show_failed_detail)) {
 127         // More technical
 128         g_string_append(str, ": ");
 129 
 130         // For completed actions, add delegate if available
 131         if (((history->state == st_failed) || (history->state == st_done))
 132             && (history->delegate != NULL)) {
 133 
 134             pcmk__g_strcat(str, PCMK_XA_DELEGATE "=", history->delegate, ", ",
 135                            NULL);
 136         }
 137 
 138         // Add information about originator
 139         pcmk__g_strcat(str,
 140                        PCMK_XA_CLIENT "=", history->client, ", "
 141                        PCMK_XA_ORIGIN "=", history->origin, NULL);
 142 
 143         // For completed actions, add completion time
 144         if (completed_time_s != NULL) {
 145             if (full_history) {
 146                 g_string_append(str, ", completed");
 147             } else if (history->state == st_failed) {
 148                 g_string_append(str, ", last-failed");
 149             } else {
 150                 g_string_append(str, ", last-successful");
 151             }
 152             pcmk__g_strcat(str, "='", completed_time_s, "'", NULL);
 153         }
 154     } else if (completed_time_s != NULL) {
 155         // More human-friendly
 156         pcmk__g_strcat(str, " at ", completed_time_s, NULL);
 157     }
 158 
 159     if ((history->state == st_failed) && (later_succeeded != NULL)) {
 160         pcmk__g_strcat(str,
 161                        " (a later attempt from ", later_succeeded,
 162                        " succeeded)", NULL);
 163     }
 164 
 165     free(completed_time_s);
 166     return g_string_free(str, FALSE);
 167 }
 168 
 169 PCMK__OUTPUT_ARGS("failed-fencing-list", "stonith_history_t *", "GList *",
     /* [previous][next][first][last][top][bottom][index][help] */
 170                   "uint32_t", "uint32_t", "bool")
 171 static int
 172 failed_history(pcmk__output_t *out, va_list args)
 173 {
 174     stonith_history_t *history = va_arg(args, stonith_history_t *);
 175     GList *only_node = va_arg(args, GList *);
 176     uint32_t section_opts = va_arg(args, uint32_t);
 177     uint32_t show_opts = va_arg(args, uint32_t);
 178     bool print_spacer = va_arg(args, int);
 179 
 180     int rc = pcmk_rc_no_output;
 181 
 182     for (stonith_history_t *hp = history; hp; hp = hp->next) {
 183         if (hp->state != st_failed) {
 184             continue;
 185         }
 186 
 187         if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
 188             continue;
 189         }
 190 
 191         PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Failed Fencing Actions");
 192         out->message(out, "stonith-event", hp,
 193                      pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
 194                      false, stonith__later_succeeded(hp, history), show_opts);
 195         out->increment_list(out);
 196     }
 197 
 198     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 199     return rc;
 200 }
 201 
 202 PCMK__OUTPUT_ARGS("fencing-list", "stonith_history_t *", "GList *", "uint32_t",
     /* [previous][next][first][last][top][bottom][index][help] */
 203                   "uint32_t", "bool")
 204 static int
 205 stonith_history(pcmk__output_t *out, va_list args)
 206 {
 207     stonith_history_t *history = va_arg(args, stonith_history_t *);
 208     GList *only_node = va_arg(args, GList *);
 209     uint32_t section_opts = va_arg(args, uint32_t);
 210     uint32_t show_opts = va_arg(args, uint32_t);
 211     bool print_spacer = va_arg(args, int);
 212 
 213     int rc = pcmk_rc_no_output;
 214 
 215     for (stonith_history_t *hp = history; hp; hp = hp->next) {
 216         if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
 217             continue;
 218         }
 219 
 220         if (hp->state != st_failed) {
 221             PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
 222             out->message(out, "stonith-event", hp,
 223                          pcmk_all_flags_set(section_opts,
 224                                             pcmk_section_fencing_all),
 225                          false, stonith__later_succeeded(hp, history), show_opts);
 226             out->increment_list(out);
 227         }
 228     }
 229 
 230     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 231     return rc;
 232 }
 233 
 234 PCMK__OUTPUT_ARGS("full-fencing-list", "crm_exit_t", "stonith_history_t *",
     /* [previous][next][first][last][top][bottom][index][help] */
 235                   "GList *", "uint32_t", "uint32_t", "bool")
 236 static int
 237 full_history(pcmk__output_t *out, va_list args)
 238 {
 239     crm_exit_t history_rc G_GNUC_UNUSED = va_arg(args, crm_exit_t);
 240     stonith_history_t *history = va_arg(args, stonith_history_t *);
 241     GList *only_node = va_arg(args, GList *);
 242     uint32_t section_opts = va_arg(args, uint32_t);
 243     uint32_t show_opts = va_arg(args, uint32_t);
 244     bool print_spacer = va_arg(args, int);
 245 
 246     int rc = pcmk_rc_no_output;
 247 
 248     for (stonith_history_t *hp = history; hp; hp = hp->next) {
 249         if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
 250             continue;
 251         }
 252 
 253         PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Fencing History");
 254         out->message(out, "stonith-event", hp,
 255                      pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
 256                      false, stonith__later_succeeded(hp, history), show_opts);
 257         out->increment_list(out);
 258     }
 259 
 260     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 261     return rc;
 262 }
 263 
 264 PCMK__OUTPUT_ARGS("full-fencing-list", "crm_exit_t", "stonith_history_t *",
     /* [previous][next][first][last][top][bottom][index][help] */
 265                   "GList *", "uint32_t", "uint32_t", "bool")
 266 static int
 267 full_history_xml(pcmk__output_t *out, va_list args)
 268 {
 269     crm_exit_t history_rc = va_arg(args, crm_exit_t);
 270     stonith_history_t *history = va_arg(args, stonith_history_t *);
 271     GList *only_node = va_arg(args, GList *);
 272     uint32_t section_opts = va_arg(args, uint32_t);
 273     uint32_t show_opts = va_arg(args, uint32_t);
 274     bool print_spacer G_GNUC_UNUSED = va_arg(args, int);
 275 
 276     int rc = pcmk_rc_no_output;
 277 
 278     if (history_rc == 0) {
 279         for (stonith_history_t *hp = history; hp; hp = hp->next) {
 280             if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
 281                 continue;
 282             }
 283 
 284             PCMK__OUTPUT_LIST_HEADER(out, false, rc, "Fencing History");
 285             out->message(out, "stonith-event", hp,
 286                          pcmk_all_flags_set(section_opts,
 287                                             pcmk_section_fencing_all),
 288                          false, stonith__later_succeeded(hp, history), show_opts);
 289             out->increment_list(out);
 290         }
 291 
 292         PCMK__OUTPUT_LIST_FOOTER(out, rc);
 293     } else {
 294         char *rc_s = pcmk__itoa(history_rc);
 295 
 296         pcmk__output_create_xml_node(out, PCMK_XE_FENCE_HISTORY,
 297                                      PCMK_XA_STATUS, rc_s,
 298                                      NULL);
 299         free(rc_s);
 300 
 301         rc = pcmk_rc_ok;
 302     }
 303 
 304     return rc;
 305 }
 306 
 307 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
     /* [previous][next][first][last][top][bottom][index][help] */
 308 static int
 309 last_fenced_html(pcmk__output_t *out, va_list args) {
 310     const char *target = va_arg(args, const char *);
 311     time_t when = va_arg(args, time_t);
 312 
 313     if (when) {
 314         char *buf = crm_strdup_printf("Node %s last fenced at: %s", target, ctime(&when));
 315         pcmk__output_create_html_node(out, PCMK__XE_DIV, NULL, NULL, buf);
 316         free(buf);
 317         return pcmk_rc_ok;
 318     } else {
 319         return pcmk_rc_no_output;
 320     }
 321 }
 322 
 323 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
     /* [previous][next][first][last][top][bottom][index][help] */
 324 static int
 325 last_fenced_text(pcmk__output_t *out, va_list args) {
 326     const char *target = va_arg(args, const char *);
 327     time_t when = va_arg(args, time_t);
 328 
 329     if (when) {
 330         pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
 331     } else {
 332         pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
 333     }
 334 
 335     return pcmk_rc_ok;
 336 }
 337 
 338 PCMK__OUTPUT_ARGS("last-fenced", "const char *", "time_t")
     /* [previous][next][first][last][top][bottom][index][help] */
 339 static int
 340 last_fenced_xml(pcmk__output_t *out, va_list args) {
 341     const char *target = va_arg(args, const char *);
 342     time_t when = va_arg(args, time_t);
 343 
 344     if (when) {
 345         char *buf = timespec_string(when, 0, false);
 346 
 347         pcmk__output_create_xml_node(out, PCMK_XE_LAST_FENCED,
 348                                      PCMK_XA_TARGET, target,
 349                                      PCMK_XA_WHEN, buf,
 350                                      NULL);
 351 
 352         free(buf);
 353         return pcmk_rc_ok;
 354     } else {
 355         return pcmk_rc_no_output;
 356     }
 357 }
 358 
 359 PCMK__OUTPUT_ARGS("pending-fencing-list", "stonith_history_t *", "GList *",
     /* [previous][next][first][last][top][bottom][index][help] */
 360                   "uint32_t", "uint32_t", "bool")
 361 static int
 362 pending_actions(pcmk__output_t *out, va_list args)
 363 {
 364     stonith_history_t *history = va_arg(args, stonith_history_t *);
 365     GList *only_node = va_arg(args, GList *);
 366     uint32_t section_opts = va_arg(args, uint32_t);
 367     uint32_t show_opts = va_arg(args, uint32_t);
 368     bool print_spacer = va_arg(args, int);
 369 
 370     int rc = pcmk_rc_no_output;
 371 
 372     for (stonith_history_t *hp = history; hp; hp = hp->next) {
 373         if (!pcmk__str_in_list(hp->target, only_node, pcmk__str_star_matches|pcmk__str_casei)) {
 374             continue;
 375         }
 376 
 377         /* Skip the rest of the history after we see a failed/done action */
 378         if ((hp->state == st_failed) || (hp->state == st_done)) {
 379             break;
 380         }
 381 
 382         PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Pending Fencing Actions");
 383         out->message(out, "stonith-event", hp,
 384                      pcmk_all_flags_set(section_opts, pcmk_section_fencing_all),
 385                      false, stonith__later_succeeded(hp, history), show_opts);
 386         out->increment_list(out);
 387     }
 388 
 389     PCMK__OUTPUT_LIST_FOOTER(out, rc);
 390     return rc;
 391 }
 392 
 393 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "bool", "bool",
     /* [previous][next][first][last][top][bottom][index][help] */
 394                   "const char *", "uint32_t")
 395 static int
 396 stonith_event_html(pcmk__output_t *out, va_list args)
 397 {
 398     stonith_history_t *event = va_arg(args, stonith_history_t *);
 399     bool full_history = va_arg(args, int);
 400     bool completed_only G_GNUC_UNUSED = va_arg(args, int);
 401     const char *succeeded = va_arg(args, const char *);
 402     uint32_t show_opts = va_arg(args, uint32_t);
 403 
 404     gchar *desc = stonith__history_description(event, full_history, succeeded,
 405                                                show_opts);
 406 
 407     switch(event->state) {
 408         case st_done:
 409             out->list_item(out, "successful-stonith-event", "%s", desc);
 410             break;
 411 
 412         case st_failed:
 413             out->list_item(out, "failed-stonith-event", "%s", desc);
 414             break;
 415 
 416         default:
 417             out->list_item(out, "pending-stonith-event", "%s", desc);
 418             break;
 419     }
 420     g_free(desc);
 421     return pcmk_rc_ok;
 422 }
 423 
 424 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "bool", "bool",
     /* [previous][next][first][last][top][bottom][index][help] */
 425                   "const char *", "uint32_t")
 426 static int
 427 stonith_event_text(pcmk__output_t *out, va_list args)
 428 {
 429     stonith_history_t *event = va_arg(args, stonith_history_t *);
 430     bool full_history = va_arg(args, int);
 431     bool completed_only = va_arg(args, int);
 432     const char *succeeded = va_arg(args, const char *);
 433     uint32_t show_opts = va_arg(args, uint32_t);
 434 
 435     if (completed_only) {
 436         pcmk__formatted_printf(out, "%lld\n", (long long) event->completed);
 437     } else {
 438         gchar *desc = stonith__history_description(event, full_history, succeeded,
 439                                                    show_opts);
 440 
 441         pcmk__indented_printf(out, "%s\n", desc);
 442         g_free(desc);
 443     }
 444 
 445     return pcmk_rc_ok;
 446 }
 447 
 448 PCMK__OUTPUT_ARGS("stonith-event", "stonith_history_t *", "bool", "bool",
     /* [previous][next][first][last][top][bottom][index][help] */
 449                   "const char *", "uint32_t")
 450 static int
 451 stonith_event_xml(pcmk__output_t *out, va_list args)
 452 {
 453     stonith_history_t *event = va_arg(args, stonith_history_t *);
 454     bool full_history G_GNUC_UNUSED = va_arg(args, int);
 455     bool completed_only G_GNUC_UNUSED = va_arg(args, int);
 456     const char *succeeded G_GNUC_UNUSED = va_arg(args, const char *);
 457     uint32_t show_opts G_GNUC_UNUSED = va_arg(args, uint32_t);
 458 
 459     xmlNodePtr node = NULL;
 460 
 461     node = pcmk__output_create_xml_node(out, PCMK_XE_FENCE_EVENT,
 462                                         PCMK_XA_ACTION, event->action,
 463                                         PCMK_XA_TARGET, event->target,
 464                                         PCMK_XA_CLIENT, event->client,
 465                                         PCMK_XA_ORIGIN, event->origin,
 466                                         NULL);
 467 
 468     switch (event->state) {
 469         case st_failed:
 470             pcmk__xe_set_props(node,
 471                                PCMK_XA_STATUS, PCMK_VALUE_FAILED,
 472                                PCMK_XA_EXIT_REASON, event->exit_reason,
 473                                NULL);
 474             break;
 475 
 476         case st_done:
 477             crm_xml_add(node, PCMK_XA_STATUS, PCMK_VALUE_SUCCESS);
 478             break;
 479 
 480         default: {
 481             char *state = pcmk__itoa(event->state);
 482             pcmk__xe_set_props(node,
 483                                PCMK_XA_STATUS, PCMK_VALUE_PENDING,
 484                                PCMK_XA_EXTENDED_STATUS, state,
 485                                NULL);
 486             free(state);
 487             break;
 488         }
 489     }
 490 
 491     if (event->delegate != NULL) {
 492         crm_xml_add(node, PCMK_XA_DELEGATE, event->delegate);
 493     }
 494 
 495     if ((event->state == st_failed) || (event->state == st_done)) {
 496         char *time_s = timespec_string(event->completed, event->completed_nsec,
 497                                        true);
 498 
 499         crm_xml_add(node, PCMK_XA_COMPLETED, time_s);
 500         free(time_s);
 501     }
 502 
 503     return pcmk_rc_ok;
 504 }
 505 
 506 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "const char *",
     /* [previous][next][first][last][top][bottom][index][help] */
 507                   "const char *", "int")
 508 static int
 509 validate_agent_html(pcmk__output_t *out, va_list args) {
 510     const char *agent = va_arg(args, const char *);
 511     const char *device = va_arg(args, const char *);
 512     const char *output = va_arg(args, const char *);
 513     const char *error_output = va_arg(args, const char *);
 514     int rc = va_arg(args, int);
 515 
 516     if (device) {
 517         char *buf = crm_strdup_printf("Validation of %s on %s %s", agent, device,
 518                                       rc ? "failed" : "succeeded");
 519         pcmk__output_create_html_node(out, PCMK__XE_DIV, NULL, NULL, buf);
 520         free(buf);
 521     } else {
 522         char *buf = crm_strdup_printf("Validation of %s %s", agent,
 523                                       rc ? "failed" : "succeeded");
 524         pcmk__output_create_html_node(out, PCMK__XE_DIV, NULL, NULL, buf);
 525         free(buf);
 526     }
 527 
 528     out->subprocess_output(out, rc, output, error_output);
 529     return rc;
 530 }
 531 
 532 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "const char *",
     /* [previous][next][first][last][top][bottom][index][help] */
 533                   "const char *", "int")
 534 static int
 535 validate_agent_text(pcmk__output_t *out, va_list args) {
 536     const char *agent = va_arg(args, const char *);
 537     const char *device = va_arg(args, const char *);
 538     const char *output = va_arg(args, const char *);
 539     const char *error_output = va_arg(args, const char *);
 540     int rc = va_arg(args, int);
 541 
 542     if (device) {
 543         pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
 544                               rc ? "failed" : "succeeded");
 545     } else {
 546         pcmk__indented_printf(out, "Validation of %s %s\n", agent,
 547                               rc ? "failed" : "succeeded");
 548     }
 549 
 550     out->subprocess_output(out, rc, output, error_output);
 551     return rc;
 552 }
 553 
 554 PCMK__OUTPUT_ARGS("validate", "const char *", "const char *", "const char *",
     /* [previous][next][first][last][top][bottom][index][help] */
 555                   "const char *", "int")
 556 static int
 557 validate_agent_xml(pcmk__output_t *out, va_list args) {
 558     const char *agent = va_arg(args, const char *);
 559     const char *device = va_arg(args, const char *);
 560     const char *output = va_arg(args, const char *);
 561     const char *error_output = va_arg(args, const char *);
 562     int rc = va_arg(args, int);
 563 
 564     const char *valid = pcmk__btoa(rc == pcmk_ok);
 565     xmlNodePtr node = pcmk__output_create_xml_node(out, PCMK_XE_VALIDATE,
 566                                                    PCMK_XA_AGENT, agent,
 567                                                    PCMK_XA_VALID, valid,
 568                                                    NULL);
 569 
 570     if (device != NULL) {
 571         crm_xml_add(node, PCMK_XA_DEVICE, device);
 572     }
 573 
 574     pcmk__output_xml_push_parent(out, node);
 575     out->subprocess_output(out, rc, output, error_output);
 576     pcmk__output_xml_pop_parent(out);
 577 
 578     return rc;
 579 }
 580 
 581 static pcmk__message_entry_t fmt_functions[] = {
 582     { "failed-fencing-list", "default", failed_history },
 583     { "fencing-list", "default", stonith_history },
 584     { "full-fencing-list", "default", full_history },
 585     { "full-fencing-list", "xml", full_history_xml },
 586     { "last-fenced", "html", last_fenced_html },
 587     { "last-fenced", "log", last_fenced_text },
 588     { "last-fenced", "text", last_fenced_text },
 589     { "last-fenced", "xml", last_fenced_xml },
 590     { "pending-fencing-list", "default", pending_actions },
 591     { "stonith-event", "html", stonith_event_html },
 592     { "stonith-event", "log", stonith_event_text },
 593     { "stonith-event", "text", stonith_event_text },
 594     { "stonith-event", "xml", stonith_event_xml },
 595     { "validate", "html", validate_agent_html },
 596     { "validate", "log", validate_agent_text },
 597     { "validate", "text", validate_agent_text },
 598     { "validate", "xml", validate_agent_xml },
 599 
 600     { NULL, NULL, NULL }
 601 };
 602 
 603 void
 604 stonith__register_messages(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
 605     pcmk__register_messages(out, fmt_functions);
 606 }

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