1 /* 2 * Copyright 2004-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 #ifndef PCMK__CRM_STONITH_NG__H 11 # define PCMK__CRM_STONITH_NG__H 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 /** 18 * \file 19 * \brief Fencing aka. STONITH 20 * \ingroup fencing 21 */ 22 23 /* IMPORTANT: DLM source code includes this file directly, without having access 24 * to other Pacemaker headers on its include path, so this file should *not* 25 * include any other Pacemaker headers. (DLM might be updated to avoid the 26 * issue, but we should still follow this guideline for a long time after.) 27 */ 28 29 # include <dlfcn.h> 30 # include <errno.h> 31 # include <stdbool.h> // bool 32 # include <stdint.h> // uint32_t 33 # include <time.h> // time_t 34 35 /* *INDENT-OFF* */ 36 enum stonith_state { 37 stonith_connected_command, 38 stonith_connected_query, 39 stonith_disconnected, 40 }; 41 42 //! Flags that can be set in call options for API requests 43 enum stonith_call_options { 44 //! No options 45 st_opt_none = 0, 46 47 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) 48 //! \deprecated Unused 49 st_opt_verbose = (1 << 0), 50 #endif 51 52 //! The fencing target is allowed to execute the request 53 st_opt_allow_self_fencing = (1 << 1), 54 55 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) 56 //! \deprecated Use st_opt_allow_self_fencing instead 57 st_opt_allow_suicide = st_opt_allow_self_fencing, 58 #endif 59 60 // Used internally to indicate that request is manual fence confirmation 61 //! \internal Do not use 62 st_opt_manual_ack = (1 << 3), 63 64 //! Do not return any reply from server 65 st_opt_discard_reply = (1 << 4), 66 67 // Used internally to indicate that request requires a fencing topology 68 //! \internal Do not use 69 st_opt_topology = (1 << 6), 70 71 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) 72 //! \deprecated Unused 73 st_opt_scope_local = (1 << 8), 74 #endif 75 76 //! Interpret target as node cluster layer ID instead of name 77 st_opt_cs_nodeid = (1 << 9), 78 79 //! Wait for request to be completed before returning 80 st_opt_sync_call = (1 << 12), 81 82 //! Request that server send an update with optimal callback timeout 83 st_opt_timeout_updates = (1 << 13), 84 85 //! Invoke callback only if request succeeded 86 st_opt_report_only_success = (1 << 14), 87 88 //! For a fence history request, request that the history be cleared 89 st_opt_cleanup = (1 << 19), 90 91 //! For a fence history request, broadcast the request to all nodes 92 st_opt_broadcast = (1 << 20), 93 }; 94 95 /*! Order matters here, do not change values */ 96 enum op_state 97 { 98 st_query, 99 st_exec, 100 st_done, 101 st_duplicate, 102 st_failed, 103 }; 104 105 // Supported fence agent interface standards 106 enum stonith_namespace { 107 st_namespace_invalid, 108 st_namespace_any, 109 st_namespace_internal, // Implemented internally by Pacemaker 110 111 /* Neither of these projects are active any longer, but the fence agent 112 * interfaces they created are still in use and supported by Pacemaker. 113 */ 114 st_namespace_rhcs, // Red Hat Cluster Suite compatible 115 st_namespace_lha, // Linux-HA compatible 116 }; 117 118 enum stonith_namespace stonith_text2namespace(const char *namespace_s); 119 const char *stonith_namespace2text(enum stonith_namespace st_namespace); 120 enum stonith_namespace stonith_get_namespace(const char *agent, 121 const char *namespace_s); 122 123 typedef struct stonith_key_value_s { 124 char *key; 125 char *value; 126 struct stonith_key_value_s *next; 127 } stonith_key_value_t; 128 129 typedef struct stonith_history_s { 130 char *target; 131 char *action; 132 char *origin; 133 char *delegate; 134 char *client; 135 int state; 136 time_t completed; 137 struct stonith_history_s *next; 138 long completed_nsec; 139 char *exit_reason; 140 } stonith_history_t; 141 142 typedef struct stonith_s stonith_t; 143 144 typedef struct stonith_event_s { 145 char *id; 146 char *operation; 147 int result; 148 char *origin; 149 char *target; 150 char *action; 151 char *executioner; 152 153 char *device; 154 155 /*! The name of the client that initiated the action. */ 156 char *client_origin; 157 158 //! \internal This field should be treated as internal to Pacemaker 159 void *opaque; 160 } stonith_event_t; 161 162 typedef struct stonith_callback_data_s { 163 int rc; 164 int call_id; 165 void *userdata; 166 167 //! \internal This field should be treated as internal to Pacemaker 168 void *opaque; 169 } stonith_callback_data_t; 170 171 typedef struct stonith_api_operations_s 172 { 173 /*! 174 * \brief Destroy a fencer connection 175 * 176 * \param[in,out] st Fencer connection to destroy 177 */ 178 int (*free) (stonith_t *st); 179 180 /*! 181 * \brief Connect to the local fencer 182 * 183 * \param[in,out] st Fencer connection to connect 184 * \param[in] name Client name to use 185 * \param[out] stonith_fd If NULL, use a main loop, otherwise 186 * store IPC file descriptor here 187 * 188 * \return Legacy Pacemaker return code 189 */ 190 int (*connect) (stonith_t *st, const char *name, int *stonith_fd); 191 192 /*! 193 * \brief Disconnect from the local stonith daemon. 194 * 195 * \param[in,out] st Fencer connection to disconnect 196 * 197 * \return Legacy Pacemaker return code 198 */ 199 int (*disconnect)(stonith_t *st); 200 201 /*! 202 * \brief Unregister a fence device with the local fencer 203 * 204 * \param[in,out] st Fencer connection to disconnect 205 * \param[in] options Group of enum stonith_call_options 206 * \param[in] name ID of fence device to unregister 207 * 208 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 209 * on success, otherwise a negative legacy Pacemaker return code 210 */ 211 int (*remove_device)(stonith_t *st, int options, const char *name); 212 213 /*! 214 * \brief Register a fence device with the local fencer 215 * 216 * \param[in,out] st Fencer connection to use 217 * \param[in] options Group of enum stonith_call_options 218 * \param[in] id ID of fence device to register 219 * \param[in] namespace_s Type of fence agent to search for ("redhat" 220 * or "stonith-ng" for RHCS-style, "internal" 221 * for Pacemaker-internal devices, "heartbeat" 222 * for LHA-style, or "any" or NULL for any) 223 * \param[in] agent Name of fence agent for device 224 * \param[in] params Fence agent parameters for device 225 * 226 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 227 * on success, otherwise a negative legacy Pacemaker return code 228 */ 229 int (*register_device)(stonith_t *st, int options, const char *id, 230 const char *namespace_s, const char *agent, 231 const stonith_key_value_t *params); 232 233 /*! 234 * \brief Unregister a fencing level for specified node with local fencer 235 * 236 * \param[in,out] st Fencer connection to use 237 * \param[in] options Group of enum stonith_call_options 238 * \param[in] node Target node to unregister level for 239 * \param[in] level Topology level number to unregister 240 * 241 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 242 * on success, otherwise a negative legacy Pacemaker return code 243 */ 244 int (*remove_level)(stonith_t *st, int options, const char *node, 245 int level); 246 247 /*! 248 * \brief Register a fencing level for specified node with local fencer 249 * 250 * \param[in,out] st Fencer connection to use 251 * \param[in] options Group of enum stonith_call_options 252 * \param[in] node Target node to register level for 253 * \param[in] level Topology level number to register 254 * \param[in] device_list Devices to register in level 255 * 256 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 257 * on success, otherwise a negative legacy Pacemaker return code 258 */ 259 int (*register_level)(stonith_t *st, int options, const char *node, 260 int level, const stonith_key_value_t *device_list); 261 262 /*! 263 * \brief Retrieve a fence agent's metadata 264 * 265 * \param[in,out] stonith Fencer connection 266 * \param[in] call_options Group of enum stonith_call_options 267 * (currently ignored) 268 * \param[in] agent Fence agent to query 269 * \param[in] namespace_s Type of fence agent to search for ("redhat" 270 * or "stonith-ng" for RHCS-style, "internal" 271 * for Pacemaker-internal devices, "heartbeat" 272 * for LHA-style, or "any" or NULL for any) 273 * \param[out] output Where to store metadata 274 * \param[in] timeout_sec Error if not complete within this time 275 * 276 * \return Legacy Pacemaker return code 277 * \note The caller is responsible for freeing *output using free(). 278 */ 279 int (*metadata)(stonith_t *stonith, int call_options, const char *agent, 280 const char *namespace_s, char **output, int timeout_sec); 281 282 /*! 283 * \brief Retrieve a list of installed fence agents 284 * 285 * \param[in,out] stonith Fencer connection to use 286 * \param[in] call_options Group of enum stonith_call_options 287 * (currently ignored) 288 * \param[in] namespace_s Type of fence agents to list ("redhat" 289 * or "stonith-ng" for RHCS-style, "internal" for 290 * Pacemaker-internal devices, "heartbeat" for 291 * LHA-style, or "any" or NULL for all) 292 * \param[out] devices Where to store agent list 293 * \param[in] timeout Error if unable to complete within this 294 * (currently ignored) 295 * 296 * \return Number of items in list on success, or negative errno otherwise 297 * \note The caller is responsible for freeing the returned list with 298 * stonith_key_value_freeall(). 299 */ 300 int (*list_agents)(stonith_t *stonith, int call_options, 301 const char *namespace_s, stonith_key_value_t **devices, 302 int timeout); 303 304 /*! 305 * \brief Get the output of a fence device's list action 306 * 307 * \param[in,out] stonith Fencer connection to use 308 * \param[in] call_options Group of enum stonith_call_options 309 * \param[in] id Fence device ID to run list for 310 * \param[out] list_info Where to store list output 311 * \param[in] timeout Error if unable to complete within this 312 * 313 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 314 * on success, otherwise a negative legacy Pacemaker return code 315 */ 316 int (*list)(stonith_t *stonith, int call_options, const char *id, 317 char **list_info, int timeout); 318 319 /*! 320 * \brief Check whether a fence device is reachable by monitor action 321 * 322 * \param[in,out] stonith Fencer connection to use 323 * \param[in] call_options Group of enum stonith_call_options 324 * \param[in] id Fence device ID to run monitor for 325 * \param[in] timeout Error if unable to complete within this 326 * 327 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 328 * on success, otherwise a negative legacy Pacemaker return code 329 */ 330 int (*monitor)(stonith_t *stonith, int call_options, const char *id, 331 int timeout); 332 333 /*! 334 * \brief Check whether a fence device target is reachable by status action 335 * 336 * \param[in,out] stonith Fencer connection to use 337 * \param[in] call_options Group of enum stonith_call_options 338 * \param[in] id Fence device ID to run status for 339 * \param[in] port Fence target to run status for 340 * \param[in] timeout Error if unable to complete within this 341 * 342 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 343 * on success, otherwise a negative legacy Pacemaker return code 344 */ 345 int (*status)(stonith_t *stonith, int call_options, const char *id, 346 const char *port, int timeout); 347 348 /*! 349 * \brief List registered fence devices 350 * 351 * \param[in,out] stonith Fencer connection to use 352 * \param[in] call_options Group of enum stonith_call_options 353 * \param[in] target Fence target to run status for 354 * \param[out] devices Where to store list of fence devices 355 * \param[in] timeout Error if unable to complete within this 356 * 357 * \note If node is provided, only devices that can fence the node id 358 * will be returned. 359 * 360 * \return Number of items in list on success, or negative errno otherwise 361 */ 362 int (*query)(stonith_t *stonith, int call_options, const char *target, 363 stonith_key_value_t **devices, int timeout); 364 365 /*! 366 * \brief Request that a target get fenced 367 * 368 * \param[in,out] stonith Fencer connection to use 369 * \param[in] call_options Group of enum stonith_call_options 370 * \param[in] node Fence target 371 * \param[in] action "on", "off", or "reboot" 372 * \param[in] timeout Default per-device timeout to use with 373 * each executed device 374 * \param[in] tolerance Accept result of identical fence action 375 * completed within this time 376 * 377 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 378 * on success, otherwise a negative legacy Pacemaker return code 379 */ 380 int (*fence)(stonith_t *stonith, int call_options, const char *node, 381 const char *action, int timeout, int tolerance); 382 383 /*! 384 * \brief Manually confirm that a node has been fenced 385 * 386 * \param[in,out] stonith Fencer connection to use 387 * \param[in] call_options Group of enum stonith_call_options 388 * \param[in] target Fence target 389 * 390 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 391 * on success, otherwise a negative legacy Pacemaker return code 392 */ 393 int (*confirm)(stonith_t *stonith, int call_options, const char *target); 394 395 /*! 396 * \brief List fencing actions that have occurred for a target 397 * 398 * \param[in,out] stonith Fencer connection to use 399 * \param[in] call_options Group of enum stonith_call_options 400 * \param[in] node Fence target 401 * \param[out] history Where to store list of fencing actions 402 * \param[in] timeout Error if unable to complete within this 403 * 404 * \return Legacy Pacemaker return code 405 */ 406 int (*history)(stonith_t *stonith, int call_options, const char *node, 407 stonith_history_t **history, int timeout); 408 409 /*! 410 * \brief Register a callback for fence notifications 411 * 412 * \param[in,out] stonith Fencer connection to use 413 * \param[in] event Event to register for 414 * \param[in] callback Callback to register 415 * 416 * \return Legacy Pacemaker return code 417 */ 418 int (*register_notification)(stonith_t *stonith, const char *event, 419 void (*callback)(stonith_t *st, 420 stonith_event_t *e)); 421 422 /*! 423 * \brief Unregister callbacks for fence notifications 424 * 425 * \param[in,out] stonith Fencer connection to use 426 * \param[in] event Event to unregister callbacks for (NULL for all) 427 * 428 * \return Legacy Pacemaker return code 429 */ 430 int (*remove_notification)(stonith_t *stonith, const char *event); 431 432 /*! 433 * \brief Register a callback for an asynchronous fencing result 434 * 435 * \param[in,out] stonith Fencer connection to use 436 * \param[in] call_id Call ID to register callback for 437 * \param[in] timeout Error if result not received in this time 438 * \param[in] options Group of enum stonith_call_options 439 * (respects \c st_opt_timeout_updates and 440 * \c st_opt_report_only_success) 441 * \param[in,out] user_data Pointer to pass to callback 442 * \param[in] callback_name Unique identifier for callback 443 * \param[in] callback Callback to register (may be called 444 * immediately if \p call_id indicates error) 445 * 446 * \return \c TRUE on success, \c FALSE if call_id indicates error, 447 * or -EINVAL if \p stonith is not valid 448 */ 449 int (*register_callback)(stonith_t *stonith, int call_id, int timeout, 450 int options, void *user_data, 451 const char *callback_name, 452 void (*callback)(stonith_t *st, 453 stonith_callback_data_t *data)); 454 455 /*! 456 * \brief Unregister callbacks for asynchronous fencing results 457 * 458 * \param[in,out] stonith Fencer connection to use 459 * \param[in] call_id If \p all_callbacks is false, call ID 460 * to unregister callback for 461 * \param[in] all_callbacks If true, unregister all callbacks 462 * 463 * \return pcmk_ok 464 */ 465 int (*remove_callback)(stonith_t *stonith, int call_id, bool all_callbacks); 466 467 /*! 468 * \brief Unregister fencing level for specified node, pattern or attribute 469 * 470 * \param[in,out] st Fencer connection to use 471 * \param[in] options Group of enum stonith_call_options 472 * \param[in] node If not NULL, unregister level targeting this node 473 * \param[in] pattern If not NULL, unregister level targeting nodes 474 * whose names match this regular expression 475 * \param[in] attr If this and \p value are not NULL, unregister 476 * level targeting nodes with this node attribute 477 * set to \p value 478 * \param[in] value If this and \p attr are not NULL, unregister 479 * level targeting nodes with node attribute \p attr 480 * set to this 481 * \param[in] level Topology level number to remove 482 * 483 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 484 * on success, otherwise a negative legacy Pacemaker return code 485 * \note The caller should set only one of \p node, \p pattern, or \p attr 486 * and \p value. 487 */ 488 int (*remove_level_full)(stonith_t *st, int options, 489 const char *node, const char *pattern, 490 const char *attr, const char *value, int level); 491 492 /*! 493 * \brief Register fencing level for specified node, pattern or attribute 494 * 495 * \param[in,out] st Fencer connection to use 496 * \param[in] options Group of enum stonith_call_options 497 * \param[in] node If not NULL, register level targeting this 498 * node by name 499 * \param[in] pattern If not NULL, register level targeting nodes 500 * whose names match this regular expression 501 * \param[in] attr If this and \p value are not NULL, register 502 * level targeting nodes with this node 503 * attribute set to \p value 504 * \param[in] value If this and \p attr are not NULL, register 505 * level targeting nodes with node attribute 506 * \p attr set to this 507 * \param[in] level Topology level number to remove 508 * \param[in] device_list Devices to use in level 509 * 510 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 511 * on success, otherwise a negative legacy Pacemaker return code 512 * 513 * \note The caller should set only one of node, pattern or attr/value. 514 */ 515 int (*register_level_full)(stonith_t *st, int options, 516 const char *node, const char *pattern, 517 const char *attr, const char *value, int level, 518 const stonith_key_value_t *device_list); 519 520 /*! 521 * \brief Validate an arbitrary stonith device configuration 522 * 523 * \param[in,out] st Fencer connection to use 524 * \param[in] call_options Group of enum stonith_call_options 525 * \param[in] rsc_id ID used to replace CIB secrets in \p params 526 * \param[in] namespace_s Type of fence agent to validate ("redhat" 527 * or "stonith-ng" for RHCS-style, "internal" 528 * for Pacemaker-internal devices, "heartbeat" 529 * for LHA-style, or "any" or NULL for any) 530 * \param[in] agent Fence agent to validate 531 * \param[in] params Configuration parameters to pass to agent 532 * \param[in] timeout Fail if no response within this many seconds 533 * \param[out] output If non-NULL, where to store any agent output 534 * \param[out] error_output If non-NULL, where to store agent error output 535 * 536 * \return pcmk_ok if validation succeeds, -errno otherwise 537 * \note If pcmk_ok is returned, the caller is responsible for freeing 538 * the output (if requested) with free(). 539 */ 540 int (*validate)(stonith_t *st, int call_options, const char *rsc_id, 541 const char *namespace_s, const char *agent, 542 const stonith_key_value_t *params, int timeout, 543 char **output, char **error_output); 544 545 /*! 546 * \brief Request delayed fencing of a target 547 * 548 * \param[in,out] stonith Fencer connection to use 549 * \param[in] call_options Group of enum stonith_call_options 550 * \param[in] node Fence target 551 * \param[in] action "on", "off", or "reboot" 552 * \param[in] timeout Default per-device timeout to use with 553 * each executed device 554 * \param[in] tolerance Accept result of identical fence action 555 * completed within this time 556 * \param[in] delay Execute fencing after this delay (-1 557 * disables any delay from pcmk_delay_base 558 * and pcmk_delay_max) 559 * 560 * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) 561 * on success, otherwise a negative legacy Pacemaker return code 562 */ 563 int (*fence_with_delay)(stonith_t *stonith, int call_options, 564 const char *node, const char *action, int timeout, 565 int tolerance, int delay); 566 567 } stonith_api_operations_t; 568 569 struct stonith_s { 570 enum stonith_state state; 571 int call_id; 572 void *st_private; 573 stonith_api_operations_t *cmds; 574 }; 575 /* *INDENT-ON* */ 576 577 /* Core functions */ 578 stonith_t *stonith_api_new(void); 579 void stonith_api_delete(stonith_t * st); 580 581 void stonith_dump_pending_callbacks(stonith_t * st); 582 583 bool stonith_dispatch(stonith_t * st); 584 585 stonith_key_value_t *stonith_key_value_add(stonith_key_value_t * kvp, const char *key, 586 const char *value); 587 void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values); 588 589 void stonith_history_free(stonith_history_t *history); 590 591 // Convenience functions 592 int stonith_api_connect_retry(stonith_t *st, const char *name, 593 int max_attempts); 594 const char *stonith_op_state_str(enum op_state state); 595 596 /* Basic helpers that allows nodes to be fenced and the history to be 597 * queried without mainloop or the caller understanding the full API 598 * 599 * At least one of nodeid and uname are required 600 * 601 * NOTE: DLM uses both of these 602 */ 603 int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off); 604 time_t stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress); 605 606 /* 607 * Helpers for using the above functions without install-time dependencies 608 * 609 * Usage: 610 * #include <crm/stonith-ng.h> 611 * 612 * To turn a node off by corosync nodeid: 613 * stonith_api_kick_helper(nodeid, 120, 1); 614 * 615 * To check the last fence date/time (also by nodeid): 616 * last = stonith_api_time_helper(nodeid, 0); 617 * 618 * To check if fencing is in progress: 619 * if(stonith_api_time_helper(nodeid, 1) > 0) { ... } 620 * 621 * eg. 622 623 #include <stdio.h> 624 #include <time.h> 625 #include <crm/stonith-ng.h> 626 int 627 main(int argc, char ** argv) 628 { 629 int rc = 0; 630 int nodeid = 102; 631 632 rc = stonith_api_time_helper(nodeid, 0); 633 printf("%d last fenced at %s\n", nodeid, ctime(rc)); 634 635 rc = stonith_api_kick_helper(nodeid, 120, 1); 636 printf("%d fence result: %d\n", nodeid, rc); 637 638 rc = stonith_api_time_helper(nodeid, 0); 639 printf("%d last fenced at %s\n", nodeid, ctime(rc)); 640 641 return 0; 642 } 643 644 */ 645 646 # define STONITH_LIBRARY "libstonithd.so.26" 647 648 typedef int (*st_api_kick_fn) (int nodeid, const char *uname, int timeout, bool off); 649 typedef time_t (*st_api_time_fn) (int nodeid, const char *uname, bool in_progress); 650 651 static inline int 652 stonith_api_kick_helper(uint32_t nodeid, int timeout, bool off) /**/ 653 { 654 static void *st_library = NULL; 655 static st_api_kick_fn st_kick_fn; 656 657 if (st_library == NULL) { 658 st_library = dlopen(STONITH_LIBRARY, RTLD_LAZY); 659 } 660 if (st_library && st_kick_fn == NULL) { 661 st_kick_fn = (st_api_kick_fn) dlsym(st_library, "stonith_api_kick"); 662 } 663 if (st_kick_fn == NULL) { 664 #ifdef ELIBACC 665 return -ELIBACC; 666 #else 667 return -ENOSYS; 668 #endif 669 } 670 671 return (*st_kick_fn) (nodeid, NULL, timeout, off); 672 } 673 674 static inline time_t 675 stonith_api_time_helper(uint32_t nodeid, bool in_progress) /*
*/ 676 { 677 static void *st_library = NULL; 678 static st_api_time_fn st_time_fn; 679 680 if (st_library == NULL) { 681 st_library = dlopen(STONITH_LIBRARY, RTLD_LAZY); 682 } 683 if (st_library && st_time_fn == NULL) { 684 st_time_fn = (st_api_time_fn) dlsym(st_library, "stonith_api_time"); 685 } 686 if (st_time_fn == NULL) { 687 return 0; 688 } 689 690 return (*st_time_fn) (nodeid, NULL, in_progress); 691 } 692 693 /** 694 * Does the given agent describe a stonith resource that can exist? 695 * 696 * \param[in] agent What is the name of the agent? 697 * \param[in] timeout Timeout to use when querying. If 0 is given, 698 * use a default of 120. 699 * 700 * \return A boolean 701 */ 702 bool stonith_agent_exists(const char *agent, int timeout); 703 704 /*! 705 * \brief Turn fence action into a more readable string 706 * 707 * \param[in] action Fence action 708 */ 709 const char *stonith_action_str(const char *action); 710 711 #ifdef __cplusplus 712 } 713 #endif 714 715 #endif