pacemaker 2.1.5-a3f44794f94
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
31static pcmk__output_t *
32new_output_object(const char *ty)
33{
34 int rc = pcmk_rc_ok;
35 pcmk__output_t *out = NULL;
36 const char* argv[] = { "", NULL };
37 pcmk__supported_format_t formats[] = {
40 { NULL, NULL, NULL }
41 };
42
43 pcmk__register_formats(NULL, formats);
44 rc = pcmk__output_new(&out, ty, NULL, (char**)argv);
45 if ((rc != pcmk_rc_ok) || (out == NULL)) {
46 crm_err("Can't out due to internal error: %s", pcmk_rc_str(rc));
47 return NULL;
48 }
49
50 return out;
51}
52
53static int
54find_attr(cib_t *cib, const char *section, const char *node_uuid,
55 const char *attr_set_type, const char *set_name, const char *attr_id,
56 const char *attr_name, const char *user_name, xmlNode **result)
57{
58 int rc = pcmk_rc_ok;
59
60 const char *xpath_base = NULL;
61 GString *xpath = NULL;
62 xmlNode *xml_search = NULL;
63 const char *set_type = NULL;
64 const char *node_type = NULL;
65
66 if (attr_set_type) {
67 set_type = attr_set_type;
68 } else {
69 set_type = XML_TAG_ATTR_SETS;
70 }
71
72 if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
73 node_uuid = NULL;
74 set_type = XML_CIB_TAG_PROPSET;
75
77 NULL)) {
78 node_uuid = NULL;
79 set_type = XML_TAG_META_SETS;
80
81 } else if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
82 node_uuid = NULL;
83 section = XML_CIB_TAG_STATUS;
85
86 } else if (node_uuid == NULL) {
87 return EINVAL;
88 }
89
90 xpath_base = pcmk_cib_xpath_for(section);
91 if (xpath_base == NULL) {
92 crm_warn("%s CIB section not known", section);
93 return ENOMSG;
94 }
95
96 xpath = g_string_sized_new(1024);
97 g_string_append(xpath, xpath_base);
98
99 if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
100 pcmk__g_strcat(xpath, "//", node_type, NULL);
101
102 } else if (node_uuid) {
103 const char *node_type = XML_CIB_TAG_NODE;
104
105 if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
108 }
109 pcmk__g_strcat(xpath,
110 "//", node_type, "[@" XML_ATTR_ID "='", node_uuid, "']",
111 NULL);
112 }
113
114 pcmk__g_strcat(xpath, "//", set_type, NULL);
115 if (set_name) {
116 pcmk__g_strcat(xpath, "[@" XML_ATTR_ID "='", set_name, "']", NULL);
117 }
118
119 g_string_append(xpath, "//nvpair");
120
121 if (attr_id && attr_name) {
122 pcmk__g_strcat(xpath,
123 "[@" XML_ATTR_ID "='", attr_id, "' "
124 "and @" XML_ATTR_NAME "='", attr_name, "']", NULL);
125
126 } else if (attr_id) {
127 pcmk__g_strcat(xpath, "[@" XML_ATTR_ID "='", attr_id, "']", NULL);
128
129 } else if (attr_name) {
130 pcmk__g_strcat(xpath, "[@" XML_ATTR_NAME "='", attr_name, "']", NULL);
131 }
132
134 (const char *) xpath->str, NULL, &xml_search,
136 if (rc < 0) {
137 rc = pcmk_legacy2rc(rc);
138 crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s",
139 attr_name, section, pcmk__s(node_uuid, "<null>"),
140 pcmk__s(set_name, "<null>"), (const char *) xpath->str,
141 pcmk_rc_str(rc));
142 } else {
143 rc = pcmk_rc_ok;
144 crm_log_xml_debug(xml_search, "Match");
145 }
146
147 g_string_free(xpath, TRUE);
148 *result = xml_search;
149 return rc;
150}
151
152static int
153handle_multiples(pcmk__output_t *out, xmlNode *search, const char *attr_name)
154{
155 if (xml_has_children(search)) {
156 xmlNode *child = NULL;
157 out->info(out, "Multiple attributes match name=%s", attr_name);
158
159 for (child = pcmk__xml_first_child(search); child != NULL;
160 child = pcmk__xml_next(child)) {
161 out->info(out, " Value: %s \t(id=%s)",
163 }
164
165 return ENOTUNIQ;
166
167 } else {
168 return pcmk_rc_ok;
169 }
170}
171
172int
173cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options, const char *section,
174 const char *node_uuid, const char *set_type, const char *set_name,
175 const char *attr_id, const char *attr_name, const char *attr_value,
176 const char *user_name, const char *node_type)
177{
178 const char *tag = NULL;
179 int rc = pcmk_rc_ok;
180 xmlNode *xml_top = NULL;
181 xmlNode *xml_obj = NULL;
182 xmlNode *xml_search = NULL;
183
184 char *local_attr_id = NULL;
185 char *local_set_name = NULL;
186
187 CRM_CHECK(section != NULL, return EINVAL);
188 CRM_CHECK(attr_value != NULL, return EINVAL);
189 CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
190
191 rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id,
192 attr_name, user_name, &xml_search);
193
194 if (rc == pcmk_rc_ok) {
195 if (handle_multiples(out, xml_search, attr_name) == ENOTUNIQ) {
196 free_xml(xml_search);
197 return ENOTUNIQ;
198 } else {
199 pcmk__str_update(&local_attr_id, crm_element_value(xml_search, XML_ATTR_ID));
200 attr_id = local_attr_id;
201 free_xml(xml_search);
202 goto do_modify;
203 }
204
205 } else if (rc != ENXIO) {
206 free_xml(xml_search);
207 return rc;
208
209 /* } else if(attr_id == NULL) { */
210 /* return EINVAL; */
211
212 } else {
213 free_xml(xml_search);
214 crm_trace("%s does not exist, create it", attr_name);
215 if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
216 node_uuid = NULL;
217 section = XML_CIB_TAG_STATUS;
219
220 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATUS);
221 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
222
223 } else if (pcmk__str_eq(section, XML_CIB_TAG_NODES, pcmk__str_casei)) {
224
225 if (node_uuid == NULL) {
226 return EINVAL;
227 }
228
229 if (pcmk__str_eq(node_type, "remote", pcmk__str_casei)) {
230 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_NODES);
231 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_NODE);
232 crm_xml_add(xml_obj, XML_ATTR_TYPE, "remote");
233 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
234 crm_xml_add(xml_obj, XML_ATTR_UNAME, node_uuid);
235 } else {
236 tag = XML_CIB_TAG_NODE;
237 }
238
239 } else if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
241 if (node_uuid == NULL) {
242 return EINVAL;
243 }
244
245 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATE);
246 crm_xml_add(xml_top, XML_ATTR_ID, node_uuid);
247 xml_obj = xml_top;
248
249 } else {
250 tag = section;
251 node_uuid = NULL;
252 }
253
254 if (set_name == NULL) {
255 if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
256 local_set_name = strdup(CIB_OPTIONS_FIRST);
257
258 } else if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
259 local_set_name = crm_strdup_printf("%s-%s", section,
261
262 } else if (node_uuid) {
263 local_set_name = crm_strdup_printf("%s-%s", section, node_uuid);
264
265 if (set_type) {
266 char *tmp_set_name = local_set_name;
267
268 local_set_name = crm_strdup_printf("%s-%s", tmp_set_name,
269 set_type);
270 free(tmp_set_name);
271 }
272 } else {
273 local_set_name = crm_strdup_printf("%s-options", section);
274 }
275 set_name = local_set_name;
276 }
277
278 if (attr_id == NULL) {
279 local_attr_id = crm_strdup_printf("%s-%s", set_name, attr_name);
280 crm_xml_sanitize_id(local_attr_id);
281 attr_id = local_attr_id;
282
283 } else if (attr_name == NULL) {
284 attr_name = attr_id;
285 }
286
287 crm_trace("Creating %s/%s", section, tag);
288 if (tag != NULL) {
289 xml_obj = create_xml_node(xml_obj, tag);
290 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
291 if (xml_top == NULL) {
292 xml_top = xml_obj;
293 }
294 }
295
296 if (node_uuid == NULL && !pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
297 if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
298 xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET);
299 } else {
300 xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS);
301 }
302
303 } else if (set_type) {
304 xml_obj = create_xml_node(xml_obj, set_type);
305
306 } else {
307 xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS);
308 }
309 crm_xml_add(xml_obj, XML_ATTR_ID, set_name);
310
311 if (xml_top == NULL) {
312 xml_top = xml_obj;
313 }
314 }
315
316 do_modify:
317 xml_obj = crm_create_nvpair_xml(xml_obj, attr_id, attr_name, attr_value);
318 if (xml_top == NULL) {
319 xml_top = xml_obj;
320 }
321
322 crm_log_xml_trace(xml_top, "update_attr");
323 rc = cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, xml_top,
324 NULL, call_options|cib_quorum_override, user_name);
325 if (rc < 0) {
326 rc = pcmk_legacy2rc(rc);
327
328 out->err(out, "Error setting %s=%s (section=%s, set=%s): %s",
329 attr_name, attr_value, section, pcmk__s(set_name, "<null>"),
330 pcmk_rc_str(rc));
331 crm_log_xml_info(xml_top, "Update");
332 } else {
333 rc = pcmk_rc_ok;
334 }
335
336 free(local_set_name);
337 free(local_attr_id);
338 free_xml(xml_top);
339
340 return rc;
341}
342
343int
344cib__get_node_attrs(pcmk__output_t *out, cib_t *cib, const char *section,
345 const char *node_uuid, const char *set_type, const char *set_name,
346 const char *attr_id, const char *attr_name, const char *user_name,
347 xmlNode **result)
348{
349 int rc = pcmk_rc_ok;
350
351 CRM_ASSERT(result != NULL);
352 CRM_CHECK(section != NULL, return EINVAL);
353
354 *result = NULL;
355
356 rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id, attr_name,
357 user_name, result);
358
359 if (rc != pcmk_rc_ok) {
360 crm_trace("Query failed for attribute %s (section=%s node=%s set=%s): %s",
361 pcmk__s(attr_name, "with unspecified name"),
362 section, pcmk__s(set_name, "<null>"),
363 pcmk__s(node_uuid, "<null>"), pcmk_strerror(rc));
364 }
365
366 return rc;
367}
368
369int
370cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options, const char *section,
371 const char *node_uuid, const char *set_type, const char *set_name,
372 const char *attr_id, const char *attr_name, const char *attr_value,
373 const char *user_name)
374{
375 int rc = pcmk_rc_ok;
376 xmlNode *xml_obj = NULL;
377 xmlNode *xml_search = 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(cib, section, node_uuid, set_type, set_name, attr_id,
385 attr_name, user_name, &xml_search);
386
387 if (rc != pcmk_rc_ok || handle_multiples(out, xml_search, attr_name) == ENOTUNIQ) {
388 free_xml(xml_search);
389 return rc;
390 } else {
391 pcmk__str_update(&local_attr_id, crm_element_value(xml_search, XML_ATTR_ID));
392 attr_id = local_attr_id;
393 free_xml(xml_search);
394 }
395 }
396
397 xml_obj = crm_create_nvpair_xml(NULL, attr_id, attr_name, attr_value);
398
399 rc = cib_internal_op(cib, PCMK__CIB_REQUEST_DELETE, NULL, section, xml_obj,
400 NULL, options|cib_quorum_override, user_name);
401 if (rc < 0) {
402 rc = pcmk_legacy2rc(rc);
403 } else {
404 rc = pcmk_rc_ok;
405 out->info(out, "Deleted %s %s: id=%s%s%s%s%s",
406 section, node_uuid ? "attribute" : "option", local_attr_id,
407 set_name ? " set=" : "", set_name ? set_name : "",
408 attr_name ? " name=" : "", attr_name ? attr_name : "");
409 }
410
411 free(local_attr_id);
412 free_xml(xml_obj);
413 return rc;
414}
415
416int
417find_nvpair_attr_delegate(cib_t *cib, const char *attr, const char *section,
418 const char *node_uuid, const char *attr_set_type, const char *set_name,
419 const char *attr_id, const char *attr_name, gboolean to_console,
420 char **value, const char *user_name)
421{
422 pcmk__output_t *out = NULL;
423 xmlNode *xml_search = NULL;
424 int rc = pcmk_ok;
425
426 out = new_output_object(to_console ? "text" : "log");
427 if (out == NULL) {
428 return pcmk_err_generic;
429 }
430
431 rc = find_attr(cib, section, node_uuid, attr_set_type, set_name, attr_id,
432 attr_name, user_name, &xml_search);
433
434 if (rc == pcmk_rc_ok) {
435 rc = handle_multiples(out, xml_search, attr_name);
436
437 if (rc == pcmk_rc_ok) {
438 pcmk__str_update(value, crm_element_value(xml_search, attr));
439 }
440 }
441
442 out->finish(out, CRM_EX_OK, true, NULL);
443 free_xml(xml_search);
445 return pcmk_rc2legacy(rc);
446}
447
448int
449update_attr_delegate(cib_t *cib, int call_options, const char *section,
450 const char *node_uuid, const char *set_type, const char *set_name,
451 const char *attr_id, const char *attr_name, const char *attr_value,
452 gboolean to_console, const char *user_name, const char *node_type)
453{
454 pcmk__output_t *out = NULL;
455 int rc = pcmk_ok;
456
457 out = new_output_object(to_console ? "text" : "log");
458 if (out == NULL) {
459 return pcmk_err_generic;
460 }
461
462 rc = cib__update_node_attr(out, cib, call_options, section, node_uuid, set_type,
463 set_name, attr_id, attr_name, attr_value, user_name,
464 node_type);
465
466 out->finish(out, CRM_EX_OK, true, NULL);
468 return pcmk_rc2legacy(rc);
469}
470
471int
472read_attr_delegate(cib_t *cib, const char *section, const char *node_uuid,
473 const char *set_type, const char *set_name, const char *attr_id,
474 const char *attr_name, char **attr_value, gboolean to_console,
475 const char *user_name)
476{
477 pcmk__output_t *out = NULL;
478 xmlNode *result = NULL;
479 int rc = pcmk_ok;
480
481 out = new_output_object(to_console ? "text" : "log");
482 if (out == NULL) {
483 return pcmk_err_generic;
484 }
485
486 rc = cib__get_node_attrs(out, cib, section, node_uuid, set_type, set_name,
487 attr_id, attr_name, user_name, &result);
488
489 if (rc == pcmk_rc_ok) {
490 if (!xml_has_children(result)) {
492 } else {
493 rc = ENOTUNIQ;
494 }
495 }
496
497 out->finish(out, CRM_EX_OK, true, NULL);
500 return pcmk_rc2legacy(rc);
501}
502
503int
504delete_attr_delegate(cib_t *cib, int options, const char *section, const char *node_uuid,
505 const char *set_type, const char *set_name, const char *attr_id,
506 const char *attr_name, const char *attr_value, gboolean to_console,
507 const char *user_name)
508{
509 pcmk__output_t *out = NULL;
510 int rc = pcmk_ok;
511
512 out = new_output_object(to_console ? "text" : "log");
513 if (out == NULL) {
514 return pcmk_err_generic;
515 }
516
517 rc = cib__delete_node_attr(out, cib, options, section, node_uuid, set_type,
518 set_name, attr_id, attr_name, attr_value, user_name);
519
520 out->finish(out, CRM_EX_OK, true, NULL);
522 return pcmk_rc2legacy(rc);
523}
524
535static int
536get_uuid_from_result(xmlNode *result, char **uuid, int *is_remote)
537{
538 int rc = -ENXIO;
539 const char *tag;
540 const char *parsed_uuid = NULL;
541 int parsed_is_remote = FALSE;
542
543 if (result == NULL) {
544 return rc;
545 }
546
547 /* If there are multiple results, the first is sufficient */
548 tag = (const char *) (result->name);
549 if (pcmk__str_eq(tag, "xpath-query", pcmk__str_casei)) {
550 result = pcmk__xml_first_child(result);
551 CRM_CHECK(result != NULL, return rc);
552 tag = (const char *) (result->name);
553 }
554
555 if (pcmk__str_eq(tag, XML_CIB_TAG_NODE, pcmk__str_casei)) {
556 /* Result is <node> tag from <nodes> section */
557
558 if (pcmk__str_eq(crm_element_value(result, XML_ATTR_TYPE), "remote", pcmk__str_casei)) {
560 parsed_is_remote = TRUE;
561 } else {
562 parsed_uuid = ID(result);
563 parsed_is_remote = FALSE;
564 }
565
566 } else if (pcmk__str_eq(tag, XML_CIB_TAG_RESOURCE, pcmk__str_casei)) {
567 /* Result is <primitive> for ocf:pacemaker:remote resource */
568
569 parsed_uuid = ID(result);
570 parsed_is_remote = TRUE;
571
572 } else if (pcmk__str_eq(tag, XML_CIB_TAG_NVPAIR, pcmk__str_casei)) {
573 /* Result is remote-node parameter of <primitive> for guest node */
574
576 parsed_is_remote = TRUE;
577
578 } else if (pcmk__str_eq(tag, XML_CIB_TAG_STATE, pcmk__str_casei)) {
579 /* Result is <node_state> tag from <status> section */
580
583 parsed_is_remote = TRUE;
584 }
585 }
586
587 if (parsed_uuid) {
588 if (uuid) {
589 *uuid = strdup(parsed_uuid);
590 }
591 if (is_remote) {
592 *is_remote = parsed_is_remote;
593 }
594 rc = pcmk_ok;
595 }
596
597 return rc;
598}
599
600/* Search string to find a node by name, as:
601 * - cluster or remote node in nodes section
602 * - remote node in resources section
603 * - guest node in resources section
604 * - orphaned remote node or bundle guest node in status section
605 */
606#define XPATH_UPPER_TRANS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
607#define XPATH_LOWER_TRANS "abcdefghijklmnopqrstuvwxyz"
608#define XPATH_NODE \
609 "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
610 "/" XML_CIB_TAG_NODE "[translate(@" XML_ATTR_UNAME ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
611 "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
612 "/" XML_CIB_TAG_RESOURCE \
613 "[@class='ocf'][@provider='pacemaker'][@type='remote'][translate(@id,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
614 "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
615 "/" XML_CIB_TAG_RESOURCE "/" XML_TAG_META_SETS "/" XML_CIB_TAG_NVPAIR \
616 "[@name='" XML_RSC_ATTR_REMOTE_NODE "'][translate(@value,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
617 "|/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS "/" XML_CIB_TAG_STATE \
618 "[@" XML_NODE_IS_REMOTE "='true'][translate(@" XML_ATTR_UUID ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']"
619
620int
621query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
622{
623 int rc = pcmk_ok;
624 char *xpath_string;
625 xmlNode *xml_search = NULL;
626 char *host_lowercase = NULL;
627
628 CRM_ASSERT(uname != NULL);
629
630 host_lowercase = g_ascii_strdown(uname, -1);
631
632 if (uuid) {
633 *uuid = NULL;
634 }
635 if (is_remote_node) {
636 *is_remote_node = FALSE;
637 }
638
639 xpath_string = crm_strdup_printf(XPATH_NODE, host_lowercase, host_lowercase, host_lowercase, host_lowercase);
640 if (cib_internal_op(the_cib, PCMK__CIB_REQUEST_QUERY, NULL, xpath_string,
641 NULL, &xml_search,
643 NULL) == pcmk_ok) {
644 rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
645 } else {
646 rc = -ENXIO;
647 }
648 free(xpath_string);
649 free_xml(xml_search);
650 g_free(host_lowercase);
651
652 if (rc != pcmk_ok) {
653 crm_debug("Could not map node name '%s' to a UUID: %s",
654 uname, pcmk_strerror(rc));
655 } else {
656 crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
657 }
658 return rc;
659}
660
661int
662query_node_uname(cib_t * the_cib, const char *uuid, char **uname)
663{
664 int rc = pcmk_ok;
665 xmlNode *a_child = NULL;
666 xmlNode *xml_obj = NULL;
667 xmlNode *fragment = NULL;
668 const char *child_name = NULL;
669
670 CRM_ASSERT(uname != NULL);
671 CRM_ASSERT(uuid != NULL);
672
673 rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
675 if (rc != pcmk_ok) {
676 return rc;
677 }
678
679 xml_obj = fragment;
680 CRM_CHECK(pcmk__str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES, pcmk__str_casei),
681 return -ENOMSG);
682 CRM_ASSERT(xml_obj != NULL);
683 crm_log_xml_trace(xml_obj, "Result section");
684
685 rc = -ENXIO;
686 *uname = NULL;
687
688 for (a_child = pcmk__xml_first_child(xml_obj); a_child != NULL;
689 a_child = pcmk__xml_next(a_child)) {
690
691 if (pcmk__str_eq((const char *)a_child->name, XML_CIB_TAG_NODE,
693 child_name = ID(a_child);
694 if (pcmk__str_eq(uuid, child_name, pcmk__str_casei)) {
695 child_name = crm_element_value(a_child, XML_ATTR_UNAME);
696 if (child_name != NULL) {
697 *uname = strdup(child_name);
698 rc = pcmk_ok;
699 }
700 break;
701 }
702 }
703 }
704
705 free_xml(fragment);
706 return rc;
707}
708
709int
710set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value)
711{
712 int rc = pcmk_ok;
713 char *attr_id = NULL;
714
715 CRM_CHECK(uuid != NULL, return -EINVAL);
716 CRM_CHECK(standby_value != NULL, return -EINVAL);
717
718 if (pcmk__strcase_any_of(scope, "reboot", XML_CIB_TAG_STATUS, NULL)) {
719 scope = XML_CIB_TAG_STATUS;
720 attr_id = crm_strdup_printf("transient-standby-%.256s", uuid);
721
722 } else {
723 scope = XML_CIB_TAG_NODES;
724 attr_id = crm_strdup_printf("standby-%.256s", uuid);
725 }
726
727 rc = update_attr_delegate(the_cib, cib_sync_call, scope, uuid, NULL, NULL,
728 attr_id, "standby", standby_value, TRUE, NULL, NULL);
729
730 free(attr_id);
731 return rc;
732}
#define PCMK__CIB_REQUEST_QUERY
Definition: internal.h:24
#define PCMK__CIB_REQUEST_DELETE
Definition: internal.h:27
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:648
#define PCMK__CIB_REQUEST_MODIFY
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:417
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:449
int query_node_uname(cib_t *the_cib, const char *uuid, char **uname)
Definition: cib_attrs.c:662
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:472
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
Definition: cib_attrs.c:621
int cib__get_node_attrs(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, const char *user_name, xmlNode **result)
Definition: cib_attrs.c:344
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:173
#define XPATH_NODE
Definition: cib_attrs.c:608
int set_standby(cib_t *the_cib, const char *uuid, const char *scope, const char *standby_value)
Definition: cib_attrs.c:710
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:370
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:504
@ 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(const xmlNode *node, const char *name)
Definition: nvpair.c:975
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:371
#define crm_info(fmt, args...)
Definition: logging.h:362
#define crm_warn(fmt, args...)
Definition: logging.h:360
#define crm_log_xml_debug(xml, text)
Definition: logging.h:372
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
#define crm_debug(fmt, args...)
Definition: logging.h:364
#define crm_err(fmt, args...)
Definition: logging.h:359
#define crm_log_xml_trace(xml, text)
Definition: logging.h:373
#define crm_trace(fmt, args...)
Definition: logging.h:365
#define ID(x)
Definition: msg_xml.h:468
#define XML_ATTR_UNAME
Definition: msg_xml.h:157
#define XML_TAG_TRANSIENT_NODEATTRS
Definition: msg_xml.h:417
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:392
#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:440
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:209
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:282
#define XML_ATTR_ID
Definition: msg_xml.h:134
#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:217
#define XML_ATTR_NAME
Definition: msg_xml.h:135
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:517
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:833
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:26
#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:42
void pcmk__register_formats(GOptionGroup *group, const pcmk__supported_format_t *table)
Definition: output.c:110
pcmk__action_result_t result
Definition: pcmk_fence.c:35
node_type
Definition: pe_types.h:71
#define ENOTUNIQ
Definition: portability.h:120
const char * pcmk_strerror(int rc)
Definition: results.c:148
#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:476
@ CRM_EX_OK
Success.
Definition: results.h:234
@ pcmk_rc_ok
Definition: results.h:148
#define pcmk_ok
Definition: results.h:68
int pcmk_rc2legacy(int rc)
Definition: results.c:521
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:534
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1190
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:928
@ pcmk__str_none
@ pcmk__str_casei
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1214
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:179
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:2136
void free_xml(xmlNode *child)
Definition: xml.c:885
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
Definition: xml.c:1190
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:749