This source file includes following definitions.
- save_cib_contents
- pe_ipc_destroy
- pe_ipc_dispatch
- do_pe_control
- do_pe_invoke
- force_local_option
- do_pe_invoke_callback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20
21 #include <unistd.h>
22
23 #include <crm/cib.h>
24 #include <crm/cluster.h>
25 #include <crm/common/xml.h>
26 #include <crm/crm.h>
27 #include <crm/msg_xml.h>
28
29 #include <crmd.h>
30 #include <crmd_fsa.h>
31 #include <crmd_messages.h>
32
33
34 struct crm_subsystem_s *pe_subsystem = NULL;
35 void do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data);
36
37 static void
38 save_cib_contents(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
39 {
40 char *id = user_data;
41
42 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
43 CRM_CHECK(id != NULL, return);
44
45 if (rc == pcmk_ok) {
46 int len = 15;
47 char *filename = NULL;
48
49 len += strlen(id);
50 len += strlen(PE_STATE_DIR);
51
52 filename = calloc(1, len);
53 CRM_CHECK(filename != NULL, return);
54
55 sprintf(filename, PE_STATE_DIR "/pe-core-%s.bz2", id);
56 if (write_xml_file(output, filename, TRUE) < 0) {
57 crm_err("Could not save Cluster Information Base to %s after Policy Engine crash",
58 filename);
59 } else {
60 crm_notice("Saved Cluster Information Base to %s after Policy Engine crash",
61 filename);
62 }
63
64 free(filename);
65 }
66 }
67
68 static void
69 pe_ipc_destroy(gpointer user_data)
70 {
71 if (is_set(fsa_input_register, pe_subsystem->flag_required)) {
72 int rc = pcmk_ok;
73 char *uuid_str = crm_generate_uuid();
74
75 crm_crit("Connection to the Policy Engine failed "
76 CRM_XS " pid=%d uuid=%s", pe_subsystem->pid, uuid_str);
77
78
79
80
81
82
83
84
85
86
87
88 rc = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local);
89 fsa_register_cib_callback(rc, FALSE, uuid_str, save_cib_contents);
90
91 } else {
92 if (is_heartbeat_cluster()) {
93 stop_subsystem(pe_subsystem, FALSE);
94 }
95 crm_info("Connection to the Policy Engine released");
96 }
97
98 clear_bit(fsa_input_register, pe_subsystem->flag_connected);
99 pe_subsystem->pid = -1;
100 pe_subsystem->source = NULL;
101 pe_subsystem->client = NULL;
102
103 mainloop_set_trigger(fsa_source);
104 return;
105 }
106
107 static int
108 pe_ipc_dispatch(const char *buffer, ssize_t length, gpointer userdata)
109 {
110 xmlNode *msg = string2xml(buffer);
111
112 if (msg) {
113 route_message(C_IPC_MESSAGE, msg);
114 }
115
116 free_xml(msg);
117 return 0;
118 }
119
120
121 void
122 do_pe_control(long long action,
123 enum crmd_fsa_cause cause,
124 enum crmd_fsa_state cur_state,
125 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
126 {
127 struct crm_subsystem_s *this_subsys = pe_subsystem;
128
129 long long stop_actions = A_PE_STOP;
130 long long start_actions = A_PE_START;
131
132 static struct ipc_client_callbacks pe_callbacks = {
133 .dispatch = pe_ipc_dispatch,
134 .destroy = pe_ipc_destroy
135 };
136
137 if (action & stop_actions) {
138 clear_bit(fsa_input_register, pe_subsystem->flag_required);
139
140 mainloop_del_ipc_client(pe_subsystem->source);
141 pe_subsystem->source = NULL;
142
143 clear_bit(fsa_input_register, pe_subsystem->flag_connected);
144 }
145
146 if ((action & start_actions) && (is_set(fsa_input_register, R_PE_CONNECTED) == FALSE)) {
147 if (cur_state != S_STOPPING) {
148 set_bit(fsa_input_register, pe_subsystem->flag_required);
149
150 pe_subsystem->source =
151 mainloop_add_ipc_client(CRM_SYSTEM_PENGINE, G_PRIORITY_DEFAULT,
152 5 * 1024 * 1024 , NULL, &pe_callbacks);
153
154 if (pe_subsystem->source == NULL) {
155 crm_warn("Setup of client connection failed, not adding channel to mainloop");
156 register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
157 return;
158 }
159
160
161
162
163
164 set_bit(fsa_input_register, pe_subsystem->flag_connected);
165
166 } else {
167 crm_info("Ignoring request to start %s while shutting down", this_subsys->name);
168 }
169 }
170 }
171
172 int fsa_pe_query = 0;
173 char *fsa_pe_ref = NULL;
174
175
176 void
177 do_pe_invoke(long long action,
178 enum crmd_fsa_cause cause,
179 enum crmd_fsa_state cur_state,
180 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
181 {
182 if (AM_I_DC == FALSE) {
183 crm_err("Not invoking Policy Engine because not DC: %s",
184 fsa_action2string(action));
185 return;
186 }
187
188 if (is_set(fsa_input_register, R_PE_CONNECTED) == FALSE) {
189 if (is_set(fsa_input_register, R_SHUTDOWN)) {
190 crm_err("Cannot shut down gracefully without the Policy Engine");
191 register_fsa_input_before(C_FSA_INTERNAL, I_TERMINATE, NULL);
192
193 } else {
194 crm_info("Waiting for the Policy Engine to connect");
195 crmd_fsa_stall(FALSE);
196 register_fsa_action(A_PE_START);
197 }
198 return;
199 }
200
201 if (cur_state != S_POLICY_ENGINE) {
202 crm_notice("Not invoking Policy Engine because in state %s",
203 fsa_state2string(cur_state));
204 return;
205 }
206 if (is_set(fsa_input_register, R_HAVE_CIB) == FALSE) {
207 crm_err("Attempted to invoke Policy Engine without consistent Cluster Information Base!");
208
209
210 register_fsa_input_before(C_FSA_INTERNAL, I_ELECTION, NULL);
211 return;
212 }
213
214 fsa_pe_query = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local);
215
216 crm_debug("Query %d: Requesting the current CIB: %s", fsa_pe_query,
217 fsa_state2string(fsa_state));
218
219
220 free(fsa_pe_ref);
221 fsa_pe_ref = NULL;
222
223 fsa_register_cib_callback(fsa_pe_query, FALSE, NULL, do_pe_invoke_callback);
224 }
225
226 static void
227 force_local_option(xmlNode *xml, const char *attr_name, const char *attr_value)
228 {
229 int max = 0;
230 int lpc = 0;
231 int xpath_max = 1024;
232 char *xpath_string = NULL;
233 xmlXPathObjectPtr xpathObj = NULL;
234
235 xpath_string = calloc(1, xpath_max);
236 lpc = snprintf(xpath_string, xpath_max, "%.128s//%s//nvpair[@name='%.128s']",
237 get_object_path(XML_CIB_TAG_CRMCONFIG), XML_CIB_TAG_PROPSET, attr_name);
238 CRM_LOG_ASSERT(lpc > 0);
239
240 xpathObj = xpath_search(xml, xpath_string);
241 max = numXpathResults(xpathObj);
242 free(xpath_string);
243
244 for (lpc = 0; lpc < max; lpc++) {
245 xmlNode *match = getXpathResult(xpathObj, lpc);
246 crm_trace("Forcing %s/%s = %s", ID(match), attr_name, attr_value);
247 crm_xml_add(match, XML_NVPAIR_ATTR_VALUE, attr_value);
248 }
249
250 if(max == 0) {
251 xmlNode *configuration = NULL;
252 xmlNode *crm_config = NULL;
253 xmlNode *cluster_property_set = NULL;
254
255 crm_trace("Creating %s-%s for %s=%s",
256 CIB_OPTIONS_FIRST, attr_name, attr_name, attr_value);
257
258 configuration = find_entity(xml, XML_CIB_TAG_CONFIGURATION, NULL);
259 if (configuration == NULL) {
260 configuration = create_xml_node(xml, XML_CIB_TAG_CONFIGURATION);
261 }
262
263 crm_config = find_entity(configuration, XML_CIB_TAG_CRMCONFIG, NULL);
264 if (crm_config == NULL) {
265 crm_config = create_xml_node(configuration, XML_CIB_TAG_CRMCONFIG);
266 }
267
268 cluster_property_set = find_entity(crm_config, XML_CIB_TAG_PROPSET, NULL);
269 if (cluster_property_set == NULL) {
270 cluster_property_set = create_xml_node(crm_config, XML_CIB_TAG_PROPSET);
271 crm_xml_add(cluster_property_set, XML_ATTR_ID, CIB_OPTIONS_FIRST);
272 }
273
274 xml = create_xml_node(cluster_property_set, XML_CIB_TAG_NVPAIR);
275
276 crm_xml_set_id(xml, "%s-%s", CIB_OPTIONS_FIRST, attr_name);
277 crm_xml_add(xml, XML_NVPAIR_ATTR_NAME, attr_name);
278 crm_xml_add(xml, XML_NVPAIR_ATTR_VALUE, attr_value);
279 }
280 freeXpathObject(xpathObj);
281 }
282
283 void
284 do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
285 {
286 int sent;
287 xmlNode *cmd = NULL;
288 pid_t watchdog = pcmk_locate_sbd();
289
290 if (rc != pcmk_ok) {
291 crm_err("Could not retrieve the Cluster Information Base: %s "
292 CRM_XS " call=%d", pcmk_strerror(rc), call_id);
293 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
294 return;
295
296 } else if (call_id != fsa_pe_query) {
297 crm_trace("Skipping superseded CIB query: %d (current=%d)", call_id, fsa_pe_query);
298 return;
299
300 } else if (AM_I_DC == FALSE || is_set(fsa_input_register, R_PE_CONNECTED) == FALSE) {
301 crm_debug("No need to invoke the PE anymore");
302 return;
303
304 } else if (fsa_state != S_POLICY_ENGINE) {
305 crm_debug("Discarding PE request in state: %s", fsa_state2string(fsa_state));
306 return;
307
308
309 } else if (num_cib_op_callbacks() > 1) {
310 crm_debug("Re-asking for the CIB: %d other peer updates still pending",
311 (num_cib_op_callbacks() - 1));
312 sleep(1);
313 register_fsa_action(A_PE_INVOKE);
314 return;
315
316 } else if (fsa_state != S_POLICY_ENGINE) {
317 crm_err("Invoking PE in state: %s", fsa_state2string(fsa_state));
318 return;
319 }
320
321 CRM_LOG_ASSERT(output != NULL);
322
323
324 crm_remote_peer_cache_refresh(output);
325
326 crm_xml_add(output, XML_ATTR_DC_UUID, fsa_our_uuid);
327 crm_xml_add_int(output, XML_ATTR_HAVE_QUORUM, fsa_has_quorum);
328
329 force_local_option(output, XML_ATTR_HAVE_WATCHDOG, watchdog?"true":"false");
330
331 if (ever_had_quorum && crm_have_quorum == FALSE) {
332 crm_xml_add_int(output, XML_ATTR_QUORUM_PANIC, 1);
333 }
334
335 cmd = create_request(CRM_OP_PECALC, output, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_DC, NULL);
336
337 free(fsa_pe_ref);
338 fsa_pe_ref = crm_element_value_copy(cmd, XML_ATTR_REFERENCE);
339
340 sent = crm_ipc_send(mainloop_get_ipc_client(pe_subsystem->source), cmd, 0, 0, NULL);
341 if (sent <= 0) {
342 crm_err("Could not contact the pengine: %d", sent);
343 register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
344 }
345
346 crm_debug("Invoking the PE: query=%d, ref=%s, seq=%llu, quorate=%d",
347 fsa_pe_query, fsa_pe_ref, crm_peer_seq, fsa_has_quorum);
348 free_xml(cmd);
349 }