root/daemons/controld/controld_fsa.c

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

DEFINITIONS

This source file includes following definitions.
  1. do_fsa_action
  2. do_log
  3. controld_init_fsa_trigger
  4. controld_destroy_fsa_trigger
  5. controld_trigger_fsa_as
  6. s_crmd_fsa
  7. s_crmd_fsa_actions
  8. log_fsa_input
  9. check_join_counts
  10. do_state_transition

   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 <inttypes.h>               // PRIx64
  13 #include <sys/param.h>
  14 #include <stdio.h>
  15 #include <stdint.h>                 // uint64_t
  16 #include <string.h>
  17 #include <time.h>
  18 
  19 #include <crm/crm.h>
  20 #include <crm/lrmd.h>
  21 #include <crm/cib.h>
  22 #include <crm/common/xml.h>
  23 #include <crm/cluster/election_internal.h>
  24 #include <crm/cluster.h>
  25 
  26 #include <pacemaker-controld.h>
  27 
  28 //! Triggers an FSA invocation
  29 static crm_trigger_t *fsa_trigger = NULL;
  30 
  31 static void do_state_transition(enum crmd_fsa_state cur_state,
  32                                 enum crmd_fsa_state next_state,
  33                                 fsa_data_t *msg_data);
  34 
  35 void s_crmd_fsa_actions(fsa_data_t * fsa_data);
  36 void log_fsa_input(fsa_data_t * stored_msg);
  37 
  38 static void
  39 do_fsa_action(fsa_data_t * fsa_data, long long an_action,
     /* [previous][next][first][last][top][bottom][index][help] */
  40               void (*function) (long long action,
  41                                 enum crmd_fsa_cause cause,
  42                                 enum crmd_fsa_state cur_state,
  43                                 enum crmd_fsa_input cur_input, fsa_data_t * msg_data))
  44 {
  45     controld_clear_fsa_action_flags(an_action);
  46     function(an_action, fsa_data->fsa_cause, controld_globals.fsa_state,
  47              fsa_data->fsa_input, fsa_data);
  48 }
  49 
  50 static const uint64_t startup_actions =
  51     A_STARTUP | A_CIB_START | A_LRM_CONNECT | A_HA_CONNECT | A_READCONFIG |
  52     A_STARTED | A_CL_JOIN_QUERY;
  53 
  54 // A_LOG, A_WARN, A_ERROR
  55 void
  56 do_log(long long action, enum crmd_fsa_cause cause,
     /* [previous][next][first][last][top][bottom][index][help] */
  57        enum crmd_fsa_state cur_state,
  58        enum crmd_fsa_input current_input, fsa_data_t *msg_data)
  59 {
  60     unsigned log_type = LOG_TRACE;
  61 
  62     if (action & A_LOG) {
  63         log_type = LOG_INFO;
  64     } else if (action & A_WARN) {
  65         log_type = LOG_WARNING;
  66     } else if (action & A_ERROR) {
  67         log_type = LOG_ERR;
  68     }
  69 
  70     do_crm_log(log_type, "Input %s received in state %s from %s",
  71                fsa_input2string(msg_data->fsa_input),
  72                fsa_state2string(cur_state), msg_data->origin);
  73 
  74     if (msg_data->data_type == fsa_dt_ha_msg) {
  75         ha_msg_input_t *input = fsa_typed_data(msg_data->data_type);
  76 
  77         crm_log_xml_debug(input->msg, __func__);
  78 
  79     } else if (msg_data->data_type == fsa_dt_xml) {
  80         xmlNode *input = fsa_typed_data(msg_data->data_type);
  81 
  82         crm_log_xml_debug(input, __func__);
  83 
  84     } else if (msg_data->data_type == fsa_dt_lrm) {
  85         lrmd_event_data_t *input = fsa_typed_data(msg_data->data_type);
  86 
  87         do_crm_log(log_type,
  88                    "Resource %s: Call ID %d returned %d (%d)."
  89                    "  New status if rc=0: %s",
  90                    input->rsc_id, input->call_id, input->rc,
  91                    input->op_status, (char *)input->user_data);
  92     }
  93 }
  94 
  95 /*!
  96  * \internal
  97  * \brief Initialize the FSA trigger
  98  */
  99 void
 100 controld_init_fsa_trigger(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102     fsa_trigger = mainloop_add_trigger(G_PRIORITY_HIGH, crm_fsa_trigger, NULL);
 103 }
 104 
 105 /*!
 106  * \internal
 107  * \brief Destroy the FSA trigger
 108  */
 109 void
 110 controld_destroy_fsa_trigger(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112     // This basically will not work, since mainloop has a reference to it
 113     mainloop_destroy_trigger(fsa_trigger);
 114     fsa_trigger = NULL;
 115 }
 116 
 117 /*!
 118  * \internal
 119  * \brief Trigger an FSA invocation
 120  *
 121  * \param[in] fn    Calling function name
 122  * \param[in] line  Line number where call occurred
 123  */
 124 void
 125 controld_trigger_fsa_as(const char *fn, int line)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127     if (fsa_trigger != NULL) {
 128         crm_trace("%s:%d - Triggered FSA invocation", fn, line);
 129         mainloop_set_trigger(fsa_trigger);
 130     }
 131 }
 132 
 133 enum crmd_fsa_state
 134 s_crmd_fsa(enum crmd_fsa_cause cause)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136     controld_globals_t *globals = &controld_globals;
 137     fsa_data_t *fsa_data = NULL;
 138     uint64_t register_copy = controld_globals.fsa_input_register;
 139     uint64_t new_actions = A_NOTHING;
 140     enum crmd_fsa_state last_state;
 141 
 142     crm_trace("FSA invoked with Cause: %s\tState: %s",
 143               fsa_cause2string(cause),
 144               fsa_state2string(globals->fsa_state));
 145 
 146     fsa_dump_actions(controld_globals.fsa_actions, "Initial");
 147 
 148     controld_clear_global_flags(controld_fsa_is_stalled);
 149     if ((controld_globals.fsa_message_queue == NULL)
 150         && (controld_globals.fsa_actions != A_NOTHING)) {
 151         /* fake the first message so we can get into the loop */
 152         fsa_data = pcmk__assert_alloc(1, sizeof(fsa_data_t));
 153         fsa_data->fsa_input = I_NULL;
 154         fsa_data->fsa_cause = C_FSA_INTERNAL;
 155         fsa_data->origin = __func__;
 156         fsa_data->data_type = fsa_dt_none;
 157         controld_globals.fsa_message_queue
 158             = g_list_append(controld_globals.fsa_message_queue, fsa_data);
 159     }
 160     while ((controld_globals.fsa_message_queue != NULL)
 161            && !pcmk_is_set(controld_globals.flags, controld_fsa_is_stalled)) {
 162         crm_trace("Checking messages (%d remaining)",
 163                   g_list_length(controld_globals.fsa_message_queue));
 164 
 165         fsa_data = get_message();
 166         if(fsa_data == NULL) {
 167             continue;
 168         }
 169 
 170         log_fsa_input(fsa_data);
 171 
 172         /* add any actions back to the queue */
 173         controld_set_fsa_action_flags(fsa_data->actions);
 174         fsa_dump_actions(fsa_data->actions, "Restored actions");
 175 
 176         /* get the next batch of actions */
 177         new_actions = controld_fsa_get_action(fsa_data->fsa_input);
 178         controld_set_fsa_action_flags(new_actions);
 179         fsa_dump_actions(new_actions, "New actions");
 180 
 181         if (fsa_data->fsa_input != I_NULL && fsa_data->fsa_input != I_ROUTER) {
 182             crm_debug("Processing %s: [ state=%s cause=%s origin=%s ]",
 183                       fsa_input2string(fsa_data->fsa_input),
 184                       fsa_state2string(globals->fsa_state),
 185                       fsa_cause2string(fsa_data->fsa_cause), fsa_data->origin);
 186         }
 187 
 188         /* logging : *before* the state is changed */
 189         if (pcmk_is_set(controld_globals.fsa_actions, A_ERROR)) {
 190             do_fsa_action(fsa_data, A_ERROR, do_log);
 191         }
 192         if (pcmk_is_set(controld_globals.fsa_actions, A_WARN)) {
 193             do_fsa_action(fsa_data, A_WARN, do_log);
 194         }
 195         if (pcmk_is_set(controld_globals.fsa_actions, A_LOG)) {
 196             do_fsa_action(fsa_data, A_LOG, do_log);
 197         }
 198 
 199         /* update state variables */
 200         last_state = globals->fsa_state;
 201         globals->fsa_state = controld_fsa_get_next_state(fsa_data->fsa_input);
 202 
 203         /*
 204          * Remove certain actions during shutdown
 205          */
 206         if ((globals->fsa_state == S_STOPPING)
 207             || pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
 208             controld_clear_fsa_action_flags(startup_actions);
 209         }
 210 
 211         /*
 212          * Hook for change of state.
 213          * Allows actions to be added or removed when entering a state
 214          */
 215         if (last_state != globals->fsa_state) {
 216             do_state_transition(last_state, globals->fsa_state, fsa_data);
 217         }
 218 
 219         /* start doing things... */
 220         s_crmd_fsa_actions(fsa_data);
 221         delete_fsa_input(fsa_data);
 222     }
 223 
 224     if ((controld_globals.fsa_message_queue != NULL)
 225         || (controld_globals.fsa_actions != A_NOTHING)
 226         || pcmk_is_set(controld_globals.flags, controld_fsa_is_stalled)) {
 227 
 228         crm_debug("Exiting the FSA: queue=%d, fsa_actions=%" PRIx64
 229                   ", stalled=%s",
 230                   g_list_length(controld_globals.fsa_message_queue),
 231                   controld_globals.fsa_actions,
 232                   pcmk__flag_text(controld_globals.flags,
 233                                   controld_fsa_is_stalled));
 234     } else {
 235         crm_trace("Exiting the FSA");
 236     }
 237 
 238     /* cleanup inputs? */
 239     if (register_copy != controld_globals.fsa_input_register) {
 240         uint64_t same = register_copy & controld_globals.fsa_input_register;
 241 
 242         fsa_dump_inputs(LOG_DEBUG, "Added",
 243                         controld_globals.fsa_input_register ^ same);
 244         fsa_dump_inputs(LOG_DEBUG, "Removed", register_copy ^ same);
 245     }
 246 
 247     fsa_dump_actions(controld_globals.fsa_actions, "Remaining");
 248     fsa_dump_queue(LOG_DEBUG);
 249 
 250     return globals->fsa_state;
 251 }
 252 
 253 void
 254 s_crmd_fsa_actions(fsa_data_t * fsa_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256     /*
 257      * Process actions in order of priority but do only one
 258      * action at a time to avoid complicating the ordering.
 259      */
 260     CRM_CHECK(fsa_data != NULL, return);
 261     while ((controld_globals.fsa_actions != A_NOTHING)
 262            && !pcmk_is_set(controld_globals.flags, controld_fsa_is_stalled)) {
 263 
 264         /* regular action processing in order of action priority
 265          *
 266          * Make sure all actions that connect to required systems
 267          * are performed first
 268          */
 269         if (pcmk_is_set(controld_globals.fsa_actions, A_ERROR)) {
 270             do_fsa_action(fsa_data, A_ERROR, do_log);
 271         } else if (pcmk_is_set(controld_globals.fsa_actions, A_WARN)) {
 272             do_fsa_action(fsa_data, A_WARN, do_log);
 273         } else if (pcmk_is_set(controld_globals.fsa_actions, A_LOG)) {
 274             do_fsa_action(fsa_data, A_LOG, do_log);
 275 
 276             /* get out of here NOW! before anything worse happens */
 277         } else if (pcmk_is_set(controld_globals.fsa_actions, A_EXIT_1)) {
 278             do_fsa_action(fsa_data, A_EXIT_1, do_exit);
 279 
 280             /* sub-system restart */
 281         } else if (pcmk_all_flags_set(controld_globals.fsa_actions,
 282                                       O_LRM_RECONNECT)) {
 283             do_fsa_action(fsa_data, O_LRM_RECONNECT, do_lrm_control);
 284 
 285         } else if (pcmk_all_flags_set(controld_globals.fsa_actions,
 286                                       O_CIB_RESTART)) {
 287             do_fsa_action(fsa_data, O_CIB_RESTART, do_cib_control);
 288 
 289         } else if (pcmk_all_flags_set(controld_globals.fsa_actions,
 290                                       O_PE_RESTART)) {
 291             do_fsa_action(fsa_data, O_PE_RESTART, do_pe_control);
 292 
 293         } else if (pcmk_all_flags_set(controld_globals.fsa_actions,
 294                                       O_TE_RESTART)) {
 295             do_fsa_action(fsa_data, O_TE_RESTART, do_te_control);
 296 
 297             /* essential start tasks */
 298         } else if (pcmk_is_set(controld_globals.fsa_actions, A_STARTUP)) {
 299             do_fsa_action(fsa_data, A_STARTUP, do_startup);
 300         } else if (pcmk_is_set(controld_globals.fsa_actions, A_CIB_START)) {
 301             do_fsa_action(fsa_data, A_CIB_START, do_cib_control);
 302         } else if (pcmk_is_set(controld_globals.fsa_actions, A_HA_CONNECT)) {
 303             do_fsa_action(fsa_data, A_HA_CONNECT, do_ha_control);
 304         } else if (pcmk_is_set(controld_globals.fsa_actions, A_READCONFIG)) {
 305             do_fsa_action(fsa_data, A_READCONFIG, do_read_config);
 306 
 307             /* sub-system start/connect */
 308         } else if (pcmk_is_set(controld_globals.fsa_actions, A_LRM_CONNECT)) {
 309             do_fsa_action(fsa_data, A_LRM_CONNECT, do_lrm_control);
 310         } else if (pcmk_is_set(controld_globals.fsa_actions, A_TE_START)) {
 311             do_fsa_action(fsa_data, A_TE_START, do_te_control);
 312         } else if (pcmk_is_set(controld_globals.fsa_actions, A_PE_START)) {
 313             do_fsa_action(fsa_data, A_PE_START, do_pe_control);
 314 
 315             /* Timers */
 316         } else if (pcmk_is_set(controld_globals.fsa_actions, A_DC_TIMER_STOP)) {
 317             do_fsa_action(fsa_data, A_DC_TIMER_STOP, do_timer_control);
 318         } else if (pcmk_is_set(controld_globals.fsa_actions,
 319                                A_INTEGRATE_TIMER_STOP)) {
 320             do_fsa_action(fsa_data, A_INTEGRATE_TIMER_STOP, do_timer_control);
 321         } else if (pcmk_is_set(controld_globals.fsa_actions,
 322                                A_INTEGRATE_TIMER_START)) {
 323             do_fsa_action(fsa_data, A_INTEGRATE_TIMER_START, do_timer_control);
 324         } else if (pcmk_is_set(controld_globals.fsa_actions,
 325                                A_FINALIZE_TIMER_STOP)) {
 326             do_fsa_action(fsa_data, A_FINALIZE_TIMER_STOP, do_timer_control);
 327         } else if (pcmk_is_set(controld_globals.fsa_actions,
 328                                A_FINALIZE_TIMER_START)) {
 329             do_fsa_action(fsa_data, A_FINALIZE_TIMER_START, do_timer_control);
 330 
 331             /*
 332              * Highest priority actions
 333              */
 334         } else if (pcmk_is_set(controld_globals.fsa_actions, A_MSG_ROUTE)) {
 335             do_fsa_action(fsa_data, A_MSG_ROUTE, do_msg_route);
 336         } else if (pcmk_is_set(controld_globals.fsa_actions, A_RECOVER)) {
 337             do_fsa_action(fsa_data, A_RECOVER, do_recover);
 338         } else if (pcmk_is_set(controld_globals.fsa_actions,
 339                                A_CL_JOIN_RESULT)) {
 340             do_fsa_action(fsa_data, A_CL_JOIN_RESULT,
 341                           do_cl_join_finalize_respond);
 342 
 343         } else if (pcmk_is_set(controld_globals.fsa_actions,
 344                                A_CL_JOIN_REQUEST)) {
 345             do_fsa_action(fsa_data, A_CL_JOIN_REQUEST,
 346                           do_cl_join_offer_respond);
 347 
 348         } else if (pcmk_is_set(controld_globals.fsa_actions, A_SHUTDOWN_REQ)) {
 349             do_fsa_action(fsa_data, A_SHUTDOWN_REQ, do_shutdown_req);
 350         } else if (pcmk_is_set(controld_globals.fsa_actions, A_ELECTION_VOTE)) {
 351             do_fsa_action(fsa_data, A_ELECTION_VOTE, do_election_vote);
 352         } else if (pcmk_is_set(controld_globals.fsa_actions,
 353                                A_ELECTION_COUNT)) {
 354             do_fsa_action(fsa_data, A_ELECTION_COUNT, do_election_count_vote);
 355 
 356             /*
 357              * High priority actions
 358              */
 359         } else if (pcmk_is_set(controld_globals.fsa_actions, A_STARTED)) {
 360             do_fsa_action(fsa_data, A_STARTED, do_started);
 361         } else if (pcmk_is_set(controld_globals.fsa_actions, A_CL_JOIN_QUERY)) {
 362             do_fsa_action(fsa_data, A_CL_JOIN_QUERY, do_cl_join_query);
 363         } else if (pcmk_is_set(controld_globals.fsa_actions,
 364                                A_DC_TIMER_START)) {
 365             do_fsa_action(fsa_data, A_DC_TIMER_START, do_timer_control);
 366 
 367             /*
 368              * Medium priority actions
 369              * - Membership
 370              */
 371         } else if (pcmk_is_set(controld_globals.fsa_actions, A_DC_TAKEOVER)) {
 372             do_fsa_action(fsa_data, A_DC_TAKEOVER, do_dc_takeover);
 373         } else if (pcmk_is_set(controld_globals.fsa_actions, A_DC_RELEASE)) {
 374             do_fsa_action(fsa_data, A_DC_RELEASE, do_dc_release);
 375         } else if (pcmk_is_set(controld_globals.fsa_actions, A_DC_JOIN_FINAL)) {
 376             do_fsa_action(fsa_data, A_DC_JOIN_FINAL, do_dc_join_final);
 377         } else if (pcmk_is_set(controld_globals.fsa_actions,
 378                                A_ELECTION_CHECK)) {
 379             do_fsa_action(fsa_data, A_ELECTION_CHECK, do_election_check);
 380 
 381         } else if (pcmk_is_set(controld_globals.fsa_actions,
 382                                A_ELECTION_START)) {
 383             do_fsa_action(fsa_data, A_ELECTION_START, do_election_vote);
 384 
 385         } else if (pcmk_is_set(controld_globals.fsa_actions,
 386                                A_DC_JOIN_OFFER_ALL)) {
 387             do_fsa_action(fsa_data, A_DC_JOIN_OFFER_ALL, do_dc_join_offer_all);
 388 
 389         } else if (pcmk_is_set(controld_globals.fsa_actions,
 390                                A_DC_JOIN_OFFER_ONE)) {
 391             do_fsa_action(fsa_data, A_DC_JOIN_OFFER_ONE, do_dc_join_offer_one);
 392 
 393         } else if (pcmk_is_set(controld_globals.fsa_actions,
 394                                A_DC_JOIN_PROCESS_REQ)) {
 395             do_fsa_action(fsa_data, A_DC_JOIN_PROCESS_REQ,
 396                           do_dc_join_filter_offer);
 397 
 398         } else if (pcmk_is_set(controld_globals.fsa_actions,
 399                                A_DC_JOIN_PROCESS_ACK)) {
 400             do_fsa_action(fsa_data, A_DC_JOIN_PROCESS_ACK, do_dc_join_ack);
 401 
 402         } else if (pcmk_is_set(controld_globals.fsa_actions,
 403                                A_DC_JOIN_FINALIZE)) {
 404             do_fsa_action(fsa_data, A_DC_JOIN_FINALIZE, do_dc_join_finalize);
 405 
 406         } else if (pcmk_is_set(controld_globals.fsa_actions,
 407                                A_CL_JOIN_ANNOUNCE)) {
 408             do_fsa_action(fsa_data, A_CL_JOIN_ANNOUNCE, do_cl_join_announce);
 409 
 410             /*
 411              * Low(er) priority actions
 412              * Make sure the CIB is always updated before invoking the
 413              * scheduler, and the scheduler before the transition engine.
 414              */
 415         } else if (pcmk_is_set(controld_globals.fsa_actions, A_TE_HALT)) {
 416             do_fsa_action(fsa_data, A_TE_HALT, do_te_invoke);
 417         } else if (pcmk_is_set(controld_globals.fsa_actions, A_TE_CANCEL)) {
 418             do_fsa_action(fsa_data, A_TE_CANCEL, do_te_invoke);
 419         } else if (pcmk_is_set(controld_globals.fsa_actions, A_LRM_INVOKE)) {
 420             do_fsa_action(fsa_data, A_LRM_INVOKE, do_lrm_invoke);
 421         } else if (pcmk_is_set(controld_globals.fsa_actions, A_PE_INVOKE)) {
 422             do_fsa_action(fsa_data, A_PE_INVOKE, do_pe_invoke);
 423         } else if (pcmk_is_set(controld_globals.fsa_actions, A_TE_INVOKE)) {
 424             do_fsa_action(fsa_data, A_TE_INVOKE, do_te_invoke);
 425 
 426             /* Shutdown actions */
 427         } else if (pcmk_is_set(controld_globals.fsa_actions, A_DC_RELEASED)) {
 428             do_fsa_action(fsa_data, A_DC_RELEASED, do_dc_release);
 429         } else if (pcmk_is_set(controld_globals.fsa_actions, A_PE_STOP)) {
 430             do_fsa_action(fsa_data, A_PE_STOP, do_pe_control);
 431         } else if (pcmk_is_set(controld_globals.fsa_actions, A_TE_STOP)) {
 432             do_fsa_action(fsa_data, A_TE_STOP, do_te_control);
 433         } else if (pcmk_is_set(controld_globals.fsa_actions, A_SHUTDOWN)) {
 434             do_fsa_action(fsa_data, A_SHUTDOWN, do_shutdown);
 435         } else if (pcmk_is_set(controld_globals.fsa_actions,
 436                                A_LRM_DISCONNECT)) {
 437             do_fsa_action(fsa_data, A_LRM_DISCONNECT, do_lrm_control);
 438 
 439         } else if (pcmk_is_set(controld_globals.fsa_actions, A_HA_DISCONNECT)) {
 440             do_fsa_action(fsa_data, A_HA_DISCONNECT, do_ha_control);
 441         } else if (pcmk_is_set(controld_globals.fsa_actions, A_CIB_STOP)) {
 442             do_fsa_action(fsa_data, A_CIB_STOP, do_cib_control);
 443         } else if (pcmk_is_set(controld_globals.fsa_actions, A_STOP)) {
 444             do_fsa_action(fsa_data, A_STOP, do_stop);
 445 
 446             /* exit gracefully */
 447         } else if (pcmk_is_set(controld_globals.fsa_actions, A_EXIT_0)) {
 448             do_fsa_action(fsa_data, A_EXIT_0, do_exit);
 449 
 450             /* Error checking and reporting */
 451         } else {
 452             crm_err("Action %s not supported " QB_XS " %" PRIx64,
 453                     fsa_action2string(controld_globals.fsa_actions),
 454                     controld_globals.fsa_actions);
 455             register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, fsa_data, NULL,
 456                                    __func__);
 457         }
 458     }
 459 }
 460 
 461 void
 462 log_fsa_input(fsa_data_t * stored_msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464     pcmk__assert(stored_msg != NULL);
 465     crm_trace("Processing queued input %d", stored_msg->id);
 466     if (stored_msg->fsa_cause == C_LRM_OP_CALLBACK) {
 467         crm_trace("FSA processing LRM callback from %s", stored_msg->origin);
 468 
 469     } else if (stored_msg->data == NULL) {
 470         crm_trace("FSA processing input from %s", stored_msg->origin);
 471 
 472     } else {
 473         ha_msg_input_t *ha_input = fsa_typed_data_adv(stored_msg, fsa_dt_ha_msg,
 474                                                       __func__);
 475 
 476         crm_trace("FSA processing XML message from %s", stored_msg->origin);
 477         crm_log_xml_trace(ha_input->xml, "FSA message data");
 478     }
 479 }
 480 
 481 static void
 482 check_join_counts(fsa_data_t *msg_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 483 {
 484     int count;
 485     guint npeers;
 486 
 487     count = crmd_join_phase_count(controld_join_finalized);
 488     if (count > 0) {
 489         crm_err("%d cluster node%s failed to confirm join",
 490                 count, pcmk__plural_s(count));
 491         crmd_join_phase_log(LOG_NOTICE);
 492         return;
 493     }
 494 
 495     npeers = pcmk__cluster_num_active_nodes();
 496     count = crmd_join_phase_count(controld_join_confirmed);
 497     if (count == npeers) {
 498         if (npeers == 1) {
 499             crm_debug("Sole active cluster node is fully joined");
 500         } else {
 501             crm_debug("All %d active cluster nodes are fully joined", count);
 502         }
 503 
 504     } else if (count > npeers) {
 505         crm_err("New election needed because more nodes confirmed join "
 506                 "than are in membership (%d > %u)", count, npeers);
 507         register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
 508 
 509     } else if (controld_globals.membership_id != controld_globals.peer_seq) {
 510         crm_info("New join needed because membership changed (%llu -> %llu)",
 511                  controld_globals.membership_id, controld_globals.peer_seq);
 512         register_fsa_input_before(C_FSA_INTERNAL, I_NODE_JOIN, NULL);
 513 
 514     } else {
 515         crm_warn("Only %d of %u active cluster nodes fully joined "
 516                  "(%d did not respond to offer)",
 517                  count, npeers, crmd_join_phase_count(controld_join_welcomed));
 518     }
 519 }
 520 
 521 static void
 522 do_state_transition(enum crmd_fsa_state cur_state,
     /* [previous][next][first][last][top][bottom][index][help] */
 523                     enum crmd_fsa_state next_state, fsa_data_t *msg_data)
 524 {
 525     int level = LOG_INFO;
 526     int count = 0;
 527     gboolean clear_recovery_bit = TRUE;
 528 #if 0
 529     uint64_t original_fsa_actions = controld_globals.fsa_actions;
 530 #endif
 531 
 532     enum crmd_fsa_cause cause = msg_data->fsa_cause;
 533     enum crmd_fsa_input current_input = msg_data->fsa_input;
 534 
 535     const char *state_from = fsa_state2string(cur_state);
 536     const char *state_to = fsa_state2string(next_state);
 537     const char *input = fsa_input2string(current_input);
 538 
 539     CRM_LOG_ASSERT(cur_state != next_state);
 540 
 541     if (cur_state == S_IDLE || next_state == S_IDLE) {
 542         level = LOG_NOTICE;
 543     } else if (cur_state == S_NOT_DC || next_state == S_NOT_DC) {
 544         level = LOG_NOTICE;
 545     } else if (cur_state == S_ELECTION) {
 546         level = LOG_NOTICE;
 547     } else if (cur_state == S_STARTING) {
 548         level = LOG_NOTICE;
 549     } else if (next_state == S_RECOVERY) {
 550         level = LOG_WARNING;
 551     }
 552 
 553     do_crm_log(level, "State transition %s -> %s "
 554                QB_XS " input=%s cause=%s origin=%s",
 555                state_from, state_to, input, fsa_cause2string(cause),
 556                msg_data->origin);
 557 
 558     if (next_state != S_ELECTION && cur_state != S_RELEASE_DC) {
 559         controld_stop_current_election_timeout();
 560     }
 561     if (next_state == S_INTEGRATION) {
 562         controld_set_fsa_action_flags(A_INTEGRATE_TIMER_START);
 563     } else {
 564         controld_set_fsa_action_flags(A_INTEGRATE_TIMER_STOP);
 565     }
 566 
 567     if (next_state == S_FINALIZE_JOIN) {
 568         controld_set_fsa_action_flags(A_FINALIZE_TIMER_START);
 569     } else {
 570         controld_set_fsa_action_flags(A_FINALIZE_TIMER_STOP);
 571     }
 572 
 573     if (next_state != S_PENDING) {
 574         controld_set_fsa_action_flags(A_DC_TIMER_STOP);
 575     }
 576     if (next_state != S_IDLE) {
 577         controld_stop_recheck_timer();
 578     }
 579 
 580     if (cur_state == S_FINALIZE_JOIN && next_state == S_POLICY_ENGINE) {
 581         populate_cib_nodes(controld_node_update_quick|controld_node_update_all,
 582                            __func__);
 583     }
 584 
 585     switch (next_state) {
 586         case S_PENDING:
 587             {
 588                 cib_t *cib_conn = controld_globals.cib_conn;
 589                 cib_conn->cmds->set_secondary(cib_conn, cib_none);
 590             }
 591             update_dc(NULL);
 592             break;
 593 
 594         case S_ELECTION:
 595             update_dc(NULL);
 596             break;
 597 
 598         case S_NOT_DC:
 599             controld_reset_counter_election_timer();
 600             purge_stonith_cleanup();
 601 
 602             if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
 603                 crm_info("(Re)Issuing shutdown request now" " that we have a new DC");
 604                 controld_set_fsa_action_flags(A_SHUTDOWN_REQ);
 605             }
 606             CRM_LOG_ASSERT(controld_globals.dc_name != NULL);
 607             if (controld_globals.dc_name == NULL) {
 608                 crm_err("Reached S_NOT_DC without a DC" " being recorded");
 609             }
 610             break;
 611 
 612         case S_RECOVERY:
 613             clear_recovery_bit = FALSE;
 614             break;
 615 
 616         case S_FINALIZE_JOIN:
 617             CRM_LOG_ASSERT(AM_I_DC);
 618             if (cause == C_TIMER_POPPED) {
 619                 crm_warn("Progressed to state %s after %s",
 620                          fsa_state2string(next_state), fsa_cause2string(cause));
 621             }
 622             count = crmd_join_phase_count(controld_join_welcomed);
 623             if (count > 0) {
 624                 crm_warn("%d cluster node%s failed to respond to join offer",
 625                          count, pcmk__plural_s(count));
 626                 crmd_join_phase_log(LOG_NOTICE);
 627 
 628             } else {
 629                 crm_debug("All cluster nodes (%d) responded to join offer",
 630                           crmd_join_phase_count(controld_join_integrated));
 631             }
 632             break;
 633 
 634         case S_POLICY_ENGINE:
 635             controld_reset_counter_election_timer();
 636             CRM_LOG_ASSERT(AM_I_DC);
 637             if (cause == C_TIMER_POPPED) {
 638                 crm_info("Progressed to state %s after %s",
 639                          fsa_state2string(next_state), fsa_cause2string(cause));
 640             }
 641             check_join_counts(msg_data);
 642             break;
 643 
 644         case S_STOPPING:
 645         case S_TERMINATE:
 646             /* possibly redundant */
 647             controld_set_fsa_input_flags(R_SHUTDOWN);
 648             break;
 649 
 650         case S_IDLE:
 651             CRM_LOG_ASSERT(AM_I_DC);
 652             if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
 653                 crm_info("(Re)Issuing shutdown request now" " that we are the DC");
 654                 controld_set_fsa_action_flags(A_SHUTDOWN_REQ);
 655             }
 656             controld_start_recheck_timer();
 657             break;
 658 
 659         default:
 660             break;
 661     }
 662 
 663     if (clear_recovery_bit && next_state != S_PENDING) {
 664         controld_clear_fsa_action_flags(A_RECOVER);
 665     } else if (clear_recovery_bit == FALSE) {
 666         controld_set_fsa_action_flags(A_RECOVER);
 667     }
 668 
 669 #if 0
 670     if (original_fsa_actions != controld_globals.fsa_actions) {
 671         fsa_dump_actions(original_fsa_actions ^ controld_globals.fsa_actions,
 672                          "New actions");
 673     }
 674 #endif
 675 }

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