pacemaker  2.1.7-0f7f88312f
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 ((search != NULL) && (search->children != NULL)) {
156  xmlNode *child = NULL;
157 
158  out->info(out, "Multiple attributes match name=%s", attr_name);
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  return ENOTUNIQ;
165 
166  } else {
167  return pcmk_rc_ok;
168  }
169 }
170 
171 int
172 cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options, const char *section,
173  const char *node_uuid, const char *set_type, const char *set_name,
174  const char *attr_id, const char *attr_name, const char *attr_value,
175  const char *user_name, const char *node_type)
176 {
177  const char *tag = NULL;
178  int rc = pcmk_rc_ok;
179  xmlNode *xml_top = NULL;
180  xmlNode *xml_obj = NULL;
181  xmlNode *xml_search = NULL;
182 
183  char *local_attr_id = NULL;
184  char *local_set_name = NULL;
185 
186  CRM_CHECK((out != NULL) && (cib != NULL) && (section != NULL)
187  && ((attr_id != NULL) || (attr_name != NULL))
188  && (attr_value != NULL), return EINVAL);
189 
190  rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id,
191  attr_name, user_name, &xml_search);
192 
193  if (rc == pcmk_rc_ok) {
194  if (handle_multiples(out, xml_search, attr_name) == ENOTUNIQ) {
195  free_xml(xml_search);
196  return ENOTUNIQ;
197  } else {
198  pcmk__str_update(&local_attr_id, crm_element_value(xml_search, XML_ATTR_ID));
199  attr_id = local_attr_id;
200  free_xml(xml_search);
201  goto do_modify;
202  }
203 
204  } else if (rc != ENXIO) {
205  free_xml(xml_search);
206  return rc;
207 
208  /* } else if(attr_id == NULL) { */
209  /* return EINVAL; */
210 
211  } else {
212  free_xml(xml_search);
213  crm_trace("%s does not exist, create it", attr_name);
214  if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
215  node_uuid = NULL;
216  section = XML_CIB_TAG_STATUS;
218 
219  xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATUS);
220  xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
221 
222  } else if (pcmk__str_eq(section, XML_CIB_TAG_NODES, pcmk__str_casei)) {
223 
224  if (node_uuid == NULL) {
225  return EINVAL;
226  }
227 
228  if (pcmk__str_eq(node_type, "remote", pcmk__str_casei)) {
229  xml_top = create_xml_node(xml_obj, XML_CIB_TAG_NODES);
230  xml_obj = create_xml_node(xml_top, XML_CIB_TAG_NODE);
231  crm_xml_add(xml_obj, XML_ATTR_TYPE, "remote");
232  crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
233  crm_xml_add(xml_obj, XML_ATTR_UNAME, node_uuid);
234  } else {
235  tag = XML_CIB_TAG_NODE;
236  }
237 
238  } else if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
240  if (node_uuid == NULL) {
241  return EINVAL;
242  }
243 
244  xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATE);
245  crm_xml_add(xml_top, XML_ATTR_ID, node_uuid);
246  xml_obj = xml_top;
247 
248  } else {
249  tag = section;
250  node_uuid = NULL;
251  }
252 
253  if (set_name == NULL) {
254  if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
255  local_set_name = strdup(CIB_OPTIONS_FIRST);
256 
257  } else if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
258  local_set_name = crm_strdup_printf("%s-%s", section,
260 
261  } else if (node_uuid) {
262  local_set_name = crm_strdup_printf("%s-%s", section, node_uuid);
263 
264  if (set_type) {
265  char *tmp_set_name = local_set_name;
266 
267  local_set_name = crm_strdup_printf("%s-%s", tmp_set_name,
268  set_type);
269  free(tmp_set_name);
270  }
271  } else {
272  local_set_name = crm_strdup_printf("%s-options", section);
273  }
274  set_name = local_set_name;
275  }
276 
277  if (attr_id == NULL) {
278  local_attr_id = crm_strdup_printf("%s-%s", set_name, attr_name);
279  crm_xml_sanitize_id(local_attr_id);
280  attr_id = local_attr_id;
281 
282  } else if (attr_name == NULL) {
283  attr_name = attr_id;
284  }
285 
286  crm_trace("Creating %s/%s", section, tag);
287  if (tag != NULL) {
288  xml_obj = create_xml_node(xml_obj, tag);
289  crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
290  if (xml_top == NULL) {
291  xml_top = xml_obj;
292  }
293  }
294 
295  if (node_uuid == NULL && !pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
296  if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
297  xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET);
298  } else {
299  xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS);
300  }
301 
302  } else if (set_type) {
303  xml_obj = create_xml_node(xml_obj, set_type);
304 
305  } else {
306  xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS);
307  }
308  crm_xml_add(xml_obj, XML_ATTR_ID, set_name);
309 
310  if (xml_top == NULL) {
311  xml_top = xml_obj;
312  }
313  }
314 
315  do_modify:
316  xml_obj = crm_create_nvpair_xml(xml_obj, attr_id, attr_name, attr_value);
317  if (xml_top == NULL) {
318  xml_top = xml_obj;
319  }
320 
321  crm_log_xml_trace(xml_top, "update_attr");
322  rc = cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, xml_top,
323  NULL, call_options, user_name);
324  if (rc < 0) {
325  rc = pcmk_legacy2rc(rc);
326 
327  out->err(out, "Error setting %s=%s (section=%s, set=%s): %s",
328  attr_name, attr_value, section, pcmk__s(set_name, "<null>"),
329  pcmk_rc_str(rc));
330  crm_log_xml_info(xml_top, "Update");
331  } else {
332  rc = pcmk_rc_ok;
333  }
334 
335  free(local_set_name);
336  free(local_attr_id);
337  free_xml(xml_top);
338 
339  return rc;
340 }
341 
342 int
343 cib__get_node_attrs(pcmk__output_t *out, cib_t *cib, const char *section,
344  const char *node_uuid, const char *set_type, const char *set_name,
345  const char *attr_id, const char *attr_name, const char *user_name,
346  xmlNode **result)
347 {
348  int rc = pcmk_rc_ok;
349 
350  CRM_ASSERT(result != NULL);
351  CRM_CHECK(section != NULL, return EINVAL);
352 
353  *result = NULL;
354 
355  rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id, attr_name,
356  user_name, result);
357 
358  if (rc != pcmk_rc_ok) {
359  crm_trace("Query failed for attribute %s (section=%s node=%s set=%s): %s",
360  pcmk__s(attr_name, "with unspecified name"),
361  section, pcmk__s(set_name, "<null>"),
362  pcmk__s(node_uuid, "<null>"), pcmk_rc_str(rc));
363  }
364 
365  return rc;
366 }
367 
368 int
369 cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options, const char *section,
370  const char *node_uuid, const char *set_type, const char *set_name,
371  const char *attr_id, const char *attr_name, const char *attr_value,
372  const char *user_name)
373 {
374  int rc = pcmk_rc_ok;
375  xmlNode *xml_obj = NULL;
376  xmlNode *xml_search = NULL;
377  char *local_attr_id = NULL;
378 
379  CRM_CHECK(section != NULL, return EINVAL);
380  CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
381 
382  if (attr_id == NULL) {
383  rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id,
384  attr_name, user_name, &xml_search);
385 
386  if (rc != pcmk_rc_ok || handle_multiples(out, xml_search, attr_name) == ENOTUNIQ) {
387  free_xml(xml_search);
388  return rc;
389  } else {
390  pcmk__str_update(&local_attr_id, crm_element_value(xml_search, XML_ATTR_ID));
391  attr_id = local_attr_id;
392  free_xml(xml_search);
393  }
394  }
395 
396  xml_obj = crm_create_nvpair_xml(NULL, attr_id, attr_name, attr_value);
397 
398  rc = cib_internal_op(cib, PCMK__CIB_REQUEST_DELETE, NULL, section, xml_obj,
399  NULL, options, user_name);
400  if (rc < 0) {
401  rc = pcmk_legacy2rc(rc);
402  } else {
403  rc = pcmk_rc_ok;
404  out->info(out, "Deleted %s %s: id=%s%s%s%s%s",
405  section, node_uuid ? "attribute" : "option", local_attr_id,
406  set_name ? " set=" : "", set_name ? set_name : "",
407  attr_name ? " name=" : "", attr_name ? attr_name : "");
408  }
409 
410  free(local_attr_id);
411  free_xml(xml_obj);
412  return rc;
413 }
414 
415 int
416 find_nvpair_attr_delegate(cib_t *cib, const char *attr, const char *section,
417  const char *node_uuid, const char *attr_set_type, const char *set_name,
418  const char *attr_id, const char *attr_name, gboolean to_console,
419  char **value, const char *user_name)
420 {
421  pcmk__output_t *out = NULL;
422  xmlNode *xml_search = NULL;
423  int rc = pcmk_ok;
424 
425  out = new_output_object(to_console ? "text" : "log");
426  if (out == NULL) {
427  return pcmk_err_generic;
428  }
429 
430  rc = find_attr(cib, section, node_uuid, attr_set_type, set_name, attr_id,
431  attr_name, user_name, &xml_search);
432 
433  if (rc == pcmk_rc_ok) {
434  rc = handle_multiples(out, xml_search, attr_name);
435 
436  if (rc == pcmk_rc_ok) {
437  pcmk__str_update(value, crm_element_value(xml_search, attr));
438  }
439  }
440 
441  out->finish(out, CRM_EX_OK, true, NULL);
442  free_xml(xml_search);
443  pcmk__output_free(out);
444  return pcmk_rc2legacy(rc);
445 }
446 
447 int
448 update_attr_delegate(cib_t *cib, int call_options, const char *section,
449  const char *node_uuid, const char *set_type, const char *set_name,
450  const char *attr_id, const char *attr_name, const char *attr_value,
451  gboolean to_console, const char *user_name, const char *node_type)
452 {
453  pcmk__output_t *out = NULL;
454  int rc = pcmk_ok;
455 
456  out = new_output_object(to_console ? "text" : "log");
457  if (out == NULL) {
458  return pcmk_err_generic;
459  }
460 
461  rc = cib__update_node_attr(out, cib, call_options, section, node_uuid, set_type,
462  set_name, attr_id, attr_name, attr_value, user_name,
463  node_type);
464 
465  out->finish(out, CRM_EX_OK, true, NULL);
466  pcmk__output_free(out);
467  return pcmk_rc2legacy(rc);
468 }
469 
470 int
471 read_attr_delegate(cib_t *cib, const char *section, const char *node_uuid,
472  const char *set_type, const char *set_name, const char *attr_id,
473  const char *attr_name, char **attr_value, gboolean to_console,
474  const char *user_name)
475 {
476  pcmk__output_t *out = NULL;
477  xmlNode *result = NULL;
478  int rc = pcmk_ok;
479 
480  out = new_output_object(to_console ? "text" : "log");
481  if (out == NULL) {
482  return pcmk_err_generic;
483  }
484 
485  rc = cib__get_node_attrs(out, cib, section, node_uuid, set_type, set_name,
486  attr_id, attr_name, user_name, &result);
487 
488  if (rc == pcmk_rc_ok) {
489  if (result->children == NULL) {
491  } else {
492  rc = ENOTUNIQ;
493  }
494  }
495 
496  out->finish(out, CRM_EX_OK, true, NULL);
497  free_xml(result);
498  pcmk__output_free(out);
499  return pcmk_rc2legacy(rc);
500 }
501 
502 int
503 delete_attr_delegate(cib_t *cib, int options, const char *section, const char *node_uuid,
504  const char *set_type, const char *set_name, const char *attr_id,
505  const char *attr_name, const char *attr_value, gboolean to_console,
506  const char *user_name)
507 {
508  pcmk__output_t *out = NULL;
509  int rc = pcmk_ok;
510 
511  out = new_output_object(to_console ? "text" : "log");
512  if (out == NULL) {
513  return pcmk_err_generic;
514  }
515 
516  rc = cib__delete_node_attr(out, cib, options, section, node_uuid, set_type,
517  set_name, attr_id, attr_name, attr_value, user_name);
518 
519  out->finish(out, CRM_EX_OK, true, NULL);
520  pcmk__output_free(out);
521  return pcmk_rc2legacy(rc);
522 }
523 
534 static int
535 get_uuid_from_result(const xmlNode *result, char **uuid, int *is_remote)
536 {
537  int rc = -ENXIO;
538  const char *tag;
539  const char *parsed_uuid = NULL;
540  int parsed_is_remote = FALSE;
541 
542  if (result == NULL) {
543  return rc;
544  }
545 
546  /* If there are multiple results, the first is sufficient */
547  tag = (const char *) (result->name);
548  if (pcmk__str_eq(tag, "xpath-query", pcmk__str_casei)) {
549  result = pcmk__xml_first_child(result);
550  CRM_CHECK(result != NULL, return rc);
551  tag = (const char *) (result->name);
552  }
553 
554  if (pcmk__str_eq(tag, XML_CIB_TAG_NODE, pcmk__str_casei)) {
555  /* Result is <node> tag from <nodes> section */
556 
557  if (pcmk__str_eq(crm_element_value(result, XML_ATTR_TYPE), "remote", pcmk__str_casei)) {
558  parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
559  parsed_is_remote = TRUE;
560  } else {
561  parsed_uuid = ID(result);
562  parsed_is_remote = FALSE;
563  }
564 
565  } else if (pcmk__str_eq(tag, XML_CIB_TAG_RESOURCE, pcmk__str_casei)) {
566  /* Result is <primitive> for ocf:pacemaker:remote resource */
567 
568  parsed_uuid = ID(result);
569  parsed_is_remote = TRUE;
570 
571  } else if (pcmk__str_eq(tag, XML_CIB_TAG_NVPAIR, pcmk__str_casei)) {
572  /* Result is remote-node parameter of <primitive> for guest node */
573 
575  parsed_is_remote = TRUE;
576 
577  } else if (pcmk__str_eq(tag, XML_CIB_TAG_STATE, pcmk__str_casei)) {
578  /* Result is <node_state> tag from <status> section */
579 
580  parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
582  parsed_is_remote = TRUE;
583  }
584  }
585 
586  if (parsed_uuid) {
587  if (uuid) {
588  *uuid = strdup(parsed_uuid);
589  }
590  if (is_remote) {
591  *is_remote = parsed_is_remote;
592  }
593  rc = pcmk_ok;
594  }
595 
596  return rc;
597 }
598 
599 /* Search string to find a node by name, as:
600  * - cluster or remote node in nodes section
601  * - remote node in resources section
602  * - guest node in resources section
603  * - orphaned remote node or bundle guest node in status section
604  */
605 #define XPATH_UPPER_TRANS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
606 #define XPATH_LOWER_TRANS "abcdefghijklmnopqrstuvwxyz"
607 #define XPATH_NODE \
608  "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
609  "/" XML_CIB_TAG_NODE "[translate(@" XML_ATTR_UNAME ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
610  "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
611  "/" XML_CIB_TAG_RESOURCE \
612  "[@class='ocf'][@provider='pacemaker'][@type='remote'][translate(@id,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
613  "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
614  "/" XML_CIB_TAG_RESOURCE "/" XML_TAG_META_SETS "/" XML_CIB_TAG_NVPAIR \
615  "[@name='" XML_RSC_ATTR_REMOTE_NODE "'][translate(@value,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
616  "|/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS "/" XML_CIB_TAG_STATE \
617  "[@" XML_NODE_IS_REMOTE "='true'][translate(@" XML_ATTR_ID ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']"
618 
619 int
620 query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
621 {
622  int rc = pcmk_ok;
623  char *xpath_string;
624  xmlNode *xml_search = NULL;
625  char *host_lowercase = NULL;
626 
627  CRM_ASSERT(uname != NULL);
628 
629  host_lowercase = g_ascii_strdown(uname, -1);
630 
631  if (uuid) {
632  *uuid = NULL;
633  }
634  if (is_remote_node) {
635  *is_remote_node = FALSE;
636  }
637 
638  xpath_string = crm_strdup_printf(XPATH_NODE, host_lowercase, host_lowercase, host_lowercase, host_lowercase);
639  if (cib_internal_op(the_cib, PCMK__CIB_REQUEST_QUERY, NULL, xpath_string,
640  NULL, &xml_search,
642  NULL) == pcmk_ok) {
643  rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
644  } else {
645  rc = -ENXIO;
646  }
647  free(xpath_string);
648  free_xml(xml_search);
649  g_free(host_lowercase);
650 
651  if (rc != pcmk_ok) {
652  crm_debug("Could not map node name '%s' to a UUID: %s",
653  uname, pcmk_strerror(rc));
654  } else {
655  crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
656  }
657  return rc;
658 }
659 
660 int
661 query_node_uname(cib_t * the_cib, const char *uuid, char **uname)
662 {
663  int rc = pcmk_ok;
664  xmlNode *a_child = NULL;
665  xmlNode *xml_obj = NULL;
666  xmlNode *fragment = NULL;
667  const char *child_name = NULL;
668 
669  CRM_ASSERT(uname != NULL);
670  CRM_ASSERT(uuid != NULL);
671 
672  rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
674  if (rc != pcmk_ok) {
675  return rc;
676  }
677 
678  xml_obj = fragment;
679  CRM_CHECK(pcmk__xe_is(xml_obj, XML_CIB_TAG_NODES), return -ENOMSG);
680  crm_log_xml_trace(xml_obj, "Result section");
681 
682  rc = -ENXIO;
683  *uname = NULL;
684 
685  for (a_child = pcmk__xml_first_child(xml_obj); a_child != NULL;
686  a_child = pcmk__xml_next(a_child)) {
687 
688  if (pcmk__str_eq((const char *)a_child->name, XML_CIB_TAG_NODE,
689  pcmk__str_none)) {
690  child_name = ID(a_child);
691  if (pcmk__str_eq(uuid, child_name, pcmk__str_casei)) {
692  child_name = crm_element_value(a_child, XML_ATTR_UNAME);
693  if (child_name != NULL) {
694  *uname = strdup(child_name);
695  rc = pcmk_ok;
696  }
697  break;
698  }
699  }
700  }
701 
702  free_xml(fragment);
703  return rc;
704 }
705 
706 int
707 set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value)
708 {
709  int rc = pcmk_ok;
710  char *attr_id = NULL;
711 
712  CRM_CHECK(uuid != NULL, return -EINVAL);
713  CRM_CHECK(standby_value != NULL, return -EINVAL);
714 
715  if (pcmk__strcase_any_of(scope, "reboot", XML_CIB_TAG_STATUS, NULL)) {
716  scope = XML_CIB_TAG_STATUS;
717  attr_id = crm_strdup_printf("transient-standby-%.256s", uuid);
718 
719  } else {
720  scope = XML_CIB_TAG_NODES;
721  attr_id = crm_strdup_printf("standby-%.256s", uuid);
722  }
723 
724  rc = update_attr_delegate(the_cib, cib_sync_call, scope, uuid, NULL, NULL,
725  attr_id, "standby", standby_value, TRUE, NULL, NULL);
726 
727  free(attr_id);
728  return rc;
729 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
#define PCMK__SUPPORTED_FORMAT_LOG
A dumping ground.
const char * pcmk_strerror(int rc)
Definition: results.c:149
node_type
Possible node types.
Definition: nodes.h:33
int pcmk_rc2legacy(int rc)
Definition: results.c:546
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:933
#define XML_ATTR_TYPE
Definition: msg_xml.h:160
#define PCMK__SUPPORTED_FORMAT_TEXT
#define PCMK__CIB_REQUEST_QUERY
Definition: internal.h:23
int set_standby(cib_t *the_cib, const char *uuid, const char *scope, const char *standby_value)
Definition: cib_attrs.c:707
#define XML_TAG_TRANSIENT_NODEATTRS
Definition: msg_xml.h:420
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:905
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:224
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:501
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:369
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:206
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
Definition: xml.c:1106
#define XML_CIB_TAG_PROPSET
Definition: msg_xml.h:226
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:343
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:227
#define crm_warn(fmt, args...)
Definition: logging.h:382
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:345
#define crm_debug(fmt, args...)
Definition: logging.h:386
#define XML_ATTR_ID
Definition: msg_xml.h:156
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:235
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:222
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:416
#define crm_trace(fmt, args...)
Definition: logging.h:387
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:157
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:394
#define XML_TAG_META_SETS
Definition: msg_xml.h:228
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:178
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:638
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:156
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
Definition: cib_attrs.c:620
Success.
Definition: results.h:240
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:559
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:288
#define CIB_OPTIONS_FIRST
Definition: msg_xml.h:110
void free_xml(xmlNode *child)
Definition: xml.c:783
#define XPATH_NODE
Definition: cib_attrs.c:607
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:223
void pcmk__output_free(pcmk__output_t *out)
Definition: output.c:28
const char * pcmk_cib_xpath_for(const char *element_name)
Get the relative XPath needed to find a specified CIB element name.
Definition: cib.c:112
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:448
pcmk__action_result_t result
Definition: pcmk_fence.c:35
#define crm_err(fmt, args...)
Definition: logging.h:381
#define CRM_ASSERT(expr)
Definition: results.h:42
#define ENOTUNIQ
Definition: portability.h:81
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:208
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:210
This structure contains everything that makes up a single output formatter.
#define crm_log_xml_info(xml, text)
Definition: logging.h:393
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:394
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:471
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:204
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:395
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:503
#define PCMK__CIB_REQUEST_MODIFY
Definition: internal.h:25
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:763
#define ID(x)
Definition: msg_xml.h:474
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:943
int query_node_uname(cib_t *the_cib, const char *uuid, char **uname)
Definition: cib_attrs.c:661
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:209
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:172
#define XML_CIB_TAG_TICKETS
Definition: msg_xml.h:446
#define crm_info(fmt, args...)
Definition: logging.h:384
#define PCMK__CIB_REQUEST_DELETE
Definition: internal.h:26