This source file includes following definitions.
- valid_cman_name
- plugin_get_details
- send_plugin_text
- terminate_cs_connection
- plugin_handle_membership
- plugin_default_deliver_message
- plugin_dispatch
- plugin_destroy
- pcmk_cman_dispatch
- cman_event_callback
- init_cman_connection
- cluster_connect_quorum
- init_cs_connection_classic
- pcmk_mcp_dispatch
- pcmk_mcp_destroy
- init_cs_connection
- classic_node_name
- cman_node_name
- init_cs_connection_once
- check_message_sanity
- get_config_opt
- config_find_init
- config_find_next
- find_corosync_variant
- crm_is_corosync_peer_active
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20 #include <crm/cluster/internal.h>
21 #include <bzlib.h>
22 #include <crm/common/ipc.h>
23 #include <crm/cluster.h>
24 #include <crm/common/mainloop.h>
25 #include <sys/utsname.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28
29 #if SUPPORT_COROSYNC
30 # include <corosync/confdb.h>
31 # include <corosync/corodefs.h>
32 # include <corosync/cpg.h>
33 # include <corosync/cfg.h>
34 #endif
35
36 #if HAVE_CMAP
37 # include <corosync/cmap.h>
38 #endif
39
40 #if SUPPORT_CMAN
41 # include <libcman.h>
42 cman_handle_t pcmk_cman_handle = NULL;
43 #endif
44
45 int ais_membership_timer = 0;
46 gboolean ais_membership_force = FALSE;
47 int plugin_dispatch(gpointer user_data);
48
49 int ais_fd_sync = -1;
50 int ais_fd_async = -1;
51 void *ais_ipc_ctx = NULL;
52
53 hdb_handle_t ais_ipc_handle = 0;
54
55 #if SUPPORT_CMAN
56 static bool valid_cman_name(const char *name, uint32_t nodeid)
57 {
58 bool rc = TRUE;
59
60
61 char *fakename = crm_strdup_printf("Node%d", nodeid);
62
63 if(crm_str_eq(fakename, name, TRUE)) {
64 rc = FALSE;
65 crm_notice("Ignoring inferred name from cman: %s", fakename);
66 }
67 free(fakename);
68 return rc;
69 }
70 #endif
71
72 static gboolean
73 plugin_get_details(uint32_t * id, char **uname)
74 {
75 struct iovec iov;
76 int retries = 0;
77 int rc = CS_OK;
78 cs_ipc_header_response_t header;
79 struct crm_ais_nodeid_resp_s answer;
80
81 static uint32_t local_id = 0;
82 static char *local_uname = NULL;
83
84 if(local_id) {
85 if(id) *id = local_id;
86 if(uname) *uname = strdup(local_uname);
87 return TRUE;
88 }
89
90 header.error = CS_OK;
91 header.id = crm_class_nodeid;
92 header.size = sizeof(cs_ipc_header_response_t);
93
94 iov.iov_base = &header;
95 iov.iov_len = header.size;
96
97 retry:
98 errno = 0;
99 rc = coroipcc_msg_send_reply_receive(ais_ipc_handle, &iov, 1, &answer, sizeof(answer));
100 if (rc == CS_OK) {
101 CRM_CHECK(answer.header.size == sizeof(struct crm_ais_nodeid_resp_s),
102 crm_err("Odd message: id=%d, size=%d, error=%d",
103 answer.header.id, answer.header.size, answer.header.error));
104 CRM_CHECK(answer.header.id == crm_class_nodeid,
105 crm_err("Bad response id: %d", answer.header.id));
106 }
107
108 if ((rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) && retries < 20) {
109 retries++;
110 crm_info("Peer overloaded: Re-sending message (Attempt %d of 20)", retries);
111 sleep(retries);
112 goto retry;
113 }
114
115 if (rc != CS_OK) {
116 crm_err("Sending nodeid request: FAILED (rc=%d): %s", rc, ais_error2text(rc));
117 return FALSE;
118
119 } else if (answer.header.error != CS_OK) {
120 crm_err("Bad response from peer: (rc=%d): %s", rc, ais_error2text(rc));
121 return FALSE;
122 }
123
124 crm_info("Server details: id=%u uname=%s cname=%s", answer.id, answer.uname, answer.cname);
125
126 local_id = answer.id;
127 local_uname = strdup(answer.uname);
128
129 if(id) *id = local_id;
130 if(uname) *uname = strdup(local_uname);
131 return TRUE;
132 }
133
134 bool
135 send_plugin_text(int class, struct iovec *iov)
136 {
137 int rc = CS_OK;
138 int retries = 0;
139 int buf_len = sizeof(cs_ipc_header_response_t);
140 char *buf = malloc(buf_len);
141 AIS_Message *ais_msg = (AIS_Message*)iov[0].iov_base;
142 cs_ipc_header_response_t *header = (cs_ipc_header_response_t *)(void*)buf;
143
144 CRM_ASSERT(buf != NULL);
145
146 CRM_CHECK(class < 6, crm_err("Invalid message class: %d", class);
147 return FALSE);
148
149 do {
150 if (rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) {
151 retries++;
152 crm_info("Peer overloaded or membership in flux:"
153 " Re-sending message (Attempt %d of 20)", retries);
154 sleep(retries);
155 }
156
157 errno = 0;
158 rc = coroipcc_msg_send_reply_receive(ais_ipc_handle, iov, 1, buf, buf_len);
159
160 } while ((rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) && retries < 20);
161
162 if (rc == CS_OK) {
163 CRM_CHECK(header->size == sizeof(cs_ipc_header_response_t),
164 crm_err("Odd message: id=%d, size=%d, class=%d, error=%d",
165 header->id, header->size, class, header->error));
166
167 CRM_ASSERT(buf_len >= header->size);
168 CRM_CHECK(header->id == CRM_MESSAGE_IPC_ACK,
169 crm_err("Bad response id (%d) for request (%d)", header->id,
170 ais_msg->header.id));
171 CRM_CHECK(header->error == CS_OK, rc = header->error);
172
173 } else {
174 crm_perror(LOG_ERR, "Sending plugin message %d FAILED: %s (%d)",
175 ais_msg->id, ais_error2text(rc), rc);
176 }
177
178 free(iov[0].iov_base);
179 free(iov);
180 free(buf);
181
182 return (rc == CS_OK);
183 }
184
185 void
186 terminate_cs_connection(crm_cluster_t *cluster)
187 {
188 crm_info("Disconnecting from Corosync");
189
190 if (is_classic_ais_cluster()) {
191 if (ais_ipc_handle) {
192 crm_trace("Disconnecting plugin");
193 coroipcc_service_disconnect(ais_ipc_handle);
194 ais_ipc_handle = 0;
195 } else {
196 crm_info("No plugin connection");
197 }
198 }
199 cluster_disconnect_cpg(cluster);
200
201 # if SUPPORT_CMAN
202 if (is_cman_cluster()) {
203 if (pcmk_cman_handle) {
204 crm_info("Disconnecting cman");
205 if (cman_stop_notification(pcmk_cman_handle) >= 0) {
206 crm_info("Destroying cman");
207 cman_finish(pcmk_cman_handle);
208 }
209
210 } else {
211 crm_info("No cman connection");
212 }
213 }
214 # endif
215 ais_fd_async = -1;
216 ais_fd_sync = -1;
217
218 crm_notice("Disconnected from Corosync");
219 }
220
221 void
222 plugin_handle_membership(AIS_Message *msg)
223 {
224 if (msg->header.id == crm_class_members || msg->header.id == crm_class_quorum) {
225 xmlNode *member = NULL;
226 const char *value = NULL;
227 gboolean quorate = FALSE;
228 xmlNode *xml = string2xml(msg->data);
229
230 if (xml == NULL) {
231 crm_err("Invalid membership update: %s", msg->data);
232 return;
233 }
234
235 value = crm_element_value(xml, "quorate");
236 CRM_CHECK(value != NULL, crm_log_xml_err(xml, "No quorum value:"); return);
237 if (crm_is_true(value)) {
238 quorate = TRUE;
239 }
240
241 value = crm_element_value(xml, "id");
242 CRM_CHECK(value != NULL, crm_log_xml_err(xml, "No membership id"); return);
243 crm_peer_seq = crm_int_helper(value, NULL);
244
245 if (quorate != crm_have_quorum) {
246 crm_notice("Membership %s: quorum %s", value, quorate ? "acquired" : "lost");
247 crm_have_quorum = quorate;
248
249 } else {
250 crm_info("Membership %s: quorum %s", value, quorate ? "retained" : "still lost");
251 }
252
253 for (member = __xml_first_child(xml); member != NULL; member = __xml_next(member)) {
254 const char *id_s = crm_element_value(member, "id");
255 const char *addr = crm_element_value(member, "addr");
256 const char *uname = crm_element_value(member, "uname");
257 const char *state = crm_element_value(member, "state");
258 const char *born_s = crm_element_value(member, "born");
259 const char *seen_s = crm_element_value(member, "seen");
260 const char *votes_s = crm_element_value(member, "votes");
261 const char *procs_s = crm_element_value(member, "processes");
262
263 int votes = crm_int_helper(votes_s, NULL);
264 unsigned int id = crm_int_helper(id_s, NULL);
265 unsigned int procs = crm_int_helper(procs_s, NULL);
266
267
268 uint64_t born = crm_int_helper(born_s, NULL);
269 uint64_t seen = crm_int_helper(seen_s, NULL);
270
271 crm_update_peer(__FUNCTION__, id, born, seen, votes, procs, uname, uname, addr, state);
272 }
273 free_xml(xml);
274 }
275 }
276
277 static void
278 plugin_default_deliver_message(cpg_handle_t handle,
279 const struct cpg_name *groupName,
280 uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
281 {
282 uint32_t kind = 0;
283 const char *from = NULL;
284 char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
285
286 free(data);
287 }
288
289 int
290 plugin_dispatch(gpointer user_data)
291 {
292 int rc = CS_OK;
293 crm_cluster_t *cluster = (crm_cluster_t *) user_data;
294
295 do {
296 char *buffer = NULL;
297
298 rc = coroipcc_dispatch_get(ais_ipc_handle, (void **)&buffer, 0);
299 if (rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) {
300 return 0;
301 }
302 if (rc != CS_OK) {
303 crm_perror(LOG_ERR, "Receiving message body failed: (%d) %s", rc, ais_error2text(rc));
304 return -1;
305 }
306 if (buffer == NULL) {
307
308 return 0;
309 }
310
311
312
313
314 if (cluster && cluster->cpg.cpg_deliver_fn) {
315 cluster->cpg.cpg_deliver_fn(0, NULL, 0, 0, buffer, 0);
316
317 } else {
318 plugin_default_deliver_message(0, NULL, 0, 0, buffer, 0);
319 }
320
321 coroipcc_dispatch_put(ais_ipc_handle);
322
323 } while (ais_ipc_handle);
324
325 return 0;
326 }
327
328 static void
329 plugin_destroy(gpointer user_data)
330 {
331 crm_err("AIS connection terminated");
332 ais_fd_sync = -1;
333 crm_exit(ENOTCONN);
334 }
335
336 # if SUPPORT_CMAN
337
338 static int
339 pcmk_cman_dispatch(gpointer user_data)
340 {
341 int rc = cman_dispatch(pcmk_cman_handle, CMAN_DISPATCH_ALL);
342
343 if (rc < 0) {
344 crm_err("Connection to cman failed: %d", rc);
345 pcmk_cman_handle = 0;
346 return FALSE;
347 }
348 return TRUE;
349 }
350
351 # define MAX_NODES 256
352
353 static void
354 cman_event_callback(cman_handle_t handle, void *privdata, int reason, int arg)
355 {
356 int rc = 0, lpc = 0, node_count = 0;
357
358 cman_cluster_t cluster;
359 static cman_node_t cman_nodes[MAX_NODES];
360
361 gboolean(*dispatch) (unsigned long long, gboolean) = privdata;
362
363 switch (reason) {
364 case CMAN_REASON_STATECHANGE:
365
366 memset(&cluster, 0, sizeof(cluster));
367 rc = cman_get_cluster(pcmk_cman_handle, &cluster);
368 if (rc < 0) {
369 crm_err("Couldn't query cman cluster details: %d %d", rc, errno);
370 return;
371 }
372
373 crm_peer_seq = cluster.ci_generation;
374 if (arg != crm_have_quorum) {
375 crm_notice("Membership %llu: quorum %s", crm_peer_seq, arg ? "acquired" : "lost");
376 crm_have_quorum = arg;
377
378 } else {
379 crm_info("Membership %llu: quorum %s", crm_peer_seq,
380 arg ? "retained" : "still lost");
381 }
382
383 memset(cman_nodes, 0, MAX_NODES * sizeof(cman_node_t));
384 rc = cman_get_nodes(pcmk_cman_handle, MAX_NODES, &node_count, cman_nodes);
385 if (rc < 0) {
386 crm_err("Couldn't query cman node list: %d %d", rc, errno);
387 return;
388 }
389
390 for (lpc = 0; lpc < node_count; lpc++) {
391 crm_node_t *peer = NULL;
392 const char *name = NULL;
393
394 if (cman_nodes[lpc].cn_nodeid == 0) {
395
396
397 continue;
398 }
399
400 if(valid_cman_name(cman_nodes[lpc].cn_name, cman_nodes[lpc].cn_nodeid)) {
401 name = cman_nodes[lpc].cn_name;
402 }
403
404 peer = crm_get_peer(cman_nodes[lpc].cn_nodeid, name);
405 if(cman_nodes[lpc].cn_member) {
406 crm_update_peer_state(__FUNCTION__, peer, CRM_NODE_MEMBER, crm_peer_seq);
407
408 } else if(peer->state) {
409 crm_update_peer_state(__FUNCTION__, peer, CRM_NODE_LOST, 0);
410
411 } else {
412 crm_info("State of node %s[%u] is still unknown", peer->uname, peer->id);
413 }
414 }
415
416 if (dispatch) {
417 dispatch(crm_peer_seq, crm_have_quorum);
418 }
419 break;
420
421 case CMAN_REASON_TRY_SHUTDOWN:
422
423 crm_notice("CMAN wants to shut down: %s", arg ? "forced" : "optional");
424 cman_replyto_shutdown(pcmk_cman_handle, 0);
425 break;
426
427 case CMAN_REASON_CONFIG_UPDATE:
428
429 break;
430 }
431 }
432 # endif
433
434 gboolean
435 init_cman_connection(gboolean(*dispatch) (unsigned long long, gboolean), void (*destroy) (gpointer))
436 {
437 # if SUPPORT_CMAN
438 int rc = -1, fd = -1;
439 cman_cluster_t cluster;
440
441 struct mainloop_fd_callbacks cman_fd_callbacks = {
442 .dispatch = pcmk_cman_dispatch,
443 .destroy = destroy,
444 };
445
446 crm_info("Configuring Pacemaker to obtain quorum from cman");
447
448 memset(&cluster, 0, sizeof(cluster));
449
450 pcmk_cman_handle = cman_init(dispatch);
451 if (pcmk_cman_handle == NULL || cman_is_active(pcmk_cman_handle) == FALSE) {
452 crm_err("Couldn't connect to cman");
453 goto cman_bail;
454 }
455
456 rc = cman_start_notification(pcmk_cman_handle, cman_event_callback);
457 if (rc < 0) {
458 crm_err("Couldn't register for cman notifications: %d %d", rc, errno);
459 goto cman_bail;
460 }
461
462
463 cman_event_callback(pcmk_cman_handle, dispatch, CMAN_REASON_STATECHANGE,
464 cman_is_quorate(pcmk_cman_handle));
465
466 fd = cman_get_fd(pcmk_cman_handle);
467
468 mainloop_add_fd("cman", G_PRIORITY_MEDIUM, fd, dispatch, &cman_fd_callbacks);
469
470 cman_bail:
471 if (rc < 0) {
472 cman_finish(pcmk_cman_handle);
473 return FALSE;
474 }
475 # else
476 crm_err("cman qorum is not supported in this build");
477 crm_exit(DAEMON_RESPAWN_STOP);
478 # endif
479 return TRUE;
480 }
481
482 # ifdef SUPPORT_COROSYNC
483
484 gboolean
485 cluster_connect_quorum(gboolean(*dispatch) (unsigned long long, gboolean),
486 void (*destroy) (gpointer))
487 {
488 crm_err("The Corosync quorum API is not supported in this build");
489 crm_exit(DAEMON_RESPAWN_STOP);
490 return TRUE;
491 }
492
493 static gboolean
494 init_cs_connection_classic(crm_cluster_t * cluster)
495 {
496 int rc;
497 int pid = 0;
498 char *pid_s = NULL;
499 const char *name = NULL;
500 crm_node_t *peer = NULL;
501 enum crm_proc_flag proc = 0;
502
503 struct mainloop_fd_callbacks ais_fd_callbacks = {
504 .dispatch = plugin_dispatch,
505 .destroy = cluster->destroy,
506 };
507
508 crm_info("Creating connection to our Corosync plugin");
509 rc = coroipcc_service_connect(COROSYNC_SOCKET_NAME, PCMK_SERVICE_ID,
510 AIS_IPC_MESSAGE_SIZE, AIS_IPC_MESSAGE_SIZE, AIS_IPC_MESSAGE_SIZE,
511 &ais_ipc_handle);
512 if (ais_ipc_handle) {
513 coroipcc_fd_get(ais_ipc_handle, &ais_fd_async);
514 } else {
515 crm_info("Connection to our Corosync plugin (%d) failed: %s (%d)",
516 PCMK_SERVICE_ID, strerror(errno), errno);
517 return FALSE;
518 }
519 if (ais_fd_async <= 0 && rc == CS_OK) {
520 crm_err("No context created, but connection reported 'ok'");
521 rc = CS_ERR_LIBRARY;
522 }
523 if (rc != CS_OK) {
524 crm_info("Connection to our Corosync plugin (%d) failed: %s (%d)", PCMK_SERVICE_ID,
525 ais_error2text(rc), rc);
526 }
527
528 if (rc != CS_OK) {
529 return FALSE;
530 }
531
532 if (ais_fd_callbacks.destroy == NULL) {
533 ais_fd_callbacks.destroy = plugin_destroy;
534 }
535
536 mainloop_add_fd("corosync-plugin", G_PRIORITY_MEDIUM, ais_fd_async, cluster, &ais_fd_callbacks);
537 crm_info("AIS connection established");
538
539 pid = getpid();
540 pid_s = crm_itoa(pid);
541 send_cluster_text(crm_class_cluster, pid_s, TRUE, NULL, crm_msg_ais);
542 free(pid_s);
543
544 cluster->nodeid = get_local_nodeid(0);
545
546 name = get_local_node_name();
547 plugin_get_details(NULL, &(cluster->uname));
548 if (safe_str_neq(name, cluster->uname)) {
549 crm_crit("Node name mismatch! Corosync supplied %s but our lookup returned %s",
550 cluster->uname, name);
551 crm_notice
552 ("Node name mismatches usually occur when assigned automatically by DHCP servers");
553 crm_exit(ENOTUNIQ);
554 }
555
556 proc = text2proc(crm_system_name);
557 peer = crm_get_peer(cluster->nodeid, cluster->uname);
558 crm_update_peer_proc(__FUNCTION__, peer, proc|crm_proc_plugin, ONLINESTATUS);
559
560 return TRUE;
561 }
562
563 static int
564 pcmk_mcp_dispatch(const char *buffer, ssize_t length, gpointer userdata)
565 {
566 xmlNode *msg = string2xml(buffer);
567
568 if (msg && is_classic_ais_cluster()) {
569 xmlNode *node = NULL;
570
571 for (node = __xml_first_child(msg); node != NULL; node = __xml_next(node)) {
572 int id = 0;
573 int children = 0;
574 const char *uname = crm_element_value(node, "uname");
575
576 crm_element_value_int(node, "id", &id);
577 crm_element_value_int(node, "processes", &children);
578 if (id == 0) {
579 crm_log_xml_err(msg, "Bad Update");
580 } else {
581 crm_node_t *peer = crm_get_peer(id, uname);
582
583 crm_update_peer_proc(__FUNCTION__, peer, children, NULL);
584 }
585 }
586 }
587
588 free_xml(msg);
589 return 0;
590 }
591
592 static void
593 pcmk_mcp_destroy(gpointer user_data)
594 {
595 void (*callback) (gpointer data) = user_data;
596
597 if (callback) {
598 callback(NULL);
599 }
600 }
601
602 gboolean
603 init_cs_connection(crm_cluster_t * cluster)
604 {
605 int retries = 0;
606
607 static struct ipc_client_callbacks mcp_callbacks = {
608 .dispatch = pcmk_mcp_dispatch,
609 .destroy = pcmk_mcp_destroy
610 };
611
612 while (retries < 5) {
613 int rc = init_cs_connection_once(cluster);
614
615 retries++;
616 switch (rc) {
617 case CS_OK:
618 if (getenv("HA_mcp") && get_cluster_type() != pcmk_cluster_cman) {
619 xmlNode *poke = create_xml_node(NULL, "poke");
620 mainloop_io_t *ipc =
621 mainloop_add_ipc_client(CRM_SYSTEM_MCP, G_PRIORITY_MEDIUM, 0,
622 cluster->destroy, &mcp_callbacks);
623
624 crm_ipc_send(mainloop_get_ipc_client(ipc), poke, 0, 0, NULL);
625 free_xml(poke);
626 }
627 return TRUE;
628 break;
629 case CS_ERR_TRY_AGAIN:
630 case CS_ERR_QUEUE_FULL:
631 sleep(retries);
632 break;
633 default:
634 return FALSE;
635 }
636 }
637
638 crm_err("Retry count exceeded: %d", retries);
639 return FALSE;
640 }
641
642 char *
643 classic_node_name(uint32_t nodeid)
644 {
645 return NULL;
646 }
647
648 char *
649 cman_node_name(uint32_t nodeid)
650 {
651 char *name = NULL;
652
653 # if SUPPORT_CMAN
654 cman_node_t us;
655 cman_handle_t cman;
656
657 cman = cman_init(NULL);
658 if (cman != NULL && cman_is_active(cman)) {
659
660 memset(&us, 0, sizeof(cman_node_t));
661 cman_get_node(cman, nodeid, &us);
662 if(valid_cman_name(us.cn_name, nodeid)) {
663 name = strdup(us.cn_name);
664 crm_info("Using CMAN node name %s for %u", name, nodeid);
665 }
666 }
667
668 cman_finish(cman);
669 # endif
670 if (name == NULL) {
671 crm_debug("Unable to get node name for nodeid %u", nodeid);
672 }
673 return name;
674 }
675
676 extern int set_cluster_type(enum cluster_type_e type);
677
678 gboolean
679 init_cs_connection_once(crm_cluster_t * cluster)
680 {
681 crm_node_t *peer = NULL;
682 enum cluster_type_e stack = get_cluster_type();
683
684 crm_peer_init();
685
686
687 switch (stack) {
688 case pcmk_cluster_classic_ais:
689 if (init_cs_connection_classic(cluster) == FALSE) {
690 return FALSE;
691 }
692 break;
693 case pcmk_cluster_cman:
694 if (cluster_connect_cpg(cluster) == FALSE) {
695 return FALSE;
696 }
697 break;
698 case pcmk_cluster_heartbeat:
699 crm_info("Could not find an active corosync based cluster");
700 return FALSE;
701 break;
702 default:
703 crm_err("Invalid cluster type: %s (%d)", name_for_cluster_type(stack), stack);
704 return FALSE;
705 break;
706 }
707
708 crm_info("Connection to '%s': established", name_for_cluster_type(stack));
709
710 cluster->nodeid = get_local_nodeid(0);
711 if(cluster->nodeid == 0) {
712 crm_err("Could not establish local nodeid");
713 return FALSE;
714 }
715
716 cluster->uname = get_node_name(0);
717 if(cluster->uname == NULL) {
718 crm_err("Could not establish local node name");
719 return FALSE;
720 }
721
722
723 peer = crm_get_peer(cluster->nodeid, cluster->uname);
724 cluster->uuid = get_corosync_uuid(peer);
725
726 return TRUE;
727 }
728
729 gboolean
730 check_message_sanity(const AIS_Message * msg, const char *data)
731 {
732 gboolean sane = TRUE;
733 int dest = msg->host.type;
734 int tmp_size = msg->header.size - sizeof(AIS_Message);
735
736 if (sane && msg->header.size == 0) {
737 crm_warn("Message with no size");
738 sane = FALSE;
739 }
740
741 if (sane && msg->header.error != CS_OK) {
742 crm_warn("Message header contains an error: %d", msg->header.error);
743 sane = FALSE;
744 }
745
746 if (sane && ais_data_len(msg) != tmp_size) {
747 crm_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg),
748 tmp_size);
749 sane = TRUE;
750 }
751
752 if (sane && ais_data_len(msg) == 0) {
753 crm_warn("Message with no payload");
754 sane = FALSE;
755 }
756
757 if (sane && data && msg->is_compressed == FALSE) {
758 int str_size = strlen(data) + 1;
759
760 if (ais_data_len(msg) != str_size) {
761 int lpc = 0;
762
763 crm_warn("Message payload is corrupted: expected %d bytes, got %d",
764 ais_data_len(msg), str_size);
765 sane = FALSE;
766 for (lpc = (str_size - 10); lpc < msg->size; lpc++) {
767 if (lpc < 0) {
768 lpc = 0;
769 }
770 crm_debug("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]);
771 }
772 }
773 }
774
775 if (sane == FALSE) {
776 crm_err("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
777 msg->id, ais_dest(&(msg->host)), msg_type2text(dest),
778 ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
779 msg->sender.pid, msg->is_compressed, ais_data_len(msg), msg->header.size);
780
781 } else {
782 crm_trace
783 ("Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
784 msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)),
785 msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed,
786 ais_data_len(msg), msg->header.size);
787 }
788
789 return sane;
790 }
791 #endif
792
793 static int
794 get_config_opt(confdb_handle_t config,
795 hdb_handle_t object_handle, const char *key, char **value, const char *fallback)
796 {
797 size_t len = 0;
798 char *env_key = NULL;
799 const char *env_value = NULL;
800 char buffer[256];
801
802 if (*value) {
803 free(*value);
804 *value = NULL;
805 }
806
807 if (object_handle > 0) {
808 if (CS_OK == confdb_key_get(config, object_handle, key, strlen(key), &buffer, &len)) {
809 *value = strdup(buffer);
810 }
811 }
812
813 if (*value) {
814 crm_info("Found '%s' for option: %s", *value, key);
815 return 0;
816 }
817
818 env_key = crm_concat("HA", key, '_');
819 env_value = getenv(env_key);
820 free(env_key);
821
822 if (*value) {
823 crm_info("Found '%s' in ENV for option: %s", *value, key);
824 *value = strdup(env_value);
825 return 0;
826 }
827
828 if (fallback) {
829 crm_info("Defaulting to '%s' for option: %s", fallback, key);
830 *value = strdup(fallback);
831
832 } else {
833 crm_info("No default for option: %s", key);
834 }
835
836 return -1;
837 }
838
839 static confdb_handle_t
840 config_find_init(confdb_handle_t config)
841 {
842 cs_error_t rc = CS_OK;
843 confdb_handle_t local_handle = OBJECT_PARENT_HANDLE;
844
845 rc = confdb_object_find_start(config, local_handle);
846 if (rc == CS_OK) {
847 return local_handle;
848 } else {
849 crm_err("Couldn't create search context: %d", rc);
850 }
851 return 0;
852 }
853
854 static hdb_handle_t
855 config_find_next(confdb_handle_t config, const char *name, confdb_handle_t top_handle)
856 {
857 cs_error_t rc = CS_OK;
858 hdb_handle_t local_handle = 0;
859
860 if (top_handle == 0) {
861 crm_err("Couldn't search for %s: no valid context", name);
862 return 0;
863 }
864
865 crm_trace("Searching for %s in " HDB_X_FORMAT, name, top_handle);
866 rc = confdb_object_find(config, top_handle, name, strlen(name), &local_handle);
867 if (rc != CS_OK) {
868 crm_info("No additional configuration supplied for: %s", name);
869 local_handle = 0;
870 } else {
871 crm_info("Processing additional %s options...", name);
872 }
873 return local_handle;
874 }
875
876 enum cluster_type_e
877 find_corosync_variant(void)
878 {
879 confdb_handle_t config;
880 enum cluster_type_e found = pcmk_cluster_unknown;
881
882 int rc;
883 char *value = NULL;
884 confdb_handle_t top_handle = 0;
885 hdb_handle_t local_handle = 0;
886 static confdb_callbacks_t callbacks = { };
887
888 rc = confdb_initialize(&config, &callbacks);
889 if (rc != CS_OK) {
890 crm_debug("Could not initialize Cluster Configuration Database API instance error %d", rc);
891 return found;
892 }
893
894 top_handle = config_find_init(config);
895 local_handle = config_find_next(config, "service", top_handle);
896 while (local_handle) {
897 get_config_opt(config, local_handle, "name", &value, NULL);
898 if (safe_str_eq("pacemaker", value)) {
899 found = pcmk_cluster_classic_ais;
900
901 get_config_opt(config, local_handle, "ver", &value, "0");
902 crm_trace("Found Pacemaker plugin version: %s", value);
903 break;
904 }
905
906 local_handle = config_find_next(config, "service", top_handle);
907 }
908
909 if (found == pcmk_cluster_unknown) {
910 top_handle = config_find_init(config);
911 local_handle = config_find_next(config, "quorum", top_handle);
912 get_config_opt(config, local_handle, "provider", &value, NULL);
913
914 if (safe_str_eq("quorum_cman", value)) {
915 crm_trace("Found CMAN quorum provider");
916 found = pcmk_cluster_cman;
917 }
918 }
919 free(value);
920
921 confdb_finalize(config);
922 if (found == pcmk_cluster_unknown) {
923 crm_err
924 ("Corosync is running, but Pacemaker could not find the CMAN or Pacemaker plugin loaded");
925 found = pcmk_cluster_invalid;
926 }
927 return found;
928 }
929
930 gboolean
931 crm_is_corosync_peer_active(const crm_node_t * node)
932 {
933 enum crm_proc_flag proc = crm_proc_none;
934
935 if (node == NULL) {
936 crm_trace("NULL");
937 return FALSE;
938
939 } else if (safe_str_neq(node->state, CRM_NODE_MEMBER)) {
940 crm_trace("%s: state=%s", node->uname, node->state);
941 return FALSE;
942
943 } else if (is_cman_cluster() && (node->processes & crm_proc_cpg)) {
944
945
946
947 crm_trace("%s: processes=%.8x", node->uname, node->processes);
948 return TRUE;
949
950 } else if (is_classic_ais_cluster()) {
951 if (node->processes < crm_proc_none) {
952 crm_debug("%s: unknown process list, assuming active for now", node->uname);
953 return TRUE;
954
955 } else if (is_set(node->processes, crm_proc_none)) {
956 crm_debug("%s: all processes are inactive", node->uname);
957 return FALSE;
958
959 } else if (is_not_set(node->processes, crm_proc_plugin)) {
960 crm_trace("%s: processes=%.8x", node->uname, node->processes);
961 return FALSE;
962 }
963 }
964
965 proc = text2proc(crm_system_name);
966 if (proc > crm_proc_none && (node->processes & proc) == 0) {
967 crm_trace("%s: proc %.8x not in %.8x", node->uname, proc, node->processes);
968 return FALSE;
969 }
970
971 return TRUE;
972 }