This source file includes following definitions.
- crm_remote_peer_cache_size
 
- crm_remote_peer_get
 
- crm_remote_peer_cache_remove
 
- remote_state_from_cib
 
- remote_cache_refresh_helper
 
- mark_dirty
 
- is_dirty
 
- crm_remote_peer_cache_refresh
 
- crm_is_peer_active
 
- crm_reap_dead_member
 
- reap_crm_member
 
- count_peer
 
- crm_active_peers
 
- destroy_crm_node
 
- crm_peer_init
 
- crm_peer_destroy
 
- crm_set_status_callback
 
- crm_set_autoreap
 
- dump_peer_hash
 
- hash_find_by_data
 
- pcmk__search_node_caches
 
- crm_get_peer_full
 
- pcmk__search_cluster_node_cache
 
- remove_conflicting_peer
 
- crm_get_peer
 
- update_peer_uname
 
- proc2text
 
- crm_update_peer_proc
 
- pcmk__update_peer_expected
 
- update_peer_state_iter
 
- pcmk__update_peer_state
 
- pcmk__reap_unseen_nodes
 
- find_known_node
 
- known_node_cache_refresh_helper
 
- refresh_known_node_cache
 
- pcmk__refresh_node_caches_from_cib
 
- pcmk__search_known_node_cache
 
- crm_terminate_member
 
