root/daemons/controld/controld_election.c

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

DEFINITIONS

This source file includes following definitions.
  1. election_win_cb
  2. controld_election_init
  3. controld_remove_voter
  4. controld_election_fini
  5. controld_set_election_period
  6. controld_stop_election_timer
  7. do_election_vote
  8. do_election_check
  9. do_election_count_vote
  10. feature_update_callback
  11. do_dc_takeover
  12. do_dc_release

   1 /*
   2  * Copyright 2004-2022 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 <sys/time.h>
  13 #include <sys/resource.h>
  14 
  15 #include <crm/msg_xml.h>
  16 #include <crm/common/xml.h>
  17 #include <crm/cluster/internal.h>
  18 #include <crm/cluster/election_internal.h>
  19 #include <crm/crm.h>
  20 
  21 #include <pacemaker-controld.h>
  22 
  23 extern pcmk__output_t *logger_out;
  24 
  25 static election_t *fsa_election = NULL;
  26 
  27 static gboolean
  28 election_win_cb(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30     register_fsa_input(C_FSA_INTERNAL, I_ELECTION_DC, NULL);
  31     return FALSE;
  32 }
  33 
  34 void
  35 controld_election_init(const char *uname)
     /* [previous][next][first][last][top][bottom][index][help] */
  36 {
  37     fsa_election = election_init("DC", uname, 60000 /*60s*/, election_win_cb);
  38 }
  39 
  40 void
  41 controld_remove_voter(const char *uname)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43     election_remove(fsa_election, uname);
  44 
  45     if (pcmk__str_eq(uname, fsa_our_dc, pcmk__str_casei)) {
  46         /* Clear any election dampening in effect. Otherwise, if the lost DC had
  47          * just won, an immediate new election could fizzle out with no new DC.
  48          */
  49         election_clear_dampening(fsa_election);
  50     }
  51 }
  52 
  53 void
  54 controld_election_fini(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56     election_fini(fsa_election);
  57     fsa_election = NULL;
  58 }
  59 
  60 void
  61 controld_set_election_period(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63     election_timeout_set_period(fsa_election, crm_parse_interval_spec(value));
  64 }
  65 
  66 void
  67 controld_stop_election_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69     election_timeout_stop(fsa_election);
  70 }
  71 
  72 /*      A_ELECTION_VOTE */
  73 void
  74 do_election_vote(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
  75                  enum crmd_fsa_cause cause,
  76                  enum crmd_fsa_state cur_state,
  77                  enum crmd_fsa_input current_input, fsa_data_t * msg_data)
  78 {
  79     gboolean not_voting = FALSE;
  80 
  81     /* don't vote if we're in one of these states or wanting to shut down */
  82     switch (cur_state) {
  83         case S_STARTING:
  84         case S_RECOVERY:
  85         case S_STOPPING:
  86         case S_TERMINATE:
  87             crm_warn("Not voting in election, we're in state %s", fsa_state2string(cur_state));
  88             not_voting = TRUE;
  89             break;
  90         case S_ELECTION:
  91         case S_INTEGRATION:
  92         case S_RELEASE_DC:
  93             break;
  94         default:
  95             crm_err("Broken? Voting in state %s", fsa_state2string(cur_state));
  96             break;
  97     }
  98 
  99     if (not_voting == FALSE) {
 100         if (pcmk_is_set(fsa_input_register, R_STARTING)) {
 101             not_voting = TRUE;
 102         }
 103     }
 104 
 105     if (not_voting) {
 106         if (AM_I_DC) {
 107             register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);
 108 
 109         } else {
 110             register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
 111         }
 112         return;
 113     }
 114 
 115     election_vote(fsa_election);
 116     return;
 117 }
 118 
 119 void
 120 do_election_check(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
 121                   enum crmd_fsa_cause cause,
 122                   enum crmd_fsa_state cur_state,
 123                   enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 124 {
 125     if (fsa_state == S_ELECTION) {
 126         election_check(fsa_election);
 127     } else {
 128         crm_debug("Ignoring election check because we are not in an election");
 129     }
 130 }
 131 
 132 /*      A_ELECTION_COUNT        */
 133 void
 134 do_election_count_vote(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
 135                        enum crmd_fsa_cause cause,
 136                        enum crmd_fsa_state cur_state,
 137                        enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 138 {
 139     enum election_result rc = 0;
 140     ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg);
 141 
 142     if(crm_peer_cache == NULL) {
 143         if (!pcmk_is_set(fsa_input_register, R_SHUTDOWN)) {
 144             crm_err("Internal error, no peer cache");
 145         }
 146         return;
 147     }
 148 
 149     rc = election_count_vote(fsa_election, vote->msg, cur_state != S_STARTING);
 150     switch(rc) {
 151         case election_start:
 152             election_reset(fsa_election);
 153             register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
 154             break;
 155 
 156         case election_lost:
 157             update_dc(NULL);
 158 
 159             if (fsa_input_register & R_THE_DC) {
 160                 register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);
 161                 fsa_cib_conn->cmds->set_secondary(fsa_cib_conn,
 162                                                   cib_scope_local);
 163 
 164             } else if (cur_state != S_STARTING) {
 165                 register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
 166             }
 167             break;
 168 
 169         default:
 170             crm_trace("Election message resulted in state %d", rc);
 171     }
 172 }
 173 
 174 static void
 175 feature_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177     if (rc != pcmk_ok) {
 178         fsa_data_t *msg_data = NULL;
 179 
 180         crm_notice("Feature update failed: %s "CRM_XS" rc=%d",
 181                    pcmk_strerror(rc), rc);
 182         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
 183     }
 184 }
 185 
 186 /*       A_DC_TAKEOVER  */
 187 void
 188 do_dc_takeover(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
 189                enum crmd_fsa_cause cause,
 190                enum crmd_fsa_state cur_state,
 191                enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 192 {
 193     int rc = pcmk_ok;
 194     xmlNode *cib = NULL;
 195     const char *cluster_type = name_for_cluster_type(get_cluster_type());
 196     pid_t watchdog = pcmk__locate_sbd();
 197 
 198     crm_info("Taking over DC status for this partition");
 199     controld_set_fsa_input_flags(R_THE_DC);
 200     execute_stonith_cleanup();
 201 
 202     election_reset(fsa_election);
 203     controld_set_fsa_input_flags(R_JOIN_OK|R_INVOKE_PE);
 204 
 205     fsa_cib_conn->cmds->set_primary(fsa_cib_conn, cib_scope_local);
 206 
 207     cib = create_xml_node(NULL, XML_TAG_CIB);
 208     crm_xml_add(cib, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
 209     fsa_cib_update(XML_TAG_CIB, cib, cib_quorum_override, rc, NULL);
 210     fsa_register_cib_callback(rc, FALSE, NULL, feature_update_callback);
 211 
 212     cib__update_node_attr(logger_out, fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG,
 213                           NULL, NULL, NULL, NULL, XML_ATTR_HAVE_WATCHDOG,
 214                           pcmk__btoa(watchdog), NULL, NULL);
 215 
 216     cib__update_node_attr(logger_out, fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG,
 217                           NULL, NULL, NULL, NULL, "dc-version",
 218                           PACEMAKER_VERSION "-" BUILD_VERSION, NULL, NULL);
 219 
 220     cib__update_node_attr(logger_out, fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG,
 221                           NULL, NULL, NULL, NULL, "cluster-infrastructure",
 222                           cluster_type, NULL, NULL);
 223 
 224 #if SUPPORT_COROSYNC
 225     if (fsa_cluster_name == NULL && is_corosync_cluster()) {
 226         char *cluster_name = pcmk__corosync_cluster_name();
 227 
 228         if (cluster_name) {
 229             cib__update_node_attr(logger_out, fsa_cib_conn, cib_none,
 230                                   XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL,
 231                                   "cluster-name", cluster_name, NULL, NULL);
 232         }
 233         free(cluster_name);
 234     }
 235 #endif
 236 
 237     mainloop_set_trigger(config_read);
 238     free_xml(cib);
 239 }
 240 
 241 /*       A_DC_RELEASE   */
 242 void
 243 do_dc_release(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
 244               enum crmd_fsa_cause cause,
 245               enum crmd_fsa_state cur_state,
 246               enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 247 {
 248     if (action & A_DC_RELEASE) {
 249         crm_debug("Releasing the role of DC");
 250         controld_clear_fsa_input_flags(R_THE_DC);
 251         controld_expect_sched_reply(NULL);
 252 
 253     } else if (action & A_DC_RELEASED) {
 254         crm_info("DC role released");
 255 #if 0
 256         if (are there errors) {
 257             /* we can't stay up if not healthy */
 258             /* or perhaps I_ERROR and go to S_RECOVER? */
 259             result = I_SHUTDOWN;
 260         }
 261 #endif
 262         if (pcmk_is_set(fsa_input_register, R_SHUTDOWN)) {
 263             xmlNode *update = NULL;
 264             crm_node_t *node = crm_get_peer(0, fsa_our_uname);
 265 
 266             pcmk__update_peer_expected(__func__, node, CRMD_JOINSTATE_DOWN);
 267             update = create_node_state_update(node, node_update_expected, NULL,
 268                                               __func__);
 269             /* Don't need a based response because controld will stop. */
 270             fsa_cib_anon_update_discard_reply(XML_CIB_TAG_STATUS, update);
 271             free_xml(update);
 272         }
 273         register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL);
 274 
 275     } else {
 276         crm_err("Unknown DC action %s", fsa_action2string(action));
 277     }
 278 
 279     crm_trace("Am I still the DC? %s", AM_I_DC ? XML_BOOLEAN_YES : XML_BOOLEAN_NO);
 280 
 281 }

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