This source file includes following definitions.
- find_nvpair_attr_delegate
- update_attr_delegate
- read_attr_delegate
- delete_attr_delegate
- get_uuid_from_result
- query_node_uuid
- query_node_uname
- set_standby
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
23 #include <crm/crm.h>
24
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <libgen.h>
33
34 #include <crm/msg_xml.h>
35 #include <crm/common/xml.h>
36 #include <crm/cib/internal.h>
37
38 #define attr_msg(level, fmt, args...) do { \
39 if(to_console) { \
40 printf(fmt"\n", ##args); \
41 } else { \
42 do_crm_log(level, fmt , ##args); \
43 } \
44 } while(0)
45
46
47 #define attr_snprintf(_str, _offset, _limit, ...) do { \
48 _offset += snprintf(_str + _offset, \
49 (_limit > _offset) ? _limit - _offset : 0, \
50 __VA_ARGS__); \
51 } while(0)
52
53 #define XPATH_MAX 1024
54
55 extern int
56 find_nvpair_attr_delegate(cib_t * the_cib, const char *attr, const char *section,
57 const char *node_uuid, const char *attr_set_type, const char *set_name,
58 const char *attr_id, const char *attr_name, gboolean to_console,
59 char **value, const char *user_name)
60 {
61 int offset = 0;
62 int rc = pcmk_ok;
63
64 char *xpath_string = NULL;
65 xmlNode *xml_search = NULL;
66 const char *set_type = NULL;
67 const char *node_type = NULL;
68
69 if (attr_set_type) {
70 set_type = attr_set_type;
71 } else {
72 set_type = XML_TAG_ATTR_SETS;
73 }
74
75 CRM_ASSERT(value != NULL);
76 *value = NULL;
77
78 if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) {
79 node_uuid = NULL;
80 set_type = XML_CIB_TAG_PROPSET;
81
82 } else if (safe_str_eq(section, XML_CIB_TAG_OPCONFIG)
83 || safe_str_eq(section, XML_CIB_TAG_RSCCONFIG)) {
84 node_uuid = NULL;
85 set_type = XML_TAG_META_SETS;
86
87 } else if (safe_str_eq(section, XML_CIB_TAG_TICKETS)) {
88 node_uuid = NULL;
89 section = XML_CIB_TAG_STATUS;
90 node_type = XML_CIB_TAG_TICKETS;
91
92 } else if (node_uuid == NULL) {
93 return -EINVAL;
94 }
95
96 xpath_string = calloc(1, XPATH_MAX);
97 if (xpath_string == NULL) {
98 crm_perror(LOG_CRIT, "Could not create xpath");
99 return -ENOMEM;
100 }
101
102 attr_snprintf(xpath_string, offset, XPATH_MAX, "%.128s", get_object_path(section));
103
104 if (safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) {
105 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s", node_type);
106
107 } else if (node_uuid) {
108 const char *node_type = XML_CIB_TAG_NODE;
109
110 if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
111 node_type = XML_CIB_TAG_STATE;
112 set_type = XML_TAG_TRANSIENT_NODEATTRS;
113 }
114 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s[@id='%s']", node_type,
115 node_uuid);
116 }
117
118 if (set_name) {
119 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s[@id='%.128s']", set_type,
120 set_name);
121 } else {
122 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s", set_type);
123 }
124
125 attr_snprintf(xpath_string, offset, XPATH_MAX, "//nvpair[");
126 if (attr_id) {
127 attr_snprintf(xpath_string, offset, XPATH_MAX, "@id='%s'", attr_id);
128 }
129
130 if (attr_name) {
131 if (attr_id) {
132 attr_snprintf(xpath_string, offset, XPATH_MAX, " and ");
133 }
134 attr_snprintf(xpath_string, offset, XPATH_MAX, "@name='%.128s'", attr_name);
135 }
136 attr_snprintf(xpath_string, offset, XPATH_MAX, "]");
137 CRM_LOG_ASSERT(offset > 0);
138
139 rc = cib_internal_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL, &xml_search,
140 cib_sync_call | cib_scope_local | cib_xpath, user_name);
141
142 if (rc != pcmk_ok) {
143 crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s",
144 attr_name, section, crm_str(node_uuid), crm_str(set_name), xpath_string,
145 pcmk_strerror(rc));
146 goto done;
147 }
148
149 crm_log_xml_debug(xml_search, "Match");
150 if (xml_has_children(xml_search)) {
151 xmlNode *child = NULL;
152
153 rc = -ENOTUNIQ;
154 attr_msg(LOG_WARNING, "Multiple attributes match name=%s", attr_name);
155
156 for (child = __xml_first_child(xml_search); child != NULL; child = __xml_next(child)) {
157 attr_msg(LOG_INFO, " Value: %s \t(id=%s)",
158 crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child));
159 }
160
161 } else {
162 const char *tmp = crm_element_value(xml_search, attr);
163
164 if (tmp) {
165 *value = strdup(tmp);
166 }
167 }
168
169 done:
170 free(xpath_string);
171 free_xml(xml_search);
172 return rc;
173 }
174
175 int
176 update_attr_delegate(cib_t * the_cib, int call_options,
177 const char *section, const char *node_uuid, const char *set_type,
178 const char *set_name, const char *attr_id, const char *attr_name,
179 const char *attr_value, gboolean to_console, const char *user_name,
180 const char *node_type)
181 {
182 const char *tag = NULL;
183 int rc = pcmk_ok;
184 xmlNode *xml_top = NULL;
185 xmlNode *xml_obj = NULL;
186
187 char *local_attr_id = NULL;
188 char *local_set_name = NULL;
189
190 CRM_CHECK(section != NULL, return -EINVAL);
191 CRM_CHECK(attr_value != NULL, return -EINVAL);
192 CRM_CHECK(attr_name != NULL || attr_id != NULL, return -EINVAL);
193
194 rc = find_nvpair_attr_delegate(the_cib, XML_ATTR_ID, section, node_uuid, set_type, set_name,
195 attr_id, attr_name, to_console, &local_attr_id, user_name);
196 if (rc == pcmk_ok) {
197 attr_id = local_attr_id;
198 goto do_modify;
199
200 } else if (rc != -ENXIO) {
201 return rc;
202
203
204
205
206 } else {
207 crm_trace("%s does not exist, create it", attr_name);
208 if (safe_str_eq(section, XML_CIB_TAG_TICKETS)) {
209 node_uuid = NULL;
210 section = XML_CIB_TAG_STATUS;
211 node_type = XML_CIB_TAG_TICKETS;
212
213 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATUS);
214 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
215
216 } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) {
217
218 if (node_uuid == NULL) {
219 return -EINVAL;
220 }
221
222 if (safe_str_eq(node_type, "remote")) {
223 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_NODES);
224 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_NODE);
225 crm_xml_add(xml_obj, XML_ATTR_TYPE, "remote");
226 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
227 crm_xml_add(xml_obj, XML_ATTR_UNAME, node_uuid);
228 } else {
229 tag = XML_CIB_TAG_NODE;
230 }
231
232 } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
233 tag = XML_TAG_TRANSIENT_NODEATTRS;
234 if (node_uuid == NULL) {
235 return -EINVAL;
236 }
237
238 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATE);
239 crm_xml_add(xml_top, XML_ATTR_ID, node_uuid);
240 xml_obj = xml_top;
241
242 } else {
243 tag = section;
244 node_uuid = NULL;
245 }
246
247 if (set_name == NULL) {
248 if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) {
249 local_set_name = strdup(CIB_OPTIONS_FIRST);
250
251 } else if (safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) {
252 local_set_name = crm_concat(section, XML_CIB_TAG_TICKETS, '-');
253
254 } else if (node_uuid) {
255 local_set_name = crm_concat(section, node_uuid, '-');
256
257 if (set_type) {
258 char *tmp_set_name = local_set_name;
259
260 local_set_name = crm_concat(tmp_set_name, set_type, '-');
261 free(tmp_set_name);
262 }
263 } else {
264 local_set_name = crm_concat(section, "options", '-');
265 }
266 set_name = local_set_name;
267 }
268
269 if (attr_id == NULL) {
270 local_attr_id = crm_concat(set_name, attr_name, '-');
271 crm_xml_sanitize_id(local_attr_id);
272 attr_id = local_attr_id;
273
274 } else if (attr_name == NULL) {
275 attr_name = attr_id;
276 }
277
278 crm_trace("Creating %s/%s", section, tag);
279 if (tag != NULL) {
280 xml_obj = create_xml_node(xml_obj, tag);
281 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
282 if (xml_top == NULL) {
283 xml_top = xml_obj;
284 }
285 }
286
287 if (node_uuid == NULL && safe_str_neq(node_type, XML_CIB_TAG_TICKETS)) {
288 if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) {
289 xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET);
290 } else {
291 xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS);
292 }
293
294 } else if (set_type) {
295 xml_obj = create_xml_node(xml_obj, set_type);
296
297 } else {
298 xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS);
299 }
300 crm_xml_add(xml_obj, XML_ATTR_ID, set_name);
301
302 if (xml_top == NULL) {
303 xml_top = xml_obj;
304 }
305 }
306
307 do_modify:
308 xml_obj = crm_create_nvpair_xml(xml_obj, attr_id, attr_name, attr_value);
309 if (xml_top == NULL) {
310 xml_top = xml_obj;
311 }
312
313 crm_log_xml_trace(xml_top, "update_attr");
314 rc = cib_internal_op(the_cib, CIB_OP_MODIFY, NULL, section, xml_top, NULL,
315 call_options | cib_quorum_override, user_name);
316
317 if (rc < pcmk_ok) {
318 attr_msg(LOG_ERR, "Error setting %s=%s (section=%s, set=%s): %s",
319 attr_name, attr_value, section, crm_str(set_name), pcmk_strerror(rc));
320 crm_log_xml_info(xml_top, "Update");
321 }
322
323 free(local_set_name);
324 free(local_attr_id);
325 free_xml(xml_top);
326
327 return rc;
328 }
329
330 int
331 read_attr_delegate(cib_t * the_cib,
332 const char *section, const char *node_uuid, const char *set_type,
333 const char *set_name, const char *attr_id, const char *attr_name,
334 char **attr_value, gboolean to_console, const char *user_name)
335 {
336 int rc = pcmk_ok;
337
338 CRM_ASSERT(attr_value != NULL);
339 CRM_CHECK(section != NULL, return -EINVAL);
340 CRM_CHECK(attr_name != NULL || attr_id != NULL, return -EINVAL);
341
342 *attr_value = NULL;
343
344 rc = find_nvpair_attr_delegate(the_cib, XML_NVPAIR_ATTR_VALUE, section, node_uuid, set_type,
345 set_name, attr_id, attr_name, to_console, attr_value, user_name);
346 if (rc != pcmk_ok) {
347 crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s): %s",
348 attr_name, section, crm_str(set_name), crm_str(node_uuid), pcmk_strerror(rc));
349 }
350 return rc;
351 }
352
353 int
354 delete_attr_delegate(cib_t * the_cib, int options,
355 const char *section, const char *node_uuid, const char *set_type,
356 const char *set_name, const char *attr_id, const char *attr_name,
357 const char *attr_value, gboolean to_console, const char *user_name)
358 {
359 int rc = pcmk_ok;
360 xmlNode *xml_obj = NULL;
361 char *local_attr_id = NULL;
362
363 CRM_CHECK(section != NULL, return -EINVAL);
364 CRM_CHECK(attr_name != NULL || attr_id != NULL, return -EINVAL);
365
366 if (attr_id == NULL) {
367 rc = find_nvpair_attr_delegate(the_cib, XML_ATTR_ID, section, node_uuid, set_type,
368 set_name, attr_id, attr_name, to_console, &local_attr_id,
369 user_name);
370 if (rc != pcmk_ok) {
371 return rc;
372 }
373 attr_id = local_attr_id;
374 }
375
376 xml_obj = crm_create_nvpair_xml(NULL, attr_id, attr_name, attr_value);
377
378 rc = cib_internal_op(the_cib, CIB_OP_DELETE, NULL, section, xml_obj, NULL,
379 options | cib_quorum_override, user_name);
380
381 if (rc == pcmk_ok) {
382 attr_msg(LOG_DEBUG, "Deleted %s %s: id=%s%s%s%s%s\n",
383 section, node_uuid ? "attribute" : "option", local_attr_id,
384 set_name ? " set=" : "", set_name ? set_name : "",
385 attr_name ? " name=" : "", attr_name ? attr_name : "");
386 }
387
388 free(local_attr_id);
389 free_xml(xml_obj);
390 return rc;
391 }
392
393
394
395
396
397
398
399
400
401
402
403 static int
404 get_uuid_from_result(xmlNode *result, char **uuid, int *is_remote)
405 {
406 int rc = -ENXIO;
407 const char *tag;
408 const char *parsed_uuid = NULL;
409 int parsed_is_remote = FALSE;
410
411 if (result == NULL) {
412 return rc;
413 }
414
415
416 tag = (const char *) (result->name);
417 if (safe_str_eq(tag, "xpath-query")) {
418 result = __xml_first_child(result);
419 CRM_CHECK(result != NULL, return rc);
420 tag = (const char *) (result->name);
421 }
422
423 if (safe_str_eq(tag, XML_CIB_TAG_NODE)) {
424
425
426 if (safe_str_eq(crm_element_value(result, XML_ATTR_TYPE), "remote")) {
427 parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
428 parsed_is_remote = TRUE;
429 } else {
430 parsed_uuid = ID(result);
431 parsed_is_remote = FALSE;
432 }
433
434 } else if (safe_str_eq(tag, XML_CIB_TAG_RESOURCE)) {
435
436
437 parsed_uuid = ID(result);
438 parsed_is_remote = TRUE;
439
440 } else if (safe_str_eq(tag, XML_CIB_TAG_NVPAIR)) {
441
442
443 parsed_uuid = crm_element_value(result, XML_NVPAIR_ATTR_VALUE);
444 parsed_is_remote = TRUE;
445
446 } else if (safe_str_eq(tag, XML_CIB_TAG_STATE)) {
447
448
449 parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
450 if (crm_is_true(crm_element_value(result, XML_NODE_IS_REMOTE))) {
451 parsed_is_remote = TRUE;
452 }
453 }
454
455 if (parsed_uuid) {
456 if (uuid) {
457 *uuid = strdup(parsed_uuid);
458 }
459 if (is_remote) {
460 *is_remote = parsed_is_remote;
461 }
462 rc = pcmk_ok;
463 }
464
465 return rc;
466 }
467
468
469
470
471
472
473
474 #define XPATH_NODE \
475 "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
476 "/" XML_CIB_TAG_NODE "[@" XML_ATTR_UNAME "='%s']" \
477 "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
478 "/" XML_CIB_TAG_RESOURCE \
479 "[@class='ocf'][@provider='pacemaker'][@type='remote'][@id='%s']" \
480 "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
481 "/" XML_CIB_TAG_RESOURCE "/" XML_TAG_META_SETS "/" XML_CIB_TAG_NVPAIR \
482 "[@name='" XML_RSC_ATTR_REMOTE_NODE "'][@value='%s']" \
483 "|/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS "/" XML_CIB_TAG_STATE \
484 "[@" XML_NODE_IS_REMOTE "='true'][@" XML_ATTR_UUID "='%s']"
485
486 int
487 query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
488 {
489 int rc = pcmk_ok;
490 char *xpath_string;
491 xmlNode *xml_search = NULL;
492
493 CRM_ASSERT(uname != NULL);
494
495 if (uuid) {
496 *uuid = NULL;
497 }
498 if (is_remote_node) {
499 *is_remote_node = FALSE;
500 }
501
502 xpath_string = crm_strdup_printf(XPATH_NODE, uname, uname, uname, uname);
503 if (cib_internal_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL,
504 &xml_search, cib_sync_call|cib_scope_local|cib_xpath,
505 NULL) == pcmk_ok) {
506 rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
507 } else {
508 rc = -ENXIO;
509 }
510 free(xpath_string);
511 free_xml(xml_search);
512
513 if (rc != pcmk_ok) {
514 crm_debug("Could not map node name '%s' to a UUID: %s",
515 uname, pcmk_strerror(rc));
516 } else {
517 crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
518 }
519 return rc;
520 }
521
522 int
523 query_node_uname(cib_t * the_cib, const char *uuid, char **uname)
524 {
525 int rc = pcmk_ok;
526 xmlNode *a_child = NULL;
527 xmlNode *xml_obj = NULL;
528 xmlNode *fragment = NULL;
529 const char *child_name = NULL;
530
531 CRM_ASSERT(uname != NULL);
532 CRM_ASSERT(uuid != NULL);
533
534 rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
535 cib_sync_call | cib_scope_local);
536 if (rc != pcmk_ok) {
537 return rc;
538 }
539
540 xml_obj = fragment;
541 CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), return -ENOMSG);
542 CRM_ASSERT(xml_obj != NULL);
543 crm_log_xml_trace(xml_obj, "Result section");
544
545 rc = -ENXIO;
546 *uname = NULL;
547
548 for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) {
549 if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) {
550 child_name = ID(a_child);
551 if (safe_str_eq(uuid, child_name)) {
552 child_name = crm_element_value(a_child, XML_ATTR_UNAME);
553 if (child_name != NULL) {
554 *uname = strdup(child_name);
555 rc = pcmk_ok;
556 }
557 break;
558 }
559 }
560 }
561
562 free_xml(fragment);
563 return rc;
564 }
565
566 int
567 set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value)
568 {
569 int rc = pcmk_ok;
570 char *attr_id = NULL;
571
572 CRM_CHECK(uuid != NULL, return -EINVAL);
573 CRM_CHECK(standby_value != NULL, return -EINVAL);
574
575 if (safe_str_eq(scope, "reboot") || safe_str_eq(scope, XML_CIB_TAG_STATUS)) {
576 scope = XML_CIB_TAG_STATUS;
577 attr_id = crm_strdup_printf("transient-standby-%.256s", uuid);
578
579 } else {
580 scope = XML_CIB_TAG_NODES;
581 attr_id = crm_strdup_printf("standby-%.256s", uuid);
582 }
583
584 rc = update_attr_delegate(the_cib, cib_sync_call, scope, uuid, NULL, NULL,
585 attr_id, "standby", standby_value, TRUE, NULL, NULL);
586
587 free(attr_id);
588 return rc;
589 }