diff options
Diffstat (limited to '')
-rw-r--r-- | lib/cib/cib_ops.c | 228 |
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); |