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