12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
23 #include <sys/utsname.h>
25 #include <qb/qbipcc.h>
26 #include <qb/qbutil.h>
28 #include <corosync/corodefs.h>
29 #include <corosync/corotypes.h>
30 #include <corosync/hdb.h>
31 #include <corosync/cfg.h>
32 #include <corosync/cmap.h>
33 #include <corosync/quorum.h>
40 static quorum_handle_t pcmk_quorum_handle = 0;
42 static gboolean (*quorum_app_callback)(
unsigned long long seq,
43 gboolean quorate) = NULL;
61 crm_info(
"Node %s is not yet known by corosync", node->
uname);
68 node_name_is_valid(
const char *key,
const char *
name)
76 }
else if (sscanf(name,
"%d.%d.%d.%d", &octet, &octet, &octet, &octet) == 4) {
77 crm_trace(
"%s contains an IPv4 address (%s), ignoring", key, name);
80 }
else if (strstr(name,
":") != NULL) {
81 crm_trace(
"%s contains an IPv6 address (%s), ignoring", key, name);
84 crm_trace(
"'%s: %s' is valid", key, name);
106 cs_error_t
rc = CS_OK;
109 cmap_handle_t local_handle = 0;
120 if (cmap_handle == 0 && local_handle == 0) {
122 crm_trace(
"Initializing CMAP connection");
124 rc = cmap_initialize(&local_handle);
127 crm_debug(
"API connection setup failed: %s. Retrying in %ds", cs_strerror(rc),
132 }
while (retries < 5 && rc != CS_OK);
135 crm_warn(
"Could not connect to Cluster Configuration Database API, error %s",
141 if (cmap_handle == 0) {
142 cmap_handle = local_handle;
144 rc = cmap_fd_get(cmap_handle, &fd);
146 crm_err(
"Could not obtain the CMAP API connection: %s (%d)",
147 cs_strerror(rc), rc);
153 &found_uid, &found_gid))) {
154 crm_err(
"CMAP provider is not authentic:"
155 " process %lld (uid: %lld, gid: %lld)",
157 (
long long) found_uid, (
long long) found_gid);
160 crm_err(
"Could not verify authenticity of CMAP provider: %s (%d)",
166 while (name == NULL && cmap_handle != 0) {
171 rc = cmap_get_uint32(cmap_handle, key, &
id);
172 crm_trace(
"Checking %u vs %u from %s", nodeid,
id, key);
180 crm_trace(
"Searching for node name for %u in nodelist.node.%d %s",
184 cmap_get_string(cmap_handle, key, &name);
190 cmap_get_string(cmap_handle, key, &name);
193 if (!node_name_is_valid(key, name)) {
207 cmap_finalize(local_handle);
211 crm_info(
"Unable to get node name for nodeid %u", nodeid);
226 if (pcmk_quorum_handle) {
227 quorum_finalize(pcmk_quorum_handle);
228 pcmk_quorum_handle = 0;
242 quorum_dispatch_cb(gpointer user_data)
244 int rc = quorum_dispatch(pcmk_quorum_handle, CS_DISPATCH_ALL);
247 crm_err(
"Connection to the Quorum API failed: %d", rc);
248 quorum_finalize(pcmk_quorum_handle);
249 pcmk_quorum_handle = 0;
266 quorum_notification_cb(quorum_handle_t handle, uint32_t quorate,
267 uint64_t ring_id, uint32_t view_list_entries,
273 static gboolean init_phase = TRUE;
278 ring_id, (
long unsigned int)view_list_entries);
281 ring_id, (
long unsigned int)view_list_entries);
287 (quorate?
"retained" :
"still lost"), ring_id,
288 (
long unsigned int)view_list_entries);
291 if (view_list_entries == 0 && init_phase) {
292 crm_info(
"Corosync membership is still forming, ignoring");
301 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
306 for (i = 0; i < view_list_entries; i++) {
307 uint32_t
id = view_list[i];
313 if (node->
uname == NULL) {
316 crm_info(
"Obtaining name for new node %u",
id);
328 if (quorum_app_callback) {
329 quorum_app_callback(ring_id, quorate);
334 .quorum_notify_fn = quorum_notification_cb,
347 void (*destroy)(gpointer))
352 uint32_t quorum_type = 0;
359 quorum_fd_callbacks.
dispatch = quorum_dispatch_cb;
362 crm_debug(
"Configuring Pacemaker to obtain quorum from Corosync");
364 rc = quorum_initialize(&pcmk_quorum_handle, &quorum_callbacks, &quorum_type);
366 crm_err(
"Could not connect to the Quorum API: %s (%d)",
367 cs_strerror(rc), rc);
370 }
else if (quorum_type != QUORUM_SET) {
371 crm_err(
"Corosync quorum is not configured");
375 rc = quorum_fd_get(pcmk_quorum_handle, &fd);
377 crm_err(
"Could not obtain the Quorum API connection: %s (%d)",
384 &found_uid, &found_gid))) {
385 crm_err(
"Quorum provider is not authentic:"
386 " process %lld (uid: %lld, gid: %lld)",
388 (
long long) found_uid, (
long long) found_gid);
392 crm_err(
"Could not verify authenticity of Quorum provider: %s (%d)",
398 rc = quorum_getquorate(pcmk_quorum_handle, &quorate);
400 crm_err(
"Could not obtain the current Quorum API state: %d", rc);
412 rc = quorum_trackstart(pcmk_quorum_handle, CS_TRACK_CHANGES | CS_TRACK_CURRENT);
414 crm_err(
"Could not setup Quorum API notifications: %d", rc);
424 quorum_finalize(pcmk_quorum_handle);
455 if (cluster->
nodeid == 0) {
456 crm_err(
"Could not determine local node ID");
461 if (cluster->
uname == NULL) {
462 crm_err(
"Could not determine local node name");
483 cmap_handle_t handle;
485 rc = cmap_initialize(&handle);
490 case CS_ERR_SECURITY:
491 crm_debug(
"Failed to initialize the cmap API: Permission denied (%d)", rc);
498 crm_info(
"Failed to initialize the cmap API: %s (%d)",
499 pcmk__cs_err_str(rc), rc);
503 cmap_finalize(handle);
518 crm_trace(
"Corosync peer inactive: NULL");
522 crm_trace(
"Corosync peer %s inactive: state=%s",
527 crm_trace(
"Corosync peer %s inactive: processes=%.16x",
546 cs_error_t rc = CS_OK;
549 cmap_handle_t cmap_handle;
557 rc = cmap_initialize(&cmap_handle);
560 crm_debug(
"API connection setup failed: %s. Retrying in %ds", cs_strerror(rc),
565 }
while (retries < 5 && rc != CS_OK);
568 crm_warn(
"Could not connect to Cluster Configuration Database API, error %d", rc);
572 rc = cmap_fd_get(cmap_handle, &fd);
574 crm_err(
"Could not obtain the CMAP API connection: %s (%d)",
575 cs_strerror(rc), rc);
581 &found_uid, &found_gid))) {
582 crm_err(
"CMAP provider is not authentic:"
583 " process %lld (uid: %lld, gid: %lld)",
585 (
long long) found_uid, (
long long) found_gid);
588 crm_err(
"Could not verify authenticity of CMAP provider: %s (%d)",
594 crm_trace(
"Initializing corosync nodelist");
595 for (lpc = 0; TRUE; lpc++) {
601 rc = cmap_get_uint32(cmap_handle, key, &nodeid);
614 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
615 if(node && node->
uname && strcasecmp(node->
uname, name) == 0) {
616 if (node->
id && node->
id != nodeid) {
617 crm_crit(
"Nodes %u and %u share the same name '%s': shutting down", node->
id,
625 if (nodeid > 0 || name != NULL) {
626 crm_trace(
"Initializing node[%d] %u = %s", lpc, nodeid, name);
630 if (nodeid > 0 && name != NULL) {
644 cmap_finalize(cmap_handle);
657 cmap_handle_t handle;
658 char *cluster_name = NULL;
659 cs_error_t rc = CS_OK;
666 rc = cmap_initialize(&handle);
668 crm_info(
"Failed to initialize the cmap API: %s (%d)",
669 cs_strerror(rc), rc);
673 rc = cmap_fd_get(handle, &fd);
675 crm_err(
"Could not obtain the CMAP API connection: %s (%d)",
676 cs_strerror(rc), rc);
682 &found_uid, &found_gid))) {
683 crm_err(
"CMAP provider is not authentic:"
684 " process %lld (uid: %lld, gid: %lld)",
686 (
long long) found_uid, (
long long) found_gid);
689 crm_err(
"Could not verify authenticity of CMAP provider: %s (%d)",
694 rc = cmap_get_string(handle,
"totem.cluster_name", &cluster_name);
696 crm_info(
"Cannot get totem.cluster_name: %s (%d)", cs_strerror(rc), rc);
699 crm_debug(
"cmap totem.cluster_name = '%s'", cluster_name);
703 cmap_finalize(handle);
716 cs_error_t cs_rc = CS_OK;
718 cmap_handle_t cmap_handle;
719 cmap_iter_handle_t iter_handle;
720 char key_name[CMAP_KEYNAME_MAXLEN + 1];
727 static bool got_result =
false;
728 static bool result =
false;
736 cs_rc = cmap_initialize(&cmap_handle);
737 if (cs_rc != CS_OK) {
739 crm_debug(
"CMAP connection failed: %s (rc=%d, retrying in %ds)",
740 cs_strerror(cs_rc), cs_rc, retries);
743 }
while ((retries < 5) && (cs_rc != CS_OK));
744 if (cs_rc != CS_OK) {
745 crm_warn(
"Assuming Corosync does not have node list: "
746 "CMAP connection failed (%s) " CRM_XS " rc=%d",
747 cs_strerror(cs_rc), cs_rc);
752 cs_rc = cmap_fd_get(cmap_handle, &fd);
753 if (cs_rc != CS_OK) {
754 crm_warn(
"Assuming Corosync does not have node list: "
755 "CMAP unusable (%s) " CRM_XS " rc=%d",
756 cs_strerror(cs_rc), cs_rc);
762 &found_pid, &found_uid, &found_gid);
764 crm_warn(
"Assuming Corosync does not have node list: "
765 "CMAP provider is inauthentic "
766 CRM_XS " pid=%lld uid=%lld gid=%lld",
768 (
long long) found_uid, (
long long) found_gid);
771 crm_warn(
"Assuming Corosync does not have node list: "
772 "Could not verify CMAP authenticity (%s) " CRM_XS " rc=%d",
778 cs_rc = cmap_iter_init(cmap_handle,
"nodelist", &iter_handle);
779 if (cs_rc != CS_OK) {
780 crm_warn(
"Assuming Corosync does not have node list: "
781 "CMAP not readable (%s) " CRM_XS " rc=%d",
782 cs_strerror(cs_rc), cs_rc);
786 cs_rc = cmap_iter_next(cmap_handle, iter_handle, key_name, NULL, NULL);
787 if (cs_rc == CS_OK) {
791 cmap_iter_finalize(cmap_handle, iter_handle);
793 crm_debug(
"Corosync %s node list", (result?
"has" :
"does not have"));
796 cmap_finalize(cmap_handle);
#define crm_notice(fmt, args...)
const char * pcmk_strerror(int rc)
#define crm_crit(fmt, args...)
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
quorum_callbacks_t quorum_callbacks
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
void pcmk__corosync_disconnect(crm_cluster_t *cluster)
void pcmk__reap_unseen_nodes(uint64_t ring_id)
char * pcmk__corosync_uuid(crm_node_t *node)
#define PCMK__SPECIAL_PID_AS_0(p)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
bool pcmk__corosync_add_nodes(xmlNode *xml_parent)
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
Get a cluster node cache entry.
int(* dispatch)(gpointer userdata)
Dispatch function for mainloop file descriptor with data ready.
enum cluster_type_e pcmk__corosync_detect(void)
char * get_node_name(uint32_t nodeid)
Get the node name corresponding to a cluster node ID.
char * strerror(int errnum)
char * pcmk__corosync_cluster_name(void)
Wrappers for and extensions to glib mainloop.
gboolean crm_is_corosync_peer_active(const crm_node_t *node)
Check whether a Corosync cluster peer is active.
void cluster_disconnect_cpg(crm_cluster_t *cluster)
Disconnect from Corosync CPG.
#define crm_warn(fmt, args...)
crm_node_t * pcmk__update_peer_state(const char *source, crm_node_t *node, const char *state, uint64_t membership)
Update a node's state and membership information.
#define crm_debug(fmt, args...)
void(* destroy)(gpointer userdata)
Destroy function for mainloop file descriptor client data.
gboolean pcmk__corosync_connect(crm_cluster_t *cluster)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
xmlNode * create_xml_node(xmlNode *parent, const char *name)
const char * name_for_cluster_type(enum cluster_type_e type)
Get a log-friendly string equivalent of a cluster type.
gboolean is_corosync_cluster(void)
Check whether the local cluster is a Corosync cluster.
uint32_t get_local_nodeid(cpg_handle_t handle)
Get the local Corosync node ID (via CPG)
void pcmk__corosync_quorum_connect(gboolean(*dispatch)(unsigned long long, gboolean), void(*destroy)(gpointer))
#define crm_err(fmt, args...)
char * pcmk__corosync_name(uint64_tcmap_handle, uint32_t nodeid)
bool pcmk__corosync_has_nodelist(void)
IPC interface to Pacemaker daemons.
GHashTable * crm_peer_cache
#define crm_info(fmt, args...)
gboolean cluster_connect_cpg(crm_cluster_t *cluster)
Connect to Corosync CPG.
enum cluster_type_e get_cluster_type(void)
Get (and validate) the local cluster type.
int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid, pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
Check the authenticity of the IPC socket peer process (legacy)