This source file includes following definitions.
- handle_level
- notify_callback
- fence_callback
- async_fence_helper
- pcmk__fence_action
- pcmk_fence_action
- pcmk__fence_history
- pcmk_fence_history
- pcmk__fence_installed
- pcmk_fence_installed
- pcmk__fence_last
- pcmk_fence_last
- pcmk__fence_list_targets
- pcmk_fence_list_targets
- pcmk__fence_metadata
- pcmk_fence_metadata
- pcmk__fence_registered
- pcmk_fence_registered
- pcmk__fence_register_level
- pcmk_fence_register_level
- pcmk__fence_unregister_level
- pcmk_fence_unregister_level
- pcmk__fence_validate
- pcmk_fence_validate
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/common/mainloop.h>
12 #include <crm/common/results.h>
13 #include <crm/common/output_internal.h>
14 #include <crm/stonith-ng.h>
15 #include <crm/fencing/internal.h>
16
17 #include <glib.h>
18 #include <libxml/tree.h>
19 #include <pacemaker.h>
20 #include <pcmki/pcmki_output.h>
21 #include <pcmki/pcmki_fence.h>
22
23 static const int st_opts = st_opt_sync_call | st_opt_allow_suicide;
24
25 static GMainLoop *mainloop = NULL;
26
27 static struct {
28 stonith_t *st;
29 const char *target;
30 const char *action;
31 char *name;
32 unsigned int timeout;
33 unsigned int tolerance;
34 int delay;
35 int rc;
36 } async_fence_data;
37
38 static int
39 handle_level(stonith_t *st, char *target, int fence_level,
40 stonith_key_value_t *devices, bool added) {
41 char *node = NULL;
42 char *pattern = NULL;
43 char *name = NULL;
44 char *value = NULL;
45 int rc = pcmk_rc_ok;
46
47 if (target == NULL) {
48
49 return EINVAL;
50 }
51
52
53 value = strchr(target, '=');
54 if (value != NULL) {
55 name = target;
56 *value++ = '\0';
57 } else if (*target == '@') {
58 pattern = target + 1;
59 } else {
60 node = target;
61 }
62
63
64 if (added) {
65 rc = st->cmds->register_level_full(st, st_opts, node, pattern,
66 name, value, fence_level,
67 devices);
68 } else {
69 rc = st->cmds->remove_level_full(st, st_opts, node, pattern,
70 name, value, fence_level);
71 }
72
73 return pcmk_legacy2rc(rc);
74 }
75
76 static void
77 notify_callback(stonith_t * st, stonith_event_t * e)
78 {
79 if (e->result != pcmk_ok) {
80 return;
81 }
82
83 if (pcmk__str_eq(async_fence_data.target, e->target, pcmk__str_casei) &&
84 pcmk__str_eq(async_fence_data.action, e->action, pcmk__str_casei)) {
85
86 async_fence_data.rc = e->result;
87 g_main_loop_quit(mainloop);
88 }
89 }
90
91 static void
92 fence_callback(stonith_t * stonith, stonith_callback_data_t * data)
93 {
94 async_fence_data.rc = data->rc;
95
96 g_main_loop_quit(mainloop);
97 }
98
99 static gboolean
100 async_fence_helper(gpointer user_data)
101 {
102 stonith_t *st = async_fence_data.st;
103 int call_id = 0;
104 int rc = stonith_api_connect_retry(st, async_fence_data.name, 10);
105
106 if (rc != pcmk_ok) {
107 fprintf(stderr, "Could not connect to fencer: %s\n", pcmk_strerror(rc));
108 g_main_loop_quit(mainloop);
109 return TRUE;
110 }
111
112 st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, notify_callback);
113
114 call_id = st->cmds->fence_with_delay(st,
115 st_opt_allow_suicide,
116 async_fence_data.target,
117 async_fence_data.action,
118 async_fence_data.timeout/1000,
119 async_fence_data.tolerance/1000,
120 async_fence_data.delay);
121
122 if (call_id < 0) {
123 g_main_loop_quit(mainloop);
124 return TRUE;
125 }
126
127 st->cmds->register_callback(st,
128 call_id,
129 async_fence_data.timeout/1000,
130 st_opt_timeout_updates, NULL, "callback", fence_callback);
131
132 return TRUE;
133 }
134
135 int
136 pcmk__fence_action(stonith_t *st, const char *target, const char *action,
137 const char *name, unsigned int timeout, unsigned int tolerance,
138 int delay)
139 {
140 crm_trigger_t *trig;
141
142 async_fence_data.st = st;
143 async_fence_data.name = strdup(name);
144 async_fence_data.target = target;
145 async_fence_data.action = action;
146 async_fence_data.timeout = timeout;
147 async_fence_data.tolerance = tolerance;
148 async_fence_data.delay = delay;
149 async_fence_data.rc = pcmk_err_generic;
150
151 trig = mainloop_add_trigger(G_PRIORITY_HIGH, async_fence_helper, NULL);
152 mainloop_set_trigger(trig);
153
154 mainloop = g_main_loop_new(NULL, FALSE);
155 g_main_loop_run(mainloop);
156
157 free(async_fence_data.name);
158
159 return pcmk_legacy2rc(async_fence_data.rc);
160 }
161
162 #ifdef BUILD_PUBLIC_LIBPACEMAKER
163 int
164 pcmk_fence_action(stonith_t *st, const char *target, const char *action,
165 const char *name, unsigned int timeout, unsigned int tolerance,
166 int delay)
167 {
168 return pcmk__fence_action(st, target, action, name, timeout, tolerance, delay);
169 }
170 #endif
171
172 int
173 pcmk__fence_history(pcmk__output_t *out, stonith_t *st, char *target,
174 unsigned int timeout, int verbose, bool broadcast,
175 bool cleanup) {
176 stonith_history_t *history = NULL, *hp, *latest = NULL;
177 int rc = pcmk_rc_ok;
178 int opts = 0;
179
180 if (!out->is_quiet(out)) {
181 if (cleanup) {
182 out->info(out, "cleaning up fencing-history%s%s",
183 target ? " for node " : "", target ? target : "");
184 }
185 if (broadcast) {
186 out->info(out, "gather fencing-history from all nodes");
187 }
188 }
189
190 stonith__set_call_options(opts, target, st_opts);
191 if (cleanup) {
192 stonith__set_call_options(opts, target, st_opt_cleanup);
193 }
194 if (broadcast) {
195 stonith__set_call_options(opts, target, st_opt_broadcast);
196 }
197 rc = st->cmds->history(st, opts,
198 pcmk__str_eq(target, "*", pcmk__str_none)? NULL : target,
199 &history, timeout/1000);
200
201 if (cleanup) {
202
203 stonith_history_free(history);
204 return pcmk_legacy2rc(rc);
205 }
206
207 out->begin_list(out, "event", "events", "Fencing history");
208
209 history = stonith__sort_history(history);
210 for (hp = history; hp; hp = hp->next) {
211 if (hp->state == st_done) {
212 latest = hp;
213 }
214
215 if (out->is_quiet(out) || !verbose) {
216 continue;
217 }
218
219 out->message(out, "stonith-event", hp, 1, stonith__later_succeeded(hp, history));
220 out->increment_list(out);
221 }
222
223 if (latest) {
224 if (out->is_quiet(out)) {
225 out->info(out, "%lld", (long long) latest->completed);
226 } else if (!verbose) {
227 out->message(out, "stonith-event", latest, 0, FALSE);
228 out->increment_list(out);
229 }
230 }
231
232 out->end_list(out);
233
234 stonith_history_free(history);
235 return pcmk_legacy2rc(rc);
236 }
237
238 #ifdef BUILD_PUBLIC_LIBPACEMAKER
239 int
240 pcmk_fence_history(xmlNodePtr *xml, stonith_t *st, char *target, unsigned int timeout,
241 bool quiet, int verbose, bool broadcast, bool cleanup) {
242 pcmk__output_t *out = NULL;
243 int rc = pcmk_rc_ok;
244
245 rc = pcmk__out_prologue(&out, xml);
246 if (rc != pcmk_rc_ok) {
247 return rc;
248 }
249
250 out->quiet = quiet;
251
252 rc = pcmk__fence_history(out, st, target, timeout, verbose, broadcast, cleanup);
253 pcmk__out_epilogue(out, xml, rc);
254 return rc;
255 }
256 #endif
257
258 int
259 pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout) {
260 stonith_key_value_t *devices = NULL;
261 int rc = pcmk_rc_ok;
262
263 rc = st->cmds->list_agents(st, st_opt_sync_call, NULL, &devices, timeout/1000);
264
265 if (rc < 0) {
266 return pcmk_legacy2rc(rc);
267 }
268
269 out->begin_list(out, "fence device", "fence devices", "Installed fence devices");
270 for (stonith_key_value_t *dIter = devices; dIter; dIter = dIter->next) {
271 out->list_item(out, "device", "%s", dIter->value);
272 }
273 out->end_list(out);
274
275 stonith_key_value_freeall(devices, 1, 1);
276 return pcmk_rc_ok;
277 }
278
279 #ifdef BUILD_PUBLIC_LIBPACEMAKER
280 int
281 pcmk_fence_installed(xmlNodePtr *xml, stonith_t *st, unsigned int timeout) {
282 pcmk__output_t *out = NULL;
283 int rc = pcmk_rc_ok;
284
285 rc = pcmk__out_prologue(&out, xml);
286 if (rc != pcmk_rc_ok) {
287 return rc;
288 }
289
290 rc = pcmk__fence_installed(out, st, timeout);
291 pcmk__out_epilogue(out, xml, rc);
292 return rc;
293 }
294 #endif
295
296 int
297 pcmk__fence_last(pcmk__output_t *out, const char *target, bool as_nodeid) {
298 time_t when = 0;
299
300 if (target == NULL) {
301 return pcmk_rc_ok;
302 }
303
304 if (as_nodeid) {
305 when = stonith_api_time(atol(target), NULL, FALSE);
306 } else {
307 when = stonith_api_time(0, target, FALSE);
308 }
309
310 return out->message(out, "last-fenced", target, when);
311 }
312
313 #ifdef BUILD_PUBLIC_LIBPACEMAKER
314 int
315 pcmk_fence_last(xmlNodePtr *xml, const char *target, bool as_nodeid) {
316 pcmk__output_t *out = NULL;
317 int rc = pcmk_rc_ok;
318
319 rc = pcmk__out_prologue(&out, xml);
320 if (rc != pcmk_rc_ok) {
321 return rc;
322 }
323
324 rc = pcmk__fence_last(out, target, as_nodeid);
325 pcmk__out_epilogue(out, xml, rc);
326 return rc;
327 }
328 #endif
329
330 int
331 pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st,
332 const char *device_id, unsigned int timeout) {
333 GList *targets = NULL;
334 char *lists = NULL;
335 int rc = pcmk_rc_ok;
336
337 rc = st->cmds->list(st, st_opts, device_id, &lists, timeout/1000);
338 if (rc != pcmk_rc_ok) {
339 return pcmk_legacy2rc(rc);
340 }
341
342 targets = stonith__parse_targets(lists);
343
344 out->begin_list(out, "fence target", "fence targets", "Fence Targets");
345 while (targets != NULL) {
346 out->list_item(out, NULL, "%s", (const char *) targets->data);
347 targets = targets->next;
348 }
349 out->end_list(out);
350
351 free(lists);
352 return rc;
353 }
354
355 #ifdef BUILD_PUBLIC_LIBPACEMAKER
356 int
357 pcmk_fence_list_targets(xmlNodePtr *xml, stonith_t *st, const char *device_id,
358 unsigned int timeout) {
359 pcmk__output_t *out = NULL;
360 int rc = pcmk_rc_ok;
361
362 rc = pcmk__out_prologue(&out, xml);
363 if (rc != pcmk_rc_ok) {
364 return rc;
365 }
366
367 rc = pcmk__fence_list_targets(out, st, device_id, timeout);
368 pcmk__out_epilogue(out, xml, rc);
369 return rc;
370 }
371 #endif
372
373 int
374 pcmk__fence_metadata(pcmk__output_t *out, stonith_t *st, char *agent,
375 unsigned int timeout) {
376 char *buffer = NULL;
377 int rc = st->cmds->metadata(st, st_opt_sync_call, agent, NULL, &buffer,
378 timeout/1000);
379
380 if (rc != pcmk_rc_ok) {
381 return pcmk_legacy2rc(rc);
382 }
383
384 out->output_xml(out, "metadata", buffer);
385 free(buffer);
386 return rc;
387 }
388
389 #ifdef BUILD_PUBLIC_LIBPACEMAKER
390 int
391 pcmk_fence_metadata(xmlNodePtr *xml, stonith_t *st, char *agent,
392 unsigned int timeout) {
393 pcmk__output_t *out = NULL;
394 int rc = pcmk_rc_ok;
395
396 rc = pcmk__out_prologue(&out, xml);
397 if (rc != pcmk_rc_ok) {
398 return rc;
399 }
400
401 rc = pcmk__fence_metadata(out, st, agent, timeout);
402 pcmk__out_epilogue(out, xml, rc);
403 return rc;
404 }
405 #endif
406
407 int
408 pcmk__fence_registered(pcmk__output_t *out, stonith_t *st, char *target,
409 unsigned int timeout) {
410 stonith_key_value_t *devices = NULL;
411 int rc = pcmk_rc_ok;
412
413 rc = st->cmds->query(st, st_opts, target, &devices, timeout/1000);
414
415 if (rc < 0) {
416 return pcmk_legacy2rc(rc);
417 }
418
419 out->begin_list(out, "fence device", "fence devices", "Registered fence devices");
420 for (stonith_key_value_t *dIter = devices; dIter; dIter = dIter->next) {
421 out->list_item(out, "device", "%s", dIter->value);
422 }
423 out->end_list(out);
424
425 stonith_key_value_freeall(devices, 1, 1);
426
427
428
429
430 return pcmk_rc_ok;
431 }
432
433 #ifdef BUILD_PUBLIC_LIBPACEMAKER
434 int
435 pcmk_fence_registered(xmlNodePtr *xml, stonith_t *st, char *target,
436 unsigned int timeout) {
437 pcmk__output_t *out = NULL;
438 int rc = pcmk_rc_ok;
439
440 rc = pcmk__out_prologue(&out, xml);
441 if (rc != pcmk_rc_ok) {
442 return rc;
443 }
444
445 rc = pcmk__fence_registered(out, st, target, timeout);
446 pcmk__out_epilogue(out, xml, rc);
447 return rc;
448 }
449 #endif
450
451 int
452 pcmk__fence_register_level(stonith_t *st, char *target, int fence_level,
453 stonith_key_value_t *devices) {
454 return handle_level(st, target, fence_level, devices, true);
455 }
456
457 #ifdef BUILD_PUBLIC_LIBPACEMAKER
458 int
459 pcmk_fence_register_level(stonith_t *st, char *target, int fence_level,
460 stonith_key_value_t *devices) {
461 return pcmk__fence_register_level(st, target, fence_level, devices);
462 }
463 #endif
464
465 int
466 pcmk__fence_unregister_level(stonith_t *st, char *target, int fence_level) {
467 return handle_level(st, target, fence_level, NULL, false);
468 }
469
470 #ifdef BUILD_PUBLIC_LIBPACEMAKER
471 int
472 pcmk_fence_unregister_level(stonith_t *st, char *target, int fence_level) {
473 return pcmk__fence_unregister_level(st, target, fence_level);
474 }
475 #endif
476
477 int
478 pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
479 const char *id, stonith_key_value_t *params,
480 unsigned int timeout) {
481 char *output = NULL;
482 char *error_output = NULL;
483 int rc;
484
485 rc = st->cmds->validate(st, st_opt_sync_call, id, NULL, agent, params,
486 timeout/1000, &output, &error_output);
487 out->message(out, "validate", agent, id, output, error_output, rc);
488 return pcmk_legacy2rc(rc);
489 }
490
491 #ifdef BUILD_PUBLIC_LIBPACEMAKER
492 int
493 pcmk_fence_validate(xmlNodePtr *xml, stonith_t *st, const char *agent,
494 const char *id, stonith_key_value_t *params,
495 unsigned int timeout) {
496 pcmk__output_t *out = NULL;
497 int rc = pcmk_rc_ok;
498
499 rc = pcmk__out_prologue(&out, xml);
500 if (rc != pcmk_rc_ok) {
501 return rc;
502 }
503
504 rc = pcmk__fence_validate(out, st, agent, id, params, timeout);
505 pcmk__out_epilogue(out, xml, rc);
506 return rc;
507 }
508 #endif