17 #include <sys/param.h> 18 #include <sys/types.h> 65 static GHashTable *cluster_node_cib_cache = NULL;
69 static bool autoreap =
true;
73 #define set_peer_flags(peer, flags_to_set) do { \ 74 (peer)->flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ 75 "Peer", (peer)->uname, \ 76 (peer)->flags, (flags_to_set), \ 80 #define clear_peer_flags(peer, flags_to_clear) do { \ 81 (peer)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ 83 "Peer", (peer)->uname, \ 84 (peer)->flags, (flags_to_clear), \ 89 static crm_node_t *find_cib_cluster_node(
const char *
id,
const char *
uname);
125 char *node_name_copy = NULL;
127 if (node_name == NULL) {
139 if ((node != NULL) && (node->
uuid == NULL)) {
143 node_name_copy = strdup(node_name);
144 if (node_name_copy == NULL) {
148 node_name = node_name_copy;
155 free(node_name_copy);
162 free(node_name_copy);
168 node->
uuid = strdup(node_name);
169 if (node->
uuid == NULL) {
172 free(node_name_copy);
178 crm_trace(
"added %s to remote cache", node_name);
181 update_peer_uname(node, node_name);
182 free(node_name_copy);
202 crm_trace(
"Removing %s from Pacemaker Remote node cache", node_name);
219 remote_state_from_cib(
const xmlNode *node_state)
232 struct refresh_data {
245 remote_cache_refresh_helper(xmlNode *
result,
void *user_data)
247 const struct refresh_data *
data = user_data;
249 const char *state = NULL;
255 if (
data->has_state) {
256 state = remote_state_from_cib(
result);
280 mark_dirty(gpointer key, gpointer value, gpointer user_data)
286 is_dirty(gpointer key, gpointer value, gpointer user_data)
298 refresh_remote_nodes(xmlNode *cib)
300 struct refresh_data
data;
312 data.has_state = TRUE;
314 remote_cache_refresh_helper, &
data);
323 data.has_state = FALSE;
325 remote_cache_refresh_helper, &
data);
327 data.has_state = FALSE;
329 remote_cache_refresh_helper, &
data);
355 switch (cluster_layer) {
361 #endif // SUPPORT_COROSYNC 366 crm_err(
"Unhandled cluster layer: %s",
397 should_forget_cluster_node(gpointer key, gpointer value, gpointer user_data)
402 if (search == NULL) {
405 if ((search->
id != 0) && (node->
id != search->
id)) {
408 if ((search->
id == 0)
419 pcmk__s(node->
uname,
"(unknown)"), node->
id);
445 char *criterion = NULL;
449 crm_trace(
"Membership cache not initialized, ignoring removal request");
459 }
else if (node_name != NULL) {
464 should_forget_cluster_node, &search);
466 if (criterion != NULL) {
467 crm_notice(
"Removed %u inactive node%s with %s from the membership " 471 crm_notice(
"Removed all (%u) inactive cluster nodes from the " 477 crm_info(
"No inactive cluster nodes%s%s to remove from the membership " 479 ((criterion != NULL)?
" with " :
""), pcmk__s(criterion,
""));
487 count_peer(gpointer key, gpointer value, gpointer user_data)
489 unsigned int *count = user_data;
509 unsigned int count = 0;
518 destroy_crm_node(gpointer
data)
547 if (cluster_node_cib_cache == NULL) {
560 crm_trace(
"Destroying peer cache with %d members",
567 crm_trace(
"Destroying remote peer cache with %d members",
573 if (cluster_node_cib_cache != NULL) {
574 crm_trace(
"Destroying configured cluster node cache with %d members",
575 g_hash_table_size(cluster_node_cib_cache));
576 g_hash_table_destroy(cluster_node_cib_cache);
577 cluster_node_cib_cache = NULL;
582 const void *) = NULL;
598 peer_status_callback = dispatch;
622 dump_peer_hash(
int level,
const char *caller)
625 const char *
id = NULL;
629 while (g_hash_table_iter_next(&iter, (gpointer *) &
id, (gpointer *) &node)) {
630 do_crm_log(level,
"%s: Node %u/%s = %p - %s", caller, node->id, node->uname, node,
id);
635 hash_find_by_data(gpointer key, gpointer value, gpointer user_data)
637 return value == user_data;
652 search_cluster_member_cache(
unsigned int id,
const char *
uname,
666 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
667 if(node->uname && strcasecmp(node->uname,
uname) == 0) {
668 crm_trace(
"Name match: %s = %p", node->uname, node);
677 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
679 crm_trace(
"ID match: %u = %p", node->id, node);
685 }
else if (uuid != NULL) {
687 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
689 crm_trace(
"UUID match: %s = %p", node->uuid, node);
697 if(by_id == by_name) {
701 }
else if(by_id == NULL && by_name) {
704 if(
id && by_name->
id) {
705 dump_peer_hash(LOG_WARNING, __func__);
706 crm_crit(
"Node %u and %u share the same name '%s'",
714 }
else if(by_name == NULL && by_id) {
718 dump_peer_hash(LOG_WARNING, __func__);
719 crm_crit(
"Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct",
725 crm_notice(
"Node '%s' has changed its ID from %u to %u", by_id->
uname, by_name->
id, by_id->
id);
726 g_hash_table_foreach_remove(
crm_peer_cache, hash_find_by_data, by_name);
730 dump_peer_hash(LOG_INFO, __func__);
731 crm_abort(__FILE__, __func__, __LINE__,
"member weirdness", TRUE,
735 }
else if(
id && by_name->
id) {
736 crm_warn(
"Node %u and %u share the same name: '%s'", by_id->
id, by_name->
id,
uname);
745 dump_peer_hash(LOG_DEBUG, __func__);
747 crm_info(
"Merging %p into %p", by_name, by_id);
748 g_hash_table_foreach_remove(
crm_peer_cache, hash_find_by_data, by_name);
780 node = search_cluster_member_cache(
id,
uname, NULL);
786 node = find_cib_cluster_node(id_str,
uname);
810 char *node_name_copy = NULL;
812 if ((node_name == NULL) && (node_id == 0U)) {
817 if ((node_name != NULL)
823 node_name = node_name_copy;
825 crm_trace(
"Purging %s from Pacemaker Remote node cache", node_name);
830 free(node_name_copy);
841 if (node->
id == 0 || node->
uname == NULL) {
850 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
851 if (existing_node->id > 0
852 && existing_node->id != node->
id 853 && existing_node->uname != NULL
854 && strcasecmp(existing_node->uname, node->
uname) == 0) {
860 crm_warn(
"Removing cached offline node %u/%s which has conflicting uname with %u",
861 existing_node->id, existing_node->uname, node->
id);
863 g_hash_table_iter_remove(&iter);
894 char *uname_lookup = NULL;
912 node = search_cluster_member_cache(
id,
uname, uuid);
916 if ((node == NULL || node->
uname == NULL) && (
uname == NULL)) {
921 uname = uname_lookup;
926 node = search_cluster_member_cache(
id,
uname, uuid);
935 crm_info(
"Created entry %s/%p for node %s/%u (%d total)",
940 if(
id > 0 &&
uname && (node->
id == 0 || node->
uname == NULL)) {
944 if(
id > 0 && node->
id == 0) {
949 update_peer_uname(node,
uname);
952 if(node->
uuid == NULL) {
958 crm_info(
"Node %u has uuid %s",
id, uuid);
961 crm_info(
"Cannot obtain a UUID for node %u/%s",
id, node->
uname);
985 crm_err(
"Bug: can't update node name without name");
return);
987 crm_err(
"Bug: can't update node name to %s without node",
uname);
995 for (
const char *c =
uname; *c; ++c) {
996 if ((*c >=
'A') && (*c <=
'Z')) {
997 crm_warn(
"Node names with capitals are discouraged, consider changing '%s'",
1005 if (peer_status_callback != NULL) {
1009 #if SUPPORT_COROSYNC 1013 remove_conflicting_peer(node);
1026 static inline const char *
1029 const char *text =
"unknown";
1036 text =
"corosync-cpg";
1062 gboolean changed = FALSE;
1065 source, proc2text(flag), status);
1074 if (status == NULL) {
1082 node->
processes = pcmk__set_flags_as(__func__, __LINE__,
1090 node->
processes = pcmk__clear_flags_as(__func__, __LINE__,
1099 crm_info(
"%s: Node %s[%u] - all processes are now offline", source, node->
uname,
1102 crm_info(
"%s: Node %s[%u] - %s is now %s", source, node->
uname, node->
id,
1103 proc2text(flag), status);
1116 if (peer_status_callback != NULL) {
1128 const char *peer_state = NULL;
1138 crm_trace(
"%s: Node %s[%u] - %s is unchanged (%s)", source, node->
uname, node->
id,
1139 proc2text(flag), status);
1154 const char *expected)
1157 gboolean changed = FALSE;
1159 CRM_CHECK(node != NULL,
crm_err(
"%s: Could not set 'expected' to %s", source, expected);
1174 crm_info(
"%s: Node %s[%u] - expected state is now %s (was %s)", source, node->
uname, node->
id,
1178 crm_trace(
"%s: Node %s[%u] - expected state is unchanged (%s)", source, node->
uname,
1179 node->
id, expected);
1200 update_peer_state_iter(
const char *source,
crm_node_t *node,
const char *state,
1201 uint64_t membership, GHashTableIter *iter)
1206 crm_err(
"Could not set state for unknown host to %s" 1207 CRM_XS " source=%s", state, source);
1219 char *last = node->
state;
1228 node->
state = strdup(state);
1230 " nodeid=%u previous=%s source=%s", node->
uname, state,
1231 node->
id, (last? last :
"unknown"), source);
1232 if (peer_status_callback != NULL) {
1237 if (autoreap && !is_member
1245 "=%u and/or uname=%s from the membership cache",
1247 g_hash_table_iter_remove(iter);
1257 " nodeid=%u source=%s", node->
uname, state, node->
id, source);
1279 const char *state, uint64_t membership)
1281 return update_peer_state_iter(source, node, state, membership, NULL);
1293 GHashTableIter iter;
1298 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
1299 if (node->last_seen != membership) {
1310 crm_info(
"State of node %s[%u] is still unknown",
1311 node->uname, node->id);
1318 find_cib_cluster_node(
const char *
id,
const char *
uname)
1320 GHashTableIter iter;
1326 g_hash_table_iter_init(&iter, cluster_node_cib_cache);
1327 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1328 if (node->uname && strcasecmp(node->uname,
uname) == 0) {
1329 crm_trace(
"Name match: %s = %p", node->uname, node);
1337 g_hash_table_iter_init(&iter, cluster_node_cib_cache);
1338 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1339 if(strcasecmp(node->uuid,
id) == 0) {
1340 crm_trace(
"ID match: %s= %p",
id, node);
1348 if (by_id == by_name) {
1352 }
else if (by_id == NULL && by_name) {
1362 }
else if (by_name == NULL && by_id) {
1374 }
else if (
id && by_name->
uuid 1388 uname?
" with name " :
"",
1396 cluster_node_cib_cache_refresh_helper(xmlNode *xml_node,
void *user_data)
1403 node = find_cib_cluster_node(
id,
uname);
1413 g_hash_table_replace(cluster_node_cib_cache, uniqueid, node);
1425 refresh_cluster_node_cib_cache(xmlNode *cib)
1429 g_hash_table_foreach(cluster_node_cib_cache, mark_dirty, NULL);
1432 cluster_node_cib_cache_refresh_helper, NULL);
1435 g_hash_table_foreach_remove(cluster_node_cib_cache, is_dirty, NULL);
1441 refresh_remote_nodes(cib);
1442 refresh_cluster_node_cib_cache(cib);
1479 return QB_MIN(count, INT_MAX);
1485 refresh_remote_nodes(cib);
1519 crm_trace(
"Membership cache not initialized, ignoring purge request");
1526 should_forget_cluster_node, &search);
1529 "=%u%s%s from the membership cache",
1531 (search.
uname?
" and/or uname=" :
""),
1536 "=%u%s%s to purge from the membership cache",
1537 search.
id, (search.
uname?
" and/or uname=" :
""),
#define CRM_CHECK(expr, failure_action)
#define crm_notice(fmt, args...)
GHashTable * crm_peer_cache
#define crm_crit(fmt, args...)
char * crm_generate_uuid(void)
unsigned int pcmk__cluster_num_active_nodes(void)
bool pcmk__corosync_is_peer_active(const crm_node_t *node)
void crm_peer_destroy(void)
const char * pcmk_cluster_layer_text(enum pcmk_cluster_layer layer)
Get a log-friendly string equivalent of a cluster layer.
int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off)
Search for cluster nodes from membership cache.
void pcmk__update_peer_expected(const char *source, crm_node_t *node, const char *expected)
void pcmk__purge_node_from_cache(const char *node_name, uint32_t node_id)
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.
GHashTable * crm_remote_peer_cache
unsigned long long crm_peer_seq
void crm_remote_peer_cache_remove(const char *node_name)
int crm_remote_peer_cache_size(void)
#define crm_warn(fmt, args...)
#define PCMK__XP_GUEST_NODE_CONFIG
crm_node_t * crm_get_peer_full(unsigned int id, const char *uname, int flags)
#define clear_peer_flags(peer, flags_to_clear)
guint reap_crm_member(uint32_t id, const char *name)
gboolean crm_is_peer_active(const crm_node_t *node)
#define crm_debug(fmt, args...)
void pcmk__reap_unseen_nodes(uint64_t membership)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
void pcmk__cluster_init_node_caches(void)
#define crm_trace(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
crm_node_t * pcmk__cluster_lookup_remote_node(const char *node_name)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
crm_node_t * pcmk__get_node(unsigned int id, const char *uname, const char *uuid, uint32_t flags)
void pcmk__refresh_node_caches_from_cib(xmlNode *cib)
void pcmk__cluster_set_status_callback(void(*dispatch)(enum crm_status_type, crm_node_t *, const void *))
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
#define PCMK__XP_REMOTE_NODE_CONFIG
void pcmk__str_update(char **str, const char *value)
Wrappers for and extensions to libxml2.
bool pcmk__cluster_is_node_active(const crm_node_t *node)
crm_node_t * pcmk__search_node_caches(unsigned int id, const char *uname, uint32_t flags)
#define pcmk__str_copy(str)
void crm_set_status_callback(void(*dispatch)(enum crm_status_type, crm_node_t *, const void *))
Deprecated Pacemaker cluster API.
int crm_terminate_member(int nodeid, const char *uname, void *unused)
void pcmk__cluster_forget_cluster_node(uint32_t id, const char *node_name)
#define PCMK_VALUE_ONLINE
void crm_remote_peer_cache_refresh(xmlNode *cib)
guint crm_active_peers(void)
#define PCMK__XP_REMOTE_NODE_STATUS
Search for cluster nodes from CIB (as of last cache refresh)
crm_node_t * crm_remote_peer_get(const char *node_name)
pcmk__action_result_t result
#define crm_err(fmt, args...)
int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection)
pcmk_cluster_layer
Types of cluster layer.
char * pcmk__cluster_node_name(uint32_t nodeid)
#define pcmk__plural_s(i)
unsigned int pcmk__cluster_num_remote_nodes(void)
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.
bool pcmk__corosync_has_nodelist(void)
IPC interface to Pacemaker daemons.
crm_node_t * crm_update_peer_proc(const char *source, crm_node_t *node, uint32_t flag, const char *status)
#define set_peer_flags(peer, flags_to_set)
void crm_set_autoreap(gboolean enable)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
#define PCMK__XP_MEMBER_NODE_CONFIG
#define pcmk__assert_alloc(nmemb, size)
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
void pcmk__cluster_destroy_node_caches(void)
#define crm_info(fmt, args...)
enum pcmk_cluster_layer pcmk_get_cluster_layer(void)
Get and validate the local cluster layer.
void pcmk__cluster_forget_remote_node(const char *node_name)
const char * pcmk__cluster_node_uuid(crm_node_t *node)
GHashTable * pcmk__strikey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
void pcmk__cluster_set_autoreap(bool enable)