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 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_working_set();
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 pcmk__schedule_actions(converted,
95 pcmk__sched_no_counts
96 |pcmk__sched_show_utilization, scheduler);
97 }
98
99
100 if (pcmk_is_set(scheduler->flags, pcmk__sched_processing_error)
101 || pcmk__config_has_error) {
102 series_id = 0;
103 } else if (pcmk_is_set(scheduler->flags, pcmk__sched_processing_warning)
104 || pcmk__config_has_warning) {
105 series_id = 1;
106 } else {
107 series_id = 2;
108 }
109
110 value = pcmk__cluster_option(scheduler->priv->options,
111 series[series_id].param);
112 if ((value == NULL)
113 || (pcmk__scan_min_int(value, &series_wrap, -1) != pcmk_rc_ok)) {
114 series_wrap = series[series_id].wrap;
115 }
116
117 if (pcmk__read_series_sequence(PCMK_SCHEDULER_INPUT_DIR, series[series_id].name,
118 &seq) != pcmk_rc_ok) {
119
120 seq = 0U;
121 }
122 crm_trace("Series %s: wrap=%d, seq=%u, pref=%s",
123 series[series_id].name, series_wrap, seq, value);
124
125 scheduler->input = NULL;
126 reply = pcmk__new_reply(msg, scheduler->priv->graph);
127
128 if (reply == NULL) {
129 pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
130 "Failed building ping reply for client %s",
131 pcmk__client_name(request->ipc_client));
132 goto done;
133 }
134
135 if (series_wrap == 0) {
136 free(filename);
137 filename = NULL;
138
139 } else if (!is_repoke) {
140 free(filename);
141 filename = pcmk__series_filename(PCMK_SCHEDULER_INPUT_DIR,
142 series[series_id].name, seq, true);
143 }
144
145 crm_xml_add(reply, PCMK__XA_CRM_TGRAPH_IN, filename);
146
147 pcmk__log_transition_summary(scheduler, filename);
148
149 if (series_wrap == 0) {
150 crm_debug("Not saving input to disk (disabled by configuration)");
151
152 } else if (is_repoke) {
153 crm_info("Input has not changed since last time, not saving to disk");
154
155 } else {
156 unlink(filename);
157 crm_xml_add_ll(xml_data, PCMK_XA_EXECUTION_DATE,
158 (long long) execution_date);
159 pcmk__xml_write_file(xml_data, filename, true);
160 pcmk__write_series_sequence(PCMK_SCHEDULER_INPUT_DIR, series[series_id].name,
161 ++seq, series_wrap);
162 }
163
164 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
165
166 done:
167 pcmk__xml_free(converted);
168 pe_free_working_set(scheduler);
169
170 return reply;
171 }
172
173 static xmlNode *
174 handle_unknown_request(pcmk__request_t *request)
175 {
176 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
177 PCMK__XE_ACK, NULL, CRM_EX_INVALID_PARAM);
178
179 pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
180 "Unknown IPC request type '%s' (bug?)",
181 pcmk__client_name(request->ipc_client));
182 return NULL;
183 }
184
185 static xmlNode *
186 handle_hello_request(pcmk__request_t *request)
187 {
188 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
189 PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
190
191 crm_trace("Received IPC hello from %s", pcmk__client_name(request->ipc_client));
192
193 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
194 return NULL;
195 }
196
197 static void
198 schedulerd_register_handlers(void)
199 {
200 pcmk__server_command_t handlers[] = {
201 { CRM_OP_HELLO, handle_hello_request },
202 { CRM_OP_PECALC, handle_pecalc_request },
203 { NULL, handle_unknown_request },
204 };
205
206 schedulerd_handlers = pcmk__register_handlers(handlers);
207 }
208
209 static int32_t
210 pe_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
211 {
212 crm_trace("Connection %p", c);
213 if (pcmk__new_client(c, uid, gid) == NULL) {
214 return -ENOMEM;
215 }
216 return 0;
217 }
218
219 static int32_t
220 pe_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
221 {
222 uint32_t id = 0;
223 uint32_t flags = 0;
224 xmlNode *msg = NULL;
225 pcmk__client_t *c = pcmk__find_client(qbc);
226 const char *sys_to = NULL;
227
228 CRM_CHECK(c != NULL, return 0);
229
230 if (schedulerd_handlers == NULL) {
231 schedulerd_register_handlers();
232 }
233
234 msg = pcmk__client_data2xml(c, data, &id, &flags);
235 if (msg == NULL) {
236 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL);
237 return 0;
238 }
239
240 sys_to = crm_element_value(msg, PCMK__XA_CRM_SYS_TO);
241
242 if (pcmk__str_eq(crm_element_value(msg, PCMK__XA_SUBT),
243 PCMK__VALUE_RESPONSE, pcmk__str_none)) {
244 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL,
245 CRM_EX_INDETERMINATE);
246 crm_info("Ignoring IPC reply from %s", pcmk__client_name(c));
247
248 } else if (!pcmk__str_eq(sys_to, CRM_SYSTEM_PENGINE, pcmk__str_none)) {
249 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL,
250 CRM_EX_INDETERMINATE);
251 crm_info("Ignoring invalid IPC message: to '%s' not "
252 CRM_SYSTEM_PENGINE, pcmk__s(sys_to, ""));
253
254 } else {
255 char *log_msg = NULL;
256 const char *reason = NULL;
257 xmlNode *reply = NULL;
258
259 pcmk__request_t request = {
260 .ipc_client = c,
261 .ipc_id = id,
262 .ipc_flags = flags,
263 .peer = NULL,
264 .xml = msg,
265 .call_options = 0,
266 .result = PCMK__UNKNOWN_RESULT,
267 };
268
269 request.op = crm_element_value_copy(request.xml, PCMK__XA_CRM_TASK);
270 CRM_CHECK(request.op != NULL, return 0);
271
272 reply = pcmk__process_request(&request, schedulerd_handlers);
273
274 if (reply != NULL) {
275 pcmk__ipc_send_xml(c, id, reply, crm_ipc_server_event);
276 pcmk__xml_free(reply);
277 }
278
279 reason = request.result.exit_reason;
280
281 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
282 request.op, pcmk__request_origin_type(&request),
283 pcmk__request_origin(&request),
284 pcmk_exec_status_str(request.result.execution_status),
285 (reason == NULL)? "" : " (",
286 (reason == NULL)? "" : reason,
287 (reason == NULL)? "" : ")");
288
289 if (!pcmk__result_ok(&request.result)) {
290 crm_warn("%s", log_msg);
291 } else {
292 crm_debug("%s", log_msg);
293 }
294
295 free(log_msg);
296 pcmk__reset_request(&request);
297 }
298
299 pcmk__xml_free(msg);
300 return 0;
301 }
302
303
304 static int32_t
305 pe_ipc_closed(qb_ipcs_connection_t * c)
306 {
307 pcmk__client_t *client = pcmk__find_client(c);
308
309 if (client == NULL) {
310 return 0;
311 }
312 crm_trace("Connection %p", c);
313 pcmk__free_client(client);
314 return 0;
315 }
316
317 static void
318 pe_ipc_destroy(qb_ipcs_connection_t * c)
319 {
320 crm_trace("Connection %p", c);
321 pe_ipc_closed(c);
322 }
323
324 struct qb_ipcs_service_handlers ipc_callbacks = {
325 .connection_accept = pe_ipc_accept,
326 .connection_created = NULL,
327 .msg_process = pe_ipc_dispatch,
328 .connection_closed = pe_ipc_closed,
329 .connection_destroyed = pe_ipc_destroy
330 };