root/lib/cib/cib_ops.c

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

DEFINITIONS

This source file includes following definitions.
  1. cib_process_query
  2. cib_process_erase
  3. cib_process_upgrade
  4. cib_process_bump
  5. cib_update_counter
  6. cib_process_replace
  7. cib_process_delete
  8. cib_process_modify
  9. update_cib_object
  10. add_cib_object
  11. cib_process_create
  12. cib_process_diff
  13. cib_config_changed
  14. cib_process_xpath
  15. update_results

   1 /*
   2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This library is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2.1 of the License, or (at your option) any later version.
   8  *
   9  * This library is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 
  19 #include <crm_internal.h>
  20 
  21 #include <stdio.h>
  22 #include <unistd.h>
  23 #include <stdlib.h>
  24 #include <errno.h>
  25 #include <fcntl.h>
  26 #include <time.h>
  27 
  28 #include <sys/param.h>
  29 #include <sys/types.h>
  30 
  31 #include <crm/crm.h>
  32 #include <crm/cib/internal.h>
  33 #include <crm/msg_xml.h>
  34 
  35 #include <crm/common/xml.h>
  36 
  37 int
  38 cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
  39                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
  40 {
  41     xmlNode *obj_root = NULL;
  42     int result = pcmk_ok;
  43 
  44     crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section));
  45 
  46     if (options & cib_xpath) {
  47         return cib_process_xpath(op, options, section, req, input,
  48                                  existing_cib, result_cib, answer);
  49     }
  50 
  51     CRM_CHECK(*answer == NULL, free_xml(*answer));
  52     *answer = NULL;
  53 
  54     if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
  55         section = NULL;
  56     }
  57 
  58     obj_root = get_object_root(section, existing_cib);
  59 
  60     if (obj_root == NULL) {
  61         result = -ENXIO;
  62 
  63     } else if (options & cib_no_children) {
  64         const char *tag = TYPE(obj_root);
  65         xmlNode *shallow = create_xml_node(*answer, tag);
  66 
  67         copy_in_properties(shallow, obj_root);
  68         *answer = shallow;
  69 
  70     } else {
  71         *answer = obj_root;
  72     }
  73 
  74     if (result == pcmk_ok && *answer == NULL) {
  75         crm_err("Error creating query response");
  76         result = -ENOMSG;
  77     }
  78 
  79     return result;
  80 }
  81 
  82 int
  83 cib_process_erase(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
  84                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
  85 {
  86     int result = pcmk_ok;
  87 
  88     crm_trace("Processing \"%s\" event", op);
  89     *answer = NULL;
  90     free_xml(*result_cib);
  91     *result_cib = createEmptyCib(0);
  92 
  93     copy_in_properties(*result_cib, existing_cib);
  94     cib_update_counter(*result_cib, XML_ATTR_GENERATION_ADMIN, FALSE);
  95 
  96     return result;
  97 }
  98 
  99 int
 100 cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
     /* [previous][next][first][last][top][bottom][index][help] */
 101                     xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
 102                     xmlNode ** answer)
 103 {
 104     int rc = 0;
 105     int new_version = 0;
 106     int current_version = 0;
 107     int max_version = 0;
 108     const char *max = crm_element_value(req, F_CIB_SCHEMA_MAX);
 109     const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);
 110 
 111     *answer = NULL;
 112     crm_trace("Processing \"%s\" event with max=%s", op, max);
 113 
 114     if (value != NULL) {
 115         current_version = get_schema_version(value);
 116     }
 117 
 118     if (max) {
 119         max_version = get_schema_version(max);
 120     }
 121 
 122     rc = update_validation(result_cib, &new_version, max_version, TRUE, TRUE);
 123     if (new_version > current_version) {
 124         cib_update_counter(*result_cib, XML_ATTR_GENERATION_ADMIN, FALSE);
 125         cib_update_counter(*result_cib, XML_ATTR_GENERATION, TRUE);
 126         cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, TRUE);
 127         return pcmk_ok;
 128     }
 129 
 130     return rc;
 131 }
 132 
 133 int
 134 cib_process_bump(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
 135                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 136 {
 137     int result = pcmk_ok;
 138 
 139     crm_trace("Processing \"%s\" event for epoch=%s",
 140               op, crm_str(crm_element_value(existing_cib, XML_ATTR_GENERATION)));
 141 
 142     *answer = NULL;
 143     cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);
 144 
 145     return result;
 146 }
 147 
 148 int
 149 cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151     char *new_value = NULL;
 152     char *old_value = NULL;
 153     int int_value = -1;
 154 
 155     if (reset == FALSE && crm_element_value(xml_obj, field) != NULL) {
 156         old_value = crm_element_value_copy(xml_obj, field);
 157     }
 158     if (old_value != NULL) {
 159         new_value = calloc(1, 128);
 160         int_value = atoi(old_value);
 161         sprintf(new_value, "%d", ++int_value);
 162     } else {
 163         new_value = strdup("1");
 164     }
 165 
 166     crm_trace("%s %d(%s)->%s", field, int_value, crm_str(old_value), crm_str(new_value));
 167     crm_xml_add(xml_obj, field, new_value);
 168 
 169     free(new_value);
 170     free(old_value);
 171 
 172     return pcmk_ok;
 173 }
 174 
 175 int
 176 cib_process_replace(const char *op, int options, const char *section, xmlNode * req,
     /* [previous][next][first][last][top][bottom][index][help] */
 177                     xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
 178                     xmlNode ** answer)
 179 {
 180     const char *tag = NULL;
 181     int result = pcmk_ok;
 182 
 183     crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section));
 184 
 185     if (options & cib_xpath) {
 186         return cib_process_xpath(op, options, section, req, input,
 187                                  existing_cib, result_cib, answer);
 188     }
 189 
 190     *answer = NULL;
 191 
 192     if (input == NULL) {
 193         return -EINVAL;
 194     }
 195 
 196     tag = crm_element_name(input);
 197 
 198     if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
 199         section = NULL;
 200 
 201     } else if (safe_str_eq(tag, section)) {
 202         section = NULL;
 203     }
 204 
 205     if (safe_str_eq(tag, XML_TAG_CIB)) {
 206         int updates = 0;
 207         int epoch = 0;
 208         int admin_epoch = 0;
 209 
 210         int replace_updates = 0;
 211         int replace_epoch = 0;
 212         int replace_admin_epoch = 0;
 213 
 214         const char *reason = NULL;
 215         const char *peer = crm_element_value(req, F_ORIG);
 216         const char *digest = crm_element_value(req, XML_ATTR_DIGEST);
 217 
 218         if (digest) {
 219             const char *version = crm_element_value(req, XML_ATTR_CRM_VERSION);
 220             char *digest_verify = calculate_xml_versioned_digest(input, FALSE, TRUE,
 221                                                                  version ? version :
 222                                                                  CRM_FEATURE_SET);
 223 
 224             if (safe_str_neq(digest_verify, digest)) {
 225                 crm_err("Digest mis-match on replace from %s: %s vs. %s (expected)", peer,
 226                         digest_verify, digest);
 227                 reason = "digest mismatch";
 228 
 229             } else {
 230                 crm_info("Digest matched on replace from %s: %s", peer, digest);
 231             }
 232             free(digest_verify);
 233 
 234         } else {
 235             crm_trace("No digest to verify");
 236         }
 237 
 238         cib_version_details(existing_cib, &admin_epoch, &epoch, &updates);
 239         cib_version_details(input, &replace_admin_epoch, &replace_epoch, &replace_updates);
 240 
 241         if (replace_admin_epoch < admin_epoch) {
 242             reason = XML_ATTR_GENERATION_ADMIN;
 243 
 244         } else if (replace_admin_epoch > admin_epoch) {
 245             /* no more checks */
 246 
 247         } else if (replace_epoch < epoch) {
 248             reason = XML_ATTR_GENERATION;
 249 
 250         } else if (replace_epoch > epoch) {
 251             /* no more checks */
 252 
 253         } else if (replace_updates < updates) {
 254             reason = XML_ATTR_NUMUPDATES;
 255         }
 256 
 257         if (reason != NULL) {
 258             crm_info("Replacement %d.%d.%d from %s not applied to %d.%d.%d:"
 259                      " current %s is greater than the replacement",
 260                      replace_admin_epoch, replace_epoch,
 261                      replace_updates, peer, admin_epoch, epoch, updates, reason);
 262             result = -pcmk_err_old_data;
 263         } else {
 264             crm_info("Replaced %d.%d.%d with %d.%d.%d from %s",
 265                      admin_epoch, epoch, updates,
 266                      replace_admin_epoch, replace_epoch, replace_updates, peer);
 267         }
 268 
 269         free_xml(*result_cib);
 270         *result_cib = copy_xml(input);
 271 
 272     } else {
 273         xmlNode *obj_root = NULL;
 274         gboolean ok = TRUE;
 275 
 276         obj_root = get_object_root(section, *result_cib);
 277         ok = replace_xml_child(NULL, obj_root, input, FALSE);
 278         if (ok == FALSE) {
 279             crm_trace("No matching object to replace");
 280             result = -ENXIO;
 281         }
 282     }
 283 
 284     return result;
 285 }
 286 
 287 int
 288 cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
 289                    xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 290 {
 291     xmlNode *obj_root = NULL;
 292 
 293     crm_trace("Processing \"%s\" event", op);
 294 
 295     if (options & cib_xpath) {
 296         return cib_process_xpath(op, options, section, req, input,
 297                                  existing_cib, result_cib, answer);
 298     }
 299 
 300     if (input == NULL) {
 301         crm_err("Cannot perform modification with no data");
 302         return -EINVAL;
 303     }
 304 
 305     obj_root = get_object_root(section, *result_cib);
 306     if(safe_str_eq(crm_element_name(input), section)) {
 307         xmlNode *child = NULL;
 308         for(child = __xml_first_child(input); child; child = __xml_next(child)) {
 309             if (replace_xml_child(NULL, obj_root, child, TRUE) == FALSE) {
 310                 crm_trace("No matching object to delete: %s=%s", child->name, ID(child));
 311             }
 312         }
 313 
 314     } else if (replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) {
 315             crm_trace("No matching object to delete: %s=%s", input->name, ID(input));
 316     }
 317 
 318     return pcmk_ok;
 319 }
 320 
 321 int
 322 cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
 323                    xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 324 {
 325     xmlNode *obj_root = NULL;
 326 
 327     crm_trace("Processing \"%s\" event", op);
 328 
 329     if (options & cib_xpath) {
 330         return cib_process_xpath(op, options, section, req, input,
 331                                  existing_cib, result_cib, answer);
 332     }
 333 
 334     if (input == NULL) {
 335         crm_err("Cannot perform modification with no data");
 336         return -EINVAL;
 337     }
 338 
 339     obj_root = get_object_root(section, *result_cib);
 340     if (obj_root == NULL) {
 341         xmlNode *tmp_section = NULL;
 342         const char *path = get_object_parent(section);
 343 
 344         if (path == NULL) {
 345             return -EINVAL;
 346         }
 347 
 348         tmp_section = create_xml_node(NULL, section);
 349         cib_process_xpath(CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer);
 350         free_xml(tmp_section);
 351 
 352         obj_root = get_object_root(section, *result_cib);
 353     }
 354 
 355     CRM_CHECK(obj_root != NULL, return -EINVAL);
 356 
 357     if (update_xml_child(obj_root, input) == FALSE) {
 358         if (options & cib_can_create) {
 359             add_node_copy(obj_root, input);
 360         } else {
 361             return -ENXIO;
 362         }
 363     }
 364 
 365     if(options & cib_mixed_update) {
 366         int max = 0, lpc;
 367         xmlXPathObjectPtr xpathObj = xpath_search(*result_cib, "//@__delete__");
 368 
 369         if (xpathObj) {
 370             max = numXpathResults(xpathObj);
 371             crm_log_xml_trace(*result_cib, "Mixed result");
 372         }
 373 
 374         for (lpc = 0; lpc < max; lpc++) {
 375             xmlNode *match = getXpathResult(xpathObj, lpc);
 376             xmlChar *match_path = xmlGetNodePath(match);
 377 
 378             crm_debug("Destroying %s", match_path);
 379             free(match_path);
 380             free_xml(match);
 381         }
 382 
 383         freeXpathObject(xpathObj);
 384     }
 385     return pcmk_ok;
 386 }
 387 
 388 static int
 389 update_cib_object(xmlNode * parent, xmlNode * update)
     /* [previous][next][first][last][top][bottom][index][help] */
 390 {
 391     int result = pcmk_ok;
 392     xmlNode *target = NULL;
 393     xmlNode *a_child = NULL;
 394     const char *replace = NULL;
 395     const char *object_id = NULL;
 396     const char *object_name = NULL;
 397 
 398     CRM_CHECK(update != NULL, return -EINVAL);
 399     CRM_CHECK(parent != NULL, return -EINVAL);
 400 
 401     object_name = crm_element_name(update);
 402     CRM_CHECK(object_name != NULL, return -EINVAL);
 403 
 404     object_id = ID(update);
 405     crm_trace("Processing: <%s id=%s>", crm_str(object_name), crm_str(object_id));
 406 
 407     if (object_id == NULL) {
 408         /*  placeholder object */
 409         target = find_xml_node(parent, object_name, FALSE);
 410 
 411     } else {
 412         target = find_entity(parent, object_name, object_id);
 413     }
 414 
 415     if (target == NULL) {
 416         target = create_xml_node(parent, object_name);
 417     }
 418 
 419     crm_trace("Found node <%s id=%s> to update", crm_str(object_name), crm_str(object_id));
 420 
 421     replace = crm_element_value(update, XML_CIB_ATTR_REPLACE);
 422     if (replace != NULL) {
 423         xmlNode *remove = NULL;
 424         int last = 0, lpc = 0, len = 0;
 425 
 426         len = strlen(replace);
 427         while (lpc <= len) {
 428             if (replace[lpc] == ',' || replace[lpc] == 0) {
 429                 char *replace_item = NULL;
 430 
 431                 if (last == lpc) {
 432                     /* nothing to do */
 433                     last = lpc + 1;
 434                     goto incr;
 435                 }
 436 
 437                 replace_item = calloc(1, lpc - last + 1);
 438                 memcpy(replace_item, replace + last, lpc - last);
 439 
 440                 remove = find_xml_node(target, replace_item, FALSE);
 441                 if (remove != NULL) {
 442                     crm_trace("Replacing node <%s> in <%s>",
 443                               replace_item, crm_element_name(target));
 444                     free_xml(remove);
 445                     remove = NULL;
 446                 }
 447                 free(replace_item);
 448                 last = lpc + 1;
 449             }
 450   incr:
 451             lpc++;
 452         }
 453         xml_remove_prop(update, XML_CIB_ATTR_REPLACE);
 454         xml_remove_prop(target, XML_CIB_ATTR_REPLACE);
 455     }
 456 
 457     copy_in_properties(target, update);
 458 
 459     crm_trace("Processing children of <%s id=%s>", crm_str(object_name), crm_str(object_id));
 460 
 461     for (a_child = __xml_first_child(update); a_child != NULL; a_child = __xml_next(a_child)) {
 462         int tmp_result = 0;
 463 
 464         crm_trace("Updating child <%s id=%s>", crm_element_name(a_child), ID(a_child));
 465 
 466         tmp_result = update_cib_object(target, a_child);
 467 
 468         /*  only the first error is likely to be interesting */
 469         if (tmp_result != pcmk_ok) {
 470             crm_err("Error updating child <%s id=%s>", crm_element_name(a_child), ID(a_child));
 471 
 472             if (result == pcmk_ok) {
 473                 result = tmp_result;
 474             }
 475         }
 476     }
 477 
 478     crm_trace("Finished with <%s id=%s>", crm_str(object_name), crm_str(object_id));
 479 
 480     return result;
 481 }
 482 
 483 static int
 484 add_cib_object(xmlNode * parent, xmlNode * new_obj)
     /* [previous][next][first][last][top][bottom][index][help] */
 485 {
 486     int result = pcmk_ok;
 487     const char *object_name = NULL;
 488     const char *object_id = NULL;
 489     xmlNode *equiv_node = NULL;
 490 
 491     if (new_obj != NULL) {
 492         object_name = crm_element_name(new_obj);
 493     }
 494     object_id = crm_element_value(new_obj, XML_ATTR_ID);
 495 
 496     crm_trace("Processing: <%s id=%s>", crm_str(object_name), crm_str(object_id));
 497 
 498     if (new_obj == NULL || object_name == NULL) {
 499         result = -EINVAL;
 500 
 501     } else if (parent == NULL) {
 502         result = -EINVAL;
 503 
 504     } else if (object_id == NULL) {
 505         /*  placeholder object */
 506         equiv_node = find_xml_node(parent, object_name, FALSE);
 507 
 508     } else {
 509         equiv_node = find_entity(parent, object_name, object_id);
 510     }
 511 
 512     if (result != pcmk_ok) {
 513         ;                       /* do nothing */
 514 
 515     } else if (equiv_node != NULL) {
 516         result = -ENOTUNIQ;
 517 
 518     } else {
 519         result = update_cib_object(parent, new_obj);
 520     }
 521 
 522     return result;
 523 }
 524 
 525 int
 526 cib_process_create(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
 527                    xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 528 {
 529     xmlNode *failed = NULL;
 530     int result = pcmk_ok;
 531     xmlNode *update_section = NULL;
 532 
 533     crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section));
 534     if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
 535         section = NULL;
 536 
 537     } else if (safe_str_eq(XML_TAG_CIB, section)) {
 538         section = NULL;
 539 
 540     } else if (safe_str_eq(crm_element_name(input), XML_TAG_CIB)) {
 541         section = NULL;
 542     }
 543 
 544     CRM_CHECK(strcasecmp(CIB_OP_CREATE, op) == 0, return -EINVAL);
 545 
 546     if (input == NULL) {
 547         crm_err("Cannot perform modification with no data");
 548         return -EINVAL;
 549     }
 550 
 551     if (section == NULL) {
 552         return cib_process_modify(op, options, section, req, input, existing_cib, result_cib,
 553                                   answer);
 554     }
 555 
 556     failed = create_xml_node(NULL, XML_TAG_FAILED);
 557 
 558     update_section = get_object_root(section, *result_cib);
 559     if (safe_str_eq(crm_element_name(input), section)) {
 560         xmlNode *a_child = NULL;
 561 
 562         for (a_child = __xml_first_child(input); a_child != NULL; a_child = __xml_next(a_child)) {
 563             result = add_cib_object(update_section, a_child);
 564             if (update_results(failed, a_child, op, result)) {
 565                 break;
 566             }
 567         }
 568 
 569     } else {
 570         result = add_cib_object(update_section, input);
 571         update_results(failed, input, op, result);
 572     }
 573 
 574     if (xml_has_children(failed)) {
 575         CRM_CHECK(result != pcmk_ok, result = -EINVAL);
 576     }
 577 
 578     if (result != pcmk_ok) {
 579         crm_log_xml_err(failed, "CIB Update failures");
 580         *answer = failed;
 581 
 582     } else {
 583         free_xml(failed);
 584     }
 585 
 586     return result;
 587 }
 588 
 589 int
 590 cib_process_diff(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
 591                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 592 {
 593     const char *originator = NULL;
 594 
 595     if (req != NULL) {
 596         originator = crm_element_value(req, F_ORIG);
 597     }
 598 
 599     crm_trace("Processing \"%s\" event from %s %s",
 600               op, originator, is_set(options, cib_force_diff)?"(global update)":"");
 601 
 602     free_xml(*result_cib);
 603     *result_cib = copy_xml(existing_cib);
 604     return xml_apply_patchset(*result_cib, input, TRUE);
 605 }
 606 
 607 gboolean
 608 cib_config_changed(xmlNode * last, xmlNode * next, xmlNode ** diff)
     /* [previous][next][first][last][top][bottom][index][help] */
 609 {
 610     int lpc = 0, max = 0;
 611     gboolean config_changes = FALSE;
 612     xmlXPathObject *xpathObj = NULL;
 613     int format = 1;
 614 
 615     CRM_ASSERT(diff != NULL);
 616 
 617     if (*diff == NULL && last != NULL && next != NULL) {
 618         *diff = diff_xml_object(last, next, FALSE);
 619     }
 620 
 621     if (*diff == NULL) {
 622         goto done;
 623     }
 624 
 625     crm_element_value_int(*diff, "format", &format);
 626     /* This function only applies to v1 diffs. */
 627     CRM_LOG_ASSERT(format == 1);
 628 
 629     xpathObj = xpath_search(*diff, "//" XML_CIB_TAG_CONFIGURATION);
 630     if (numXpathResults(xpathObj) > 0) {
 631         config_changes = TRUE;
 632         goto done;
 633     }
 634     freeXpathObject(xpathObj);
 635 
 636     /*
 637      * Do not check XML_TAG_DIFF_ADDED "//" XML_TAG_CIB
 638      * This always contains every field and would produce a false positive
 639      * every time if the checked value existed
 640      */
 641     xpathObj = xpath_search(*diff, "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_CIB);
 642     max = numXpathResults(xpathObj);
 643 
 644     for (lpc = 0; lpc < max; lpc++) {
 645         xmlNode *top = getXpathResult(xpathObj, lpc);
 646 
 647         if (crm_element_value(top, XML_ATTR_GENERATION) != NULL) {
 648             config_changes = TRUE;
 649             goto done;
 650         }
 651         if (crm_element_value(top, XML_ATTR_GENERATION_ADMIN) != NULL) {
 652             config_changes = TRUE;
 653             goto done;
 654         }
 655 
 656         if (crm_element_value(top, XML_ATTR_VALIDATION) != NULL) {
 657             config_changes = TRUE;
 658             goto done;
 659         }
 660         if (crm_element_value(top, XML_ATTR_CRM_VERSION) != NULL) {
 661             config_changes = TRUE;
 662             goto done;
 663         }
 664         if (crm_element_value(top, "remote-clear-port") != NULL) {
 665             config_changes = TRUE;
 666             goto done;
 667         }
 668         if (crm_element_value(top, "remote-tls-port") != NULL) {
 669             config_changes = TRUE;
 670             goto done;
 671         }
 672     }
 673 
 674   done:
 675     freeXpathObject(xpathObj);
 676     return config_changes;
 677 }
 678 
 679 int
 680 cib_process_xpath(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
     /* [previous][next][first][last][top][bottom][index][help] */
 681                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 682 {
 683     int lpc = 0;
 684     int max = 0;
 685     int rc = pcmk_ok;
 686     gboolean is_query = safe_str_eq(op, CIB_OP_QUERY);
 687 
 688     xmlXPathObjectPtr xpathObj = NULL;
 689 
 690     crm_trace("Processing \"%s\" event", op);
 691 
 692     if (is_query) {
 693         xpathObj = xpath_search(existing_cib, section);
 694     } else {
 695         xpathObj = xpath_search(*result_cib, section);
 696     }
 697 
 698     max = numXpathResults(xpathObj);
 699 
 700     if (max < 1 && safe_str_eq(op, CIB_OP_DELETE)) {
 701         crm_debug("%s was already removed", section);
 702 
 703     } else if (max < 1) {
 704         crm_debug("%s: %s does not exist", op, section);
 705         rc = -ENXIO;
 706 
 707     } else if (is_query) {
 708         if (max > 1) {
 709             *answer = create_xml_node(NULL, "xpath-query");
 710         }
 711     }
 712 
 713     if (safe_str_eq(op, CIB_OP_DELETE) && (options & cib_multiple)) {
 714         dedupXpathResults(xpathObj);
 715     }
 716 
 717     for (lpc = 0; lpc < max; lpc++) {
 718         xmlChar *path = NULL;
 719         xmlNode *match = getXpathResult(xpathObj, lpc);
 720 
 721         if (match == NULL) {
 722             continue;
 723         }
 724 
 725         path = xmlGetNodePath(match);
 726         crm_debug("Processing %s op for %s with %s", op, section, path);
 727         free(path);
 728 
 729         if (safe_str_eq(op, CIB_OP_DELETE)) {
 730             if (match == *result_cib) {
 731                 /* Attempting to delete the whole "/cib" */
 732                 crm_warn("Cannot perform %s for %s: The xpath is addressing the whole /cib", op, section);
 733                 rc = -EINVAL;
 734                 break;
 735             }
 736 
 737             free_xml(match);
 738             if ((options & cib_multiple) == 0) {
 739                 break;
 740             }
 741 
 742         } else if (safe_str_eq(op, CIB_OP_MODIFY)) {
 743             if (update_xml_child(match, input) == FALSE) {
 744                 rc = -ENXIO;
 745             } else if ((options & cib_multiple) == 0) {
 746                 break;
 747             }
 748 
 749         } else if (safe_str_eq(op, CIB_OP_CREATE)) {
 750             add_node_copy(match, input);
 751             break;
 752 
 753         } else if (safe_str_eq(op, CIB_OP_QUERY)) {
 754 
 755             if (options & cib_no_children) {
 756                 const char *tag = TYPE(match);
 757                 xmlNode *shallow = create_xml_node(*answer, tag);
 758 
 759                 copy_in_properties(shallow, match);
 760 
 761                 if (*answer == NULL) {
 762                     *answer = shallow;
 763                 }
 764 
 765             } else if (options & cib_xpath_address) {
 766 
 767                 int path_len = 0;
 768                 char *path = NULL;
 769                 xmlNode *parent = match;
 770 
 771                 while (parent && parent->type == XML_ELEMENT_NODE) {
 772                     int extra = 1;
 773                     char *new_path = NULL;
 774                     const char *id = crm_element_value(parent, XML_ATTR_ID);
 775 
 776                     extra += strlen((const char *)parent->name);
 777                     if (id) {
 778                         extra += 8;     /* [@id=""] */
 779                         extra += strlen(id);
 780                     }
 781 
 782                     path_len += extra;
 783                     new_path = malloc(path_len + 1);
 784                     if(new_path == NULL) {
 785                         break;
 786 
 787                     } else if (id) {
 788                         snprintf(new_path, path_len + 1, "/%s[@id='%s']%s", parent->name, id,
 789                                  path ? path : "");
 790                     } else {
 791                         snprintf(new_path, path_len + 1, "/%s%s", parent->name, path ? path : "");
 792                     }
 793                     free(path);
 794                     path = new_path;
 795                     parent = parent->parent;
 796                 }
 797                 crm_trace("Got: %s", path);
 798 
 799                 if (*answer == NULL) {
 800                     *answer = create_xml_node(NULL, "xpath-query");
 801                 }
 802                 parent = create_xml_node(*answer, "xpath-query-path");
 803                 crm_xml_add(parent, XML_ATTR_ID, path);
 804                 free(path);
 805 
 806             } else if (*answer) {
 807                 add_node_copy(*answer, match);
 808 
 809             } else {
 810                 *answer = match;
 811             }
 812 
 813         } else if (safe_str_eq(op, CIB_OP_REPLACE)) {
 814             xmlNode *parent = match->parent;
 815 
 816             free_xml(match);
 817             if (input != NULL) {
 818                 add_node_copy(parent, input);
 819             }
 820 
 821             if ((options & cib_multiple) == 0) {
 822                 break;
 823             }
 824         }
 825     }
 826 
 827     freeXpathObject(xpathObj);
 828     return rc;
 829 }
 830 
 831 /* remove this function */
 832 gboolean
 833 update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 834 {
 835     xmlNode *xml_node = NULL;
 836     gboolean was_error = FALSE;
 837     const char *error_msg = NULL;
 838 
 839     if (return_code != pcmk_ok) {
 840         error_msg = pcmk_strerror(return_code);
 841 
 842         was_error = TRUE;
 843         xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB);
 844         add_node_copy(xml_node, target);
 845 
 846         crm_xml_add(xml_node, XML_FAILCIB_ATTR_ID, ID(target));
 847         crm_xml_add(xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target));
 848         crm_xml_add(xml_node, XML_FAILCIB_ATTR_OP, operation);
 849         crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg);
 850 
 851         crm_warn("Action %s failed: %s (cde=%d)", operation, error_msg, return_code);
 852     }
 853 
 854     return was_error;
 855 }

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