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