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