- crm_terminate_member_no_mainloop
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #ifndef _GNU_SOURCE
  13 #  define _GNU_SOURCE
  14 #endif
  15 
  16 #include <sys/param.h>
  17 #include <sys/types.h>
  18 #include <stdio.h>
  19 #include <unistd.h>
  20 #include <string.h>
  21 #include <glib.h>
  22 #include <crm/common/ipc.h>
  23 #include <crm/common/xml_internal.h>
  24 #include <crm/cluster/internal.h>
  25 #include <crm/msg_xml.h>
  26 #include <crm/stonith-ng.h>
  27 #include "crmcluster_private.h"
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 GHashTable *crm_peer_cache = NULL;
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 GHashTable *crm_remote_peer_cache = NULL;
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 static GHashTable *known_node_cache = NULL;
  62 
  63 unsigned long long crm_peer_seq = 0;
  64 gboolean crm_have_quorum = FALSE;
  65 static gboolean crm_autoreap  = TRUE;
  66 
  67 
  68 
  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),     \
  73                                            #flags_to_set);                    \
  74     } while (0)
  75 
  76 #define clear_peer_flags(peer, flags_to_clear) do {                           \
  77         (peer)->flags = pcmk__clear_flags_as(__func__, __LINE__,              \
  78                                              LOG_TRACE,                       \
  79                                              "Peer", (peer)->uname,           \
  80                                              (peer)->flags, (flags_to_clear), \
  81                                              #flags_to_clear);                \
  82     } while (0)
  83 
  84 static void update_peer_uname(crm_node_t *node, const char *uname);
  85 
  86 int
  87 crm_remote_peer_cache_size(void)
     
  88 {
  89     if (crm_remote_peer_cache == NULL) {
  90         return 0;
  91     }
  92     return g_hash_table_size(crm_remote_peer_cache);
  93 }
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 crm_node_t *
 107 crm_remote_peer_get(const char *node_name)
     
 108 {
 109     crm_node_t *node;
 110 
 111     if (node_name == NULL) {
 112         errno = -EINVAL;
 113         return NULL;
 114     }
 115 
 116     
 117     node = g_hash_table_lookup(crm_remote_peer_cache, node_name);
 118     if (node) {
 119         return node;
 120     }
 121 
 122     
 123     node = calloc(1, sizeof(crm_node_t));
 124     if (node == NULL) {
 125         return NULL;
 126     }
 127 
 128     
 129     set_peer_flags(node, crm_remote_node);
 130     node->uuid = strdup(node_name);
 131     if (node->uuid == NULL) {
 132         free(node);
 133         errno = -ENOMEM;
 134         return NULL;
 135     }
 136 
 137     
 138     g_hash_table_replace(crm_remote_peer_cache, node->uuid, node);
 139     crm_trace("added %s to remote cache", node_name);
 140 
 141     
 142     update_peer_uname(node, node_name);
 143     return node;
 144 }
 145 
 146 void
 147 crm_remote_peer_cache_remove(const char *node_name)
     
 148 {
 149     if (g_hash_table_remove(crm_remote_peer_cache, node_name)) {
 150         crm_trace("removed %s from remote peer cache", node_name);
 151     }
 152 }
 153 
 154 
 155 
 156 
 157 
 158 
 159 
 160 
 161 
 162 
 163 
 164 
 165 static const char *
 166 remote_state_from_cib(const xmlNode *node_state)
     
 167 {
 168     bool status = false;
 169 
 170     if (pcmk__xe_get_bool_attr(node_state, XML_NODE_IN_CLUSTER, &status) == pcmk_rc_ok && !status) {
 171         return CRM_NODE_LOST;
 172     } else {
 173         return CRM_NODE_MEMBER;
 174     }
 175 }
 176 
 177 
 178 struct refresh_data {
 179     const char *field;  
 180     gboolean has_state; 
 181 };
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 
 190 static void
 191 remote_cache_refresh_helper(xmlNode *result, void *user_data)
     
 192 {
 193     const struct refresh_data *data = user_data;
 194     const char *remote = crm_element_value(result, data->field);
 195     const char *state = NULL;
 196     crm_node_t *node;
 197 
 198     CRM_CHECK(remote != NULL, return);
 199 
 200     
 201     if (data->has_state) {
 202         state = remote_state_from_cib(result);
 203     }
 204 
 205     
 206     node = g_hash_table_lookup(crm_remote_peer_cache, remote);
 207 
 208     if (node == NULL) {
 209         
 210         node = crm_remote_peer_get(remote);
 211         CRM_ASSERT(node);
 212         if (state) {
 213             pcmk__update_peer_state(__func__, node, state, 0);
 214         }
 215 
 216     } else if (pcmk_is_set(node->flags, crm_node_dirty)) {
 217         
 218         clear_peer_flags(node, crm_node_dirty);
 219         if (state) {
 220             pcmk__update_peer_state(__func__, node, state, 0);
 221         }
 222     }
 223 }
 224 
 225 static void
 226 mark_dirty(gpointer key, gpointer value, gpointer user_data)
     
 227 {
 228     set_peer_flags((crm_node_t *) value, crm_node_dirty);
 229 }
 230 
 231 static gboolean
 232 is_dirty(gpointer key, gpointer value, gpointer user_data)
     
 233 {
 234     return pcmk_is_set(((crm_node_t*)value)->flags, crm_node_dirty);
 235 }
 236 
 237 
 238 
 239 
 240 
 241 
 242 void
 243 crm_remote_peer_cache_refresh(xmlNode *cib)
     
 244 {
 245     struct refresh_data data;
 246 
 247     crm_peer_init();
 248 
 249     
 250 
 251 
 252 
 253     g_hash_table_foreach(crm_remote_peer_cache, mark_dirty, NULL);
 254 
 255     
 256     data.field = "id";
 257     data.has_state = TRUE;
 258     crm_foreach_xpath_result(cib, PCMK__XP_REMOTE_NODE_STATUS,
 259                              remote_cache_refresh_helper, &data);
 260 
 261     
 262 
 263 
 264 
 265 
 266 
 267     data.field = "value";
 268     data.has_state = FALSE;
 269     crm_foreach_xpath_result(cib, PCMK__XP_GUEST_NODE_CONFIG,
 270                              remote_cache_refresh_helper, &data);
 271     data.field = "id";
 272     data.has_state = FALSE;
 273     crm_foreach_xpath_result(cib, PCMK__XP_REMOTE_NODE_CONFIG,
 274                              remote_cache_refresh_helper, &data);
 275 
 276     
 277     g_hash_table_foreach_remove(crm_remote_peer_cache, is_dirty, NULL);
 278 }
 279 
 280 gboolean
 281 crm_is_peer_active(const crm_node_t * node)
     
 282 {
 283     if(node == NULL) {
 284         return FALSE;
 285     }
 286 
 287     if (pcmk_is_set(node->flags, crm_remote_node)) {
 288         
 289 
 290         return FALSE;
 291     }
 292 #if SUPPORT_COROSYNC
 293     if (is_corosync_cluster()) {
 294         return crm_is_corosync_peer_active(node);
 295     }
 296 #endif
 297     crm_err("Unhandled cluster type: %s", name_for_cluster_type(get_cluster_type()));
 298     return FALSE;
 299 }
 300 
 301 static gboolean
 302 crm_reap_dead_member(gpointer key, gpointer value, gpointer user_data)
     
 303 {
 304     crm_node_t *node = value;
 305     crm_node_t *search = user_data;
 306 
 307     if (search == NULL) {
 308         return FALSE;
 309 
 310     } else if (search->id && node->id != search->id) {
 311         return FALSE;
 312 
 313     } else if (search->id == 0 && !pcmk__str_eq(node->uname, search->uname, pcmk__str_casei)) {
 314         return FALSE;
 315 
 316     } else if (crm_is_peer_active(value) == FALSE) {
 317         crm_info("Removing node with name %s and id %u from membership cache",
 318                  (node->uname? node->uname : "unknown"), node->id);
 319         return TRUE;
 320     }
 321     return FALSE;
 322 }
 323 
 324 
 325 
 326 
 327 
 328 
 329 
 330 
 331 
 332 guint
 333 reap_crm_member(uint32_t id, const char *name)
     
 334 {
 335     int matches = 0;
 336     crm_node_t search = { 0, };
 337 
 338     if (crm_peer_cache == NULL) {
 339         crm_trace("Membership cache not initialized, ignoring purge request");
 340         return 0;
 341     }
 342 
 343     search.id = id;
 344     pcmk__str_update(&search.uname, name);
 345     matches = g_hash_table_foreach_remove(crm_peer_cache, crm_reap_dead_member, &search);
 346     if(matches) {
 347         crm_notice("Purged %d peer%s with id=%u%s%s from the membership cache",
 348                    matches, pcmk__plural_s(matches), search.id,
 349                    (search.uname? " and/or uname=" : ""),
 350                    (search.uname? search.uname : ""));
 351 
 352     } else {
 353         crm_info("No peers with id=%u%s%s to purge from the membership cache",
 354                  search.id, (search.uname? " and/or uname=" : ""),
 355                  (search.uname? search.uname : ""));
 356     }
 357 
 358     free(search.uname);
 359     return matches;
 360 }
 361 
 362 static void
 363 count_peer(gpointer key, gpointer value, gpointer user_data)
     
 364 {
 365     guint *count = user_data;
 366     crm_node_t *node = value;
 367 
 368     if (crm_is_peer_active(node)) {
 369         *count = *count + 1;
 370     }
 371 }
 372 
 373 guint
 374 crm_active_peers(void)
     
 375 {
 376     guint count = 0;
 377 
 378     if (crm_peer_cache) {
 379         g_hash_table_foreach(crm_peer_cache, count_peer, &count);
 380     }
 381     return count;
 382 }
 383 
 384 static void
 385 destroy_crm_node(gpointer data)
     
 386 {
 387     crm_node_t *node = data;
 388 
 389     crm_trace("Destroying entry for node %u: %s", node->id, node->uname);
 390 
 391     free(node->uname);
 392     free(node->state);
 393     free(node->uuid);
 394     free(node->expected);
 395     free(node->conn_host);
 396     free(node);
 397 }
 398 
 399 void
 400 crm_peer_init(void)
     
 401 {
 402     if (crm_peer_cache == NULL) {
 403         crm_peer_cache = pcmk__strikey_table(free, destroy_crm_node);
 404     }
 405 
 406     if (crm_remote_peer_cache == NULL) {
 407         crm_remote_peer_cache = pcmk__strikey_table(NULL, destroy_crm_node);
 408     }
 409 
 410     if (known_node_cache == NULL) {
 411         known_node_cache = pcmk__strikey_table(free, destroy_crm_node);
 412     }
 413 }
 414 
 415 void
 416 crm_peer_destroy(void)
     
 417 {
 418     if (crm_peer_cache != NULL) {
 419         crm_trace("Destroying peer cache with %d members", g_hash_table_size(crm_peer_cache));
 420         g_hash_table_destroy(crm_peer_cache);
 421         crm_peer_cache = NULL;
 422     }
 423 
 424     if (crm_remote_peer_cache != NULL) {
 425         crm_trace("Destroying remote peer cache with %d members", g_hash_table_size(crm_remote_peer_cache));
 426         g_hash_table_destroy(crm_remote_peer_cache);
 427         crm_remote_peer_cache = NULL;
 428     }
 429 
 430     if (known_node_cache != NULL) {
 431         crm_trace("Destroying known node cache with %d members",
 432                   g_hash_table_size(known_node_cache));
 433         g_hash_table_destroy(known_node_cache);
 434         known_node_cache = NULL;
 435     }
 436 
 437 }
 438 
 439 static void (*peer_status_callback)(enum crm_status_type, crm_node_t *,
 440                                     const void *) = NULL;
 441 
 442 
 443 
 444 
 445 
 446 
 447 
 448 
 449 
 450 
 451 
 452 void
 453 crm_set_status_callback(void (*dispatch) (enum crm_status_type, crm_node_t *, const void *))
     
 454 {
 455     peer_status_callback = dispatch;
 456 }
 457 
 458 
 459 
 460 
 461 
 462 
 463 
 464 
 465 
 466 
 467 
 468 
 469 void
 470 crm_set_autoreap(gboolean autoreap)
     
 471 {
 472     crm_autoreap = autoreap;
 473 }
 474 
 475 static void
 476 dump_peer_hash(int level, const char *caller)
     
 477 {
 478     GHashTableIter iter;
 479     const char *id = NULL;
 480     crm_node_t *node = NULL;
 481 
 482     g_hash_table_iter_init(&iter, crm_peer_cache);
 483     while (g_hash_table_iter_next(&iter, (gpointer *) &id, (gpointer *) &node)) {
 484         do_crm_log(level, "%s: Node %u/%s = %p - %s", caller, node->id, node->uname, node, id);
 485     }
 486 }
 487 
 488 static gboolean
 489 hash_find_by_data(gpointer key, gpointer value, gpointer user_data)
     
 490 {
 491     return value == user_data;
 492 }
 493 
 494 
 495 
 496 
 497 
 498 
 499 
 500 
 501 
 502 
 503 
 504 crm_node_t *
 505 pcmk__search_node_caches(unsigned int id, const char *uname, uint32_t flags)
     
 506 {
 507     crm_node_t *node = NULL;
 508 
 509     CRM_ASSERT(id > 0 || uname != NULL);
 510 
 511     crm_peer_init();
 512 
 513     if ((uname != NULL) && pcmk_is_set(flags, CRM_GET_PEER_REMOTE)) {
 514         node = g_hash_table_lookup(crm_remote_peer_cache, uname);
 515     }
 516 
 517     if ((node == NULL) && pcmk_is_set(flags, CRM_GET_PEER_CLUSTER)) {
 518         node = pcmk__search_cluster_node_cache(id, uname);
 519     }
 520     return node;
 521 }
 522 
 523 
 524 
 525 
 526 
 527 
 528 
 529 
 530 
 531 
 532 crm_node_t *
 533 crm_get_peer_full(unsigned int id, const char *uname, int flags)
     
 534 {
 535     crm_node_t *node = NULL;
 536 
 537     CRM_ASSERT(id > 0 || uname != NULL);
 538 
 539     crm_peer_init();
 540 
 541     if (pcmk_is_set(flags, CRM_GET_PEER_REMOTE)) {
 542         node = g_hash_table_lookup(crm_remote_peer_cache, uname);
 543     }
 544 
 545     if ((node == NULL) && pcmk_is_set(flags, CRM_GET_PEER_CLUSTER)) {
 546         node = crm_get_peer(id, uname);
 547     }
 548     return node;
 549 }
 550 
 551 
 552 
 553 
 554 
 555 
 556 
 557 
 558 
 559 
 560 crm_node_t *
 561 pcmk__search_cluster_node_cache(unsigned int id, const char *uname)
     
 562 {
 563     GHashTableIter iter;
 564     crm_node_t *node = NULL;
 565     crm_node_t *by_id = NULL;
 566     crm_node_t *by_name = NULL;
 567 
 568     CRM_ASSERT(id > 0 || uname != NULL);
 569 
 570     crm_peer_init();
 571 
 572     if (uname != NULL) {
 573         g_hash_table_iter_init(&iter, crm_peer_cache);
 574         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
 575             if(node->uname && strcasecmp(node->uname, uname) == 0) {
 576                 crm_trace("Name match: %s = %p", node->uname, node);
 577                 by_name = node;
 578                 break;
 579             }
 580         }
 581     }
 582 
 583     if (id > 0) {
 584         g_hash_table_iter_init(&iter, crm_peer_cache);
 585         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
 586             if(node->id == id) {
 587                 crm_trace("ID match: %u = %p", node->id, node);
 588                 by_id = node;
 589                 break;
 590             }
 591         }
 592     }
 593 
 594     node = by_id; 
 595     if(by_id == by_name) {
 596         
 597         crm_trace("Consistent: %p for %u/%s", by_id, id, uname);
 598 
 599     } else if(by_id == NULL && by_name) {
 600         crm_trace("Only one: %p for %u/%s", by_name, id, uname);
 601 
 602         if(id && by_name->id) {
 603             dump_peer_hash(LOG_WARNING, __func__);
 604             crm_crit("Node %u and %u share the same name '%s'",
 605                      id, by_name->id, uname);
 606             node = NULL; 
 607 
 608         } else {
 609             node = by_name;
 610         }
 611 
 612     } else if(by_name == NULL && by_id) {
 613         crm_trace("Only one: %p for %u/%s", by_id, id, uname);
 614 
 615         if(uname && by_id->uname) {
 616             dump_peer_hash(LOG_WARNING, __func__);
 617             crm_crit("Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct",
 618                      uname, by_id->uname, id, uname);
 619         }
 620 
 621     } else if(uname && by_id->uname) {
 622         if(pcmk__str_eq(uname, by_id->uname, pcmk__str_casei)) {
 623             crm_notice("Node '%s' has changed its ID from %u to %u", by_id->uname, by_name->id, by_id->id);
 624             g_hash_table_foreach_remove(crm_peer_cache, hash_find_by_data, by_name);
 625 
 626         } else {
 627             crm_warn("Node '%s' and '%s' share the same cluster nodeid: %u %s", by_id->uname, by_name->uname, id, uname);
 628             dump_peer_hash(LOG_INFO, __func__);
 629             crm_abort(__FILE__, __func__, __LINE__, "member weirdness", TRUE,
 630                       TRUE);
 631         }
 632 
 633     } else if(id && by_name->id) {
 634         crm_warn("Node %u and %u share the same name: '%s'", by_id->id, by_name->id, uname);
 635 
 636     } else {
 637         
 638 
 639         
 640 
 641 
 642 
 643         dump_peer_hash(LOG_DEBUG, __func__);
 644 
 645         crm_info("Merging %p into %p", by_name, by_id);
 646         g_hash_table_foreach_remove(crm_peer_cache, hash_find_by_data, by_name);
 647     }
 648 
 649     return node;
 650 }
 651 
 652 #if SUPPORT_COROSYNC
 653 static guint
 654 remove_conflicting_peer(crm_node_t *node)
     
 655 {
 656     int matches = 0;
 657     GHashTableIter iter;
 658     crm_node_t *existing_node = NULL;
 659 
 660     if (node->id == 0 || node->uname == NULL) {
 661         return 0;
 662     }
 663 
 664     if (!pcmk__corosync_has_nodelist()) {
 665         return 0;
 666     }
 667 
 668     g_hash_table_iter_init(&iter, crm_peer_cache);
 669     while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) {
 670         if (existing_node->id > 0
 671             && existing_node->id != node->id
 672             && existing_node->uname != NULL
 673             && strcasecmp(existing_node->uname, node->uname) == 0) {
 674 
 675             if (crm_is_peer_active(existing_node)) {
 676                 continue;
 677             }
 678 
 679             crm_warn("Removing cached offline node %u/%s which has conflicting uname with %u",
 680                      existing_node->id, existing_node->uname, node->id);
 681 
 682             g_hash_table_iter_remove(&iter);
 683             matches++;
 684         }
 685     }
 686 
 687     return matches;
 688 }
 689 #endif
 690 
 691 
 692 
 693 
 694 
 695 
 696 
 697 
 698 
 699 
 700 crm_node_t *
 701 crm_get_peer(unsigned int id, const char *uname)
     
 702 {
 703     crm_node_t *node = NULL;
 704     char *uname_lookup = NULL;
 705 
 706     CRM_ASSERT(id > 0 || uname != NULL);
 707 
 708     crm_peer_init();
 709 
 710     node = pcmk__search_cluster_node_cache(id, uname);
 711 
 712     
 713 
 714     if ((node == NULL || node->uname == NULL) && (uname == NULL)) { 
 715         uname_lookup = get_node_name(id);
 716     }
 717 
 718     if (uname_lookup) {
 719         uname = uname_lookup;
 720         crm_trace("Inferred a name of '%s' for node %u", uname, id);
 721 
 722         
 723         if (node == NULL) {
 724             node = pcmk__search_cluster_node_cache(id, uname);
 725         }
 726     }
 727 
 728 
 729     if (node == NULL) {
 730         char *uniqueid = crm_generate_uuid();
 731 
 732         node = calloc(1, sizeof(crm_node_t));
 733         CRM_ASSERT(node);
 734 
 735         crm_info("Created entry %s/%p for node %s/%u (%d total)",
 736                  uniqueid, node, uname, id, 1 + g_hash_table_size(crm_peer_cache));
 737         g_hash_table_replace(crm_peer_cache, uniqueid, node);
 738     }
 739 
 740     if(id > 0 && uname && (node->id == 0 || node->uname == NULL)) {
 741         crm_info("Node %u is now known as %s", id, uname);
 742     }
 743 
 744     if(id > 0 && node->id == 0) {
 745         node->id = id;
 746     }
 747 
 748     if (uname && (node->uname == NULL)) {
 749         update_peer_uname(node, uname);
 750     }
 751 
 752     if(node->uuid == NULL) {
 753         const char *uuid = crm_peer_uuid(node);
 754 
 755         if (uuid) {
 756             crm_info("Node %u has uuid %s", id, uuid);
 757 
 758         } else {
 759             crm_info("Cannot obtain a UUID for node %u/%s", id, node->uname);
 760         }
 761     }
 762 
 763     free(uname_lookup);
 764 
 765     return node;
 766 }
 767 
 768 
 769 
 770 
 771 
 772 
 773 
 774 
 775 
 776 
 777 
 778 
 779 static void
 780 update_peer_uname(crm_node_t *node, const char *uname)
     
 781 {
 782     CRM_CHECK(uname != NULL,
 783               crm_err("Bug: can't update node name without name"); return);
 784     CRM_CHECK(node != NULL,
 785               crm_err("Bug: can't update node name to %s without node", uname);
 786               return);
 787 
 788     if (pcmk__str_eq(uname, node->uname, pcmk__str_casei)) {
 789         crm_debug("Node uname '%s' did not change", uname);
 790         return;
 791     }
 792 
 793     for (const char *c = uname; *c; ++c) {
 794         if ((*c >= 'A') && (*c <= 'Z')) {
 795             crm_warn("Node names with capitals are discouraged, consider changing '%s'",
 796                      uname);
 797             break;
 798         }
 799     }
 800 
 801     pcmk__str_update(&node->uname, uname);
 802 
 803     if (peer_status_callback != NULL) {
 804         peer_status_callback(crm_status_uname, node, NULL);
 805     }
 806 
 807 #if SUPPORT_COROSYNC
 808     if (is_corosync_cluster() && !pcmk_is_set(node->flags, crm_remote_node)) {
 809         remove_conflicting_peer(node);
 810     }
 811 #endif
 812 }
 813 
 814 
 815 
 816 
 817 
 818 
 819 
 820 
 821 
 822 static inline const char *
 823 proc2text(enum crm_proc_flag proc)
     
 824 {
 825     const char *text = "unknown";
 826 
 827     switch (proc) {
 828         case crm_proc_none:
 829             text = "none";
 830             break;
 831         case crm_proc_based:
 832             text = "pacemaker-based";
 833             break;
 834         case crm_proc_controld:
 835             text = "pacemaker-controld";
 836             break;
 837         case crm_proc_schedulerd:
 838             text = "pacemaker-schedulerd";
 839             break;
 840         case crm_proc_execd:
 841             text = "pacemaker-execd";
 842             break;
 843         case crm_proc_attrd:
 844             text = "pacemaker-attrd";
 845             break;
 846         case crm_proc_fenced:
 847             text = "pacemaker-fenced";
 848             break;
 849         case crm_proc_cpg:
 850             text = "corosync-cpg";
 851             break;
 852     }
 853     return text;
 854 }
 855 
 856 
 857 
 858 
 859 
 860 
 861 
 862 
 863 
 864 
 865 
 866 
 867 
 868 
 869 
 870 
 871 
 872 crm_node_t *
 873 crm_update_peer_proc(const char *source, crm_node_t * node, uint32_t flag, const char *status)
     
 874 {
 875     uint32_t last = 0;
 876     gboolean changed = FALSE;
 877 
 878     CRM_CHECK(node != NULL, crm_err("%s: Could not set %s to %s for NULL",
 879                                     source, proc2text(flag), status);
 880                             return NULL);
 881 
 882     
 883     if (pcmk_is_set(node->flags, crm_remote_node)) {
 884         return node;
 885     }
 886 
 887     last = node->processes;
 888     if (status == NULL) {
 889         node->processes = flag;
 890         if (node->processes != last) {
 891             changed = TRUE;
 892         }
 893 
 894     } else if (pcmk__str_eq(status, ONLINESTATUS, pcmk__str_casei)) {
 895         if ((node->processes & flag) != flag) {
 896             node->processes = pcmk__set_flags_as(__func__, __LINE__,
 897                                                  LOG_TRACE, "Peer process",
 898                                                  node->uname, node->processes,
 899                                                  flag, "processes");
 900             changed = TRUE;
 901         }
 902 
 903     } else if (node->processes & flag) {
 904         node->processes = pcmk__clear_flags_as(__func__, __LINE__,
 905                                                LOG_TRACE, "Peer process",
 906                                                node->uname, node->processes,
 907                                                flag, "processes");
 908         changed = TRUE;
 909     }
 910 
 911     if (changed) {
 912         if (status == NULL && flag <= crm_proc_none) {
 913             crm_info("%s: Node %s[%u] - all processes are now offline", source, node->uname,
 914                      node->id);
 915         } else {
 916             crm_info("%s: Node %s[%u] - %s is now %s", source, node->uname, node->id,
 917                      proc2text(flag), status);
 918         }
 919 
 920         
 921 
 922 
 923         if (peer_status_callback != NULL) {
 924             peer_status_callback(crm_status_processes, node, &last);
 925         }
 926 
 927         
 928 
 929 
 930         if (crm_peer_cache == NULL) {
 931             return NULL;
 932         }
 933 
 934         if (crm_autoreap) {
 935             const char *peer_state = NULL;
 936 
 937             if (pcmk_is_set(node->processes, crm_get_cluster_proc())) {
 938                 peer_state = CRM_NODE_MEMBER;
 939             } else {
 940                 peer_state = CRM_NODE_LOST;
 941             }
 942             node = pcmk__update_peer_state(__func__, node, peer_state, 0);
 943         }
 944     } else {
 945         crm_trace("%s: Node %s[%u] - %s is unchanged (%s)", source, node->uname, node->id,
 946                   proc2text(flag), status);
 947     }
 948     return node;
 949 }
 950 
 951 
 952 
 953 
 954 
 955 
 956 
 957 
 958 
 959 void
 960 pcmk__update_peer_expected(const char *source, crm_node_t *node,
     
 961                            const char *expected)
 962 {
 963     char *last = NULL;
 964     gboolean changed = FALSE;
 965 
 966     CRM_CHECK(node != NULL, crm_err("%s: Could not set 'expected' to %s", source, expected);
 967               return);
 968 
 969     
 970     if (pcmk_is_set(node->flags, crm_remote_node)) {
 971         return;
 972     }
 973 
 974     last = node->expected;
 975     if (expected != NULL && !pcmk__str_eq(node->expected, expected, pcmk__str_casei)) {
 976         node->expected = strdup(expected);
 977         changed = TRUE;
 978     }
 979 
 980     if (changed) {
 981         crm_info("%s: Node %s[%u] - expected state is now %s (was %s)", source, node->uname, node->id,
 982                  expected, last);
 983         free(last);
 984     } else {
 985         crm_trace("%s: Node %s[%u] - expected state is unchanged (%s)", source, node->uname,
 986                   node->id, expected);
 987     }
 988 }
 989 
 990 
 991 
 992 
 993 
 994 
 995 
 996 
 997 
 998 
 999 
