This source file includes following definitions.
- stonith__list_rhcs_agents
- stonith_rhcs_parameter_not_required
- stonith__rhcs_get_metadata
- stonith__rhcs_metadata
- stonith__agent_is_rhcs
- stonith__rhcs_validate
1
2
3
4
5
6
7
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/stonith-ng.h>
20 #include <crm/fencing/internal.h>
21
22 #include "fencing_private.h"
23
24 #define RH_STONITH_PREFIX "fence_"
25
26
27
28
29
30
31
32
33
34 int
35 stonith__list_rhcs_agents(stonith_key_value_t **devices)
36 {
37
38
39 int count = 0, i;
40 struct dirent **namelist;
41 const int file_num = scandir(PCMK__FENCE_BINDIR, &namelist, 0, alphasort);
42
43 #if _POSIX_C_SOURCE < 200809L && !(defined(O_SEARCH) || defined(O_PATH))
44 char buffer[FILENAME_MAX + 1];
45 #elif defined(O_SEARCH)
46 const int dirfd = open(PCMK__FENCE_BINDIR, O_SEARCH);
47 #else
48 const int dirfd = open(PCMK__FENCE_BINDIR, O_PATH);
49 #endif
50
51 for (i = 0; i < file_num; i++) {
52 struct stat prop;
53
54 if (pcmk__starts_with(namelist[i]->d_name, RH_STONITH_PREFIX)) {
55 #if _POSIX_C_SOURCE < 200809L && !(defined(O_SEARCH) || defined(O_PATH))
56 snprintf(buffer, sizeof(buffer), "%s/%s", PCMK__FENCE_BINDIR,
57 namelist[i]->d_name);
58 if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
59 #else
60 if (dirfd == -1) {
61 if (i == 0) {
62 crm_notice("Problem with listing %s directory"
63 CRM_XS "errno=%d", RH_STONITH_PREFIX, errno);
64 }
65 free(namelist[i]);
66 continue;
67 }
68
69
70
71 if (fstatat(dirfd, namelist[i]->d_name, &prop, 0) == 0
72 && S_ISREG(prop.st_mode)) {
73 #endif
74 *devices = stonith_key_value_add(*devices, NULL,
75 namelist[i]->d_name);
76 count++;
77 }
78 }
79 free(namelist[i]);
80 }
81 if (file_num > 0) {
82 free(namelist);
83 }
84 #if _POSIX_C_SOURCE >= 200809L || defined(O_SEARCH) || defined(O_PATH)
85 if (dirfd >= 0) {
86 close(dirfd);
87 }
88 #endif
89 return count;
90 }
91
92 static void
93 stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
94 {
95 char *xpath = NULL;
96 xmlXPathObject *xpathObj = NULL;
97
98 CRM_CHECK(metadata != NULL, return);
99 CRM_CHECK(parameter != NULL, return);
100
101 xpath = crm_strdup_printf("//parameter[@name='%s']", parameter);
102
103
104 xpathObj = xpath_search(metadata, xpath);
105 if (numXpathResults(xpathObj) > 0) {
106 xmlNode *tmp = getXpathResult(xpathObj, 0);
107
108 crm_xml_add(tmp, "required", "0");
109 }
110 freeXpathObject(xpathObj);
111 free(xpath);
112 }
113
114
115
116
117
118
119
120
121 static int
122 stonith__rhcs_get_metadata(const char *agent, int timeout_sec,
123 xmlNode **metadata)
124 {
125 xmlNode *xml = NULL;
126 xmlNode *actions = NULL;
127 xmlXPathObject *xpathObj = NULL;
128 stonith_action_t *action = stonith__action_create(agent, "metadata", NULL,
129 0, timeout_sec, NULL,
130 NULL, NULL);
131 int rc = stonith__execute(action);
132 pcmk__action_result_t *result = stonith__action_result(action);
133
134 if (result == NULL) {
135 if (rc < 0) {
136 crm_warn("Could not execute metadata action for %s: %s "
137 CRM_XS " rc=%d", agent, pcmk_strerror(rc), rc);
138 }
139 stonith__destroy_action(action);
140 return rc;
141 }
142
143 if (result->execution_status != PCMK_EXEC_DONE) {
144 crm_warn("Could not execute metadata action for %s: %s",
145 agent, pcmk_exec_status_str(result->execution_status));
146 rc = pcmk_rc2legacy(stonith__result2rc(result));
147 stonith__destroy_action(action);
148 return rc;
149 }
150
151 if (!pcmk__result_ok(result)) {
152 crm_warn("Metadata action for %s returned error code %d",
153 agent, result->exit_status);
154 rc = pcmk_rc2legacy(stonith__result2rc(result));
155 stonith__destroy_action(action);
156 return rc;
157 }
158
159 if (result->action_stdout == NULL) {
160 crm_warn("Metadata action for %s returned no data", agent);
161 stonith__destroy_action(action);
162 return -ENODATA;
163 }
164
165 xml = string2xml(result->action_stdout);
166 stonith__destroy_action(action);
167
168 if (xml == NULL) {
169 crm_warn("Metadata for %s is invalid", agent);
170 return -pcmk_err_schema_validation;
171 }
172
173 xpathObj = xpath_search(xml, "//actions");
174 if (numXpathResults(xpathObj) > 0) {
175 actions = getXpathResult(xpathObj, 0);
176 }
177 freeXpathObject(xpathObj);
178
179
180 xpathObj = xpath_search(xml, "//action[@name='stop']");
181 if (numXpathResults(xpathObj) <= 0) {
182 xmlNode *tmp = NULL;
183 const char *timeout_str = NULL;
184
185 timeout_str = pcmk__readable_interval(PCMK_DEFAULT_ACTION_TIMEOUT_MS);
186
187 tmp = create_xml_node(actions, "action");
188 crm_xml_add(tmp, "name", PCMK_ACTION_STOP);
189 crm_xml_add(tmp, "timeout", timeout_str);
190
191 tmp = create_xml_node(actions, "action");
192 crm_xml_add(tmp, "name", PCMK_ACTION_START);
193 crm_xml_add(tmp, "timeout", timeout_str);
194 }
195 freeXpathObject(xpathObj);
196
197
198 stonith_rhcs_parameter_not_required(xml, "action");
199 stonith_rhcs_parameter_not_required(xml, "plug");
200 stonith_rhcs_parameter_not_required(xml, "port");
201
202 if (metadata) {
203 *metadata = xml;
204
205 } else {
206 free_xml(xml);
207 }
208
209 return pcmk_ok;
210 }
211
212
213
214
215
216
217
218
219 int
220 stonith__rhcs_metadata(const char *agent, int timeout_sec, char **output)
221 {
222 char *buffer = NULL;
223 xmlNode *xml = NULL;
224
225 int rc = stonith__rhcs_get_metadata(agent, timeout_sec, &xml);
226
227 if (rc != pcmk_ok) {
228 free_xml(xml);
229 return rc;
230 }
231
232 buffer = dump_xml_formatted_with_text(xml);
233 free_xml(xml);
234 if (buffer == NULL) {
235 return -pcmk_err_schema_validation;
236 }
237 if (output) {
238 *output = buffer;
239 } else {
240 free(buffer);
241 }
242 return pcmk_ok;
243 }
244
245 bool
246 stonith__agent_is_rhcs(const char *agent)
247 {
248 struct stat prop;
249 char *buffer = crm_strdup_printf(PCMK__FENCE_BINDIR "/%s", agent);
250 int rc = stat(buffer, &prop);
251
252 free(buffer);
253 return (rc >= 0) && S_ISREG(prop.st_mode);
254 }
255
256 int
257 stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
258 const char *agent, GHashTable *params,
259 const char * host_arg, int timeout,
260 char **output, char **error_output)
261 {
262 int rc = pcmk_ok;
263 int remaining_timeout = timeout;
264 xmlNode *metadata = NULL;
265 stonith_action_t *action = NULL;
266 pcmk__action_result_t *result = NULL;
267
268 if (host_arg == NULL) {
269 time_t start_time = time(NULL);
270
271 rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata);
272
273 if (rc == pcmk_ok) {
274 uint32_t device_flags = 0;
275
276 stonith__device_parameter_flags(&device_flags, agent, metadata);
277 if (pcmk_is_set(device_flags, st_device_supports_parameter_port)) {
278 host_arg = "port";
279
280 } else if (pcmk_is_set(device_flags,
281 st_device_supports_parameter_plug)) {
282 host_arg = "plug";
283 }
284 }
285
286 free_xml(metadata);
287
288 remaining_timeout -= time(NULL) - start_time;
289
290 if (rc == -ETIME || remaining_timeout <= 0 ) {
291 return -ETIME;
292 }
293
294 } else if (pcmk__str_eq(host_arg, PCMK__VALUE_NONE, pcmk__str_casei)) {
295 host_arg = NULL;
296 }
297
298 action = stonith__action_create(agent, PCMK_ACTION_VALIDATE_ALL, target, 0,
299 remaining_timeout, params, NULL, host_arg);
300
301 rc = stonith__execute(action);
302 result = stonith__action_result(action);
303
304 if (result != NULL) {
305 rc = pcmk_rc2legacy(stonith__result2rc(result));
306
307
308 if (output != NULL) {
309 *output = result->action_stdout;
310 result->action_stdout = NULL;
311 }
312 if (error_output != NULL) {
313 *error_output = result->action_stderr;
314 result->action_stderr = NULL;
315 }
316 }
317 stonith__destroy_action(action);
318 return rc;
319 }