This source file includes following definitions.
- update_dc_expected
- do_cl_join_query
- do_cl_join_announce
- do_cl_join_offer_respond
- join_query_callback
- set_join_state
- update_conn_host_cache
- do_cl_join_finalize_respond
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/crm.h>
13 #include <crm/cib.h>
14 #include <crm/common/xml.h>
15
16 #include <pacemaker-controld.h>
17
18 void join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data);
19
20 extern ha_msg_input_t *copy_ha_msg_input(ha_msg_input_t * orig);
21
22
23
24
25
26
27
28
29
30
31
32 static void
33 update_dc_expected(const xmlNode *msg)
34 {
35 if ((controld_globals.dc_name != NULL)
36 && pcmk__xe_attr_is_true(msg, PCMK__XA_DC_LEAVING)) {
37 crm_node_t *dc_node = pcmk__get_node(0, controld_globals.dc_name, NULL,
38 pcmk__node_search_cluster_member);
39
40 pcmk__update_peer_expected(__func__, dc_node, CRMD_JOINSTATE_DOWN);
41 }
42 }
43
44
45
46 void
47 do_cl_join_query(long long action,
48 enum crmd_fsa_cause cause,
49 enum crmd_fsa_state cur_state,
50 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
51 {
52 xmlNode *req = create_request(CRM_OP_JOIN_ANNOUNCE, NULL, NULL,
53 CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
54
55 sleep(1);
56 update_dc(NULL);
57 crm_debug("Querying for a DC");
58 pcmk__cluster_send_message(NULL, crm_msg_crmd, req);
59 free_xml(req);
60 }
61
62
63
64
65
66
67 void
68 do_cl_join_announce(long long action,
69 enum crmd_fsa_cause cause,
70 enum crmd_fsa_state cur_state,
71 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
72 {
73
74 if (cur_state != S_PENDING) {
75 crm_warn("Not announcing cluster join because in state %s",
76 fsa_state2string(cur_state));
77 return;
78 }
79
80 if (!pcmk_is_set(controld_globals.fsa_input_register, R_STARTING)) {
81
82 xmlNode *req = create_request(CRM_OP_JOIN_ANNOUNCE, NULL, NULL,
83 CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
84
85 crm_debug("Announcing availability");
86 update_dc(NULL);
87 pcmk__cluster_send_message(NULL, crm_msg_crmd, req);
88 free_xml(req);
89
90 } else {
91
92 crm_warn("Delaying announce of cluster join until local startup is complete");
93 return;
94 }
95 }
96
97 static int query_call_id = 0;
98
99
100
101 void
102 do_cl_join_offer_respond(long long action,
103 enum crmd_fsa_cause cause,
104 enum crmd_fsa_state cur_state,
105 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
106 {
107 cib_t *cib_conn = controld_globals.cib_conn;
108
109 ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
110 const char *welcome_from;
111 const char *join_id;
112
113 CRM_CHECK(input != NULL, return);
114
115 welcome_from = crm_element_value(input->msg, PCMK__XA_SRC);
116 join_id = crm_element_value(input->msg, PCMK__XA_JOIN_ID);
117 crm_trace("Accepting cluster join offer from node %s "CRM_XS" join-%s",
118 welcome_from, crm_element_value(input->msg, PCMK__XA_JOIN_ID));
119
120
121 if (query_call_id > 0) {
122 crm_trace("Cancelling previous join query: %d", query_call_id);
123 remove_cib_op_callback(query_call_id, FALSE);
124 query_call_id = 0;
125 }
126
127 if (update_dc(input->msg) == FALSE) {
128 crm_warn("Discarding cluster join offer from node %s (expected %s)",
129 welcome_from, controld_globals.dc_name);
130 return;
131 }
132
133 update_dc_expected(input->msg);
134
135 query_call_id = cib_conn->cmds->query(cib_conn, NULL, NULL,
136 cib_scope_local|cib_no_children);
137 fsa_register_cib_callback(query_call_id, pcmk__str_copy(join_id),
138 join_query_callback);
139 crm_trace("Registered join query callback: %d", query_call_id);
140
141 controld_set_fsa_action_flags(A_DC_TIMER_STOP);
142 controld_trigger_fsa();
143 }
144
145 void
146 join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
147 {
148 char *join_id = user_data;
149 xmlNode *generation = pcmk__xe_create(NULL, PCMK__XE_GENERATION_TUPLE);
150
151 CRM_LOG_ASSERT(join_id != NULL);
152
153 if (query_call_id != call_id) {
154 crm_trace("Query %d superseded", call_id);
155 goto done;
156 }
157
158 query_call_id = 0;
159 if(rc != pcmk_ok || output == NULL) {
160 crm_err("Could not retrieve version details for join-%s: %s (%d)",
161 join_id, pcmk_strerror(rc), rc);
162 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __func__);
163
164 } else if (controld_globals.dc_name == NULL) {
165 crm_debug("Membership is in flux, not continuing join-%s", join_id);
166
167 } else {
168 xmlNode *reply = NULL;
169 const crm_node_t *dc_node =
170 pcmk__get_node(0, controld_globals.dc_name, NULL,
171 pcmk__node_search_cluster_member);
172
173 crm_debug("Respond to join offer join-%s from %s",
174 join_id, controld_globals.dc_name);
175 pcmk__xe_copy_attrs(generation, output, pcmk__xaf_none);
176
177 reply = create_request(CRM_OP_JOIN_REQUEST, generation,
178 controld_globals.dc_name, CRM_SYSTEM_DC,
179 CRM_SYSTEM_CRMD, NULL);
180
181 crm_xml_add(reply, PCMK__XA_JOIN_ID, join_id);
182 crm_xml_add(reply, PCMK_XA_CRM_FEATURE_SET, CRM_FEATURE_SET);
183 pcmk__cluster_send_message(dc_node, crm_msg_crmd, reply);
184 free_xml(reply);
185 }
186
187 done:
188 free_xml(generation);
189 }
190
191 void
192 set_join_state(const char *start_state, const char *node_name, const char *node_uuid,
193 bool remote)
194 {
195 if (pcmk__str_eq(start_state, PCMK_VALUE_STANDBY, pcmk__str_casei)) {
196 crm_notice("Forcing node %s to join in %s state per configured "
197 "environment", node_name, start_state);
198 cib__update_node_attr(controld_globals.logger_out,
199 controld_globals.cib_conn, cib_sync_call,
200 PCMK_XE_NODES, node_uuid,
201 NULL, NULL, NULL, PCMK_NODE_ATTR_STANDBY,
202 PCMK_VALUE_TRUE, NULL,
203 (remote? PCMK_VALUE_REMOTE : NULL));
204
205 } else if (pcmk__str_eq(start_state, PCMK_VALUE_ONLINE, pcmk__str_casei)) {
206 crm_notice("Forcing node %s to join in %s state per configured "
207 "environment", node_name, start_state);
208 cib__update_node_attr(controld_globals.logger_out,
209 controld_globals.cib_conn, cib_sync_call,
210 PCMK_XE_NODES, node_uuid,
211 NULL, NULL, NULL, PCMK_NODE_ATTR_STANDBY,
212 PCMK_VALUE_FALSE, NULL,
213 (remote? PCMK_VALUE_REMOTE : NULL));
214
215 } else if (pcmk__str_eq(start_state, PCMK_VALUE_DEFAULT, pcmk__str_casei)) {
216 crm_debug("Not forcing a starting state on node %s", node_name);
217
218 } else {
219 crm_warn("Unrecognized start state '%s', using "
220 "'" PCMK_VALUE_DEFAULT "' (%s)",
221 start_state, node_name);
222 }
223 }
224
225 static int
226 update_conn_host_cache(xmlNode *node, void *userdata)
227 {
228 const char *remote = crm_element_value(node, PCMK_XA_ID);
229 const char *conn_host = crm_element_value(node, PCMK__XA_CONNECTION_HOST);
230 const char *state = crm_element_value(node, PCMK__XA_NODE_STATE);
231
232 crm_node_t *remote_peer = pcmk__cluster_lookup_remote_node(remote);
233
234 if (remote_peer == NULL) {
235 return pcmk_rc_ok;
236 }
237
238 if (conn_host != NULL) {
239 pcmk__str_update(&remote_peer->conn_host, conn_host);
240 }
241
242 if (state != NULL) {
243 pcmk__update_peer_state(__func__, remote_peer, state, 0);
244 }
245
246 return pcmk_rc_ok;
247 }
248
249
250
251 void
252 do_cl_join_finalize_respond(long long action,
253 enum crmd_fsa_cause cause,
254 enum crmd_fsa_state cur_state,
255 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
256 {
257 xmlNode *tmp1 = NULL;
258 gboolean was_nack = TRUE;
259 static gboolean first_join = TRUE;
260 ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
261 const char *start_state = pcmk__env_option(PCMK__ENV_NODE_START_STATE);
262
263 int join_id = -1;
264 const char *op = crm_element_value(input->msg, PCMK__XA_CRM_TASK);
265 const char *welcome_from = crm_element_value(input->msg, PCMK__XA_SRC);
266
267 if (!pcmk__str_eq(op, CRM_OP_JOIN_ACKNAK, pcmk__str_casei)) {
268 crm_trace("Ignoring op=%s message", op);
269 return;
270 }
271
272
273 if (pcmk__xe_attr_is_true(input->msg, CRM_OP_JOIN_ACKNAK)) {
274 was_nack = FALSE;
275 }
276
277 crm_element_value_int(input->msg, PCMK__XA_JOIN_ID, &join_id);
278
279 if (was_nack) {
280 crm_err("Shutting down because cluster join with leader %s failed "
281 CRM_XS" join-%d NACK'd", welcome_from, join_id);
282 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
283 controld_set_fsa_input_flags(R_STAYDOWN);
284 return;
285 }
286
287 if (!AM_I_DC
288 && pcmk__str_eq(welcome_from, controld_globals.our_nodename,
289 pcmk__str_casei)) {
290 crm_warn("Discarding our own welcome - we're no longer the DC");
291 return;
292 }
293
294 if (update_dc(input->msg) == FALSE) {
295 crm_warn("Discarding %s from node %s (expected from %s)",
296 op, welcome_from, controld_globals.dc_name);
297 return;
298 }
299
300 update_dc_expected(input->msg);
301
302
303 update_attrd(controld_globals.our_nodename, CRM_ATTR_FEATURE_SET,
304 CRM_FEATURE_SET, NULL, FALSE);
305
306
307 tmp1 = controld_query_executor_state();
308 if (tmp1 != NULL) {
309 xmlNode *remotes = NULL;
310 xmlNode *reply = create_request(CRM_OP_JOIN_CONFIRM, tmp1,
311 controld_globals.dc_name, CRM_SYSTEM_DC,
312 CRM_SYSTEM_CRMD, NULL);
313 const crm_node_t *dc_node =
314 pcmk__get_node(0, controld_globals.dc_name, NULL,
315 pcmk__node_search_cluster_member);
316
317 crm_xml_add_int(reply, PCMK__XA_JOIN_ID, join_id);
318
319 crm_debug("Confirming join-%d: sending local operation history to %s",
320 join_id, controld_globals.dc_name);
321
322
323
324
325
326
327
328
329
330
331
332
333
334 if (first_join
335 && !pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
336
337 first_join = FALSE;
338 if (start_state) {
339 set_join_state(start_state, controld_globals.our_nodename,
340 controld_globals.our_uuid, false);
341 }
342 }
343
344 pcmk__cluster_send_message(dc_node, crm_msg_crmd, reply);
345 free_xml(reply);
346
347 if (AM_I_DC == FALSE) {
348 register_fsa_input_adv(cause, I_NOT_DC, NULL, A_NOTHING, TRUE,
349 __func__);
350 }
351
352 free_xml(tmp1);
353
354
355
356
357 remotes = pcmk__xe_first_child(input->msg, PCMK_XE_NODES, NULL, NULL);
358 if (remotes != NULL) {
359 pcmk__xe_foreach_child(remotes, PCMK_XE_NODE,
360 update_conn_host_cache, NULL);
361 }
362
363 } else {
364 crm_err("Could not confirm join-%d with %s: Local operation history "
365 "failed", join_id, controld_globals.dc_name);
366 register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
367 }
368 }