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