1000 
1001 
1002 
1003 
1004 
1005 
1006 static crm_node_t *
1007 update_peer_state_iter(const char *source, crm_node_t *node, const char *state,
     
1008                        uint64_t membership, GHashTableIter *iter)
1009 {
1010     gboolean is_member;
1011 
1012     CRM_CHECK(node != NULL,
1013               crm_err("Could not set state for unknown host to %s"
1014                       CRM_XS " source=%s", state, source);
1015               return NULL);
1016 
1017     is_member = pcmk__str_eq(state, CRM_NODE_MEMBER, pcmk__str_casei);
1018     if (is_member) {
1019         node->when_lost = 0;
1020         if (membership) {
1021             node->last_seen = membership;
1022         }
1023     }
1024 
1025     if (state && !pcmk__str_eq(node->state, state, pcmk__str_casei)) {
1026         char *last = node->state;
1027 
1028         node->state = strdup(state);
1029         crm_notice("Node %s state is now %s " CRM_XS
1030                    " nodeid=%u previous=%s source=%s", node->uname, state,
1031                    node->id, (last? last : "unknown"), source);
1032         if (peer_status_callback != NULL) {
1033             peer_status_callback(crm_status_nstate, node, last);
1034         }
1035         free(last);
1036 
1037         if (crm_autoreap && !is_member
1038             && !pcmk_is_set(node->flags, crm_remote_node)) {
1039             
1040 
1041 
1042 
1043             if(iter) {
1044                 crm_notice("Purged 1 peer with id=%u and/or uname=%s from the membership cache", node->id, node->uname);
1045                 g_hash_table_iter_remove(iter);
1046 
1047             } else {
1048                 reap_crm_member(node->id, node->uname);
1049             }
1050             node = NULL;
1051         }
1052 
1053     } else {
1054         crm_trace("Node %s state is unchanged (%s) " CRM_XS
1055                   " nodeid=%u source=%s", node->uname, state, node->id, source);
1056     }
1057     return node;
1058 }
1059 
1060 
1061 
1062 
1063 
1064 
1065 
1066 
1067 
1068 
1069 
1070 
1071 
1072 
1073 
1074 
1075 crm_node_t *
1076 pcmk__update_peer_state(const char *source, crm_node_t *node,
     
1077                         const char *state, uint64_t membership)
1078 {
1079     return update_peer_state_iter(source, node, state, membership, NULL);
1080 }
1081 
1082 
1083 
1084 
1085 
1086 
1087 
1088 void
1089 pcmk__reap_unseen_nodes(uint64_t membership)
     
