root/lib/pacemaker/pcmk_fence.c

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

DEFINITIONS

This source file includes following definitions.
  1. handle_level
  2. reduce_fence_history
  3. notify_callback
  4. fence_callback
  5. async_fence_helper
  6. pcmk__request_fencing
  7. pcmk_request_fencing
  8. pcmk__fence_history
  9. pcmk_fence_history
  10. pcmk__fence_installed
  11. pcmk_fence_installed
  12. pcmk__fence_last
  13. pcmk_fence_last
  14. pcmk__fence_list_targets
  15. pcmk_fence_list_targets
  16. pcmk__fence_metadata
  17. pcmk_fence_metadata
  18. pcmk__fence_registered
  19. pcmk_fence_registered
  20. pcmk__fence_register_level
  21. pcmk_fence_register_level
  22. pcmk__fence_unregister_level
  23. pcmk_fence_unregister_level
  24. pcmk__fence_validate
  25. pcmk_fence_validate
  26. pcmk__get_fencing_history

   1 /*
   2  * Copyright 2009-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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 #include <crm/common/mainloop.h>
  12 #include <crm/common/results.h>
  13 #include <crm/common/output.h>
  14 #include <crm/common/output_internal.h>
  15 #include <crm/stonith-ng.h>
  16 #include <crm/fencing/internal.h>   // stonith__*
  17 
  18 #include <glib.h>
  19 #include <libxml/tree.h>
  20 #include <pacemaker.h>
  21 #include <pacemaker-internal.h>
  22 
  23 #include "libpacemaker_private.h"
  24 
  25 static const int st_opts = st_opt_sync_call|st_opt_allow_self_fencing;
  26 
  27 static GMainLoop *mainloop = NULL;
  28 
  29 static struct {
  30     stonith_t *st;
  31     const char *target;
  32     const char *action;
  33     char *name;
  34     unsigned int timeout;
  35     unsigned int tolerance;
  36     int delay;
  37     pcmk__action_result_t result;
  38 } async_fence_data = { NULL, };
  39 
  40 static int
  41 handle_level(stonith_t *st, const char *target, int fence_level, GList *devices,
     /* [previous][next][first][last][top][bottom][index][help] */
  42              bool added)
  43 {
  44     const char *node = NULL;
  45     const char *pattern = NULL;
  46     const char *name = NULL;
  47     char *value = NULL;
  48     int rc = pcmk_rc_ok;
  49 
  50     if (target == NULL) {
  51         // Not really possible, but makes static analysis happy
  52         return EINVAL;
  53     }
  54 
  55     /* Determine if targeting by attribute, node name pattern or node name */
  56     value = strchr(target, '=');
  57     if (value != NULL)  {
  58         name = target;
  59         *value++ = '\0';
  60     } else if (*target == '@') {
  61         pattern = target + 1;
  62     } else {
  63         node = target;
  64     }
  65 
  66     /* Register or unregister level as appropriate */
  67     if (added) {
  68         stonith_key_value_t *kvs = NULL;
  69 
  70         for (GList *iter = devices; iter != NULL; iter = iter->next) {
  71             kvs = stonith_key_value_add(kvs, NULL, iter->data);
  72         }
  73 
  74         rc = st->cmds->register_level_full(st, st_opts, node, pattern, name,
  75                                            value, fence_level, kvs);
  76         stonith_key_value_freeall(kvs, 0, 1);
  77     } else {
  78         rc = st->cmds->remove_level_full(st, st_opts, node, pattern,
  79                                          name, value, fence_level);
  80     }
  81 
  82     return pcmk_legacy2rc(rc);
  83 }
  84 
  85 static stonith_history_t *
  86 reduce_fence_history(stonith_history_t *history)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88     stonith_history_t *new, *hp, *np;
  89 
  90     if (!history) {
  91         return history;
  92     }
  93 
  94     new = history;
  95     hp = new->next;
  96     new->next = NULL;
  97 
  98     while (hp) {
  99         stonith_history_t *hp_next = hp->next;
 100 
 101         hp->next = NULL;
 102 
 103         for (np = new; ; np = np->next) {
 104             if ((hp->state == st_done) || (hp->state == st_failed)) {
 105                 /* action not in progress */
 106                 if (pcmk__str_eq(hp->target, np->target, pcmk__str_casei)
 107                     && pcmk__str_eq(hp->action, np->action, pcmk__str_none)
 108                     && (hp->state == np->state)
 109                     && ((hp->state == st_done)
 110                         || pcmk__str_eq(hp->delegate, np->delegate,
 111                                         pcmk__str_casei))) {
 112                         /* purge older hp */
 113                         stonith_history_free(hp);
 114                         break;
 115                 }
 116             }
 117 
 118             if (!np->next) {
 119                 np->next = hp;
 120                 break;
 121             }
 122         }
 123         hp = hp_next;
 124     }
 125 
 126     return new;
 127 }
 128 
 129 static void
 130 notify_callback(stonith_t * st, stonith_event_t * e)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132     if (pcmk__str_eq(async_fence_data.target, e->target, pcmk__str_casei)
 133         && pcmk__str_eq(async_fence_data.action, e->action, pcmk__str_none)) {
 134 
 135         pcmk__set_result(&async_fence_data.result,
 136                          stonith__event_exit_status(e),
 137                          stonith__event_execution_status(e),
 138                          stonith__event_exit_reason(e));
 139         g_main_loop_quit(mainloop);
 140     }
 141 }
 142 
 143 static void
 144 fence_callback(stonith_t * stonith, stonith_callback_data_t * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146     pcmk__set_result(&async_fence_data.result, stonith__exit_status(data),
 147                      stonith__execution_status(data),
 148                      stonith__exit_reason(data));
 149     g_main_loop_quit(mainloop);
 150 }
 151 
 152 static gboolean
 153 async_fence_helper(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155     stonith_t *st = async_fence_data.st;
 156     int call_id = 0;
 157     int rc = stonith_api_connect_retry(st, async_fence_data.name, 10);
 158     int timeout = 0;
 159 
 160     if (rc != pcmk_ok) {
 161         g_main_loop_quit(mainloop);
 162         pcmk__set_result(&async_fence_data.result, CRM_EX_ERROR,
 163                          PCMK_EXEC_NOT_CONNECTED, pcmk_strerror(rc));
 164         return TRUE;
 165     }
 166 
 167     st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_FENCE,
 168                                     notify_callback);
 169 
 170     call_id = st->cmds->fence_with_delay(st,
 171                                          st_opt_allow_self_fencing,
 172                                          async_fence_data.target,
 173                                          async_fence_data.action,
 174                                          pcmk__timeout_ms2s(async_fence_data.timeout),
 175                                          pcmk__timeout_ms2s(async_fence_data.tolerance),
 176                                          async_fence_data.delay);
 177 
 178     if (call_id < 0) {
 179         g_main_loop_quit(mainloop);
 180         pcmk__set_result(&async_fence_data.result, CRM_EX_ERROR,
 181                          PCMK_EXEC_ERROR, pcmk_strerror(call_id));
 182         return TRUE;
 183     }
 184 
 185     timeout = pcmk__timeout_ms2s(async_fence_data.timeout);
 186     if (async_fence_data.delay > 0) {
 187         timeout += async_fence_data.delay;
 188     }
 189     st->cmds->register_callback(st, call_id, timeout, st_opt_timeout_updates,
 190                                 NULL, "callback", fence_callback);
 191     return TRUE;
 192 }
 193 
 194 int
 195 pcmk__request_fencing(stonith_t *st, const char *target, const char *action,
     /* [previous][next][first][last][top][bottom][index][help] */
 196                       const char *name, unsigned int timeout,
 197                       unsigned int tolerance, int delay, char **reason)
 198 {
 199     crm_trigger_t *trig;
 200     int rc = pcmk_rc_ok;
 201 
 202     async_fence_data.st = st;
 203     async_fence_data.name = strdup(name);
 204     async_fence_data.target = target;
 205     async_fence_data.action = action;
 206     async_fence_data.timeout = timeout;
 207     async_fence_data.tolerance = tolerance;
 208     async_fence_data.delay = delay;
 209     pcmk__set_result(&async_fence_data.result, CRM_EX_ERROR, PCMK_EXEC_UNKNOWN,
 210                      NULL);
 211 
 212     trig = mainloop_add_trigger(G_PRIORITY_HIGH, async_fence_helper, NULL);
 213     mainloop_set_trigger(trig);
 214 
 215     mainloop = g_main_loop_new(NULL, FALSE);
 216     g_main_loop_run(mainloop);
 217 
 218     free(async_fence_data.name);
 219 
 220     if (reason != NULL) {
 221         // Give the caller ownership of the exit reason
 222         *reason = async_fence_data.result.exit_reason;
 223         async_fence_data.result.exit_reason = NULL;
 224     }
 225     rc = stonith__result2rc(&async_fence_data.result);
 226     pcmk__reset_result(&async_fence_data.result);
 227     return rc;
 228 }
 229 
 230 int
 231 pcmk_request_fencing(xmlNodePtr *xml, const char *target, const char *action,
     /* [previous][next][first][last][top][bottom][index][help] */
 232                      const char *name, unsigned int timeout,
 233                      unsigned int tolerance, int delay, char **reason)
 234 {
 235     stonith_t *st = NULL;
 236     pcmk__output_t *out = NULL;
 237     int rc = pcmk_rc_ok;
 238 
 239     rc = pcmk__setup_output_fencing(&out, &st, xml);
 240     if (rc != pcmk_rc_ok) {
 241         return rc;
 242     }
 243 
 244     rc = pcmk__request_fencing(st, target, action, name, timeout, tolerance,
 245                                delay, reason);
 246     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 247 
 248     st->cmds->disconnect(st);
 249     stonith_api_delete(st);
 250     return rc;
 251 }
 252 
 253 int
 254 pcmk__fence_history(pcmk__output_t *out, stonith_t *st, const char *target,
     /* [previous][next][first][last][top][bottom][index][help] */
 255                     unsigned int timeout, int verbose, bool broadcast,
 256                     bool cleanup)
 257 {
 258     stonith_history_t *history = NULL;
 259     stonith_history_t *latest = NULL;
 260     int rc = pcmk_rc_ok;
 261     int opts = 0;
 262 
 263     if (cleanup) {
 264         out->info(out, "cleaning up fencing-history%s%s",
 265                   target ? " for node " : "", target ? target : "");
 266     }
 267 
 268     if (broadcast) {
 269         out->info(out, "gather fencing-history from all nodes");
 270     }
 271 
 272     stonith__set_call_options(opts, target, st_opts);
 273 
 274     if (cleanup) {
 275         stonith__set_call_options(opts, target, st_opt_cleanup);
 276     }
 277 
 278     if (broadcast) {
 279         stonith__set_call_options(opts, target, st_opt_broadcast);
 280     }
 281 
 282     if (pcmk__str_eq(target, "*", pcmk__str_none)) {
 283         target = NULL;
 284     }
 285 
 286     rc = st->cmds->history(st, opts, target, &history, pcmk__timeout_ms2s(timeout));
 287 
 288     if (cleanup) {
 289         // Cleanup doesn't return a history list
 290         stonith_history_free(history);
 291         return pcmk_legacy2rc(rc);
 292     }
 293 
 294     out->begin_list(out, "event", "events", "Fencing history");
 295 
 296     history = stonith__sort_history(history);
 297     for (stonith_history_t *hp = history; hp != NULL; hp = hp->next) {
 298         if (hp->state == st_done) {
 299             latest = hp;
 300         }
 301 
 302         if (out->is_quiet(out) || !verbose) {
 303             continue;
 304         }
 305 
 306         out->message(out, "stonith-event", hp, true, false,
 307                      stonith__later_succeeded(hp, history),
 308                      (uint32_t) pcmk_show_failed_detail);
 309         out->increment_list(out);
 310     }
 311 
 312     if (latest) {
 313         if (out->is_quiet(out)) {
 314             out->message(out, "stonith-event", latest, false, true, NULL,
 315                          (uint32_t) pcmk_show_failed_detail);
 316         } else if (!verbose) { // already printed if verbose
 317             out->message(out, "stonith-event", latest, false, false, NULL,
 318                          (uint32_t) pcmk_show_failed_detail);
 319             out->increment_list(out);
 320         }
 321     }
 322 
 323     out->end_list(out);
 324 
 325     stonith_history_free(history);
 326     return pcmk_legacy2rc(rc);
 327 }
 328 
 329 int
 330 pcmk_fence_history(xmlNodePtr *xml, const char *target, unsigned int timeout,
     /* [previous][next][first][last][top][bottom][index][help] */
 331                    bool quiet, int verbose, bool broadcast, bool cleanup)
 332 {
 333     stonith_t *st = NULL;
 334     pcmk__output_t *out = NULL;
 335     int rc = pcmk_rc_ok;
 336 
 337     rc = pcmk__setup_output_fencing(&out, &st, xml);
 338     if (rc != pcmk_rc_ok) {
 339         return rc;
 340     }
 341 
 342     out->quiet = quiet;
 343 
 344     rc = pcmk__fence_history(out, st, target, timeout, verbose, broadcast,
 345                              cleanup);
 346     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 347 
 348     st->cmds->disconnect(st);
 349     stonith_api_delete(st);
 350     return rc;
 351 }
 352 
 353 int
 354 pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 355 {
 356     stonith_key_value_t *devices = NULL;
 357     int rc = pcmk_rc_ok;
 358 
 359     rc = st->cmds->list_agents(st, st_opt_sync_call, NULL, &devices,
 360                                pcmk__timeout_ms2s(timeout));
 361     // rc is a negative error code or a positive number of agents
 362     if (rc < 0) {
 363         return pcmk_legacy2rc(rc);
 364     }
 365 
 366     out->begin_list(out, "fence device", "fence devices",
 367                     "Installed fence devices");
 368     for (stonith_key_value_t *iter = devices; iter != NULL; iter = iter->next) {
 369         out->list_item(out, "device", "%s", iter->value);
 370     }
 371     out->end_list(out);
 372 
 373     stonith_key_value_freeall(devices, 1, 1);
 374     return pcmk_rc_ok;
 375 }
 376 
 377 int
 378 pcmk_fence_installed(xmlNodePtr *xml, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380     stonith_t *st = NULL;
 381     pcmk__output_t *out = NULL;
 382     int rc = pcmk_rc_ok;
 383 
 384     rc = pcmk__setup_output_fencing(&out, &st, xml);
 385     if (rc != pcmk_rc_ok) {
 386         return rc;
 387     }
 388 
 389     rc = pcmk__fence_installed(out, st, timeout);
 390     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 391 
 392     st->cmds->disconnect(st);
 393     stonith_api_delete(st);
 394     return rc;
 395 }
 396 
 397 int
 398 pcmk__fence_last(pcmk__output_t *out, const char *target, bool as_nodeid)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400     time_t when = 0;
 401 
 402     if (target == NULL) {
 403         return pcmk_rc_ok;
 404     }
 405 
 406     if (as_nodeid) {
 407         when = stonith_api_time(atol(target), NULL, FALSE);
 408     } else {
 409         when = stonith_api_time(0, target, FALSE);
 410     }
 411 
 412     return out->message(out, "last-fenced", target, when);
 413 }
 414 
 415 int
 416 pcmk_fence_last(xmlNodePtr *xml, const char *target, bool as_nodeid)
     /* [previous][next][first][last][top][bottom][index][help] */
 417 {
 418     pcmk__output_t *out = NULL;
 419     int rc = pcmk_rc_ok;
 420 
 421     rc = pcmk__xml_output_new(&out, xml);
 422     if (rc != pcmk_rc_ok) {
 423         return rc;
 424     }
 425 
 426     stonith__register_messages(out);
 427 
 428     rc = pcmk__fence_last(out, target, as_nodeid);
 429     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 430     return rc;
 431 }
 432 
 433 int
 434 pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st,
     /* [previous][next][first][last][top][bottom][index][help] */
 435                          const char *device_id, unsigned int timeout)
 436 {
 437     GList *targets = NULL;
 438     char *lists = NULL;
 439     int rc = pcmk_rc_ok;
 440 
 441     rc = st->cmds->list(st, st_opts, device_id, &lists, pcmk__timeout_ms2s(timeout));
 442     if (rc != pcmk_rc_ok) {
 443         return pcmk_legacy2rc(rc);
 444     }
 445 
 446     targets = stonith__parse_targets(lists);
 447 
 448     out->begin_list(out, "fence target", "fence targets", "Fence Targets");
 449     while (targets != NULL) {
 450         out->list_item(out, NULL, "%s", (const char *) targets->data);
 451         targets = targets->next;
 452     }
 453     out->end_list(out);
 454 
 455     free(lists);
 456     return rc;
 457 }
 458 
 459 int
 460 pcmk_fence_list_targets(xmlNodePtr *xml, const char *device_id, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462     stonith_t *st = NULL;
 463     pcmk__output_t *out = NULL;
 464     int rc = pcmk_rc_ok;
 465 
 466     rc = pcmk__setup_output_fencing(&out, &st, xml);
 467     if (rc != pcmk_rc_ok) {
 468         return rc;
 469     }
 470 
 471     rc = pcmk__fence_list_targets(out, st, device_id, timeout);
 472     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 473 
 474     st->cmds->disconnect(st);
 475     stonith_api_delete(st);
 476     return rc;
 477 }
 478 
 479 int
 480 pcmk__fence_metadata(pcmk__output_t *out, stonith_t *st, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 481                      unsigned int timeout)
 482 {
 483     char *buffer = NULL;
 484     int rc = st->cmds->metadata(st, st_opt_sync_call, agent, NULL, &buffer,
 485                                 pcmk__timeout_ms2s(timeout));
 486 
 487     if (rc != pcmk_rc_ok) {
 488         return pcmk_legacy2rc(rc);
 489     }
 490 
 491     out->output_xml(out, PCMK_XE_METADATA, buffer);
 492     free(buffer);
 493     return rc;
 494 }
 495 
 496 int
 497 pcmk_fence_metadata(xmlNodePtr *xml, const char *agent, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 498 {
 499     stonith_t *st = NULL;
 500     pcmk__output_t *out = NULL;
 501     int rc = pcmk_rc_ok;
 502 
 503     rc = pcmk__setup_output_fencing(&out, &st, xml);
 504     if (rc != pcmk_rc_ok) {
 505         return rc;
 506     }
 507 
 508     rc = pcmk__fence_metadata(out, st, agent, timeout);
 509     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 510 
 511     st->cmds->disconnect(st);
 512     stonith_api_delete(st);
 513     return rc;
 514 }
 515 
 516 int
 517 pcmk__fence_registered(pcmk__output_t *out, stonith_t *st, const char *target,
     /* [previous][next][first][last][top][bottom][index][help] */
 518                        unsigned int timeout)
 519 {
 520     stonith_key_value_t *devices = NULL;
 521     int rc = pcmk_rc_ok;
 522 
 523     rc = st->cmds->query(st, st_opts, target, &devices, pcmk__timeout_ms2s(timeout));
 524     /* query returns a negative error code or a positive number of results. */
 525     if (rc < 0) {
 526         return pcmk_legacy2rc(rc);
 527     }
 528 
 529     out->begin_list(out, "fence device", "fence devices",
 530                     "Registered fence devices");
 531     for (stonith_key_value_t *iter = devices; iter != NULL; iter = iter->next) {
 532         out->list_item(out, "device", "%s", iter->value);
 533     }
 534     out->end_list(out);
 535 
 536     stonith_key_value_freeall(devices, 1, 1);
 537 
 538     /* Return pcmk_rc_ok here, not the number of results.  Callers probably
 539      * don't care.
 540      */
 541     return pcmk_rc_ok;
 542 }
 543 
 544 int
 545 pcmk_fence_registered(xmlNodePtr *xml, const char *target, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 546 {
 547     stonith_t *st = NULL;
 548     pcmk__output_t *out = NULL;
 549     int rc = pcmk_rc_ok;
 550 
 551     rc = pcmk__setup_output_fencing(&out, &st, xml);
 552     if (rc != pcmk_rc_ok) {
 553         return rc;
 554     }
 555 
 556     rc = pcmk__fence_registered(out, st, target, timeout);
 557     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 558 
 559     st->cmds->disconnect(st);
 560     stonith_api_delete(st);
 561     return rc;
 562 }
 563 
 564 int
 565 pcmk__fence_register_level(stonith_t *st, const char *target, int fence_level,
     /* [previous][next][first][last][top][bottom][index][help] */
 566                            GList *devices)
 567 {
 568     return handle_level(st, target, fence_level, devices, true);
 569 }
 570 
 571 int
 572 pcmk_fence_register_level(xmlNodePtr *xml, const char *target, int fence_level,
     /* [previous][next][first][last][top][bottom][index][help] */
 573                           GList *devices)
 574 {
 575     stonith_t* st = NULL;
 576     pcmk__output_t *out = NULL;
 577     int rc = pcmk_rc_ok;
 578 
 579     rc = pcmk__setup_output_fencing(&out, &st, xml);
 580     if (rc != pcmk_rc_ok) {
 581         return rc;
 582     }
 583 
 584     rc = pcmk__fence_register_level(st, target, fence_level, devices);
 585     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 586 
 587     st->cmds->disconnect(st);
 588     stonith_api_delete(st);
 589     return rc;
 590 }
 591 
 592 int
 593 pcmk__fence_unregister_level(stonith_t *st, const char *target, int fence_level)
     /* [previous][next][first][last][top][bottom][index][help] */
 594 {
 595     return handle_level(st, target, fence_level, NULL, false);
 596 }
 597 
 598 int
 599 pcmk_fence_unregister_level(xmlNodePtr *xml, const char *target, int fence_level)
     /* [previous][next][first][last][top][bottom][index][help] */
 600 {
 601     stonith_t* st = NULL;
 602     pcmk__output_t *out = NULL;
 603     int rc = pcmk_rc_ok;
 604 
 605     rc = pcmk__setup_output_fencing(&out, &st, xml);
 606     if (rc != pcmk_rc_ok) {
 607         return rc;
 608     }
 609 
 610     rc = pcmk__fence_unregister_level(st, target, fence_level);
 611     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 612 
 613     st->cmds->disconnect(st);
 614     stonith_api_delete(st);
 615     return rc;
 616 }
 617 
 618 int
 619 pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 620                      const char *id, GHashTable *params, unsigned int timeout)
 621 {
 622     char *output = NULL;
 623     char *error_output = NULL;
 624     int rc;
 625 
 626     rc  = stonith__validate(st, st_opt_sync_call, id, NULL, agent, params,
 627                             pcmk__timeout_ms2s(timeout), &output, &error_output);
 628     out->message(out, "validate", agent, id, output, error_output, rc);
 629     return pcmk_legacy2rc(rc);
 630 }
 631 
 632 int
 633 pcmk_fence_validate(xmlNodePtr *xml, const char *agent, const char *id,
     /* [previous][next][first][last][top][bottom][index][help] */
 634                     GHashTable *params, unsigned int timeout)
 635 {
 636     stonith_t *st = NULL;
 637     pcmk__output_t *out = NULL;
 638     int rc = pcmk_rc_ok;
 639 
 640     rc = pcmk__setup_output_fencing(&out, &st, xml);
 641     if (rc != pcmk_rc_ok) {
 642         return rc;
 643     }
 644 
 645     rc = pcmk__fence_validate(out, st, agent, id, params, timeout);
 646     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 647 
 648     st->cmds->disconnect(st);
 649     stonith_api_delete(st);
 650     return rc;
 651 }
 652 
 653 int
 654 pcmk__get_fencing_history(stonith_t *st, stonith_history_t **stonith_history,
     /* [previous][next][first][last][top][bottom][index][help] */
 655                           enum pcmk__fence_history fence_history)
 656 {
 657     int rc = pcmk_rc_ok;
 658 
 659     if ((st == NULL) || (st->state == stonith_disconnected)) {
 660         rc = ENOTCONN;
 661     } else if (fence_history != pcmk__fence_history_none) {
 662         rc = st->cmds->history(st, st_opt_sync_call, NULL, stonith_history,
 663                                120);
 664 
 665         rc = pcmk_legacy2rc(rc);
 666         if (rc != pcmk_rc_ok) {
 667             return rc;
 668         }
 669 
 670         *stonith_history = stonith__sort_history(*stonith_history);
 671         if (fence_history == pcmk__fence_history_reduced) {
 672             *stonith_history = reduce_fence_history(*stonith_history);
 673         }
 674     }
 675 
 676     return rc;
 677 }

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