root/lib/cib/cib_attrs.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. new_output_object
  2. find_attr
  3. cib__update_node_attr
  4. cib__read_node_attr
  5. cib__delete_node_attr
  6. find_nvpair_attr_delegate
  7. update_attr_delegate
  8. read_attr_delegate
  9. delete_attr_delegate
  10. get_uuid_from_result
  11. query_node_uuid
  12. query_node_uname
  13. set_standby

   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>
  27 #include <crm/common/xml_internal.h>
  28 #include <crm/common/output_internal.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)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43     int rc = pcmk_rc_ok;
  44     pcmk__output_t *out = NULL;
  45     const char* argv[] = { "", NULL };
  46     pcmk__supported_format_t formats[] = {
  47         PCMK__SUPPORTED_FORMAT_LOG,
  48         PCMK__SUPPORTED_FORMAT_TEXT,
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
  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 
  90     } else if (pcmk__strcase_any_of(section, XML_CIB_TAG_OPCONFIG, XML_CIB_TAG_RSCCONFIG,
  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;
  98         node_type = XML_CIB_TAG_TICKETS;
  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)) {
 124             node_type = XML_CIB_TAG_STATE;
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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;
 222             node_type = XML_CIB_TAG_TICKETS;
 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)) {
 244             tag = XML_TAG_TRANSIENT_NODEATTRS;
 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,
 264                                                    XML_CIB_TAG_TICKETS);
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 501 /*!
 502  * \internal
 503  * \brief Parse node UUID from search result
 504  *
 505  * \param[in]  result     XML search result
 506  * \param[out] uuid       If non-NULL, where to store parsed UUID
 507  * \param[out] is_remote  If non-NULL, set TRUE if result is remote node
 508  *
 509  * \return pcmk_ok if UUID was successfully parsed, -ENXIO otherwise
 510  */
 511 static int
 512 get_uuid_from_result(xmlNode *result, char **uuid, int *is_remote)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 551         parsed_uuid = crm_element_value(result, XML_NVPAIR_ATTR_VALUE);
 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);
 558         if (pcmk__xe_attr_is_true(result, XML_NODE_IS_REMOTE)) {
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
 617                         &xml_search, cib_sync_call|cib_scope_local|cib_xpath,
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
 649                               cib_sync_call | cib_scope_local);
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

/* [previous][next][first][last][top][bottom][index][help] */