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