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