This source file includes following definitions.
- cib_process_shutdown_req
- cib_process_default
- cib_process_readwrite
- send_sync_request
- cib_process_ping
- cib_process_sync
- cib_process_upgrade_server
- cib_process_sync_one
- cib_server_process_diff
- cib_process_replace_svr
- cib_process_delete_absolute
- sync_our_cib
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <time.h>
18
19 #include <sys/param.h>
20 #include <sys/types.h>
21
22 #include <crm/crm.h>
23 #include <crm/cib/internal.h>
24 #include <crm/msg_xml.h>
25
26 #include <crm/common/xml.h>
27 #include <crm/common/ipc_internal.h>
28 #include <crm/common/xml_internal.h>
29 #include <crm/cluster/internal.h>
30
31 #include <pacemaker-based.h>
32
33
34 #define MAX_DIFF_RETRY 5
35
36 bool based_is_primary = false;
37
38 xmlNode *the_cib = NULL;
39
40 int
41 cib_process_shutdown_req(const char *op, int options, const char *section, xmlNode * req,
42 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
43 xmlNode ** answer)
44 {
45 const char *host = crm_element_value(req, F_ORIG);
46
47 *answer = NULL;
48
49 if (crm_element_value(req, F_CIB_ISREPLY) == NULL) {
50 crm_info("Peer %s is requesting to shut down", host);
51 return pcmk_ok;
52 }
53
54 if (cib_shutdown_flag == FALSE) {
55 crm_err("Peer %s mistakenly thinks we wanted to shut down", host);
56 return -EINVAL;
57 }
58
59 crm_info("Peer %s has acknowledged our shutdown request", host);
60 terminate_cib(__func__, 0);
61 return pcmk_ok;
62 }
63
64 int
65 cib_process_default(const char *op, int options, const char *section, xmlNode * req,
66 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
67 xmlNode ** answer)
68 {
69 int result = pcmk_ok;
70
71 crm_trace("Processing \"%s\" event", op);
72 *answer = NULL;
73
74 if (op == NULL) {
75 result = -EINVAL;
76 crm_err("No operation specified");
77
78 } else if (strcmp(PCMK__CIB_REQUEST_NOOP, op) != 0) {
79 result = -EPROTONOSUPPORT;
80 crm_err("Action [%s] is not supported by the CIB manager", op);
81 }
82 return result;
83 }
84
85 int
86 cib_process_readwrite(const char *op, int options, const char *section, xmlNode * req,
87 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
88 xmlNode ** answer)
89 {
90 int result = pcmk_ok;
91
92 crm_trace("Processing \"%s\" event", op);
93
94 if (pcmk__str_eq(op, PCMK__CIB_REQUEST_IS_PRIMARY, pcmk__str_none)) {
95 if (based_is_primary) {
96 result = pcmk_ok;
97 } else {
98 result = -EPERM;
99 }
100 return result;
101 }
102
103 if (pcmk__str_eq(op, PCMK__CIB_REQUEST_PRIMARY, pcmk__str_none)) {
104 if (!based_is_primary) {
105 crm_info("We are now in R/W mode");
106 based_is_primary = true;
107 } else {
108 crm_debug("We are still in R/W mode");
109 }
110
111 } else if (based_is_primary) {
112 crm_info("We are now in R/O mode");
113 based_is_primary = false;
114 }
115
116 return result;
117 }
118
119
120
121
122 static int sync_in_progress = 0;
123
124 void
125 send_sync_request(const char *host)
126 {
127 xmlNode *sync_me = create_xml_node(NULL, "sync-me");
128
129 crm_info("Requesting re-sync from %s", (host? host : "all peers"));
130 sync_in_progress = 1;
131
132 crm_xml_add(sync_me, F_TYPE, "cib");
133 crm_xml_add(sync_me, F_CIB_OPERATION, PCMK__CIB_REQUEST_SYNC_TO_ONE);
134 crm_xml_add(sync_me, F_CIB_DELEGATED,
135 stand_alone? "localhost" : crm_cluster->uname);
136
137 send_cluster_message(host ? crm_get_peer(0, host) : NULL, crm_msg_cib, sync_me, FALSE);
138 free_xml(sync_me);
139 }
140
141 int
142 cib_process_ping(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
143 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
144 {
145 const char *host = crm_element_value(req, F_ORIG);
146 const char *seq = crm_element_value(req, F_CIB_PING_ID);
147 char *digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET);
148
149 crm_trace("Processing \"%s\" event %s from %s", op, seq, host);
150 *answer = create_xml_node(NULL, XML_CRM_TAG_PING);
151
152 crm_xml_add(*answer, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
153 crm_xml_add(*answer, XML_ATTR_DIGEST, digest);
154 crm_xml_add(*answer, F_CIB_PING_ID, seq);
155
156 pcmk__if_tracing(
157 {
158
159 add_message_xml(*answer, F_CIB_CALLDATA, the_cib);
160 },
161 {
162
163 const char *tag = TYPE(the_cib);
164 xmlNode *shallow = create_xml_node(NULL, tag);
165
166 copy_in_properties(shallow, the_cib);
167 add_message_xml(*answer, F_CIB_CALLDATA, shallow);
168 free_xml(shallow);
169 }
170 );
171
172 crm_info("Reporting our current digest to %s: %s for %s.%s.%s",
173 host, digest,
174 crm_element_value(existing_cib, XML_ATTR_GENERATION_ADMIN),
175 crm_element_value(existing_cib, XML_ATTR_GENERATION),
176 crm_element_value(existing_cib, XML_ATTR_NUMUPDATES));
177
178 free(digest);
179
180 return pcmk_ok;
181 }
182
183 int
184 cib_process_sync(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
185 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
186 {
187 return sync_our_cib(req, TRUE);
188 }
189
190 int
191 cib_process_upgrade_server(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
192 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
193 {
194 int rc = pcmk_ok;
195
196 *answer = NULL;
197
198 if(crm_element_value(req, F_CIB_SCHEMA_MAX)) {
199
200
201
202
203
204 return cib_process_upgrade(
205 op, options, section, req, input, existing_cib, result_cib, answer);
206
207 } else {
208 int new_version = 0;
209 int current_version = 0;
210 xmlNode *scratch = copy_xml(existing_cib);
211 const char *host = crm_element_value(req, F_ORIG);
212 const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);
213 const char *client_id = crm_element_value(req, F_CIB_CLIENTID);
214 const char *call_opts = crm_element_value(req, F_CIB_CALLOPTS);
215 const char *call_id = crm_element_value(req, F_CIB_CALLID);
216
217 crm_trace("Processing \"%s\" event", op);
218 if (value != NULL) {
219 current_version = get_schema_version(value);
220 }
221
222 rc = update_validation(&scratch, &new_version, 0, TRUE, TRUE);
223 if (new_version > current_version) {
224 xmlNode *up = create_xml_node(NULL, __func__);
225
226 rc = pcmk_ok;
227 crm_notice("Upgrade request from %s verified", host);
228
229 crm_xml_add(up, F_TYPE, "cib");
230 crm_xml_add(up, F_CIB_OPERATION, PCMK__CIB_REQUEST_UPGRADE);
231 crm_xml_add(up, F_CIB_SCHEMA_MAX, get_schema_name(new_version));
232 crm_xml_add(up, F_CIB_DELEGATED, host);
233 crm_xml_add(up, F_CIB_CLIENTID, client_id);
234 crm_xml_add(up, F_CIB_CALLOPTS, call_opts);
235 crm_xml_add(up, F_CIB_CALLID, call_id);
236
237 if (cib_legacy_mode() && based_is_primary) {
238 rc = cib_process_upgrade(
239 op, options, section, up, input, existing_cib, result_cib, answer);
240
241 } else {
242 send_cluster_message(NULL, crm_msg_cib, up, FALSE);
243 }
244
245 free_xml(up);
246
247 } else if(rc == pcmk_ok) {
248 rc = -pcmk_err_schema_unchanged;
249 }
250
251 if (rc != pcmk_ok) {
252
253 crm_node_t *origin = pcmk__search_cluster_node_cache(0, host);
254
255 crm_info("Rejecting upgrade request from %s: %s "
256 CRM_XS " rc=%d peer=%s", host, pcmk_strerror(rc), rc,
257 (origin? origin->uname : "lost"));
258
259 if (origin) {
260 xmlNode *up = create_xml_node(NULL, __func__);
261
262 crm_xml_add(up, F_TYPE, "cib");
263 crm_xml_add(up, F_CIB_OPERATION, PCMK__CIB_REQUEST_UPGRADE);
264 crm_xml_add(up, F_CIB_DELEGATED, host);
265 crm_xml_add(up, F_CIB_ISREPLY, host);
266 crm_xml_add(up, F_CIB_CLIENTID, client_id);
267 crm_xml_add(up, F_CIB_CALLOPTS, call_opts);
268 crm_xml_add(up, F_CIB_CALLID, call_id);
269 crm_xml_add_int(up, F_CIB_UPGRADE_RC, rc);
270 if (send_cluster_message(origin, crm_msg_cib, up, TRUE)
271 == FALSE) {
272 crm_warn("Could not send CIB upgrade result to %s", host);
273 }
274 free_xml(up);
275 }
276 }
277 free_xml(scratch);
278 }
279 return rc;
280 }
281
282 int
283 cib_process_sync_one(const char *op, int options, const char *section, xmlNode * req,
284 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
285 xmlNode ** answer)
286 {
287 return sync_our_cib(req, FALSE);
288 }
289
290 int
291 cib_server_process_diff(const char *op, int options, const char *section, xmlNode * req,
292 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
293 xmlNode ** answer)
294 {
295 int rc = pcmk_ok;
296
297 if (sync_in_progress > MAX_DIFF_RETRY) {
298
299
300
301 sync_in_progress = 0;
302 }
303
304
305 if (sync_in_progress && !based_is_primary) {
306 int diff_add_updates = 0;
307 int diff_add_epoch = 0;
308 int diff_add_admin_epoch = 0;
309
310 int diff_del_updates = 0;
311 int diff_del_epoch = 0;
312 int diff_del_admin_epoch = 0;
313
314 cib_diff_version_details(input,
315 &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
316 &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
317
318 sync_in_progress++;
319 crm_notice("Not applying diff %d.%d.%d -> %d.%d.%d (sync in progress)",
320 diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
321 diff_add_admin_epoch, diff_add_epoch, diff_add_updates);
322 return -pcmk_err_diff_resync;
323 }
324
325 rc = cib_process_diff(op, options, section, req, input, existing_cib, result_cib, answer);
326 crm_trace("result: %s (%d), %s", pcmk_strerror(rc), rc,
327 (based_is_primary? "primary": "secondary"));
328
329 if ((rc == -pcmk_err_diff_resync) && !based_is_primary) {
330 free_xml(*result_cib);
331 *result_cib = NULL;
332 send_sync_request(NULL);
333
334 } else if (rc == -pcmk_err_diff_resync) {
335 rc = -pcmk_err_diff_failed;
336 if (options & cib_force_diff) {
337 crm_warn("Not requesting full refresh in R/W mode");
338 }
339
340 } else if ((rc != pcmk_ok) && !based_is_primary && cib_legacy_mode()) {
341 crm_warn("Requesting full CIB refresh because update failed: %s"
342 CRM_XS " rc=%d", pcmk_strerror(rc), rc);
343
344 pcmk__output_set_log_level(logger_out, LOG_INFO);
345 logger_out->message(logger_out, "xml-patchset", input);
346 free_xml(*result_cib);
347 *result_cib = NULL;
348 send_sync_request(NULL);
349 }
350
351 return rc;
352 }
353
354 int
355 cib_process_replace_svr(const char *op, int options, const char *section, xmlNode * req,
356 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
357 xmlNode ** answer)
358 {
359 const char *tag = crm_element_name(input);
360 int rc =
361 cib_process_replace(op, options, section, req, input, existing_cib, result_cib, answer);
362 if (rc == pcmk_ok && pcmk__str_eq(tag, XML_TAG_CIB, pcmk__str_casei)) {
363 sync_in_progress = 0;
364 }
365 return rc;
366 }
367
368 int
369 cib_process_delete_absolute(const char *op, int options, const char *section, xmlNode * req,
370 xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
371 xmlNode ** answer)
372 {
373 return -EINVAL;
374 }
375
376 int
377 sync_our_cib(xmlNode * request, gboolean all)
378 {
379 int result = pcmk_ok;
380 char *digest = NULL;
381 const char *host = crm_element_value(request, F_ORIG);
382 const char *op = crm_element_value(request, F_CIB_OPERATION);
383
384 xmlNode *replace_request = NULL;
385
386 CRM_CHECK(the_cib != NULL, return -EINVAL);
387
388 replace_request = cib_msg_copy(request, FALSE);
389 CRM_CHECK(replace_request != NULL, return -EINVAL);
390
391 crm_debug("Syncing CIB to %s", all ? "all peers" : host);
392 if (all == FALSE && host == NULL) {
393 crm_log_xml_err(request, "bad sync");
394 }
395
396
397
398
399
400
401
402
403 if (host != NULL) {
404 crm_xml_add(replace_request, F_CIB_ISREPLY, host);
405 }
406 if (all) {
407 xml_remove_prop(replace_request, F_CIB_HOST);
408 }
409
410 crm_xml_add(replace_request, F_CIB_OPERATION, PCMK__CIB_REQUEST_REPLACE);
411 crm_xml_add(replace_request, "original_" F_CIB_OPERATION, op);
412 pcmk__xe_set_bool_attr(replace_request, F_CIB_GLOBAL_UPDATE, true);
413
414 crm_xml_add(replace_request, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
415 digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET);
416 crm_xml_add(replace_request, XML_ATTR_DIGEST, digest);
417
418 add_message_xml(replace_request, F_CIB_CALLDATA, the_cib);
419
420 if (send_cluster_message
421 (all ? NULL : crm_get_peer(0, host), crm_msg_cib, replace_request, FALSE) == FALSE) {
422 result = -ENOTCONN;
423 }
424 free_xml(replace_request);
425 free(digest);
426 return result;
427 }