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. handle_multiples
  4. cib__update_node_attr
  5. cib__get_node_attrs
  6. cib__delete_node_attr
  7. find_nvpair_attr_delegate
  8. update_attr_delegate
  9. read_attr_delegate
  10. delete_attr_delegate
  11. get_uuid_from_result
  12. query_node_uuid
  13. query_node_uname
  14. set_standby

   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>
  27 #include <crm/common/xml_internal.h>
  28 #include <crm/common/output_internal.h>
  29 #include <crm/cib/internal.h>
  30 
  31 static pcmk__output_t *
  32 new_output_object(const char *ty)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34     int rc = pcmk_rc_ok;
  35     pcmk__output_t *out = NULL;
  36     const char* argv[] = { "", NULL };
  37     pcmk__supported_format_t formats[] = {
  38         PCMK__SUPPORTED_FORMAT_LOG,
  39         PCMK__SUPPORTED_FORMAT_TEXT,
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
  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 
  76     } else if (pcmk__strcase_any_of(section, XML_CIB_TAG_OPCONFIG, XML_CIB_TAG_RSCCONFIG,
  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;
  84         node_type = XML_CIB_TAG_TICKETS;
  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)) {
 106             node_type = XML_CIB_TAG_STATE;
 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 
 133     rc = cib_internal_op(cib, PCMK__CIB_REQUEST_QUERY, NULL,
 134                          (const char *) xpath->str, NULL, &xml_search,
 135                          cib_sync_call|cib_scope_local|cib_xpath, user_name);
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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;
 218             node_type = XML_CIB_TAG_TICKETS;
 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)) {
 240             tag = XML_TAG_TRANSIENT_NODEATTRS;
 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,
 260                                                    XML_CIB_TAG_TICKETS);
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)) {
 491             pcmk__str_update(attr_value, crm_element_value(result, XML_NVPAIR_ATTR_VALUE));
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 525 /*!
 526  * \internal
 527  * \brief Parse node UUID from search result
 528  *
 529  * \param[in]  result     XML search result
 530  * \param[out] uuid       If non-NULL, where to store parsed UUID
 531  * \param[out] is_remote  If non-NULL, set TRUE if result is remote node
 532  *
 533  * \return pcmk_ok if UUID was successfully parsed, -ENXIO otherwise
 534  */
 535 static int
 536 get_uuid_from_result(const xmlNode *result, char **uuid, int *is_remote)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 575         parsed_uuid = crm_element_value(result, XML_NVPAIR_ATTR_VALUE);
 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);
 582         if (pcmk__xe_attr_is_true(result, XML_NODE_IS_REMOTE)) {
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
 642                         cib_sync_call|cib_scope_local|cib_xpath,
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
 674                               cib_sync_call | cib_scope_local);
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

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