21 #include <sys/types.h>
23 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
35 #include <corosync/totem/totempg.h>
36 #include <corosync/engine/objdb.h>
37 #include <corosync/engine/config.h>
45 #include <sys/resource.h>
46 #include <sys/utsname.h>
47 #include <sys/socket.h>
67 static uint64_t local_born_on = 0;
79 #define MAX_RESPAWN 100
80 #define LOOPBACK_ID 16777343
81 #define crm_flag_none 0x00000000
82 #define crm_flag_members 0x00000001
84 struct crm_identify_msg_s {
97 { 0,
crm_proc_none,
crm_flag_none, 0, 0, FALSE,
"none", NULL, NULL, NULL, NULL },
98 { 0,
crm_proc_plugin,
crm_flag_none, 0, 0, FALSE,
"ais", NULL, NULL, NULL, NULL },
99 { 0,
crm_proc_lrmd,
crm_flag_none, 3, 0, TRUE,
"lrmd", NULL,
CRM_DAEMON_DIR"/lrmd", NULL, NULL },
100 { 0,
crm_proc_cib,
crm_flag_members, 1, 0, TRUE,
"cib",
CRM_DAEMON_USER,
CRM_DAEMON_DIR"/cib", NULL, NULL },
101 { 0,
crm_proc_crmd,
crm_flag_members, 6, 0, TRUE,
"crmd",
CRM_DAEMON_USER,
CRM_DAEMON_DIR"/crmd", NULL, NULL },
102 { 0,
crm_proc_attrd,
crm_flag_none, 4, 0, TRUE,
"attrd",
CRM_DAEMON_USER,
CRM_DAEMON_DIR"/attrd", NULL, NULL },
103 { 0,
crm_proc_stonithd,
crm_flag_none, 0, 0, TRUE,
"stonithd", NULL,
"/bin/false", NULL, NULL },
104 { 0,
crm_proc_pe,
crm_flag_none, 5, 0, TRUE,
"pengine",
CRM_DAEMON_USER,
CRM_DAEMON_DIR"/pengine", NULL, NULL },
105 { 0,
crm_proc_mgmtd,
crm_flag_none, 7, 0, TRUE,
"mgmtd", NULL,
HB_DAEMON_DIR"/mgmtd", NULL, NULL },
106 { 0,
crm_proc_stonith_ng,
crm_flag_members, 2, 0, TRUE,
"stonith-ng", NULL,
CRM_DAEMON_DIR"/stonithd", NULL, NULL },
118 const unsigned int *member_list,
size_t member_list_entries,
119 const unsigned int *left_list,
size_t left_list_entries,
120 const unsigned int *joined_list,
size_t joined_list_entries,
121 const struct memb_ring_id *ring_id);
128 void pcmk_ipc(
void *conn, ais_void_ptr * msg);
135 void pcmk_nodes(
void *conn, ais_void_ptr * msg);
146 get_process_list(
void)
155 for (lpc = 0; lpc <
SIZEOF(pcmk_children); lpc++) {
156 if (pcmk_children[lpc].
pid != 0) {
157 procs |= pcmk_children[lpc].
flag;
163 static struct corosync_lib_handler pcmk_lib_service[] = {
166 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
170 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
174 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
178 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
182 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
186 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
190 static struct corosync_exec_handler pcmk_exec_service[] = {
206 .private_data_size = 0,
207 .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
208 .allow_inquorate = CS_LIB_ALLOW_INQUORATE,
215 .lib_engine = pcmk_lib_service,
216 .lib_engine_count =
sizeof (pcmk_lib_service) /
sizeof (
struct corosync_lib_handler),
217 .exec_engine = pcmk_exec_service,
218 .exec_engine_count =
sizeof (pcmk_exec_service) /
sizeof (
struct corosync_exec_handler),
237 static struct lcr_iface openais_pcmk_ver0[2] = {
241 .versions_replace = 0,
242 .versions_replace_count = 0,
244 .dependency_count = 0,
252 .versions_replace = 0,
253 .versions_replace_count = 0,
255 .dependency_count = 0,
262 static struct lcr_comp pcmk_comp_ver0 = {
264 .ifaces = openais_pcmk_ver0
268 struct corosync_service_engine *
271 return (&pcmk_service_handler);
276 register_this_component(
void)
278 lcr_interfaces_set(&openais_pcmk_ver0[0], &pcmk_service_handler_iface);
279 lcr_interfaces_set(&openais_pcmk_ver0[1], &pcmk_service_handler_iface);
281 lcr_component_register(&pcmk_comp_ver0);
285 plugin_has_quorum(
void)
294 update_expected_votes(
int value)
298 ais_info(
"Cannot update expected quorum votes %d -> %d:"
299 " value cannot be less that the current number of votes",
310 process_ais_conf(
void)
313 gboolean any_log = FALSE;
314 hdb_handle_t top_handle = 0;
315 hdb_handle_t local_handle = 0;
336 ais_err(
"Logging to a file requested but no log file specified");
339 uid_t pcmk_uid = geteuid();
340 uid_t pcmk_gid = getegid();
342 FILE *logfile = fopen(value,
"a");
346 int logfd = fileno(logfile);
351 ignore = fchown(logfd, pcmk_uid, pcmk_gid);
352 ignore = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
355 fprintf(logfile,
"Could not set r/w permissions for uid=%d, gid=%d on %s\n",
356 pcmk_uid, pcmk_gid, value);
359 fprintf(logfile,
"Set r/w permissions for uid=%d, gid=%d on %s\n",
360 pcmk_uid, pcmk_gid, value);
368 ais_err(
"Couldn't create logfile: %s", value);
375 ais_info(
"User configured file based logging and explicitly disabled syslog.");
381 (
"Please enable some sort of logging, either 'to_file: on' or 'to_syslog: on'.");
382 ais_err(
"If you use file logging, be sure to also define a value for 'logfile'");
393 if (value && ais_str_eq(
"quorum_cman", value)) {
401 while (local_handle) {
403 pcmk_api->object_key_get(local_handle,
"name", strlen(
"name"), (
void **)&value, NULL);
404 if (ais_str_eq(
"pacemaker", value)) {
411 if (ais_str_eq(value,
"1")) {
412 ais_info(
"Enabling MCP mode: Use the Pacemaker init script to complete Pacemaker startup");
426 for (; lpc <
SIZEOF(pcmk_children); lpc++) {
445 pcmk_wait_dispatch(
void *arg)
447 struct timespec waitsleep = {
455 for (; lpc <
SIZEOF(pcmk_children); lpc++) {
456 if (pcmk_children[lpc].
pid > 0) {
458 pid_t
pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL);
463 }
else if (pid < 0) {
464 ais_perror(
"Call to wait4(%s) failed", pcmk_children[lpc].name);
469 pcmk_children[lpc].
pid = 0;
470 pcmk_children[lpc].
conn = NULL;
473 if (WIFSIGNALED(status)) {
474 int sig = WTERMSIG(status);
476 ais_err(
"Child process %s terminated with signal %d"
477 " (pid=%d, core=%s)",
478 pcmk_children[lpc].name, sig, pid,
479 WCOREDUMP(status) ?
"true" :
"false");
481 }
else if (WIFEXITED(status)) {
482 int rc = WEXITSTATUS(status);
485 "Child process %s exited (pid=%d, rc=%d)", pcmk_children[lpc].name,
489 ais_notice(
"Child process %s no longer wishes"
490 " to be respawned", pcmk_children[lpc].name);
491 pcmk_children[lpc].
respawn = FALSE;
506 if (pcmk_children[lpc].respawn_count >
MAX_RESPAWN) {
507 ais_err(
"Child respawn count exceeded by %s", pcmk_children[lpc].name);
508 pcmk_children[lpc].
respawn = FALSE;
510 if (pcmk_children[lpc].respawn) {
511 ais_notice(
"Respawning failed child process: %s", pcmk_children[lpc].name);
518 nanosleep(&waitsleep, 0);
524 pcmk_update_nodeid(
void)
539 snprintf(last_s, 31,
"%u", last);
550 build_path(
const char *path_c, mode_t mode)
552 int offset = 1, len = 0;
553 char *path = ais_strdup(path_c);
556 for (len = strlen(path); offset < len; offset++) {
557 if (path[offset] ==
'/') {
559 if (mkdir(path, mode) < 0 && errno != EEXIST) {
560 ais_perror(
"Could not create directory '%s'", path);
566 if (mkdir(path, mode) < 0 && errno != EEXIST) {
567 ais_perror(
"Could not create directory '%s'", path);
580 static int max =
SIZEOF(pcmk_children);
586 uid_t cs_uid = geteuid();
597 if (cs_uid != root_uid) {
598 ais_err(
"Corosync must be configured to start as 'root',"
599 " otherwise Pacemaker cannot manage services."
600 " Expected %d got %d", root_uid, cs_uid);
611 log_printf(LOG_INFO,
"Logging: Initialized %s\n", __FUNCTION__);
613 rc = getrlimit(RLIMIT_CORE, &cores);
615 ais_perror(
"Cannot determine current maximum core size.");
617 if (cores.rlim_max == 0 && geteuid() == 0) {
618 cores.rlim_max = RLIM_INFINITY;
620 ais_info(
"Maximum core file size is: %lu", cores.rlim_max);
622 cores.rlim_cur = cores.rlim_max;
624 rc = setrlimit(RLIMIT_CORE, &cores);
626 ais_perror(
"Core file generation will remain disabled."
627 " Core files are an important diagnositic tool,"
628 " please consider enabling them by default.");
634 if (system(
"echo 1 > /proc/sys/kernel/core_uses_pid") != 0) {
635 ais_perror(
"Could not enable /proc/sys/kernel/core_uses_pid");
661 pcmk_update_nodeid();
665 for (start_seq = 1; start_seq < max; start_seq++) {
667 for (lpc = 0; lpc < max; lpc++) {
668 if (start_seq == pcmk_children[lpc].start_seq) {
680 totempg_ifaces_print(
unsigned int nodeid)
686 unsigned int iface_count;
690 iface_string[0] =
'\0';
692 res = totempg_ifaces_get(nodeid, interfaces, &status, &iface_count);
694 return (
"no interface found for nodeid");
697 for (i = 0; i < iface_count; i++) {
698 sprintf(one_iface,
"r(%d) ip(%s), ", i, totemip_print(&interfaces[i]));
699 strcat(iface_string, one_iface);
701 return (iface_string);
706 ais_mark_unseen_peer_dead(gpointer key, gpointer value, gpointer user_data)
708 int *changed = user_data;
712 ais_info(
"Node %s was not seen in the previous transition", node->
uname);
720 const unsigned int *member_list,
size_t member_list_entries,
721 const unsigned int *left_list,
size_t left_list_entries,
722 const unsigned int *joined_list,
size_t joined_list_entries,
723 const struct memb_ring_id *ring_id)
730 switch (configuration_type) {
731 case TOTEM_CONFIGURATION_REGULAR:
734 case TOTEM_CONFIGURATION_TRANSITIONAL:
739 ais_notice(
"%s membership event on ring %lld: memb=%ld, new=%ld, lost=%ld",
740 do_update ?
"Stable" :
"Transitional", ring_id->seq,
741 (
long)member_list_entries, (
long)joined_list_entries, (
long)left_list_entries);
743 if (do_update == 0) {
744 for (lpc = 0; lpc < joined_list_entries; lpc++) {
745 const char *prefix =
"new: ";
750 for (lpc = 0; lpc < member_list_entries; lpc++) {
751 const char *prefix =
"memb:";
756 for (lpc = 0; lpc < left_list_entries; lpc++) {
757 const char *prefix =
"lost:";
765 for (lpc = 0; lpc < joined_list_entries; lpc++) {
766 const char *prefix =
"NEW: ";
775 if (node->
addr == NULL) {
776 const char *addr = totempg_ifaces_print(nodeid);
778 node->
addr = ais_strdup(addr);
783 for (lpc = 0; lpc < member_list_entries; lpc++) {
784 const char *prefix =
"MEMB:";
792 for (lpc = 0; lpc < left_list_entries; lpc++) {
793 const char *prefix =
"LOST:";
800 if (changed && joined_list_entries == 0 && left_list_entries == 0) {
801 ais_err(
"Something strange happened: %d", changed);
806 g_hash_table_foreach(
membership_list, ais_mark_unseen_peer_dead, &changed);
808 if (member_list_entries > 1) {
818 pcmk_update_nodeid();
829 const char *client = NULL;
830 void *async_conn = conn;
832 for (; lpc <
SIZEOF(pcmk_children); lpc++) {
833 if (pcmk_children[lpc].conn == conn) {
836 pcmk_children[lpc].
pid = 0;
838 pcmk_children[lpc].
conn = NULL;
840 client = pcmk_children[lpc].
name;
849 do_ais_log(LOG_INFO,
"Client %s (conn=%p, async-conn=%p) left", client, conn, async_conn);
851 do_ais_log((LOG_DEBUG + 1),
"Client %s (conn=%p, async-conn=%p) left",
852 "unknown-transient", conn, async_conn);
875 ais_trace(
"Performing endian conversion...");
876 ais_msg->
id = swab32(ais_msg->
id);
877 ais_msg->
size = swab32(ais_msg->
size);
893 ais_msg->header.
size = swab32(ais_msg->header.
size);
894 ais_msg->header.
id = swab32(ais_msg->header.
id);
895 ais_msg->header.error = swab32(ais_msg->header.error);
913 ais_trace(
"Discarding Msg[%d] (dest=%s:%s, from=%s:%s)",
914 ais_msg->
id, ais_dest(&(ais_msg->
host)),
923 struct crm_identify_msg_s *ais_msg = msg;
925 ais_trace(
"Performing endian conversion...");
926 ais_msg->id = swab32(ais_msg->id);
927 ais_msg->pid = swab32(ais_msg->pid);
928 ais_msg->votes = swab32(ais_msg->votes);
929 ais_msg->processes = swab32(ais_msg->processes);
930 ais_msg->born_on = swab64(ais_msg->born_on);
932 ais_msg->header.size = swab32(ais_msg->header.size);
933 ais_msg->header.id = swab32(ais_msg->header.id);
940 const struct crm_identify_msg_s *msg = message;
942 if (nodeid != msg->id) {
943 ais_err(
"Invalid message: Node %u claimed to be node %d", nodeid, msg->id);
946 ais_debug(
"Node update: %s (%s)", msg->uname, msg->version);
964 send_ipc_ack(
void *conn)
966 if (res_overlay == NULL) {
967 ais_malloc0(res_overlay,
sizeof(
struct res_overlay));
972 res_overlay->header.error = CS_OK;
973 pcmk_api->ipc_response_send(conn, res_overlay, res_overlay->header.size);
982 gboolean
transient = TRUE;
984 void *async_conn = conn;
986 ais_trace(
"Message from client %p", conn);
1000 mutable = ais_msg_copy(ais_msg);
1003 type =
mutable->sender.type;
1005 (
"type: %d local: %d conn: %p host type: %d ais: %d sender pid: %d child pid: %d size: %d",
1006 type, mutable->host.local, pcmk_children[type].
conn, mutable->host.type,
crm_msg_ais,
1007 mutable->sender.pid, pcmk_children[type].
pid, ((
int)
SIZEOF(pcmk_children)));
1017 AIS_CHECK(
transient || mutable->sender.pid == pcmk_children[type].
pid,
1018 ais_err(
"Sender: %d, child[%d]: %d", mutable->sender.pid, type,
1019 pcmk_children[type].
pid);
1024 if (
transient == FALSE
1026 && mutable->host.local
1027 && pcmk_children[type].
conn == NULL && mutable->host.type ==
crm_msg_ais) {
1028 AIS_CHECK(mutable->sender.type != mutable->sender.pid,
1029 ais_err(
"Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
1031 ais_info(
"Recorded connection %p for %s/%d",
1032 conn, pcmk_children[type].name, pcmk_children[type].pid);
1046 }
else if (
transient) {
1047 AIS_CHECK(mutable->sender.type == mutable->sender.pid,
1048 ais_err(
"Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
1049 g_hash_table_replace(
ipc_client_list, async_conn, GUINT_TO_POINTER(mutable->sender.pid));
1054 memset(mutable->sender.uname, 0,
MAX_NAME);
1055 memcpy(mutable->sender.uname,
local_uname, mutable->sender.size);
1067 static int phase = 0;
1068 static int max_wait = 0;
1069 static time_t next_log = 0;
1070 static int max =
SIZEOF(pcmk_children);
1074 time_t now = time(NULL);
1076 if (now > next_log) {
1077 next_log = now + 300;
1079 (
"Preventing Corosync shutdown. Please ensure Pacemaker is stopped first.");
1094 for (; phase > 0; phase--) {
1097 for (lpc = max - 1; lpc >= 0; lpc--) {
1098 if (phase != pcmk_children[lpc].start_seq) {
1102 if (pcmk_children[lpc].pid) {
1105 time_t now = time(NULL);
1107 if (pcmk_children[lpc].respawn) {
1109 next_log = now + 30;
1110 pcmk_children[lpc].
respawn = FALSE;
1114 pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL);
1116 ais_perror(
"Call to wait4(%s/%d) failed - treating it as stopped",
1117 pcmk_children[lpc].name, pcmk_children[lpc].pid);
1119 }
else if (pid == 0) {
1120 if (now >= next_log) {
1122 next_log = now + 30;
1123 ais_notice(
"Still waiting for %s (pid=%d, seq=%d) to terminate...",
1124 pcmk_children[lpc].name, pcmk_children[lpc].pid,
1125 pcmk_children[lpc].start_seq);
1126 if (max_wait <= 0 && phase < pcmk_children[
crm_msg_crmd].start_seq) {
1127 ais_err(
"Child %s taking too long to terminate, sending SIGKILL",
1128 pcmk_children[lpc].name);
1138 ais_notice(
"%s confirmed stopped", pcmk_children[lpc].name);
1140 pcmk_children[lpc].
conn = NULL;
1141 pcmk_children[lpc].
pid = 0;
1152 struct member_loop_data {
1157 member_vote_count_fn(gpointer key, gpointer value, gpointer user_data)
1170 struct member_loop_data *
data = user_data;
1180 struct member_loop_data data;
1194 snprintf(data.string, size,
1195 "<nodes id=\"" U64T "\" quorate=\"%s\" expected=\"%u\" actual=\"%u\">",
1200 size = strlen(data.string);
1201 data.string = realloc_safe(data.string, size + 9);
1202 sprintf(data.string + size,
"</nodes>");
1210 void *async_conn = conn;
1234 char *bcast =
ais_concat(
"remove-peer", data,
':');
1245 send_quorum_details(
void *conn)
1252 snprintf(data, size,
"<quorum id=\"" U64T "\" quorate=\"%s\" expected=\"%u\" actual=\"%u\"/>",
1275 if (data != NULL && strlen(data) > 0) {
1278 update_expected_votes(value);
1281 send_quorum_details(conn);
1290 void *async_conn = conn;
1298 if (ais_str_eq(
"true", data)) {
1302 ais_info(
"%s node notifications for child %d (%p)",
1303 enable ?
"Enabling" :
"Disabling", sender, async_conn);
1322 resp.header.error = CS_OK;
1330 pcmk_api->ipc_response_send(conn, &resp, resp.header.size);
1334 ghash_send_update(gpointer key, gpointer value, gpointer data)
1348 ais_info(
"Sending membership update " U64T " to %d children",
1358 gboolean sane = TRUE;
1359 gboolean repaired = FALSE;
1363 if (sane && msg->header.
size == 0) {
1364 ais_err(
"Message with no size");
1368 if (sane && msg->header.error != CS_OK) {
1369 ais_err(
"Message header contains an error: %d", msg->header.error);
1374 ais_err(
"Message %d size too small: %d < %llu",
1375 msg->header.
id, msg->header.
size,
1386 ais_err(
"Message with no payload");
1391 int str_size = strlen(data) + 1;
1396 ais_err(
"Message payload is corrupted: expected %d bytes, got %d",
1399 for (lpc = (str_size - 10); lpc < msg->
size; lpc++) {
1403 ais_trace(
"bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]);
1408 if (sane == FALSE) {
1411 (
"Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
1412 msg->
id, ais_dest(&(msg->
host)), msg_type2text(dest), ais_dest(&(msg->
sender)),
1416 }
else if (repaired) {
1418 (
"Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
1419 msg->
id, ais_dest(&(msg->
host)), msg_type2text(dest), ais_dest(&(msg->
sender)),
1424 (
"Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
1425 msg->
id, ais_dest(&(msg->
host)), msg_type2text(dest), ais_dest(&(msg->
sender)),
1432 static int delivered_transient = 0;
1434 deliver_transient_msg(gpointer key, gpointer value, gpointer user_data)
1436 int pid = GPOINTER_TO_INT(value);
1439 if (pid == mutable->host.type) {
1442 delivered_transient++;
1444 ais_info(
"Sent message to %s.%d (rc=%d)", ais_dest(&(mutable->host)), pid, rc);
1446 ais_warn(
"Sending message to %s.%d failed (rc=%d)",
1447 ais_dest(&(mutable->host)), pid, rc);
1458 const char *reason =
"unknown";
1462 ais_trace(
"Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d)",
1463 mutable->id, ais_dest(&(mutable->host)), msg_type2text(dest),
1464 ais_dest(&(mutable->sender)), msg_type2text(mutable->sender.type),
1465 mutable->sender.pid, local_origin ?
"false" :
"true",
ais_data_len((
mutable)));
1467 if (local_origin == FALSE) {
1468 if (mutable->host.size == 0 || ais_str_eq(
local_uname, mutable->host.uname)) {
1469 mutable->host.local = TRUE;
1479 if (mutable->host.local) {
1481 const char *lookup = NULL;
1482 int children_index = 0;
1496 }
else if (dest >=
SIZEOF(pcmk_children)) {
1499 delivered_transient = 0;
1500 g_hash_table_foreach(
ipc_client_list, deliver_transient_msg,
mutable);
1501 if (delivered_transient) {
1502 ais_trace(
"Sent message to %d transient clients: %d", delivered_transient, dest);
1507 ais_trace(
"Sending message to transient client %d via crmd", dest);
1511 }
else if (dest == 0) {
1512 ais_err(
"Invalid destination: %d", dest);
1519 lookup = msg_type2text(dest);
1521 if (dest ==
crm_msg_pe && ais_str_eq(pcmk_children[7].name, lookup)) {
1525 children_index = dest;
1528 conn = pcmk_children[children_index].
async_conn;
1530 if (mutable->header.id == service_id) {
1531 mutable->header.id = 0;
1533 }
else if (mutable->header.id != 0) {
1534 ais_err(
"reset header id back to zero from %d", mutable->header.id);
1535 mutable->header.id = 0;
1538 reason =
"ipc delivery failed";
1541 }
else if (local_origin) {
1544 reason =
"cluster delivery failed";
1549 ais_warn(
"Sending message to %s.%s failed: %s (rc=%d)",
1550 ais_dest(&(mutable->host)), msg_type2text(dest), reason, rc);
1556 return rc == 0 ? TRUE : FALSE;
1570 if (mutable->id == 0) {
1573 msg_id++;
ais_err(
"Message ID wrapped around"));
1574 mutable->id = msg_id;
1577 mutable->header.error = CS_OK;
1582 memset(mutable->sender.uname, 0,
MAX_NAME);
1583 memcpy(mutable->sender.uname,
local_uname, mutable->sender.size);
1585 iovec.iov_base = (
char *)
mutable;
1586 iovec.iov_len =
mutable->header.size;
1588 ais_trace(
"Sending message (size=%u)", (
unsigned int)iovec.iov_len);
1589 rc =
pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
1591 if (rc == 0 && mutable->is_compressed == FALSE) {
1592 ais_trace(
"Message sent: %.80s", mutable->data);
1595 AIS_CHECK(rc == 0,
ais_err(
"Message not sent (%d): %.120s", rc, mutable->data));
1601 #define min(x,y) (x)<(y)?(x):(y)
1608 time_t now = time(NULL);
1610 struct crm_identify_msg_s *msg = NULL;
1612 static time_t started = 0;
1613 static uint64_t first_seq = 0;
1622 if (local_born_on == 0) {
1623 if (started + 15 < now) {
1625 local_born_on = first_seq;
1636 ais_malloc0(msg,
sizeof(
struct crm_identify_msg_s));
1637 msg->header.size =
sizeof(
struct crm_identify_msg_s);
1649 memcpy(msg->version,
VERSION, len);
1652 msg->pid = getpid();
1653 msg->processes = get_process_list();
1654 msg->born_on = local_born_on;
1661 iovec.iov_base = (
char *)msg;
1662 iovec.iov_len = msg->header.size;
1664 rc =
pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
1672 ghash_send_removal(gpointer key, gpointer value, gpointer data)
1674 send_quorum_details(value);
1689 ais_info(
"Peer %u is unknown",
id);
1694 }
else if (g_hash_table_remove(
membership_list, GUINT_TO_POINTER(
id))) {
1696 ais_notice(
"Removed dead peer %u from the membership list",
id);
1697 ais_info(
"Sending removal of %u to %d children",
1713 GList *node_list = NULL;
1717 while (g_hash_table_iter_next(&iter, &key, (
void **)&node)) {
1718 if (ais_str_eq(node_name, node->
uname)) {
1719 uint32_t node_id = GPOINTER_TO_UINT(key);
1720 char *node_id_s = NULL;
1723 snprintf(node_id_s, 31,
"%u", node_id);
1724 node_list = g_list_append(node_list, node_id_s);
1729 GList *gIter = NULL;
1731 for (gIter = node_list; gIter != NULL; gIter = gIter->next) {
1732 char *node_id_s = gIter->data;
1736 g_list_free_full(node_list, free);
1739 ais_warn(
"Peer %s is unkown", node_name);
1750 "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
1756 if (data && len > 12 && strncmp(
"remove-peer:", data, 12) == 0) {
1757 char *node = data + 12;
1767 member_dump_fn(gpointer key, gpointer value, gpointer user_data)
1771 ais_info(
" node id:%u, uname=%s state=%s processes=%.16x born=" U64T " seen=" U64T
1772 " addr=%s version=%s", node->
id, node->
uname ? node->
uname :
"-unknown-", node->
state,
1783 ais_info(
"Membership id: " U64T ", quorate: %s, expected: %u, actual: %u",
enum crm_ais_msg_types type
GHashTable * membership_notify_list
gboolean route_ais_message(const AIS_Message *msg, gboolean local_origin)
hdb_handle_t config_find_init(struct corosync_api_v1 *config, char *name)
int pcmk_user_lookup(const char *name, uid_t *uid, gid_t *gid)
uint32_t plugin_expected_votes
void pcmk_nodeid(void *conn, ais_void_ptr *msg)
void pcmk_notify(void *conn, ais_void_ptr *msg)
void pcmk_cluster_callback(ais_void_ptr *message, unsigned int nodeid)
long long ais_get_int(const char *text, char **end_text)
void log_ais_message(int level, const AIS_Message *msg)
#define ais_notice(fmt, args...)
void config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle)
struct corosync_service_engine * pcmk_get_handler_ver0(void)
pthread_t pcmk_wait_thread
void pcmk_quorum(void *conn, ais_void_ptr *msg)
void ais_remove_peer_by_name(const char *node_name)
#define ais_perror(fmt, args...)
void pcmk_exec_dump(void)
void pcmk_cluster_id_callback(ais_void_ptr *message, unsigned int nodeid)
void pcmk_nodes(void *conn, ais_void_ptr *msg)
#define ais_info(fmt, args...)
#define ais_trace(fmt, args...)
void ais_remove_peer(char *node_id)
int pcmk_config_init(struct corosync_api_v1 *corosync_api)
#define PACEMAKER_VERSION
#define ais_malloc0(malloc_obj, length)
gboolean have_reliable_membership_id
struct pcmk_env_s pcmk_env
int ais_get_boolean(const char *value)
int update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes, uint32_t procs, const char *uname, const char *state, const char *version)
void send_member_notification(void)
struct corosync_api_v1 * pcmk_api
#define ais_err(fmt, args...)
int pcmk_ipc_connect(void *conn)
struct res_overlay * res_overlay
struct corosync_service_engine pcmk_service_handler
int get_config_opt(struct corosync_api_v1 *config, hdb_handle_t object_service_handle, char *key, char **value, const char *fallback)
#define CRM_MESSAGE_IPC_ACK
void send_cluster_id(void)
enum crm_proc_flag __attribute__
int send_plugin_msg(enum crm_ais_msg_types type, const char *host, const char *data)
gboolean stop_child(crm_child_t *child, int signal)
const char * member_uname(uint32_t id)
#define AIS_CHECK(expr, failure_action)
gboolean check_message_sanity(const AIS_Message *msg, const char *data)
struct crm_ais_msg_s AIS_Message
#define ais_data_len(msg)
struct qb_ipc_response_header cs_ipc_header_response_t
void member_loop_fn(gpointer key, gpointer value, gpointer user_data)
void pcmk_peer_update(enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id)
char * pcmk_generate_membership_data(void)
uint32_t plugin_has_votes
#define ais_debug(fmt, args...)
char * ais_concat(const char *prefix, const char *suffix, char join)
hdb_handle_t config_find_next(struct corosync_api_v1 *config, char *name, hdb_handle_t top_handle)
#define do_ais_log(level, fmt, args...)
void destroy_ais_node(gpointer data)
struct corosync_service_engine_iface_ver0 pcmk_service_handler_iface
int send_plugin_msg_raw(const AIS_Message *ais_msg)
char * get_ais_data(const AIS_Message *msg)
void pcmk_remove_member(void *conn, ais_void_ptr *msg)
void pcmk_cluster_id_swab(void *msg)
#define ais_warn(fmt, args...)
gboolean spawn_child(crm_child_t *child)
void pcmk_ipc(void *conn, ais_void_ptr *msg)
char * append_member(char *data, crm_node_t *node)
gboolean process_ais_message(const AIS_Message *msg)
int send_client_msg(void *conn, enum crm_ais_msg_class class, enum crm_ais_msg_types type, const char *data)
int send_client_ipc(void *conn, const AIS_Message *ais_msg)
void pcmk_cluster_swab(void *msg)
int pcmk_startup(struct corosync_api_v1 *corosync_api)
GHashTable * membership_list
int pcmk_ipc_exit(void *conn)
enum crm_ais_msg_types type
GHashTable * ipc_client_list
struct qb_ipc_request_header cs_ipc_header_request_t