1090 {
1091     GHashTableIter iter;
1092     crm_node_t *node = NULL;
1093 
1094     crm_trace("Reaping unseen nodes...");
1095     g_hash_table_iter_init(&iter, crm_peer_cache);
1096     while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&node)) {
1097         if (node->last_seen != membership) {
1098             if (node->state) {
1099                 
1100 
1101 
1102 
1103 
1104                 update_peer_state_iter(__func__, node, CRM_NODE_LOST,
1105                                            membership, &iter);
1106 
1107             } else {
1108                 crm_info("State of node %s[%u] is still unknown",
1109                          node->uname, node->id);
1110             }
1111         }
1112     }
1113 }
1114 
1115 static crm_node_t *
1116 find_known_node(const char *id, const char *uname)
     
1117 {
1118     GHashTableIter iter;
1119     crm_node_t *node = NULL;
1120     crm_node_t *by_id = NULL;
1121     crm_node_t *by_name = NULL;
1122 
1123     if (uname) {
1124         g_hash_table_iter_init(&iter, known_node_cache);
1125         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1126             if (node->uname && strcasecmp(node->uname, uname) == 0) {
1127                 crm_trace("Name match: %s = %p", node->uname, node);
1128                 by_name = node;
1129                 break;
1130             }
1131         }
1132     }
1133 
1134     if (id) {
1135         g_hash_table_iter_init(&iter, known_node_cache);
1136         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
1137             if(strcasecmp(node->uuid, id) == 0) {
1138                 crm_trace("ID match: %s= %p", id, node);
1139                 by_id = node;
1140                 break;
1141             }
1142         }
1143     }
1144 
1145     node = by_id; 
1146     if (by_id == by_name) {
1147         
1148         crm_trace("Consistent: %p for %s/%s", by_id, id, uname);
1149 
1150     } else if (by_id == NULL && by_name) {
1151         crm_trace("Only one: %p for %s/%s", by_name, id, uname);
1152 
1153         if (id) {
1154             node = NULL;
1155 
1156         } else {
1157             node = by_name;
1158         }
1159 
1160     } else if (by_name == NULL && by_id) {
1161         crm_trace("Only one: %p for %s/%s", by_id, id, uname);
1162 
1163         if (uname) {
1164             node = NULL;
1165         }
1166 
1167     } else if (uname && by_id->uname
1168                && pcmk__str_eq(uname, by_id->uname, pcmk__str_casei)) {
1169         
1170 
1171 
1172     } else if (id && by_name->uuid
1173                && pcmk__str_eq(id, by_name->uuid, pcmk__str_casei)) {
1174         
1175 
1176         node = by_name;
1177 
1178     } else {
1179         node = NULL;
1180     }
1181 
1182     if (node == NULL) {
1183         crm_debug("Couldn't find node%s%s%s%s",
1184                    id? " " : "",
1185                    id? id : "",
1186                    uname? " with name " : "",
1187                    uname? uname : "");
1188     }
1189 
1190     return node;
1191 }
1192 
1193 static void
1194 known_node_cache_refresh_helper(xmlNode *xml_node, void *user_data)
     
