root/daemons/controld/controld_utils.c

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

DEFINITIONS

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

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

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