pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
st_actions.c
Go to the documentation of this file.
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#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#include <glib.h>
20
21#include <crm/crm.h>
22#include <crm/stonith-ng.h>
24#include <crm/common/xml.h>
26
27#include "fencing_private.h"
28
29struct stonith_action_s {
31 char *agent;
32 char *action;
33 GHashTable *args;
34 int timeout;
35 bool async;
36 void *userdata;
37 void (*done_cb) (int pid, const pcmk__action_result_t *result,
38 void *user_data);
39 void (*fork_cb) (int pid, void *user_data);
40
41 svc_action_t *svc_action;
42
44 time_t initial_start_time;
45 int tries;
46 int remaining_timeout;
47 int max_retries;
48
49 int pid;
51};
52
53static int internal_stonith_action_execute(stonith_action_t *action);
54static void log_action(stonith_action_t *action, pid_t pid);
55
63static void
64set_result_from_svc_action(stonith_action_t *action, svc_action_t *svc_action)
65{
66 pcmk__set_result(&(action->result), svc_action->rc, svc_action->status,
67 services__exit_reason(svc_action));
69 services__grab_stdout(svc_action),
70 services__grab_stderr(svc_action));
71}
72
73static void
74log_action(stonith_action_t *action, pid_t pid)
75{
76 /* The services library has already logged the output at info or debug
77 * level, so just raise to warning for stderr.
78 */
79 if (action->result.action_stderr != NULL) {
80 /* Logging the whole string confuses syslog when the string is xml */
81 char *prefix = crm_strdup_printf("%s[%d] stderr:", action->agent, pid);
82
83 crm_log_output(LOG_WARNING, prefix, action->result.action_stderr);
84 free(prefix);
85 }
86}
87
88static void
89append_config_arg(gpointer key, gpointer value, gpointer user_data)
90{
91 /* The fencer will filter "action" out when it registers the device,
92 * but ignore it here in case any external API users don't.
93 *
94 * Also filter out parameters handled directly by Pacemaker.
95 */
96 if (!pcmk__str_eq(key, STONITH_ATTR_ACTION_OP, pcmk__str_casei)
97 && !pcmk_stonith_param(key)
98 && (strstr(key, CRM_META) == NULL)
99 && !pcmk__str_eq(key, PCMK_XA_CRM_FEATURE_SET, pcmk__str_none)) {
100
101 crm_trace("Passing %s=%s with fence action",
102 (const char *) key, (const char *) (value? value : ""));
103 pcmk__insert_dup((GHashTable *) user_data, key, pcmk__s(value, ""));
104 }
105}
106
121static GHashTable *
122make_args(const char *agent, const char *action, const char *target,
123 uint32_t target_nodeid, GHashTable *device_args,
124 GHashTable *port_map, const char *host_arg)
125{
126 GHashTable *arg_list = NULL;
127 const char *value = NULL;
128
129 CRM_CHECK(action != NULL, return NULL);
130
131 arg_list = pcmk__strkey_table(free, free);
132
133 // Add action to arguments (using an alias if requested)
134 if (device_args) {
135 char buffer[512];
136
137 snprintf(buffer, sizeof(buffer), "pcmk_%s_action", action);
138 value = g_hash_table_lookup(device_args, buffer);
139 if (value) {
140 crm_debug("Substituting '%s' for fence action %s targeting %s",
141 value, action, pcmk__s(target, "no node"));
142 action = value;
143 }
144 }
146
147 /* If this is a fencing operation against another node, add more standard
148 * arguments.
149 */
150 if ((target != NULL) && (device_args != NULL)) {
151 const char *param = NULL;
152
153 /* Always pass the target's name, per
154 * https://github.com/ClusterLabs/fence-agents/blob/main/doc/FenceAgentAPI.md
155 */
156 pcmk__insert_dup(arg_list, "nodename", target);
157
158 // If the target's node ID was specified, pass it, too
159 if (target_nodeid != 0) {
160 char *nodeid = crm_strdup_printf("%" PRIu32, target_nodeid);
161
162 // cts-fencing looks for this log message
163 crm_info("Passing '%s' as nodeid with fence action '%s' targeting %s",
164 nodeid, action, pcmk__s(target, "no node"));
165 g_hash_table_insert(arg_list, strdup("nodeid"), nodeid);
166 }
167
168 // Check whether target must be specified in some other way
169 param = g_hash_table_lookup(device_args, PCMK_STONITH_HOST_ARGUMENT);
170 if (!pcmk__str_eq(agent, "fence_legacy", pcmk__str_none)
171 && !pcmk__str_eq(param, PCMK_VALUE_NONE, pcmk__str_casei)) {
172
173 if (param == NULL) {
174 /* Use the caller's default for pcmk_host_argument, or "port" if
175 * none was given
176 */
177 param = (host_arg == NULL)? "port" : host_arg;
178 }
179 value = g_hash_table_lookup(device_args, param);
180
181 if (pcmk__str_eq(value, "dynamic",
183 /* If the host argument was "dynamic" or not explicitly specified,
184 * add it with the target
185 */
186 const char *alias = NULL;
187
188 if (port_map) {
189 alias = g_hash_table_lookup(port_map, target);
190 }
191 if (alias == NULL) {
192 alias = target;
193 }
194 crm_debug("Passing %s='%s' with fence action %s targeting %s",
195 param, alias, action, pcmk__s(target, "no node"));
196 pcmk__insert_dup(arg_list, param, alias);
197 }
198 }
199 }
200
201 if (device_args) {
202 g_hash_table_foreach(device_args, append_config_arg, arg_list);
203 }
204
205 return arg_list;
206}
207
214void
216{
217 if (action) {
218 free(action->agent);
219 if (action->args) {
220 g_hash_table_destroy(action->args);
221 }
222 free(action->action);
223 if (action->svc_action) {
224 services_action_free(action->svc_action);
225 }
226 pcmk__reset_result(&(action->result));
227 free(action);
228 }
229}
230
241{
242 return (action == NULL)? NULL : &(action->result);
243}
244
245#define FAILURE_MAX_RETRIES 2
246
263stonith__action_create(const char *agent, const char *action_name,
264 const char *target, uint32_t target_nodeid,
265 int timeout_sec, GHashTable *device_args,
266 GHashTable *port_map, const char *host_arg)
267{
269
270 action->args = make_args(agent, action_name, target, target_nodeid,
271 device_args, port_map, host_arg);
272 crm_debug("Preparing '%s' action targeting %s using agent %s",
273 action_name, pcmk__s(target, "no node"), agent);
274 action->agent = strdup(agent);
275 action->action = strdup(action_name);
276 action->timeout = action->remaining_timeout = timeout_sec;
277 action->max_retries = FAILURE_MAX_RETRIES;
278
280 "Initialization bug in fencing library");
281
282 if (device_args) {
283 char buffer[512];
284 const char *value = NULL;
285
286 snprintf(buffer, sizeof(buffer), "pcmk_%s_retries", action_name);
287 value = g_hash_table_lookup(device_args, buffer);
288
289 if (value) {
290 action->max_retries = atoi(value);
291 }
292 }
293
294 return action;
295}
296
297static gboolean
298update_remaining_timeout(stonith_action_t * action)
299{
300 int diff = time(NULL) - action->initial_start_time;
301
302 if (action->tries >= action->max_retries) {
303 crm_info("Attempted to execute agent %s (%s) the maximum number of times (%d) allowed",
304 action->agent, action->action, action->max_retries);
305 action->remaining_timeout = 0;
306 } else if ((action->result.execution_status != PCMK_EXEC_TIMEOUT)
307 && (diff < (action->timeout * 0.7))) {
308 /* only set remaining timeout period if there is 30%
309 * or greater of the original timeout period left */
310 action->remaining_timeout = action->timeout - diff;
311 } else {
312 action->remaining_timeout = 0;
313 }
314 return action->remaining_timeout ? TRUE : FALSE;
315}
316
325int
327{
328 if (pcmk__result_ok(result)) {
329 return pcmk_rc_ok;
330 }
331
332 switch (result->execution_status) {
333 case PCMK_EXEC_PENDING: return EINPROGRESS;
334 case PCMK_EXEC_CANCELLED: return ECANCELED;
335 case PCMK_EXEC_TIMEOUT: return ETIME;
336 case PCMK_EXEC_NOT_INSTALLED: return ENOENT;
337 case PCMK_EXEC_NOT_SUPPORTED: return EOPNOTSUPP;
338 case PCMK_EXEC_NOT_CONNECTED: return ENOTCONN;
339 case PCMK_EXEC_NO_FENCE_DEVICE: return ENODEV;
340 case PCMK_EXEC_NO_SECRETS: return EACCES;
341
342 /* For the fencing API, PCMK_EXEC_INVALID is used with fencer API
343 * operations that don't involve executing an agent (for example,
344 * registering devices). This allows us to use the CRM_EX_* codes in the
345 * exit status for finer-grained responses.
346 */
348 switch (result->exit_status) {
349 case CRM_EX_INVALID_PARAM: return EINVAL;
350 case CRM_EX_INSUFFICIENT_PRIV: return EACCES;
351 case CRM_EX_PROTOCOL: return EPROTO;
352
353 /* CRM_EX_EXPIRED is used for orphaned fencing operations left
354 * over from a previous instance of the fencer. For API backward
355 * compatibility, this is mapped to the previously used code for
356 * this case, EHOSTUNREACH.
357 */
358 case CRM_EX_EXPIRED: return EHOSTUNREACH;
359 default: break;
360 }
361 break;
362
363 default:
364 break;
365 }
366
367 // Try to provide useful error code based on result's error output
368
369 if (result->action_stderr == NULL) {
370 return ENODATA;
371
372 } else if (strcasestr(result->action_stderr, "timed out")
373 || strcasestr(result->action_stderr, "timeout")) {
374 return ETIME;
375
376 } else if (strcasestr(result->action_stderr, "unrecognised action")
377 || strcasestr(result->action_stderr, "unrecognized action")
378 || strcasestr(result->action_stderr, "unsupported action")) {
379 return EOPNOTSUPP;
380 }
381
382 // Oh well, we tried
383 return pcmk_rc_error;
384}
385
399int
401{
402 if (rc >= 0) {
403 return PCMK_EXEC_DONE;
404 }
405 switch (-rc) {
406 case EACCES: return PCMK_EXEC_NO_SECRETS;
407 case ECANCELED: return PCMK_EXEC_CANCELLED;
408 case EHOSTUNREACH: return PCMK_EXEC_INVALID;
409 case EINPROGRESS: return PCMK_EXEC_PENDING;
410 case ENODEV: return PCMK_EXEC_NO_FENCE_DEVICE;
411 case ENOENT: return PCMK_EXEC_NOT_INSTALLED;
412 case ENOTCONN: return PCMK_EXEC_NOT_CONNECTED;
413 case EOPNOTSUPP: return PCMK_EXEC_NOT_SUPPORTED;
414 case EPROTO: return PCMK_EXEC_INVALID;
415 case EPROTONOSUPPORT: return PCMK_EXEC_NOT_SUPPORTED;
416 case ETIME: return PCMK_EXEC_TIMEOUT;
417 case ETIMEDOUT: return PCMK_EXEC_TIMEOUT;
418 default: return PCMK_EXEC_ERROR;
419 }
420}
421
429void
431{
432 int exit_status = CRM_EX_OK;
433 enum pcmk_exec_status execution_status = PCMK_EXEC_DONE;
434 const char *exit_reason = NULL;
435 const char *action_stdout = NULL;
436 int rc = pcmk_ok;
437
438 CRM_CHECK(xml != NULL, return);
439
440 if (result != NULL) {
441 exit_status = result->exit_status;
442 execution_status = result->execution_status;
443 exit_reason = result->exit_reason;
444 action_stdout = result->action_stdout;
446 }
447
448 crm_xml_add_int(xml, PCMK__XA_OP_STATUS, (int) execution_status);
449 crm_xml_add_int(xml, PCMK__XA_RC_CODE, exit_status);
450 crm_xml_add(xml, PCMK_XA_EXIT_REASON, exit_reason);
451 crm_xml_add(xml, PCMK__XA_ST_OUTPUT, action_stdout);
452
453 /* @COMPAT Peers in rolling upgrades, Pacemaker Remote nodes, and external
454 * code that use libstonithd <=2.1.2 don't check for the full result, and
455 * need a legacy return code instead.
456 */
458}
459
468xmlNode *
470{
471 xmlNode *match = get_xpath_object("//@" PCMK__XA_RC_CODE, xml, LOG_NEVER);
472
473 if (match == NULL) {
474 /* @COMPAT Peers <=2.1.2 in a rolling upgrade provide only a legacy
475 * return code, not a full result, so check for that.
476 */
477 match = get_xpath_object("//@" PCMK__XA_ST_RC, xml, LOG_ERR);
478 }
479 return match;
480}
481
489void
491{
492 int exit_status = CRM_EX_OK;
493 int execution_status = PCMK_EXEC_DONE;
494 const char *exit_reason = NULL;
495 char *action_stdout = NULL;
496
497 CRM_CHECK((xml != NULL) && (result != NULL), return);
498
499 exit_reason = crm_element_value(xml, PCMK_XA_EXIT_REASON);
500 action_stdout = crm_element_value_copy(xml, PCMK__XA_ST_OUTPUT);
501
502 // A result must include an exit status and execution status
503 if ((crm_element_value_int(xml, PCMK__XA_RC_CODE, &exit_status) < 0)
505 &execution_status) < 0)) {
506 int rc = pcmk_ok;
507 exit_status = CRM_EX_ERROR;
508
509 /* @COMPAT Peers <=2.1.2 in rolling upgrades provide only a legacy
510 * return code, not a full result, so check for that.
511 */
512 if (crm_element_value_int(xml, PCMK__XA_ST_RC, &rc) == 0) {
513 if ((rc == pcmk_ok) || (rc == -EINPROGRESS)) {
514 exit_status = CRM_EX_OK;
515 }
516 execution_status = stonith__legacy2status(rc);
517 exit_reason = pcmk_strerror(rc);
518
519 } else {
520 execution_status = PCMK_EXEC_ERROR;
521 exit_reason = "Fencer reply contained neither a full result "
522 "nor a legacy return code (bug?)";
523 }
524 }
525 pcmk__set_result(result, exit_status, execution_status, exit_reason);
526 pcmk__set_result_output(result, action_stdout, NULL);
527}
528
529static void
530stonith_action_async_done(svc_action_t *svc_action)
531{
533
534 set_result_from_svc_action(action, svc_action);
535 svc_action->params = NULL;
536 log_action(action, action->pid);
537
538 if (!pcmk__result_ok(&(action->result))
539 && update_remaining_timeout(action)) {
540
541 int rc = internal_stonith_action_execute(action);
542 if (rc == pcmk_ok) {
543 return;
544 }
545 }
546
547 if (action->done_cb) {
548 action->done_cb(action->pid, &(action->result), action->userdata);
549 }
550
551 action->svc_action = NULL; // don't remove our caller
553}
554
555static void
556stonith_action_async_forked(svc_action_t *svc_action)
557{
559
560 action->pid = svc_action->pid;
561 action->svc_action = svc_action;
562
563 if (action->fork_cb) {
564 (action->fork_cb) (svc_action->pid, action->userdata);
565 }
566
568 NULL);
569
570 crm_trace("Child process %d performing action '%s' successfully forked",
571 action->pid, action->action);
572}
573
574static int
575internal_stonith_action_execute(stonith_action_t * action)
576{
577 int rc = -EPROTO;
578 int is_retry = 0;
579 svc_action_t *svc_action = NULL;
580 static int stonith_sequence = 0;
581 char *buffer = NULL;
582
583 CRM_CHECK(action != NULL, return -EINVAL);
584
585 if ((action->action == NULL) || (action->args == NULL)
586 || (action->agent == NULL)) {
588 PCMK_EXEC_ERROR_FATAL, "Bug in fencing library");
589 return -EINVAL;
590 }
591
592 if (!action->tries) {
593 action->initial_start_time = time(NULL);
594 }
595 action->tries++;
596
597 if (action->tries > 1) {
598 crm_info("Attempt %d to execute %s (%s). remaining timeout is %d",
599 action->tries, action->agent, action->action, action->remaining_timeout);
600 is_retry = 1;
601 }
602
604 basename(action->agent));
605 svc_action = services_action_create_generic(buffer, NULL);
606 free(buffer);
607
608 if (svc_action->rc != PCMK_OCF_UNKNOWN) {
609 set_result_from_svc_action(action, svc_action);
610 services_action_free(svc_action);
611 return -E2BIG;
612 }
613
614 svc_action->timeout = 1000 * action->remaining_timeout;
615 svc_action->standard = strdup(PCMK_RESOURCE_CLASS_STONITH);
616 svc_action->id = crm_strdup_printf("%s_%s_%dof%d", basename(action->agent),
617 action->action, action->tries,
618 action->max_retries);
619 svc_action->agent = strdup(action->agent);
620 svc_action->sequence = stonith_sequence++;
621 svc_action->params = action->args;
622 svc_action->cb_data = (void *) action;
623 svc_action->flags = pcmk__set_flags_as(__func__, __LINE__,
624 LOG_TRACE, "Action",
625 svc_action->id, svc_action->flags,
627 "SVC_ACTION_NON_BLOCKED");
628
629 /* keep retries from executing out of control and free previous results */
630 if (is_retry) {
631 pcmk__reset_result(&(action->result));
632 sleep(1);
633 }
634
635 if (action->async) {
636 // We never create a recurring action, so this should always return TRUE
638 &stonith_action_async_done,
639 &stonith_action_async_forked));
640 return pcmk_ok;
641
642 } else if (services_action_sync(svc_action)) { // sync success
643 rc = pcmk_ok;
644
645 } else { // sync failure
646 rc = -ECONNABORTED;
647 }
648
649 set_result_from_svc_action(action, svc_action);
650 svc_action->params = NULL;
651 services_action_free(svc_action);
652 return rc;
653}
654
666int
668 void (*done) (int pid,
670 void *user_data),
671 void (*fork_cb) (int pid, void *user_data))
672{
673 if (!action) {
674 return -EINVAL;
675 }
676
677 action->userdata = userdata;
678 action->done_cb = done;
679 action->fork_cb = fork_cb;
680 action->async = true;
681
682 return internal_stonith_action_execute(action);
683}
684
693int
695{
696 int rc = pcmk_ok;
697
698 CRM_CHECK(action != NULL, return -EINVAL);
699
700 // Keep trying until success, max retries, or timeout
701 do {
702 rc = internal_stonith_action_execute(action);
703 } while ((rc != pcmk_ok) && update_remaining_timeout(action));
704
705 return rc;
706}
#define PCMK_STONITH_HOST_ARGUMENT
Definition agents.h:44
bool pcmk_stonith_param(const char *param)
Check whether a given stonith parameter is handled by Pacemaker.
Definition agents.c:175
#define PCMK_RESOURCE_CLASS_STONITH
Definition agents.h:31
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define PCMK__FENCE_BINDIR
Definition config.h:556
uint32_t pid
Definition cpg.c:1
A dumping ground.
#define CRM_META
Definition crm.h:81
struct stonith_action_s stonith_action_t
Definition internal.h:51
#define STONITH_ATTR_ACTION_OP
Definition internal.h:110
#define crm_info(fmt, args...)
Definition logging.h:397
#define crm_log_output(level, prefix, output)
Definition logging.h:115
#define CRM_LOG_ASSERT(expr)
Definition logging.h:228
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define LOG_NEVER
Definition logging.h:48
#define crm_trace(fmt, args...)
Definition logging.h:402
#define LOG_TRACE
Definition logging.h:38
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition nvpair.c:482
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition nvpair.c:348
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition nvpair.c:674
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:301
#define PCMK_VALUE_NONE
Definition options.h:178
unsigned int timeout
Definition pcmk_fence.c:32
const char * action
Definition pcmk_fence.c:30
pcmk__action_result_t result
Definition pcmk_fence.c:35
const char * target
Definition pcmk_fence.c:29
#define ENODATA
#define ETIME
const char * pcmk_strerror(int rc)
Definition results.c:149
@ CRM_EX_PROTOCOL
Protocol violated.
Definition results.h:281
@ CRM_EX_ERROR
Unspecified error.
Definition results.h:256
@ CRM_EX_EXPIRED
Requested item has expired.
Definition results.h:296
@ CRM_EX_OK
Success.
Definition results.h:255
@ CRM_EX_INVALID_PARAM
Parameter invalid (in local context)
Definition results.h:259
@ CRM_EX_INSUFFICIENT_PRIV
Insufficient privileges.
Definition results.h:261
@ PCMK_OCF_UNKNOWN_ERROR
Unspecified error.
Definition results.h:181
@ PCMK_OCF_UNKNOWN
Action is pending.
Definition results.h:203
@ pcmk_rc_ok
Definition results.h:162
@ pcmk_rc_error
Definition results.h:157
#define pcmk_ok
Definition results.h:69
int pcmk_rc2legacy(int rc)
Definition results.c:546
pcmk_exec_status
Execution status.
Definition results.h:330
@ PCMK_EXEC_CANCELLED
Action was cancelled.
Definition results.h:334
@ PCMK_EXEC_NO_SECRETS
Necessary CIB secrets are unavailable.
Definition results.h:344
@ PCMK_EXEC_ERROR_FATAL
Execution failed, do not retry anywhere.
Definition results.h:339
@ PCMK_EXEC_NOT_INSTALLED
Agent or dependency not available locally.
Definition results.h:340
@ PCMK_EXEC_INVALID
Action cannot be attempted (e.g. shutdown)
Definition results.h:342
@ PCMK_EXEC_DONE
Action completed, result is known.
Definition results.h:333
@ PCMK_EXEC_ERROR
Execution failed, may be retried.
Definition results.h:337
@ PCMK_EXEC_NOT_SUPPORTED
Agent does not implement requested action.
Definition results.h:336
@ PCMK_EXEC_TIMEOUT
Action did not complete in time.
Definition results.h:335
@ PCMK_EXEC_PENDING
Action is in progress.
Definition results.h:332
@ PCMK_EXEC_UNKNOWN
Used only to initialize variables.
Definition results.h:331
@ PCMK_EXEC_NO_FENCE_DEVICE
No fence device is configured for target.
Definition results.h:343
@ PCMK_EXEC_NOT_CONNECTED
No connection to executor.
Definition results.h:341
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:976
void void pcmk__set_result_output(pcmk__action_result_t *result, char *out, char *err)
Definition results.c:1045
void pcmk__reset_result(pcmk__action_result_t *result)
Definition results.c:1065
@ SVC_ACTION_NON_BLOCKED
Definition services.h:104
gboolean services_action_sync(svc_action_t *op)
Definition services.c:1018
void services_action_free(svc_action_t *op)
Definition services.c:583
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
Request execution of an arbitrary command.
Definition services.c:356
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:865
char * services__grab_stdout(svc_action_t *action)
Definition services.c:1390
const char * services__exit_reason(const svc_action_t *action)
Definition services.c:1374
char * services__grab_stderr(svc_action_t *action)
Definition services.c:1409
int stonith__legacy2status(int rc)
Definition st_actions.c:400
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:667
void stonith__destroy_action(stonith_action_t *action)
Definition st_actions.c:215
stonith_action_t * stonith__action_create(const char *agent, const char *action_name, const char *target, uint32_t target_nodeid, int timeout_sec, GHashTable *device_args, GHashTable *port_map, const char *host_arg)
Definition st_actions.c:263
pcmk__action_result_t * stonith__action_result(stonith_action_t *action)
Definition st_actions.c:240
xmlNode * stonith__find_xe_with_result(xmlNode *xml)
Definition st_actions.c:469
int stonith__execute(stonith_action_t *action)
Definition st_actions.c:694
void stonith__xe_get_result(const xmlNode *xml, pcmk__action_result_t *result)
Definition st_actions.c:490
#define FAILURE_MAX_RETRIES
Definition st_actions.c:245
int stonith__result2rc(const pcmk__action_result_t *result)
Definition st_actions.c:326
void stonith__xe_set_result(xmlNode *xml, const pcmk__action_result_t *result)
Definition st_actions.c:430
Fencing aka. STONITH.
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:701
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:683
@ pcmk__str_none
@ pcmk__str_null_matches
@ pcmk__str_casei
enum pcmk_exec_status execution_status
Object for executing external actions.
Definition services.h:122
char * id
Definition services.h:126
void * cb_data
For caller's use (not used by library)
Definition services.h:179
char * agent
Resource agent name for resource actions, otherwise NULL.
Definition services.h:144
char * standard
Resource standard for resource actions, otherwise NULL.
Definition services.h:138
int rc
Exit status of action (set by library upon completion)
Definition services.h:155
enum svc_action_flags flags
Flag group of enum svc_action_flags.
Definition services.h:176
GHashTable * params
Definition services.h:153
int timeout
Action timeout (in milliseconds)
Definition services.h:146
int status
Execution status (enum pcmk_exec_status set by library)
Definition services.h:163
Wrappers for and extensions to libxml2.
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:189
#define PCMK_XA_CRM_FEATURE_SET
Definition xml_names.h:249
#define PCMK_XA_EXIT_REASON
Definition xml_names.h:269
#define PCMK__XA_ST_OUTPUT
#define PCMK__XA_OP_STATUS
#define PCMK__XA_ST_RC
#define PCMK__XA_RC_CODE