19 #include <sys/param.h> 20 #include <sys/types.h> 23 #include <libxml/tree.h> 33 static GHashTable *operation_table = NULL;
144 CRM_ASSERT((op != NULL) && (operation != NULL));
146 if (operation_table == NULL) {
149 for (
int lpc = 0; lpc <
PCMK__NELEM(cib_ops); lpc++) {
152 g_hash_table_insert(operation_table, (gpointer) oper->
name,
157 *operation = g_hash_table_lookup(operation_table, op);
158 if (*operation == NULL) {
159 crm_err(
"Operation %s is invalid", op);
167 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
169 xmlNode *obj_root = NULL;
172 crm_trace(
"Processing %s for %s section",
173 op, pcmk__s(section,
"unspecified"));
177 existing_cib, result_cib, answer);
189 if (obj_root == NULL) {
194 (
const char *) obj_root->name);
204 crm_err(
"Error creating query response");
212 update_counter(xmlNode *xml_obj,
const char *field,
bool reset)
214 char *new_value = NULL;
215 char *old_value = NULL;
221 if (old_value != NULL) {
222 int_value = atoi(old_value);
223 new_value = pcmk__itoa(++int_value);
225 new_value = strdup(
"1");
230 field, pcmk__s(old_value,
"unset"), new_value);
241 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
245 crm_trace(
"Processing \"%s\" event", op);
247 if (*result_cib != existing_cib) {
260 xmlNode *
input, xmlNode * existing_cib, xmlNode ** result_cib,
265 int current_version = 0;
271 crm_trace(
"Processing \"%s\" event with max=%s", op, max);
283 if (new_version > current_version) {
295 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
299 crm_trace(
"Processing %s for epoch='%s'", op,
310 xmlNode *
input, xmlNode * existing_cib, xmlNode ** result_cib,
315 crm_trace(
"Processing %s for %s section",
316 op, pcmk__s(section,
"unspecified"));
320 existing_cib, result_cib, answer);
332 }
else if (pcmk__xe_is(
input, section)) {
341 int replace_updates = 0;
342 int replace_epoch = 0;
343 int replace_admin_epoch = 0;
345 const char *reason = NULL;
356 crm_err(
"Digest mis-match on replace from %s: %s vs. %s (expected)", peer,
357 digest_verify, digest);
358 reason =
"digest mismatch";
361 crm_info(
"Digest matched on replace from %s: %s", peer, digest);
372 if (replace_admin_epoch < admin_epoch) {
375 }
else if (replace_admin_epoch > admin_epoch) {
378 }
else if (replace_epoch < epoch) {
381 }
else if (replace_epoch > epoch) {
384 }
else if (replace_updates < updates) {
388 if (reason != NULL) {
389 crm_info(
"Replacement %d.%d.%d from %s not applied to %d.%d.%d:" 390 " current %s is greater than the replacement",
391 replace_admin_epoch, replace_epoch,
392 replace_updates, peer, admin_epoch, epoch, updates, reason);
395 crm_info(
"Replaced %d.%d.%d with %d.%d.%d from %s",
396 admin_epoch, epoch, updates,
397 replace_admin_epoch, replace_epoch, replace_updates, peer);
400 if (*result_cib != existing_cib) {
406 xmlNode *obj_root = NULL;
412 crm_trace(
"No matching object to replace");
422 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
424 xmlNode *obj_root = NULL;
426 crm_trace(
"Processing \"%s\" event", op);
430 existing_cib, result_cib, answer);
434 crm_err(
"Cannot perform modification with no data");
439 if (pcmk__xe_is(
input, section)) {
440 xmlNode *child = NULL;
441 for (child = pcmk__xml_first_child(
input); child;
442 child = pcmk__xml_next(child)) {
444 crm_trace(
"No matching object to delete: %s=%s", child->name,
ID(child));
457 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
459 xmlNode *obj_root = NULL;
461 crm_trace(
"Processing \"%s\" event", op);
465 existing_cib, result_cib, answer);
469 crm_err(
"Cannot perform modification with no data");
474 if (obj_root == NULL) {
475 xmlNode *tmp_section = NULL;
484 NULL, result_cib, answer);
490 CRM_CHECK(obj_root != NULL,
return -EINVAL);
503 xmlXPathObjectPtr xpathObj =
xpath_search(*result_cib,
"//@__delete__");
506 max = numXpathResults(xpathObj);
510 for (lpc = 0; lpc < max; lpc++) {
512 xmlChar *match_path = xmlGetNodePath(match);
525 update_cib_object(xmlNode *
parent, xmlNode * update)
529 xmlNode *a_child = NULL;
530 const char *replace = NULL;
531 const char *object_id = NULL;
532 const char *object_name = NULL;
534 CRM_CHECK(update != NULL,
return -EINVAL);
537 object_name = (
const char *) update->name;
538 CRM_CHECK(object_name != NULL,
return -EINVAL);
540 object_id =
ID(update);
541 crm_trace(
"Processing update for <%s%s%s%s>", object_name,
543 pcmk__s(object_id,
""),
544 ((object_id == NULL)?
"" :
"'"));
546 if (object_id == NULL) {
558 crm_trace(
"Found node <%s%s%s%s> to update", object_name,
560 pcmk__s(object_id,
""),
561 ((object_id == NULL)?
"" :
"'"));
565 if (replace != NULL) {
567 int len = strlen(replace);
569 for (
int lpc = 0; lpc <= len; ++lpc) {
570 if (replace[lpc] ==
',' || replace[lpc] == 0) {
572 char *replace_item = strndup(replace + last, lpc - last);
576 if (
remove != NULL) {
578 replace_item,
target->name);
594 pcmk__s(object_name,
"<null>"),
595 pcmk__s(object_id,
"<null>"));
599 crm_trace(
"Processing children of <%s%s%s%s>", object_name,
601 pcmk__s(object_id,
""),
602 ((object_id == NULL)?
"" :
"'"));
604 for (a_child = pcmk__xml_first_child(update); a_child != NULL;
605 a_child = pcmk__xml_next(a_child)) {
608 crm_trace(
"Updating child <%s%s%s%s>", a_child->name,
610 pcmk__s(
ID(a_child),
""), ((
ID(a_child) == NULL)?
"" :
"'"));
612 tmp_result = update_cib_object(
target, a_child);
616 crm_err(
"Error updating child <%s%s%s%s>",
619 pcmk__s(
ID(a_child),
""),
620 ((
ID(a_child) == NULL)?
"" :
"'"));
628 crm_trace(
"Finished handling update for <%s%s%s%s>", object_name,
630 pcmk__s(object_id,
""),
631 ((object_id == NULL)?
"" :
"'"));
637 add_cib_object(xmlNode *
parent, xmlNode * new_obj)
639 const char *object_name = NULL;
640 const char *object_id = NULL;
641 xmlNode *equiv_node = NULL;
643 if ((
parent == NULL) || (new_obj == NULL)) {
647 object_name = (
const char *) new_obj->name;
648 if (object_name == NULL) {
652 object_id =
ID(new_obj);
654 crm_trace(
"Processing creation of <%s%s%s%s>", object_name,
656 pcmk__s(object_id,
""),
657 ((object_id == NULL)?
"" :
"'"));
659 if (object_id == NULL) {
665 if (equiv_node != NULL) {
669 return update_cib_object(
parent, new_obj);
673 update_results(xmlNode *failed, xmlNode *
target,
const char *operation,
676 xmlNode *xml_node = NULL;
677 bool was_error =
false;
678 const char *error_msg = NULL;
689 (
const char *)
target->name);
693 crm_warn(
"Action %s failed: %s (cde=%d)",
694 operation, error_msg, return_code);
702 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
704 xmlNode *failed = NULL;
706 xmlNode *update_section = NULL;
708 crm_trace(
"Processing %s for %s section",
709 op, pcmk__s(section,
"unspecified"));
723 crm_err(
"Cannot perform modification with no data");
727 if (section == NULL) {
735 if (pcmk__xe_is(
input, section)) {
736 xmlNode *a_child = NULL;
738 for (a_child = pcmk__xml_first_child(
input); a_child != NULL;
739 a_child = pcmk__xml_next(a_child)) {
740 result = add_cib_object(update_section, a_child);
741 if (update_results(failed, a_child, op,
result)) {
768 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
770 const char *originator = NULL;
776 crm_trace(
"Processing \"%s\" event from %s%s",
780 if (*result_cib != existing_cib) {
783 *result_cib =
copy_xml(existing_cib);
792 int lpc = 0, max = 0;
793 bool config_changes =
false;
794 xmlXPathObject *xpathObj = NULL;
799 if (*diff == NULL && last != NULL && next != NULL) {
811 if (numXpathResults(xpathObj) > 0) {
812 config_changes =
true;
823 max = numXpathResults(xpathObj);
825 for (lpc = 0; lpc < max; lpc++) {
829 config_changes =
true;
833 config_changes =
true;
838 config_changes =
true;
842 config_changes =
true;
846 config_changes =
true;
850 config_changes =
true;
857 return config_changes;
862 const xmlNode *req, xmlNode *
input, xmlNode *existing_cib,
863 xmlNode **result_cib, xmlNode **answer)
870 xmlXPathObjectPtr xpathObj = NULL;
872 crm_trace(
"Processing \"%s\" event", op);
880 max = numXpathResults(xpathObj);
884 crm_debug(
"%s was already removed", section);
886 }
else if (max < 1) {
887 crm_debug(
"%s: %s does not exist", op, section);
890 }
else if (is_query) {
901 for (lpc = 0; lpc < max; lpc++) {
902 xmlChar *
path = NULL;
909 path = xmlGetNodePath(match);
910 crm_debug(
"Processing %s op for %s with %s", op, section,
path);
914 if (match == *result_cib) {
916 crm_warn(
"Cannot perform %s for %s: The xpath is addressing the whole /cib", op, section);
941 (
const char *) match->name);
945 if (*answer == NULL) {
955 char *new_path = NULL;
972 if (*answer == NULL) {
979 }
else if (*answer) {
988 xmlNode *
parent = match->parent;
#define pcmk_err_old_data
#define CRM_CHECK(expr, failure_action)
int cib__get_operation(const char *op, const cib__operation_t **operation)
bool cib__config_changed_v1(xmlNode *last, xmlNode *next, xmlNode **diff)
#define crm_notice(fmt, args...)
const char * pcmk_strerror(int rc)
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
#define XML_CIB_TAG_SECTION_ALL
int cib_process_create(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int cib_process_modify(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
#define XML_ATTR_NUMUPDATES
xmlNode * pcmk__xe_match(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
#define PCMK__CIB_REQUEST_SYNC_TO_ONE
#define PCMK__CIB_REQUEST_PRIMARY
#define PCMK__CIB_REQUEST_CREATE
int cib_process_delete(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
#define PCMK__CIB_REQUEST_QUERY
void copy_in_properties(xmlNode *target, const xmlNode *src)
xmlNode * find_xml_node(const xmlNode *root, const char *search_path, gboolean must_find)
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int get_schema_version(const char *name)
#define CRM_LOG_ASSERT(expr)
Supported in a transaction.
void dedupXpathResults(xmlXPathObjectPtr xpathObj)
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
#define XML_ATTR_GENERATION
#define PCMK__CIB_REQUEST_ERASE
int cib_process_diff(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
xmlNode * copy_xml(xmlNode *src_node)
#define PCMK__CIB_REQUEST_ABS_DELETE
#define crm_warn(fmt, args...)
Writes to disk on success.
#define crm_debug(fmt, args...)
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define PCMK__CIB_REQUEST_IS_PRIMARY
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
int cib_process_upgrade(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
gboolean update_xml_child(xmlNode *child, xmlNode *to_update)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int cib_process_xpath(const char *op, int options, const char *section, const xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Wrappers for and extensions to libxml2.
int cib_process_erase(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int cib_process_query(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
xmlNode * create_xml_node(xmlNode *parent, const char *name)
#define XML_ATTR_VALIDATION
const char * pcmk_cib_parent_name_for(const char *element_name)
Get the parent element name of a given CIB element name.
Must only be processed locally.
#define XML_FAILCIB_ATTR_OP
void free_xml(xmlNode *child)
#define XML_FAILCIB_ATTR_OBJTYPE
#define PCMK__CIB_REQUEST_UPGRADE
#define PCMK__CIB_REQUEST_BUMP
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
int cib_process_replace(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
#define crm_log_xml_err(xml, text)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
pcmk__action_result_t result
#define crm_err(fmt, args...)
#define PCMK__CIB_REQUEST_REPLACE
#define XML_FAILCIB_ATTR_REASON
void xml_remove_prop(xmlNode *obj, const char *name)
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
char * calculate_xml_versioned_digest(xmlNode *input, gboolean sort, gboolean do_filter, const char *version)
Calculate and return digest of XML tree.
#define PCMK__CIB_REQUEST_SYNC_TO_ALL
#define XML_ATTR_GENERATION_ADMIN
#define XML_CIB_ATTR_REPLACE
#define PCMK__CIB_REQUEST_SECONDARY
#define PCMK__CIB_REQUEST_NOOP
#define XML_ATTR_CRM_VERSION
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
int update_validation(xmlNode **xml_blob, int *best, int max, gboolean transform, gboolean to_logs)
Update CIB XML to most recent schema version.
xmlNode * diff_xml_object(xmlNode *left, xmlNode *right, gboolean suppress)
#define crm_log_xml_trace(xml, text)
#define PCMK__CIB_REQUEST_MODIFY
#define XML_TAG_DIFF_REMOVED
#define XML_CIB_TAG_CONFIGURATION
#define XML_FAILCIB_ATTR_ID
void freeXpathObject(xmlXPathObjectPtr xpathObj)
#define PCMK__CIB_REQUEST_SHUTDOWN
#define crm_info(fmt, args...)
#define PCMK__CIB_REQUEST_APPLY_PATCH
int cib_process_bump(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
#define PCMK__CIB_REQUEST_DELETE
gboolean replace_xml_child(xmlNode *parent, xmlNode *child, xmlNode *update, gboolean delete_only)