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)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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