This source file includes following definitions.
- init_scheduler
- handle_pecalc_request
- handle_unknown_request
- handle_hello_request
- schedulerd_register_handlers
- pe_ipc_accept
- pe_ipc_dispatch
- pe_ipc_closed
- pe_ipc_destroy
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/crm.h>
13 #include <crm/common/xml.h>
14 #include <pacemaker-internal.h>
15
16 #include <stdbool.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include "pacemaker-schedulerd.h"
22
23 static GHashTable *schedulerd_handlers = NULL;
24
25 static pcmk_scheduler_t *
26 init_scheduler(void)
27 {
28 pcmk_scheduler_t *scheduler = pcmk_new_scheduler();
29
30 pcmk__mem_assert(scheduler);
31 scheduler->priv->out = logger_out;
32 return scheduler;
33 }
34
35 static xmlNode *
36 handle_pecalc_request(pcmk__request_t *request)
37 {
38 static struct series_s {
39 const char *name;
40 const char *param;
41
42
43
44
45 int wrap;
46 } series[] = {
47 { "pe-error", PCMK_OPT_PE_ERROR_SERIES_MAX, -1 },
48 { "pe-warn", PCMK_OPT_PE_WARN_SERIES_MAX, 5000 },
49 { "pe-input", PCMK_OPT_PE_INPUT_SERIES_MAX, 4000 },
50 };
51
52 xmlNode *msg = request->xml;
53 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CRM_XML, NULL, NULL);
54 xmlNode *xml_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
55
56 static char *last_digest = NULL;
57 static char *filename = NULL;
58
59 unsigned int seq = 0U;
60 int series_id = 0;
61 int series_wrap = 0;
62 char *digest = NULL;
63 const char *value = NULL;
64 time_t execution_date = time(NULL);
65 xmlNode *converted = NULL;
66 xmlNode *reply = NULL;
67 bool is_repoke = false;
68 bool process = true;
69 pcmk_scheduler_t *scheduler = init_scheduler();
70
71 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
72 PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
73
74 digest = pcmk__digest_xml(xml_data, false);
75 converted = pcmk__xml_copy(NULL, xml_data);
76 if (pcmk__update_configured_schema(&converted, true) != pcmk_rc_ok) {
77 scheduler->priv->graph = pcmk__xe_create(NULL,
78 PCMK__XE_TRANSITION_GRAPH);
79 crm_xml_add_int(scheduler->priv->graph, "transition_id", 0);
80 crm_xml_add_int(scheduler->priv->graph, PCMK_OPT_CLUSTER_DELAY, 0);
81 process = false;
82 free(digest);
83
84 } else if (pcmk__str_eq(digest, last_digest, pcmk__str_casei)) {
85 is_repoke = true;
86 free(digest);
87
88 } else {
89 free(last_digest);
90 last_digest = digest;
91 }
92
93 if (process) {
94 scheduler->input = converted;
95 pcmk__set_scheduler_flags(scheduler,
96 pcmk__sched_no_counts
97 |pcmk__sched_show_utilization);
98 pcmk__schedule_actions(scheduler);
99
100
101 scheduler->input = NULL;
102 }
103
104
105 if (pcmk_is_set(scheduler->flags, pcmk__sched_processing_error)
106 || pcmk__config_has_error) {
107 series_id = 0;
108 } else if (pcmk_is_set(scheduler->flags, pcmk__sched_processing_warning)
109 || pcmk__config_has_warning) {
110 series_id = 1;
111 } else {
112 series_id = 2;
113 }
114
115 value = pcmk__cluster_option(scheduler->priv->options,
116 series[series_id].param);
117 if ((value == NULL)
118 || (pcmk__scan_min_int(value, &series_wrap, -1) != pcmk_rc_ok)) {
119 series_wrap = series[series_id].wrap;
120 }
121
122 if (pcmk__read_series_sequence(PCMK_SCHEDULER_INPUT_DIR, series[series_id].name,
123 &seq) != pcmk_rc_ok) {
124
125 seq = 0U;
126 }
127 crm_trace("Series %s: wrap=%d, seq=%u, pref=%s",
128 series[series_id].name, series_wrap, seq, value);
129
130 reply = pcmk__new_reply(msg, scheduler->priv->graph);
131
132 if (reply == NULL) {
133 pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
134 "Failed building ping reply for client %s",
135 pcmk__client_name(request->ipc_client));
136 goto done;
137 }
138
139 if (series_wrap == 0) {
140 free(filename);
141 filename = NULL;
142
143 } else if (!is_repoke) {
144 free(filename);
145 filename = pcmk__series_filename(PCMK_SCHEDULER_INPUT_DIR,
146 series[series_id].name, seq, true);
147 }
148
149 crm_xml_add(reply, PCMK__XA_CRM_TGRAPH_IN, filename);
150
151 pcmk__log_transition_summary(scheduler, filename);
152
153 if (series_wrap == 0) {
154 crm_debug("Not saving input to disk (disabled by configuration)");
155
156 } else if (is_repoke) {
157 crm_info("Input has not changed since last time, not saving to disk");
158
159 } else {
160 unlink(filename);
161 crm_xml_add_ll(xml_data, PCMK_XA_EXECUTION_DATE,
162 (long long) execution_date);
163 pcmk__xml_write_file(xml_data, filename, true);
164 pcmk__write_series_sequence(PCMK_SCHEDULER_INPUT_DIR, series[series_id].name,
165 ++seq, series_wrap);
166 }
167
168 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
169
170 done:
171 pcmk__xml_free(converted);
172 pcmk_free_scheduler(scheduler);
173
174 return reply;
175 }
176
177 static xmlNode *
178 handle_unknown_request(pcmk__request_t *request)
179 {
180 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
181 PCMK__XE_ACK, NULL, CRM_EX_INVALID_PARAM);
182
183 pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
184 "Unknown IPC request type '%s' (bug?)",
185 pcmk__client_name(request->ipc_client));
186 return NULL;
187 }
188
189 static xmlNode *
190 handle_hello_request(pcmk__request_t *request)
191 {
192 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
193 PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
194
195 crm_trace("Received IPC hello from %s", pcmk__client_name(request->ipc_client));
196
197 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
198 return NULL;
199 }
200
201 static void
202 schedulerd_register_handlers(void)
203 {
204 pcmk__server_command_t handlers[] = {
205 { CRM_OP_HELLO, handle_hello_request },
206 { CRM_OP_PECALC, handle_pecalc_request },
207 { NULL, handle_unknown_request },
208 };
209
210 schedulerd_handlers = pcmk__register_handlers(handlers);
211 }
212
213 static int32_t
214 pe_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
215 {
216 crm_trace("Connection %p", c);
217 if (pcmk__new_client(c, uid, gid) == NULL) {
218 return -ENOMEM;
219 }
220 return 0;
221 }
222
223 static int32_t
224 pe_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
225 {
226 int rc = pcmk_rc_ok;
227 uint32_t id = 0;
228 uint32_t flags = 0;
229 xmlNode *msg = NULL;
230 pcmk__client_t *c = pcmk__find_client(qbc);
231 const char *sys_to = NULL;
232
233 CRM_CHECK(c != NULL, return 0);
234
235 if (schedulerd_handlers == NULL) {
236 schedulerd_register_handlers();
237 }
238
239 rc = pcmk__ipc_msg_append(&c->buffer, data);
240
241 if (rc == pcmk_rc_ipc_more) {
242
243 return 0;
244
245 } else if (rc == pcmk_rc_ok) {
246
247
248
249 msg = pcmk__client_data2xml(c, &id, &flags);
250 g_byte_array_free(c->buffer, TRUE);
251 c->buffer = NULL;
252
253 } else {
254
255
256
257 crm_err("Error when reading IPC message: %s", pcmk_rc_str(rc));
258
259 if (c->buffer != NULL) {
260 g_byte_array_free(c->buffer, TRUE);
261 c->buffer = NULL;
262 }
263
264 return 0;
265 }
266
267 if (msg == NULL) {
268 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL);
269 return 0;
270 }
271
272 sys_to = crm_element_value(msg, PCMK__XA_CRM_SYS_TO);
273
274 if (pcmk__str_eq(crm_element_value(msg, PCMK__XA_SUBT),
275 PCMK__VALUE_RESPONSE, pcmk__str_none)) {
276 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL,
277 CRM_EX_INDETERMINATE);
278 crm_info("Ignoring IPC reply from %s", pcmk__client_name(c));
279
280 } else if (!pcmk__str_eq(sys_to, CRM_SYSTEM_PENGINE, pcmk__str_none)) {
281 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL,
282 CRM_EX_INDETERMINATE);
283 crm_info("Ignoring invalid IPC message: to '%s' not "
284 CRM_SYSTEM_PENGINE, pcmk__s(sys_to, ""));
285
286 } else {
287 char *log_msg = NULL;
288 const char *reason = NULL;
289 xmlNode *reply = NULL;
290
291 pcmk__request_t request = {
292 .ipc_client = c,
293 .ipc_id = id,
294 .ipc_flags = flags,
295 .peer = NULL,
296 .xml = msg,
297 .call_options = 0,
298 .result = PCMK__UNKNOWN_RESULT,
299 };
300
301 request.op = crm_element_value_copy(request.xml, PCMK__XA_CRM_TASK);
302 CRM_CHECK(request.op != NULL, return 0);
303
304 reply = pcmk__process_request(&request, schedulerd_handlers);
305
306 if (reply != NULL) {
307 pcmk__ipc_send_xml(c, id, reply, crm_ipc_server_event);
308 pcmk__xml_free(reply);
309 }
310
311 reason = request.result.exit_reason;
312
313 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
314 request.op, pcmk__request_origin_type(&request),
315 pcmk__request_origin(&request),
316 pcmk_exec_status_str(request.result.execution_status),
317 (reason == NULL)? "" : " (",
318 (reason == NULL)? "" : reason,
319 (reason == NULL)? "" : ")");
320
321 if (!pcmk__result_ok(&request.result)) {
322 crm_warn("%s", log_msg);
323 } else {
324 crm_debug("%s", log_msg);
325 }
326
327 free(log_msg);
328 pcmk__reset_request(&request);
329 }
330
331 pcmk__xml_free(msg);
332 return 0;
333 }
334
335
336 static int32_t
337 pe_ipc_closed(qb_ipcs_connection_t * c)
338 {
339 pcmk__client_t *client = pcmk__find_client(c);
340
341 if (client == NULL) {
342 return 0;
343 }
344 crm_trace("Connection %p", c);
345 pcmk__free_client(client);
346 return 0;
347 }
348
349 static void
350 pe_ipc_destroy(qb_ipcs_connection_t * c)
351 {
352 crm_trace("Connection %p", c);
353 pe_ipc_closed(c);
354 }
355
356 struct qb_ipcs_service_handlers ipc_callbacks = {
357 .connection_accept = pe_ipc_accept,
358 .connection_created = NULL,
359 .msg_process = pe_ipc_dispatch,
360 .connection_closed = pe_ipc_closed,
361 .connection_destroyed = pe_ipc_destroy
362 };