This source file includes following definitions.
- cib_prepare_common
- cib_prepare_none
- cib_prepare_data
- cib_prepare_sync
- cib_prepare_diff
- cib_cleanup_query
- cib_cleanup_data
- cib_cleanup_output
- cib_cleanup_none
- cib_cleanup_sync
- cib_get_operation_id
- cib_msg_copy
- cib_op_func
- cib_op_modifies
- cib_op_can_run
- cib_op_prepare
- cib_op_cleanup
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 <sys/param.h>
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <fcntl.h>
29
30 #include <crm/crm.h>
31 #include <crm/cib.h>
32 #include <crm/msg_xml.h>
33 #include <crm/common/ipc.h>
34 #include <crm/cluster.h>
35
36 #include <crm/common/xml.h>
37
38 #include <cibio.h>
39 #include <callbacks.h>
40 #include <cibmessages.h>
41 #include "common.h"
42
43 extern gboolean cib_is_master;
44 extern const char *cib_root;
45 gboolean stand_alone = FALSE;
46 extern int cib_status;
47 extern gboolean can_write(int flags);
48 extern int cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff,
49 gboolean privileged);
50
51 static xmlNode *
52 cib_prepare_common(xmlNode * root, const char *section)
53 {
54 xmlNode *data = NULL;
55
56
57 if (root == NULL) {
58 return NULL;
59
60 } else if (safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT)
61 || safe_str_eq(crm_element_name(root), F_CRM_DATA)
62 || safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) {
63 data = first_named_child(root, XML_TAG_CIB);
64
65 } else {
66 data = root;
67 }
68
69
70 if (section != NULL && data != NULL && crm_str_eq(crm_element_name(data), XML_TAG_CIB, TRUE)) {
71 data = get_object_root(section, data);
72 }
73
74
75 return data;
76 }
77
78 static int
79 cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section)
80 {
81 *data = NULL;
82 *section = crm_element_value(request, F_CIB_SECTION);
83 return pcmk_ok;
84 }
85
86 static int
87 cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section)
88 {
89 xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
90
91 *section = crm_element_value(request, F_CIB_SECTION);
92 *data = cib_prepare_common(input_fragment, *section);
93
94 return pcmk_ok;
95 }
96
97 static int
98 cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section)
99 {
100 *data = NULL;
101 *section = crm_element_value(request, F_CIB_SECTION);
102 return pcmk_ok;
103 }
104
105 static int
106 cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section)
107 {
108 xmlNode *input_fragment = NULL;
109 const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
110
111 *data = NULL;
112 *section = NULL;
113
114 if (crm_is_true(update)) {
115 input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
116
117 } else {
118 input_fragment = get_message_xml(request, F_CIB_CALLDATA);
119 }
120
121 CRM_CHECK(input_fragment != NULL, crm_log_xml_warn(request, "no input"));
122 *data = cib_prepare_common(input_fragment, NULL);
123 return pcmk_ok;
124 }
125
126 static int
127 cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output)
128 {
129 CRM_LOG_ASSERT(*data == NULL);
130 if ((options & cib_no_children)
131 || safe_str_eq(crm_element_name(*output), "xpath-query")) {
132 free_xml(*output);
133 }
134 return pcmk_ok;
135 }
136
137 static int
138 cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output)
139 {
140 free_xml(*output);
141 *data = NULL;
142 return pcmk_ok;
143 }
144
145 static int
146 cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output)
147 {
148 free_xml(*output);
149 return pcmk_ok;
150 }
151
152 static int
153 cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output)
154 {
155 CRM_LOG_ASSERT(*data == NULL);
156 CRM_LOG_ASSERT(*output == NULL);
157 return pcmk_ok;
158 }
159
160 static int
161 cib_cleanup_sync(int options, xmlNode ** data, xmlNode ** output)
162 {
163
164 CRM_LOG_ASSERT(*data == NULL);
165 CRM_LOG_ASSERT(*output == NULL);
166 return pcmk_ok;
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 static cib_operation_t cib_server_ops[] = {
188 {NULL, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_default},
189 {CIB_OP_QUERY, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query, cib_process_query},
190 {CIB_OP_MODIFY, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_modify},
191 {CIB_OP_APPLY_DIFF,TRUE, TRUE, TRUE, cib_prepare_diff, cib_cleanup_data, cib_server_process_diff},
192 {CIB_OP_REPLACE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_replace_svr},
193 {CIB_OP_CREATE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_create},
194 {CIB_OP_DELETE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_delete},
195 {CIB_OP_SYNC, FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_sync},
196 {CIB_OP_BUMP, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_bump},
197 {CIB_OP_ERASE, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_erase},
198 {CRM_OP_NOOP, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_default},
199 {CIB_OP_DELETE_ALT,TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_delete_absolute},
200 {CIB_OP_UPGRADE, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server},
201 {CIB_OP_SLAVE, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
202 {CIB_OP_SLAVEALL, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
203 {CIB_OP_SYNC_ONE, FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_sync_one},
204 {CIB_OP_MASTER, TRUE, TRUE, FALSE, cib_prepare_data, cib_cleanup_data, cib_process_readwrite},
205 {CIB_OP_ISMASTER, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
206 {"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_shutdown_req},
207 {CRM_OP_PING, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping},
208 };
209
210
211 int
212 cib_get_operation_id(const char *op, int *operation)
213 {
214 static GHashTable *operation_hash = NULL;
215
216 if (operation_hash == NULL) {
217 int lpc = 0;
218 int max_msg_types = DIMOF(cib_server_ops);
219
220 operation_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
221 for (lpc = 1; lpc < max_msg_types; lpc++) {
222 int *value = malloc(sizeof(int));
223
224 if(value) {
225 *value = lpc;
226 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
227 }
228 }
229 }
230
231 if (op != NULL) {
232 int *value = g_hash_table_lookup(operation_hash, op);
233
234 if (value) {
235 *operation = *value;
236 return pcmk_ok;
237 }
238 }
239 crm_err("Operation %s is not valid", op);
240 *operation = -1;
241 return -EINVAL;
242 }
243
244 xmlNode *
245 cib_msg_copy(xmlNode * msg, gboolean with_data)
246 {
247 int lpc = 0;
248 const char *field = NULL;
249 const char *value = NULL;
250 xmlNode *value_struct = NULL;
251
252 static const char *field_list[] = {
253 F_XML_TAGNAME,
254 F_TYPE,
255 F_CIB_CLIENTID,
256 F_CIB_CALLOPTS,
257 F_CIB_CALLID,
258 F_CIB_OPERATION,
259 F_CIB_ISREPLY,
260 F_CIB_SECTION,
261 F_CIB_HOST,
262 F_CIB_RC,
263 F_CIB_DELEGATED,
264 F_CIB_OBJID,
265 F_CIB_OBJTYPE,
266 F_CIB_EXISTING,
267 F_CIB_SEENCOUNT,
268 F_CIB_TIMEOUT,
269 F_CIB_CALLBACK_TOKEN,
270 F_CIB_GLOBAL_UPDATE,
271 F_CIB_CLIENTNAME,
272 #if ENABLE_ACL
273 F_CIB_USER,
274 #endif
275 F_CIB_NOTIFY_TYPE,
276 F_CIB_NOTIFY_ACTIVATE
277 };
278
279 static const char *data_list[] = {
280 F_CIB_CALLDATA,
281 F_CIB_UPDATE,
282 F_CIB_UPDATE_RESULT
283 };
284
285 xmlNode *copy = create_xml_node(NULL, "copy");
286
287 CRM_ASSERT(copy != NULL);
288
289 for (lpc = 0; lpc < DIMOF(field_list); lpc++) {
290 field = field_list[lpc];
291 value = crm_element_value(msg, field);
292 if (value != NULL) {
293 crm_xml_add(copy, field, value);
294 }
295 }
296 for (lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) {
297 field = data_list[lpc];
298 value_struct = get_message_xml(msg, field);
299 if (value_struct != NULL) {
300 add_message_xml(copy, field, value_struct);
301 }
302 }
303
304 return copy;
305 }
306
307 cib_op_t *
308 cib_op_func(int call_type)
309 {
310 return &(cib_server_ops[call_type].fn);
311 }
312
313 gboolean
314 cib_op_modifies(int call_type)
315 {
316 return cib_server_ops[call_type].modifies_cib;
317 }
318
319 int
320 cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update)
321 {
322 if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) {
323
324 return -EACCES;
325 }
326 #if 0
327 if (rc == pcmk_ok
328 && stand_alone == FALSE
329 && global_update == FALSE
330 && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) {
331 return -pcmk_err_no_quorum;
332 }
333 #endif
334 return pcmk_ok;
335 }
336
337 int
338 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
339 {
340 crm_trace("Prepare %d", call_type);
341 return cib_server_ops[call_type].prepare(request, input, section);
342 }
343
344 int
345 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
346 {
347 crm_trace("Cleanup %d", call_type);
348 return cib_server_ops[call_type].cleanup(options, input, output);
349 }