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),
234 .corosync_get_service_engine_ver0 = pcmk_get_handler_ver0
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) {
696 totempg_ifaces_print(
unsigned int nodeid)
700 struct totem_ip_address interfaces[INTERFACE_MAX];
702 unsigned int iface_count;
706 iface_string[0] =
'\0';
708 res = totempg_ifaces_get(nodeid, interfaces, &status, &iface_count);
710 return (
"no interface found for nodeid");
713 for (i = 0; i < iface_count; i++) {
714 sprintf(one_iface,
"r(%d) ip(%s), ", i, totemip_print(&interfaces[i]));
715 strcat(iface_string, one_iface);
717 return (iface_string);
722 ais_mark_unseen_peer_dead(gpointer key, gpointer value, gpointer user_data)
724 int *changed = user_data;
728 ais_info(
"Node %s was not seen in the previous transition", node->
uname);
736 const unsigned int *member_list,
size_t member_list_entries,
737 const unsigned int *left_list,
size_t left_list_entries,
738 const unsigned int *joined_list,
size_t joined_list_entries,
739 const struct memb_ring_id *ring_id)
746 switch (configuration_type) {
747 case TOTEM_CONFIGURATION_REGULAR:
750 case TOTEM_CONFIGURATION_TRANSITIONAL:
755 ais_notice(
"%s membership event on ring %lld: memb=%ld, new=%ld, lost=%ld",
756 do_update ?
"Stable" :
"Transitional", ring_id->seq,
757 (
long)member_list_entries, (
long)joined_list_entries, (
long)left_list_entries);
759 if (do_update == 0) {
760 for (lpc = 0; lpc < joined_list_entries; lpc++) {
761 const char *prefix =
"new: ";
766 for (lpc = 0; lpc < member_list_entries; lpc++) {
767 const char *prefix =
"memb:";
772 for (lpc = 0; lpc < left_list_entries; lpc++) {
773 const char *prefix =
"lost:";
781 for (lpc = 0; lpc < joined_list_entries; lpc++) {
782 const char *prefix =
"NEW: ";
791 if (node->
addr == NULL) {
792 const char *addr = totempg_ifaces_print(nodeid);
794 node->
addr = ais_strdup(addr);
799 for (lpc = 0; lpc < member_list_entries; lpc++) {
800 const char *prefix =
"MEMB:";
808 for (lpc = 0; lpc < left_list_entries; lpc++) {
809 const char *prefix =
"LOST:";
816 if (changed && joined_list_entries == 0 && left_list_entries == 0) {
817 ais_err(
"Something strange happened: %d", changed);
822 g_hash_table_foreach(
membership_list, ais_mark_unseen_peer_dead, &changed);
824 if (member_list_entries > 1) {
834 pcmk_update_nodeid();
845 const char *client = NULL;
846 void *async_conn = conn;
848 for (; lpc <
SIZEOF(pcmk_children); lpc++) {
849 if (pcmk_children[lpc].conn == conn) {
852 pcmk_children[lpc].
pid = 0;
854 pcmk_children[lpc].
conn = NULL;
856 client = pcmk_children[lpc].
name;
865 do_ais_log(LOG_INFO,
"Client %s (conn=%p, async-conn=%p) left", client, conn, async_conn);
867 do_ais_log((LOG_DEBUG + 1),
"Client %s (conn=%p, async-conn=%p) left",
868 "unknown-transient", conn, async_conn);
891 ais_trace(
"Performing endian conversion...");
892 ais_msg->
id = swab32(ais_msg->
id);
893 ais_msg->
size = swab32(ais_msg->
size);
909 ais_msg->header.
size = swab32(ais_msg->header.
size);
910 ais_msg->header.
id = swab32(ais_msg->header.
id);
911 ais_msg->header.error = swab32(ais_msg->header.error);
929 ais_trace(
"Discarding Msg[%d] (dest=%s:%s, from=%s:%s)",
930 ais_msg->
id, ais_dest(&(ais_msg->
host)),
939 struct crm_identify_msg_s *ais_msg = msg;
941 ais_trace(
"Performing endian conversion...");
942 ais_msg->id = swab32(ais_msg->id);
943 ais_msg->pid = swab32(ais_msg->pid);
944 ais_msg->votes = swab32(ais_msg->votes);
945 ais_msg->processes = swab32(ais_msg->processes);
946 ais_msg->born_on = swab64(ais_msg->born_on);
948 ais_msg->header.size = swab32(ais_msg->header.size);
949 ais_msg->header.id = swab32(ais_msg->header.id);
956 const struct crm_identify_msg_s *msg = message;
958 if (nodeid != msg->id) {
959 ais_err(
"Invalid message: Node %u claimed to be node %d", nodeid, msg->id);
962 ais_debug(
"Node update: %s (%s)", msg->uname, msg->version);
980 send_ipc_ack(
void *conn)
982 if (res_overlay == NULL) {
983 ais_malloc0(res_overlay,
sizeof(
struct res_overlay));
988 res_overlay->header.error = CS_OK;
989 pcmk_api->ipc_response_send(conn, res_overlay, res_overlay->header.size);
998 gboolean
transient = TRUE;
1000 void *async_conn = conn;
1002 ais_trace(
"Message from client %p", conn);
1016 mutable = ais_msg_copy(ais_msg);
1019 type =
mutable->sender.type;
1021 (
"type: %d local: %d conn: %p host type: %d ais: %d sender pid: %d child pid: %d size: %d",
1022 type, mutable->host.local, pcmk_children[type].
conn, mutable->host.type,
crm_msg_ais,
1023 mutable->sender.pid, pcmk_children[type].
pid, ((
int)
SIZEOF(pcmk_children)));
1033 AIS_CHECK(
transient || mutable->sender.pid == pcmk_children[type].
pid,
1034 ais_err(
"Sender: %d, child[%d]: %d", mutable->sender.pid, type,
1035 pcmk_children[type].
pid);
1040 if (
transient == FALSE
1042 && mutable->host.local
1043 && pcmk_children[type].
conn == NULL && mutable->host.type ==
crm_msg_ais) {
1044 AIS_CHECK(mutable->sender.type != mutable->sender.pid,
1045 ais_err(
"Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
1047 ais_info(
"Recorded connection %p for %s/%d",
1048 conn, pcmk_children[type].name, pcmk_children[type].
pid);
1062 }
else if (
transient) {
1063 AIS_CHECK(mutable->sender.type == mutable->sender.pid,
1064 ais_err(
"Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
1065 g_hash_table_replace(
ipc_client_list, async_conn, GUINT_TO_POINTER(mutable->sender.pid));
1070 memset(mutable->sender.uname, 0,
MAX_NAME);
1071 memcpy(mutable->sender.uname,
local_uname, mutable->sender.size);
1083 static int phase = 0;
1084 static int max_wait = 0;
1085 static time_t next_log = 0;
1086 static int max =
SIZEOF(pcmk_children);
1090 time_t now = time(NULL);
1092 if (now > next_log) {
1093 next_log = now + 300;
1095 (
"Preventing Corosync shutdown. Please ensure Pacemaker is stopped first.");
1110 for (; phase > 0; phase--) {
1113 for (lpc = max - 1; lpc >= 0; lpc--) {
1114 if (phase != pcmk_children[lpc].start_seq) {
1118 if (pcmk_children[lpc].
pid) {
1121 time_t now = time(NULL);
1123 if (pcmk_children[lpc].respawn) {
1125 next_log = now + 30;
1126 pcmk_children[lpc].
respawn = FALSE;
1130 pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL);
1132 ais_perror(
"Call to wait4(%s/%d) failed - treating it as stopped",
1133 pcmk_children[lpc].name, pcmk_children[lpc].pid);
1135 }
else if (pid == 0) {
1136 if (now >= next_log) {
1138 next_log = now + 30;
1139 ais_notice(
"Still waiting for %s (pid=%d, seq=%d) to terminate...",
1140 pcmk_children[lpc].name, pcmk_children[lpc].pid,
1141 pcmk_children[lpc].start_seq);
1142 if (max_wait <= 0 && phase < pcmk_children[
crm_msg_crmd].start_seq) {
1143 ais_err(
"Child %s taking too long to terminate, sending SIGKILL",
1144 pcmk_children[lpc].name);
1154 ais_notice(
"%s confirmed stopped", pcmk_children[lpc].name);
1156 pcmk_children[lpc].
conn = NULL;
1157 pcmk_children[lpc].
pid = 0;
1168 struct member_loop_data {
1173 member_vote_count_fn(gpointer key, gpointer value, gpointer user_data)
1186 struct member_loop_data *
data = user_data;
1196 struct member_loop_data data;
1210 snprintf(data.string, size,
1211 "<nodes id=\"" U64T "\" quorate=\"%s\" expected=\"%u\" actual=\"%u\">",
1216 size = strlen(data.string);
1217 data.string = realloc_safe(data.string, size + 9);
1218 sprintf(data.string + size,
"</nodes>");
1226 void *async_conn = conn;
1250 char *bcast =
ais_concat(
"remove-peer", data,
':');
1261 send_quorum_details(
void *conn)
1268 snprintf(data, size,
"<quorum id=\"" U64T "\" quorate=\"%s\" expected=\"%u\" actual=\"%u\"/>",
1291 if (data != NULL && strlen(data) > 0) {
1294 update_expected_votes(value);
1297 send_quorum_details(conn);
1306 void *async_conn = conn;
1314 if (ais_str_eq(
"true", data)) {
1318 ais_info(
"%s node notifications for child %d (%p)",
1319 enable ?
"Enabling" :
"Disabling", sender, async_conn);
1338 resp.header.error = CS_OK;
1346 pcmk_api->ipc_response_send(conn, &resp, resp.header.size);
1350 ghash_send_update(gpointer key, gpointer value, gpointer
data)
1364 ais_info(
"Sending membership update " U64T " to %d children",
1374 gboolean sane = TRUE;
1375 gboolean repaired = FALSE;
1379 if (sane && msg->header.
size == 0) {
1380 ais_err(
"Message with no size");
1384 if (sane && msg->header.error != CS_OK) {
1385 ais_err(
"Message header contains an error: %d", msg->header.error);
1390 ais_err(
"Message %d size too small: %d < %zu",
1401 ais_err(
"Message with no payload");
1406 int str_size = strlen(data) + 1;
1411 ais_err(
"Message payload is corrupted: expected %d bytes, got %d",
1414 for (lpc = (str_size - 10); lpc < msg->
size; lpc++) {
1418 ais_trace(
"bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]);
1423 if (sane == FALSE) {
1426 (
"Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
1427 msg->
id, ais_dest(&(msg->
host)), msg_type2text(dest), ais_dest(&(msg->
sender)),
1431 }
else if (repaired) {
1433 (
"Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
1434 msg->
id, ais_dest(&(msg->
host)), msg_type2text(dest), ais_dest(&(msg->
sender)),
1439 (
"Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
1440 msg->
id, ais_dest(&(msg->
host)), msg_type2text(dest), ais_dest(&(msg->
sender)),
1447 static int delivered_transient = 0;
1449 deliver_transient_msg(gpointer key, gpointer value, gpointer user_data)
1451 int pid = GPOINTER_TO_INT(value);
1454 if (pid == mutable->host.type) {
1457 delivered_transient++;
1459 ais_info(
"Sent message to %s.%d (rc=%d)", ais_dest(&(mutable->host)), pid, rc);
1461 ais_warn(
"Sending message to %s.%d failed (rc=%d)",
1462 ais_dest(&(mutable->host)), pid, rc);
1473 const char *reason =
"unknown";
1477 ais_trace(
"Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d)",
1478 mutable->id, ais_dest(&(mutable->host)), msg_type2text(dest),
1479 ais_dest(&(mutable->sender)), msg_type2text(mutable->sender.type),
1480 mutable->sender.pid, local_origin ?
"false" :
"true",
ais_data_len((
mutable)));
1482 if (local_origin == FALSE) {
1483 if (mutable->host.size == 0 || ais_str_eq(
local_uname, mutable->host.uname)) {
1484 mutable->host.local = TRUE;
1494 if (mutable->host.local) {
1496 const char *lookup = NULL;
1497 int children_index = 0;
1511 }
else if (dest >=
SIZEOF(pcmk_children)) {
1514 delivered_transient = 0;
1515 g_hash_table_foreach(
ipc_client_list, deliver_transient_msg,
mutable);
1516 if (delivered_transient) {
1517 ais_trace(
"Sent message to %d transient clients: %d", delivered_transient, dest);
1522 ais_trace(
"Sending message to transient client %d via crmd", dest);
1526 }
else if (dest == 0) {
1527 ais_err(
"Invalid destination: %d", dest);
1534 lookup = msg_type2text(dest);
1536 if (dest ==
crm_msg_pe && ais_str_eq(pcmk_children[7].name, lookup)) {
1540 children_index = dest;
1543 conn = pcmk_children[children_index].
async_conn;
1545 if (mutable->header.id == service_id) {
1546 mutable->header.id = 0;
1548 }
else if (mutable->header.id != 0) {
1549 ais_err(
"reset header id back to zero from %d", mutable->header.id);
1550 mutable->header.id = 0;
1553 reason =
"ipc delivery failed";
1556 }
else if (local_origin) {
1559 reason =
"cluster delivery failed";
1564 ais_warn(
"Sending message to %s.%s failed: %s (rc=%d)",
1565 ais_dest(&(mutable->host)), msg_type2text(dest), reason, rc);
1571 return rc == 0 ? TRUE : FALSE;
1585 if (mutable->id == 0) {
1588 msg_id++;
ais_err(
"Message ID wrapped around"));
1589 mutable->id = msg_id;
1592 mutable->header.error = CS_OK;
1597 memset(mutable->sender.uname, 0,
MAX_NAME);
1598 memcpy(mutable->sender.uname,
local_uname, mutable->sender.size);
1600 iovec.iov_base = (
char *)
mutable;
1601 iovec.iov_len =
mutable->header.size;
1603 ais_trace(
"Sending message (size=%u)", (
unsigned int)iovec.iov_len);
1604 rc =
pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
1606 if (rc == 0 && mutable->is_compressed == FALSE) {
1607 ais_trace(
"Message sent: %.80s", mutable->data);
1610 AIS_CHECK(rc == 0,
ais_err(
"Message not sent (%d): %.120s", rc, mutable->data));
1616 #define min(x,y) (x)<(y)?(x):(y) 1623 time_t now = time(NULL);
1625 struct crm_identify_msg_s *msg = NULL;
1627 static time_t started = 0;
1628 static uint64_t first_seq = 0;
1637 if (local_born_on == 0) {
1638 if (started + 15 < now) {
1640 local_born_on = first_seq;
1651 ais_malloc0(msg,
sizeof(
struct crm_identify_msg_s));
1652 msg->header.size =
sizeof(
struct crm_identify_msg_s);
1664 memcpy(msg->version,
VERSION, len);
1667 msg->pid = getpid();
1668 msg->processes = get_process_list();
1669 msg->born_on = local_born_on;
1676 iovec.iov_base = (
char *)msg;
1677 iovec.iov_len = msg->header.size;
1679 rc =
pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
1687 ghash_send_removal(gpointer key, gpointer value, gpointer data)
1689 send_quorum_details(value);
1704 ais_info(
"Peer %u is unknown",
id);
1709 }
else if (g_hash_table_remove(
membership_list, GUINT_TO_POINTER(
id))) {
1711 ais_notice(
"Removed dead peer %u from the membership list",
id);
1712 ais_info(
"Sending removal of %u to %d children",
1728 GList *node_list = NULL;
1732 while (g_hash_table_iter_next(&iter, &key, (
void **)&node)) {
1733 if (ais_str_eq(node_name, node->
uname)) {
1734 uint32_t node_id = GPOINTER_TO_UINT(key);
1735 char *node_id_s = NULL;
1738 snprintf(node_id_s, 31,
"%u", node_id);
1739 node_list = g_list_append(node_list, node_id_s);
1744 GList *gIter = NULL;
1746 for (gIter = node_list; gIter != NULL; gIter = gIter->next) {
1747 char *node_id_s = gIter->data;
1751 g_list_free_full(node_list, free);
1754 ais_warn(
"Peer %s is unkown", node_name);
1765 "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
1771 if (data && len > 12 && strncmp(
"remove-peer:", data, 12) == 0) {
1772 char *node = data + 12;
1782 member_dump_fn(gpointer key, gpointer value, gpointer user_data)
1786 ais_info(
" node id:%u, uname=%s state=%s processes=%.16x born=" U64T " seen=" U64T 1787 " addr=%s version=%s", node->
id, node->
uname ? node->
uname :
"-unknown-", node->
state,
1798 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...)
struct res_overlay __attribute__
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)
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)
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
gboolean check_message_sanity(const AIS_Message *msg, const char *data)
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