1195 {
1196     const char *id = crm_element_value(xml_node, XML_ATTR_ID);
1197     const char *uname = crm_element_value(xml_node, XML_ATTR_UNAME);
1198     crm_node_t * node =  NULL;
1199 
1200     CRM_CHECK(id != NULL && uname !=NULL, return);
1201     node = find_known_node(id, uname);
1202 
1203     if (node == NULL) {
1204         char *uniqueid = crm_generate_uuid();
1205 
1206         node = calloc(1, sizeof(crm_node_t));
1207         CRM_ASSERT(node != NULL);
1208 
1209         node->uname = strdup(uname);
1210         CRM_ASSERT(node->uname != NULL);
1211 
1212         node->uuid = strdup(id);
1213         CRM_ASSERT(node->uuid != NULL);
1214 
1215         g_hash_table_replace(known_node_cache, uniqueid, node);
1216 
1217     } else if (pcmk_is_set(node->flags, crm_node_dirty)) {
1218         pcmk__str_update(&node->uname, uname);
1219 
1220         
1221         clear_peer_flags(node, crm_node_dirty);
1222     }
1223 
1224 }
1225 
1226 static void
1227 refresh_known_node_cache(xmlNode *cib)
     
1228 {
1229     crm_peer_init();
1230 
1231     g_hash_table_foreach(known_node_cache, mark_dirty, NULL);
1232 
1233     crm_foreach_xpath_result(cib, PCMK__XP_MEMBER_NODE_CONFIG,
1234                              known_node_cache_refresh_helper, NULL);
1235 
1236     
1237     g_hash_table_foreach_remove(known_node_cache, is_dirty, NULL);
1238 }
1239 
1240 void
1241 pcmk__refresh_node_caches_from_cib(xmlNode *cib)
     
