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