63static GHashTable *cluster_node_cib_cache = NULL;
65static bool autoreap =
true;
66static bool has_quorum =
false;
70#define set_peer_flags(peer, flags_to_set) do { \
71 (peer)->flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \
72 "Peer", (peer)->name, \
73 (peer)->flags, (flags_to_set), \
77#define clear_peer_flags(peer, flags_to_clear) do { \
78 (peer)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
80 "Peer", (peer)->name, \
81 (peer)->flags, (flags_to_clear), \
110 has_quorum = quorate;
147 char *node_name_copy = NULL;
149 if (node_name == NULL) {
162 && ((node->
xml_id == NULL)
171 node_name_copy = strdup(node_name);
172 if (node_name_copy == NULL) {
176 node_name = node_name_copy;
183 free(node_name_copy);
190 free(node_name_copy);
196 node->
xml_id = strdup(node_name);
197 if (node->
xml_id == NULL) {
200 free(node_name_copy);
206 crm_trace(
"added %s to remote cache", node_name);
209 update_peer_uname(node, node_name);
210 free(node_name_copy);
230 crm_trace(
"Removing %s from Pacemaker Remote node cache", node_name);
245remote_state_from_cib(
const xmlNode *node_state)
270remote_cache_refresh_helper(xmlNode *
result,
void *user_data)
272 const struct refresh_data *
data = user_data;
274 const char *state = NULL;
280 if (
data->has_state) {
281 state = remote_state_from_cib(
result);
305mark_dirty(gpointer key, gpointer value, gpointer user_data)
311is_dirty(gpointer key, gpointer value, gpointer user_data)
325refresh_remote_nodes(xmlNode *cib)
327 struct refresh_data
data;
339 data.has_state = TRUE;
341 remote_cache_refresh_helper, &
data);
350 data.has_state = FALSE;
352 remote_cache_refresh_helper, &
data);
354 data.has_state = FALSE;
356 remote_cache_refresh_helper, &
data);
382 switch (cluster_layer) {
393 crm_err(
"Unhandled cluster layer: %s",
425should_forget_cluster_node(gpointer key, gpointer value, gpointer user_data)
430 if (search == NULL) {
446 crm_info(
"Removing node with name %s and cluster layer ID %" PRIu32
447 " from membership cache",
474 char *criterion = NULL;
478 crm_trace(
"Membership cache not initialized, ignoring removal request");
488 }
else if (node_name != NULL) {
493 should_forget_cluster_node, &search);
495 if (criterion != NULL) {
496 crm_notice(
"Removed %u inactive node%s with %s from the membership "
500 crm_notice(
"Removed all (%u) inactive cluster nodes from the "
506 crm_info(
"No inactive cluster nodes%s%s to remove from the membership "
508 ((criterion != NULL)?
" with " :
""), pcmk__s(criterion,
""));
516count_peer(gpointer key, gpointer value, gpointer user_data)
518 unsigned int *count = user_data;
538 unsigned int count = 0;
547destroy_crm_node(gpointer
data)
551 crm_trace(
"Destroying entry for node %" PRIu32
": %s",
578 if (cluster_node_cib_cache == NULL) {
591 crm_trace(
"Destroying peer cache with %d members",
598 crm_trace(
"Destroying remote peer cache with %d members",
604 if (cluster_node_cib_cache != NULL) {
605 crm_trace(
"Destroying configured cluster node cache with %d members",
606 g_hash_table_size(cluster_node_cib_cache));
607 g_hash_table_destroy(cluster_node_cib_cache);
608 cluster_node_cib_cache = NULL;
614 const void *) = NULL;
631 peer_status_callback = dispatch;
655dump_peer_hash(
int level,
const char *caller)
658 const char *
id = NULL;
662 while (g_hash_table_iter_next(&iter, (gpointer *) &
id, (gpointer *) &node)) {
663 do_crm_log(level,
"%s: Node %" PRIu32
"/%s = %p - %s",
664 caller, node->cluster_layer_id, node->name, node,
id);
669hash_find_by_data(gpointer key, gpointer value, gpointer user_data)
671 return value == user_data;
686search_cluster_member_cache(
unsigned int id,
const char *
uname,
700 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
711 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
712 if (node->cluster_layer_id ==
id) {
713 crm_trace(
"ID match: %" PRIu32, node->cluster_layer_id);
719 }
else if (uuid != NULL) {
721 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
725 crm_trace(
"Found cluster node cache entry by XML ID %s",
734 if(by_id == by_name) {
738 }
else if(by_id == NULL && by_name) {
742 dump_peer_hash(LOG_WARNING, __func__);
743 crm_crit(
"Nodes %u and %" PRIu32
" share the same name '%s'",
751 }
else if(by_name == NULL && by_id) {
754 if ((
uname != NULL) && (by_id->
name != NULL)) {
755 dump_peer_hash(LOG_WARNING, __func__);
756 crm_crit(
"Nodes '%s' and '%s' share the same cluster nodeid %u: "
757 "assuming '%s' is correct",
761 }
else if ((
uname != NULL) && (by_id->
name != NULL)) {
763 crm_notice(
"Node '%s' has changed its cluster layer ID "
764 "from %" PRIu32
" to %" PRIu32,
771 crm_warn(
"Nodes '%s' and '%s' share the same cluster nodeid: %u %s",
773 dump_peer_hash(LOG_INFO, __func__);
774 crm_abort(__FILE__, __func__, __LINE__,
"member weirdness", TRUE,
779 crm_warn(
"Nodes %" PRIu32
" and %" PRIu32
" share the same name: '%s'",
789 dump_peer_hash(LOG_DEBUG, __func__);
791 crm_info(
"Merging %p into %p", by_name, by_id);
812 const char *xml_id, uint32_t
flags)
823 }
else if (xml_id != NULL) {
831 node = search_cluster_member_cache(
id,
uname, xml_id);
835 if (xml_id != NULL) {
836 node = find_cib_cluster_node(xml_id,
uname);
841 node = find_cib_cluster_node(id_str,
uname);
866 char *node_name_copy = NULL;
868 if ((node_name == NULL) && (node_id == 0U)) {
873 if ((node_name != NULL)
879 node_name = node_name_copy;
881 crm_trace(
"Purging %s from Pacemaker Remote node cache", node_name);
886 free(node_name_copy);
906 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
907 if ((existing_node->cluster_layer_id > 0)
915 crm_warn(
"Removing cached offline node %" PRIu32
"/%s which has "
916 "conflicting name with %" PRIu32,
917 existing_node->cluster_layer_id, existing_node->name,
920 g_hash_table_iter_remove(&iter);
951 char *uname_lookup = NULL;
969 node = search_cluster_member_cache(
id,
uname, xml_id);
973 if ((
uname == NULL) && ((node == NULL) || (node->
name == NULL))) {
978 uname = uname_lookup;
983 node = search_cluster_member_cache(
id,
uname, xml_id);
992 crm_info(
"Created entry %s/%p for node %s/%u (%d total)",
993 uniqueid, node,
uname,
id,
998 if ((
id > 0) && (
uname != NULL)
1007 if ((
uname != NULL) && (node->
name == NULL)) {
1008 update_peer_uname(node,
uname);
1011 if ((xml_id == NULL) && (node->
xml_id == NULL)) {
1013 if (xml_id == NULL) {
1014 crm_debug(
"Cannot obtain an XML ID for node %s[%u] at this time",
1017 crm_info(
"Node %s[%u] has XML ID %s", node->
name,
id, xml_id);
1041 crm_err(
"Bug: can't update node name without name");
return);
1043 crm_err(
"Bug: can't update node name to %s without node",
uname);
1051 for (
const char *c =
uname; *c; ++c) {
1052 if ((*c >=
'A') && (*c <=
'Z')) {
1053 crm_warn(
"Node names with capitals are discouraged, consider changing '%s'",
1061 if (peer_status_callback != NULL) {
1069 remove_conflicting_peer(node);
1082static inline const char *
1085 const char *text =
"unknown";
1092 text =
"corosync-cpg";
1116 uint32_t flag,
const char *status)
1119 gboolean changed = FALSE;
1122 source, proc2text(flag), status);
1131 if (status == NULL) {
1139 node->
processes = pcmk__set_flags_as(__func__, __LINE__,
1147 node->
processes = pcmk__clear_flags_as(__func__, __LINE__,
1156 crm_info(
"%s: Node %s[%" PRIu32
"] - all processes are now offline",
1159 crm_info(
"%s: Node %s[%" PRIu32
"] - %s is now %s",
1161 proc2text(flag), status);
1174 if (peer_status_callback != NULL) {
1186 const char *peer_state = NULL;
1196 crm_trace(
"%s: Node %s[%" PRIu32
"] - %s is unchanged (%s)",
1213 const char *expected)
1216 gboolean changed = FALSE;
1218 CRM_CHECK(node != NULL,
crm_err(
"%s: Could not set 'expected' to %s", source, expected);
1233 crm_info(
"%s: Node %s[%" PRIu32
"] - expected state is now %s (was %s)",
1237 crm_trace(
"%s: Node %s[%" PRIu32
"] - expected state is unchanged (%s)",
1260 const char *state, uint64_t membership,
1261 GHashTableIter *iter)
1266 crm_err(
"Could not set state for unknown host to %s "
1267 QB_XS
" source=%s", state, source);
1279 char *last = node->
state;
1288 node->
state = strdup(state);
1290 " nodeid=%" PRIu32
" previous=%s source=%s",
1292 pcmk__s(last,
"unknown"), source);
1293 if (peer_status_callback != NULL) {
1298 if (autoreap && !is_member
1305 crm_notice(
"Purged 1 peer with cluster layer ID %" PRIu32
1306 "and/or name=%s from the membership cache",
1308 g_hash_table_iter_remove(iter);
1318 crm_trace(
"Node %s state is unchanged (%s) " QB_XS
1319 " nodeid=%" PRIu32
" source=%s",
1342 const char *state, uint64_t membership)
1344 return update_peer_state_iter(source, node, state, membership, NULL);
1356 GHashTableIter iter;
1361 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
1371 crm_info(
"State of node %s[%" PRIu32
"] is still unknown",
1379find_cib_cluster_node(
const char *
id,
const char *
uname)
1381 GHashTableIter iter;
1387 g_hash_table_iter_init(&iter, cluster_node_cib_cache);
1388 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1390 crm_trace(
"Name match: %s = %p", node->name, node);
1398 g_hash_table_iter_init(&iter, cluster_node_cib_cache);
1399 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1402 crm_trace(
"ID match: %s= %p",
id, node);
1410 if (by_id == by_name) {
1414 }
else if (by_id == NULL && by_name) {
1424 }
else if (by_name == NULL && by_id) {
1431 }
else if ((
uname != NULL) && (by_id->
name != NULL)
1436 }
else if ((
id != NULL) && (by_name->
xml_id != NULL)
1450 uname?
" with name " :
"",
1458cluster_node_cib_cache_refresh_helper(xmlNode *xml_node,
void *user_data)
1465 node = find_cib_cluster_node(
id,
uname);
1475 g_hash_table_replace(cluster_node_cib_cache, uniqueid, node);
1487refresh_cluster_node_cib_cache(xmlNode *cib)
1491 g_hash_table_foreach(cluster_node_cib_cache, mark_dirty, NULL);
1494 cluster_node_cib_cache_refresh_helper, NULL);
1497 g_hash_table_foreach_remove(cluster_node_cib_cache, is_dirty, NULL);
1503 refresh_remote_nodes(cib);
1504 refresh_cluster_node_cib_cache(cib);
@ pcmk__node_update_processes
Node process group membership updated.
@ pcmk__node_update_name
Node name updated.
@ pcmk__node_update_state
Node connection state updated.
const char * pcmk__cluster_get_xml_id(pcmk__node_status_t *node)
@ pcmk__node_search_cluster_member
Search for cluster nodes from membership cache.
@ pcmk__node_search_cluster_cib
Search for cluster nodes from CIB (as of last cache refresh)
@ pcmk__node_search_remote
Search for remote nodes.
@ pcmk__node_status_remote
@ pcmk__node_status_dirty
Node's cache entry is dirty.
char * pcmk__cluster_node_name(uint32_t nodeid)
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__assert_alloc(nmemb, size)
char * crm_generate_uuid(void)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Deprecated Pacemaker cluster API.
bool pcmk__corosync_has_nodelist(void)
bool pcmk__corosync_is_peer_active(const pcmk__node_status_t *node)
IPC interface to Pacemaker daemons.
#define crm_info(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
#define crm_warn(fmt, args...)
#define crm_crit(fmt, args...)
#define crm_notice(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
unsigned int pcmk__cluster_num_remote_nodes(void)
void pcmk__cluster_forget_cluster_node(uint32_t id, const char *node_name)
#define clear_peer_flags(peer, flags_to_clear)
GHashTable * pcmk__peer_cache
void pcmk__cluster_set_quorum(bool quorate)
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.
void pcmk__reap_unseen_nodes(uint64_t membership)
void pcmk__refresh_node_caches_from_cib(xmlNode *cib)
void pcmk__purge_node_from_cache(const char *node_name, uint32_t node_id)
void pcmk__cluster_set_status_callback(void(*dispatch)(enum pcmk__node_update, pcmk__node_status_t *, const void *))
pcmk__node_status_t * pcmk__get_node(unsigned int id, const char *uname, const char *xml_id, uint32_t flags)
#define set_peer_flags(peer, flags_to_set)
void pcmk__cluster_destroy_node_caches(void)
pcmk__node_status_t * pcmk__cluster_lookup_remote_node(const char *node_name)
bool pcmk__cluster_is_node_active(const pcmk__node_status_t *node)
unsigned int pcmk__cluster_num_active_nodes(void)
bool pcmk__cluster_has_quorum(void)
void pcmk__cluster_forget_remote_node(const char *node_name)
void pcmk__cluster_init_node_caches(void)
void pcmk__update_peer_expected(const char *source, pcmk__node_status_t *node, const char *expected)
void pcmk__cluster_set_autoreap(bool enable)
pcmk__node_status_t * crm_update_peer_proc(const char *source, pcmk__node_status_t *node, uint32_t flag, const char *status)
GHashTable * pcmk__remote_peer_cache
pcmk__node_status_t * pcmk__search_node_caches(unsigned int id, const char *uname, const char *xml_id, uint32_t flags)
#define PCMK_VALUE_MEMBER
#define PCMK_VALUE_ONLINE
pcmk__action_result_t result
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
#define pcmk__assert(expr)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk__plural_s(i)
void pcmk__str_update(char **str, const char *value)
#define pcmk__str_copy(str)
GHashTable * pcmk__strikey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Node status data (may be a cluster node or a Pacemaker Remote node)
uint32_t cluster_layer_id
Cluster-layer numeric node ID.
void * user_data
Arbitrary data (must be freeable by free())
char * name
Node name as known to cluster layer, or Pacemaker Remote node name.
time_t when_lost
When CPG membership was last lost.
uint32_t flags
Group of enum pcmk__node_status_flags
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
#define PCMK__XP_REMOTE_NODE_CONFIG
XPath expression matching CIB Pacemaker Remote connection resource.
#define PCMK__XP_REMOTE_NODE_STATUS
XPath expression matching CIB node state elements for Pacemaker Remote nodes.
#define PCMK__XP_MEMBER_NODE_CONFIG
XPath expression matching CIB node elements for cluster nodes.
#define PCMK__XP_GUEST_NODE_CONFIG
XPath expression matching CIB primitive meta-attribute defining a guest node.
void pcmk__xpath_foreach_result(xmlDoc *doc, const char *path, void(*fn)(xmlNode *, void *), void *user_data)