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