This source file includes following definitions.
- st_ipc_accept
- st_ipc_dispatch
- st_ipc_closed
- st_ipc_destroy
- stonith_peer_callback
- stonith_peer_ais_callback
- stonith_peer_cs_destroy
- do_local_reply
- get_stonith_flag
- stonith_notify_client
- do_stonith_async_timeout_update
- fenced_send_notification
- send_config_notification
- fenced_send_device_notification
- fenced_send_level_notification
- topology_remove_helper
- remove_cib_device
- remove_topology_level
- add_topology_level
- remove_fencing_topology
- register_fencing_topology
- fencing_topology_init
- our_node_allowed_for
- watchdog_device_update
- update_stonith_watchdog_timeout_ms
- cib_device_update
- cib_devices_update
- update_cib_stonith_devices_v2
- update_cib_stonith_devices_v1
- update_cib_stonith_devices
- node_has_attr
- node_does_watchdog_fencing
- update_fencing_topology
- update_cib_cache_cb
- init_cib_cache_cb
- stonith_shutdown
- cib_connection_destroy
- stonith_cleanup
- stand_alone_cpg_cb
- setup_cib
- st_peer_update_callback
- fencer_metadata
- build_arg_context
- main
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <unistd.h>
17 #include <sys/utsname.h>
18
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23
24 #include <crm/crm.h>
25 #include <crm/msg_xml.h>
26 #include <crm/common/cmdline_internal.h>
27 #include <crm/common/ipc.h>
28 #include <crm/common/ipc_internal.h>
29 #include <crm/common/output_internal.h>
30 #include <crm/cluster/internal.h>
31
32 #include <crm/stonith-ng.h>
33 #include <crm/fencing/internal.h>
34 #include <crm/common/xml.h>
35 #include <crm/common/xml_internal.h>
36
37 #include <crm/common/mainloop.h>
38
39 #include <crm/cib/internal.h>
40 #include <crm/pengine/status.h>
41 #include <pacemaker-internal.h>
42
43 #include <pacemaker-fenced.h>
44
45 #define SUMMARY "daemon for executing fencing devices in a Pacemaker cluster"
46
47 char *stonith_our_uname = NULL;
48 long stonith_watchdog_timeout_ms = 0;
49 GList *stonith_watchdog_targets = NULL;
50
51 static GMainLoop *mainloop = NULL;
52
53 gboolean stand_alone = FALSE;
54 static gboolean stonith_shutdown_flag = FALSE;
55
56 static qb_ipcs_service_t *ipcs = NULL;
57 static xmlNode *local_cib = NULL;
58 static pe_working_set_t *fenced_data_set = NULL;
59 static const unsigned long long data_set_flags = pe_flag_quick_location
60 | pe_flag_no_compat
61 | pe_flag_no_counts;
62
63 static cib_t *cib_api = NULL;
64
65 static pcmk__output_t *logger_out = NULL;
66 static pcmk__output_t *out = NULL;
67
68 pcmk__supported_format_t formats[] = {
69 PCMK__SUPPORTED_FORMAT_NONE,
70 PCMK__SUPPORTED_FORMAT_TEXT,
71 PCMK__SUPPORTED_FORMAT_XML,
72 { NULL, NULL, NULL }
73 };
74
75 static struct {
76 bool no_cib_connect;
77 gchar **log_files;
78 } options;
79
80 static crm_exit_t exit_code = CRM_EX_OK;
81
82 static void stonith_shutdown(int nsig);
83 static void stonith_cleanup(void);
84
85 static int32_t
86 st_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
87 {
88 if (stonith_shutdown_flag) {
89 crm_info("Ignoring new client [%d] during shutdown",
90 pcmk__client_pid(c));
91 return -EPERM;
92 }
93
94 if (pcmk__new_client(c, uid, gid) == NULL) {
95 return -EIO;
96 }
97 return 0;
98 }
99
100
101 static int32_t
102 st_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
103 {
104 uint32_t id = 0;
105 uint32_t flags = 0;
106 int call_options = 0;
107 xmlNode *request = NULL;
108 pcmk__client_t *c = pcmk__find_client(qbc);
109 const char *op = NULL;
110
111 if (c == NULL) {
112 crm_info("Invalid client: %p", qbc);
113 return 0;
114 }
115
116 request = pcmk__client_data2xml(c, data, &id, &flags);
117 if (request == NULL) {
118 pcmk__ipc_send_ack(c, id, flags, "nack", NULL, CRM_EX_PROTOCOL);
119 return 0;
120 }
121
122
123 op = crm_element_value(request, F_CRM_TASK);
124 if(pcmk__str_eq(op, CRM_OP_RM_NODE_CACHE, pcmk__str_casei)) {
125 crm_xml_add(request, F_TYPE, T_STONITH_NG);
126 crm_xml_add(request, F_STONITH_OPERATION, op);
127 crm_xml_add(request, F_STONITH_CLIENTID, c->id);
128 crm_xml_add(request, F_STONITH_CLIENTNAME, pcmk__client_name(c));
129 crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname);
130
131 send_cluster_message(NULL, crm_msg_stonith_ng, request, FALSE);
132 free_xml(request);
133 return 0;
134 }
135
136 if (c->name == NULL) {
137 const char *value = crm_element_value(request, F_STONITH_CLIENTNAME);
138
139 if (value == NULL) {
140 value = "unknown";
141 }
142 c->name = crm_strdup_printf("%s.%u", value, c->pid);
143 }
144
145 crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options);
146 crm_trace("Flags %#08" PRIx32 "/%#08x for command %" PRIu32
147 " from client %s", flags, call_options, id, pcmk__client_name(c));
148
149 if (pcmk_is_set(call_options, st_opt_sync_call)) {
150 CRM_ASSERT(flags & crm_ipc_client_response);
151 CRM_LOG_ASSERT(c->request_id == 0);
152 c->request_id = id;
153 }
154
155 crm_xml_add(request, F_STONITH_CLIENTID, c->id);
156 crm_xml_add(request, F_STONITH_CLIENTNAME, pcmk__client_name(c));
157 crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname);
158
159 crm_log_xml_trace(request, "ipc-received");
160 stonith_command(c, id, flags, request, NULL);
161
162 free_xml(request);
163 return 0;
164 }
165
166
167 static int32_t
168 st_ipc_closed(qb_ipcs_connection_t * c)
169 {
170 pcmk__client_t *client = pcmk__find_client(c);
171
172 if (client == NULL) {
173 return 0;
174 }
175
176 crm_trace("Connection %p closed", c);
177 pcmk__free_client(client);
178
179
180 return 0;
181 }
182
183 static void
184 st_ipc_destroy(qb_ipcs_connection_t * c)
185 {
186 crm_trace("Connection %p destroyed", c);
187 st_ipc_closed(c);
188 }
189
190 static void
191 stonith_peer_callback(xmlNode * msg, void *private_data)
192 {
193 const char *remote_peer = crm_element_value(msg, F_ORIG);
194 const char *op = crm_element_value(msg, F_STONITH_OPERATION);
195
196 if (pcmk__str_eq(op, "poke", pcmk__str_none)) {
197 return;
198 }
199
200 crm_log_xml_trace(msg, "Peer[inbound]");
201 stonith_command(NULL, 0, 0, msg, remote_peer);
202 }
203
204 #if SUPPORT_COROSYNC
205 static void
206 stonith_peer_ais_callback(cpg_handle_t handle,
207 const struct cpg_name *groupName,
208 uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
209 {
210 uint32_t kind = 0;
211 xmlNode *xml = NULL;
212 const char *from = NULL;
213 char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
214
215 if(data == NULL) {
216 return;
217 }
218 if (kind == crm_class_cluster) {
219 xml = string2xml(data);
220 if (xml == NULL) {
221 crm_err("Invalid XML: '%.120s'", data);
222 free(data);
223 return;
224 }
225 crm_xml_add(xml, F_ORIG, from);
226
227 stonith_peer_callback(xml, NULL);
228 }
229
230 free_xml(xml);
231 free(data);
232 return;
233 }
234
235 static void
236 stonith_peer_cs_destroy(gpointer user_data)
237 {
238 crm_crit("Lost connection to cluster layer, shutting down");
239 stonith_shutdown(0);
240 }
241 #endif
242
243 void
244 do_local_reply(xmlNode *notify_src, pcmk__client_t *client, int call_options)
245 {
246
247 int local_rc = pcmk_rc_ok;
248 int rid = 0;
249 uint32_t ipc_flags = crm_ipc_server_event;
250
251 if (pcmk_is_set(call_options, st_opt_sync_call)) {
252 CRM_LOG_ASSERT(client->request_id);
253 rid = client->request_id;
254 client->request_id = 0;
255 ipc_flags = crm_ipc_flags_none;
256 }
257
258 local_rc = pcmk__ipc_send_xml(client, rid, notify_src, ipc_flags);
259 if (local_rc == pcmk_rc_ok) {
260 crm_trace("Sent response %d to client %s",
261 rid, pcmk__client_name(client));
262 } else {
263 crm_warn("%synchronous reply to client %s failed: %s",
264 (pcmk_is_set(call_options, st_opt_sync_call)? "S" : "As"),
265 pcmk__client_name(client), pcmk_rc_str(local_rc));
266 }
267 }
268
269 uint64_t
270 get_stonith_flag(const char *name)
271 {
272 if (pcmk__str_eq(name, T_STONITH_NOTIFY_FENCE, pcmk__str_casei)) {
273 return st_callback_notify_fence;
274
275 } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_ADD, pcmk__str_casei)) {
276 return st_callback_device_add;
277
278 } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_DEL, pcmk__str_casei)) {
279 return st_callback_device_del;
280
281 } else if (pcmk__str_eq(name, T_STONITH_NOTIFY_HISTORY, pcmk__str_casei)) {
282 return st_callback_notify_history;
283
284 } else if (pcmk__str_eq(name, T_STONITH_NOTIFY_HISTORY_SYNCED, pcmk__str_casei)) {
285 return st_callback_notify_history_synced;
286
287 }
288 return st_callback_unknown;
289 }
290
291 static void
292 stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
293 {
294
295 xmlNode *update_msg = user_data;
296 pcmk__client_t *client = value;
297 const char *type = NULL;
298
299 CRM_CHECK(client != NULL, return);
300 CRM_CHECK(update_msg != NULL, return);
301
302 type = crm_element_value(update_msg, F_SUBTYPE);
303 CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);
304
305 if (client->ipcs == NULL) {
306 crm_trace("Skipping client with NULL channel");
307 return;
308 }
309
310 if (pcmk_is_set(client->flags, get_stonith_flag(type))) {
311 int rc = pcmk__ipc_send_xml(client, 0, update_msg,
312 crm_ipc_server_event);
313
314 if (rc != pcmk_rc_ok) {
315 crm_warn("%s notification of client %s failed: %s "
316 CRM_XS " id=%.8s rc=%d", type, pcmk__client_name(client),
317 pcmk_rc_str(rc), client->id, rc);
318 } else {
319 crm_trace("Sent %s notification to client %s",
320 type, pcmk__client_name(client));
321 }
322 }
323 }
324
325 void
326 do_stonith_async_timeout_update(const char *client_id, const char *call_id, int timeout)
327 {
328 pcmk__client_t *client = NULL;
329 xmlNode *notify_data = NULL;
330
331 if (!timeout || !call_id || !client_id) {
332 return;
333 }
334
335 client = pcmk__find_client_by_id(client_id);
336 if (!client) {
337 return;
338 }
339
340 notify_data = create_xml_node(NULL, T_STONITH_TIMEOUT_VALUE);
341 crm_xml_add(notify_data, F_TYPE, T_STONITH_TIMEOUT_VALUE);
342 crm_xml_add(notify_data, F_STONITH_CALLID, call_id);
343 crm_xml_add_int(notify_data, F_STONITH_TIMEOUT, timeout);
344
345 crm_trace("timeout update is %d for client %s and call id %s", timeout, client_id, call_id);
346
347 if (client) {
348 pcmk__ipc_send_xml(client, 0, notify_data, crm_ipc_server_event);
349 }
350
351 free_xml(notify_data);
352 }
353
354
355
356
357
358
359
360
361
362 void
363 fenced_send_notification(const char *type, const pcmk__action_result_t *result,
364 xmlNode *data)
365 {
366
367 xmlNode *update_msg = create_xml_node(NULL, "notify");
368
369 CRM_LOG_ASSERT(type != NULL);
370
371 crm_xml_add(update_msg, F_TYPE, T_STONITH_NOTIFY);
372 crm_xml_add(update_msg, F_SUBTYPE, type);
373 crm_xml_add(update_msg, F_STONITH_OPERATION, type);
374 stonith__xe_set_result(update_msg, result);
375
376 if (data != NULL) {
377 add_message_xml(update_msg, F_STONITH_CALLDATA, data);
378 }
379
380 crm_trace("Notifying clients");
381 pcmk__foreach_ipc_client(stonith_notify_client, update_msg);
382 free_xml(update_msg);
383 crm_trace("Notify complete");
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397 static void
398 send_config_notification(const char *op, const pcmk__action_result_t *result,
399 const char *desc, int active)
400 {
401 xmlNode *notify_data = create_xml_node(NULL, op);
402
403 CRM_CHECK(notify_data != NULL, return);
404
405 crm_xml_add(notify_data, F_STONITH_DEVICE, desc);
406 crm_xml_add_int(notify_data, F_STONITH_ACTIVE, active);
407
408 fenced_send_notification(op, result, notify_data);
409 free_xml(notify_data);
410 }
411
412
413
414
415
416
417
418
419
420
421 void
422 fenced_send_device_notification(const char *op,
423 const pcmk__action_result_t *result,
424 const char *desc)
425 {
426 send_config_notification(op, result, desc, g_hash_table_size(device_list));
427 }
428
429
430
431
432
433
434
435
436
437
438 void
439 fenced_send_level_notification(const char *op,
440 const pcmk__action_result_t *result,
441 const char *desc)
442 {
443 send_config_notification(op, result, desc, g_hash_table_size(topology));
444 }
445
446 static void
447 topology_remove_helper(const char *node, int level)
448 {
449 char *desc = NULL;
450 pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
451 xmlNode *data = create_xml_node(NULL, XML_TAG_FENCING_LEVEL);
452
453 crm_xml_add(data, F_STONITH_ORIGIN, __func__);
454 crm_xml_add_int(data, XML_ATTR_STONITH_INDEX, level);
455 crm_xml_add(data, XML_ATTR_STONITH_TARGET, node);
456
457 fenced_unregister_level(data, &desc, &result);
458 fenced_send_level_notification(STONITH_OP_LEVEL_DEL, &result, desc);
459 pcmk__reset_result(&result);
460 free_xml(data);
461 free(desc);
462 }
463
464 static void
465 remove_cib_device(xmlXPathObjectPtr xpathObj)
466 {
467 int max = numXpathResults(xpathObj), lpc = 0;
468
469 for (lpc = 0; lpc < max; lpc++) {
470 const char *rsc_id = NULL;
471 const char *standard = NULL;
472 xmlNode *match = getXpathResult(xpathObj, lpc);
473
474 CRM_LOG_ASSERT(match != NULL);
475 if(match != NULL) {
476 standard = crm_element_value(match, XML_AGENT_ATTR_CLASS);
477 }
478
479 if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
480 continue;
481 }
482
483 rsc_id = crm_element_value(match, XML_ATTR_ID);
484
485 stonith_device_remove(rsc_id, true);
486 }
487 }
488
489 static void
490 remove_topology_level(xmlNode *match)
491 {
492 int index = 0;
493 char *key = NULL;
494
495 CRM_CHECK(match != NULL, return);
496
497 key = stonith_level_key(match, fenced_target_by_unknown);
498 crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
499 topology_remove_helper(key, index);
500 free(key);
501 }
502
503 static void
504 add_topology_level(xmlNode *match)
505 {
506 char *desc = NULL;
507 pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
508
509 CRM_CHECK(match != NULL, return);
510
511 fenced_register_level(match, &desc, &result);
512 fenced_send_level_notification(STONITH_OP_LEVEL_ADD, &result, desc);
513 pcmk__reset_result(&result);
514 free(desc);
515 }
516
517 static void
518 remove_fencing_topology(xmlXPathObjectPtr xpathObj)
519 {
520 int max = numXpathResults(xpathObj), lpc = 0;
521
522 for (lpc = 0; lpc < max; lpc++) {
523 xmlNode *match = getXpathResult(xpathObj, lpc);
524
525 CRM_LOG_ASSERT(match != NULL);
526 if (match && crm_element_value(match, XML_DIFF_MARKER)) {
527
528 int index = 0;
529 char *target = stonith_level_key(match, fenced_target_by_unknown);
530
531 crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
532 if (target == NULL) {
533 crm_err("Invalid fencing target in element %s", ID(match));
534
535 } else if (index <= 0) {
536 crm_err("Invalid level for %s in element %s", target, ID(match));
537
538 } else {
539 topology_remove_helper(target, index);
540 }
541
542 }
543 }
544 }
545
546 static void
547 register_fencing_topology(xmlXPathObjectPtr xpathObj)
548 {
549 int max = numXpathResults(xpathObj), lpc = 0;
550
551 for (lpc = 0; lpc < max; lpc++) {
552 xmlNode *match = getXpathResult(xpathObj, lpc);
553
554 remove_topology_level(match);
555 add_topology_level(match);
556 }
557 }
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578 static void
579 fencing_topology_init(void)
580 {
581 xmlXPathObjectPtr xpathObj = NULL;
582 const char *xpath = "//" XML_TAG_FENCING_LEVEL;
583
584 crm_trace("Full topology refresh");
585 free_topology_list();
586 init_topology_list();
587
588
589 xpathObj = xpath_search(local_cib, xpath);
590 register_fencing_topology(xpathObj);
591
592 freeXpathObject(xpathObj);
593 }
594
595 #define rsc_name(x) x->clone_name?x->clone_name:x->id
596
597
598
599
600
601
602
603
604
605 static pe_node_t *
606 our_node_allowed_for(const pe_resource_t *rsc)
607 {
608 GHashTableIter iter;
609 pe_node_t *node = NULL;
610
611 if (rsc && stonith_our_uname) {
612 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
613 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
614 if (node && strcmp(node->details->uname, stonith_our_uname) == 0) {
615 break;
616 }
617 node = NULL;
618 }
619 }
620 return node;
621 }
622
623 static void
624 watchdog_device_update(void)
625 {
626 if (stonith_watchdog_timeout_ms > 0) {
627 if (!g_hash_table_lookup(device_list, STONITH_WATCHDOG_ID) &&
628 !stonith_watchdog_targets) {
629
630
631
632 int rc;
633 xmlNode *xml;
634
635 xml = create_device_registration_xml(
636 STONITH_WATCHDOG_ID,
637 st_namespace_internal,
638 STONITH_WATCHDOG_AGENT,
639 NULL,
640
641
642
643 NULL);
644 rc = stonith_device_register(xml, TRUE);
645 free_xml(xml);
646 if (rc != pcmk_ok) {
647 rc = pcmk_legacy2rc(rc);
648 exit_code = CRM_EX_FATAL;
649 crm_crit("Cannot register watchdog pseudo fence agent: %s",
650 pcmk_rc_str(rc));
651 stonith_shutdown(0);
652 }
653 }
654
655 } else if (g_hash_table_lookup(device_list, STONITH_WATCHDOG_ID) != NULL) {
656
657 stonith_device_remove(STONITH_WATCHDOG_ID, true);
658 }
659 }
660
661 static void
662 update_stonith_watchdog_timeout_ms(xmlNode *cib)
663 {
664 long timeout_ms = 0;
665 xmlNode *stonith_watchdog_xml = NULL;
666 const char *value = NULL;
667
668 stonith_watchdog_xml = get_xpath_object("//nvpair[@name='stonith-watchdog-timeout']",
669 cib, LOG_NEVER);
670 if (stonith_watchdog_xml) {
671 value = crm_element_value(stonith_watchdog_xml, XML_NVPAIR_ATTR_VALUE);
672 }
673 if (value) {
674 timeout_ms = crm_get_msec(value);
675 }
676
677 if (timeout_ms < 0) {
678 timeout_ms = pcmk__auto_watchdog_timeout();
679 }
680
681 stonith_watchdog_timeout_ms = timeout_ms;
682 }
683
684
685
686
687
688
689
690
691
692 static void
693 cib_device_update(pe_resource_t *rsc, pe_working_set_t *data_set)
694 {
695 pe_node_t *node = NULL;
696 const char *value = NULL;
697 const char *rclass = NULL;
698 pe_node_t *parent = NULL;
699
700
701 if(rsc->children) {
702 GList *gIter = NULL;
703 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
704 cib_device_update(gIter->data, data_set);
705 if(pe_rsc_is_clone(rsc)) {
706 crm_trace("Only processing one copy of the clone %s", rsc->id);
707 break;
708 }
709 }
710 return;
711 }
712
713
714 rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
715 if (!pcmk__str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
716 return;
717 }
718
719
720 if (pe__resource_is_disabled(rsc)) {
721 crm_info("Device %s has been disabled", rsc->id);
722 return;
723 }
724
725
726
727
728 if ((stonith_watchdog_timeout_ms <= 0) &&
729 pcmk__str_eq(rsc->id, STONITH_WATCHDOG_ID, pcmk__str_none)) {
730 crm_info("Watchdog-fencing disabled thus handling "
731 "device %s as disabled", rsc->id);
732 return;
733 }
734
735
736 node = our_node_allowed_for(rsc);
737 if (rsc->parent && (rsc->parent->variant == pe_group)) {
738 parent = our_node_allowed_for(rsc->parent);
739 }
740
741 if(node == NULL) {
742
743 GHashTableIter iter;
744
745 crm_info("Device %s has been disabled on %s: unknown", rsc->id, stonith_our_uname);
746 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
747 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
748 crm_trace("Available: %s = %d", pe__node_name(node), node->weight);
749 }
750
751 return;
752
753 } else if(node->weight < 0 || (parent && parent->weight < 0)) {
754
755 int score = (node->weight < 0)? node->weight : parent->weight;
756
757 crm_info("Device %s has been disabled on %s: score=%s",
758 rsc->id, stonith_our_uname, pcmk_readable_score(score));
759 return;
760
761 } else {
762
763 int rc;
764 xmlNode *data;
765 GHashTable *rsc_params = NULL;
766 GHashTableIter gIter;
767 stonith_key_value_t *params = NULL;
768
769 const char *name = NULL;
770 const char *agent = crm_element_value(rsc->xml, XML_EXPR_ATTR_TYPE);
771 const char *rsc_provides = NULL;
772
773 crm_debug("Device %s is allowed on %s: score=%d", rsc->id, stonith_our_uname, node->weight);
774 rsc_params = pe_rsc_params(rsc, node, data_set);
775 get_meta_attributes(rsc->meta, rsc, node, data_set);
776
777 rsc_provides = g_hash_table_lookup(rsc->meta, PCMK_STONITH_PROVIDES);
778
779 g_hash_table_iter_init(&gIter, rsc_params);
780 while (g_hash_table_iter_next(&gIter, (gpointer *) & name, (gpointer *) & value)) {
781 if (!name || !value) {
782 continue;
783 }
784 params = stonith_key_value_add(params, name, value);
785 crm_trace(" %s=%s", name, value);
786 }
787
788 data = create_device_registration_xml(rsc_name(rsc), st_namespace_any,
789 agent, params, rsc_provides);
790 stonith_key_value_freeall(params, 1, 1);
791 rc = stonith_device_register(data, TRUE);
792 CRM_ASSERT(rc == pcmk_ok);
793 free_xml(data);
794 }
795 }
796
797
798
799
800
801 static void
802 cib_devices_update(void)
803 {
804 GHashTableIter iter;
805 stonith_device_t *device = NULL;
806
807 crm_info("Updating devices to version %s.%s.%s",
808 crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN),
809 crm_element_value(local_cib, XML_ATTR_GENERATION),
810 crm_element_value(local_cib, XML_ATTR_NUMUPDATES));
811
812 if (fenced_data_set->now != NULL) {
813 crm_time_free(fenced_data_set->now);
814 fenced_data_set->now = NULL;
815 }
816 fenced_data_set->localhost = stonith_our_uname;
817 pcmk__schedule_actions(local_cib, data_set_flags, fenced_data_set);
818
819 g_hash_table_iter_init(&iter, device_list);
820 while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
821 if (device->cib_registered) {
822 device->dirty = TRUE;
823 }
824 }
825
826
827
828
829 g_list_free_full(stonith_watchdog_targets, free);
830 stonith_watchdog_targets = NULL;
831 g_list_foreach(fenced_data_set->resources, (GFunc) cib_device_update, fenced_data_set);
832
833 g_hash_table_iter_init(&iter, device_list);
834 while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
835 if (device->dirty) {
836 g_hash_table_iter_remove(&iter);
837 }
838 }
839
840 fenced_data_set->input = NULL;
841 pe_reset_working_set(fenced_data_set);
842 }
843
844 static void
845 update_cib_stonith_devices_v2(const char *event, xmlNode * msg)
846 {
847 xmlNode *change = NULL;
848 char *reason = NULL;
849 bool needs_update = FALSE;
850 xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
851
852 for (change = pcmk__xml_first_child(patchset); change != NULL;
853 change = pcmk__xml_next(change)) {
854 const char *op = crm_element_value(change, XML_DIFF_OP);
855 const char *xpath = crm_element_value(change, XML_DIFF_PATH);
856 const char *shortpath = NULL;
857
858 if ((op == NULL) ||
859 (strcmp(op, "move") == 0) ||
860 strstr(xpath, "/"XML_CIB_TAG_STATUS)) {
861 continue;
862 } else if (pcmk__str_eq(op, "delete", pcmk__str_casei) && strstr(xpath, "/"XML_CIB_TAG_RESOURCE)) {
863 const char *rsc_id = NULL;
864 char *search = NULL;
865 char *mutable = NULL;
866
867 if (strstr(xpath, XML_TAG_ATTR_SETS) ||
868 strstr(xpath, XML_TAG_META_SETS)) {
869 needs_update = TRUE;
870 pcmk__str_update(&reason,
871 "(meta) attribute deleted from resource");
872 break;
873 }
874 pcmk__str_update(&mutable, xpath);
875 rsc_id = strstr(mutable, "primitive[@" XML_ATTR_ID "=\'");
876 if (rsc_id != NULL) {
877 rsc_id += strlen("primitive[@" XML_ATTR_ID "=\'");
878 search = strchr(rsc_id, '\'');
879 }
880 if (search != NULL) {
881 *search = 0;
882 stonith_device_remove(rsc_id, true);
883
884
885 } else {
886 crm_warn("Ignoring malformed CIB update (resource deletion)");
887 }
888 free(mutable);
889
890 } else if (strstr(xpath, "/"XML_CIB_TAG_RESOURCES) ||
891 strstr(xpath, "/"XML_CIB_TAG_CONSTRAINTS) ||
892 strstr(xpath, "/"XML_CIB_TAG_RSCCONFIG)) {
893 shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath);
894 reason = crm_strdup_printf("%s %s", op, shortpath+1);
895 needs_update = TRUE;
896 break;
897 }
898 }
899
900 if(needs_update) {
901 crm_info("Updating device list from CIB: %s", reason);
902 cib_devices_update();
903 } else {
904 crm_trace("No updates for device list found in CIB");
905 }
906 free(reason);
907 }
908
909
910 static void
911 update_cib_stonith_devices_v1(const char *event, xmlNode * msg)
912 {
913 const char *reason = "none";
914 gboolean needs_update = FALSE;
915 xmlXPathObjectPtr xpath_obj = NULL;
916
917
918 xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_CONS_TAG_RSC_LOCATION);
919 if (numXpathResults(xpath_obj) > 0) {
920 int max = numXpathResults(xpath_obj), lpc = 0;
921
922
923 needs_update = TRUE;
924 reason = "new location constraint";
925
926 for (lpc = 0; lpc < max; lpc++) {
927 xmlNode *match = getXpathResult(xpath_obj, lpc);
928
929 crm_log_xml_trace(match, "new constraint");
930 }
931 }
932 freeXpathObject(xpath_obj);
933
934
935 xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_CIB_TAG_RESOURCE);
936 if (numXpathResults(xpath_obj) > 0) {
937 remove_cib_device(xpath_obj);
938 }
939 freeXpathObject(xpath_obj);
940
941
942 xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_RESOURCE);
943 if (numXpathResults(xpath_obj) > 0) {
944 int max = numXpathResults(xpath_obj), lpc = 0;
945
946 for (lpc = 0; lpc < max; lpc++) {
947 const char *rsc_id = NULL;
948 const char *standard = NULL;
949 xmlNode *match = getXpathResult(xpath_obj, lpc);
950
951 rsc_id = crm_element_value(match, XML_ATTR_ID);
952 standard = crm_element_value(match, XML_AGENT_ATTR_CLASS);
953
954 if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
955 continue;
956 }
957
958 crm_trace("Fencing resource %s was added or modified", rsc_id);
959 reason = "new resource";
960 needs_update = TRUE;
961 }
962 }
963 freeXpathObject(xpath_obj);
964
965 if(needs_update) {
966 crm_info("Updating device list from CIB: %s", reason);
967 cib_devices_update();
968 }
969 }
970
971 static void
972 update_cib_stonith_devices(const char *event, xmlNode * msg)
973 {
974 int format = 1;
975 xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
976
977 CRM_ASSERT(patchset);
978 crm_element_value_int(patchset, "format", &format);
979 switch(format) {
980 case 1:
981 update_cib_stonith_devices_v1(event, msg);
982 break;
983 case 2:
984 update_cib_stonith_devices_v2(event, msg);
985 break;
986 default:
987 crm_warn("Unknown patch format: %d", format);
988 }
989 }
990
991
992
993
994
995
996
997
998
999
1000
1001 gboolean
1002 node_has_attr(const char *node, const char *name, const char *value)
1003 {
1004 GString *xpath = NULL;
1005 xmlNode *match;
1006
1007 CRM_CHECK((local_cib != NULL) && (node != NULL) && (name != NULL)
1008 && (value != NULL), return FALSE);
1009
1010
1011
1012
1013
1014
1015 xpath = g_string_sized_new(256);
1016 pcmk__g_strcat(xpath,
1017 "//" XML_CIB_TAG_NODES "/" XML_CIB_TAG_NODE
1018 "[@" XML_ATTR_UNAME "='", node, "']/" XML_TAG_ATTR_SETS
1019 "/" XML_CIB_TAG_NVPAIR
1020 "[@" XML_NVPAIR_ATTR_NAME "='", name, "' "
1021 "and @" XML_NVPAIR_ATTR_VALUE "='", value, "']", NULL);
1022
1023 match = get_xpath_object((const char *) xpath->str, local_cib, LOG_NEVER);
1024
1025 g_string_free(xpath, TRUE);
1026 return (match != NULL);
1027 }
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039 gboolean
1040 node_does_watchdog_fencing(const char *node)
1041 {
1042 return ((stonith_watchdog_targets == NULL) ||
1043 pcmk__str_in_list(node, stonith_watchdog_targets, pcmk__str_casei));
1044 }
1045
1046
1047 static void
1048 update_fencing_topology(const char *event, xmlNode * msg)
1049 {
1050 int format = 1;
1051 const char *xpath;
1052 xmlXPathObjectPtr xpathObj = NULL;
1053 xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
1054
1055 CRM_ASSERT(patchset);
1056 crm_element_value_int(patchset, "format", &format);
1057
1058 if(format == 1) {
1059
1060 xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_FENCING_LEVEL;
1061 xpathObj = xpath_search(msg, xpath);
1062
1063 remove_fencing_topology(xpathObj);
1064 freeXpathObject(xpathObj);
1065
1066
1067 xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL;
1068 xpathObj = xpath_search(msg, xpath);
1069
1070 register_fencing_topology(xpathObj);
1071 freeXpathObject(xpathObj);
1072
1073 } else if(format == 2) {
1074 xmlNode *change = NULL;
1075 int add[] = { 0, 0, 0 };
1076 int del[] = { 0, 0, 0 };
1077
1078 xml_patch_versions(patchset, add, del);
1079
1080 for (change = pcmk__xml_first_child(patchset); change != NULL;
1081 change = pcmk__xml_next(change)) {
1082 const char *op = crm_element_value(change, XML_DIFF_OP);
1083 const char *xpath = crm_element_value(change, XML_DIFF_PATH);
1084
1085 if(op == NULL) {
1086 continue;
1087
1088 } else if(strstr(xpath, "/" XML_TAG_FENCING_LEVEL) != NULL) {
1089
1090
1091 crm_trace("Handling %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath);
1092 if(strcmp(op, "move") == 0) {
1093 continue;
1094
1095 } else if(strcmp(op, "create") == 0) {
1096 add_topology_level(change->children);
1097
1098 } else if(strcmp(op, "modify") == 0) {
1099 xmlNode *match = first_named_child(change, XML_DIFF_RESULT);
1100
1101 if(match) {
1102 remove_topology_level(match->children);
1103 add_topology_level(match->children);
1104 }
1105
1106 } else if(strcmp(op, "delete") == 0) {
1107
1108 crm_info("Re-initializing fencing topology after %s operation %d.%d.%d for %s",
1109 op, add[0], add[1], add[2], xpath);
1110 fencing_topology_init();
1111 return;
1112 }
1113
1114 } else if (strstr(xpath, "/" XML_TAG_FENCING_TOPOLOGY) != NULL) {
1115
1116 crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s",
1117 op, add[0], add[1], add[2], xpath);
1118 fencing_topology_init();
1119 return;
1120
1121 } else if (strstr(xpath, "/" XML_CIB_TAG_CONFIGURATION)) {
1122
1123 if(first_named_child(change, XML_TAG_FENCING_TOPOLOGY) == NULL) {
1124 crm_trace("Nothing for us in %s operation %d.%d.%d for %s.",
1125 op, add[0], add[1], add[2], xpath);
1126
1127 } else if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) {
1128 crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s.",
1129 op, add[0], add[1], add[2], xpath);
1130 fencing_topology_init();
1131 return;
1132 }
1133
1134 } else {
1135 crm_trace("Nothing for us in %s operation %d.%d.%d for %s",
1136 op, add[0], add[1], add[2], xpath);
1137 }
1138 }
1139
1140 } else {
1141 crm_warn("Unknown patch format: %d", format);
1142 }
1143 }
1144 static bool have_cib_devices = FALSE;
1145
1146 static void
1147 update_cib_cache_cb(const char *event, xmlNode * msg)
1148 {
1149 int rc = pcmk_ok;
1150 long timeout_ms_saved = stonith_watchdog_timeout_ms;
1151 bool need_full_refresh = false;
1152
1153 if(!have_cib_devices) {
1154 crm_trace("Skipping updates until we get a full dump");
1155 return;
1156
1157 } else if(msg == NULL) {
1158 crm_trace("Missing %s update", event);
1159 return;
1160 }
1161
1162
1163
1164
1165 if (local_cib != NULL) {
1166 int rc = pcmk_ok;
1167 xmlNode *patchset = NULL;
1168
1169 crm_element_value_int(msg, F_CIB_RC, &rc);
1170 if (rc != pcmk_ok) {
1171 return;
1172 }
1173
1174 patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
1175 pcmk__output_set_log_level(logger_out, LOG_TRACE);
1176 out->message(out, "xml-patchset", patchset);
1177 rc = xml_apply_patchset(local_cib, patchset, TRUE);
1178 switch (rc) {
1179 case pcmk_ok:
1180 case -pcmk_err_old_data:
1181 break;
1182 case -pcmk_err_diff_resync:
1183 case -pcmk_err_diff_failed:
1184 crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc);
1185 free_xml(local_cib);
1186 local_cib = NULL;
1187 break;
1188 default:
1189 crm_warn("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc);
1190 free_xml(local_cib);
1191 local_cib = NULL;
1192 }
1193 }
1194
1195 if (local_cib == NULL) {
1196 crm_trace("Re-requesting full CIB");
1197 rc = cib_api->cmds->query(cib_api, NULL, &local_cib, cib_scope_local | cib_sync_call);
1198 if(rc != pcmk_ok) {
1199 crm_err("Couldn't retrieve the CIB: %s (%d)", pcmk_strerror(rc), rc);
1200 return;
1201 }
1202 CRM_ASSERT(local_cib != NULL);
1203 need_full_refresh = true;
1204 }
1205
1206 pcmk__refresh_node_caches_from_cib(local_cib);
1207 update_stonith_watchdog_timeout_ms(local_cib);
1208
1209 if (timeout_ms_saved != stonith_watchdog_timeout_ms) {
1210 need_full_refresh = true;
1211 }
1212
1213 if (need_full_refresh) {
1214 fencing_topology_init();
1215 cib_devices_update();
1216 } else {
1217
1218 update_fencing_topology(event, msg);
1219 update_cib_stonith_devices(event, msg);
1220 }
1221
1222 watchdog_device_update();
1223 }
1224
1225 static void
1226 init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
1227 {
1228 crm_info("Updating device list from CIB");
1229 have_cib_devices = TRUE;
1230 local_cib = copy_xml(output);
1231
1232 pcmk__refresh_node_caches_from_cib(local_cib);
1233 update_stonith_watchdog_timeout_ms(local_cib);
1234
1235 fencing_topology_init();
1236 cib_devices_update();
1237 watchdog_device_update();
1238 }
1239
1240 static void
1241 stonith_shutdown(int nsig)
1242 {
1243 crm_info("Terminating with %d clients", pcmk__ipc_client_count());
1244 stonith_shutdown_flag = TRUE;
1245 if (mainloop != NULL && g_main_loop_is_running(mainloop)) {
1246 g_main_loop_quit(mainloop);
1247 }
1248 }
1249
1250 static void
1251 cib_connection_destroy(gpointer user_data)
1252 {
1253 if (stonith_shutdown_flag) {
1254 crm_info("Connection to the CIB manager closed");
1255 return;
1256 } else {
1257 crm_crit("Lost connection to the CIB manager, shutting down");
1258 }
1259 if (cib_api) {
1260 cib_api->cmds->signoff(cib_api);
1261 }
1262 stonith_shutdown(0);
1263 }
1264
1265 static void
1266 stonith_cleanup(void)
1267 {
1268 if (cib_api) {
1269 cib_api->cmds->del_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, update_cib_cache_cb);
1270 cib_api->cmds->signoff(cib_api);
1271 }
1272
1273 if (ipcs) {
1274 qb_ipcs_destroy(ipcs);
1275 }
1276
1277 crm_peer_destroy();
1278 pcmk__client_cleanup();
1279 free_stonith_remote_op_list();
1280 free_topology_list();
1281 free_device_list();
1282 free_metadata_cache();
1283 fenced_unregister_handlers();
1284
1285 free(stonith_our_uname);
1286 stonith_our_uname = NULL;
1287
1288 free_xml(local_cib);
1289 local_cib = NULL;
1290 }
1291
1292 static gboolean
1293 stand_alone_cpg_cb(const gchar *option_name, const gchar *optarg, gpointer data,
1294 GError **error)
1295 {
1296 stand_alone = FALSE;
1297 options.no_cib_connect = true;
1298 return TRUE;
1299 }
1300
1301 static void
1302 setup_cib(void)
1303 {
1304 int rc, retries = 0;
1305
1306 cib_api = cib_new();
1307 if (cib_api == NULL) {
1308 crm_err("No connection to the CIB manager");
1309 return;
1310 }
1311
1312 do {
1313 sleep(retries);
1314 rc = cib_api->cmds->signon(cib_api, CRM_SYSTEM_STONITHD, cib_command);
1315 } while (rc == -ENOTCONN && ++retries < 5);
1316
1317 if (rc != pcmk_ok) {
1318 crm_err("Could not connect to the CIB manager: %s (%d)", pcmk_strerror(rc), rc);
1319
1320 } else if (pcmk_ok !=
1321 cib_api->cmds->add_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, update_cib_cache_cb)) {
1322 crm_err("Could not set CIB notification callback");
1323
1324 } else {
1325 rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local);
1326 cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL, "init_cib_cache_cb",
1327 init_cib_cache_cb);
1328 cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy);
1329 crm_info("Watching for fencing topology changes");
1330 }
1331 }
1332
1333 struct qb_ipcs_service_handlers ipc_callbacks = {
1334 .connection_accept = st_ipc_accept,
1335 .connection_created = NULL,
1336 .msg_process = st_ipc_dispatch,
1337 .connection_closed = st_ipc_closed,
1338 .connection_destroyed = st_ipc_destroy
1339 };
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349 static void
1350 st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data)
1351 {
1352 if ((type != crm_status_processes)
1353 && !pcmk_is_set(node->flags, crm_remote_node)) {
1354
1355
1356
1357
1358 xmlNode *query = create_xml_node(NULL, "stonith_command");
1359
1360 crm_xml_add(query, F_XML_TAGNAME, "stonith_command");
1361 crm_xml_add(query, F_TYPE, T_STONITH_NG);
1362 crm_xml_add(query, F_STONITH_OPERATION, "poke");
1363
1364 crm_debug("Broadcasting our uname because of node %u", node->id);
1365 send_cluster_message(NULL, crm_msg_stonith_ng, query, FALSE);
1366
1367 free_xml(query);
1368 }
1369 }
1370
1371 static pcmk__cluster_option_t fencer_options[] = {
1372
1373
1374
1375
1376
1377 {
1378 PCMK_STONITH_HOST_ARGUMENT, NULL, "string", NULL, "port", NULL,
1379 N_("Advanced use only: An alternate parameter to supply instead of 'port'"),
1380 N_("some devices do not support the "
1381 "standard 'port' parameter or may provide additional ones. Use "
1382 "this to specify an alternate, device-specific, parameter "
1383 "that should indicate the machine to be fenced. A value of "
1384 "none can be used to tell the cluster not to supply any "
1385 "additional parameters.")
1386 },
1387 {
1388 PCMK_STONITH_HOST_MAP,NULL, "string", NULL, "", NULL,
1389 N_("A mapping of host names to ports numbers for devices that do not support host names."),
1390 N_("Eg. node1:1;node2:2,3 would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2")
1391 },
1392 {
1393 PCMK_STONITH_HOST_LIST,NULL, "string", NULL, "", NULL,
1394 N_("Eg. node1,node2,node3"),
1395 N_("A list of machines controlled by "
1396 "this device (Optional unless pcmk_host_list=static-list)")
1397 },
1398 {
1399 PCMK_STONITH_HOST_CHECK,NULL, "string", NULL, "dynamic-list", NULL,
1400 N_("How to determine which machines are controlled by the device."),
1401 N_("Allowed values: dynamic-list "
1402 "(query the device via the 'list' command), static-list "
1403 "(check the pcmk_host_list attribute), status "
1404 "(query the device via the 'status' command), "
1405 "none (assume every device can fence every "
1406 "machine)")
1407 },
1408 {
1409 PCMK_STONITH_DELAY_MAX,NULL, "time", NULL, "0s", NULL,
1410 N_("Enable a base delay for fencing actions and specify base delay value."),
1411 N_("Enable a delay of no more than the "
1412 "time specified before executing fencing actions. Pacemaker "
1413 "derives the overall delay by taking the value of "
1414 "pcmk_delay_base and adding a random delay value such "
1415 "that the sum is kept below this maximum.")
1416 },
1417 {
1418 PCMK_STONITH_DELAY_BASE,NULL, "string", NULL, "0s", NULL,
1419 N_("Enable a base delay for "
1420 "fencing actions and specify base delay value."),
1421 N_("This enables a static delay for "
1422 "fencing actions, which can help avoid \"death matches\" where "
1423 "two nodes try to fence each other at the same time. If "
1424 "pcmk_delay_max is also used, a random delay will be "
1425 "added such that the total delay is kept below that value."
1426 "This can be set to a single time value to apply to any node "
1427 "targeted by this device (useful if a separate device is "
1428 "configured for each target), or to a node map (for example, "
1429 "\"node1:1s;node2:5\") to set a different value per target.")
1430 },
1431 {
1432 PCMK_STONITH_ACTION_LIMIT,NULL, "integer", NULL, "1", NULL,
1433 N_("The maximum number of actions can be performed in parallel on this device"),
1434 N_("Cluster property concurrent-fencing=true needs to be configured first."
1435 "Then use this to specify the maximum number of actions can be performed in parallel on this device. -1 is unlimited.")
1436 },
1437 {
1438 "pcmk_reboot_action",NULL, "string", NULL, "reboot", NULL,
1439 N_("Advanced use only: An alternate command to run instead of 'reboot'"),
1440 N_("Some devices do not support the standard commands or may provide additional ones.\n"
1441 "Use this to specify an alternate, device-specific, command that implements the \'reboot\' action.")
1442 },
1443 {
1444 "pcmk_reboot_timeout",NULL, "time", NULL, "60s", NULL,
1445 N_("Advanced use only: Specify an alternate timeout to use for reboot actions instead of stonith-timeout"),
1446 N_("Some devices need much more/less time to complete than normal."
1447 "Use this to specify an alternate, device-specific, timeout for \'reboot\' actions.")
1448 },
1449 {
1450 "pcmk_reboot_retries",NULL, "integer", NULL, "2", NULL,
1451 N_("Advanced use only: The maximum number of times to retry the 'reboot' command within the timeout period"),
1452 N_("Some devices do not support multiple connections."
1453 " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
1454 " Use this option to alter the number of times Pacemaker retries \'reboot\' actions before giving up.")
1455 },
1456 {
1457 "pcmk_off_action",NULL, "string", NULL, "off", NULL,
1458 N_("Advanced use only: An alternate command to run instead of \'off\'"),
1459 N_("Some devices do not support the standard commands or may provide additional ones."
1460 "Use this to specify an alternate, device-specific, command that implements the \'off\' action.")
1461 },
1462 {
1463 "pcmk_off_timeout",NULL, "time", NULL, "60s", NULL,
1464 N_("Advanced use only: Specify an alternate timeout to use for off actions instead of stonith-timeout"),
1465 N_("Some devices need much more/less time to complete than normal."
1466 "Use this to specify an alternate, device-specific, timeout for \'off\' actions.")
1467 },
1468 {
1469 "pcmk_off_retries",NULL, "integer", NULL, "2", NULL,
1470 N_("Advanced use only: The maximum number of times to retry the 'off' command within the timeout period"),
1471 N_("Some devices do not support multiple connections."
1472 " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
1473 " Use this option to alter the number of times Pacemaker retries \'off\' actions before giving up.")
1474 },
1475 {
1476 "pcmk_on_action",NULL, "string", NULL, "on", NULL,
1477 N_("Advanced use only: An alternate command to run instead of 'on'"),
1478 N_("Some devices do not support the standard commands or may provide additional ones."
1479 "Use this to specify an alternate, device-specific, command that implements the \'on\' action.")
1480 },
1481 {
1482 "pcmk_on_timeout",NULL, "time", NULL, "60s", NULL,
1483 N_("Advanced use only: Specify an alternate timeout to use for on actions instead of stonith-timeout"),
1484 N_("Some devices need much more/less time to complete than normal."
1485 "Use this to specify an alternate, device-specific, timeout for \'on\' actions.")
1486 },
1487 {
1488 "pcmk_on_retries",NULL, "integer", NULL, "2", NULL,
1489 N_("Advanced use only: The maximum number of times to retry the 'on' command within the timeout period"),
1490 N_("Some devices do not support multiple connections."
1491 " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
1492 " Use this option to alter the number of times Pacemaker retries \'on\' actions before giving up.")
1493 },
1494 {
1495 "pcmk_list_action",NULL, "string", NULL, "list", NULL,
1496 N_("Advanced use only: An alternate command to run instead of \'list\'"),
1497 N_("Some devices do not support the standard commands or may provide additional ones."
1498 "Use this to specify an alternate, device-specific, command that implements the \'list\' action.")
1499 },
1500 {
1501 "pcmk_list_timeout",NULL, "time", NULL, "60s", NULL,
1502 N_("Advanced use only: Specify an alternate timeout to use for list actions instead of stonith-timeout"),
1503 N_("Some devices need much more/less time to complete than normal."
1504 "Use this to specify an alternate, device-specific, timeout for \'list\' actions.")
1505 },
1506 {
1507 "pcmk_list_retries",NULL, "integer", NULL, "2", NULL,
1508 N_("Advanced use only: The maximum number of times to retry the \'list\' command within the timeout period"),
1509 N_("Some devices do not support multiple connections."
1510 " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
1511 " Use this option to alter the number of times Pacemaker retries \'list\' actions before giving up.")
1512 },
1513 {
1514 "pcmk_monitor_action",NULL, "string", NULL, "monitor", NULL,
1515 N_("Advanced use only: An alternate command to run instead of \'monitor\'"),
1516 N_("Some devices do not support the standard commands or may provide additional ones."
1517 "Use this to specify an alternate, device-specific, command that implements the \'monitor\' action.")
1518 },
1519 {
1520 "pcmk_monitor_timeout",NULL, "time", NULL, "60s", NULL,
1521 N_("Advanced use only: Specify an alternate timeout to use for monitor actions instead of stonith-timeout"),
1522 N_("Some devices need much more/less time to complete than normal.\n"
1523 "Use this to specify an alternate, device-specific, timeout for \'monitor\' actions.")
1524 },
1525 {
1526 "pcmk_monitor_retries",NULL, "integer", NULL, "2", NULL,
1527 N_("Advanced use only: The maximum number of times to retry the \'monitor\' command within the timeout period"),
1528 N_("Some devices do not support multiple connections."
1529 " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
1530 " Use this option to alter the number of times Pacemaker retries \'monitor\' actions before giving up.")
1531 },
1532 {
1533 "pcmk_status_action",NULL, "string", NULL, "status", NULL,
1534 N_("Advanced use only: An alternate command to run instead of \'status\'"),
1535 N_("Some devices do not support the standard commands or may provide additional ones."
1536 "Use this to specify an alternate, device-specific, command that implements the \'status\' action.")
1537 },
1538 {
1539 "pcmk_status_timeout",NULL, "time", NULL, "60s", NULL,
1540 N_("Advanced use only: Specify an alternate timeout to use for status actions instead of stonith-timeout"),
1541 N_("Some devices need much more/less time to complete than normal."
1542 "Use this to specify an alternate, device-specific, timeout for \'status\' actions.")
1543 },
1544 {
1545 "pcmk_status_retries",NULL, "integer", NULL, "2", NULL,
1546 N_("Advanced use only: The maximum number of times to retry the \'status\' command within the timeout period"),
1547 N_("Some devices do not support multiple connections."
1548 " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
1549 " Use this option to alter the number of times Pacemaker retries \'status\' actions before giving up.")
1550 },
1551 };
1552
1553 void
1554 fencer_metadata(void)
1555 {
1556 const char *desc_short = N_("Instance attributes available for all "
1557 "\"stonith\"-class resources");
1558 const char *desc_long = N_("Instance attributes available for all \"stonith\"-"
1559 "class resources and used by Pacemaker's fence "
1560 "daemon, formerly known as stonithd");
1561
1562 gchar *s = pcmk__format_option_metadata("pacemaker-fenced", desc_short,
1563 desc_long, fencer_options,
1564 PCMK__NELEM(fencer_options));
1565 printf("%s", s);
1566 g_free(s);
1567 }
1568
1569 static GOptionEntry entries[] = {
1570 { "stand-alone", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &stand_alone,
1571 "Deprecated (will be removed in a future release)", NULL },
1572
1573 { "stand-alone-w-cpg", 'c', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
1574 stand_alone_cpg_cb, "Intended for use in regression testing only", NULL },
1575
1576 { "logfile", 'l', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME_ARRAY,
1577 &options.log_files, "Send logs to the additional named logfile", NULL },
1578
1579 { NULL }
1580 };
1581
1582 static GOptionContext *
1583 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group)
1584 {
1585 GOptionContext *context = NULL;
1586
1587 context = pcmk__build_arg_context(args, "text (default), xml", group,
1588 "[metadata]");
1589 pcmk__add_main_args(context, entries);
1590 return context;
1591 }
1592
1593 int
1594 main(int argc, char **argv)
1595 {
1596 int rc = pcmk_rc_ok;
1597 crm_cluster_t *cluster = NULL;
1598 crm_ipc_t *old_instance = NULL;
1599
1600 GError *error = NULL;
1601
1602 GOptionGroup *output_group = NULL;
1603 pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
1604 gchar **processed_args = pcmk__cmdline_preproc(argv, "l");
1605 GOptionContext *context = build_arg_context(args, &output_group);
1606
1607 crm_log_preinit(NULL, argc, argv);
1608
1609 pcmk__register_formats(output_group, formats);
1610 if (!g_option_context_parse_strv(context, &processed_args, &error)) {
1611 exit_code = CRM_EX_USAGE;
1612 goto done;
1613 }
1614
1615 rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
1616 if (rc != pcmk_rc_ok) {
1617 exit_code = CRM_EX_ERROR;
1618 g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
1619 "Error creating output format %s: %s",
1620 args->output_ty, pcmk_rc_str(rc));
1621 goto done;
1622 }
1623
1624 if (args->version) {
1625 out->version(out, false);
1626 goto done;
1627 }
1628
1629 if ((g_strv_length(processed_args) >= 2)
1630 && pcmk__str_eq(processed_args[1], "metadata", pcmk__str_none)) {
1631 fencer_metadata();
1632 goto done;
1633 }
1634
1635
1636 pcmk__add_logfiles(options.log_files, out);
1637
1638 crm_log_init(NULL, LOG_INFO + args->verbosity, TRUE,
1639 (args->verbosity > 0), argc, argv, FALSE);
1640
1641 crm_notice("Starting Pacemaker fencer");
1642
1643 old_instance = crm_ipc_new("stonith-ng", 0);
1644 if (old_instance == NULL) {
1645
1646
1647
1648 exit_code = CRM_EX_FATAL;
1649 goto done;
1650 }
1651
1652 if (crm_ipc_connect(old_instance)) {
1653
1654 crm_ipc_close(old_instance);
1655 crm_ipc_destroy(old_instance);
1656 crm_err("pacemaker-fenced is already active, aborting startup");
1657 goto done;
1658 } else {
1659
1660 crm_ipc_destroy(old_instance);
1661 old_instance = NULL;
1662 }
1663
1664 mainloop_add_signal(SIGTERM, stonith_shutdown);
1665
1666 crm_peer_init();
1667
1668 fenced_data_set = pe_new_working_set();
1669 CRM_ASSERT(fenced_data_set != NULL);
1670
1671 cluster = pcmk_cluster_new();
1672
1673
1674
1675
1676
1677 rc = pcmk__log_output_new(&logger_out) != pcmk_rc_ok;
1678 if (rc != pcmk_rc_ok) {
1679 exit_code = CRM_EX_FATAL;
1680 g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
1681 "Error creating output format log: %s", pcmk_rc_str(rc));
1682 goto done;
1683 }
1684 pe__register_messages(logger_out);
1685 pcmk__register_lib_messages(logger_out);
1686 pcmk__output_set_log_level(logger_out, LOG_TRACE);
1687 fenced_data_set->priv = logger_out;
1688
1689 if (!stand_alone) {
1690 #if SUPPORT_COROSYNC
1691 if (is_corosync_cluster()) {
1692 cluster->destroy = stonith_peer_cs_destroy;
1693 cluster->cpg.cpg_deliver_fn = stonith_peer_ais_callback;
1694 cluster->cpg.cpg_confchg_fn = pcmk_cpg_membership;
1695 }
1696 #endif
1697
1698 crm_set_status_callback(&st_peer_update_callback);
1699
1700 if (crm_cluster_connect(cluster) == FALSE) {
1701 exit_code = CRM_EX_FATAL;
1702 crm_crit("Cannot sign in to the cluster... terminating");
1703 goto done;
1704 }
1705 pcmk__str_update(&stonith_our_uname, cluster->uname);
1706
1707 if (!options.no_cib_connect) {
1708 setup_cib();
1709 }
1710
1711 } else {
1712 pcmk__str_update(&stonith_our_uname, "localhost");
1713 crm_warn("Stand-alone mode is deprecated and will be removed "
1714 "in a future release");
1715 }
1716
1717 init_device_list();
1718 init_topology_list();
1719
1720 pcmk__serve_fenced_ipc(&ipcs, &ipc_callbacks);
1721
1722
1723 mainloop = g_main_loop_new(NULL, FALSE);
1724 crm_notice("Pacemaker fencer successfully started and accepting connections");
1725 g_main_loop_run(mainloop);
1726
1727 done:
1728 g_strfreev(processed_args);
1729 pcmk__free_arg_context(context);
1730
1731 g_strfreev(options.log_files);
1732
1733 stonith_cleanup();
1734 pcmk_cluster_free(cluster);
1735 pe_free_working_set(fenced_data_set);
1736
1737 pcmk__output_and_clear_error(&error, out);
1738
1739 if (logger_out != NULL) {
1740 logger_out->finish(logger_out, exit_code, true, NULL);
1741 pcmk__output_free(logger_out);
1742 }
1743
1744 if (out != NULL) {
1745 out->finish(out, exit_code, true, NULL);
1746 pcmk__output_free(out);
1747 }
1748
1749 pcmk__unregister_formats();
1750 crm_exit(exit_code);
1751 }