19 #include <sys/param.h> 20 #include <sys/types.h> 23 #include <libxml/tree.h> 32 static GHashTable *operation_table = NULL;
146 CRM_ASSERT((op != NULL) && (operation != NULL));
148 if (operation_table == NULL) {
151 for (
int lpc = 0; lpc <
PCMK__NELEM(cib_ops); lpc++) {
154 g_hash_table_insert(operation_table, (gpointer) oper->
name,
159 *operation = g_hash_table_lookup(operation_table, op);
160 if (*operation == NULL) {
161 crm_err(
"Operation %s is invalid", op);
169 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
171 xmlNode *obj_root = NULL;
174 crm_trace(
"Processing %s for %s section",
175 op, pcmk__s(section,
"unspecified"));
179 existing_cib, result_cib, answer);
191 if (obj_root == NULL) {
196 (
const char *) obj_root->name);
206 crm_err(
"Error creating query response");
214 update_counter(xmlNode *xml_obj,
const char *field,
bool reset)
216 char *new_value = NULL;
217 char *old_value = NULL;
223 if (old_value != NULL) {
224 int_value = atoi(old_value);
225 new_value = pcmk__itoa(++int_value);
231 field, pcmk__s(old_value,
"unset"), new_value);
242 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
246 crm_trace(
"Processing \"%s\" event", op);
248 if (*result_cib != existing_cib) {
261 xmlNode *
input, xmlNode * existing_cib, xmlNode ** result_cib,
266 const char *original_schema = NULL;
267 const char *new_schema = NULL;
270 crm_trace(
"Processing \"%s\" event with max=%s", op, max_schema);
290 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
294 crm_trace(
"Processing %s for epoch='%s'", op,
305 xmlNode *
input, xmlNode * existing_cib, xmlNode ** result_cib,
310 crm_trace(
"Processing %s for %s section",
311 op, pcmk__s(section,
"unspecified"));
315 existing_cib, result_cib, answer);
327 }
else if (pcmk__xe_is(
input, section)) {
336 int replace_updates = 0;
337 int replace_epoch = 0;
338 int replace_admin_epoch = 0;
340 const char *reason = NULL;
352 crm_err(
"Digest mis-match on replace from %s: %s vs. %s (expected)", peer,
353 digest_verify, digest);
354 reason =
"digest mismatch";
357 crm_info(
"Digest matched on replace from %s: %s", peer, digest);
368 if (replace_admin_epoch < admin_epoch) {
371 }
else if (replace_admin_epoch > admin_epoch) {
374 }
else if (replace_epoch < epoch) {
377 }
else if (replace_epoch > epoch) {
380 }
else if (replace_updates < updates) {
384 if (reason != NULL) {
385 crm_info(
"Replacement %d.%d.%d from %s not applied to %d.%d.%d:" 386 " current %s is greater than the replacement",
387 replace_admin_epoch, replace_epoch,
388 replace_updates, peer, admin_epoch, epoch, updates, reason);
391 crm_info(
"Replaced %d.%d.%d with %d.%d.%d from %s",
392 admin_epoch, epoch, updates,
393 replace_admin_epoch, replace_epoch, replace_updates, peer);
396 if (*result_cib != existing_cib) {
402 xmlNode *obj_root = NULL;
408 crm_trace(
"No matching object to replace");
416 delete_child(xmlNode *child,
void *userdata)
418 xmlNode *obj_root = userdata;
421 crm_trace(
"No matching object to delete: %s=%s",
422 child->name, pcmk__xe_id(child));
430 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
432 xmlNode *obj_root = NULL;
434 crm_trace(
"Processing \"%s\" event", op);
438 existing_cib, result_cib, answer);
442 crm_err(
"Cannot perform modification with no data");
447 if (pcmk__xe_is(
input, section)) {
450 delete_child(
input, obj_root);
458 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
460 xmlNode *obj_root = NULL;
463 crm_trace(
"Processing \"%s\" event", op);
467 existing_cib, result_cib, answer);
471 crm_err(
"Cannot perform modification with no data");
476 if (obj_root == NULL) {
477 xmlNode *tmp_section = NULL;
486 NULL, result_cib, answer);
492 CRM_CHECK(obj_root != NULL,
return -EINVAL);
509 xmlXPathObjectPtr xpathObj =
xpath_search(*result_cib,
"//@__delete__");
512 max = numXpathResults(xpathObj);
516 for (lpc = 0; lpc < max; lpc++) {
518 xmlChar *match_path = xmlGetNodePath(match);
531 add_cib_object(xmlNode *
parent, xmlNode * new_obj)
533 const char *object_name = NULL;
534 const char *object_id = NULL;
536 if ((
parent == NULL) || (new_obj == NULL)) {
540 object_name = (
const char *) new_obj->name;
541 if (object_name == NULL) {
545 object_id = pcmk__xe_id(new_obj);
552 if (object_id != NULL) {
554 object_name, object_id);
556 crm_trace(
"Processing creation of <%s>", object_name);
575 update_results(xmlNode *failed, xmlNode *
target,
const char *operation,
578 xmlNode *xml_node = NULL;
579 bool was_error =
false;
580 const char *error_msg = NULL;
594 crm_warn(
"Action %s failed: %s (cde=%d)",
595 operation, error_msg, return_code);
603 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
605 xmlNode *failed = NULL;
607 xmlNode *update_section = NULL;
609 crm_trace(
"Processing %s for %s section",
610 op, pcmk__s(section,
"unspecified"));
624 crm_err(
"Cannot perform modification with no data");
628 if (section == NULL) {
637 if (pcmk__xe_is(
input, section)) {
638 xmlNode *a_child = NULL;
640 for (a_child = pcmk__xml_first_child(
input); a_child != NULL;
641 a_child = pcmk__xml_next(a_child)) {
642 result = add_cib_object(update_section, a_child);
643 if (update_results(failed, a_child, op,
result)) {
670 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
672 const char *originator = NULL;
678 crm_trace(
"Processing \"%s\" event from %s%s",
682 if (*result_cib != existing_cib) {
694 int lpc = 0, max = 0;
695 bool config_changes =
false;
696 xmlXPathObject *xpathObj = NULL;
701 if (*diff == NULL && last != NULL && next != NULL) {
713 if (numXpathResults(xpathObj) > 0) {
714 config_changes =
true;
725 max = numXpathResults(xpathObj);
727 for (lpc = 0; lpc < max; lpc++) {
731 config_changes =
true;
735 config_changes =
true;
740 config_changes =
true;
744 config_changes =
true;
748 config_changes =
true;
752 config_changes =
true;
759 return config_changes;
764 const xmlNode *req, xmlNode *
input, xmlNode *existing_cib,
765 xmlNode **result_cib, xmlNode **answer)
772 xmlXPathObjectPtr xpathObj = NULL;
774 crm_trace(
"Processing \"%s\" event", op);
782 max = numXpathResults(xpathObj);
786 crm_debug(
"%s was already removed", section);
788 }
else if (max < 1) {
789 crm_debug(
"%s: %s does not exist", op, section);
792 }
else if (is_query) {
803 for (lpc = 0; lpc < max; lpc++) {
804 xmlChar *
path = NULL;
811 path = xmlGetNodePath(match);
812 crm_debug(
"Processing %s op for %s with %s", op, section,
path);
816 if (match == *result_cib) {
818 crm_warn(
"Cannot perform %s for %s: The xpath is addressing the whole /cib", op, section);
849 (
const char *) match->name);
853 if (*answer == NULL) {
863 char *new_path = NULL;
880 if (*answer == NULL) {
887 }
else if (*answer) {
896 xmlNode *
parent = match->parent;
#define pcmk_err_old_data
#define CRM_CHECK(expr, failure_action)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
#define PCMK__XE_DIFF_REMOVED
int cib__get_operation(const char *op, const cib__operation_t **operation)
bool cib__config_changed_v1(xmlNode *last, xmlNode *next, xmlNode **diff)
const char * pcmk_strerror(int rc)
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
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 pcmk__cmp_schemas_by_name(const char *schema1_name, const char *schema2_name)
int cib_process_modify(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int pcmk_rc2legacy(int rc)
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
#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)
xmlNode * pcmk__diff_v1_xml_object(xmlNode *left, xmlNode *right, bool suppress)
#define PCMK_XA_REMOTE_CLEAR_PORT
int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace)
#define PCMK__CIB_REQUEST_QUERY
#define PCMK_XA_NUM_UPDATES
#define PCMK__XE_FAILED_UPDATE
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
#define PCMK__XE_XPATH_QUERY
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#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 PCMK__XA_CIB_SCHEMA_MAX
#define PCMK_XA_OPERATION
#define PCMK__CIB_REQUEST_ERASE
int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search)
int cib_process_diff(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
#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__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
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)
#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.
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)
#define PCMK_XA_REMOTE_TLS_PORT
bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data)
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.
void free_xml(xmlNode *child)
#define PCMK_XE_CONFIGURATION
int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags)
#define pcmk__str_copy(str)
#define PCMK_XA_VALIDATE_WITH
#define PCMK__XE_XPATH_QUERY_PATH
int pcmk__update_schema(xmlNode **xml, const char *max_schema_name, bool transform, bool to_logs)
Update CIB XML to latest schema that validates it.
#define PCMK__CIB_REQUEST_UPGRADE
#define PCMK__CIB_REQUEST_BUMP
#define PCMK_XA_CRM_FEATURE_SET
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 PCMK__CIB_REQUEST_SCHEMAS
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
#define crm_err(fmt, args...)
#define PCMK__CIB_REQUEST_REPLACE
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 PCMK__CIB_REQUEST_SECONDARY
#define PCMK__CIB_REQUEST_NOOP
bool pcmk__xml_tree_foreach(xmlNode *xml, bool(*fn)(xmlNode *, void *), void *user_data)
#define crm_log_xml_trace(xml, text)
#define PCMK__CIB_REQUEST_MODIFY
#define PCMK_XA_OBJECT_TYPE
#define PCMK_XA_ADMIN_EPOCH
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Treat new attribute values as atomic score updates where possible.
#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