1242 {
1243     crm_remote_peer_cache_refresh(cib);
1244     refresh_known_node_cache(cib);
1245 }
1246 
1247 
1248 
1249 
1250 
1251 
1252 
1253 
1254 
1255 
1256 
1257 crm_node_t *
1258 pcmk__search_known_node_cache(unsigned int id, const char *uname,
     
1259                               uint32_t flags)
1260 {
1261     crm_node_t *node = NULL;
1262     char *id_str = NULL;
1263 
1264     CRM_ASSERT(id > 0 || uname != NULL);
1265 
1266     node = pcmk__search_node_caches(id, uname, flags);
1267 
1268     if (node || !(flags & CRM_GET_PEER_CLUSTER)) {
1269         return node;
1270     }
1271 
1272     if (id > 0) {
1273         id_str = crm_strdup_printf("%u", id);
1274     }
1275 
1276     node = find_known_node(id_str, uname);
1277 
1278     free(id_str);
1279     return node;
1280 }
1281 
1282 
1283 
1284 
1285 
1286 #include <crm/cluster/compat.h>
1287 
1288 int
1289 crm_terminate_member(int nodeid, const char *uname, void *unused)
     
1290 {
1291     return stonith_api_kick(nodeid, uname, 120, TRUE);
1292 }
1293 
1294 int
1295 crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection)
     
1296 {
1297     return stonith_api_kick(nodeid, uname, 120, TRUE);
1298 }
1299 
1300 
1301