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()
     /* [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()
     /* [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_slave(fsa_cib_conn, cib_scope_local);
 162 
 163             } else if (cur_state != S_STARTING) {
 164                 register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
 165             }
 166             break;
 167 
 168         default:
 169             crm_trace("Election message resulted in state %d", rc);
 170     }
 171 }
 172 
 173 static void
 174 feature_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176     if (rc != pcmk_ok) {
 177         fsa_data_t *msg_data = NULL;
 178 
 179         crm_notice("Feature update failed: %s "CRM_XS" rc=%d",
 180                    pcmk_strerror(rc), rc);
 181         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
 182     }
 183 }
 184 
 185 /*       A_DC_TAKEOVER  */
 186 void
 187 do_dc_takeover(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
 188                enum crmd_fsa_cause cause,
 189                enum crmd_fsa_state cur_state,
 190                enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 191 {
 192     int rc = pcmk_ok;
 193     xmlNode *cib = NULL;
 194     const char *cluster_type = name_for_cluster_type(get_cluster_type());
 195     pid_t watchdog = pcmk__locate_sbd();
 196 
 197     crm_info("Taking over DC status for this partition");
 198     controld_set_fsa_input_flags(R_THE_DC);
 199     execute_stonith_cleanup();
 200 
 201     election_reset(fsa_election);
 202     controld_set_fsa_input_flags(R_JOIN_OK|R_INVOKE_PE);
 203 
 204     fsa_cib_conn->cmds->set_master(fsa_cib_conn, cib_scope_local);
 205 
 206     cib = create_xml_node(NULL, XML_TAG_CIB);
 207     crm_xml_add(cib, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
 208     fsa_cib_update(XML_TAG_CIB, cib, cib_quorum_override, rc, NULL);
 209     fsa_register_cib_callback(rc, FALSE, NULL, feature_update_callback);
 210 
 211     cib__update_node_attr(logger_out, fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG,
 212                           NULL, NULL, NULL, NULL, XML_ATTR_HAVE_WATCHDOG,
 213                           pcmk__btoa(watchdog), NULL, NULL);
 214 
 215     cib__update_node_attr(logger_out, fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG,
 216                           NULL, NULL, NULL, NULL, "dc-version",
 217                           PACEMAKER_VERSION "-" BUILD_VERSION, NULL, NULL);
 218 
 219     cib__update_node_attr(logger_out, fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG,
 220                           NULL, NULL, NULL, NULL, "cluster-infrastructure",
 221                           cluster_type, NULL, NULL);
 222 
 223 #if SUPPORT_COROSYNC
 224     if (fsa_cluster_name == NULL && is_corosync_cluster()) {
 225         char *cluster_name = pcmk__corosync_cluster_name();
 226 
 227         if (cluster_name) {
 228             cib__update_node_attr(logger_out, fsa_cib_conn, cib_none,
 229                                   XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL,
 230                                   "cluster-name", cluster_name, NULL, NULL);
 231         }
 232         free(cluster_name);
 233     }
 234 #endif
 235 
 236     mainloop_set_trigger(config_read);
 237     free_xml(cib);
 238 }
 239 
 240 /*       A_DC_RELEASE   */
 241 void
 242 do_dc_release(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
 243               enum crmd_fsa_cause cause,
 244               enum crmd_fsa_state cur_state,
 245               enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 246 {
 247     if (action & A_DC_RELEASE) {
 248         crm_debug("Releasing the role of DC");
 249         controld_clear_fsa_input_flags(R_THE_DC);
 250         controld_expect_sched_reply(NULL);
 251 
 252     } else if (action & A_DC_RELEASED) {
 253         crm_info("DC role released");
 254 #if 0
 255         if (are there errors) {
 256             /* we can't stay up if not healthy */
 257             /* or perhaps I_ERROR and go to S_RECOVER? */
 258             result = I_SHUTDOWN;
 259         }
 260 #endif
 261         if (pcmk_is_set(fsa_input_register, R_SHUTDOWN)) {
 262             xmlNode *update = NULL;
 263             crm_node_t *node = crm_get_peer(0, fsa_our_uname);
 264 
 265             pcmk__update_peer_expected(__func__, node, CRMD_JOINSTATE_DOWN);
 266             update = create_node_state_update(node, node_update_expected, NULL,
 267                                               __func__);
 268             /* Don't need a based response because controld will stop. */
 269             fsa_cib_anon_update_discard_reply(XML_CIB_TAG_STATUS, update);
 270             free_xml(update);
 271         }
 272         register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL);
 273 
 274     } else {
 275         crm_err("Unknown DC action %s", fsa_action2string(action));
 276     }
 277 
 278     crm_trace("Am I still the DC? %s", AM_I_DC ? XML_BOOLEAN_YES : XML_BOOLEAN_NO);
 279 
 280 }

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