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

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