16 #include <sys/param.h>
17 #include <sys/types.h>
57 static gboolean crm_autoreap = TRUE;
84 if (node_name == NULL) {
103 node->
uuid = strdup(node_name);
104 if (node->
uuid == NULL) {
112 crm_trace(
"added %s to remote cache", node_name);
123 crm_trace(
"removed %s from remote peer cache", node_name);
139 remote_state_from_cib(xmlNode *node_state)
153 struct refresh_data {
166 remote_cache_refresh_helper(xmlNode *result,
void *user_data)
168 struct refresh_data *
data = user_data;
170 const char *state = NULL;
176 if (data->has_state) {
177 state = remote_state_from_cib(result);
201 mark_dirty(gpointer key, gpointer value, gpointer user_data)
207 is_dirty(gpointer key, gpointer value, gpointer user_data)
213 #define XPATH_GUEST_NODE_CONFIG \
214 "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
215 "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \
216 "[@name='" XML_RSC_ATTR_REMOTE_NODE "']"
219 #define XPATH_REMOTE_NODE_CONFIG \
220 "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
221 "[@type='remote'][@provider='pacemaker']"
224 #define XPATH_REMOTE_NODE_STATUS \
225 "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \
226 "[@" XML_NODE_IS_REMOTE "='true']"
236 struct refresh_data data;
248 data.has_state = TRUE;
250 remote_cache_refresh_helper, &data);
258 data.field =
"value";
259 data.has_state = FALSE;
261 remote_cache_refresh_helper, &data);
263 data.has_state = FALSE;
265 remote_cache_refresh_helper, &data);
293 crm_reap_dead_member(gpointer key, gpointer value, gpointer user_data)
298 if (search == NULL) {
301 }
else if (search->
id && node->
id != search->
id) {
308 crm_info(
"Removing node with name %s and id %u from membership cache",
330 crm_trace(
"Membership cache not initialized, ignoring purge request");
335 search.
uname = name ? strdup(name) : NULL;
336 matches = g_hash_table_foreach_remove(
crm_peer_cache, crm_reap_dead_member, &search);
338 crm_notice(
"Purged %d peer%s with id=%u%s%s from the membership cache",
340 (search.
uname?
" and/or uname=" :
""),
344 crm_info(
"No peers with id=%u%s%s to purge from the membership cache",
345 search.
id, (search.
uname?
" and/or uname=" :
""),
354 crm_count_peer(gpointer key, gpointer value, gpointer user_data)
356 guint *count = user_data;
376 destroy_crm_node(gpointer data)
460 crm_autoreap = autoreap;
463 static void crm_dump_peer_hash(
int level,
const char *caller)
466 const char *
id = NULL;
467 crm_node_t *node = NULL;
470 while (g_hash_table_iter_next(&iter, (gpointer *) &
id, (gpointer *) &node)) {
471 do_crm_log(level,
"%s: Node %u/%s = %p - %s", caller, node->
id, node->
uname, node,
id);
475 static gboolean crm_hash_find_by_data(gpointer key, gpointer value, gpointer user_data)
477 if(value == user_data) {
486 crm_node_t *node = NULL;
505 crm_node_t *node = NULL;
525 crm_node_t *node = NULL;
526 crm_node_t *by_id = NULL;
527 crm_node_t *by_name = NULL;
535 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
536 if(node->
uname && strcasecmp(node->
uname, uname) == 0) {
546 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
556 if(by_id == by_name) {
558 crm_trace(
"Consistent: %p for %u/%s", by_id,
id, uname);
560 }
else if(by_id == NULL && by_name) {
561 crm_trace(
"Only one: %p for %u/%s", by_name,
id, uname);
563 if(
id && by_name->
id) {
564 crm_dump_peer_hash(LOG_WARNING, __FUNCTION__);
565 crm_crit(
"Node %u and %u share the same name '%s'",
566 id, by_name->
id, uname);
573 }
else if(by_name == NULL && by_id) {
574 crm_trace(
"Only one: %p for %u/%s", by_id,
id, uname);
576 if(uname && by_id->
uname) {
577 crm_dump_peer_hash(LOG_WARNING, __FUNCTION__);
578 crm_crit(
"Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct",
579 uname, by_id->
uname,
id, uname);
582 }
else if(uname && by_id->
uname) {
584 crm_notice(
"Node '%s' has changed its ID from %u to %u", by_id->
uname, by_name->
id, by_id->
id);
585 g_hash_table_foreach_remove(
crm_peer_cache, crm_hash_find_by_data, by_name);
588 crm_warn(
"Node '%s' and '%s' share the same cluster nodeid: %u %s", by_id->
uname, by_name->
uname,
id, uname);
589 crm_dump_peer_hash(LOG_INFO, __FUNCTION__);
590 crm_abort(__FILE__, __FUNCTION__, __LINE__,
"member weirdness", TRUE, TRUE);
593 }
else if(
id && by_name->
id) {
594 crm_warn(
"Node %u and %u share the same name: '%s'", by_id->
id, by_name->
id, uname);
603 crm_dump_peer_hash(LOG_DEBUG, __FUNCTION__);
605 crm_info(
"Merging %p into %p", by_name, by_id);
606 g_hash_table_foreach_remove(
crm_peer_cache, crm_hash_find_by_data, by_name);
614 crm_remove_conflicting_peer(crm_node_t *node)
618 crm_node_t *existing_node = NULL;
620 if (node->
id == 0 || node->
uname == NULL) {
629 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
630 if (existing_node->
id > 0
631 && existing_node->
id != node->
id
632 && existing_node->
uname != NULL
633 && strcasecmp(existing_node->
uname, node->
uname) == 0) {
639 crm_warn(
"Removing cached offline node %u/%s which has conflicting uname with %u",
640 existing_node->
id, existing_node->
uname, node->
id);
642 g_hash_table_iter_remove(&iter);
655 crm_node_t *node = NULL;
656 char *uname_lookup = NULL;
666 if ((node == NULL || node->
uname == NULL) && (uname == NULL)) {
671 uname = uname_lookup;
672 crm_trace(
"Inferred a name of '%s' for node %u", uname,
id);
684 node = calloc(1,
sizeof(crm_node_t));
687 crm_info(
"Created entry %s/%p for node %s/%u (%d total)",
688 uniqueid, node, uname,
id, 1 + g_hash_table_size(
crm_peer_cache));
692 if(
id > 0 && uname && (node->
id == 0 || node->
uname == NULL)) {
693 crm_info(
"Node %u is now known as %s",
id, uname);
696 if(
id > 0 && node->
id == 0) {
700 if (uname && (node->
uname == NULL)) {
704 if(node->
uuid == NULL) {
708 crm_info(
"Node %u has uuid %s",
id, uuid);
711 crm_info(
"Cannot obtain a UUID for node %u/%s",
id, node->
uname);
735 crm_err(
"Bug: can't update node name without name");
return);
737 crm_err(
"Bug: can't update node name to %s without node", uname);
741 crm_debug(
"Node uname '%s' did not change", uname);
745 for (
const char *c = uname; *c; ++c) {
746 if ((*c >=
'A') && (*c <=
'Z')) {
747 crm_warn(
"Node names with capitals are discouraged, consider changing '%s'",
754 node->
uname = strdup(uname);
763 crm_remove_conflicting_peer(node);
788 gboolean changed = FALSE;
791 source, peer2text(flag), status);
return NULL);
799 if (status == NULL) {
818 crm_info(
"%s: Node %s[%u] - all processes are now offline", source, node->
uname,
821 crm_info(
"%s: Node %s[%u] - %s is now %s", source, node->
uname, node->
id,
822 peer2text(flag), status);
841 is_set(node->
processes, crm_get_cluster_proc())?
845 crm_trace(
"%s: Node %s[%u] - %s is unchanged (%s)", source, node->
uname, node->
id,
846 peer2text(flag), status);
855 gboolean changed = FALSE;
857 CRM_CHECK(node != NULL,
crm_err(
"%s: Could not set 'expected' to %s", source, expected);
872 crm_info(
"%s: Node %s[%u] - expected state is now %s (was %s)", source, node->
uname, node->
id,
876 crm_trace(
"%s: Node %s[%u] - expected state is unchanged (%s)", source, node->
uname,
898 crm_update_peer_state_iter(
const char *source, crm_node_t * node,
const char *state, uint64_t membership, GHashTableIter *iter)
903 crm_err(
"Could not set state for unknown host to %s"
904 CRM_XS " source=%s", state, source);
916 char *last = node->
state;
918 node->
state = strdup(state);
920 " nodeid=%u previous=%s source=%s", node->
uname, state,
921 node->
id, (last? last :
"unknown"), source);
933 crm_notice(
"Purged 1 peer with id=%u and/or uname=%s from the membership cache", node->
id, node->
uname);
934 g_hash_table_iter_remove(iter);
944 " nodeid=%u source=%s", node->
uname, state, node->
id, source);
967 return crm_update_peer_state_iter(source, node, state, membership, NULL);
980 crm_node_t *node = NULL;
984 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
992 crm_update_peer_state_iter(__FUNCTION__, node,
CRM_NODE_LOST, membership, &iter);
995 crm_info(
"State of node %s[%u] is still unknown",
1016 crm_find_known_peer(
const char *
id,
const char *
uname)
1018 GHashTableIter iter;
1019 crm_node_t *node = NULL;
1020 crm_node_t *by_id = NULL;
1021 crm_node_t *by_name = NULL;
1025 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1026 if (node->
uname && strcasecmp(node->
uname, uname) == 0) {
1036 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1037 if(strcasecmp(node->
uuid,
id) == 0) {
1038 crm_trace(
"ID match: %s= %p",
id, node);
1046 if (by_id == by_name) {
1048 crm_trace(
"Consistent: %p for %s/%s", by_id,
id, uname);
1050 }
else if (by_id == NULL && by_name) {
1051 crm_trace(
"Only one: %p for %s/%s", by_name,
id, uname);
1060 }
else if (by_name == NULL && by_id) {
1061 crm_trace(
"Only one: %p for %s/%s", by_id,
id, uname);
1067 }
else if (uname && by_id->
uname
1072 }
else if (
id && by_name->
uuid
1086 uname?
" with name " :
"",
1094 known_peer_cache_refresh_helper(xmlNode *xml_node,
void *user_data)
1098 crm_node_t * node = NULL;
1100 CRM_CHECK(
id != NULL && uname !=NULL,
return);
1101 node = crm_find_known_peer(
id, uname);
1106 node = calloc(1,
sizeof(crm_node_t));
1109 node->
uname = strdup(uname);
1112 node->
uuid = strdup(
id);
1120 node->
uname = strdup(uname);
1130 #define XPATH_MEMBER_NODE_CONFIG \
1131 "//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
1132 "/" XML_CIB_TAG_NODE "[not(@type) or @type='member']"
1135 crm_known_peer_cache_refresh(xmlNode *cib)
1142 known_peer_cache_refresh_helper, NULL);
1152 crm_known_peer_cache_refresh(cib);
1158 crm_node_t *node = NULL;
1159 char *id_str = NULL;
1173 node = crm_find_known_peer(id_str, uname);
void crm_peer_destroy(void)
#define CRM_CHECK(expr, failure_action)
#define crm_notice(fmt, args...)
#define XPATH_REMOTE_NODE_STATUS
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.
#define crm_crit(fmt, args...)
gboolean safe_str_neq(const char *a, const char *b)
char * crm_generate_uuid(void)
void crm_reap_unseen_nodes(uint64_t ring_id)
gboolean crm_is_peer_active(const crm_node_t *node)
int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off)
int crm_terminate_member(int nodeid, const char *uname, void *unused)
void crm_set_autoreap(gboolean autoreap)
Tell the library whether to automatically reap lost nodes.
GHashTable * crm_remote_peer_cache
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
crm_node_t * crm_update_peer_state(const char *source, crm_node_t *node, const char *state, uint64_t membership)
Update a node's state and membership information.
guint crm_active_peers(void)
#define clear_bit(word, bit)
char * get_node_name(uint32_t nodeid)
crm_node_t * crm_get_peer_full(unsigned int id, const char *uname, int flags)
gboolean crm_is_corosync_peer_active(const crm_node_t *node)
#define crm_warn(fmt, args...)
#define set_bit(word, bit)
void crm_remote_peer_cache_remove(const char *node_name)
#define crm_debug(fmt, args...)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define XPATH_GUEST_NODE_CONFIG
#define crm_trace(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
crm_node_t * crm_update_peer_proc(const char *source, crm_node_t *peer, uint32_t flag, const char *status)
guint crm_strcase_hash(gconstpointer v)
#define pcmk__plural_s(i)
int corosync_cmap_has_config(const char *prefix)
void(* crm_status_callback)(enum crm_status_type, crm_node_t *, const void *)
unsigned long long crm_peer_seq
guint reap_crm_member(uint32_t id, const char *name)
Remove all peer cache entries matching a node ID and/or uname.
const char * name_for_cluster_type(enum cluster_type_e type)
void crm_update_peer_expected(const char *source, crm_node_t *node, const char *expected)
gboolean is_corosync_cluster(void)
crm_node_t * crm_find_known_peer_full(unsigned int id, const char *uname, int flags)
crm_node_t * crm_remote_peer_get(const char *node_name)
Get a remote node peer cache entry, creating it if necessary.
#define crm_err(fmt, args...)
crm_node_t * crm_find_peer_full(unsigned int id, const char *uname, int flags)
void crm_foreach_xpath_result(xmlNode *xml, const char *xpath, void(*helper)(xmlNode *, void *), void *user_data)
Run a supplied function for each result of an xpath search.
Wrappers for and extensions to libqb IPC.
GHashTable * crm_known_peer_cache
#define XML_NODE_IN_CLUSTER
gboolean crm_is_true(const char *s)
void crm_update_peer_uname(crm_node_t *node, const char *uname)
#define safe_str_eq(a, b)
void crm_peer_caches_refresh(xmlNode *cib)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection)
crm_node_t * crm_find_peer(unsigned int id, const char *uname)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define XPATH_MEMBER_NODE_CONFIG
void crm_remote_peer_cache_refresh(xmlNode *cib)
Repopulate the remote peer cache based on CIB XML.
GHashTable * crm_peer_cache
#define XPATH_REMOTE_NODE_CONFIG
#define crm_info(fmt, args...)
const char * crm_peer_uuid(crm_node_t *node)
gboolean crm_strcase_equal(gconstpointer a, gconstpointer b)
enum cluster_type_e get_cluster_type(void)
int crm_remote_peer_cache_size(void)