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