23#include <libxml/tree.h>
24#include <libxml/xpath.h>
33static GHashTable *operation_table = NULL;
149 if (operation_table == NULL) {
152 for (
int lpc = 0; lpc <
PCMK__NELEM(cib_ops); lpc++) {
155 g_hash_table_insert(operation_table, (gpointer) oper->
name,
160 *operation = g_hash_table_lookup(operation_table, op);
161 if (*operation == NULL) {
162 crm_err(
"Operation %s is invalid", op);
170 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
172 xmlNode *obj_root = NULL;
175 crm_trace(
"Processing %s for %s section",
176 op, pcmk__s(section,
"unspecified"));
180 existing_cib, result_cib, answer);
192 if (obj_root == NULL) {
197 (
const char *) obj_root->name);
207 crm_err(
"Error creating query response");
215update_counter(xmlNode *xml_obj,
const char *field,
bool reset)
217 char *new_value = NULL;
218 char *old_value = NULL;
224 if (old_value != NULL) {
225 int_value = atoi(old_value);
226 new_value = pcmk__itoa(++int_value);
232 field, pcmk__s(old_value,
"unset"), new_value);
243 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
247 crm_trace(
"Processing \"%s\" event", op);
249 if (*result_cib != existing_cib) {
262 xmlNode *
input, xmlNode * existing_cib, xmlNode ** result_cib,
267 const char *original_schema = NULL;
268 const char *new_schema = NULL;
271 crm_trace(
"Processing \"%s\" event with max=%s", op, max_schema);
291 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
295 crm_trace(
"Processing %s for epoch='%s'", op,
306 xmlNode *
input, xmlNode * existing_cib, xmlNode ** result_cib,
311 crm_trace(
"Processing %s for %s section",
312 op, pcmk__s(section,
"unspecified"));
316 existing_cib, result_cib, answer);
328 }
else if (pcmk__xe_is(
input, section)) {
337 int replace_updates = 0;
338 int replace_epoch = 0;
339 int replace_admin_epoch = 0;
341 const char *reason = NULL;
349 crm_err(
"Digest mis-match on replace from %s: %s vs. %s (expected)", peer,
350 digest_verify, digest);
351 reason =
"digest mismatch";
354 crm_info(
"Digest matched on replace from %s: %s", peer, digest);
365 if (replace_admin_epoch < admin_epoch) {
368 }
else if (replace_admin_epoch > admin_epoch) {
371 }
else if (replace_epoch < epoch) {
374 }
else if (replace_epoch > epoch) {
377 }
else if (replace_updates < updates) {
381 if (reason != NULL) {
382 crm_info(
"Replacement %d.%d.%d from %s not applied to %d.%d.%d:"
383 " current %s is greater than the replacement",
384 replace_admin_epoch, replace_epoch,
385 replace_updates, peer, admin_epoch, epoch, updates, reason);
388 crm_info(
"Replaced %d.%d.%d with %d.%d.%d from %s",
389 admin_epoch, epoch, updates,
390 replace_admin_epoch, replace_epoch, replace_updates, peer);
393 if (*result_cib != existing_cib) {
399 xmlNode *obj_root = NULL;
405 crm_trace(
"No matching object to replace");
413delete_child(xmlNode *child,
void *userdata)
415 xmlNode *obj_root = userdata;
418 crm_trace(
"No matching object to delete: %s=%s",
419 child->name, pcmk__xe_id(child));
427 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
429 xmlNode *obj_root = NULL;
431 crm_trace(
"Processing \"%s\" event", op);
435 existing_cib, result_cib, answer);
439 crm_err(
"Cannot perform modification with no data");
444 if (pcmk__xe_is(
input, section)) {
447 delete_child(
input, obj_root);
455 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
457 xmlNode *obj_root = NULL;
460 crm_trace(
"Processing \"%s\" event", op);
464 existing_cib, result_cib, answer);
468 crm_err(
"Cannot perform modification with no data");
473 if (obj_root == NULL) {
474 xmlNode *tmp_section = NULL;
483 NULL, result_cib, answer);
489 CRM_CHECK(obj_root != NULL,
return -EINVAL);
507add_cib_object(xmlNode *
parent, xmlNode * new_obj)
509 const char *object_name = NULL;
510 const char *object_id = NULL;
512 if ((
parent == NULL) || (new_obj == NULL)) {
516 object_name = (
const char *) new_obj->name;
517 if (object_name == NULL) {
521 object_id = pcmk__xe_id(new_obj);
528 if (object_id != NULL) {
530 object_name, object_id);
532 crm_trace(
"Processing creation of <%s>", object_name);
551update_results(xmlNode *failed, xmlNode *
target,
const char *operation,
554 xmlNode *xml_node = NULL;
555 bool was_error =
false;
556 const char *error_msg = NULL;
570 crm_warn(
"Action %s failed: %s (cde=%d)",
571 operation, error_msg, return_code);
579 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
581 xmlNode *failed = NULL;
583 xmlNode *update_section = NULL;
585 crm_trace(
"Processing %s for %s section",
586 op, pcmk__s(section,
"unspecified"));
600 crm_err(
"Cannot perform modification with no data");
604 if (section == NULL) {
613 if (pcmk__xe_is(
input, section)) {
614 xmlNode *a_child = NULL;
616 for (a_child = pcmk__xml_first_child(
input); a_child != NULL;
617 a_child = pcmk__xml_next(a_child)) {
618 result = add_cib_object(update_section, a_child);
619 if (update_results(failed, a_child, op,
result)) {
646 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
648 const char *originator = NULL;
654 crm_trace(
"Processing \"%s\" event from %s%s",
658 if (*result_cib != existing_cib) {
668 const xmlNode *req, xmlNode *
input, xmlNode *existing_cib,
669 xmlNode **result_cib, xmlNode **answer)
677 xmlXPathObject *xpathObj = NULL;
679 crm_trace(
"Processing \"%s\" event", op);
687 num_results = pcmk__xpath_num_results(xpathObj);
688 if (num_results == 0) {
690 crm_debug(
"%s was already removed", section);
693 crm_debug(
"%s: %s does not exist", op, section);
699 if (is_query && (num_results > 1)) {
703 for (
int i = 0; i < num_results; i++) {
704 xmlNode *match = NULL;
705 xmlChar *
path = NULL;
723 if (delete_multiple) {
733 path = xmlGetNodePath(match);
734 crm_debug(
"Processing %s op for %s with %s", op, section,
path);
738 if (match == *result_cib) {
740 crm_warn(
"Cannot perform %s for %s: The xpath is addressing the whole /cib", op, section);
771 (
const char *) match->name);
775 if (*answer == NULL) {
785 char *new_path = NULL;
802 if (*answer == NULL) {
809 }
else if (*answer) {
818 xmlNode *
parent = match->parent;
830 xmlXPathFreeObject(xpathObj);
#define PCMK__CIB_REQUEST_SYNC_TO_ONE
#define PCMK__CIB_REQUEST_ABS_DELETE
#define PCMK__CIB_REQUEST_SYNC_TO_ALL
#define PCMK__CIB_REQUEST_PRIMARY
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
#define PCMK__CIB_REQUEST_IS_PRIMARY
@ cib__op_attr_none
No special attributes.
@ cib__op_attr_transaction
Supported in a transaction.
@ cib__op_attr_privileged
Requires privileges.
@ cib__op_attr_local
Must only be processed locally.
@ cib__op_attr_replaces
Replaces CIB.
@ cib__op_attr_modifies
Modifies CIB.
@ cib__op_attr_writes_through
Writes to disk on success.
#define PCMK__CIB_REQUEST_SECONDARY
#define PCMK__CIB_REQUEST_QUERY
#define PCMK__CIB_REQUEST_REPLACE
#define PCMK__CIB_REQUEST_DELETE
#define PCMK__CIB_REQUEST_APPLY_PATCH
#define PCMK__CIB_REQUEST_BUMP
#define PCMK__CIB_REQUEST_CREATE
#define PCMK__CIB_REQUEST_NOOP
#define PCMK__CIB_REQUEST_MODIFY
#define PCMK__CIB_REQUEST_SHUTDOWN
@ cib__op_commit_transact
#define PCMK__CIB_REQUEST_UPGRADE
#define PCMK__CIB_REQUEST_SCHEMAS
#define PCMK__CIB_REQUEST_ERASE
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
int cib_process_delete(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
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)
int cib__get_operation(const char *op, const cib__operation_t **operation)
int cib_process_query(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)
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_bump(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int cib_process_replace(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int cib_process_diff(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int cib_process_upgrade(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
int cib_process_erase(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
@ cib_score_update
Treat new attribute values as atomic score updates where possible.
@ cib_verbose
Prefer stderr to logs.
const char * pcmk_cib_parent_name_for(const char *element_name)
Get the parent element name of a given CIB element name.
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
char * pcmk__digest_xml(xmlNode *input, bool filter)
#define crm_info(fmt, args...)
#define crm_warn(fmt, args...)
#define crm_log_xml_err(xml, text)
#define CRM_CHECK(expr, failure_action)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
pcmk__action_result_t result
const char * pcmk_strerror(int rc)
#define pcmk_err_old_data
int pcmk_rc2legacy(int rc)
#define pcmk__assert(expr)
int pcmk__cmp_schemas_by_name(const char *schema1_name, const char *schema2_name)
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.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
#define pcmk__str_copy(str)
Wrappers for and extensions to libxml2.
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data)
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search)
int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
@ pcmk__xaf_none
Flag has no effect.
bool pcmk__xml_tree_foreach(xmlNode *xml, bool(*fn)(xmlNode *, void *), void *user_data)
void pcmk__xml_free(xmlNode *xml)
#define PCMK_XA_VALIDATE_WITH
#define PCMK_XA_OBJECT_TYPE
#define PCMK_XA_OPERATION
#define PCMK_XA_ADMIN_EPOCH
#define PCMK_XA_NUM_UPDATES
#define PCMK__XA_CIB_SCHEMA_MAX
#define PCMK__XE_FAILED_UPDATE
#define PCMK__XE_XPATH_QUERY_PATH
#define PCMK__XE_XPATH_QUERY
xmlXPathObject * pcmk__xpath_search(xmlDoc *doc, const char *path)
xmlNode * pcmk__xpath_result(xmlXPathObject *xpath_obj, int index)