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