pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
cib_attrs.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 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 static pcmk__output_t *
32 new_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 
53 static int
54 find_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)) {
107  set_type = XML_TAG_TRANSIENT_NODEATTRS;
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 
152 static int
153 handle_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)",
162  crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child));
163  }
164 
165  return ENOTUNIQ;
166 
167  } else {
168  return pcmk_rc_ok;
169  }
170 }
171 
172 int
173 cib__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, 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 
343 int
344 cib__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 
369 int
370 cib__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, 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 
416 int
417 find_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);
444  pcmk__output_free(out);
445  return pcmk_rc2legacy(rc);
446 }
447 
448 int
449 update_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);
467  pcmk__output_free(out);
468  return pcmk_rc2legacy(rc);
469 }
470 
471 int
472 read_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);
498  free_xml(result);
499  pcmk__output_free(out);
500  return pcmk_rc2legacy(rc);
501 }
502 
503 int
504 delete_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);
521  pcmk__output_free(out);
522  return pcmk_rc2legacy(rc);
523 }
524 
535 static int
536 get_uuid_from_result(const 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)) {
559  parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
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 
581  parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
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_ID ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']"
619 
620 int
621 query_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 
661 int
662 query_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,
692  pcmk__str_none)) {
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 
709 int
710 set_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 CRM_CHECK(expr, failure_action)
Definition: logging.h:235
#define PCMK__SUPPORTED_FORMAT_LOG
A dumping ground.
const char * pcmk_strerror(int rc)
Definition: results.c:148
int pcmk_rc2legacy(int rc)
Definition: results.c:533
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:933
#define XML_ATTR_TYPE
Definition: msg_xml.h:151
#define PCMK__SUPPORTED_FORMAT_TEXT
#define PCMK__CIB_REQUEST_QUERY
Definition: internal.h:24
int set_standby(cib_t *the_cib, const char *uuid, const char *scope, const char *standby_value)
Definition: cib_attrs.c:710
#define XML_TAG_TRANSIENT_NODEATTRS
Definition: msg_xml.h:429
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:302
#define pcmk_err_generic
Definition: results.h:71
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:954
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:219
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:488
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
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:200
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
Definition: xml.c:1094
#define XML_CIB_TAG_PROPSET
Definition: msg_xml.h:221
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
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:222
#define crm_warn(fmt, args...)
Definition: logging.h:378
Formatted output for pacemaker tools.
void pcmk__register_formats(GOptionGroup *group, const pcmk__supported_format_t *table)
Definition: output.c:145
cib_api_operations_t * cmds
Definition: cib_types.h:216
#define crm_debug(fmt, args...)
Definition: logging.h:382
#define XML_ATTR_ID
Definition: msg_xml.h:147
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:496
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:230
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:217
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
#define crm_trace(fmt, args...)
Definition: logging.h:383
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1217
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define XML_ATTR_NAME
Definition: msg_xml.h:148
int(*) int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define crm_log_xml_debug(xml, text)
Definition: logging.h:390
#define XML_TAG_META_SETS
Definition: msg_xml.h:223
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
Wrappers for and extensions to libxml2.
#define XML_ATTR_UNAME
Definition: msg_xml.h:170
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:677
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:103
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
Definition: cib_attrs.c:621
Success.
Definition: results.h:237
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:546
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:297
#define CIB_OPTIONS_FIRST
Definition: msg_xml.h:101
void free_xml(xmlNode *child)
Definition: xml.c:813
#define XPATH_NODE
Definition: cib_attrs.c:608
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:1726
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:218
void pcmk__output_free(pcmk__output_t *out)
Definition: output.c:28
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
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
pcmk__action_result_t result
Definition: pcmk_fence.c:35
#define crm_err(fmt, args...)
Definition: logging.h:377
#define CRM_ASSERT(expr)
Definition: results.h:42
#define ENOTUNIQ
Definition: portability.h:120
node_type
Definition: pe_types.h:87
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:203
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:205
This structure contains everything that makes up a single output formatter.
#define crm_log_xml_info(xml, text)
Definition: logging.h:389
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:404
char uname[MAX_NAME]
Definition: cpg.c:50
#define pcmk_ok
Definition: results.h:68
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
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:198
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:111
#define crm_log_xml_trace(xml, text)
Definition: logging.h:391
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
#define PCMK__CIB_REQUEST_MODIFY
Definition: internal.h:26
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:812
#define ID(x)
Definition: msg_xml.h:480
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:657
int query_node_uname(cib_t *the_cib, const char *uuid, char **uname)
Definition: cib_attrs.c:662
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:204
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 XML_CIB_TAG_TICKETS
Definition: msg_xml.h:452
#define crm_info(fmt, args...)
Definition: logging.h:380
#define PCMK__CIB_REQUEST_DELETE
Definition: internal.h:27