pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
st_actions.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-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 Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdbool.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <libgen.h>
17#include <inttypes.h>
18#include <sys/types.h>
19
20#include <glib.h>
21#include <libxml/tree.h> // xmlNode
22
23#include <crm/crm.h>
24#include <crm/stonith-ng.h>
26#include <crm/common/xml.h>
28
29#include "fencing_private.h"
30
31struct stonith_action_s {
33 char *agent;
34 char *action;
35 GHashTable *args;
36 int timeout;
37 bool async;
38 void *userdata;
39 void (*done_cb) (int pid, const pcmk__action_result_t *result,
40 void *user_data);
41 void (*fork_cb) (int pid, void *user_data);
42
43 svc_action_t *svc_action;
44
46 time_t initial_start_time;
47 int tries;
48 int remaining_timeout;
49 int max_retries;
50
51 int pid;
53};
54
55static int internal_stonith_action_execute(stonith_action_t *action);
56static void log_action(stonith_action_t *action, pid_t pid);
57
65static void
66set_result_from_svc_action(stonith_action_t *action, svc_action_t *svc_action)
67{
68 services__copy_result(svc_action, &(action->result));
70 services__grab_stdout(svc_action),
71 services__grab_stderr(svc_action));
72}
73
74static void
75log_action(stonith_action_t *action, pid_t pid)
76{
77 /* The services library has already logged the output at info or debug
78 * level, so just raise to warning for stderr.
79 */
80 if (action->result.action_stderr != NULL) {
81 /* Logging the whole string confuses syslog when the string is xml */
82 char *prefix = crm_strdup_printf("%s[%d] stderr:", action->agent, pid);
83
84 crm_log_output(LOG_WARNING, prefix, action->result.action_stderr);
85 free(prefix);
86 }
87}
88
89static void
90append_config_arg(gpointer key, gpointer value, gpointer user_data)
91{
92 /* Filter out parameters handled directly by Pacemaker.
93 *
94 * STONITH_ATTR_ACTION_OP is added elsewhere and should never be part of the
95 * fencing resource's parameter list. We should ignore its value if it is
96 * configured there.
97 */
98 if (!pcmk__str_eq(key, STONITH_ATTR_ACTION_OP, pcmk__str_casei)
99 && !pcmk_stonith_param(key)
100 && (strstr(key, CRM_META) == NULL)
101 && !pcmk__str_eq(key, PCMK_XA_CRM_FEATURE_SET, pcmk__str_none)) {
102
103 crm_trace("Passing %s=%s with fence action",
104 (const char *) key, (const char *) (value? value : ""));
105 pcmk__insert_dup((GHashTable *) user_data, key, pcmk__s(value, ""));
106 }
107}
108
122static GHashTable *
123make_args(const char *agent, const char *action, const char *target,
124 GHashTable *device_args, GHashTable *port_map,
125 const char *default_host_arg)
126{
127 GHashTable *arg_list = NULL;
128 const char *value = NULL;
129
130 CRM_CHECK(action != NULL, return NULL);
131
132 arg_list = pcmk__strkey_table(free, free);
133
134 // Add action to arguments (using an alias if requested)
135 if (device_args) {
136 char buffer[512];
137
138 snprintf(buffer, sizeof(buffer), "pcmk_%s_action", action);
139 value = g_hash_table_lookup(device_args, buffer);
140 if (value) {
141 crm_debug("Substituting '%s' for fence action %s targeting %s",
142 value, action, pcmk__s(target, "no node"));
143 action = value;
144 }
145 }
146
147 // Tell the fence agent what action to perform
149
150 /* If this is a fencing operation against another node, add more standard
151 * arguments.
152 */
153 if ((target != NULL) && (device_args != NULL)) {
154 const char *param = NULL;
155
156 /* Always pass the target's name, per
157 * https://github.com/ClusterLabs/fence-agents/blob/main/doc/FenceAgentAPI.md
158 */
159 pcmk__insert_dup(arg_list, "nodename", target);
160
161 // Check whether target should be specified as some other argument
162 param = g_hash_table_lookup(device_args, PCMK_STONITH_HOST_ARGUMENT);
163 if (param == NULL) {
164 // Use caller's default (likely from agent metadata)
165 param = default_host_arg;
166 }
167 if ((param != NULL)
168 && !pcmk__str_eq(agent, "fence_legacy", pcmk__str_none)
169 && !pcmk__str_eq(param, PCMK_VALUE_NONE, pcmk__str_casei)) {
170
171 value = g_hash_table_lookup(device_args, param);
172 if (pcmk__str_eq(value, "dynamic",
174 /* If the host argument is "dynamic" or not configured,
175 * reset it to the target
176 */
177 const char *alias = NULL;
178
179 if (port_map) {
180 alias = g_hash_table_lookup(port_map, target);
181 }
182 if (alias == NULL) {
183 alias = target;
184 }
185 crm_debug("Passing %s='%s' with fence action %s targeting %s",
186 param, alias, action, pcmk__s(target, "no node"));
187 pcmk__insert_dup(arg_list, param, alias);
188 }
189 }
190 }
191
192 if (device_args) {
193 g_hash_table_foreach(device_args, append_config_arg, arg_list);
194 }
195
196 return arg_list;
197}
198
205void
207{
208 if (action) {
209 free(action->agent);
210 if (action->args) {
211 g_hash_table_destroy(action->args);
212 }
213 free(action->action);
214 if (action->svc_action) {
215 services_action_free(action->svc_action);
216 }
217 pcmk__reset_result(&(action->result));
218 free(action);
219 }
220}
221
232{
233 return (action == NULL)? NULL : &(action->result);
234}
235
236#define FAILURE_MAX_RETRIES 2
237
253stonith__action_create(const char *agent, const char *action_name,
254 const char *target, int timeout_sec,
255 GHashTable *device_args, GHashTable *port_map,
256 const char *default_host_arg)
257{
259
260 action->args = make_args(agent, action_name, target, device_args, port_map,
261 default_host_arg);
262 crm_debug("Preparing '%s' action targeting %s using agent %s",
263 action_name, pcmk__s(target, "no node"), agent);
264 action->agent = strdup(agent);
265 action->action = strdup(action_name);
266 action->timeout = action->remaining_timeout = timeout_sec;
267 action->max_retries = FAILURE_MAX_RETRIES;
268
270 "Initialization bug in fencing library");
271
272 if (device_args) {
273 char buffer[512];
274 const char *value = NULL;
275
276 snprintf(buffer, sizeof(buffer), "pcmk_%s_retries", action_name);
277 value = g_hash_table_lookup(device_args, buffer);
278
279 if (value) {
280 action->max_retries = atoi(value);
281 }
282 }
283
284 return action;
285}
286
287static gboolean
288update_remaining_timeout(stonith_action_t * action)
289{
290 int diff = time(NULL) - action->initial_start_time;
291
292 if (action->tries >= action->max_retries) {
293 crm_info("Attempted to execute agent %s (%s) the maximum number of times (%d) allowed",
294 action->agent, action->action, action->max_retries);
295 action->remaining_timeout = 0;
296 } else if ((action->result.execution_status != PCMK_EXEC_TIMEOUT)
297 && (diff < (action->timeout * 0.7))) {
298 /* only set remaining timeout period if there is 30%
299 * or greater of the original timeout period left */
300 action->remaining_timeout = action->timeout - diff;
301 } else {
302 action->remaining_timeout = 0;
303 }
304 return action->remaining_timeout ? TRUE : FALSE;
305}
306
315int
317{
318 if (pcmk__result_ok(result)) {
319 return pcmk_rc_ok;
320 }
321
322 switch (result->execution_status) {
323 case PCMK_EXEC_PENDING: return EINPROGRESS;
324 case PCMK_EXEC_CANCELLED: return ECANCELED;
325 case PCMK_EXEC_TIMEOUT: return ETIME;
326 case PCMK_EXEC_NOT_INSTALLED: return ENOENT;
327 case PCMK_EXEC_NOT_SUPPORTED: return EOPNOTSUPP;
328 case PCMK_EXEC_NOT_CONNECTED: return ENOTCONN;
329 case PCMK_EXEC_NO_FENCE_DEVICE: return ENODEV;
330 case PCMK_EXEC_NO_SECRETS: return EACCES;
331
332 /* For the fencing API, PCMK_EXEC_INVALID is used with fencer API
333 * operations that don't involve executing an agent (for example,
334 * registering devices). This allows us to use the CRM_EX_* codes in the
335 * exit status for finer-grained responses.
336 */
338 switch (result->exit_status) {
339 case CRM_EX_INVALID_PARAM: return EINVAL;
340 case CRM_EX_INSUFFICIENT_PRIV: return EACCES;
341 case CRM_EX_PROTOCOL: return EPROTO;
342
343 /* CRM_EX_EXPIRED is used for orphaned fencing operations left
344 * over from a previous instance of the fencer. For API backward
345 * compatibility, this is mapped to the previously used code for
346 * this case, EHOSTUNREACH.
347 */
348 case CRM_EX_EXPIRED: return EHOSTUNREACH;
349 default: break;
350 }
351 break;
352
353 default:
354 break;
355 }
356
357 // Try to provide useful error code based on result's error output
358
359 if (result->action_stderr == NULL) {
360 return ENODATA;
361
362 } else if (strcasestr(result->action_stderr, "timed out")
363 || strcasestr(result->action_stderr, "timeout")) {
364 return ETIME;
365
366 } else if (strcasestr(result->action_stderr, "unrecognised action")
367 || strcasestr(result->action_stderr, "unrecognized action")
368 || strcasestr(result->action_stderr, "unsupported action")) {
369 return EOPNOTSUPP;
370 }
371
372 // Oh well, we tried
373 return pcmk_rc_error;
374}
375
389int
391{
392 if (rc >= 0) {
393 return PCMK_EXEC_DONE;
394 }
395 switch (-rc) {
396 case EACCES: return PCMK_EXEC_NO_SECRETS;
397 case ECANCELED: return PCMK_EXEC_CANCELLED;
398 case EHOSTUNREACH: return PCMK_EXEC_INVALID;
399 case EINPROGRESS: return PCMK_EXEC_PENDING;
400 case ENODEV: return PCMK_EXEC_NO_FENCE_DEVICE;
401 case ENOENT: return PCMK_EXEC_NOT_INSTALLED;
402 case ENOTCONN: return PCMK_EXEC_NOT_CONNECTED;
403 case EOPNOTSUPP: return PCMK_EXEC_NOT_SUPPORTED;
404 case EPROTO: return PCMK_EXEC_INVALID;
405 case EPROTONOSUPPORT: return PCMK_EXEC_NOT_SUPPORTED;
406 case ETIME: return PCMK_EXEC_TIMEOUT;
407 case ETIMEDOUT: return PCMK_EXEC_TIMEOUT;
408 default: return PCMK_EXEC_ERROR;
409 }
410}
411
419void
421{
422 int exit_status = CRM_EX_OK;
423 enum pcmk_exec_status execution_status = PCMK_EXEC_DONE;
424 const char *exit_reason = NULL;
425 const char *action_stdout = NULL;
426 int rc = pcmk_ok;
427
428 CRM_CHECK(xml != NULL, return);
429
430 if (result != NULL) {
431 exit_status = result->exit_status;
432 execution_status = result->execution_status;
433 exit_reason = result->exit_reason;
434 action_stdout = result->action_stdout;
436 }
437
438 crm_xml_add_int(xml, PCMK__XA_OP_STATUS, (int) execution_status);
439 crm_xml_add_int(xml, PCMK__XA_RC_CODE, exit_status);
440 crm_xml_add(xml, PCMK_XA_EXIT_REASON, exit_reason);
441 crm_xml_add(xml, PCMK__XA_ST_OUTPUT, action_stdout);
442
443 /* @COMPAT Peers in rolling upgrades, Pacemaker Remote nodes, and external
444 * code that use libstonithd <=2.1.2 don't check for the full result, and
445 * need a legacy return code instead.
446 */
448}
449
458xmlNode *
460{
461 xmlNode *match = pcmk__xpath_find_one(xml->doc,
462 "//*[@" PCMK__XA_RC_CODE "]",
463 LOG_NEVER);
464
465 if (match == NULL) {
466 /* @COMPAT Peers <=2.1.2 in a rolling upgrade provide only a legacy
467 * return code, not a full result, so check for that.
468 */
469 match = pcmk__xpath_find_one(xml->doc, "//*[@" PCMK__XA_ST_RC "]",
470 LOG_ERR);
471 }
472 return match;
473}
474
482void
484{
485 int exit_status = CRM_EX_OK;
486 int execution_status = PCMK_EXEC_DONE;
487 const char *exit_reason = NULL;
488 char *action_stdout = NULL;
489
490 CRM_CHECK((xml != NULL) && (result != NULL), return);
491
492 exit_reason = crm_element_value(xml, PCMK_XA_EXIT_REASON);
493 action_stdout = crm_element_value_copy(xml, PCMK__XA_ST_OUTPUT);
494
495 // A result must include an exit status and execution status
496 if ((crm_element_value_int(xml, PCMK__XA_RC_CODE, &exit_status) < 0)
498 &execution_status) < 0)) {
499 int rc = pcmk_ok;
500 exit_status = CRM_EX_ERROR;
501
502 /* @COMPAT Peers <=2.1.2 in rolling upgrades provide only a legacy
503 * return code, not a full result, so check for that.
504 */
505 if (crm_element_value_int(xml, PCMK__XA_ST_RC, &rc) == 0) {
506 if ((rc == pcmk_ok) || (rc == -EINPROGRESS)) {
507 exit_status = CRM_EX_OK;
508 }
509 execution_status = stonith__legacy2status(rc);
510 exit_reason = pcmk_strerror(rc);
511
512 } else {
513 execution_status = PCMK_EXEC_ERROR;
514 exit_reason = "Fencer reply contained neither a full result "
515 "nor a legacy return code (bug?)";
516 }
517 }
518 pcmk__set_result(result, exit_status, execution_status, exit_reason);
519 pcmk__set_result_output(result, action_stdout, NULL);
520}
521
522static void
523stonith_action_async_done(svc_action_t *svc_action)
524{
526
527 set_result_from_svc_action(action, svc_action);
528 svc_action->params = NULL;
529 log_action(action, action->pid);
530
531 if (!pcmk__result_ok(&(action->result))
532 && update_remaining_timeout(action)) {
533
534 int rc = internal_stonith_action_execute(action);
535 if (rc == pcmk_ok) {
536 return;
537 }
538 }
539
540 if (action->done_cb) {
541 action->done_cb(action->pid, &(action->result), action->userdata);
542 }
543
544 action->svc_action = NULL; // don't remove our caller
546}
547
548static void
549stonith_action_async_forked(svc_action_t *svc_action)
550{
552
553 action->pid = svc_action->pid;
554 action->svc_action = svc_action;
555
556 if (action->fork_cb) {
557 (action->fork_cb) (svc_action->pid, action->userdata);
558 }
559
561 NULL);
562
563 crm_trace("Child process %d performing action '%s' successfully forked",
564 action->pid, action->action);
565}
566
576static svc_action_t *
577stonith_action_to_svc(stonith_action_t *action)
578{
579 static int stonith_sequence = 0;
580
581 char *path = crm_strdup_printf(PCMK__FENCE_BINDIR "/%s", action->agent);
583
584 free(path);
585 if (svc_action->rc != PCMK_OCF_UNKNOWN) {
586 set_result_from_svc_action(action, svc_action);
587 services_action_free(svc_action);
588 return NULL;
589 }
590
591 svc_action->timeout = action->remaining_timeout * 1000;
593 svc_action->id = crm_strdup_printf("%s_%s_%dof%d", action->agent,
594 action->action, action->tries,
595 action->max_retries);
596 svc_action->agent = pcmk__str_copy(action->agent);
597 svc_action->sequence = stonith_sequence++;
598 svc_action->params = action->args;
599 svc_action->cb_data = (void *) action;
600 svc_action->flags = pcmk__set_flags_as(__func__, __LINE__,
601 LOG_TRACE, "Action",
602 svc_action->id, svc_action->flags,
604 "SVC_ACTION_NON_BLOCKED");
605
606 return svc_action;
607}
608
609static int
610internal_stonith_action_execute(stonith_action_t * action)
611{
612 int rc = pcmk_ok;
613 int is_retry = 0;
614 svc_action_t *svc_action = NULL;
615
616 CRM_CHECK(action != NULL, return -EINVAL);
617
618 if ((action->action == NULL) || (action->args == NULL)
619 || (action->agent == NULL)) {
621 PCMK_EXEC_ERROR_FATAL, "Bug in fencing library");
622 return -EINVAL;
623 }
624
625 if (action->tries++ == 0) {
626 // First attempt of the desired action
627 action->initial_start_time = time(NULL);
628 } else {
629 // Later attempt after earlier failure
630 crm_info("Attempt %d to execute '%s' action of agent %s "
631 "(%ds timeout remaining)",
632 action->tries, action->action, action->agent,
633 action->remaining_timeout);
634 is_retry = 1;
635 }
636
637 svc_action = stonith_action_to_svc(action);
638 if (svc_action == NULL) {
639 // The only possible errors are out-of-memory and too many arguments
640 return -E2BIG;
641 }
642
643 /* keep retries from executing out of control and free previous results */
644 if (is_retry) {
645 pcmk__reset_result(&(action->result));
646 // @TODO This should be nonblocking via timer if mainloop is used
647 sleep(1);
648 }
649
650 if (action->async) {
651 // We never create a recurring action, so this should always return TRUE
653 &stonith_action_async_done,
654 &stonith_action_async_forked));
655 return pcmk_ok;
656
657 } else if (!services_action_sync(svc_action)) {
658 rc = -ECONNABORTED; // @TODO Update API to return more useful error
659 }
660
661 set_result_from_svc_action(action, svc_action);
662 svc_action->params = NULL;
663 services_action_free(svc_action);
664 return rc;
665}
666
678int
680 void (*done) (int pid,
682 void *user_data),
683 void (*fork_cb) (int pid, void *user_data))
684{
685 if (!action) {
686 return -EINVAL;
687 }
688
689 action->userdata = userdata;
690 action->done_cb = done;
691 action->fork_cb = fork_cb;
692 action->async = true;
693
694 return internal_stonith_action_execute(action);
695}
696
705int
707{
708 int rc = pcmk_ok;
709
710 CRM_CHECK(action != NULL, return -EINVAL);
711
712 // Keep trying until success, max retries, or timeout
713 do {
714 rc = internal_stonith_action_execute(action);
715 } while ((rc != pcmk_ok) && update_remaining_timeout(action));
716
717 return rc;
718}
#define PCMK_STONITH_HOST_ARGUMENT
Definition agents.h:40
bool pcmk_stonith_param(const char *param)
Check whether a given stonith parameter is handled by Pacemaker.
Definition agents.c:166
#define PCMK_RESOURCE_CLASS_STONITH
Definition agents.h:31
const char * path
Definition cib.c:28
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:246
#define PCMK__FENCE_BINDIR
Definition config.h:487
uint32_t pid
Definition cpg.c:1
A dumping ground.
#define CRM_META
Definition crm.h:75
struct stonith_action_s stonith_action_t
Definition internal.h:55
#define STONITH_ATTR_ACTION_OP
Definition internal.h:111
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_log_output(level, prefix, output)
Definition logging.h:83
#define CRM_LOG_ASSERT(expr)
Definition logging.h:196
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_debug(fmt, args...)
Definition logging.h:368
#define LOG_NEVER
Definition logging.h:48
#define crm_trace(fmt, args...)
Definition logging.h:370
#define LOG_TRACE
Definition logging.h:38
#define PCMK_VALUE_NONE
Definition options.h:180
const char * action
Definition pcmk_fence.c:32
pcmk__action_result_t result
Definition pcmk_fence.c:37
const char * target
Definition pcmk_fence.c:31
#define ENODATA
Definition portability.h:61
#define ETIME
Definition portability.h:66
const char * pcmk_strerror(int rc)
Definition results.c:257
@ CRM_EX_PROTOCOL
Protocol violated.
Definition results.h:259
@ CRM_EX_ERROR
Unspecified error.
Definition results.h:234
@ CRM_EX_EXPIRED
Requested item has expired.
Definition results.h:274
@ CRM_EX_OK
Success.
Definition results.h:233
@ CRM_EX_INVALID_PARAM
Parameter invalid (in local context)
Definition results.h:237
@ CRM_EX_INSUFFICIENT_PRIV
Insufficient privileges.
Definition results.h:239
@ PCMK_OCF_UNKNOWN_ERROR
Unspecified error.
Definition results.h:177
@ PCMK_OCF_UNKNOWN
Action is pending.
Definition results.h:199
@ pcmk_rc_ok
Definition results.h:159
@ pcmk_rc_error
Definition results.h:154
#define pcmk_ok
Definition results.h:65
int pcmk_rc2legacy(int rc)
Definition results.c:662
pcmk_exec_status
Execution status.
Definition results.h:308
@ PCMK_EXEC_CANCELLED
Action was cancelled.
Definition results.h:312
@ PCMK_EXEC_NO_SECRETS
Necessary CIB secrets are unavailable.
Definition results.h:322
@ PCMK_EXEC_ERROR_FATAL
Execution failed, do not retry anywhere.
Definition results.h:317
@ PCMK_EXEC_NOT_INSTALLED
Agent or dependency not available locally.
Definition results.h:318
@ PCMK_EXEC_INVALID
Action cannot be attempted (e.g. shutdown)
Definition results.h:320
@ PCMK_EXEC_DONE
Action completed, result is known.
Definition results.h:311
@ PCMK_EXEC_ERROR
Execution failed, may be retried.
Definition results.h:315
@ PCMK_EXEC_NOT_SUPPORTED
Agent does not implement requested action.
Definition results.h:314
@ PCMK_EXEC_TIMEOUT
Action did not complete in time.
Definition results.h:313
@ PCMK_EXEC_PENDING
Action is in progress.
Definition results.h:310
@ PCMK_EXEC_UNKNOWN
Used only to initialize variables.
Definition results.h:309
@ PCMK_EXEC_NO_FENCE_DEVICE
No fence device is configured for target.
Definition results.h:321
@ PCMK_EXEC_NOT_CONNECTED
No connection to executor.
Definition results.h:319
void pcmk__set_result(pcmk__action_result_t *result, int exit_status, enum pcmk_exec_status exec_status, const char *exit_reason)
Definition results.c:1088
void void pcmk__set_result_output(pcmk__action_result_t *result, char *out, char *err)
Definition results.c:1157
void pcmk__reset_result(pcmk__action_result_t *result)
Definition results.c:1177
@ SVC_ACTION_NON_BLOCKED
Definition services.h:81
gboolean services_action_sync(svc_action_t *op)
Definition services.c:996
void services_action_free(svc_action_t *op)
Definition services.c:566
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
Request execution of an arbitrary command.
Definition services.c:350
gboolean services_action_async_fork_notify(svc_action_t *op, void(*action_callback)(svc_action_t *), void(*action_fork_callback)(svc_action_t *))
Run an action asynchronously, with callback after process is forked.
Definition services.c:846
char * services__grab_stdout(svc_action_t *action)
Definition services.c:1353
void services__copy_result(const svc_action_t *action, pcmk__action_result_t *result)
Definition services.c:1243
char * services__grab_stderr(svc_action_t *action)
Definition services.c:1372
int stonith__legacy2status(int rc)
Definition st_actions.c:390
int stonith__execute_async(stonith_action_t *action, void *userdata, void(*done)(int pid, const pcmk__action_result_t *result, void *user_data), void(*fork_cb)(int pid, void *user_data))
Definition st_actions.c:679
void stonith__destroy_action(stonith_action_t *action)
Definition st_actions.c:206
stonith_action_t * stonith__action_create(const char *agent, const char *action_name, const char *target, int timeout_sec, GHashTable *device_args, GHashTable *port_map, const char *default_host_arg)
Definition st_actions.c:253
pcmk__action_result_t * stonith__action_result(stonith_action_t *action)
Definition st_actions.c:231
xmlNode * stonith__find_xe_with_result(xmlNode *xml)
Definition st_actions.c:459
int stonith__execute(stonith_action_t *action)
Definition st_actions.c:706
void stonith__xe_get_result(const xmlNode *xml, pcmk__action_result_t *result)
Definition st_actions.c:483
#define FAILURE_MAX_RETRIES
Definition st_actions.c:236
int stonith__result2rc(const pcmk__action_result_t *result)
Definition st_actions.c:316
void stonith__xe_set_result(xmlNode *xml, const pcmk__action_result_t *result)
Definition st_actions.c:420
Fencing aka. STONITH.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:703
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:685
@ pcmk__str_none
@ pcmk__str_null_matches
@ pcmk__str_casei
#define pcmk__str_copy(str)
enum pcmk_exec_status execution_status
Object for executing external actions.
Definition services.h:99
char * id
Definition services.h:103
void * cb_data
For caller's use (not used by library)
Definition services.h:156
char * agent
Resource agent name for resource actions, otherwise NULL.
Definition services.h:121
char * standard
Resource standard for resource actions, otherwise NULL.
Definition services.h:115
int rc
Exit status of action (set by library upon completion)
Definition services.h:132
enum svc_action_flags flags
Flag group of enum svc_action_flags.
Definition services.h:153
GHashTable * params
Definition services.h:130
int timeout
Action timeout (in milliseconds)
Definition services.h:123
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#define PCMK_XA_CRM_FEATURE_SET
Definition xml_names.h:254
#define PCMK_XA_EXIT_REASON
Definition xml_names.h:274
#define PCMK__XA_ST_OUTPUT
#define PCMK__XA_OP_STATUS
#define PCMK__XA_ST_RC
#define PCMK__XA_RC_CODE
xmlNode * pcmk__xpath_find_one(xmlDoc *doc, const char *path, uint8_t level)
Definition xpath.c:206