This source file includes following definitions.
- rhcs_agent_filter
- 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 <dirent.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/stat.h>
16
17 #include <glib.h>
18 #include <libxml/xpath.h>
19
20 #include <crm/crm.h>
21 #include <crm/common/xml.h>
22 #include <crm/stonith-ng.h>
23 #include <crm/fencing/internal.h>
24
25 #include "fencing_private.h"
26
27
28
29
30
31
32
33
34
35
36 static int
37 rhcs_agent_filter(const struct dirent *entry)
38 {
39 char *buf = NULL;
40 struct stat sb;
41 int rc = 0;
42
43 if (!pcmk__starts_with(entry->d_name, "fence_")) {
44 goto done;
45 }
46
47
48 buf = crm_strdup_printf(PCMK__FENCE_BINDIR "/%s", entry->d_name);
49 if ((stat(buf, &sb) != 0) || !S_ISREG(sb.st_mode)) {
50 goto done;
51 }
52
53 rc = 1;
54
55 done:
56 free(buf);
57 return rc;
58 }
59
60
61
62
63
64
65
66
67
68 int
69 stonith__list_rhcs_agents(stonith_key_value_t **devices)
70 {
71 struct dirent **namelist = NULL;
72 const int file_num = scandir(PCMK__FENCE_BINDIR, &namelist,
73 rhcs_agent_filter, alphasort);
74
75 if (file_num < 0) {
76 int rc = errno;
77
78 crm_err("Could not list " PCMK__FENCE_BINDIR ": %s", pcmk_rc_str(rc));
79 free(namelist);
80 return 0;
81 }
82
83 for (int i = 0; i < file_num; i++) {
84 *devices = stonith__key_value_add(*devices, NULL, namelist[i]->d_name);
85 free(namelist[i]);
86 }
87 free(namelist);
88 return file_num;
89 }
90
91 static void
92 stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
93 {
94 char *xpath = NULL;
95 xmlXPathObject *xpathObj = NULL;
96
97 CRM_CHECK(metadata != NULL, return);
98 CRM_CHECK(parameter != NULL, return);
99
100 xpath = crm_strdup_printf("//" PCMK_XE_PARAMETER "[@" PCMK_XA_NAME "='%s']",
101 parameter);
102
103
104 xpathObj = pcmk__xpath_search(metadata->doc, xpath);
105 if (pcmk__xpath_num_results(xpathObj) > 0) {
106 xmlNode *tmp = pcmk__xpath_result(xpathObj, 0);
107
108 if (tmp != NULL) {
109 crm_xml_add(tmp, "required", "0");
110 }
111 }
112 xmlXPathFreeObject(xpathObj);
113 free(xpath);
114 }
115
116
117
118
119
120
121
122
123 static int
124 stonith__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;
130 stonith_action_t *action = stonith__action_create(agent,
131 PCMK_ACTION_METADATA,
132 NULL, timeout_sec, NULL,
133 NULL, NULL);
134 int rc = stonith__execute(action);
135 pcmk__action_result_t *result = stonith__action_result(action);
136
137 if (result == NULL) {
138 if (rc < 0) {
139 crm_warn("Could not execute metadata action for %s: %s "
140 QB_XS " rc=%d", agent, pcmk_strerror(rc), rc);
141 }
142 stonith__destroy_action(action);
143 return rc;
144 }
145
146 if (result->execution_status != PCMK_EXEC_DONE) {
147 crm_warn("Could not execute metadata action for %s: %s",
148 agent, pcmk_exec_status_str(result->execution_status));
149 rc = pcmk_rc2legacy(stonith__result2rc(result));
150 stonith__destroy_action(action);
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);
157 rc = pcmk_rc2legacy(stonith__result2rc(result));
158 stonith__destroy_action(action);
159 return rc;
160 }
161
162 if (result->action_stdout == NULL) {
163 crm_warn("Metadata action for %s returned no data", agent);
164 stonith__destroy_action(action);
165 return -ENODATA;
166 }
167
168 xml = pcmk__xml_parse(result->action_stdout);
169 stonith__destroy_action(action);
170
171 if (xml == NULL) {
172 crm_warn("Metadata for %s is invalid", agent);
173 return -pcmk_err_schema_validation;
174 }
175
176 xpathObj = pcmk__xpath_search(xml->doc, "//" PCMK_XE_ACTIONS);
177 if (pcmk__xpath_num_results(xpathObj) > 0) {
178 actions = pcmk__xpath_result(xpathObj, 0);
179 }
180 xmlXPathFreeObject(xpathObj);
181
182
183 xpathObj = pcmk__xpath_search(xml->doc,
184 "//" PCMK_XE_ACTION
185 "[@" PCMK_XA_NAME "='" PCMK_ACTION_STOP "']");
186 if (pcmk__xpath_num_results(xpathObj) == 0) {
187 xmlNode *tmp = NULL;
188 const char *timeout_str = NULL;
189
190 timeout_str = pcmk__readable_interval(PCMK_DEFAULT_ACTION_TIMEOUT_MS);
191
192 tmp = pcmk__xe_create(actions, PCMK_XE_ACTION);
193 crm_xml_add(tmp, PCMK_XA_NAME, PCMK_ACTION_STOP);
194 crm_xml_add(tmp, PCMK_META_TIMEOUT, timeout_str);
195
196 tmp = pcmk__xe_create(actions, PCMK_XE_ACTION);
197 crm_xml_add(tmp, PCMK_XA_NAME, PCMK_ACTION_START);
198 crm_xml_add(tmp, PCMK_META_TIMEOUT, timeout_str);
199 }
200 xmlXPathFreeObject(xpathObj);
201
202
203 stonith_rhcs_parameter_not_required(xml, STONITH_ATTR_ACTION_OP);
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 pcmk__xml_free(xml);
212 }
213
214 return pcmk_ok;
215 }
216
217
218
219
220
221
222
223
224 int
225 stonith__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);
237 pcmk__xml_string(xml, pcmk__xml_fmt_pretty|pcmk__xml_fmt_text, buffer, 0);
238
239 if (pcmk__str_empty(buffer->str)) {
240 rc = -pcmk_err_schema_validation;
241 goto done;
242 }
243
244 if (output != NULL) {
245 pcmk__str_update(output, buffer->str);
246 }
247
248 done:
249 if (buffer != NULL) {
250 g_string_free(buffer, TRUE);
251 }
252 pcmk__xml_free(xml);
253 return rc;
254 }
255
256 bool
257 stonith__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
267 int
268 stonith__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;
277 pcmk__action_result_t *result = 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 host_arg = stonith__default_host_arg(metadata);
286 crm_trace("Using '%s' as default " PCMK_STONITH_HOST_ARGUMENT
287 " for %s",
288 pcmk__s(host_arg, PCMK_VALUE_NONE), agent);
289 }
290
291 pcmk__xml_free(metadata);
292
293 remaining_timeout -= time(NULL) - start_time;
294
295 if (rc == -ETIME || remaining_timeout <= 0 ) {
296 return -ETIME;
297 }
298
299 } else if (pcmk__str_eq(host_arg, PCMK_VALUE_NONE, pcmk__str_casei)) {
300 host_arg = NULL;
301 }
302
303 action = stonith__action_create(agent, PCMK_ACTION_VALIDATE_ALL, target,
304 remaining_timeout, params, NULL, host_arg);
305
306 rc = stonith__execute(action);
307 result = stonith__action_result(action);
308
309 if (result != NULL) {
310 rc = pcmk_rc2legacy(stonith__result2rc(result));
311
312
313 if (output != NULL) {
314 *output = result->action_stdout;
315 result->action_stdout = NULL;
316 }
317 if (error_output != NULL) {
318 *error_output = result->action_stderr;
319 result->action_stderr = NULL;
320 }
321 }
322 stonith__destroy_action(action);
323 return rc;
324 }