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");
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;
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) {
535 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
536 if(node->uname && strcasecmp(node->uname,
uname) == 0) {
537 crm_trace(
"Name match: %s = %p", node->uname, node);
546 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
548 crm_trace(
"ID match: %u = %p", node->id, node);
556 if(by_id == by_name) {
560 }
else if(by_id == NULL && by_name) {
563 if(
id && by_name->
id) {
564 crm_dump_peer_hash(LOG_WARNING, __func__);
565 crm_crit(
"Node %u and %u share the same name '%s'",
573 }
else if(by_name == NULL && by_id) {
577 crm_dump_peer_hash(LOG_WARNING, __func__);
578 crm_crit(
"Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct",
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);
589 crm_dump_peer_hash(LOG_INFO, __func__);
590 crm_abort(__FILE__, __func__, __LINE__,
"member weirdness", TRUE,
594 }
else if(
id && by_name->
id) {
595 crm_warn(
"Node %u and %u share the same name: '%s'", by_id->
id, by_name->
id,
uname);
604 crm_dump_peer_hash(LOG_DEBUG, __func__);
606 crm_info(
"Merging %p into %p", by_name, by_id);
607 g_hash_table_foreach_remove(
crm_peer_cache, crm_hash_find_by_data, by_name);
621 if (node->
id == 0 || node->
uname == NULL) {
630 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
631 if (existing_node->id > 0
632 && existing_node->id != node->
id 633 && existing_node->uname != NULL
634 && strcasecmp(existing_node->uname, node->
uname) == 0) {
640 crm_warn(
"Removing cached offline node %u/%s which has conflicting uname with %u",
641 existing_node->id, existing_node->uname, node->
id);
643 g_hash_table_iter_remove(&iter);
657 char *uname_lookup = NULL;
667 if ((node == NULL || node->
uname == NULL) && (
uname == NULL)) {
672 uname = uname_lookup;
688 crm_info(
"Created entry %s/%p for node %s/%u (%d total)",
693 if(
id > 0 &&
uname && (node->
id == 0 || node->
uname == NULL)) {
697 if(
id > 0 && node->
id == 0) {
705 if(node->
uuid == NULL) {
709 crm_info(
"Node %u has uuid %s",
id, uuid);
712 crm_info(
"Cannot obtain a UUID for node %u/%s",
id, node->
uname);
736 crm_err(
"Bug: can't update node name without name");
return);
738 crm_err(
"Bug: can't update node name to %s without node",
uname);
746 for (
const char *c =
uname; *c; ++c) {
747 if ((*c >=
'A') && (*c <=
'Z')) {
748 crm_warn(
"Node names with capitals are discouraged, consider changing '%s'",
764 crm_remove_conflicting_peer(node);
789 gboolean changed = FALSE;
792 source, peer2text(flag), status);
return NULL);
800 if (status == NULL) {
808 node->
processes = pcmk__set_flags_as(__func__, __LINE__,
816 node->
processes = pcmk__clear_flags_as(__func__, __LINE__,
825 crm_info(
"%s: Node %s[%u] - all processes are now offline", source, node->
uname,
828 crm_info(
"%s: Node %s[%u] - %s is now %s", source, node->
uname, node->
id,
829 peer2text(flag), status);
847 const char *peer_state = NULL;
857 crm_trace(
"%s: Node %s[%u] - %s is unchanged (%s)", source, node->
uname, node->
id,
858 peer2text(flag), status);
867 gboolean changed = FALSE;
869 CRM_CHECK(node != NULL,
crm_err(
"%s: Could not set 'expected' to %s", source, expected);
884 crm_info(
"%s: Node %s[%u] - expected state is now %s (was %s)", source, node->
uname, node->
id,
888 crm_trace(
"%s: Node %s[%u] - expected state is unchanged (%s)", source, node->
uname,
910 crm_update_peer_state_iter(
const char *source,
crm_node_t * node,
const char *state, uint64_t membership, GHashTableIter *iter)
915 crm_err(
"Could not set state for unknown host to %s" 916 CRM_XS " source=%s", state, source);
928 char *last = node->
state;
930 node->
state = strdup(state);
932 " nodeid=%u previous=%s source=%s", node->
uname, state,
933 node->
id, (last? last :
"unknown"), source);
939 if (crm_autoreap && !is_member
946 crm_notice(
"Purged 1 peer with id=%u and/or uname=%s from the membership cache", node->
id, node->
uname);
947 g_hash_table_iter_remove(iter);
957 " nodeid=%u source=%s", node->
uname, state, node->
id, source);
980 return crm_update_peer_state_iter(source, node, state, membership, NULL);
997 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
998 if (node->last_seen != membership) {
1009 crm_info(
"State of node %s[%u] is still unknown",
1010 node->uname, node->id);
1030 crm_find_known_peer(
const char *
id,
const char *
uname)
1032 GHashTableIter iter;
1039 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1040 if (node->uname && strcasecmp(node->uname,
uname) == 0) {
1041 crm_trace(
"Name match: %s = %p", node->uname, node);
1050 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1051 if(strcasecmp(node->uuid,
id) == 0) {
1052 crm_trace(
"ID match: %s= %p",
id, node);
1060 if (by_id == by_name) {
1064 }
else if (by_id == NULL && by_name) {
1074 }
else if (by_name == NULL && by_id) {
1086 }
else if (
id && by_name->
uuid 1100 uname?
" with name " :
"",
1108 known_peer_cache_refresh_helper(xmlNode *xml_node,
void *user_data)
1115 node = crm_find_known_peer(
id,
uname);
1126 node->
uuid = strdup(
id);
1144 #define XPATH_MEMBER_NODE_CONFIG \ 1145 "//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \ 1146 "/" XML_CIB_TAG_NODE "[not(@type) or @type='member']" 1149 crm_known_peer_cache_refresh(xmlNode *cib)
1156 known_peer_cache_refresh_helper, NULL);
1166 crm_known_peer_cache_refresh(cib);
1173 char *id_str = NULL;
1187 node = crm_find_known_peer(id_str,
uname);
#define CRM_CHECK(expr, failure_action)
void crm_reap_unseen_nodes(uint64_t membership)
#define crm_notice(fmt, args...)
#define XPATH_REMOTE_NODE_STATUS
GHashTable * crm_peer_cache
#define crm_crit(fmt, args...)
char * crm_generate_uuid(void)
void crm_peer_destroy(void)
#define pcmk__clear_peer_flags(peer, flags_to_clear)
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)
crm_node_t * crm_find_known_peer_full(unsigned int id, const char *uname, int flags)
crm_node_t * crm_find_peer_full(unsigned int id, const char *uname, int flags)
GHashTable * crm_remote_peer_cache
#define pcmk__set_peer_flags(peer, flags_to_set)
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_peer_caches_refresh(xmlNode *cib)
void crm_remote_peer_cache_remove(const char *node_name)
gboolean crm_is_corosync_peer_active(const crm_node_t *node)
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.
int crm_remote_peer_cache_size(void)
#define crm_warn(fmt, args...)
crm_node_t * crm_get_peer_full(unsigned int id, const char *uname, int flags)
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)
#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
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.
guint crm_strcase_hash(gconstpointer v)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
int corosync_cmap_has_config(const char *prefix)
void crm_update_peer_uname(crm_node_t *node, const char *uname)
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_status_callback)(enum crm_status_type, crm_node_t *, const void *)
gboolean is_corosync_cluster(void)
void crm_remote_peer_cache_refresh(xmlNode *cib)
Repopulate the remote peer cache based on CIB XML.
guint crm_active_peers(void)
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...)
int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection)
#define pcmk__plural_s(i)
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.
IPC interface to Pacemaker daemons.
GHashTable * crm_known_peer_cache
crm_node_t * crm_update_peer_proc(const char *source, crm_node_t *node, uint32_t flag, const char *status)
#define XML_NODE_IN_CLUSTER
gboolean crm_is_true(const char *s)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define XPATH_MEMBER_NODE_CONFIG
#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)