15#include <netinet/in.h>
17#include <sys/socket.h>
18#include <sys/utsname.h>
21#include <corosync/cfg.h>
22#include <corosync/cmap.h>
23#include <corosync/corodefs.h>
24#include <corosync/corotypes.h>
25#include <corosync/hdb.h>
26#include <corosync/quorum.h>
38static quorum_handle_t pcmk_quorum_handle = 0;
40static gboolean (*quorum_app_callback)(
unsigned long long seq,
41 gboolean quorate) = NULL;
61 crm_info(
"Node %s is not yet known by Corosync", node->
name);
68node_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);
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 = pcmk__init_cmap(&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",
181 nodeid, lpc, pcmk__s(
name,
"<null>"));
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);
227 if (pcmk_quorum_handle != 0) {
228 quorum_finalize(pcmk_quorum_handle);
229 pcmk_quorum_handle = 0;
243quorum_dispatch_cb(gpointer user_data)
245 int rc = quorum_dispatch(pcmk_quorum_handle, CS_DISPATCH_ALL);
248 crm_err(
"Connection to the Quorum API failed: %d", rc);
249 quorum_finalize(pcmk_quorum_handle);
250 pcmk_quorum_handle = 0;
267quorum_notification_cb(quorum_handle_t handle, uint32_t quorate,
268 uint64_t ring_id, uint32_t view_list_entries,
274 static gboolean init_phase = TRUE;
276 bool is_quorate = (quorate != 0);
279 if (is_quorate && !was_quorate) {
280 crm_notice(
"Quorum acquired " QB_XS
" membership=%" PRIu64
282 ring_id, view_list_entries);
285 }
else if (!is_quorate && was_quorate) {
286 crm_warn(
"Quorum lost " QB_XS
" membership=%" PRIu64
" members=" PRIu32,
287 ring_id, view_list_entries);
291 crm_info(
"Quorum %s " QB_XS
" membership=%" PRIu64
" members=%" PRIu32,
292 (is_quorate?
"retained" :
"still lost"), ring_id,
296 if (view_list_entries == 0 && init_phase) {
297 crm_info(
"Corosync membership is still forming, ignoring");
306 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
307 node->membership_id = 0;
311 for (i = 0; i < view_list_entries; i++) {
312 uint32_t
id = view_list[i];
318 if (node->name == NULL) {
321 crm_info(
"Obtaining name for new node %u",
id);
334 if (quorum_app_callback) {
335 quorum_app_callback(ring_id, is_quorate);
349 void (*destroy)(gpointer))
354 uint32_t quorum_type = 0;
361 quorum_fd_callbacks.
dispatch = quorum_dispatch_cb;
364 crm_debug(
"Configuring Pacemaker to obtain quorum from Corosync");
369 quorum_model_v0_data_t quorum_model_data = {
370 .model = QUORUM_MODEL_V0,
371 .quorum_notify_fn = quorum_notification_cb,
374 rc = quorum_model_initialize(&pcmk_quorum_handle, QUORUM_MODEL_V0,
375 (quorum_model_data_t *) &quorum_model_data,
378 quorum_callbacks_t quorum_callbacks = {
379 .quorum_notify_fn = quorum_notification_cb,
382 rc = quorum_initialize(&pcmk_quorum_handle, &quorum_callbacks,
388 crm_err(
"Could not connect to the Quorum API: %s (%d)",
389 cs_strerror(rc), rc);
392 }
else if (quorum_type != QUORUM_SET) {
393 crm_err(
"Corosync quorum is not configured");
397 rc = quorum_fd_get(pcmk_quorum_handle, &fd);
399 crm_err(
"Could not obtain the Quorum API connection: %s (%d)",
406 &found_uid, &found_gid))) {
407 crm_err(
"Quorum provider is not authentic:"
408 " process %lld (uid: %lld, gid: %lld)",
410 (
long long) found_uid, (
long long) found_gid);
414 crm_err(
"Could not verify authenticity of Quorum provider: %s (%d)",
420 rc = quorum_getquorate(pcmk_quorum_handle, &quorate);
422 crm_err(
"Could not obtain the current Quorum API state: %d", rc);
434 rc = quorum_trackstart(pcmk_quorum_handle, CS_TRACK_CHANGES | CS_TRACK_CURRENT);
436 crm_err(
"Could not setup Quorum API notifications: %d", rc);
446 quorum_finalize(pcmk_quorum_handle);
469 crm_err(
"Invalid cluster layer: %s " QB_XS
" cluster_layer=%d",
470 cluster_layer_s, cluster_layer);
479 crm_info(
"Connection to %s established", cluster_layer_s);
483 crm_err(
"Could not determine local node ID");
489 crm_err(
"Could not determine local node name");
513 cmap_handle_t handle;
514 int rc = pcmk__init_cmap(&handle);
517 cmap_finalize(handle);
521 crm_info(
"Failed to initialize the cmap API: %s (%d)",
522 pcmk__cs_err_str(rc), rc);
538 crm_trace(
"Corosync peer inactive: NULL");
542 crm_trace(
"Corosync peer %s inactive: state=%s",
547 crm_trace(
"Corosync peer %s inactive " QB_XS
" processes=%.16" PRIx32,
566 cs_error_t rc = CS_OK;
569 cmap_handle_t cmap_handle;
577 rc = pcmk__init_cmap(&cmap_handle);
580 crm_debug(
"API connection setup failed: %s. Retrying in %ds", cs_strerror(rc),
585 }
while (retries < 5 && rc != CS_OK);
588 crm_warn(
"Could not connect to Cluster Configuration Database API, error %d", rc);
592 rc = cmap_fd_get(cmap_handle, &fd);
594 crm_err(
"Could not obtain the CMAP API connection: %s (%d)",
595 cs_strerror(rc), rc);
601 &found_uid, &found_gid))) {
602 crm_err(
"CMAP provider is not authentic:"
603 " process %lld (uid: %lld, gid: %lld)",
605 (
long long) found_uid, (
long long) found_gid);
608 crm_err(
"Could not verify authenticity of CMAP provider: %s (%d)",
614 crm_trace(
"Initializing Corosync node list");
615 for (lpc = 0; TRUE; lpc++) {
621 rc = cmap_get_uint32(cmap_handle, key, &nodeid);
634 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
640 crm_crit(
"Nodes %" PRIu32
" and %" PRIu32
" share the "
641 "same name '%s': shutting down",
648 if (nodeid > 0 ||
name != NULL) {
649 crm_trace(
"Initializing node[%d] %u = %s", lpc, nodeid,
name);
653 if (nodeid > 0 &&
name != NULL) {
667 cmap_finalize(cmap_handle);
680 cmap_handle_t handle;
681 char *cluster_name = NULL;
682 cs_error_t rc = CS_OK;
689 rc = pcmk__init_cmap(&handle);
691 crm_info(
"Failed to initialize the cmap API: %s (%d)",
692 cs_strerror(rc), rc);
696 rc = cmap_fd_get(handle, &fd);
698 crm_err(
"Could not obtain the CMAP API connection: %s (%d)",
699 cs_strerror(rc), rc);
705 &found_uid, &found_gid))) {
706 crm_err(
"CMAP provider is not authentic:"
707 " process %lld (uid: %lld, gid: %lld)",
709 (
long long) found_uid, (
long long) found_gid);
712 crm_err(
"Could not verify authenticity of CMAP provider: %s (%d)",
717 rc = cmap_get_string(handle,
"totem.cluster_name", &cluster_name);
719 crm_info(
"Cannot get totem.cluster_name: %s (%d)", cs_strerror(rc), rc);
722 crm_debug(
"cmap totem.cluster_name = '%s'", cluster_name);
726 cmap_finalize(handle);
739 cs_error_t cs_rc = CS_OK;
741 cmap_handle_t cmap_handle;
742 cmap_iter_handle_t iter_handle;
743 char key_name[CMAP_KEYNAME_MAXLEN + 1];
750 static bool got_result =
false;
751 static bool result =
false;
759 cs_rc = pcmk__init_cmap(&cmap_handle);
760 if (cs_rc != CS_OK) {
762 crm_debug(
"CMAP connection failed: %s (rc=%d, retrying in %ds)",
763 cs_strerror(cs_rc), cs_rc, retries);
766 }
while ((retries < 5) && (cs_rc != CS_OK));
767 if (cs_rc != CS_OK) {
768 crm_warn(
"Assuming Corosync does not have node list: "
769 "CMAP connection failed (%s) " QB_XS
" rc=%d",
770 cs_strerror(cs_rc), cs_rc);
775 cs_rc = cmap_fd_get(cmap_handle, &fd);
776 if (cs_rc != CS_OK) {
777 crm_warn(
"Assuming Corosync does not have node list: "
778 "CMAP unusable (%s) " QB_XS
" rc=%d",
779 cs_strerror(cs_rc), cs_rc);
785 &found_pid, &found_uid, &found_gid);
787 crm_warn(
"Assuming Corosync does not have node list: "
788 "CMAP provider is inauthentic "
789 QB_XS
" pid=%lld uid=%lld gid=%lld",
791 (
long long) found_uid, (
long long) found_gid);
794 crm_warn(
"Assuming Corosync does not have node list: "
795 "Could not verify CMAP authenticity (%s) " QB_XS
" rc=%d",
801 cs_rc = cmap_iter_init(cmap_handle,
"nodelist", &iter_handle);
802 if (cs_rc != CS_OK) {
803 crm_warn(
"Assuming Corosync does not have node list: "
804 "CMAP not readable (%s) " QB_XS
" rc=%d",
805 cs_strerror(cs_rc), cs_rc);
809 cs_rc = cmap_iter_next(cmap_handle, iter_handle, key_name, NULL, NULL);
810 if (cs_rc == CS_OK) {
814 cmap_iter_finalize(cmap_handle, iter_handle);
819 cmap_finalize(cmap_handle);
GHashTable * pcmk__peer_cache
@ pcmk__node_search_cluster_member
Search for cluster nodes from membership cache.
pcmk__node_status_t * pcmk__update_peer_state(const char *source, pcmk__node_status_t *node, const char *state, uint64_t membership)
Update a node's state and membership information.
pcmk__node_status_t * pcmk__get_node(unsigned int id, const char *uname, const char *xml_id, uint32_t flags)
bool pcmk__cluster_has_quorum(void)
void pcmk__cluster_init_node_caches(void)
char * pcmk__cluster_node_name(uint32_t nodeid)
void pcmk__reap_unseen_nodes(uint64_t ring_id)
const char * pcmk_cluster_layer_text(enum pcmk_cluster_layer layer)
Get a log-friendly string equivalent of a cluster layer.
enum pcmk_cluster_layer pcmk_get_cluster_layer(void)
Get and validate the local cluster layer.
pcmk_cluster_layer
Types of cluster layer.
@ pcmk_cluster_layer_corosync
Corosync Cluster Engine.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
bool pcmk__corosync_is_active(void)
char * pcmk__corosync_cluster_name(void)
char * pcmk__corosync_name(uint64_t cmap_handle, uint32_t nodeid)
bool pcmk__corosync_add_nodes(xmlNode *xml_parent)
char * pcmk__corosync_uuid(const pcmk__node_status_t *node)
int pcmk__corosync_connect(pcmk_cluster_t *cluster)
void pcmk__corosync_quorum_connect(gboolean(*dispatch)(unsigned long long, gboolean), void(*destroy)(gpointer))
bool pcmk__corosync_has_nodelist(void)
void pcmk__corosync_disconnect(pcmk_cluster_t *cluster)
bool pcmk__corosync_is_peer_active(const pcmk__node_status_t *node)
int pcmk__cpg_connect(pcmk_cluster_t *cluster)
Connect to Corosync CPG.
void pcmk__cpg_disconnect(pcmk_cluster_t *cluster)
uint32_t pcmk__cpg_local_nodeid(cpg_handle_t handle)
G_GNUC_INTERNAL void pcmk__cluster_set_quorum(bool quorate)
IPC interface to Pacemaker daemons.
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)
#define PCMK__SPECIAL_PID_AS_0(p)
#define crm_info(fmt, args...)
#define crm_warn(fmt, args...)
#define crm_crit(fmt, args...)
#define CRM_LOG_ASSERT(expr)
#define crm_notice(fmt, args...)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
Wrappers for and extensions to glib mainloop.
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
#define PCMK_VALUE_MEMBER
pcmk__action_result_t result
const char * pcmk_strerror(int rc)
@ CRM_EX_FATAL
Do not respawn.
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
#define pcmk__assert(expr)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int(* dispatch)(gpointer userdata)
Dispatch function for mainloop file descriptor with data ready.
void(* destroy)(gpointer userdata)
Destroy function for mainloop file descriptor client data.
char * node_name
Local node name at cluster layer.
char * node_xml_id
Local node XML ID in CIB.
uint32_t node_id
Local node ID at cluster layer.
pcmk__cluster_private_t * priv
Node status data (may be a cluster node or a Pacemaker Remote node)
uint32_t cluster_layer_id
Cluster-layer numeric node ID.
char * name
Node name as known to cluster layer, or Pacemaker Remote node name.
Wrappers for and extensions to libxml2.
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)