This source file includes following definitions.
- set_pairs_data
- reply_expected
- dispatch
- pcmk__attrd_api_methods
- create_attrd_op
- connect_and_send_attrd_request
- pcmk__attrd_api_clear_failures
- pcmk__attrd_api_delete
- pcmk__attrd_api_purge
- pcmk__attrd_api_query
- pcmk__attrd_api_refresh
- add_op_attr
- populate_update_op
- pcmk__attrd_api_update
- pcmk__attrd_api_update_list
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13
14 #include <crm/crm.h>
15 #include <crm/common/attrs_internal.h>
16 #include <crm/common/ipc.h>
17 #include <crm/common/ipc_attrd_internal.h>
18 #include <crm/common/xml.h>
19 #include "crmcommon_private.h"
20
21 static void
22 set_pairs_data(pcmk__attrd_api_reply_t *data, xmlNode *msg_data)
23 {
24 const char *name = NULL;
25 pcmk__attrd_query_pair_t *pair;
26
27 name = crm_element_value(msg_data, PCMK__XA_ATTR_NAME);
28
29 for (xmlNode *node = pcmk__xe_first_child(msg_data, PCMK_XE_NODE, NULL,
30 NULL);
31 node != NULL; node = pcmk__xe_next(node, PCMK_XE_NODE)) {
32
33 pair = pcmk__assert_alloc(1, sizeof(pcmk__attrd_query_pair_t));
34
35 pair->node = crm_element_value(node, PCMK__XA_ATTR_HOST);
36 pair->name = name;
37 pair->value = crm_element_value(node, PCMK__XA_ATTR_VALUE);
38 data->data.pairs = g_list_prepend(data->data.pairs, pair);
39 }
40 }
41
42 static bool
43 reply_expected(pcmk_ipc_api_t *api, const xmlNode *request)
44 {
45 const char *command = crm_element_value(request, PCMK_XA_TASK);
46
47 return pcmk__str_any_of(command,
48 PCMK__ATTRD_CMD_CLEAR_FAILURE,
49 PCMK__ATTRD_CMD_QUERY,
50 PCMK__ATTRD_CMD_REFRESH,
51 PCMK__ATTRD_CMD_UPDATE,
52 PCMK__ATTRD_CMD_UPDATE_BOTH,
53 PCMK__ATTRD_CMD_UPDATE_DELAY,
54 NULL);
55 }
56
57 static bool
58 dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
59 {
60 const char *value = NULL;
61 crm_exit_t status = CRM_EX_OK;
62
63 pcmk__attrd_api_reply_t reply_data = {
64 pcmk__attrd_reply_unknown
65 };
66
67 if (pcmk__xe_is(reply, PCMK__XE_ACK)) {
68 return false;
69 }
70
71
72 value = crm_element_value(reply, PCMK__XA_T);
73 if (pcmk__str_empty(value)
74 || !pcmk__str_eq(value, PCMK__VALUE_ATTRD, pcmk__str_none)) {
75 crm_info("Unrecognizable message from attribute manager: "
76 "message type '%s' not '" PCMK__VALUE_ATTRD "'",
77 pcmk__s(value, ""));
78 status = CRM_EX_PROTOCOL;
79 goto done;
80 }
81
82 value = crm_element_value(reply, PCMK__XA_SUBT);
83
84
85
86
87 if (pcmk__str_eq(value, PCMK__ATTRD_CMD_QUERY, pcmk__str_null_matches)) {
88 if (!xmlHasProp(reply, (pcmkXmlStr) PCMK__XA_ATTR_NAME)) {
89 status = ENXIO;
90 goto done;
91 }
92 reply_data.reply_type = pcmk__attrd_reply_query;
93 set_pairs_data(&reply_data, reply);
94
95 } else {
96 crm_info("Unrecognizable message from attribute manager: "
97 "message subtype '%s' unknown", pcmk__s(value, ""));
98 status = CRM_EX_PROTOCOL;
99 goto done;
100 }
101
102 done:
103 pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
104
105
106 if (reply_data.data.pairs) {
107 g_list_free_full(reply_data.data.pairs, free);
108 }
109
110 return false;
111 }
112
113 pcmk__ipc_methods_t *
114 pcmk__attrd_api_methods(void)
115 {
116 pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
117
118 if (cmds != NULL) {
119 cmds->new_data = NULL;
120 cmds->free_data = NULL;
121 cmds->post_connect = NULL;
122 cmds->reply_expected = reply_expected;
123 cmds->dispatch = dispatch;
124 }
125 return cmds;
126 }
127
128
129
130
131
132
133
134
135
136 static xmlNode *
137 create_attrd_op(const char *user_name)
138 {
139 xmlNode *attrd_op = pcmk__xe_create(NULL, __func__);
140
141 crm_xml_add(attrd_op, PCMK__XA_T, PCMK__VALUE_ATTRD);
142 crm_xml_add(attrd_op, PCMK__XA_SRC, pcmk__s(crm_system_name, "unknown"));
143 crm_xml_add(attrd_op, PCMK__XA_ATTR_USER, user_name);
144
145 return attrd_op;
146 }
147
148 static int
149 connect_and_send_attrd_request(pcmk_ipc_api_t *api, const xmlNode *request)
150 {
151 int rc = pcmk_rc_ok;
152 bool created_api = false;
153 enum pcmk_ipc_dispatch dispatch = pcmk_ipc_dispatch_sync;
154
155 if (api == NULL) {
156 rc = pcmk_new_ipc_api(&api, pcmk_ipc_attrd);
157 if (rc != pcmk_rc_ok) {
158 return rc;
159 }
160 created_api = true;
161 } else {
162 dispatch = api->dispatch_type;
163 }
164
165 rc = pcmk__connect_ipc(api, dispatch, 5);
166 if (rc == pcmk_rc_ok) {
167 rc = pcmk__send_ipc_request(api, request);
168 }
169
170 if (created_api) {
171 pcmk_free_ipc_api(api);
172 }
173 return rc;
174 }
175
176 int
177 pcmk__attrd_api_clear_failures(pcmk_ipc_api_t *api, const char *node,
178 const char *resource, const char *operation,
179 const char *interval_spec, const char *user_name,
180 uint32_t options)
181 {
182 int rc = pcmk_rc_ok;
183 xmlNode *request = create_attrd_op(user_name);
184 const char *interval_desc = NULL;
185 const char *op_desc = NULL;
186 const char *target = pcmk__node_attr_target(node);
187
188 if (target != NULL) {
189 node = target;
190 }
191
192 if (operation) {
193 interval_desc = pcmk__s(interval_spec, "nonrecurring");
194 op_desc = operation;
195 } else {
196 interval_desc = "all";
197 op_desc = "operations";
198 }
199 crm_debug("Asking %s to clear failure of %s %s for %s on %s",
200 pcmk_ipc_name(api, true), interval_desc, op_desc,
201 pcmk__s(resource, "all resources"), pcmk__s(node, "all nodes"));
202
203 crm_xml_add(request, PCMK_XA_TASK, PCMK__ATTRD_CMD_CLEAR_FAILURE);
204 pcmk__xe_add_node(request, node, 0);
205 crm_xml_add(request, PCMK__XA_ATTR_RESOURCE, resource);
206 crm_xml_add(request, PCMK__XA_ATTR_CLEAR_OPERATION, operation);
207 crm_xml_add(request, PCMK__XA_ATTR_CLEAR_INTERVAL, interval_spec);
208 crm_xml_add_int(request, PCMK__XA_ATTR_IS_REMOTE,
209 pcmk_is_set(options, pcmk__node_attr_remote));
210
211 rc = connect_and_send_attrd_request(api, request);
212
213 pcmk__xml_free(request);
214 return rc;
215 }
216
217 int
218 pcmk__attrd_api_delete(pcmk_ipc_api_t *api, const char *node, const char *name,
219 uint32_t options)
220 {
221 const char *target = NULL;
222
223 if (name == NULL) {
224 return EINVAL;
225 }
226
227 target = pcmk__node_attr_target(node);
228
229 if (target != NULL) {
230 node = target;
231 }
232
233
234 options &= ~pcmk__node_attr_delay;
235 options |= pcmk__node_attr_value;
236
237 return pcmk__attrd_api_update(api, node, name, NULL, NULL, NULL, NULL, options);
238 }
239
240 int
241 pcmk__attrd_api_purge(pcmk_ipc_api_t *api, const char *node, bool reap)
242 {
243 int rc = pcmk_rc_ok;
244 xmlNode *request = NULL;
245 const char *target = pcmk__node_attr_target(node);
246
247 if (target != NULL) {
248 node = target;
249 }
250
251 crm_debug("Asking %s to purge transient attributes%s for %s",
252 pcmk_ipc_name(api, true),
253 (reap? " and node cache entries" : ""),
254 pcmk__s(node, "local node"));
255
256 request = create_attrd_op(NULL);
257
258 crm_xml_add(request, PCMK_XA_TASK, PCMK__ATTRD_CMD_PEER_REMOVE);
259 pcmk__xe_set_bool_attr(request, PCMK__XA_REAP, reap);
260 pcmk__xe_add_node(request, node, 0);
261
262 rc = connect_and_send_attrd_request(api, request);
263
264 pcmk__xml_free(request);
265 return rc;
266 }
267
268 int
269 pcmk__attrd_api_query(pcmk_ipc_api_t *api, const char *node, const char *name,
270 uint32_t options)
271 {
272 int rc = pcmk_rc_ok;
273 xmlNode *request = NULL;
274 const char *target = NULL;
275
276 if (name == NULL) {
277 return EINVAL;
278 }
279
280 if (pcmk_is_set(options, pcmk__node_attr_query_all)) {
281 node = NULL;
282 } else {
283 target = pcmk__node_attr_target(node);
284
285 if (target != NULL) {
286 node = target;
287 } else if (node == NULL) {
288 node = "localhost";
289 }
290 }
291
292 crm_debug("Querying %s for value of '%s'%s%s",
293 pcmk_ipc_name(api, true), name,
294 ((node == NULL)? "" : " on "), pcmk__s(node, ""));
295
296 request = create_attrd_op(NULL);
297
298 crm_xml_add(request, PCMK__XA_ATTR_NAME, name);
299 crm_xml_add(request, PCMK_XA_TASK, PCMK__ATTRD_CMD_QUERY);
300 pcmk__xe_add_node(request, node, 0);
301
302 rc = connect_and_send_attrd_request(api, request);
303 pcmk__xml_free(request);
304 return rc;
305 }
306
307 int
308 pcmk__attrd_api_refresh(pcmk_ipc_api_t *api, const char *node)
309 {
310 int rc = pcmk_rc_ok;
311 xmlNode *request = NULL;
312 const char *target = pcmk__node_attr_target(node);
313
314 if (target != NULL) {
315 node = target;
316 }
317
318 crm_debug("Asking %s to write all transient attributes for %s to CIB",
319 pcmk_ipc_name(api, true), pcmk__s(node, "local node"));
320
321 request = create_attrd_op(NULL);
322
323 crm_xml_add(request, PCMK_XA_TASK, PCMK__ATTRD_CMD_REFRESH);
324 pcmk__xe_add_node(request, node, 0);
325
326 rc = connect_and_send_attrd_request(api, request);
327
328 pcmk__xml_free(request);
329 return rc;
330 }
331
332 static void
333 add_op_attr(xmlNode *op, uint32_t options)
334 {
335 if (pcmk_all_flags_set(options, pcmk__node_attr_value | pcmk__node_attr_delay)) {
336 crm_xml_add(op, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE_BOTH);
337 } else if (pcmk_is_set(options, pcmk__node_attr_value)) {
338 crm_xml_add(op, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE);
339 } else if (pcmk_is_set(options, pcmk__node_attr_delay)) {
340 crm_xml_add(op, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE_DELAY);
341 }
342 }
343
344 static void
345 populate_update_op(xmlNode *op, const char *node, const char *name, const char *value,
346 const char *dampen, const char *set, uint32_t options)
347 {
348 if (pcmk_is_set(options, pcmk__node_attr_pattern)) {
349 crm_xml_add(op, PCMK__XA_ATTR_REGEX, name);
350 } else {
351 crm_xml_add(op, PCMK__XA_ATTR_NAME, name);
352 }
353
354 if (pcmk_is_set(options, pcmk__node_attr_utilization)) {
355 crm_xml_add(op, PCMK__XA_ATTR_SET_TYPE, PCMK_XE_UTILIZATION);
356 } else {
357 crm_xml_add(op, PCMK__XA_ATTR_SET_TYPE, PCMK_XE_INSTANCE_ATTRIBUTES);
358 }
359
360 add_op_attr(op, options);
361
362 crm_xml_add(op, PCMK__XA_ATTR_VALUE, value);
363 crm_xml_add(op, PCMK__XA_ATTR_DAMPENING, dampen);
364 pcmk__xe_add_node(op, node, 0);
365 crm_xml_add(op, PCMK__XA_ATTR_SET, set);
366 crm_xml_add_int(op, PCMK__XA_ATTR_IS_REMOTE,
367 pcmk_is_set(options, pcmk__node_attr_remote));
368 crm_xml_add_int(op, PCMK__XA_ATTR_IS_PRIVATE,
369 pcmk_is_set(options, pcmk__node_attr_private));
370
371 if (pcmk_is_set(options, pcmk__node_attr_sync_local)) {
372 crm_xml_add(op, PCMK__XA_ATTR_SYNC_POINT, PCMK__VALUE_LOCAL);
373 } else if (pcmk_is_set(options, pcmk__node_attr_sync_cluster)) {
374 crm_xml_add(op, PCMK__XA_ATTR_SYNC_POINT, PCMK__VALUE_CLUSTER);
375 }
376 }
377
378 int
379 pcmk__attrd_api_update(pcmk_ipc_api_t *api, const char *node, const char *name,
380 const char *value, const char *dampen, const char *set,
381 const char *user_name, uint32_t options)
382 {
383 int rc = pcmk_rc_ok;
384 xmlNode *request = NULL;
385 const char *target = NULL;
386
387 if (name == NULL) {
388 return EINVAL;
389 }
390
391 target = pcmk__node_attr_target(node);
392
393 if (target != NULL) {
394 node = target;
395 }
396
397 crm_debug("Asking %s to update '%s' to '%s' for %s",
398 pcmk_ipc_name(api, true), name, pcmk__s(value, "(null)"),
399 pcmk__s(node, "local node"));
400
401 request = create_attrd_op(user_name);
402 populate_update_op(request, node, name, value, dampen, set, options);
403
404 rc = connect_and_send_attrd_request(api, request);
405
406 pcmk__xml_free(request);
407 return rc;
408 }
409
410 int
411 pcmk__attrd_api_update_list(pcmk_ipc_api_t *api, GList *attrs, const char *dampen,
412 const char *set, const char *user_name,
413 uint32_t options)
414 {
415 int rc = pcmk_rc_ok;
416 xmlNode *request = NULL;
417
418 if (attrs == NULL) {
419 return EINVAL;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 for (GList *iter = attrs; iter != NULL; iter = iter->next) {
445 pcmk__attrd_query_pair_t *pair = (pcmk__attrd_query_pair_t *) iter->data;
446
447 if (pcmk__is_daemon) {
448 const char *target = NULL;
449 xmlNode *child = NULL;
450
451
452 if (request == NULL) {
453 request = create_attrd_op(user_name);
454 add_op_attr(request, options);
455 }
456
457
458
459
460
461
462 child = pcmk__xe_create(request, PCMK_XE_OP);
463 target = pcmk__node_attr_target(pair->node);
464
465 if (target != NULL) {
466 pair->node = target;
467 }
468
469 populate_update_op(child, pair->node, pair->name, pair->value, dampen,
470 set, options);
471 } else {
472 rc = pcmk__attrd_api_update(api, pair->node, pair->name, pair->value,
473 dampen, set, user_name, options);
474 }
475 }
476
477
478
479
480 if (pcmk__is_daemon) {
481 rc = connect_and_send_attrd_request(api, request);
482 pcmk__xml_free(request);
483 }
484
485 return rc;
486 }