This source file includes following definitions.
- election_win_cb
- controld_election_init
- controld_configure_election
- controld_remove_voter
- controld_election_fini
- controld_stop_current_election_timeout
- do_election_vote
- do_election_check
- do_election_count_vote
- feature_update_callback
- do_dc_takeover
- do_dc_release
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/time.h>
13 #include <sys/resource.h>
14
15 #include <crm/common/xml.h>
16 #include <crm/cluster/internal.h>
17 #include <crm/cluster/election_internal.h>
18 #include <crm/crm.h>
19
20 #include <pacemaker-controld.h>
21
22 static election_t *fsa_election = NULL;
23
24 static gboolean
25 election_win_cb(gpointer data)
26 {
27 register_fsa_input(C_FSA_INTERNAL, I_ELECTION_DC, NULL);
28 return FALSE;
29 }
30
31 void
32 controld_election_init(const char *uname)
33 {
34 fsa_election = election_init("DC", uname, 60000 , election_win_cb);
35 }
36
37
38
39
40
41
42
43 void
44 controld_configure_election(GHashTable *options)
45 {
46 const char *value = g_hash_table_lookup(options, PCMK_OPT_ELECTION_TIMEOUT);
47 guint interval_ms = 0U;
48
49 pcmk_parse_interval_spec(value, &interval_ms);
50 election_timeout_set_period(fsa_election, interval_ms);
51 }
52
53 void
54 controld_remove_voter(const char *uname)
55 {
56 election_remove(fsa_election, uname);
57
58 if (pcmk__str_eq(uname, controld_globals.dc_name, pcmk__str_casei)) {
59
60
61
62 election_clear_dampening(fsa_election);
63 }
64 }
65
66 void
67 controld_election_fini(void)
68 {
69 election_fini(fsa_election);
70 fsa_election = NULL;
71 }
72
73 void
74 controld_stop_current_election_timeout(void)
75 {
76 election_timeout_stop(fsa_election);
77 }
78
79
80 void
81 do_election_vote(long long action,
82 enum crmd_fsa_cause cause,
83 enum crmd_fsa_state cur_state,
84 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
85 {
86 gboolean not_voting = FALSE;
87
88
89 switch (cur_state) {
90 case S_STARTING:
91 case S_RECOVERY:
92 case S_STOPPING:
93 case S_TERMINATE:
94 crm_warn("Not voting in election, we're in state %s", fsa_state2string(cur_state));
95 not_voting = TRUE;
96 break;
97 case S_ELECTION:
98 case S_INTEGRATION:
99 case S_RELEASE_DC:
100 break;
101 default:
102 crm_err("Broken? Voting in state %s", fsa_state2string(cur_state));
103 break;
104 }
105
106 if (not_voting == FALSE) {
107 if (pcmk_is_set(controld_globals.fsa_input_register, R_STARTING)) {
108 not_voting = TRUE;
109 }
110 }
111
112 if (not_voting) {
113 if (AM_I_DC) {
114 register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);
115
116 } else {
117 register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
118 }
119 return;
120 }
121
122 election_vote(fsa_election);
123 return;
124 }
125
126 void
127 do_election_check(long long action,
128 enum crmd_fsa_cause cause,
129 enum crmd_fsa_state cur_state,
130 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
131 {
132 if (controld_globals.fsa_state == S_ELECTION) {
133 election_check(fsa_election);
134 } else {
135 crm_debug("Ignoring election check because we are not in an election");
136 }
137 }
138
139
140 void
141 do_election_count_vote(long long action,
142 enum crmd_fsa_cause cause,
143 enum crmd_fsa_state cur_state,
144 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
145 {
146 enum election_result rc = 0;
147 ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg);
148
149 if(crm_peer_cache == NULL) {
150 if (!pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
151 crm_err("Internal error, no peer cache");
152 }
153 return;
154 }
155
156 rc = election_count_vote(fsa_election, vote->msg, cur_state != S_STARTING);
157 switch(rc) {
158 case election_start:
159 election_reset(fsa_election);
160 register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
161 break;
162
163 case election_lost:
164 update_dc(NULL);
165
166 if (pcmk_is_set(controld_globals.fsa_input_register, R_THE_DC)) {
167 cib_t *cib_conn = controld_globals.cib_conn;
168
169 register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);
170 cib_conn->cmds->set_secondary(cib_conn, cib_scope_local);
171
172 } else if (cur_state != S_STARTING) {
173 register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
174 }
175 break;
176
177 default:
178 crm_trace("Election message resulted in state %d", rc);
179 }
180 }
181
182 static void
183 feature_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
184 {
185 if (rc != pcmk_ok) {
186 fsa_data_t *msg_data = NULL;
187
188 crm_notice("Feature update failed: %s "CRM_XS" rc=%d",
189 pcmk_strerror(rc), rc);
190 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
191 }
192 }
193
194
195
196
197
198
199
200
201 #define dc_takeover_update_attr(name, value) do { \
202 cib__update_node_attr(controld_globals.logger_out, \
203 controld_globals.cib_conn, cib_none, \
204 PCMK_XE_CRM_CONFIG, NULL, NULL, NULL, NULL, \
205 name, value, NULL, NULL); \
206 } while (0)
207
208
209 void
210 do_dc_takeover(long long action,
211 enum crmd_fsa_cause cause,
212 enum crmd_fsa_state cur_state,
213 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
214 {
215 xmlNode *cib = NULL;
216 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
217 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
218 pid_t watchdog = pcmk__locate_sbd();
219
220 crm_info("Taking over DC status for this partition");
221 controld_set_fsa_input_flags(R_THE_DC);
222 execute_stonith_cleanup();
223
224 election_reset(fsa_election);
225 controld_set_fsa_input_flags(R_JOIN_OK|R_INVOKE_PE);
226
227 controld_globals.cib_conn->cmds->set_primary(controld_globals.cib_conn,
228 cib_scope_local);
229
230 cib = pcmk__xe_create(NULL, PCMK_XE_CIB);
231 crm_xml_add(cib, PCMK_XA_CRM_FEATURE_SET, CRM_FEATURE_SET);
232 controld_update_cib(PCMK_XE_CIB, cib, cib_none, feature_update_callback);
233
234 dc_takeover_update_attr(PCMK_OPT_HAVE_WATCHDOG, pcmk__btoa(watchdog));
235 dc_takeover_update_attr(PCMK_OPT_DC_VERSION,
236 PACEMAKER_VERSION "-" BUILD_VERSION);
237 dc_takeover_update_attr(PCMK_OPT_CLUSTER_INFRASTRUCTURE, cluster_layer_s);
238
239 #if SUPPORT_COROSYNC
240 if ((controld_globals.cluster_name == NULL)
241 && (pcmk_get_cluster_layer() == pcmk_cluster_layer_corosync)) {
242
243 char *cluster_name = pcmk__corosync_cluster_name();
244
245 if (cluster_name != NULL) {
246 dc_takeover_update_attr(PCMK_OPT_CLUSTER_NAME, cluster_name);
247 }
248 free(cluster_name);
249 }
250 #endif
251
252 controld_trigger_config();
253 free_xml(cib);
254 }
255
256
257 void
258 do_dc_release(long long action,
259 enum crmd_fsa_cause cause,
260 enum crmd_fsa_state cur_state,
261 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
262 {
263 if (action & A_DC_RELEASE) {
264 crm_debug("Releasing the role of DC");
265 controld_clear_fsa_input_flags(R_THE_DC);
266 controld_expect_sched_reply(NULL);
267
268 } else if (action & A_DC_RELEASED) {
269 crm_info("DC role released");
270 if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
271 xmlNode *update = NULL;
272 crm_node_t *node =
273 pcmk__get_node(0, controld_globals.our_nodename,
274 NULL, pcmk__node_search_cluster_member);
275
276 pcmk__update_peer_expected(__func__, node, CRMD_JOINSTATE_DOWN);
277 update = create_node_state_update(node, node_update_expected, NULL,
278 __func__);
279
280 fsa_cib_anon_update_discard_reply(PCMK_XE_STATUS, update);
281 free_xml(update);
282 }
283 register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL);
284
285 } else {
286 crm_err("Unknown DC action %s", fsa_action2string(action));
287 }
288
289 crm_trace("Am I still the DC? %s", pcmk__btoa(AM_I_DC));
290 }