pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
st_rhcs.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 <stdio.h>
13#include <string.h>
14#include <sys/stat.h>
15#include <glib.h>
16#include <dirent.h>
17
18#include <crm/crm.h>
19#include <crm/common/xml.h>
20#include <crm/stonith-ng.h>
22
23#include "fencing_private.h"
24
25#define RH_STONITH_PREFIX "fence_"
26
35int
37{
38 // Essentially: ls -1 @sbin_dir@/fence_*
39
40 int count = 0, i;
41 struct dirent **namelist;
42 const int file_num = scandir(PCMK__FENCE_BINDIR, &namelist, 0, alphasort);
43
44#if _POSIX_C_SOURCE < 200809L && !(defined(O_SEARCH) || defined(O_PATH))
45 char buffer[FILENAME_MAX + 1];
46#elif defined(O_SEARCH)
47 const int dirfd = open(PCMK__FENCE_BINDIR, O_SEARCH);
48#else
49 const int dirfd = open(PCMK__FENCE_BINDIR, O_PATH);
50#endif
51
52 for (i = 0; i < file_num; i++) {
53 struct stat prop;
54
55 if (pcmk__starts_with(namelist[i]->d_name, RH_STONITH_PREFIX)) {
56#if _POSIX_C_SOURCE < 200809L && !(defined(O_SEARCH) || defined(O_PATH))
57 snprintf(buffer, sizeof(buffer), "%s/%s", PCMK__FENCE_BINDIR,
58 namelist[i]->d_name);
59 if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
60#else
61 if (dirfd == -1) {
62 if (i == 0) {
63 crm_notice("Problem with listing %s directory"
64 CRM_XS "errno=%d", RH_STONITH_PREFIX, errno);
65 }
66 free(namelist[i]);
67 continue;
68 }
69 /* note: we can possibly prevent following symlinks here,
70 which may be a good idea, but fall on the nose when
71 these agents are moved elsewhere & linked back */
72 if (fstatat(dirfd, namelist[i]->d_name, &prop, 0) == 0
73 && S_ISREG(prop.st_mode)) {
74#endif
75 *devices = stonith_key_value_add(*devices, NULL,
76 namelist[i]->d_name);
77 count++;
78 }
79 }
80 free(namelist[i]);
81 }
82 if (file_num > 0) {
83 free(namelist);
84 }
85#if _POSIX_C_SOURCE >= 200809L || defined(O_SEARCH) || defined(O_PATH)
86 if (dirfd >= 0) {
87 close(dirfd);
88 }
89#endif
90 return count;
91}
92
93static void
94stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
95{
96 char *xpath = NULL;
97 xmlXPathObject *xpathObj = NULL;
98
99 CRM_CHECK(metadata != NULL, return);
100 CRM_CHECK(parameter != NULL, return);
101
102 xpath = crm_strdup_printf("//" PCMK_XE_PARAMETER "[@" PCMK_XA_NAME "='%s']",
103 parameter);
104 /* Fudge metadata so that the parameter isn't required in config
105 * Pacemaker handles and adds it */
106 xpathObj = xpath_search(metadata, xpath);
107 if (numXpathResults(xpathObj) > 0) {
108 xmlNode *tmp = getXpathResult(xpathObj, 0);
109
110 crm_xml_add(tmp, "required", "0");
111 }
112 freeXpathObject(xpathObj);
113 free(xpath);
114}
115
123static int
124stonith__rhcs_get_metadata(const char *agent, int timeout_sec,
125 xmlNode **metadata)
126{
127 xmlNode *xml = NULL;
128 xmlNode *actions = NULL;
129 xmlXPathObject *xpathObj = NULL;
132 NULL, 0, timeout_sec,
133 NULL, NULL, NULL);
134 int rc = stonith__execute(action);
136
137 if (result == NULL) {
138 if (rc < 0) {
139 crm_warn("Could not execute metadata action for %s: %s "
140 CRM_XS " rc=%d", agent, pcmk_strerror(rc), rc);
141 }
143 return rc;
144 }
145
147 crm_warn("Could not execute metadata action for %s: %s",
148 agent, pcmk_exec_status_str(result->execution_status));
151 return rc;
152 }
153
154 if (!pcmk__result_ok(result)) {
155 crm_warn("Metadata action for %s returned error code %d",
156 agent, result->exit_status);
159 return rc;
160 }
161
162 if (result->action_stdout == NULL) {
163 crm_warn("Metadata action for %s returned no data", agent);
165 return -ENODATA;
166 }
167
170
171 if (xml == NULL) {
172 crm_warn("Metadata for %s is invalid", agent);
174 }
175
176 xpathObj = xpath_search(xml, "//" PCMK_XE_ACTIONS);
177 if (numXpathResults(xpathObj) > 0) {
178 actions = getXpathResult(xpathObj, 0);
179 }
180 freeXpathObject(xpathObj);
181
182 // Add start and stop (implemented by pacemaker, not agent) to meta-data
183 xpathObj = xpath_search(xml,
184 "//" PCMK_XE_ACTION
185 "[@" PCMK_XA_NAME "='" PCMK_ACTION_STOP "']");
186 if (numXpathResults(xpathObj) <= 0) {
187 xmlNode *tmp = NULL;
188 const char *timeout_str = NULL;
189
191
192 tmp = pcmk__xe_create(actions, PCMK_XE_ACTION);
194 crm_xml_add(tmp, PCMK_META_TIMEOUT, timeout_str);
195
196 tmp = pcmk__xe_create(actions, PCMK_XE_ACTION);
198 crm_xml_add(tmp, PCMK_META_TIMEOUT, timeout_str);
199 }
200 freeXpathObject(xpathObj);
201
202 // Fudge metadata so parameters are not required in config (pacemaker adds them)
203 stonith_rhcs_parameter_not_required(xml, "action");
204 stonith_rhcs_parameter_not_required(xml, "plug");
205 stonith_rhcs_parameter_not_required(xml, "port");
206
207 if (metadata) {
208 *metadata = xml;
209
210 } else {
211 free_xml(xml);
212 }
213
214 return pcmk_ok;
215}
216
224int
225stonith__rhcs_metadata(const char *agent, int timeout_sec, char **output)
226{
227 GString *buffer = NULL;
228 xmlNode *xml = NULL;
229
230 int rc = stonith__rhcs_get_metadata(agent, timeout_sec, &xml);
231
232 if (rc != pcmk_ok) {
233 goto done;
234 }
235
236 buffer = g_string_sized_new(1024);
238
239 if (pcmk__str_empty(buffer->str)) {
241 goto done;
242 }
243
244 if (output != NULL) {
245 pcmk__str_update(output, buffer->str);
246 }
247
248done:
249 if (buffer != NULL) {
250 g_string_free(buffer, TRUE);
251 }
252 free_xml(xml);
253 return rc;
254}
255
256bool
257stonith__agent_is_rhcs(const char *agent)
258{
259 struct stat prop;
260 char *buffer = crm_strdup_printf(PCMK__FENCE_BINDIR "/%s", agent);
261 int rc = stat(buffer, &prop);
262
263 free(buffer);
264 return (rc >= 0) && S_ISREG(prop.st_mode);
265}
266
267int
268stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
269 const char *agent, GHashTable *params,
270 const char * host_arg, int timeout,
271 char **output, char **error_output)
272{
273 int rc = pcmk_ok;
274 int remaining_timeout = timeout;
275 xmlNode *metadata = NULL;
276 stonith_action_t *action = NULL;
278
279 if (host_arg == NULL) {
280 time_t start_time = time(NULL);
281
282 rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata);
283
284 if (rc == pcmk_ok) {
285 uint32_t device_flags = 0;
286
287 stonith__device_parameter_flags(&device_flags, agent, metadata);
289 host_arg = "port";
290
291 } else if (pcmk_is_set(device_flags,
293 host_arg = "plug";
294 }
295 }
296
297 free_xml(metadata);
298
299 remaining_timeout -= time(NULL) - start_time;
300
301 if (rc == -ETIME || remaining_timeout <= 0 ) {
302 return -ETIME;
303 }
304
305 } else if (pcmk__str_eq(host_arg, PCMK_VALUE_NONE, pcmk__str_casei)) {
306 host_arg = NULL;
307 }
308
310 remaining_timeout, params, NULL, host_arg);
311
314
315 if (result != NULL) {
317
318 // Take ownership of output so stonith__destroy_action() doesn't free it
319 if (output != NULL) {
320 *output = result->action_stdout;
321 result->action_stdout = NULL;
322 }
323 if (error_output != NULL) {
324 *error_output = result->action_stderr;
325 result->action_stderr = NULL;
326 }
327 }
329 return rc;
330}
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_METADATA
Definition actions.h:57
#define PCMK_ACTION_START
Definition actions.h:72
#define PCMK_DEFAULT_ACTION_TIMEOUT_MS
Default timeout (in milliseconds) for non-metadata actions.
Definition actions.h:38
#define PCMK_ACTION_VALIDATE_ALL
Definition actions.h:77
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
#define PCMK__FENCE_BINDIR
Definition config.h:556
A dumping ground.
@ st_device_supports_parameter_port
Definition internal.h:25
@ st_device_supports_parameter_plug
Definition internal.h:24
void stonith__destroy_action(stonith_action_t *action)
Definition st_actions.c:215
void stonith__device_parameter_flags(uint32_t *device_flags, const char *device_name, xmlNode *metadata)
Definition st_client.c:2404
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
struct stonith_action_s stonith_action_t
Definition internal.h:51
int stonith__result2rc(const pcmk__action_result_t *result)
Definition st_actions.c:326
G_GNUC_INTERNAL int stonith__execute(stonith_action_t *action)
Definition st_actions.c:694
const char * pcmk__readable_interval(guint interval_ms)
Definition iso8601.c:2134
#define crm_warn(fmt, args...)
Definition logging.h:392
#define CRM_XS
Definition logging.h:56
#define crm_notice(fmt, args...)
Definition logging.h:395
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
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
#define PCMK_META_TIMEOUT
Definition options.h:114
unsigned int timeout
Definition pcmk_fence.c:32
stonith_t * st
Definition pcmk_fence.c:28
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
#define pcmk_err_schema_validation
Definition results.h:75
#define pcmk_ok
Definition results.h:69
int pcmk_rc2legacy(int rc)
Definition results.c:546
@ PCMK_EXEC_DONE
Action completed, result is known.
Definition results.h:333
bool stonith__agent_is_rhcs(const char *agent)
Definition st_rhcs.c:257
int stonith__rhcs_validate(stonith_t *st, int call_options, const char *target, const char *agent, GHashTable *params, const char *host_arg, int timeout, char **output, char **error_output)
Definition st_rhcs.c:268
#define RH_STONITH_PREFIX
Definition st_rhcs.c:25
int stonith__rhcs_metadata(const char *agent, int timeout_sec, char **output)
Retrieve metadata for RHCS-compatible fence agent.
Definition st_rhcs.c:225
int stonith__list_rhcs_agents(stonith_key_value_t **devices)
Definition st_rhcs.c:36
Fencing aka. STONITH.
stonith_key_value_t * stonith_key_value_add(stonith_key_value_t *kvp, const char *key, const char *value)
Definition st_client.c:1932
bool pcmk__starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition strings.c:556
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1277
@ pcmk__str_casei
enum pcmk_exec_status execution_status
Wrappers for and extensions to libxml2.
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition xpath.c:58
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition xpath.c:39
void free_xml(xmlNode *child)
Definition xml.c:867
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
Definition xpath.c:139
@ pcmk__xml_fmt_pretty
Include indentation and newlines.
@ pcmk__xml_fmt_text
Include XML text nodes.
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition xml.c:720
void pcmk__xml_string(const xmlNode *data, uint32_t options, GString *buffer, int depth)
Definition xml_io.c:488
xmlNode * pcmk__xml_parse(const char *input)
Definition xml_io.c:244
#define PCMK_XE_ACTIONS
Definition xml_names.h:61
#define PCMK_XE_ACTION
Definition xml_names.h:60
#define PCMK_XA_NAME
Definition xml_names.h:325
#define PCMK_XE_PARAMETER
Definition xml_names.h:155