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/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)
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)
34 {
35 fsa_election = election_init("DC", uname, 60000 , election_win_cb);
36 }
37
38
39
40
41
42
43
44 void
45 controld_configure_election(GHashTable *options)
46 {
47 const char *value = NULL;
48
49 value = g_hash_table_lookup(options, XML_CONFIG_ATTR_ELECTION_FAIL);
50 election_timeout_set_period(fsa_election, crm_parse_interval_spec(value));
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 XML_CIB_TAG_CRMCONFIG, 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 char *cluster_type = name_for_cluster_type(get_cluster_type());
217 pid_t watchdog = pcmk__locate_sbd();
218
219 crm_info("Taking over DC status for this partition");
220 controld_set_fsa_input_flags(R_THE_DC);
221 execute_stonith_cleanup();
222
223 election_reset(fsa_election);
224 controld_set_fsa_input_flags(R_JOIN_OK|R_INVOKE_PE);
225
226 controld_globals.cib_conn->cmds->set_primary(controld_globals.cib_conn,
227 cib_scope_local);
228
229 cib = create_xml_node(NULL, XML_TAG_CIB);
230 crm_xml_add(cib, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
231 controld_update_cib(XML_TAG_CIB, cib, cib_none, feature_update_callback);
232
233 dc_takeover_update_attr(XML_ATTR_HAVE_WATCHDOG, pcmk__btoa(watchdog));
234 dc_takeover_update_attr("dc-version", PACEMAKER_VERSION "-" BUILD_VERSION);
235 dc_takeover_update_attr("cluster-infrastructure", cluster_type);
236
237 #if SUPPORT_COROSYNC
238 if ((controld_globals.cluster_name == NULL) && is_corosync_cluster()) {
239 char *cluster_name = pcmk__corosync_cluster_name();
240
241 if (cluster_name != NULL) {
242 dc_takeover_update_attr("cluster-name", cluster_name);
243 }
244 free(cluster_name);
245 }
246 #endif
247
248 controld_trigger_config();
249 free_xml(cib);
250 }
251
252
253 void
254 do_dc_release(long long action,
255 enum crmd_fsa_cause cause,
256 enum crmd_fsa_state cur_state,
257 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
258 {
259 if (action & A_DC_RELEASE) {
260 crm_debug("Releasing the role of DC");
261 controld_clear_fsa_input_flags(R_THE_DC);
262 controld_expect_sched_reply(NULL);
263
264 } else if (action & A_DC_RELEASED) {
265 crm_info("DC role released");
266 if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
267 xmlNode *update = NULL;
268 crm_node_t *node = crm_get_peer(0, controld_globals.our_nodename);
269
270 pcmk__update_peer_expected(__func__, node, CRMD_JOINSTATE_DOWN);
271 update = create_node_state_update(node, node_update_expected, NULL,
272 __func__);
273
274 fsa_cib_anon_update_discard_reply(XML_CIB_TAG_STATUS, update);
275 free_xml(update);
276 }
277 register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL);
278
279 } else {
280 crm_err("Unknown DC action %s", fsa_action2string(action));
281 }
282
283 crm_trace("Am I still the DC? %s", AM_I_DC ? XML_BOOLEAN_YES : XML_BOOLEAN_NO);
284
285 }