24 #include <sys/param.h>
25 #include <sys/types.h>
39 static gboolean crm_autoreap = TRUE;
56 crm_trace(
"added %s to remote cache", node_name);
60 node->
uname = strdup(node_name);
61 node->
uuid = strdup(node_name);
74 remote_cache_refresh_helper(xmlNode *cib,
const char *xpath,
const char *field)
76 const char *remote = NULL;
78 xmlXPathObjectPtr xpathObj = NULL;
83 max = numXpathResults(xpathObj);
84 for (lpc = 0; lpc < max; lpc++) {
93 crm_trace(
"added %s to remote cache", remote);
97 node->
uname = strdup(remote);
98 node->
uuid = strdup(remote);
107 #define XPATH_GUEST_NODE_CONFIG \
108 "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
109 "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \
110 "[@name='" XML_RSC_ATTR_REMOTE_NODE "']"
113 #define XPATH_REMOTE_NODE_CONFIG \
114 "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
115 "[@type='remote'][@provider='pacemaker']"
118 #define XPATH_REMOTE_NODE_STATUS \
119 "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \
120 "[@" XML_NODE_IS_REMOTE "='true']"
159 #if SUPPORT_HEARTBEAT
161 return crm_is_heartbeat_peer_active(node);
169 crm_reap_dead_member(gpointer key, gpointer value, gpointer user_data)
174 if (search == NULL) {
177 }
else if (search->
id && node->
id != search->
id) {
205 crm_trace(
"Nothing to do, cache not initialized");
210 search.
uname = name ? strdup(name) : NULL;
211 matches = g_hash_table_foreach_remove(
crm_peer_cache, crm_reap_dead_member, &search);
213 crm_notice(
"Purged %d peers with id=%u and/or uname=%s from the membership cache",
214 matches, search.
id, search.
uname);
217 crm_info(
"No peers with id=%u and/or uname=%s exist",
id, name);
225 crm_count_peer(gpointer key, gpointer value, gpointer user_data)
227 guint *count = user_data;
247 destroy_crm_node(gpointer
data)
321 crm_autoreap = autoreap;
324 static void crm_dump_peer_hash(
int level,
const char *caller)
327 const char *
id = NULL;
328 crm_node_t *node = NULL;
331 while (g_hash_table_iter_next(&iter, (gpointer *) &
id, (gpointer *) &node)) {
332 do_crm_log(level,
"%s: Node %u/%s = %p - %s", caller, node->
id, node->
uname, node,
id);
336 static gboolean crm_hash_find_by_data(gpointer key, gpointer value, gpointer user_data)
338 if(value == user_data) {
347 crm_node_t *node = NULL;
366 crm_node_t *node = NULL;
386 crm_node_t *node = NULL;
387 crm_node_t *by_id = NULL;
388 crm_node_t *by_name = NULL;
396 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
397 if(node->
uname && strcasecmp(node->
uname, uname) == 0) {
407 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
417 if(by_id == by_name) {
419 crm_trace(
"Consistent: %p for %u/%s", by_id,
id, uname);
421 }
else if(by_id == NULL && by_name) {
422 crm_trace(
"Only one: %p for %u/%s", by_name,
id, uname);
424 if(
id && by_name->
id) {
425 crm_dump_peer_hash(LOG_WARNING, __FUNCTION__);
426 crm_crit(
"Node %u and %u share the same name '%s'",
427 id, by_name->
id, uname);
434 }
else if(by_name == NULL && by_id) {
435 crm_trace(
"Only one: %p for %u/%s", by_id,
id, uname);
437 if(uname && by_id->
uname) {
438 crm_dump_peer_hash(LOG_WARNING, __FUNCTION__);
439 crm_crit(
"Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct",
440 uname, by_id->
uname,
id, uname);
443 }
else if(uname && by_id->
uname) {
445 crm_notice(
"Node '%s' has changed its ID from %u to %u", by_id->
uname, by_name->
id, by_id->
id);
446 g_hash_table_foreach_remove(
crm_peer_cache, crm_hash_find_by_data, by_name);
449 crm_warn(
"Node '%s' and '%s' share the same cluster nodeid: %u %s", by_id->
uname, by_name->
uname,
id, uname);
450 crm_dump_peer_hash(LOG_INFO, __FUNCTION__);
451 crm_abort(__FILE__, __FUNCTION__, __LINE__,
"member weirdness", TRUE, TRUE);
454 }
else if(
id && by_name->
id) {
455 crm_warn(
"Node %u and %u share the same name: '%s'", by_id->
id, by_name->
id, uname);
467 crm_dump_peer_hash(LOG_DEBUG, __FUNCTION__);
469 crm_info(
"Merging %p into %p", by_name, by_id);
470 g_hash_table_foreach_remove(
crm_peer_cache, crm_hash_find_by_data, by_name);
478 crm_remove_conflicting_peer(crm_node_t *node)
482 crm_node_t *existing_node = NULL;
484 if (node->
id == 0 || node->
uname == NULL) {
495 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
496 if (existing_node->
id > 0
497 && existing_node->
id != node->
id
498 && existing_node->
uname != NULL
499 && strcasecmp(existing_node->
uname, node->
uname) == 0) {
505 crm_warn(
"Removing cached offline node %u/%s which has conflicting uname with %u",
506 existing_node->
id, existing_node->
uname, node->
id);
508 g_hash_table_iter_remove(&iter);
521 crm_node_t *node = NULL;
522 char *uname_lookup = NULL;
532 if ((node == NULL || node->
uname == NULL) && (uname == NULL)) {
537 uname = uname_lookup;
538 crm_trace(
"Inferred a name of '%s' for node %u", uname,
id);
550 node = calloc(1,
sizeof(crm_node_t));
553 crm_info(
"Created entry %s/%p for node %s/%u (%d total)",
554 uniqueid, node, uname,
id, 1 + g_hash_table_size(
crm_peer_cache));
558 if(
id > 0 && uname && (node->
id == 0 || node->
uname == NULL)) {
559 crm_info(
"Node %u is now known as %s",
id, uname);
562 if(
id > 0 && node->
id == 0) {
566 if (uname && (node->
uname == NULL)) {
570 if(node->
uuid == NULL) {
574 crm_info(
"Node %u has uuid %s",
id, uuid);
577 crm_info(
"Cannot obtain a UUID for node %u/%s",
id, node->
uname);
599 uint32_t children,
const char *uuid,
const char *
uname,
const char *addr,
603 gboolean addr_changed = FALSE;
604 gboolean votes_changed = FALSE;
606 crm_node_t *node = NULL;
613 if (node->
uuid == NULL) {
618 }
else if (uuid != NULL) {
619 node->
uuid = strdup(uuid);
634 #if SUPPORT_HEARTBEAT
646 if (votes > 0 && node->
votes != votes) {
647 votes_changed = TRUE;
655 node->
addr = strdup(addr);
658 if (addr_changed || votes_changed) {
659 crm_info(
"%s: Node %s: id=%u state=%s addr=%s%s votes=%d%s born=" U64T " seen=" U64T
660 " proc=%.32x", source, node->
uname, node->
id, node->
state,
661 node->
addr, addr_changed ?
" (new)" :
"", node->
votes,
683 int i, len = strlen(uname);
685 for (i = 0; i < len; i++) {
686 if (uname[i] >=
'A' && uname[i] <=
'Z') {
687 crm_warn(
"Node names with capitals are discouraged, consider changing '%s'",
694 node->
uname = strdup(uname);
701 crm_remove_conflicting_peer(node);
726 gboolean changed = FALSE;
729 source, peer2text(flag), status);
return NULL);
737 if (status == NULL) {
750 if (flag > 0 && node->
processes != flag) {
763 crm_info(
"%s: Node %s[%u] - all processes are now offline", source, node->
uname,
766 crm_info(
"%s: Node %s[%u] - %s is now %s", source, node->
uname, node->
id,
767 peer2text(flag), status);
786 is_set(node->
processes, crm_get_cluster_proc())?
790 crm_trace(
"%s: Node %s[%u] - %s is unchanged (%s)", source, node->
uname, node->
id,
791 peer2text(flag), status);
800 gboolean changed = FALSE;
802 CRM_CHECK(node != NULL,
crm_err(
"%s: Could not set 'expected' to %s", source, expected);
817 crm_info(
"%s: Node %s[%u] - expected state is now %s (was %s)", source, node->
uname, node->
id,
821 crm_trace(
"%s: Node %s[%u] - expected state is unchanged (%s)", source, node->
uname,
843 crm_update_peer_state_iter(
const char *source, crm_node_t * node,
const char *state,
int membership,
GHashTableIter *iter)
847 CRM_CHECK(node != NULL,
crm_err(
"%s: Could not set 'state' to %s", source, state);
851 if (membership && is_member) {
856 char *last = node->
state;
860 node->
state = strdup(state);
861 crm_notice(
"%s: Node %s[%u] - state is now %s (was %s)",
862 source, node->
uname, node->
id, state, last);
874 crm_notice(
"Purged 1 peer with id=%u and/or uname=%s from the membership cache", node->
id, node->
uname);
875 g_hash_table_iter_remove(iter);
884 crm_trace(
"%s: Node %s[%u] - state is unchanged (%s)", source, node->
uname, node->
id,
908 return crm_update_peer_state_iter(source, node, state, membership, NULL);
921 crm_node_t *node = NULL;
925 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
933 crm_update_peer_state_iter(__FUNCTION__, node,
CRM_NODE_LOST, membership, &iter);
936 crm_info(
"State of node %s[%u] is still unknown",
#define CRM_CHECK(expr, failure_action)
void crm_remote_peer_cache_add(const char *node_name)
void crm_reap_unseen_nodes(uint64_t membership)
#define crm_notice(fmt, args...)
#define XPATH_REMOTE_NODE_STATUS
GHashTable * crm_peer_cache
gboolean is_openais_cluster(void)
#define crm_crit(fmt, args...)
gboolean safe_str_neq(const char *a, const char *b)
char * crm_generate_uuid(void)
void crm_peer_destroy(void)
gboolean is_heartbeat_cluster(void)
int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off)
crm_node_t * crm_find_peer(unsigned int id, const char *uname)
int get_corosync_id(int id, const char *uuid)
crm_node_t * crm_find_peer_full(unsigned int id, const char *uname, int flags)
GHashTable * crm_remote_peer_cache
#define CRM_LOG_ASSERT(expr)
#define clear_bit(word, bit)
unsigned long long crm_peer_seq
char * get_node_name(uint32_t nodeid)
void crm_set_autoreap(gboolean autoreap)
Tell the library whether to automatically reap lost nodes.
void crm_remote_peer_cache_remove(const char *node_name)
gboolean crm_is_corosync_peer_active(const crm_node_t *node)
int crm_remote_peer_cache_size(void)
#define crm_warn(fmt, args...)
#define set_bit(word, bit)
crm_node_t * crm_get_peer_full(unsigned int id, const char *uname, int flags)
crm_node_t * crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t seen, int32_t votes, uint32_t children, const char *uuid, const char *uname, const char *addr, const char *state)
guint reap_crm_member(uint32_t id, const char *name)
Remove all peer cache entries matching a node ID and/or uname.
gboolean crm_is_peer_active(const crm_node_t *node)
guint crm_strcase_hash(gconstpointer v)
#define XPATH_GUEST_NODE_CONFIG
void crm_update_peer_expected(const char *source, crm_node_t *node, const char *expected)
#define crm_trace(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
const char * crm_element_value(xmlNode *data, const char *name)
int corosync_cmap_has_config(const char *prefix)
void crm_update_peer_uname(crm_node_t *node, const char *uname)
void(* crm_status_callback)(enum crm_status_type, crm_node_t *, const void *)
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
void crm_set_status_callback(void(*dispatch)(enum crm_status_type, crm_node_t *, const void *))
Set a client function that will be called after peer status changes.
const char * name_for_cluster_type(enum cluster_type_e type)
int crm_terminate_member(int nodeid, const char *uname, void *unused)
void crm_remote_peer_cache_refresh(xmlNode *cib)
Repopulate the remote peer cache based on CIB XML.
guint crm_active_peers(void)
#define crm_err(fmt, args...)
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection)
Wrappers for and extensions to libqb IPC.
crm_node_t * crm_update_peer_proc(const char *source, crm_node_t *node, uint32_t flag, const char *status)
#define safe_str_eq(a, b)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
void freeXpathObject(xmlXPathObjectPtr xpathObj)
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
#define XPATH_REMOTE_NODE_CONFIG
#define crm_info(fmt, args...)
const char * crm_peer_uuid(crm_node_t *node)
int(* dispatch)(const char *buffer, ssize_t length, gpointer userdata)
enum cluster_type_e get_cluster_type(void)
crm_node_t * crm_update_peer_state(const char *source, crm_node_t *node, const char *state, int membership)
Update a node's state and membership information.