16 #include <sys/param.h>    17 #include <sys/types.h>    61 static GHashTable *known_node_cache = NULL;
    65 static gboolean crm_autoreap  = TRUE;
    69 #define set_peer_flags(peer, flags_to_set) do {                               \    70         (peer)->flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE,     \    71                                            "Peer", (peer)->uname,             \    72                                            (peer)->flags, (flags_to_set),     \    76 #define clear_peer_flags(peer, flags_to_clear) do {                           \    77         (peer)->flags = pcmk__clear_flags_as(__func__, __LINE__,              \    79                                              "Peer", (peer)->uname,           \    80                                              (peer)->flags, (flags_to_clear), \   111     if (node_name == NULL) {
   130     node->
uuid = strdup(node_name);
   131     if (node->
uuid == NULL) {
   139     crm_trace(
"added %s to remote cache", node_name);
   142     update_peer_uname(node, node_name);
   150         crm_trace(
"removed %s from remote peer cache", node_name);
   166 remote_state_from_cib(
const xmlNode *node_state)
   179 struct refresh_data {
   192 remote_cache_refresh_helper(xmlNode *
result, 
void *user_data)
   194     const struct refresh_data *
data = user_data;
   196     const char *state = NULL;
   202     if (
data->has_state) {
   203         state = remote_state_from_cib(
result);
   227 mark_dirty(gpointer key, gpointer value, gpointer user_data)
   233 is_dirty(gpointer key, gpointer value, gpointer user_data)
   246     struct refresh_data 
data;
   258     data.has_state = TRUE;
   260                              remote_cache_refresh_helper, &
data);
   268     data.field = 
"value";
   269     data.has_state = FALSE;
   271                              remote_cache_refresh_helper, &
data);
   273     data.has_state = FALSE;
   275                              remote_cache_refresh_helper, &
data);
   303 crm_reap_dead_member(gpointer key, gpointer value, gpointer user_data)
   308     if (search == NULL) {
   311     } 
