pacemaker  2.1.3-ea053b43a
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 
40 static pcmk__output_t *
41 new_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 
62 static int
63 find_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)) {
125  set_type = XML_TAG_TRANSIENT_NODEATTRS;
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,
153  cib_sync_call | cib_scope_local | cib_xpath, user_name);
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)",
174  crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child));
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 
187 int
188 cib__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 
346 int
347 cib__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 
370 int
371 cib__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 
412 int
413 find_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);
430  pcmk__output_free(out);
431  return pcmk_rc2legacy(rc);
432 }
433 
434 int
435 update_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);
453  pcmk__output_free(out);
454  return pcmk_rc2legacy(rc);
455 }
456 
457 int
458 read_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);
475  pcmk__output_free(out);
476  return pcmk_rc2legacy(rc);
477 }
478 
479 int
480 delete_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);
497  pcmk__output_free(out);
498  return pcmk_rc2legacy(rc);
499 }
500 
511 static int
512 get_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)) {
535  parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
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 
557  parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
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 
596 int
597 query_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 
636 int
637 query_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,
667  pcmk__str_none)) {
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 
684 int
685 set_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 CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define PCMK__SUPPORTED_FORMAT_LOG
A dumping ground.
const char * pcmk_strerror(int rc)
Definition: results.c:58
int pcmk_rc2legacy(int rc)
Definition: results.c:415
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:931
#define XML_ATTR_TYPE
Definition: msg_xml.h:138
#define PCMK__SUPPORTED_FORMAT_TEXT
int set_standby(cib_t *the_cib, const char *uuid, const char *scope, const char *standby_value)
Definition: cib_attrs.c:685
#define XML_TAG_TRANSIENT_NODEATTRS
Definition: msg_xml.h:409
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
#define pcmk_err_generic
Definition: results.h:71
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:210
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define attr_snprintf(_str, _offset, _limit,...)
Definition: cib_attrs.c:32
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:206
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:370
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
void pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *table)
Definition: output.c:99
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:187
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
Definition: xml.c:1129
#define XML_CIB_TAG_PROPSET
Definition: msg_xml.h:208
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:209
#define crm_warn(fmt, args...)
Definition: logging.h:359
Formatted output for pacemaker tools.
cib_api_operations_t * cmds
Definition: cib_types.h:147
#define crm_debug(fmt, args...)
Definition: logging.h:363
#define XML_ATTR_ID
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:529
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:220
#define XML_CIB_TAG_STATE
Definition: msg_xml.h:204
#define CIB_OP_QUERY
Definition: internal.h:23
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
#define crm_trace(fmt, args...)
Definition: logging.h:364
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define crm_log_xml_debug(xml, text)
Definition: logging.h:371
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define XML_TAG_META_SETS
Definition: msg_xml.h:210
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1188
Wrappers for and extensions to libxml2.
#define XML_ATTR_UNAME
Definition: msg_xml.h:157
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:696
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:92
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
Definition: cib_attrs.c:597
Success.
Definition: results.h:239
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:428
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:285
#define CIB_OPTIONS_FIRST
Definition: msg_xml.h:88
void free_xml(xmlNode *child)
Definition: xml.c:824
#define XPATH_NODE
Definition: cib_attrs.c:584
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:2028
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:205
#define XPATH_MAX
Definition: cib_attrs.c:38
void pcmk__output_free(pcmk__output_t *out)
Definition: output.c:19
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:435
pcmk__action_result_t result
Definition: pcmk_fence.c:34
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:309
#define crm_err(fmt, args...)
Definition: logging.h:358
#define CRM_ASSERT(expr)
Definition: results.h:42
#define ENOTUNIQ
Definition: portability.h:120
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
node_type
Definition: pe_types.h:71
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:190
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:192
#define CIB_OP_DELETE
Definition: internal.h:26
This structure contains everything that makes up a single output formatter.
#define crm_log_xml_info(xml, text)
Definition: logging.h:370
#define CIB_OP_MODIFY
Definition: internal.h:25
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:384
char uname[MAX_NAME]
Definition: cpg.c:50
#define crm_str(x)
Definition: logging.h:384
#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:458
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:185
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:31
#define crm_log_xml_trace(xml, text)
Definition: logging.h:372
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
bool pcmk__xe_attr_is_true(xmlNodePtr node, const char *name)
Definition: nvpair.c:986
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
#define ID(x)
Definition: msg_xml.h:460
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
int query_node_uname(cib_t *the_cib, const char *uuid, char **uname)
Definition: cib_attrs.c:637
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:191
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 XML_CIB_TAG_TICKETS
Definition: msg_xml.h:432
#define crm_info(fmt, args...)
Definition: logging.h:361