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