pacemaker 2.1.4-dc6eb4362e
Scalable High-Availability cluster resource manager
cib_attrs.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2022 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
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>
29#include <crm/cib/internal.h>
30
31/* could also check for possible truncation */
32#define attr_snprintf(_str, _offset, _limit, ...) do { \
33 _offset += snprintf(_str + _offset, \
34 (_limit > _offset) ? _limit - _offset : 0, \
35 __VA_ARGS__); \
36 } while(0)
37
38#define XPATH_MAX 1024
39
40static pcmk__output_t *
41new_output_object(const char *ty)
42{
43 int rc = pcmk_rc_ok;
44 pcmk__output_t *out = NULL;
45 const char* argv[] = { "", NULL };
46 pcmk__supported_format_t formats[] = {
49 { NULL, NULL, NULL }
50 };
51
52 pcmk__register_formats(NULL, formats);
53 rc = pcmk__output_new(&out, ty, NULL, (char**)argv);
54 if ((rc != pcmk_rc_ok) || (out == NULL)) {
55 crm_err("Can't out due to internal error: %s", pcmk_rc_str(rc));
56 return NULL;
57 }
58
59 return out;
60}
61
62static int
63find_attr(pcmk__output_t *out, cib_t *cib, const char *attr, const char *section,
64 const char *node_uuid, const char *attr_set_type, const char *set_name,
65 const char *attr_id, const char *attr_name, char **value,
66 const char *user_name)
67{
68 int offset = 0;
69 int rc = pcmk_rc_ok;
70
71 const char *xpath_base = NULL;
72 char *xpath_string = NULL;
73 xmlNode *xml_search = NULL;
74 const char *set_type = NULL;
75 const char *node_type = NULL;
76
77 if (attr_set_type) {
78 set_type = attr_set_type;
79 } else {
80 set_type = XML_TAG_ATTR_SETS;
81 }
82
83 CRM_ASSERT(value != NULL);
84 *value = NULL;
85
86 if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
87 node_uuid = NULL;
88 set_type = XML_CIB_TAG_PROPSET;
89
91 NULL)) {
92 node_uuid = NULL;
93 set_type = XML_TAG_META_SETS;
94
95 } else if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
96 node_uuid = NULL;
97 section = XML_CIB_TAG_STATUS;
99
100 } else if (node_uuid == NULL) {
101 return EINVAL;
102 }
103
104 xpath_base = pcmk_cib_xpath_for(section);
105 if (xpath_base == NULL) {
106 crm_warn("%s CIB section not known", section);
107 return ENOMSG;
108 }
109
110 xpath_string = calloc(1, XPATH_MAX);
111 if (xpath_string == NULL) {
112 crm_perror(LOG_CRIT, "Could not create xpath");
113 return ENOMEM;
114 }
115 attr_snprintf(xpath_string, offset, XPATH_MAX, "%s", xpath_base);
116
117 if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
118 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s", node_type);
119
120 } else if (node_uuid) {
121 const char *node_type = XML_CIB_TAG_NODE;
122
123 if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
126 }
127 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s[@id='%s']", node_type,
128 node_uuid);
129 }
130
131 if (set_name) {
132 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s[@id='%.128s']", set_type,
133 set_name);
134 } else {
135 attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s", set_type);
136 }
137
138 attr_snprintf(xpath_string, offset, XPATH_MAX, "//nvpair[");
139 if (attr_id) {
140 attr_snprintf(xpath_string, offset, XPATH_MAX, "@id='%s'", attr_id);
141 }
142
143 if (attr_name) {
144 if (attr_id) {
145 attr_snprintf(xpath_string, offset, XPATH_MAX, " and ");
146 }
147 attr_snprintf(xpath_string, offset, XPATH_MAX, "@name='%.128s'", attr_name);
148 }
149 attr_snprintf(xpath_string, offset, XPATH_MAX, "]");
150 CRM_LOG_ASSERT(offset > 0);
151
152 rc = cib_internal_op(cib, CIB_OP_QUERY, NULL, xpath_string, NULL, &xml_search,
154 if (rc < 0) {
155 rc = pcmk_legacy2rc(rc);
156 crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s",
157 attr_name, section, crm_str(node_uuid), crm_str(set_name), xpath_string,
158 pcmk_rc_str(rc));
159 goto done;
160 } else {
161 rc = pcmk_rc_ok;
162 }
163
164 crm_log_xml_debug(xml_search, "Match");
165 if (xml_has_children(xml_search)) {
166 xmlNode *child = NULL;
167
168 rc = ENOTUNIQ;
169 out->info(out, "Multiple attributes match name=%s", attr_name);
170
171 for (child = pcmk__xml_first_child(xml_search); child != NULL;
172 child = pcmk__xml_next(child)) {
173 out->info(out, " Value: %s \t(id=%s)",
175 }
176
177 } else {
178 pcmk__str_update(value, crm_element_value(xml_search, attr));
179 }
180
181 done:
182 free(xpath_string);
183 free_xml(xml_search);
184 return rc;
185}
186
187int
188cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options, const char *section,
189 const char *node_uuid, const char *set_type, const char *set_name,
190 const char *attr_id, const char *attr_name, const char *attr_value,
191 const char *user_name, const char *node_type)
192{
193 const char *tag = NULL;
194 int rc = pcmk_rc_ok;
195 xmlNode *xml_top = NULL;
196 xmlNode *xml_obj = NULL;
197
198 char *local_attr_id = NULL;
199 char *local_set_name = NULL;
200
201 CRM_CHECK(section != NULL, return EINVAL);
202 CRM_CHECK(attr_value != NULL, return EINVAL);
203 CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
204
205 rc = find_attr(out, cib, XML_ATTR_ID, section, node_uuid, set_type, set_name,
206 attr_id, attr_name, &local_attr_id, user_name);
207 if (rc == pcmk_rc_ok) {
208 attr_id = local_attr_id;
209 goto do_modify;
210
211 } else if (rc != ENXIO) {
212 return rc;
213
214 /* } else if(attr_id == NULL) { */
215 /* return EINVAL; */
216
217 } else {
218 crm_trace("%s does not exist, create it", attr_name);
219 if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
220 node_uuid = NULL;
221 section = XML_CIB_TAG_STATUS;
223
224 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATUS);
225 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
226
227 } else if (pcmk__str_eq(section, XML_CIB_TAG_NODES, pcmk__str_casei)) {
228
229 if (node_uuid == NULL) {
230 return EINVAL;
231 }
232
233 if (pcmk__str_eq(node_type, "remote", pcmk__str_casei)) {
234 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_NODES);
235 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_NODE);
236 crm_xml_add(xml_obj, XML_ATTR_TYPE, "remote");
237 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
238 crm_xml_add(xml_obj, XML_ATTR_UNAME, node_uuid);
239 } else {
240 tag = XML_CIB_TAG_NODE;
241 }
242
243 } else if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
245 if (node_uuid == NULL) {
246 return EINVAL;
247 }
248
249 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATE);
250 crm_xml_add(xml_top, XML_ATTR_ID, node_uuid);
251 xml_obj = xml_top;
252
253 } else {
254 tag = section;
255 node_uuid = NULL;
256 }
257
258 if (set_name == NULL) {
259 if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
260 local_set_name = strdup(CIB_OPTIONS_FIRST);
261
262 } else if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
263 local_set_name = crm_strdup_printf("%s-%s", section,
265
266 } else if (node_uuid) {
267 local_set_name = crm_strdup_printf("%s-%s", section, node_uuid);
268
269 if (set_type) {
270 char *tmp_set_name = local_set_name;
271
272 local_set_name = crm_strdup_printf("%s-%s", tmp_set_name,
273 set_type);
274 free(tmp_set_name);
275 }
276 } else {
277 local_set_name = crm_strdup_printf("%s-options", section);
278 }
279 set_name = local_set_name;
280 }
281
282 if (attr_id == NULL) {
283 local_attr_id = crm_strdup_printf("%s-%s", set_name, attr_name);
284 crm_xml_sanitize_id(local_attr_id);
285 attr_id = local_attr_id;
286
287 } else if (attr_name == NULL) {
288 attr_name = attr_id;
289 }
290
291 crm_trace("Creating %s/%s", section, tag);
292 if (tag != NULL) {
293 xml_obj = create_xml_node(xml_obj, tag);
294 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
295 if (xml_top == NULL) {
296 xml_top = xml_obj;
297 }
298 }
299
300 if (node_uuid == NULL && !pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
301 if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
302 xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET);
303 } else {
304 xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS);
305 }
306
307 } else if (set_type) {
308 xml_obj = create_xml_node(xml_obj, set_type);
309
310 } else {
311 xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS);
312 }
313 crm_xml_add(xml_obj, XML_ATTR_ID, set_name);
314
315 if (xml_top == NULL) {
316 xml_top = xml_obj;
317 }
318 }
319
320 do_modify:
321 xml_obj = crm_create_nvpair_xml(xml_obj, attr_id, attr_name, attr_value);
322 if (xml_top == NULL) {
323 xml_top = xml_obj;
324 }
325
326 crm_log_xml_trace(xml_top, "update_attr");
327 rc = cib_internal_op(cib, CIB_OP_MODIFY, NULL, section, xml_top, NULL,
328 call_options | cib_quorum_override, user_name);
329 if (rc < 0) {
330 rc = pcmk_legacy2rc(rc);
331
332 out->err(out, "Error setting %s=%s (section=%s, set=%s): %s",
333 attr_name, attr_value, section, crm_str(set_name), pcmk_rc_str(rc));
334 crm_log_xml_info(xml_top, "Update");
335 } else {
336 rc = pcmk_rc_ok;
337 }
338
339 free(local_set_name);
340 free(local_attr_id);
341 free_xml(xml_top);
342
343 return rc;
344}
345
346int
347cib__read_node_attr(pcmk__output_t *out, cib_t *cib, const char *section,
348 const char *node_uuid, const char *set_type, const char *set_name,
349 const char *attr_id, const char *attr_name, char **attr_value,
350 const char *user_name)
351{
352 int rc = pcmk_rc_ok;
353
354 CRM_ASSERT(attr_value != NULL);
355 CRM_CHECK(section != NULL, return EINVAL);
356 CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
357
358 *attr_value = NULL;
359
360 rc = find_attr(out, cib, XML_NVPAIR_ATTR_VALUE, section, node_uuid, set_type,
361 set_name, attr_id, attr_name, attr_value, user_name);
362 if (rc != pcmk_rc_ok) {
363 crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s): %s",
364 attr_name, section, crm_str(set_name), crm_str(node_uuid), pcmk_strerror(rc));
365 }
366
367 return rc;
368}
369
370int
371cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options, const char *section,
372 const char *node_uuid, const char *set_type, const char *set_name,
373 const char *attr_id, const char *attr_name, const char *attr_value,
374 const char *user_name)
375{
376 int rc = pcmk_rc_ok;
377 xmlNode *xml_obj = NULL;
378 char *local_attr_id = NULL;
379
380 CRM_CHECK(section != NULL, return EINVAL);
381 CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
382
383 if (attr_id == NULL) {
384 rc = find_attr(out, cib, XML_ATTR_ID, section, node_uuid, set_type,
385 set_name, attr_id, attr_name, &local_attr_id,
386 user_name);
387 if (rc != pcmk_rc_ok) {
388 return rc;
389 }
390 attr_id = local_attr_id;
391 }
392
393 xml_obj = crm_create_nvpair_xml(NULL, attr_id, attr_name, attr_value);
394
395 rc = cib_internal_op(cib, CIB_OP_DELETE, NULL, section, xml_obj, NULL,
396 options | cib_quorum_override, user_name);
397 if (rc < 0) {
398 rc = pcmk_legacy2rc(rc);
399 } else {
400 rc = pcmk_rc_ok;
401 out->info(out, "Deleted %s %s: id=%s%s%s%s%s",
402 section, node_uuid ? "attribute" : "option", local_attr_id,
403 set_name ? " set=" : "", set_name ? set_name : "",
404 attr_name ? " name=" : "", attr_name ? attr_name : "");
405 }
406
407 free(local_attr_id);
408 free_xml(xml_obj);
409 return rc;
410}
411
412int
413find_nvpair_attr_delegate(cib_t *cib, const char *attr, const char *section,
414 const char *node_uuid, const char *attr_set_type, const char *set_name,
415 const char *attr_id, const char *attr_name, gboolean to_console,
416 char **value, const char *user_name)
417{
418 pcmk__output_t *out = NULL;
419 int rc = pcmk_ok;
420
421 out = new_output_object(to_console ? "text" : "log");
422 if (out == NULL) {
423 return pcmk_err_generic;
424 }
425
426 rc = find_attr(out, cib, attr, section, node_uuid, attr_set_type,
427 set_name, attr_id, attr_name, value, user_name);
428
429 out->finish(out, CRM_EX_OK, true, NULL);
431 return pcmk_rc2legacy(rc);
432}
433
434int
435update_attr_delegate(cib_t *cib, int call_options, const char *section,
436 const char *node_uuid, const char *set_type, const char *set_name,
437 const char *attr_id, const char *attr_name, const char *attr_value,
438 gboolean to_console, const char *user_name, const char *node_type)
439{
440 pcmk__output_t *out = NULL;
441 int rc = pcmk_ok;
442
443 out = new_output_object(to_console ? "text" : "log");
444 if (out == NULL) {
445 return pcmk_err_generic;
446 }
447
448 rc = cib__update_node_attr(out, cib, call_options, section, node_uuid, set_type,
449 set_name, attr_id, attr_name, attr_value, user_name,
450 node_type);
451
452 out->finish(out, CRM_EX_OK, true, NULL);
454 return pcmk_rc2legacy(rc);
455}
456
457int
458read_attr_delegate(cib_t *cib, const char *section, const char *node_uuid,
459 const char *set_type, const char *set_name, const char *attr_id,
460 const char *attr_name, char **attr_value, gboolean to_console,
461 const char *user_name)
462{
463 pcmk__output_t *out = NULL;
464 int rc = pcmk_ok;
465
466 out = new_output_object(to_console ? "text" : "log");
467 if (out == NULL) {
468 return pcmk_err_generic;
469 }
470
471 rc = cib__read_node_attr(out, cib, section, node_uuid, set_type, set_name,
472 attr_id, attr_name, attr_value, user_name);
473
474 out->finish(out, CRM_EX_OK, true, NULL);
476 return pcmk_rc2legacy(rc);
477}
478
479int
480delete_attr_delegate(cib_t *cib, int options, const char *section, const char *node_uuid,
481 const char *set_type, const char *set_name, const char *attr_id,
482 const char *attr_name, const char *attr_value, gboolean to_console,
483 const char *user_name)
484{
485 pcmk__output_t *out = NULL;
486 int rc = pcmk_ok;
487
488 out = new_output_object(to_console ? "text" : "log");
489 if (out == NULL) {
490 return pcmk_err_generic;
491 }
492
493 rc = cib__delete_node_attr(out, cib, options, section, node_uuid, set_type,
494 set_name, attr_id, attr_name, attr_value, user_name);
495
496 out->finish(out, CRM_EX_OK, true, NULL);
498 return pcmk_rc2legacy(rc);
499}
500
511static int
512get_uuid_from_result(xmlNode *result, char **uuid, int *is_remote)
513{
514 int rc = -ENXIO;
515 const char *tag;
516 const char *parsed_uuid = NULL;
517 int parsed_is_remote = FALSE;
518
519 if (result == NULL) {
520 return rc;
521 }
522
523 /* If there are multiple results, the first is sufficient */
524 tag = (const char *) (result->name);
525 if (pcmk__str_eq(tag, "xpath-query", pcmk__str_casei)) {
526 result = pcmk__xml_first_child(result);
527 CRM_CHECK(result != NULL, return rc);
528 tag = (const char *) (result->name);
529 }
530
531 if (pcmk__str_eq(tag, XML_CIB_TAG_NODE, pcmk__str_casei)) {
532 /* Result is <node> tag from <nodes> section */
533
534 if (pcmk__str_eq(crm_element_value(result, XML_ATTR_TYPE), "remote", pcmk__str_casei)) {
536 parsed_is_remote = TRUE;
537 } else {
538 parsed_uuid = ID(result);
539 parsed_is_remote = FALSE;
540 }
541
542 } else if (pcmk__str_eq(tag, XML_CIB_TAG_RESOURCE, pcmk__str_casei)) {
543 /* Result is <primitive> for ocf:pacemaker:remote resource */
544
545 parsed_uuid = ID(result);
546 parsed_is_remote = TRUE;
547
548 } else if (pcmk__str_eq(tag, XML_CIB_TAG_NVPAIR, pcmk__str_casei)) {
549 /* Result is remote-node parameter of <primitive> for guest node */
550
552 parsed_is_remote = TRUE;
553
554 } else if (pcmk__str_eq(tag, XML_CIB_TAG_STATE, pcmk__str_casei)) {
555 /* Result is <node_state> tag from <status> section */
556
559 parsed_is_remote = TRUE;
560 }
561 }
562
563 if (parsed_uuid) {
564 if (uuid) {
565 *uuid = strdup(parsed_uuid);
566 }
567 if (is_remote) {
568 *is_remote = parsed_is_remote;
569 }
570 rc = pcmk_ok;
571 }
572
573 return rc;
574}
575
576/* Search string to find a node by name, as:
577 * - cluster or remote node in nodes section
578 * - remote node in resources section
579 * - guest node in resources section
580 * - orphaned remote node or bundle guest node in status section
581 */
582#define XPATH_UPPER_TRANS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
583#define XPATH_LOWER_TRANS "abcdefghijklmnopqrstuvwxyz"
584#define XPATH_NODE \
585 "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
586 "/" XML_CIB_TAG_NODE "[translate(@" XML_ATTR_UNAME ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
587 "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
588 "/" XML_CIB_TAG_RESOURCE \
589 "[@class='ocf'][@provider='pacemaker'][@type='remote'][translate(@id,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
590 "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
591 "/" XML_CIB_TAG_RESOURCE "/" XML_TAG_META_SETS "/" XML_CIB_TAG_NVPAIR \
592 "[@name='" XML_RSC_ATTR_REMOTE_NODE "'][translate(@value,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
593 "|/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS "/" XML_CIB_TAG_STATE \
594 "[@" XML_NODE_IS_REMOTE "='true'][translate(@" XML_ATTR_UUID ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']"
595
596int
597query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
598{
599 int rc = pcmk_ok;
600 char *xpath_string;
601 xmlNode *xml_search = NULL;
602 char *host_lowercase = NULL;
603
604 CRM_ASSERT(uname != NULL);
605
606 host_lowercase = g_ascii_strdown(uname, -1);
607
608 if (uuid) {
609 *uuid = NULL;
610 }
611 if (is_remote_node) {
612 *is_remote_node = FALSE;
613 }
614
615 xpath_string = crm_strdup_printf(XPATH_NODE, host_lowercase, host_lowercase, host_lowercase, host_lowercase);
616 if (cib_internal_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL,
618 NULL) == pcmk_ok) {
619 rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
620 } else {
621 rc = -ENXIO;
622 }
623 free(xpath_string);
624 free_xml(xml_search);
625 g_free(host_lowercase);
626
627 if (rc != pcmk_ok) {
628 crm_debug("Could not map node name '%s' to a UUID: %s",
629 uname, pcmk_strerror(rc));
630 } else {
631 crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
632 }
633 return rc;
634}
635
636int
637query_node_uname(cib_t * the_cib, const char *uuid, char **uname)
638{
639 int rc = pcmk_ok;
640 xmlNode *a_child = NULL;
641 xmlNode *xml_obj = NULL;
642 xmlNode *fragment = NULL;
643 const char *child_name = NULL;
644
645 CRM_ASSERT(uname != NULL);
646 CRM_ASSERT(uuid != NULL);
647
648 rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
650 if (rc != pcmk_ok) {
651 return rc;
652 }
653
654 xml_obj = fragment;
655 CRM_CHECK(pcmk__str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES, pcmk__str_casei),
656 return -ENOMSG);
657 CRM_ASSERT(xml_obj != NULL);
658 crm_log_xml_trace(xml_obj, "Result section");
659
660 rc = -ENXIO;
661 *uname = NULL;
662
663 for (a_child = pcmk__xml_first_child(xml_obj); a_child != NULL;
664 a_child = pcmk__xml_next(a_child)) {
665
666 if (pcmk__str_eq((const char *)a_child->name, XML_CIB_TAG_NODE,
668 child_name = ID(a_child);
669 if (pcmk__str_eq(uuid, child_name, pcmk__str_casei)) {
670 child_name = crm_element_value(a_child, XML_ATTR_UNAME);
671 if (child_name != NULL) {
672 *uname = strdup(child_name);
673 rc = pcmk_ok;
674 }
675 break;
676 }
677 }
678 }
679
680 free_xml(fragment);
681 return rc;
682}
683
684int
685set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value)
686{
687 int rc = pcmk_ok;
688 char *attr_id = NULL;
689
690 CRM_CHECK(uuid != NULL, return -EINVAL);
691 CRM_CHECK(standby_value != NULL, return -EINVAL);
692
693 if (pcmk__strcase_any_of(scope, "reboot", XML_CIB_TAG_STATUS, NULL)) {
694 scope = XML_CIB_TAG_STATUS;
695 attr_id = crm_strdup_printf("transient-standby-%.256s", uuid);
696
697 } else {
698 scope = XML_CIB_TAG_NODES;
699 attr_id = crm_strdup_printf("standby-%.256s", uuid);
700 }
701
702 rc = update_attr_delegate(the_cib, cib_sync_call, scope, uuid, NULL, NULL,
703 attr_id, "standby", standby_value, TRUE, NULL, NULL);
704
705 free(attr_id);
706 return rc;
707}
#define CIB_OP_MODIFY
Definition: internal.h:25
int cib_internal_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, xmlNode **output_data, int call_options, const char *user_name)
Definition: cib_utils.c:645
#define CIB_OP_QUERY
Definition: internal.h:23
#define CIB_OP_DELETE
Definition: internal.h:26
int find_nvpair_attr_delegate(cib_t *cib, const char *attr, const char *section, const char *node_uuid, const char *attr_set_type, const char *set_name, const char *attr_id, const char *attr_name, gboolean to_console, char **value, const char *user_name)
Definition: cib_attrs.c:413
int update_attr_delegate(cib_t *cib, int call_options, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *attr_value, gboolean to_console, const char *user_name, const char *node_type)
Definition: cib_attrs.c:435
int query_node_uname(cib_t *the_cib, const char *uuid, char **uname)
Definition: cib_attrs.c:637
int read_attr_delegate(cib_t *cib, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, char **attr_value, gboolean to_console, const char *user_name)
Definition: cib_attrs.c:458
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
Definition: cib_attrs.c:597
int cib__read_node_attr(pcmk__output_t *out, cib_t *cib, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, char **attr_value, const char *user_name)
Definition: cib_attrs.c:347
int cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *attr_value, const char *user_name, const char *node_type)
Definition: cib_attrs.c:188
#define XPATH_NODE
Definition: cib_attrs.c:584
int set_standby(cib_t *the_cib, const char *uuid, const char *scope, const char *standby_value)
Definition: cib_attrs.c:685
int cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *attr_value, const char *user_name)
Definition: cib_attrs.c:371
#define XPATH_MAX
Definition: cib_attrs.c:38
int delete_attr_delegate(cib_t *cib, int options, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *attr_value, gboolean to_console, const char *user_name)
Definition: cib_attrs.c:480
#define attr_snprintf(_str, _offset, _limit,...)
Definition: cib_attrs.c:32
@ cib_scope_local
Definition: cib_types.h:59
@ cib_xpath
Definition: cib_types.h:52
@ cib_sync_call
Definition: cib_types.h:61
@ cib_quorum_override
Definition: cib_types.h:65
const char * pcmk_cib_xpath_for(const char *element_name)
Get the XPath needed to find a specified CIB element name.
Definition: cib.c:110
bool pcmk__xe_attr_is_true(xmlNodePtr node, const char *name)
Definition: nvpair.c:986
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
char uname[MAX_NAME]
Definition: cpg.c:5
A dumping ground.
#define crm_log_xml_info(xml, text)
Definition: logging.h:370
#define crm_str(x)
Definition: logging.h:384
#define crm_info(fmt, args...)
Definition: logging.h:361
#define crm_warn(fmt, args...)
Definition: logging.h:359
#define crm_log_xml_debug(xml, text)
Definition: logging.h:371
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:210
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:309
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define crm_debug(fmt, args...)
Definition: logging.h:363
#define crm_err(fmt, args...)
Definition: logging.h:358
#define crm_log_xml_trace(xml, text)
Definition: logging.h:372
#define crm_trace(fmt, args...)
Definition: logging.h:364
#define ID(x)
Definition: msg_xml.h:460
#define XML_ATTR_UNAME
Definition: msg_xml.h:157
#define XML_TAG_TRANSIENT_NODEATTRS
Definition: msg_xml.h:409
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:384
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:192
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:204
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:190
#define XML_CIB_TAG_TICKETS
Definition: msg_xml.h:432
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:209
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:285
#define XML_ATTR_ID
Definition: msg_xml.h:135
#define XML_TAG_META_SETS
Definition: msg_xml.h:210
#define XML_CIB_TAG_PROPSET
Definition: msg_xml.h:208
#define XML_ATTR_TYPE
Definition: msg_xml.h:138
#define CIB_OPTIONS_FIRST
Definition: msg_xml.h:88
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:187
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:206
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:185
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:205
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:191
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:220
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
xmlNode * crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name, const char *value)
Create an XML name/value pair.
Definition: nvpair.c:845
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:323
Formatted output for pacemaker tools.
void pcmk__output_free(pcmk__output_t *out)
Definition: output.c:19
#define PCMK__SUPPORTED_FORMAT_TEXT
#define PCMK__SUPPORTED_FORMAT_LOG
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:31
void pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *table)
Definition: output.c:99
pcmk__action_result_t result
Definition: pcmk_fence.c:34
node_type
Definition: pe_types.h:71
#define ENOTUNIQ
Definition: portability.h:120
const char * pcmk_strerror(int rc)
Definition: results.c:58
#define pcmk_err_generic
Definition: results.h:71
#define CRM_ASSERT(expr)
Definition: results.h:42
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:370
@ CRM_EX_OK
Success.
Definition: results.h:239
@ pcmk_rc_ok
Definition: results.h:146
#define pcmk_ok
Definition: results.h:68
int pcmk_rc2legacy(int rc)
Definition: results.c:415
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:428
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1188
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:931
@ pcmk__str_none
@ pcmk__str_casei
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:92
cib_api_operations_t * cmds
Definition: cib_types.h:147
This structure contains everything that makes up a single output formatter.
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
Wrappers for and extensions to libxml2.
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:2028
void free_xml(xmlNode *child)
Definition: xml.c:824
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
Definition: xml.c:1129
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696