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-2025 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, false, true);
  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_rc_ok) {
 161         g_main_loop_quit(mainloop);
 162         pcmk__set_result(&async_fence_data.result, CRM_EX_ERROR,
 163                          PCMK_EXEC_NOT_CONNECTED, pcmk_rc_str(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_free(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_free(st);
 350     return rc;
 351 }
 352 
 353 int
 354 pcmk__fence_installed(pcmk__output_t *out, stonith_t *st)
     /* [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, 0);
 360     // rc is a negative error code or a positive number of agents
 361     if (rc < 0) {
 362         return pcmk_legacy2rc(rc);
 363     }
 364 
 365     out->begin_list(out, "fence device", "fence devices",
 366                     "Installed fence devices");
 367     for (stonith_key_value_t *iter = devices; iter != NULL; iter = iter->next) {
 368         out->list_item(out, "device", "%s", iter->value);
 369     }
 370     out->end_list(out);
 371 
 372     stonith__key_value_freeall(devices, true, true);
 373     return pcmk_rc_ok;
 374 }
 375 
 376 int
 377 pcmk_fence_installed(xmlNodePtr *xml, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379     stonith_t *st = NULL;
 380     pcmk__output_t *out = NULL;
 381     int rc = pcmk_rc_ok;
 382 
 383     rc = pcmk__setup_output_fencing(&out, &st, xml);
 384     if (rc != pcmk_rc_ok) {
 385         return rc;
 386     }
 387 
 388     rc = pcmk__fence_installed(out, st);
 389     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 390 
 391     st->cmds->disconnect(st);
 392     stonith__api_free(st);
 393     return rc;
 394 }
 395 
 396 int
 397 pcmk__fence_last(pcmk__output_t *out, const char *target, bool as_nodeid)
     /* [previous][next][first][last][top][bottom][index][help] */
 398 {
 399     time_t when = 0;
 400 
 401     if (target == NULL) {
 402         return pcmk_rc_ok;
 403     }
 404 
 405     if (as_nodeid) {
 406         when = stonith_api_time(atol(target), NULL, FALSE);
 407     } else {
 408         when = stonith_api_time(0, target, FALSE);
 409     }
 410 
 411     return out->message(out, "last-fenced", target, when);
 412 }
 413 
 414 int
 415 pcmk_fence_last(xmlNodePtr *xml, const char *target, bool as_nodeid)
     /* [previous][next][first][last][top][bottom][index][help] */
 416 {
 417     pcmk__output_t *out = NULL;
 418     int rc = pcmk_rc_ok;
 419 
 420     rc = pcmk__xml_output_new(&out, xml);
 421     if (rc != pcmk_rc_ok) {
 422         return rc;
 423     }
 424 
 425     stonith__register_messages(out);
 426 
 427     rc = pcmk__fence_last(out, target, as_nodeid);
 428     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 429     return rc;
 430 }
 431 
 432 int
 433 pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st,
     /* [previous][next][first][last][top][bottom][index][help] */
 434                          const char *device_id, unsigned int timeout)
 435 {
 436     GList *targets = NULL;
 437     char *lists = NULL;
 438     int rc = pcmk_rc_ok;
 439 
 440     rc = st->cmds->list(st, st_opts, device_id, &lists, pcmk__timeout_ms2s(timeout));
 441     if (rc != pcmk_rc_ok) {
 442         return pcmk_legacy2rc(rc);
 443     }
 444 
 445     targets = stonith__parse_targets(lists);
 446 
 447     out->begin_list(out, "fence target", "fence targets", "Fence Targets");
 448     while (targets != NULL) {
 449         out->list_item(out, NULL, "%s", (const char *) targets->data);
 450         targets = targets->next;
 451     }
 452     out->end_list(out);
 453 
 454     free(lists);
 455     return rc;
 456 }
 457 
 458 int
 459 pcmk_fence_list_targets(xmlNodePtr *xml, const char *device_id, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461     stonith_t *st = NULL;
 462     pcmk__output_t *out = NULL;
 463     int rc = pcmk_rc_ok;
 464 
 465     rc = pcmk__setup_output_fencing(&out, &st, xml);
 466     if (rc != pcmk_rc_ok) {
 467         return rc;
 468     }
 469 
 470     rc = pcmk__fence_list_targets(out, st, device_id, timeout);
 471     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 472 
 473     st->cmds->disconnect(st);
 474     stonith__api_free(st);
 475     return rc;
 476 }
 477 
 478 int
 479 pcmk__fence_metadata(pcmk__output_t *out, stonith_t *st, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 480                      unsigned int timeout)
 481 {
 482     char *buffer = NULL;
 483     int rc = st->cmds->metadata(st, st_opt_sync_call, agent, NULL, &buffer,
 484                                 pcmk__timeout_ms2s(timeout));
 485 
 486     if (rc != pcmk_rc_ok) {
 487         return pcmk_legacy2rc(rc);
 488     }
 489 
 490     out->output_xml(out, PCMK_XE_METADATA, buffer);
 491     free(buffer);
 492     return rc;
 493 }
 494 
 495 int
 496 pcmk_fence_metadata(xmlNodePtr *xml, const char *agent, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 497 {
 498     stonith_t *st = NULL;
 499     pcmk__output_t *out = NULL;
 500     int rc = pcmk_rc_ok;
 501 
 502     rc = pcmk__setup_output_fencing(&out, &st, xml);
 503     if (rc != pcmk_rc_ok) {
 504         return rc;
 505     }
 506 
 507     rc = pcmk__fence_metadata(out, st, agent, timeout);
 508     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 509 
 510     st->cmds->disconnect(st);
 511     stonith__api_free(st);
 512     return rc;
 513 }
 514 
 515 int
 516 pcmk__fence_registered(pcmk__output_t *out, stonith_t *st, const char *target,
     /* [previous][next][first][last][top][bottom][index][help] */
 517                        unsigned int timeout)
 518 {
 519     stonith_key_value_t *devices = NULL;
 520     int rc = pcmk_rc_ok;
 521 
 522     rc = st->cmds->query(st, st_opts, target, &devices, pcmk__timeout_ms2s(timeout));
 523     /* query returns a negative error code or a positive number of results. */
 524     if (rc < 0) {
 525         return pcmk_legacy2rc(rc);
 526     }
 527 
 528     out->begin_list(out, "fence device", "fence devices",
 529                     "Registered fence devices");
 530     for (stonith_key_value_t *iter = devices; iter != NULL; iter = iter->next) {
 531         out->list_item(out, "device", "%s", iter->value);
 532     }
 533     out->end_list(out);
 534 
 535     stonith__key_value_freeall(devices, true, true);
 536 
 537     /* Return pcmk_rc_ok here, not the number of results.  Callers probably
 538      * don't care.
 539      */
 540     return pcmk_rc_ok;
 541 }
 542 
 543 int
 544 pcmk_fence_registered(xmlNodePtr *xml, const char *target, unsigned int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 545 {
 546     stonith_t *st = NULL;
 547     pcmk__output_t *out = NULL;
 548     int rc = pcmk_rc_ok;
 549 
 550     rc = pcmk__setup_output_fencing(&out, &st, xml);
 551     if (rc != pcmk_rc_ok) {
 552         return rc;
 553     }
 554 
 555     rc = pcmk__fence_registered(out, st, target, timeout);
 556     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 557 
 558     st->cmds->disconnect(st);
 559     stonith__api_free(st);
 560     return rc;
 561 }
 562 
 563 int
 564 pcmk__fence_register_level(stonith_t *st, const char *target, int fence_level,
     /* [previous][next][first][last][top][bottom][index][help] */
 565                            GList *devices)
 566 {
 567     return handle_level(st, target, fence_level, devices, true);
 568 }
 569 
 570 int
 571 pcmk_fence_register_level(xmlNodePtr *xml, const char *target, int fence_level,
     /* [previous][next][first][last][top][bottom][index][help] */
 572                           GList *devices)
 573 {
 574     stonith_t* st = NULL;
 575     pcmk__output_t *out = NULL;
 576     int rc = pcmk_rc_ok;
 577 
 578     rc = pcmk__setup_output_fencing(&out, &st, xml);
 579     if (rc != pcmk_rc_ok) {
 580         return rc;
 581     }
 582 
 583     rc = pcmk__fence_register_level(st, target, fence_level, devices);
 584     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 585 
 586     st->cmds->disconnect(st);
 587     stonith__api_free(st);
 588     return rc;
 589 }
 590 
 591 int
 592 pcmk__fence_unregister_level(stonith_t *st, const char *target, int fence_level)
     /* [previous][next][first][last][top][bottom][index][help] */
 593 {
 594     return handle_level(st, target, fence_level, NULL, false);
 595 }
 596 
 597 int
 598 pcmk_fence_unregister_level(xmlNodePtr *xml, const char *target, int fence_level)
     /* [previous][next][first][last][top][bottom][index][help] */
 599 {
 600     stonith_t* st = NULL;
 601     pcmk__output_t *out = NULL;
 602     int rc = pcmk_rc_ok;
 603 
 604     rc = pcmk__setup_output_fencing(&out, &st, xml);
 605     if (rc != pcmk_rc_ok) {
 606         return rc;
 607     }
 608 
 609     rc = pcmk__fence_unregister_level(st, target, fence_level);
 610     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 611 
 612     st->cmds->disconnect(st);
 613     stonith__api_free(st);
 614     return rc;
 615 }
 616 
 617 int
 618 pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 619                      const char *id, GHashTable *params, unsigned int timeout)
 620 {
 621     char *output = NULL;
 622     char *error_output = NULL;
 623     int rc;
 624 
 625     rc  = stonith__validate(st, st_opt_sync_call, id, agent, params,
 626                             pcmk__timeout_ms2s(timeout), &output, &error_output);
 627     out->message(out, "validate", agent, id, output, error_output, rc);
 628     return pcmk_legacy2rc(rc);
 629 }
 630 
 631 int
 632 pcmk_fence_validate(xmlNodePtr *xml, const char *agent, const char *id,
     /* [previous][next][first][last][top][bottom][index][help] */
 633                     GHashTable *params, unsigned int timeout)
 634 {
 635     stonith_t *st = NULL;
 636     pcmk__output_t *out = NULL;
 637     int rc = pcmk_rc_ok;
 638 
 639     rc = pcmk__setup_output_fencing(&out, &st, xml);
 640     if (rc != pcmk_rc_ok) {
 641         return rc;
 642     }
 643 
 644     rc = pcmk__fence_validate(out, st, agent, id, params, timeout);
 645     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 646 
 647     st->cmds->disconnect(st);
 648     stonith__api_free(st);
 649     return rc;
 650 }
 651 
 652 int
 653 pcmk__get_fencing_history(stonith_t *st, stonith_history_t **stonith_history,
     /* [previous][next][first][last][top][bottom][index][help] */
 654                           enum pcmk__fence_history fence_history)
 655 {
 656     int rc = pcmk_rc_ok;
 657 
 658     if ((st == NULL) || (st->state == stonith_disconnected)) {
 659         rc = ENOTCONN;
 660     } else if (fence_history != pcmk__fence_history_none) {
 661         rc = st->cmds->history(st, st_opt_sync_call, NULL, stonith_history,
 662                                120);
 663 
 664         rc = pcmk_legacy2rc(rc);
 665         if (rc != pcmk_rc_ok) {
 666             return rc;
 667         }
 668 
 669         *stonith_history = stonith__sort_history(*stonith_history);
 670         if (fence_history == pcmk__fence_history_reduced) {
 671             *stonith_history = reduce_fence_history(*stonith_history);
 672         }
 673     }
 674 
 675     return rc;
 676 }

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