This source file includes following definitions.
- pe_subsystem_free
- save_cib_contents
- pe_ipc_destroy
- pe_ipc_dispatch
- pe_subsystem_new
- pe_subsystem_send
- do_pe_control
- controld_sched_timeout
- controld_stop_sched_timer
- controld_expect_sched_reply
- controld_free_sched_timer
- do_pe_invoke
- force_local_option
- do_pe_invoke_callback
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <unistd.h>
13
14 #include <crm/cib.h>
15 #include <crm/cluster.h>
16 #include <crm/common/xml.h>
17 #include <crm/crm.h>
18 #include <crm/msg_xml.h>
19 #include <crm/common/xml_internal.h>
20
21 #include <pacemaker-controld.h>
22
23 static mainloop_io_t *pe_subsystem = NULL;
24
25
26
27
28
29 void
30 pe_subsystem_free(void)
31 {
32 controld_clear_fsa_input_flags(R_PE_REQUIRED);
33 if (pe_subsystem) {
34 controld_expect_sched_reply(NULL);
35 mainloop_del_ipc_client(pe_subsystem);
36 pe_subsystem = NULL;
37 controld_clear_fsa_input_flags(R_PE_CONNECTED);
38 }
39 }
40
41
42
43
44
45
46
47
48
49
50
51
52
53 static void
54 save_cib_contents(xmlNode *msg, int call_id, int rc, xmlNode *output,
55 void *user_data)
56 {
57 char *id = user_data;
58
59 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __func__);
60 CRM_CHECK(id != NULL, return);
61
62 if (rc == pcmk_ok) {
63 char *filename = crm_strdup_printf(PE_STATE_DIR "/pe-core-%s.bz2", id);
64
65 if (write_xml_file(output, filename, TRUE) < 0) {
66 crm_err("Could not save Cluster Information Base to %s after scheduler crash",
67 filename);
68 } else {
69 crm_notice("Saved Cluster Information Base to %s after scheduler crash",
70 filename);
71 }
72 free(filename);
73 }
74 }
75
76
77
78
79
80
81
82 static void
83 pe_ipc_destroy(gpointer user_data)
84 {
85
86 controld_expect_sched_reply(NULL);
87
88 if (pcmk_is_set(fsa_input_register, R_PE_REQUIRED)) {
89 int rc = pcmk_ok;
90 char *uuid_str = crm_generate_uuid();
91
92 crm_crit("Connection to the scheduler failed "
93 CRM_XS " uuid=%s", uuid_str);
94
95
96
97
98
99
100
101
102
103
104
105 rc = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local);
106 fsa_register_cib_callback(rc, FALSE, uuid_str, save_cib_contents);
107
108 } else {
109 crm_info("Connection to the scheduler released");
110 }
111
112 controld_clear_fsa_input_flags(R_PE_CONNECTED);
113 pe_subsystem = NULL;
114 mainloop_set_trigger(fsa_source);
115 return;
116 }
117
118
119
120
121
122
123
124
125
126
127
128 static int
129 pe_ipc_dispatch(const char *buffer, ssize_t length, gpointer userdata)
130 {
131 xmlNode *msg = string2xml(buffer);
132
133 if (msg) {
134 route_message(C_IPC_MESSAGE, msg);
135 }
136 free_xml(msg);
137 return 0;
138 }
139
140
141
142
143
144
145
146 static bool
147 pe_subsystem_new(void)
148 {
149 struct ipc_client_callbacks pe_callbacks = {
150 .dispatch = pe_ipc_dispatch,
151 .destroy = pe_ipc_destroy
152 };
153
154 controld_set_fsa_input_flags(R_PE_REQUIRED);
155 pe_subsystem = mainloop_add_ipc_client(CRM_SYSTEM_PENGINE,
156 G_PRIORITY_DEFAULT,
157 5 * 1024 * 1024 ,
158 NULL, &pe_callbacks);
159 if (pe_subsystem == NULL) {
160 return FALSE;
161 }
162 controld_set_fsa_input_flags(R_PE_CONNECTED);
163 return TRUE;
164 }
165
166
167
168
169
170
171
172
173
174 static int
175 pe_subsystem_send(xmlNode *cmd)
176 {
177 if (pe_subsystem) {
178 int sent = crm_ipc_send(mainloop_get_ipc_client(pe_subsystem), cmd,
179 0, 0, NULL);
180
181 if (sent == 0) {
182 sent = -ENODATA;
183 } else if (sent > 0) {
184 sent = pcmk_ok;
185 }
186 return sent;
187 }
188 return -ENOTCONN;
189 }
190
191 static void do_pe_invoke_callback(xmlNode *msg, int call_id, int rc,
192 xmlNode *output, void *user_data);
193
194
195 void
196 do_pe_control(long long action,
197 enum crmd_fsa_cause cause,
198 enum crmd_fsa_state cur_state,
199 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
200 {
201 if (action & A_PE_STOP) {
202 pe_subsystem_free();
203 }
204 if ((action & A_PE_START)
205 && !pcmk_is_set(fsa_input_register, R_PE_CONNECTED)) {
206
207 if (cur_state == S_STOPPING) {
208 crm_info("Ignoring request to connect to scheduler while shutting down");
209
210 } else if (!pe_subsystem_new()) {
211 crm_warn("Could not connect to scheduler");
212 register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
213 }
214 }
215 }
216
217 int fsa_pe_query = 0;
218 char *fsa_pe_ref = NULL;
219 static mainloop_timer_t *controld_sched_timer = NULL;
220
221
222 #define SCHED_TIMEOUT_MS (120000)
223
224
225
226
227
228
229
230
231
232 static gboolean
233 controld_sched_timeout(gpointer user_data)
234 {
235 if (AM_I_DC) {
236
237
238
239
240
241
242
243
244
245 crmd_exit(CRM_EX_FATAL);
246 }
247 return FALSE;
248 }
249
250 void
251 controld_stop_sched_timer(void)
252 {
253 if (controld_sched_timer && fsa_pe_ref) {
254 crm_trace("Stopping timer for scheduler reply %s", fsa_pe_ref);
255 }
256 mainloop_timer_stop(controld_sched_timer);
257 }
258
259
260
261
262
263
264
265 void
266 controld_expect_sched_reply(xmlNode *msg)
267 {
268 char *ref = NULL;
269
270 if (msg) {
271 ref = crm_element_value_copy(msg, XML_ATTR_REFERENCE);
272 CRM_ASSERT(ref != NULL);
273
274 if (controld_sched_timer == NULL) {
275 controld_sched_timer = mainloop_timer_add("scheduler_reply_timer",
276 SCHED_TIMEOUT_MS, FALSE,
277 controld_sched_timeout,
278 NULL);
279 }
280 mainloop_timer_start(controld_sched_timer);
281 } else {
282 controld_stop_sched_timer();
283 }
284 free(fsa_pe_ref);
285 fsa_pe_ref = ref;
286 }
287
288
289
290
291
292 void
293 controld_free_sched_timer(void)
294 {
295 if (controld_sched_timer != NULL) {
296 mainloop_timer_del(controld_sched_timer);
297 controld_sched_timer = NULL;
298 }
299 }
300
301
302 void
303 do_pe_invoke(long long action,
304 enum crmd_fsa_cause cause,
305 enum crmd_fsa_state cur_state,
306 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
307 {
308 if (AM_I_DC == FALSE) {
309 crm_err("Not invoking scheduler because not DC: %s",
310 fsa_action2string(action));
311 return;
312 }
313
314 if (!pcmk_is_set(fsa_input_register, R_PE_CONNECTED)) {
315 if (pcmk_is_set(fsa_input_register, R_SHUTDOWN)) {
316 crm_err("Cannot shut down gracefully without the scheduler");
317 register_fsa_input_before(C_FSA_INTERNAL, I_TERMINATE, NULL);
318
319 } else {
320 crm_info("Waiting for the scheduler to connect");
321 crmd_fsa_stall(FALSE);
322 controld_set_fsa_action_flags(A_PE_START);
323 trigger_fsa();
324 }
325 return;
326 }
327
328 if (cur_state != S_POLICY_ENGINE) {
329 crm_notice("Not invoking scheduler because in state %s",
330 fsa_state2string(cur_state));
331 return;
332 }
333 if (!pcmk_is_set(fsa_input_register, R_HAVE_CIB)) {
334 crm_err("Attempted to invoke scheduler without consistent Cluster Information Base!");
335
336
337 register_fsa_input_before(C_FSA_INTERNAL, I_ELECTION, NULL);
338 return;
339 }
340
341 fsa_pe_query = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local);
342
343 crm_debug("Query %d: Requesting the current CIB: %s", fsa_pe_query,
344 fsa_state2string(fsa_state));
345
346 controld_expect_sched_reply(NULL);
347 fsa_register_cib_callback(fsa_pe_query, FALSE, NULL, do_pe_invoke_callback);
348 }
349
350 static void
351 force_local_option(xmlNode *xml, const char *attr_name, const char *attr_value)
352 {
353 int max = 0;
354 int lpc = 0;
355 char *xpath_string = NULL;
356 xmlXPathObjectPtr xpathObj = NULL;
357
358 xpath_string = crm_strdup_printf("%.128s//%s//nvpair[@name='%.128s']",
359 get_object_path(XML_CIB_TAG_CRMCONFIG),
360 XML_CIB_TAG_PROPSET, attr_name);
361 xpathObj = xpath_search(xml, xpath_string);
362 max = numXpathResults(xpathObj);
363 free(xpath_string);
364
365 for (lpc = 0; lpc < max; lpc++) {
366 xmlNode *match = getXpathResult(xpathObj, lpc);
367 crm_trace("Forcing %s/%s = %s", ID(match), attr_name, attr_value);
368 crm_xml_add(match, XML_NVPAIR_ATTR_VALUE, attr_value);
369 }
370
371 if(max == 0) {
372 xmlNode *configuration = NULL;
373 xmlNode *crm_config = NULL;
374 xmlNode *cluster_property_set = NULL;
375
376 crm_trace("Creating %s-%s for %s=%s",
377 CIB_OPTIONS_FIRST, attr_name, attr_name, attr_value);
378
379 configuration = pcmk__xe_match(xml, XML_CIB_TAG_CONFIGURATION, NULL,
380 NULL);
381 if (configuration == NULL) {
382 configuration = create_xml_node(xml, XML_CIB_TAG_CONFIGURATION);
383 }
384
385 crm_config = pcmk__xe_match(configuration, XML_CIB_TAG_CRMCONFIG, NULL,
386 NULL);
387 if (crm_config == NULL) {
388 crm_config = create_xml_node(configuration, XML_CIB_TAG_CRMCONFIG);
389 }
390
391 cluster_property_set = pcmk__xe_match(crm_config, XML_CIB_TAG_PROPSET,
392 NULL, NULL);
393 if (cluster_property_set == NULL) {
394 cluster_property_set = create_xml_node(crm_config, XML_CIB_TAG_PROPSET);
395 crm_xml_add(cluster_property_set, XML_ATTR_ID, CIB_OPTIONS_FIRST);
396 }
397
398 xml = create_xml_node(cluster_property_set, XML_CIB_TAG_NVPAIR);
399
400 crm_xml_set_id(xml, "%s-%s", CIB_OPTIONS_FIRST, attr_name);
401 crm_xml_add(xml, XML_NVPAIR_ATTR_NAME, attr_name);
402 crm_xml_add(xml, XML_NVPAIR_ATTR_VALUE, attr_value);
403 }
404 freeXpathObject(xpathObj);
405 }
406
407 static void
408 do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
409 {
410 xmlNode *cmd = NULL;
411 pid_t watchdog = pcmk__locate_sbd();
412
413 if (rc != pcmk_ok) {
414 crm_err("Could not retrieve the Cluster Information Base: %s "
415 CRM_XS " rc=%d call=%d", pcmk_strerror(rc), rc, call_id);
416 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __func__);
417 return;
418
419 } else if (call_id != fsa_pe_query) {
420 crm_trace("Skipping superseded CIB query: %d (current=%d)", call_id, fsa_pe_query);
421 return;
422
423 } else if (!AM_I_DC || !pcmk_is_set(fsa_input_register, R_PE_CONNECTED)) {
424 crm_debug("No need to invoke the scheduler anymore");
425 return;
426
427 } else if (fsa_state != S_POLICY_ENGINE) {
428 crm_debug("Discarding scheduler request in state: %s",
429 fsa_state2string(fsa_state));
430 return;
431
432
433 } else if (num_cib_op_callbacks() > 1) {
434 crm_debug("Re-asking for the CIB: %d other peer updates still pending",
435 (num_cib_op_callbacks() - 1));
436 sleep(1);
437 controld_set_fsa_action_flags(A_PE_INVOKE);
438 trigger_fsa();
439 return;
440 }
441
442 CRM_LOG_ASSERT(output != NULL);
443
444
445
446 crm_peer_caches_refresh(output);
447
448 crm_xml_add(output, XML_ATTR_DC_UUID, fsa_our_uuid);
449 crm_xml_add_int(output, XML_ATTR_HAVE_QUORUM, fsa_has_quorum);
450
451 force_local_option(output, XML_ATTR_HAVE_WATCHDOG, pcmk__btoa(watchdog));
452
453 if (ever_had_quorum && crm_have_quorum == FALSE) {
454 crm_xml_add_int(output, XML_ATTR_QUORUM_PANIC, 1);
455 }
456
457 cmd = create_request(CRM_OP_PECALC, output, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_DC, NULL);
458
459 rc = pe_subsystem_send(cmd);
460 if (rc < 0) {
461 crm_err("Could not contact the scheduler: %s " CRM_XS " rc=%d",
462 pcmk_strerror(rc), rc);
463 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __func__);
464 } else {
465 controld_expect_sched_reply(cmd);
466 crm_debug("Invoking the scheduler: query=%d, ref=%s, seq=%llu, quorate=%d",
467 fsa_pe_query, fsa_pe_ref, crm_peer_seq, fsa_has_quorum);
468 }
469 free_xml(cmd);
470 }