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
- 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/msg_xml.h>
15 #include <crm/common/xml.h>
16
17 #include <pacemaker-controld.h>
18
19 int reannounce_count = 0;
20 void join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data);
21
22 extern ha_msg_input_t *copy_ha_msg_input(ha_msg_input_t * orig);
23
24
25
26
27
28
29
30
31
32
33
34 static void
35 update_dc_expected(xmlNode *msg)
36 {
37 if (fsa_our_dc && crm_is_true(crm_element_value(msg, F_CRM_DC_LEAVING))) {
38 crm_node_t *dc_node = crm_get_peer(0, fsa_our_dc);
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 send_cluster_message(NULL, crm_msg_crmd, req, FALSE);
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 (AM_I_OPERATIONAL) {
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 send_cluster_message(NULL, crm_msg_crmd, req, FALSE);
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 ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
108 const char *welcome_from;
109 const char *join_id;
110
111 CRM_CHECK(input != NULL, return);
112
113 #if 0
114 if (we are sick) {
115 log error;
116
117
118 return;
119 }
120 #endif
121
122 welcome_from = crm_element_value(input->msg, F_CRM_HOST_FROM);
123 join_id = crm_element_value(input->msg, F_CRM_JOIN_ID);
124 crm_trace("Accepting cluster join offer from node %s "CRM_XS" join-%s",
125 welcome_from, crm_element_value(input->msg, F_CRM_JOIN_ID));
126
127
128 if (query_call_id > 0) {
129 crm_trace("Cancelling previous join query: %d", query_call_id);
130 remove_cib_op_callback(query_call_id, FALSE);
131 query_call_id = 0;
132 }
133
134 if (update_dc(input->msg) == FALSE) {
135 crm_warn("Discarding cluster join offer from node %s (expected %s)",
136 welcome_from, fsa_our_dc);
137 return;
138 }
139
140 update_dc_expected(input->msg);
141
142 query_call_id =
143 fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local | cib_no_children);
144 fsa_register_cib_callback(query_call_id, FALSE, strdup(join_id), join_query_callback);
145 crm_trace("Registered join query callback: %d", query_call_id);
146
147 controld_set_fsa_action_flags(A_DC_TIMER_STOP);
148 trigger_fsa();
149 }
150
151 void
152 join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
153 {
154 char *join_id = user_data;
155 xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
156
157 CRM_LOG_ASSERT(join_id != NULL);
158
159 if (query_call_id != call_id) {
160 crm_trace("Query %d superseded", call_id);
161 goto done;
162 }
163
164 query_call_id = 0;
165 if(rc != pcmk_ok || output == NULL) {
166 crm_err("Could not retrieve version details for join-%s: %s (%d)",
167 join_id, pcmk_strerror(rc), rc);
168 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __func__);
169
170 } else if (fsa_our_dc == NULL) {
171 crm_debug("Membership is in flux, not continuing join-%s", join_id);
172
173 } else {
174 xmlNode *reply = NULL;
175
176 crm_debug("Respond to join offer join-%s from %s", join_id, fsa_our_dc);
177 copy_in_properties(generation, output);
178
179 reply = create_request(CRM_OP_JOIN_REQUEST, generation, fsa_our_dc,
180 CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
181
182 crm_xml_add(reply, F_CRM_JOIN_ID, join_id);
183 crm_xml_add(reply, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
184 send_cluster_message(crm_get_peer(0, fsa_our_dc), crm_msg_crmd, reply, TRUE);
185 free_xml(reply);
186 }
187
188 done:
189 free_xml(generation);
190 }
191
192 static void
193 set_join_state(const char * start_state)
194 {
195 if (pcmk__str_eq(start_state, "standby", pcmk__str_casei)) {
196 crm_notice("Forcing node %s to join in %s state per configured environment",
197 fsa_our_uname, start_state);
198 update_attr_delegate(fsa_cib_conn, cib_sync_call, XML_CIB_TAG_NODES, fsa_our_uuid,
199 NULL, NULL, NULL, "standby", "on", TRUE, NULL, NULL);
200
201 } else if (pcmk__str_eq(start_state, "online", pcmk__str_casei)) {
202 crm_notice("Forcing node %s to join in %s state per configured environment",
203 fsa_our_uname, start_state);
204 update_attr_delegate(fsa_cib_conn, cib_sync_call, XML_CIB_TAG_NODES, fsa_our_uuid,
205 NULL, NULL, NULL, "standby", "off", TRUE, NULL, NULL);
206
207 } else if (pcmk__str_eq(start_state, "default", pcmk__str_casei)) {
208 crm_debug("Not forcing a starting state on node %s", fsa_our_uname);
209
210 } else {
211 crm_warn("Unrecognized start state '%s', using 'default' (%s)",
212 start_state, fsa_our_uname);
213 }
214 }
215
216
217
218 void
219 do_cl_join_finalize_respond(long long action,
220 enum crmd_fsa_cause cause,
221 enum crmd_fsa_state cur_state,
222 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
223 {
224 xmlNode *tmp1 = NULL;
225 gboolean was_nack = TRUE;
226 static gboolean first_join = TRUE;
227 ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
228 const char *start_state = pcmk__env_option(PCMK__ENV_NODE_START_STATE);
229
230 int join_id = -1;
231 const char *op = crm_element_value(input->msg, F_CRM_TASK);
232 const char *ack_nack = crm_element_value(input->msg, CRM_OP_JOIN_ACKNAK);
233 const char *welcome_from = crm_element_value(input->msg, F_CRM_HOST_FROM);
234
235 if (!pcmk__str_eq(op, CRM_OP_JOIN_ACKNAK, pcmk__str_casei)) {
236 crm_trace("Ignoring op=%s message", op);
237 return;
238 }
239
240
241 if (crm_is_true(ack_nack)) {
242 was_nack = FALSE;
243 }
244
245 crm_element_value_int(input->msg, F_CRM_JOIN_ID, &join_id);
246
247 if (was_nack) {
248 crm_err("Shutting down because cluster join with leader %s failed "
249 CRM_XS" join-%d NACK'd", welcome_from, join_id);
250 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
251 return;
252 }
253
254 if (AM_I_DC == FALSE && pcmk__str_eq(welcome_from, fsa_our_uname, pcmk__str_casei)) {
255 crm_warn("Discarding our own welcome - we're no longer the DC");
256 return;
257 }
258
259 if (update_dc(input->msg) == FALSE) {
260 crm_warn("Discarding %s from node %s (expected from %s)",
261 op, welcome_from, fsa_our_dc);
262 return;
263 }
264
265 update_dc_expected(input->msg);
266
267
268 tmp1 = controld_query_executor_state(fsa_our_uname);
269 if (tmp1 != NULL) {
270 xmlNode *reply = create_request(CRM_OP_JOIN_CONFIRM, tmp1, fsa_our_dc,
271 CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
272
273 crm_xml_add_int(reply, F_CRM_JOIN_ID, join_id);
274
275 crm_debug("Confirming join-%d: sending local operation history to %s",
276 join_id, fsa_our_dc);
277
278
279
280
281
282
283
284
285
286
287
288
289
290 if (first_join && !pcmk_is_set(fsa_input_register, R_SHUTDOWN)) {
291 first_join = FALSE;
292 if (start_state) {
293 set_join_state(start_state);
294 }
295 }
296
297 send_cluster_message(crm_get_peer(0, fsa_our_dc), crm_msg_crmd, reply, TRUE);
298 free_xml(reply);
299
300 if (AM_I_DC == FALSE) {
301 register_fsa_input_adv(cause, I_NOT_DC, NULL, A_NOTHING, TRUE,
302 __func__);
303 }
304
305 free_xml(tmp1);
306
307 } else {
308 crm_err("Could not confirm join-%d with %s: Local operation history failed",
309 join_id, fsa_our_dc);
310 register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
311 }
312 }