summaryrefslogtreecommitdiffstats
path: root/lib/cib/cib_ops.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/cib/cib_ops.c228
1 files changed, 181 insertions, 47 deletions
diff --git a/lib/cib/cib_ops.c b/lib/cib/cib_ops.c
index d3293c4..c324304 100644
--- a/lib/cib/cib_ops.c
+++ b/lib/cib/cib_ops.c
@@ -19,6 +19,9 @@
#include <sys/param.h>
#include <sys/types.h>
+#include <glib.h>
+#include <libxml/tree.h>
+
#include <crm/crm.h>
#include <crm/cib/internal.h>
#include <crm/msg_xml.h>
@@ -26,6 +29,139 @@
#include <crm/common/xml.h>
#include <crm/common/xml_internal.h>
+// @TODO: Free this via crm_exit() when libcib gets merged with libcrmcommon
+static GHashTable *operation_table = NULL;
+
+static const cib__operation_t cib_ops[] = {
+ {
+ PCMK__CIB_REQUEST_ABS_DELETE, cib__op_abs_delete,
+ cib__op_attr_modifies|cib__op_attr_privileged
+ },
+ {
+ PCMK__CIB_REQUEST_APPLY_PATCH, cib__op_apply_patch,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_BUMP, cib__op_bump,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_COMMIT_TRANSACT, cib__op_commit_transact,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_replaces
+ |cib__op_attr_writes_through
+ },
+ {
+ PCMK__CIB_REQUEST_CREATE, cib__op_create,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_DELETE, cib__op_delete,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_ERASE, cib__op_erase,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_replaces
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_IS_PRIMARY, cib__op_is_primary,
+ cib__op_attr_privileged
+ },
+ {
+ PCMK__CIB_REQUEST_MODIFY, cib__op_modify,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_NOOP, cib__op_noop, cib__op_attr_none
+ },
+ {
+ CRM_OP_PING, cib__op_ping, cib__op_attr_none
+ },
+ {
+ // @COMPAT: Drop cib__op_attr_modifies when we drop legacy mode support
+ PCMK__CIB_REQUEST_PRIMARY, cib__op_primary,
+ cib__op_attr_modifies|cib__op_attr_privileged|cib__op_attr_local
+ },
+ {
+ PCMK__CIB_REQUEST_QUERY, cib__op_query, cib__op_attr_none
+ },
+ {
+ PCMK__CIB_REQUEST_REPLACE, cib__op_replace,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_replaces
+ |cib__op_attr_writes_through
+ |cib__op_attr_transaction
+ },
+ {
+ PCMK__CIB_REQUEST_SECONDARY, cib__op_secondary,
+ cib__op_attr_privileged|cib__op_attr_local
+ },
+ {
+ PCMK__CIB_REQUEST_SHUTDOWN, cib__op_shutdown, cib__op_attr_privileged
+ },
+ {
+ PCMK__CIB_REQUEST_SYNC_TO_ALL, cib__op_sync_all, cib__op_attr_privileged
+ },
+ {
+ PCMK__CIB_REQUEST_SYNC_TO_ONE, cib__op_sync_one, cib__op_attr_privileged
+ },
+ {
+ PCMK__CIB_REQUEST_UPGRADE, cib__op_upgrade,
+ cib__op_attr_modifies
+ |cib__op_attr_privileged
+ |cib__op_attr_writes_through
+ |cib__op_attr_transaction
+ },
+};
+
+/*!
+ * \internal
+ * \brief Get the \c cib__operation_t object for a given CIB operation name
+ *
+ * \param[in] op CIB operation name
+ * \param[out] operation Where to store CIB operation object
+ *
+ * \return Standard Pacemaker return code
+ */
+int
+cib__get_operation(const char *op, const cib__operation_t **operation)
+{
+ CRM_ASSERT((op != NULL) && (operation != NULL));
+
+ if (operation_table == NULL) {
+ operation_table = pcmk__strkey_table(NULL, NULL);
+
+ for (int lpc = 0; lpc < PCMK__NELEM(cib_ops); lpc++) {
+ const cib__operation_t *oper = &(cib_ops[lpc]);
+
+ g_hash_table_insert(operation_table, (gpointer) oper->name,
+ (gpointer) oper);
+ }
+ }
+
+ *operation = g_hash_table_lookup(operation_table, op);
+ if (*operation == NULL) {
+ crm_err("Operation %s is invalid", op);
+ return EINVAL;
+ }
+ return pcmk_rc_ok;
+}
+
int
cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
@@ -54,8 +190,8 @@ cib_process_query(const char *op, int options, const char *section, xmlNode * re
result = -ENXIO;
} else if (options & cib_no_children) {
- const char *tag = TYPE(obj_root);
- xmlNode *shallow = create_xml_node(*answer, tag);
+ xmlNode *shallow = create_xml_node(*answer,
+ (const char *) obj_root->name);
copy_in_properties(shallow, obj_root);
*answer = shallow;
@@ -107,12 +243,14 @@ cib_process_erase(const char *op, int options, const char *section, xmlNode * re
int result = pcmk_ok;
crm_trace("Processing \"%s\" event", op);
- *answer = NULL;
- free_xml(*result_cib);
- *result_cib = createEmptyCib(0);
+ if (*result_cib != existing_cib) {
+ free_xml(*result_cib);
+ }
+ *result_cib = createEmptyCib(0);
copy_in_properties(*result_cib, existing_cib);
update_counter(*result_cib, XML_ATTR_GENERATION_ADMIN, false);
+ *answer = NULL;
return result;
}
@@ -172,7 +310,6 @@ cib_process_replace(const char *op, int options, const char *section, xmlNode *
xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
xmlNode ** answer)
{
- const char *tag = NULL;
int result = pcmk_ok;
crm_trace("Processing %s for %s section",
@@ -189,16 +326,14 @@ cib_process_replace(const char *op, int options, const char *section, xmlNode *
return -EINVAL;
}
- tag = crm_element_name(input);
-
if (pcmk__str_eq(XML_CIB_TAG_SECTION_ALL, section, pcmk__str_casei)) {
section = NULL;
- } else if (pcmk__str_eq(tag, section, pcmk__str_casei)) {
+ } else if (pcmk__xe_is(input, section)) {
section = NULL;
}
- if (pcmk__str_eq(tag, XML_TAG_CIB, pcmk__str_casei)) {
+ if (pcmk__xe_is(input, XML_TAG_CIB)) {
int updates = 0;
int epoch = 0;
int admin_epoch = 0;
@@ -262,7 +397,9 @@ cib_process_replace(const char *op, int options, const char *section, xmlNode *
replace_admin_epoch, replace_epoch, replace_updates, peer);
}
- free_xml(*result_cib);
+ if (*result_cib != existing_cib) {
+ free_xml(*result_cib);
+ }
*result_cib = copy_xml(input);
} else {
@@ -299,7 +436,7 @@ cib_process_delete(const char *op, int options, const char *section, xmlNode * r
}
obj_root = pcmk_find_cib_element(*result_cib, section);
- if(pcmk__str_eq(crm_element_name(input), section, pcmk__str_casei)) {
+ if (pcmk__xe_is(input, section)) {
xmlNode *child = NULL;
for (child = pcmk__xml_first_child(input); child;
child = pcmk__xml_next(child)) {
@@ -360,7 +497,8 @@ cib_process_modify(const char *op, int options, const char *section, xmlNode * r
}
}
- if(options & cib_mixed_update) {
+ // @COMPAT cib_mixed_update is deprecated as of 2.1.7
+ if (pcmk_is_set(options, cib_mixed_update)) {
int max = 0, lpc;
xmlXPathObjectPtr xpathObj = xpath_search(*result_cib, "//@__delete__");
@@ -396,7 +534,7 @@ update_cib_object(xmlNode * parent, xmlNode * update)
CRM_CHECK(update != NULL, return -EINVAL);
CRM_CHECK(parent != NULL, return -EINVAL);
- object_name = crm_element_name(update);
+ object_name = (const char *) update->name;
CRM_CHECK(object_name != NULL, return -EINVAL);
object_id = ID(update);
@@ -425,33 +563,25 @@ update_cib_object(xmlNode * parent, xmlNode * update)
// @COMPAT: XML_CIB_ATTR_REPLACE is unused internally. Remove at break.
replace = crm_element_value(update, XML_CIB_ATTR_REPLACE);
if (replace != NULL) {
- xmlNode *remove = NULL;
- int last = 0, lpc = 0, len = 0;
+ int last = 0;
+ int len = strlen(replace);
- len = strlen(replace);
- while (lpc <= len) {
+ for (int lpc = 0; lpc <= len; ++lpc) {
if (replace[lpc] == ',' || replace[lpc] == 0) {
- char *replace_item = NULL;
-
- if (last == lpc) {
- /* nothing to do */
- last = lpc + 1;
- goto incr;
- }
-
- replace_item = strndup(replace + last, lpc - last);
- remove = find_xml_node(target, replace_item, FALSE);
- if (remove != NULL) {
- crm_trace("Replacing node <%s> in <%s>",
- replace_item, crm_element_name(target));
- free_xml(remove);
- remove = NULL;
+ if (last != lpc) {
+ char *replace_item = strndup(replace + last, lpc - last);
+ xmlNode *remove = find_xml_node(target, replace_item,
+ FALSE);
+
+ if (remove != NULL) {
+ crm_trace("Replacing node <%s> in <%s>",
+ replace_item, target->name);
+ free_xml(remove);
+ }
+ free(replace_item);
}
- free(replace_item);
last = lpc + 1;
}
- incr:
- lpc++;
}
xml_remove_prop(update, XML_CIB_ATTR_REPLACE);
xml_remove_prop(target, XML_CIB_ATTR_REPLACE);
@@ -475,7 +605,7 @@ update_cib_object(xmlNode * parent, xmlNode * update)
a_child = pcmk__xml_next(a_child)) {
int tmp_result = 0;
- crm_trace("Updating child <%s%s%s%s>", crm_element_name(a_child),
+ crm_trace("Updating child <%s%s%s%s>", a_child->name,
((ID(a_child) == NULL)? "" : " " XML_ATTR_ID "='"),
pcmk__s(ID(a_child), ""), ((ID(a_child) == NULL)? "" : "'"));
@@ -484,7 +614,7 @@ update_cib_object(xmlNode * parent, xmlNode * update)
/* only the first error is likely to be interesting */
if (tmp_result != pcmk_ok) {
crm_err("Error updating child <%s%s%s%s>",
- crm_element_name(a_child),
+ a_child->name,
((ID(a_child) == NULL)? "" : " " XML_ATTR_ID "='"),
pcmk__s(ID(a_child), ""),
((ID(a_child) == NULL)? "" : "'"));
@@ -514,7 +644,7 @@ add_cib_object(xmlNode * parent, xmlNode * new_obj)
return -EINVAL;
}
- object_name = crm_element_name(new_obj);
+ object_name = (const char *) new_obj->name;
if (object_name == NULL) {
return -EINVAL;
}
@@ -555,7 +685,8 @@ update_results(xmlNode *failed, xmlNode *target, const char *operation,
add_node_copy(xml_node, target);
crm_xml_add(xml_node, XML_FAILCIB_ATTR_ID, ID(target));
- crm_xml_add(xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target));
+ crm_xml_add(xml_node, XML_FAILCIB_ATTR_OBJTYPE,
+ (const char *) target->name);
crm_xml_add(xml_node, XML_FAILCIB_ATTR_OP, operation);
crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg);
@@ -582,7 +713,7 @@ cib_process_create(const char *op, int options, const char *section, xmlNode * r
} else if (pcmk__str_eq(XML_TAG_CIB, section, pcmk__str_casei)) {
section = NULL;
- } else if (pcmk__str_eq(crm_element_name(input), XML_TAG_CIB, pcmk__str_casei)) {
+ } else if (pcmk__xe_is(input, XML_TAG_CIB)) {
section = NULL;
}
@@ -601,7 +732,7 @@ cib_process_create(const char *op, int options, const char *section, xmlNode * r
failed = create_xml_node(NULL, XML_TAG_FAILED);
update_section = pcmk_find_cib_element(*result_cib, section);
- if (pcmk__str_eq(crm_element_name(input), section, pcmk__str_casei)) {
+ if (pcmk__xe_is(input, section)) {
xmlNode *a_child = NULL;
for (a_child = pcmk__xml_first_child(input); a_child != NULL;
@@ -617,7 +748,7 @@ cib_process_create(const char *op, int options, const char *section, xmlNode * r
update_results(failed, input, op, result);
}
- if ((result == pcmk_ok) && xml_has_children(failed)) {
+ if ((result == pcmk_ok) && (failed->children != NULL)) {
result = -EINVAL;
}
@@ -646,8 +777,11 @@ cib_process_diff(const char *op, int options, const char *section, xmlNode * req
op, originator,
(pcmk_is_set(options, cib_force_diff)? " (global update)" : ""));
- free_xml(*result_cib);
+ if (*result_cib != existing_cib) {
+ free_xml(*result_cib);
+ }
*result_cib = copy_xml(existing_cib);
+
return xml_apply_patchset(*result_cib, input, TRUE);
}
@@ -670,7 +804,7 @@ cib__config_changed_v1(xmlNode *last, xmlNode *next, xmlNode **diff)
goto done;
}
- crm_element_value_int(*diff, "format", &format);
+ crm_element_value_int(*diff, PCMK_XA_FORMAT, &format);
CRM_LOG_ASSERT(format == 1);
xpathObj = xpath_search(*diff, "//" XML_CIB_TAG_CONFIGURATION);
@@ -803,8 +937,8 @@ cib_process_xpath(const char *op, int options, const char *section,
} else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_QUERY, pcmk__str_none)) {
if (options & cib_no_children) {
- const char *tag = TYPE(match);
- xmlNode *shallow = create_xml_node(*answer, tag);
+ xmlNode *shallow = create_xml_node(*answer,
+ (const char *) match->name);
copy_in_properties(shallow, match);