else if (search->
id && node->
id != search->
id) {
   318         crm_info(
"Removing node with name %s and id %u from membership cache",
   340         crm_trace(
"Membership cache not initialized, ignoring purge request");
   346     matches = g_hash_table_foreach_remove(
crm_peer_cache, crm_reap_dead_member, &search);
   348         crm_notice(
"Purged %d peer%s with id=%u%s%s from the membership cache",
   350                    (search.
uname? 
" and/or uname=" : 
""),
   354         crm_info(
"No peers with id=%u%s%s to purge from the membership cache",
   355                  search.
id, (search.
uname? 
" and/or uname=" : 
""),
   364 count_peer(gpointer key, gpointer value, gpointer user_data)
   366     guint *count = user_data;
   386 destroy_crm_node(gpointer 
data)
   411     if (known_node_cache == NULL) {
   431     if (known_node_cache != NULL) {
   432         crm_trace(
"Destroying known node cache with %d members",
   433                   g_hash_table_size(known_node_cache));
   434         g_hash_table_destroy(known_node_cache);
   435         known_node_cache = NULL;
   441                                     const void *) = NULL;
   456     peer_status_callback = dispatch;
   473     crm_autoreap = autoreap;
   477 dump_peer_hash(
int level, 
const char *caller)
   480     const char *
id = NULL;
   484     while (g_hash_table_iter_next(&iter, (gpointer *) &
id, (gpointer *) &node)) {
   485         do_crm_log(level, 
"%s: Node %u/%s = %p - %s", caller, node->id, node->uname, node, 
id);
   490 hash_find_by_data(gpointer key, gpointer value, gpointer user_data)
   492     return value == user_data;
   596         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
   597             if(node->uname && strcasecmp(node->uname, 
uname) == 0) {
   598                 crm_trace(
"Name match: %s = %p", node->uname, node);
   607         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
   609                 crm_trace(
"ID match: %u = %p", node->id, node);
   615     } 
else if (uuid != NULL) {
   617         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
   619                 crm_trace(
"UUID match: %s = %p", node->uuid, node);
   627     if(by_id == by_name) {
   631     } 
else if(by_id == NULL && by_name) {
   634         if(
id && by_name->
id) {
   635             dump_peer_hash(LOG_WARNING, __func__);
   636             crm_crit(
"Node %u and %u share the same name '%s'",
   644     } 
else if(by_name == NULL && by_id) {
   648             dump_peer_hash(LOG_WARNING, __func__);
   649             crm_crit(
"Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct",
   655             crm_notice(
"Node '%s' has changed its ID from %u to %u", by_id->
uname, by_name->
id, by_id->
id);
   656             g_hash_table_foreach_remove(
crm_peer_cache, hash_find_by_data, by_name);
   660             dump_peer_hash(LOG_INFO, __func__);
   661             crm_abort(__FILE__, __func__, __LINE__, 
"member weirdness", TRUE,
   665     } 
else if(
id && by_name->
id) {
   666         crm_warn(
"Node %u and %u share the same name: '%s'", by_id->
id, by_name->
id, 
uname);
   675         dump_peer_hash(LOG_DEBUG, __func__);
   677         crm_info(
"Merging %p into %p", by_name, by_id);
   678         g_hash_table_foreach_remove(
crm_peer_cache, hash_find_by_data, by_name);
   692     if (node->
id == 0 || node->
uname == NULL) {
   701     while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
   702         if (existing_node->id > 0
   703             && existing_node->id != node->
id   704             && existing_node->uname != NULL
   705             && strcasecmp(existing_node->uname, node->
uname) == 0) {
   711             crm_warn(
"Removing cached offline node %u/%s which has conflicting uname with %u",
   712                      existing_node->id, existing_node->uname, node->
id);
   714             g_hash_table_iter_remove(&iter);
   738     char *uname_lookup = NULL;
   748     if ((node == NULL || node->
uname == NULL) && (
uname == NULL)) { 
   753         uname = uname_lookup;
   769         crm_info(
"Created entry %s/%p for node %s/%u (%d total)",
   774     if(
id > 0 && 
uname && (node->
id == 0 || node->
uname == NULL)) {
   778     if(
id > 0 && node->
id == 0) {
   783         update_peer_uname(node, 
uname);
   786     if(node->
uuid == NULL) {
   792             crm_info(
"Node %u has uuid %s", 
id, uuid);
   795             crm_info(
"Cannot obtain a UUID for node %u/%s", 
id, node->
uname);
   834               crm_err(
"Bug: can't update node name without name"); 
return);
   836               crm_err(
"Bug: can't update node name to %s without node", 
uname);
   844     for (
const char *c = 
uname; *c; ++c) {
   845         if ((*c >= 
'A') && (*c <= 
'Z')) {
   846             crm_warn(
"Node names with capitals are discouraged, consider changing '%s'",
   854     if (peer_status_callback != NULL) {
   860         remove_conflicting_peer(node);
   873 static inline const char *
   876     const char *text = 
"unknown";
   883             text = 
"pacemaker-based";
   886             text = 
"pacemaker-controld";
   889             text = 
"pacemaker-schedulerd";
   892             text = 
"pacemaker-execd";
   895             text = 
"pacemaker-attrd";
   898             text = 
"pacemaker-fenced";
   901             text = 
"corosync-cpg";
   927     gboolean changed = FALSE;
   930                                     source, proc2text(flag), status);
   939     if (status == NULL) {
   947             node->
processes = pcmk__set_flags_as(__func__, __LINE__,
   955         node->
processes = pcmk__clear_flags_as(__func__, __LINE__,
   964             crm_info(
"%s: Node %s[%u] - all processes are now offline", source, node->
uname,
   967             crm_info(
"%s: Node %s[%u] - %s is now %s", source, node->
uname, node->
id,
   968                      proc2text(flag), status);
   981         if (peer_status_callback != NULL) {
   993             const char *peer_state = NULL;
  1003         crm_trace(
"%s: Node %s[%u] - %s is unchanged (%s)", source, node->
uname, node->
id,
  1004                   proc2text(flag), status);
  1019                            const char *expected)
  1022     gboolean changed = FALSE;
  1024     CRM_CHECK(node != NULL, 
crm_err(
"%s: Could not set 'expected' to %s", source, expected);
  1039         crm_info(
"%s: Node %s[%u] - expected state is now %s (was %s)", source, node->
uname, node->
id,
  1043         crm_trace(
"%s: Node %s[%u] - expected state is unchanged (%s)", source, node->
uname,
  1044                   node->
id, expected);
  1065 update_peer_state_iter(
const char *source, 
crm_node_t *node, 
const char *state,
  1066                        uint64_t membership, GHashTableIter *iter)
  1071               crm_err(
"Could not set state for unknown host to %s"  1072                       CRM_XS " source=%s", state, source);
  1084         char *last = node->
state;
  1093         node->
state = strdup(state);
  1095                    " nodeid=%u previous=%s source=%s", node->
uname, state,
  1096                    node->
id, (last? last : 
"unknown"), source);
  1097         if (peer_status_callback != NULL) {
  1102         if (crm_autoreap && !is_member
  1109                 crm_notice(
"Purged 1 peer with id=%u and/or uname=%s from the membership cache", node->
id, node->
uname);
  1110                 g_hash_table_iter_remove(iter);
  1120                   " nodeid=%u source=%s", node->
uname, state, node->
id, source);
  1142                         const char *state, uint64_t membership)
  1144     return update_peer_state_iter(source, node, state, membership, NULL);
  1156     GHashTableIter iter;
  1161     while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
  1162         if (node->last_seen != membership) {
  1173                 crm_info(
"State of node %s[%u] is still unknown",
  1174                          node->uname, node->id);
  1181 find_known_node(
const char *
id, 
const char *
uname)
  1183     GHashTableIter iter;
  1189         g_hash_table_iter_init(&iter, known_node_cache);
  1190         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
  1191             if (node->uname && strcasecmp(node->uname, 
uname) == 0) {
  1192                 crm_trace(
"Name match: %s = %p", node->uname, node);
  1200         g_hash_table_iter_init(&iter, known_node_cache);
  1201         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
  1202             if(strcasecmp(node->uuid, 
id) == 0) {
  1203                 crm_trace(
"ID match: %s= %p", 
id, node);
  1211     if (by_id == by_name) {
  1215     } 
else if (by_id == NULL && by_name) {
  1225     } 
else if (by_name == NULL && by_id) {
  1237     } 
else if (
id && by_name->
uuid  1251                    uname? 
" with name " : 
"",
  1259 known_node_cache_refresh_helper(xmlNode *xml_node, 
void *user_data)
  1266     node = find_known_node(
id, 
uname);
  1277         node->
uuid = strdup(
id);
  1280         g_hash_table_replace(known_node_cache, uniqueid, node);
  1292 refresh_known_node_cache(xmlNode *cib)
  1296     g_hash_table_foreach(known_node_cache, mark_dirty, NULL);
  1299                              known_node_cache_refresh_helper, NULL);
  1302     g_hash_table_foreach_remove(known_node_cache, is_dirty, NULL);
  1309     refresh_known_node_cache(cib);
  1327     char *id_str = NULL;
  1341     node = find_known_node(id_str, 
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)
 
void crm_peer_destroy(void)
 
int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off)
 
void pcmk__update_peer_expected(const char *source, crm_node_t *node, const char *expected)
 
crm_node_t * pcmk__get_peer(unsigned int id, const char *uname, const char *uuid)
Get a cluster node cache entry. 
 
crm_node_t * pcmk__get_peer_full(unsigned int id, const char *uname, const char *uuid, int flags)
Get a node cache entry (cluster or Pacemaker Remote) 
 
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
 
char * get_node_name(uint32_t nodeid)
Get the node name corresponding to a cluster node ID. 
 
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)
Check whether a Corosync cluster peer is active. 
 
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)
Get a node cache entry (cluster or Pacemaker Remote) 
 
#define clear_peer_flags(peer, flags_to_clear)
 
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...)
 
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. 
 
#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
 
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag. 
 
void pcmk__refresh_node_caches_from_cib(xmlNode *cib)
 
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)
 
crm_node_t * pcmk__search_node_caches(unsigned int id, const char *uname, uint32_t flags)
 
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)
Get a log-friendly string equivalent of a cluster type. 
 
crm_node_t * pcmk__search_known_node_cache(unsigned int id, const char *uname, uint32_t flags)
 
Deprecated Pacemaker cluster API. 
 
int crm_terminate_member(int nodeid, const char *uname, void *unused)
 
gboolean is_corosync_cluster(void)
Check whether the local cluster is a Corosync cluster. 
 
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 * pcmk__search_cluster_node_cache(unsigned int id, const char *uname, const char *uuid)
 
#define PCMK__XP_REMOTE_NODE_STATUS
 
crm_node_t * crm_remote_peer_get(const char *node_name)
Get a remote node peer cache entry, creating it if necessary. 
 
pcmk__action_result_t result
 
#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. 
 
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_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
 
#define PCMK__XP_MEMBER_NODE_CONFIG
 
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
Get a cluster node cache entry. 
 
#define crm_info(fmt, args...)
 
const char * crm_peer_uuid(crm_node_t *node)
Get (and set if needed) a node's UUID. 
 
GHashTable * pcmk__strikey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
 
enum cluster_type_e get_cluster_type(void)
Get (and validate) the local cluster type.