root/daemons/controld/controld_utils.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fsa_input2string
  2. fsa_state2string
  3. fsa_cause2string
  4. fsa_action2string
  5. fsa_dump_inputs
  6. fsa_dump_actions
  7. update_dc
  8. crmd_peer_down
  9. feature_set_compatible
  10. get_node_id

   1 /*
   2  * Copyright 2004-2023 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <stdlib.h>
  13 #include <stdint.h>                 // uint64_t
  14 
  15 #include <crm/crm.h>
  16 #include <crm/cib.h>
  17 #include <crm/msg_xml.h>
  18 #include <crm/common/xml.h>
  19 
  20 #include <pacemaker-controld.h>
  21 
  22 const char *
  23 fsa_input2string(enum crmd_fsa_input input)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25     const char *inputAsText = NULL;
  26 
  27     switch (input) {
  28         case I_NULL:
  29             inputAsText = "I_NULL";
  30             break;
  31         case I_CIB_OP:
  32             inputAsText = "I_CIB_OP (unused)";
  33             break;
  34         case I_CIB_UPDATE:
  35             inputAsText = "I_CIB_UPDATE";
  36             break;
  37         case I_DC_TIMEOUT:
  38             inputAsText = "I_DC_TIMEOUT";
  39             break;
  40         case I_ELECTION:
  41             inputAsText = "I_ELECTION";
  42             break;
  43         case I_PE_CALC:
  44             inputAsText = "I_PE_CALC";
  45             break;
  46         case I_RELEASE_DC:
  47             inputAsText = "I_RELEASE_DC";
  48             break;
  49         case I_ELECTION_DC:
  50             inputAsText = "I_ELECTION_DC";
  51             break;
  52         case I_ERROR:
  53             inputAsText = "I_ERROR";
  54             break;
  55         case I_FAIL:
  56             inputAsText = "I_FAIL";
  57             break;
  58         case I_INTEGRATED:
  59             inputAsText = "I_INTEGRATED";
  60             break;
  61         case I_FINALIZED:
  62             inputAsText = "I_FINALIZED";
  63             break;
  64         case I_NODE_JOIN:
  65             inputAsText = "I_NODE_JOIN";
  66             break;
  67         case I_JOIN_OFFER:
  68             inputAsText = "I_JOIN_OFFER";
  69             break;
  70         case I_JOIN_REQUEST:
  71             inputAsText = "I_JOIN_REQUEST";
  72             break;
  73         case I_JOIN_RESULT:
  74             inputAsText = "I_JOIN_RESULT";
  75             break;
  76         case I_NOT_DC:
  77             inputAsText = "I_NOT_DC";
  78             break;
  79         case I_RECOVERED:
  80             inputAsText = "I_RECOVERED";
  81             break;
  82         case I_RELEASE_FAIL:
  83             inputAsText = "I_RELEASE_FAIL";
  84             break;
  85         case I_RELEASE_SUCCESS:
  86             inputAsText = "I_RELEASE_SUCCESS";
  87             break;
  88         case I_RESTART:
  89             inputAsText = "I_RESTART";
  90             break;
  91         case I_PE_SUCCESS:
  92             inputAsText = "I_PE_SUCCESS";
  93             break;
  94         case I_ROUTER:
  95             inputAsText = "I_ROUTER";
  96             break;
  97         case I_SHUTDOWN:
  98             inputAsText = "I_SHUTDOWN";
  99             break;
 100         case I_STARTUP:
 101             inputAsText = "I_STARTUP";
 102             break;
 103         case I_TE_SUCCESS:
 104             inputAsText = "I_TE_SUCCESS";
 105             break;
 106         case I_STOP:
 107             inputAsText = "I_STOP";
 108             break;
 109         case I_DC_HEARTBEAT:
 110             inputAsText = "I_DC_HEARTBEAT";
 111             break;
 112         case I_WAIT_FOR_EVENT:
 113             inputAsText = "I_WAIT_FOR_EVENT";
 114             break;
 115         case I_LRM_EVENT:
 116             inputAsText = "I_LRM_EVENT";
 117             break;
 118         case I_PENDING:
 119             inputAsText = "I_PENDING";
 120             break;
 121         case I_HALT:
 122             inputAsText = "I_HALT";
 123             break;
 124         case I_TERMINATE:
 125             inputAsText = "I_TERMINATE";
 126             break;
 127         case I_ILLEGAL:
 128             inputAsText = "I_ILLEGAL";
 129             break;
 130     }
 131 
 132     if (inputAsText == NULL) {
 133         crm_err("Input %d is unknown", input);
 134         inputAsText = "<UNKNOWN_INPUT>";
 135     }
 136 
 137     return inputAsText;
 138 }
 139 
 140 const char *
 141 fsa_state2string(enum crmd_fsa_state state)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143     const char *stateAsText = NULL;
 144 
 145     switch (state) {
 146         case S_IDLE:
 147             stateAsText = "S_IDLE";
 148             break;
 149         case S_ELECTION:
 150             stateAsText = "S_ELECTION";
 151             break;
 152         case S_INTEGRATION:
 153             stateAsText = "S_INTEGRATION";
 154             break;
 155         case S_FINALIZE_JOIN:
 156             stateAsText = "S_FINALIZE_JOIN";
 157             break;
 158         case S_NOT_DC:
 159             stateAsText = "S_NOT_DC";
 160             break;
 161         case S_POLICY_ENGINE:
 162             stateAsText = "S_POLICY_ENGINE";
 163             break;
 164         case S_RECOVERY:
 165             stateAsText = "S_RECOVERY";
 166             break;
 167         case S_RELEASE_DC:
 168             stateAsText = "S_RELEASE_DC";
 169             break;
 170         case S_PENDING:
 171             stateAsText = "S_PENDING";
 172             break;
 173         case S_STOPPING:
 174             stateAsText = "S_STOPPING";
 175             break;
 176         case S_TERMINATE:
 177             stateAsText = "S_TERMINATE";
 178             break;
 179         case S_TRANSITION_ENGINE:
 180             stateAsText = "S_TRANSITION_ENGINE";
 181             break;
 182         case S_STARTING:
 183             stateAsText = "S_STARTING";
 184             break;
 185         case S_HALT:
 186             stateAsText = "S_HALT";
 187             break;
 188         case S_ILLEGAL:
 189             stateAsText = "S_ILLEGAL";
 190             break;
 191     }
 192 
 193     if (stateAsText == NULL) {
 194         crm_err("State %d is unknown", state);
 195         stateAsText = "<UNKNOWN_STATE>";
 196     }
 197 
 198     return stateAsText;
 199 }
 200 
 201 const char *
 202 fsa_cause2string(enum crmd_fsa_cause cause)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204     const char *causeAsText = NULL;
 205 
 206     switch (cause) {
 207         case C_UNKNOWN:
 208             causeAsText = "C_UNKNOWN";
 209             break;
 210         case C_STARTUP:
 211             causeAsText = "C_STARTUP";
 212             break;
 213         case C_IPC_MESSAGE:
 214             causeAsText = "C_IPC_MESSAGE";
 215             break;
 216         case C_HA_MESSAGE:
 217             causeAsText = "C_HA_MESSAGE";
 218             break;
 219         case C_TIMER_POPPED:
 220             causeAsText = "C_TIMER_POPPED";
 221             break;
 222         case C_SHUTDOWN:
 223             causeAsText = "C_SHUTDOWN";
 224             break;
 225         case C_LRM_OP_CALLBACK:
 226             causeAsText = "C_LRM_OP_CALLBACK";
 227             break;
 228         case C_CRMD_STATUS_CALLBACK:
 229             causeAsText = "C_CRMD_STATUS_CALLBACK";
 230             break;
 231         case C_FSA_INTERNAL:
 232             causeAsText = "C_FSA_INTERNAL";
 233             break;
 234     }
 235 
 236     if (causeAsText == NULL) {
 237         crm_err("Cause %d is unknown", cause);
 238         causeAsText = "<UNKNOWN_CAUSE>";
 239     }
 240 
 241     return causeAsText;
 242 }
 243 
 244 const char *
 245 fsa_action2string(long long action)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247     const char *actionAsText = NULL;
 248 
 249     switch (action) {
 250 
 251         case A_NOTHING:
 252             actionAsText = "A_NOTHING";
 253             break;
 254         case A_ELECTION_START:
 255             actionAsText = "A_ELECTION_START";
 256             break;
 257         case A_DC_JOIN_FINAL:
 258             actionAsText = "A_DC_JOIN_FINAL";
 259             break;
 260         case A_READCONFIG:
 261             actionAsText = "A_READCONFIG";
 262             break;
 263         case O_RELEASE:
 264             actionAsText = "O_RELEASE";
 265             break;
 266         case A_STARTUP:
 267             actionAsText = "A_STARTUP";
 268             break;
 269         case A_STARTED:
 270             actionAsText = "A_STARTED";
 271             break;
 272         case A_HA_CONNECT:
 273             actionAsText = "A_HA_CONNECT";
 274             break;
 275         case A_HA_DISCONNECT:
 276             actionAsText = "A_HA_DISCONNECT";
 277             break;
 278         case A_LRM_CONNECT:
 279             actionAsText = "A_LRM_CONNECT";
 280             break;
 281         case A_LRM_EVENT:
 282             actionAsText = "A_LRM_EVENT";
 283             break;
 284         case A_LRM_INVOKE:
 285             actionAsText = "A_LRM_INVOKE";
 286             break;
 287         case A_LRM_DISCONNECT:
 288             actionAsText = "A_LRM_DISCONNECT";
 289             break;
 290         case O_LRM_RECONNECT:
 291             actionAsText = "O_LRM_RECONNECT";
 292             break;
 293         case A_CL_JOIN_QUERY:
 294             actionAsText = "A_CL_JOIN_QUERY";
 295             break;
 296         case A_DC_TIMER_STOP:
 297             actionAsText = "A_DC_TIMER_STOP";
 298             break;
 299         case A_DC_TIMER_START:
 300             actionAsText = "A_DC_TIMER_START";
 301             break;
 302         case A_INTEGRATE_TIMER_START:
 303             actionAsText = "A_INTEGRATE_TIMER_START";
 304             break;
 305         case A_INTEGRATE_TIMER_STOP:
 306             actionAsText = "A_INTEGRATE_TIMER_STOP";
 307             break;
 308         case A_FINALIZE_TIMER_START:
 309             actionAsText = "A_FINALIZE_TIMER_START";
 310             break;
 311         case A_FINALIZE_TIMER_STOP:
 312             actionAsText = "A_FINALIZE_TIMER_STOP";
 313             break;
 314         case A_ELECTION_COUNT:
 315             actionAsText = "A_ELECTION_COUNT";
 316             break;
 317         case A_ELECTION_VOTE:
 318             actionAsText = "A_ELECTION_VOTE";
 319             break;
 320         case A_ELECTION_CHECK:
 321             actionAsText = "A_ELECTION_CHECK";
 322             break;
 323         case A_CL_JOIN_ANNOUNCE:
 324             actionAsText = "A_CL_JOIN_ANNOUNCE";
 325             break;
 326         case A_CL_JOIN_REQUEST:
 327             actionAsText = "A_CL_JOIN_REQUEST";
 328             break;
 329         case A_CL_JOIN_RESULT:
 330             actionAsText = "A_CL_JOIN_RESULT";
 331             break;
 332         case A_DC_JOIN_OFFER_ALL:
 333             actionAsText = "A_DC_JOIN_OFFER_ALL";
 334             break;
 335         case A_DC_JOIN_OFFER_ONE:
 336             actionAsText = "A_DC_JOIN_OFFER_ONE";
 337             break;
 338         case A_DC_JOIN_PROCESS_REQ:
 339             actionAsText = "A_DC_JOIN_PROCESS_REQ";
 340             break;
 341         case A_DC_JOIN_PROCESS_ACK:
 342             actionAsText = "A_DC_JOIN_PROCESS_ACK";
 343             break;
 344         case A_DC_JOIN_FINALIZE:
 345             actionAsText = "A_DC_JOIN_FINALIZE";
 346             break;
 347         case A_MSG_PROCESS:
 348             actionAsText = "A_MSG_PROCESS";
 349             break;
 350         case A_MSG_ROUTE:
 351             actionAsText = "A_MSG_ROUTE";
 352             break;
 353         case A_RECOVER:
 354             actionAsText = "A_RECOVER";
 355             break;
 356         case A_DC_RELEASE:
 357             actionAsText = "A_DC_RELEASE";
 358             break;
 359         case A_DC_RELEASED:
 360             actionAsText = "A_DC_RELEASED";
 361             break;
 362         case A_DC_TAKEOVER:
 363             actionAsText = "A_DC_TAKEOVER";
 364             break;
 365         case A_SHUTDOWN:
 366             actionAsText = "A_SHUTDOWN";
 367             break;
 368         case A_SHUTDOWN_REQ:
 369             actionAsText = "A_SHUTDOWN_REQ";
 370             break;
 371         case A_STOP:
 372             actionAsText = "A_STOP  ";
 373             break;
 374         case A_EXIT_0:
 375             actionAsText = "A_EXIT_0";
 376             break;
 377         case A_EXIT_1:
 378             actionAsText = "A_EXIT_1";
 379             break;
 380         case O_CIB_RESTART:
 381             actionAsText = "O_CIB_RESTART";
 382             break;
 383         case A_CIB_START:
 384             actionAsText = "A_CIB_START";
 385             break;
 386         case A_CIB_STOP:
 387             actionAsText = "A_CIB_STOP";
 388             break;
 389         case A_TE_INVOKE:
 390             actionAsText = "A_TE_INVOKE";
 391             break;
 392         case O_TE_RESTART:
 393             actionAsText = "O_TE_RESTART";
 394             break;
 395         case A_TE_START:
 396             actionAsText = "A_TE_START";
 397             break;
 398         case A_TE_STOP:
 399             actionAsText = "A_TE_STOP";
 400             break;
 401         case A_TE_HALT:
 402             actionAsText = "A_TE_HALT";
 403             break;
 404         case A_TE_CANCEL:
 405             actionAsText = "A_TE_CANCEL";
 406             break;
 407         case A_PE_INVOKE:
 408             actionAsText = "A_PE_INVOKE";
 409             break;
 410         case O_PE_RESTART:
 411             actionAsText = "O_PE_RESTART";
 412             break;
 413         case A_PE_START:
 414             actionAsText = "A_PE_START";
 415             break;
 416         case A_PE_STOP:
 417             actionAsText = "A_PE_STOP";
 418             break;
 419         case A_NODE_BLOCK:
 420             actionAsText = "A_NODE_BLOCK";
 421             break;
 422         case A_UPDATE_NODESTATUS:
 423             actionAsText = "A_UPDATE_NODESTATUS";
 424             break;
 425         case A_LOG:
 426             actionAsText = "A_LOG   ";
 427             break;
 428         case A_ERROR:
 429             actionAsText = "A_ERROR ";
 430             break;
 431         case A_WARN:
 432             actionAsText = "A_WARN  ";
 433             break;
 434             /* Composite actions */
 435         case A_DC_TIMER_START | A_CL_JOIN_QUERY:
 436             actionAsText = "A_DC_TIMER_START|A_CL_JOIN_QUERY";
 437             break;
 438     }
 439 
 440     if (actionAsText == NULL) {
 441         crm_err("Action %.16llx is unknown", action);
 442         actionAsText = "<UNKNOWN_ACTION>";
 443     }
 444 
 445     return actionAsText;
 446 }
 447 
 448 void
 449 fsa_dump_inputs(int log_level, const char *text, long long input_register)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451     if (input_register == A_NOTHING) {
 452         return;
 453     }
 454     if (text == NULL) {
 455         text = "Input register contents:";
 456     }
 457 
 458     if (pcmk_is_set(input_register, R_THE_DC)) {
 459         crm_trace("%s %.16llx (R_THE_DC)", text, R_THE_DC);
 460     }
 461     if (pcmk_is_set(input_register, R_STARTING)) {
 462         crm_trace("%s %.16llx (R_STARTING)", text, R_STARTING);
 463     }
 464     if (pcmk_is_set(input_register, R_SHUTDOWN)) {
 465         crm_trace("%s %.16llx (R_SHUTDOWN)", text, R_SHUTDOWN);
 466     }
 467     if (pcmk_is_set(input_register, R_STAYDOWN)) {
 468         crm_trace("%s %.16llx (R_STAYDOWN)", text, R_STAYDOWN);
 469     }
 470     if (pcmk_is_set(input_register, R_JOIN_OK)) {
 471         crm_trace("%s %.16llx (R_JOIN_OK)", text, R_JOIN_OK);
 472     }
 473     if (pcmk_is_set(input_register, R_READ_CONFIG)) {
 474         crm_trace("%s %.16llx (R_READ_CONFIG)", text, R_READ_CONFIG);
 475     }
 476     if (pcmk_is_set(input_register, R_INVOKE_PE)) {
 477         crm_trace("%s %.16llx (R_INVOKE_PE)", text, R_INVOKE_PE);
 478     }
 479     if (pcmk_is_set(input_register, R_CIB_CONNECTED)) {
 480         crm_trace("%s %.16llx (R_CIB_CONNECTED)", text, R_CIB_CONNECTED);
 481     }
 482     if (pcmk_is_set(input_register, R_PE_CONNECTED)) {
 483         crm_trace("%s %.16llx (R_PE_CONNECTED)", text, R_PE_CONNECTED);
 484     }
 485     if (pcmk_is_set(input_register, R_TE_CONNECTED)) {
 486         crm_trace("%s %.16llx (R_TE_CONNECTED)", text, R_TE_CONNECTED);
 487     }
 488     if (pcmk_is_set(input_register, R_LRM_CONNECTED)) {
 489         crm_trace("%s %.16llx (R_LRM_CONNECTED)", text, R_LRM_CONNECTED);
 490     }
 491     if (pcmk_is_set(input_register, R_CIB_REQUIRED)) {
 492         crm_trace("%s %.16llx (R_CIB_REQUIRED)", text, R_CIB_REQUIRED);
 493     }
 494     if (pcmk_is_set(input_register, R_PE_REQUIRED)) {
 495         crm_trace("%s %.16llx (R_PE_REQUIRED)", text, R_PE_REQUIRED);
 496     }
 497     if (pcmk_is_set(input_register, R_TE_REQUIRED)) {
 498         crm_trace("%s %.16llx (R_TE_REQUIRED)", text, R_TE_REQUIRED);
 499     }
 500     if (pcmk_is_set(input_register, R_REQ_PEND)) {
 501         crm_trace("%s %.16llx (R_REQ_PEND)", text, R_REQ_PEND);
 502     }
 503     if (pcmk_is_set(input_register, R_PE_PEND)) {
 504         crm_trace("%s %.16llx (R_PE_PEND)", text, R_PE_PEND);
 505     }
 506     if (pcmk_is_set(input_register, R_TE_PEND)) {
 507         crm_trace("%s %.16llx (R_TE_PEND)", text, R_TE_PEND);
 508     }
 509     if (pcmk_is_set(input_register, R_RESP_PEND)) {
 510         crm_trace("%s %.16llx (R_RESP_PEND)", text, R_RESP_PEND);
 511     }
 512     if (pcmk_is_set(input_register, R_CIB_DONE)) {
 513         crm_trace("%s %.16llx (R_CIB_DONE)", text, R_CIB_DONE);
 514     }
 515     if (pcmk_is_set(input_register, R_HAVE_CIB)) {
 516         crm_trace("%s %.16llx (R_HAVE_CIB)", text, R_HAVE_CIB);
 517     }
 518     if (pcmk_is_set(input_register, R_MEMBERSHIP)) {
 519         crm_trace("%s %.16llx (R_MEMBERSHIP)", text, R_MEMBERSHIP);
 520     }
 521     if (pcmk_is_set(input_register, R_PEER_DATA)) {
 522         crm_trace("%s %.16llx (R_PEER_DATA)", text, R_PEER_DATA);
 523     }
 524     if (pcmk_is_set(input_register, R_IN_RECOVERY)) {
 525         crm_trace("%s %.16llx (R_IN_RECOVERY)", text, R_IN_RECOVERY);
 526     }
 527 }
 528 
 529 void
 530 fsa_dump_actions(uint64_t action, const char *text)
     /* [previous][next][first][last][top][bottom][index][help] */
 531 {
 532     if (pcmk_is_set(action, A_READCONFIG)) {
 533         crm_trace("Action %.16llx (A_READCONFIG) %s", A_READCONFIG, text);
 534     }
 535     if (pcmk_is_set(action, A_STARTUP)) {
 536         crm_trace("Action %.16llx (A_STARTUP) %s", A_STARTUP, text);
 537     }
 538     if (pcmk_is_set(action, A_STARTED)) {
 539         crm_trace("Action %.16llx (A_STARTED) %s", A_STARTED, text);
 540     }
 541     if (pcmk_is_set(action, A_HA_CONNECT)) {
 542         crm_trace("Action %.16llx (A_CONNECT) %s", A_HA_CONNECT, text);
 543     }
 544     if (pcmk_is_set(action, A_HA_DISCONNECT)) {
 545         crm_trace("Action %.16llx (A_DISCONNECT) %s", A_HA_DISCONNECT, text);
 546     }
 547     if (pcmk_is_set(action, A_LRM_CONNECT)) {
 548         crm_trace("Action %.16llx (A_LRM_CONNECT) %s", A_LRM_CONNECT, text);
 549     }
 550     if (pcmk_is_set(action, A_LRM_EVENT)) {
 551         crm_trace("Action %.16llx (A_LRM_EVENT) %s", A_LRM_EVENT, text);
 552     }
 553     if (pcmk_is_set(action, A_LRM_INVOKE)) {
 554         crm_trace("Action %.16llx (A_LRM_INVOKE) %s", A_LRM_INVOKE, text);
 555     }
 556     if (pcmk_is_set(action, A_LRM_DISCONNECT)) {
 557         crm_trace("Action %.16llx (A_LRM_DISCONNECT) %s", A_LRM_DISCONNECT, text);
 558     }
 559     if (pcmk_is_set(action, A_DC_TIMER_STOP)) {
 560         crm_trace("Action %.16llx (A_DC_TIMER_STOP) %s", A_DC_TIMER_STOP, text);
 561     }
 562     if (pcmk_is_set(action, A_DC_TIMER_START)) {
 563         crm_trace("Action %.16llx (A_DC_TIMER_START) %s", A_DC_TIMER_START, text);
 564     }
 565     if (pcmk_is_set(action, A_INTEGRATE_TIMER_START)) {
 566         crm_trace("Action %.16llx (A_INTEGRATE_TIMER_START) %s", A_INTEGRATE_TIMER_START, text);
 567     }
 568     if (pcmk_is_set(action, A_INTEGRATE_TIMER_STOP)) {
 569         crm_trace("Action %.16llx (A_INTEGRATE_TIMER_STOP) %s", A_INTEGRATE_TIMER_STOP, text);
 570     }
 571     if (pcmk_is_set(action, A_FINALIZE_TIMER_START)) {
 572         crm_trace("Action %.16llx (A_FINALIZE_TIMER_START) %s", A_FINALIZE_TIMER_START, text);
 573     }
 574     if (pcmk_is_set(action, A_FINALIZE_TIMER_STOP)) {
 575         crm_trace("Action %.16llx (A_FINALIZE_TIMER_STOP) %s", A_FINALIZE_TIMER_STOP, text);
 576     }
 577     if (pcmk_is_set(action, A_ELECTION_COUNT)) {
 578         crm_trace("Action %.16llx (A_ELECTION_COUNT) %s", A_ELECTION_COUNT, text);
 579     }
 580     if (pcmk_is_set(action, A_ELECTION_VOTE)) {
 581         crm_trace("Action %.16llx (A_ELECTION_VOTE) %s", A_ELECTION_VOTE, text);
 582     }
 583     if (pcmk_is_set(action, A_ELECTION_CHECK)) {
 584         crm_trace("Action %.16llx (A_ELECTION_CHECK) %s", A_ELECTION_CHECK, text);
 585     }
 586     if (pcmk_is_set(action, A_CL_JOIN_ANNOUNCE)) {
 587         crm_trace("Action %.16llx (A_CL_JOIN_ANNOUNCE) %s", A_CL_JOIN_ANNOUNCE, text);
 588     }
 589     if (pcmk_is_set(action, A_CL_JOIN_REQUEST)) {
 590         crm_trace("Action %.16llx (A_CL_JOIN_REQUEST) %s", A_CL_JOIN_REQUEST, text);
 591     }
 592     if (pcmk_is_set(action, A_CL_JOIN_RESULT)) {
 593         crm_trace("Action %.16llx (A_CL_JOIN_RESULT) %s", A_CL_JOIN_RESULT, text);
 594     }
 595     if (pcmk_is_set(action, A_DC_JOIN_OFFER_ALL)) {
 596         crm_trace("Action %.16llx (A_DC_JOIN_OFFER_ALL) %s", A_DC_JOIN_OFFER_ALL, text);
 597     }
 598     if (pcmk_is_set(action, A_DC_JOIN_OFFER_ONE)) {
 599         crm_trace("Action %.16llx (A_DC_JOIN_OFFER_ONE) %s", A_DC_JOIN_OFFER_ONE, text);
 600     }
 601     if (pcmk_is_set(action, A_DC_JOIN_PROCESS_REQ)) {
 602         crm_trace("Action %.16llx (A_DC_JOIN_PROCESS_REQ) %s", A_DC_JOIN_PROCESS_REQ, text);
 603     }
 604     if (pcmk_is_set(action, A_DC_JOIN_PROCESS_ACK)) {
 605         crm_trace("Action %.16llx (A_DC_JOIN_PROCESS_ACK) %s", A_DC_JOIN_PROCESS_ACK, text);
 606     }
 607     if (pcmk_is_set(action, A_DC_JOIN_FINALIZE)) {
 608         crm_trace("Action %.16llx (A_DC_JOIN_FINALIZE) %s", A_DC_JOIN_FINALIZE, text);
 609     }
 610     if (pcmk_is_set(action, A_MSG_PROCESS)) {
 611         crm_trace("Action %.16llx (A_MSG_PROCESS) %s", A_MSG_PROCESS, text);
 612     }
 613     if (pcmk_is_set(action, A_MSG_ROUTE)) {
 614         crm_trace("Action %.16llx (A_MSG_ROUTE) %s", A_MSG_ROUTE, text);
 615     }
 616     if (pcmk_is_set(action, A_RECOVER)) {
 617         crm_trace("Action %.16llx (A_RECOVER) %s", A_RECOVER, text);
 618     }
 619     if (pcmk_is_set(action, A_DC_RELEASE)) {
 620         crm_trace("Action %.16llx (A_DC_RELEASE) %s", A_DC_RELEASE, text);
 621     }
 622     if (pcmk_is_set(action, A_DC_RELEASED)) {
 623         crm_trace("Action %.16llx (A_DC_RELEASED) %s", A_DC_RELEASED, text);
 624     }
 625     if (pcmk_is_set(action, A_DC_TAKEOVER)) {
 626         crm_trace("Action %.16llx (A_DC_TAKEOVER) %s", A_DC_TAKEOVER, text);
 627     }
 628     if (pcmk_is_set(action, A_SHUTDOWN)) {
 629         crm_trace("Action %.16llx (A_SHUTDOWN) %s", A_SHUTDOWN, text);
 630     }
 631     if (pcmk_is_set(action, A_SHUTDOWN_REQ)) {
 632         crm_trace("Action %.16llx (A_SHUTDOWN_REQ) %s", A_SHUTDOWN_REQ, text);
 633     }
 634     if (pcmk_is_set(action, A_STOP)) {
 635         crm_trace("Action %.16llx (A_STOP  ) %s", A_STOP, text);
 636     }
 637     if (pcmk_is_set(action, A_EXIT_0)) {
 638         crm_trace("Action %.16llx (A_EXIT_0) %s", A_EXIT_0, text);
 639     }
 640     if (pcmk_is_set(action, A_EXIT_1)) {
 641         crm_trace("Action %.16llx (A_EXIT_1) %s", A_EXIT_1, text);
 642     }
 643     if (pcmk_is_set(action, A_CIB_START)) {
 644         crm_trace("Action %.16llx (A_CIB_START) %s", A_CIB_START, text);
 645     }
 646     if (pcmk_is_set(action, A_CIB_STOP)) {
 647         crm_trace("Action %.16llx (A_CIB_STOP) %s", A_CIB_STOP, text);
 648     }
 649     if (pcmk_is_set(action, A_TE_INVOKE)) {
 650         crm_trace("Action %.16llx (A_TE_INVOKE) %s", A_TE_INVOKE, text);
 651     }
 652     if (pcmk_is_set(action, A_TE_START)) {
 653         crm_trace("Action %.16llx (A_TE_START) %s", A_TE_START, text);
 654     }
 655     if (pcmk_is_set(action, A_TE_STOP)) {
 656         crm_trace("Action %.16llx (A_TE_STOP) %s", A_TE_STOP, text);
 657     }
 658     if (pcmk_is_set(action, A_TE_CANCEL)) {
 659         crm_trace("Action %.16llx (A_TE_CANCEL) %s", A_TE_CANCEL, text);
 660     }
 661     if (pcmk_is_set(action, A_PE_INVOKE)) {
 662         crm_trace("Action %.16llx (A_PE_INVOKE) %s", A_PE_INVOKE, text);
 663     }
 664     if (pcmk_is_set(action, A_PE_START)) {
 665         crm_trace("Action %.16llx (A_PE_START) %s", A_PE_START, text);
 666     }
 667     if (pcmk_is_set(action, A_PE_STOP)) {
 668         crm_trace("Action %.16llx (A_PE_STOP) %s", A_PE_STOP, text);
 669     }
 670     if (pcmk_is_set(action, A_NODE_BLOCK)) {
 671         crm_trace("Action %.16llx (A_NODE_BLOCK) %s", A_NODE_BLOCK, text);
 672     }
 673     if (pcmk_is_set(action, A_UPDATE_NODESTATUS)) {
 674         crm_trace("Action %.16llx (A_UPDATE_NODESTATUS) %s", A_UPDATE_NODESTATUS, text);
 675     }
 676     if (pcmk_is_set(action, A_LOG)) {
 677         crm_trace("Action %.16llx (A_LOG   ) %s", A_LOG, text);
 678     }
 679     if (pcmk_is_set(action, A_ERROR)) {
 680         crm_trace("Action %.16llx (A_ERROR ) %s", A_ERROR, text);
 681     }
 682     if (pcmk_is_set(action, A_WARN)) {
 683         crm_trace("Action %.16llx (A_WARN  ) %s", A_WARN, text);
 684     }
 685 }
 686 
 687 gboolean
 688 update_dc(xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 689 {
 690     char *last_dc = controld_globals.dc_name;
 691     const char *dc_version = NULL;
 692     const char *welcome_from = NULL;
 693 
 694     if (msg != NULL) {
 695         gboolean invalid = FALSE;
 696 
 697         dc_version = crm_element_value(msg, F_CRM_VERSION);
 698         welcome_from = crm_element_value(msg, F_CRM_HOST_FROM);
 699 
 700         CRM_CHECK(dc_version != NULL, return FALSE);
 701         CRM_CHECK(welcome_from != NULL, return FALSE);
 702 
 703         if (AM_I_DC
 704             && !pcmk__str_eq(welcome_from, controld_globals.our_nodename,
 705                              pcmk__str_casei)) {
 706             invalid = TRUE;
 707 
 708         } else if ((controld_globals.dc_name != NULL)
 709                    && !pcmk__str_eq(welcome_from, controld_globals.dc_name,
 710                                     pcmk__str_casei)) {
 711             invalid = TRUE;
 712         }
 713 
 714         if (invalid) {
 715             if (AM_I_DC) {
 716                 crm_err("Not updating DC to %s (%s): we are also a DC",
 717                         welcome_from, dc_version);
 718             } else {
 719                 crm_warn("New DC %s is not %s",
 720                          welcome_from, controld_globals.dc_name);
 721             }
 722 
 723             controld_set_fsa_action_flags(A_CL_JOIN_QUERY | A_DC_TIMER_START);
 724             controld_trigger_fsa();
 725             return FALSE;
 726         }
 727     }
 728 
 729     controld_globals.dc_name = NULL;    // freed as last_dc
 730     pcmk__str_update(&(controld_globals.dc_name), welcome_from);
 731     pcmk__str_update(&(controld_globals.dc_version), dc_version);
 732 
 733     if (pcmk__str_eq(controld_globals.dc_name, last_dc, pcmk__str_casei)) {
 734         /* do nothing */
 735 
 736     } else if (controld_globals.dc_name != NULL) {
 737         crm_node_t *dc_node = crm_get_peer(0, controld_globals.dc_name);
 738 
 739         crm_info("Set DC to %s (%s)",
 740                  controld_globals.dc_name,
 741                  pcmk__s(controld_globals.dc_version, "unknown version"));
 742         pcmk__update_peer_expected(__func__, dc_node, CRMD_JOINSTATE_MEMBER);
 743 
 744     } else if (last_dc != NULL) {
 745         crm_info("Unset DC (was %s)", last_dc);
 746     }
 747 
 748     free(last_dc);
 749     return TRUE;
 750 }
 751 
 752 void crmd_peer_down(crm_node_t *peer, bool full) 
     /* [previous][next][first][last][top][bottom][index][help] */
 753 {
 754     if(full && peer->state == NULL) {
 755         pcmk__update_peer_state(__func__, peer, CRM_NODE_LOST, 0);
 756         crm_update_peer_proc(__func__, peer, crm_proc_none, NULL);
 757     }
 758     crm_update_peer_join(__func__, peer, crm_join_none);
 759     pcmk__update_peer_expected(__func__, peer, CRMD_JOINSTATE_DOWN);
 760 }
 761 
 762 /*!
 763  * \internal
 764  * \brief Check feature set compatibility of DC and joining node
 765  *
 766  * Return true if a joining node's CRM feature set is compatible with the
 767  * current DC's. The feature sets are compatible if they have the same major
 768  * version number, and the DC's minor version number is the same or older than
 769  * the joining node's. The minor-minor version is intended solely to allow
 770  * resource agents to detect feature support, and so is ignored.
 771  *
 772  * \param[in] dc_version    DC's feature set
 773  * \param[in] join_version  Joining node's version
 774  */
 775 bool
 776 feature_set_compatible(const char *dc_version, const char *join_version)
     /* [previous][next][first][last][top][bottom][index][help] */
 777 {
 778     char *dc_minor = NULL;
 779     char *join_minor = NULL;
 780     long dc_v = 0;
 781     long join_v = 0;
 782 
 783     // Get DC's major version
 784     errno = 0;
 785     dc_v = strtol(dc_version, &dc_minor, 10);
 786     if (errno) {
 787         return FALSE;
 788     }
 789 
 790     // Get joining node's major version
 791     errno = 0;
 792     join_v = strtol(join_version, &join_minor, 10);
 793     if (errno) {
 794         return FALSE;
 795     }
 796 
 797     // Major version component must be identical
 798     if (dc_v != join_v) {
 799         return FALSE;
 800     }
 801 
 802     // Get DC's minor version
 803     if (*dc_minor == '.') {
 804         ++dc_minor;
 805     }
 806     errno = 0;
 807     dc_v = strtol(dc_minor, NULL, 10);
 808     if (errno) {
 809         return FALSE;
 810     }
 811 
 812     // Get joining node's minor version
 813     if (*join_minor == '.') {
 814         ++join_minor;
 815     }
 816     errno = 0;
 817     join_v = strtol(join_minor, NULL, 10);
 818     if (errno) {
 819         return FALSE;
 820     }
 821 
 822     // DC's minor version must be the same or older
 823     return dc_v <= join_v;
 824 }
 825 
 826 const char *
 827 get_node_id(xmlNode *lrm_rsc_op)
     /* [previous][next][first][last][top][bottom][index][help] */
 828 {
 829     xmlNode *node = lrm_rsc_op;
 830 
 831     while (node != NULL && !pcmk__str_eq(XML_CIB_TAG_STATE, TYPE(node), pcmk__str_casei)) {
 832         node = node->parent;
 833     }
 834 
 835     CRM_CHECK(node != NULL, return NULL);
 836     return ID(node);
 837 }

/* [previous][next][first][last][top][bottom][index][help] */