Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/cib/messages.c b/cib/messages.c
index 203c580731..9c998768d9 100644
--- a/cib/messages.c
+++ b/cib/messages.c
@@ -1,462 +1,462 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <crm_internal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/msg.h>
#include <crm/common/xml.h>
#include <crm/common/cluster.h>
#include <cibio.h>
#include <cibmessages.h>
#include <callbacks.h>
#define MAX_DIFF_RETRY 5
#ifdef CIBPIPE
gboolean cib_is_master = TRUE;
#else
gboolean cib_is_master = FALSE;
#endif
xmlNode *the_cib = NULL;
gboolean syncd_once = FALSE;
extern const char *cib_our_uname;
enum cib_errors revision_check(xmlNode *cib_update, xmlNode *cib_copy, int flags);
int get_revision(xmlNode *xml_obj, int cur_revision);
enum cib_errors updateList(
xmlNode *local_cib, xmlNode *update_command, xmlNode *failed,
int operation, const char *section);
gboolean check_generation(xmlNode *newCib, xmlNode *oldCib);
gboolean update_results(
xmlNode *failed, xmlNode *target, const char *operation, int return_code);
enum cib_errors cib_update_counter(
xmlNode *xml_obj, const char *field, gboolean reset);
enum cib_errors sync_our_cib(xmlNode *request, gboolean all);
extern xmlNode *cib_msg_copy(const xmlNode *msg, gboolean with_data);
extern gboolean cib_shutdown_flag;
extern void terminate_cib(const char *caller);
enum cib_errors
cib_process_shutdown_req(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
#ifdef CIBPIPE
return cib_invalid_argument;
#else
enum cib_errors result = cib_ok;
const char *host = crm_element_value(req, F_ORIG);
*answer = NULL;
if(crm_element_value(req, F_CIB_ISREPLY) == NULL) {
crm_info("Shutdown REQ from %s", host);
return cib_ok;
} else if(cib_shutdown_flag) {
crm_info("Shutdown ACK from %s", host);
terminate_cib(__FUNCTION__);
return cib_ok;
} else {
crm_err("Shutdown ACK from %s - not shutting down",host);
result = cib_unknown;
}
return result;
#endif
}
enum cib_errors
cib_process_default(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event", op);
*answer = NULL;
if(op == NULL) {
result = cib_operation;
crm_err("No operation specified");
} else if(strcasecmp(CRM_OP_NOOP, op) == 0) {
;
} else {
result = cib_NOTSUPPORTED;
crm_err("Action [%s] is not supported by the CIB", op);
}
return result;
}
enum cib_errors
cib_process_quit(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event", op);
crm_warn("The CRMd has asked us to exit... complying");
exit(0);
return result;
}
enum cib_errors
cib_process_readwrite(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
#ifdef CIBPIPE
return cib_invalid_argument;
#else
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event", op);
if(safe_str_eq(op, CIB_OP_ISMASTER)) {
if(cib_is_master == TRUE) {
result = cib_ok;
} else {
result = cib_not_master;
}
return result;
}
if(safe_str_eq(op, CIB_OP_MASTER)) {
if(cib_is_master == FALSE) {
crm_info("We are now in R/W mode");
cib_is_master = TRUE;
syncd_once = TRUE;
} else {
crm_debug("We are still in R/W mode");
}
} else if(cib_is_master) {
crm_info("We are now in R/O mode");
cib_is_master = FALSE;
}
return result;
#endif
}
enum cib_errors
cib_process_ping(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
#ifdef CIBPIPE
return cib_invalid_argument;
#else
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event", op);
*answer = createPingAnswerFragment(CRM_SYSTEM_CIB, "ok");
return result;
#endif
}
enum cib_errors
cib_process_sync(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
#ifdef CIBPIPE
return cib_invalid_argument;
#else
return sync_our_cib(req, TRUE);
#endif
}
enum cib_errors
cib_process_sync_one(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
#ifdef CIBPIPE
return cib_invalid_argument;
#else
return sync_our_cib(req, FALSE);
#endif
}
int sync_in_progress = 0;
enum cib_errors
cib_server_process_diff(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
int rc = cib_ok;
if(cib_is_master) {
/* the master is never waiting for a resync */
sync_in_progress = 0;
}
if(sync_in_progress > MAX_DIFF_RETRY) {
/* request another full-sync,
* the last request may have been lost
*/
sync_in_progress = 0;
}
if(sync_in_progress) {
int diff_add_updates = 0;
int diff_add_epoch = 0;
int diff_add_admin_epoch = 0;
int diff_del_updates = 0;
int diff_del_epoch = 0;
int diff_del_admin_epoch = 0;
cib_diff_version_details(
input,
&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
sync_in_progress++;
crm_warn("Not applying diff %d.%d.%d -> %d.%d.%d (sync in progress)",
diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
diff_add_admin_epoch,diff_add_epoch,diff_add_updates);
return cib_diff_resync;
}
rc = cib_process_diff(op, options, section, req, input, existing_cib, result_cib, answer);
if(rc == cib_diff_resync && cib_is_master == FALSE) {
xmlNode *sync_me = create_xml_node(NULL, "sync-me");
free_xml(*result_cib);
*result_cib = NULL;
crm_info("Requesting re-sync from peer");
sync_in_progress++;
crm_xml_add(sync_me, F_TYPE, "cib");
crm_xml_add(sync_me, F_CIB_OPERATION, CIB_OP_SYNC_ONE);
crm_xml_add(sync_me, F_CIB_DELEGATED, cib_our_uname);
if(send_cluster_message(NULL, crm_msg_cib, sync_me, FALSE) == FALSE) {
rc = cib_not_connected;
}
free_xml(sync_me);
} else if(rc == cib_diff_resync) {
rc = cib_diff_failed;
if(options & cib_force_diff) {
crm_warn("Not requesting full refresh in slave mode.");
}
}
return rc;
}
enum cib_errors
cib_process_replace_svr(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
const char *tag = crm_element_name(input);
enum cib_errors rc = cib_process_replace(
op, options, section, req, input, existing_cib, result_cib, answer);
if(rc == cib_ok && safe_str_eq(tag, XML_TAG_CIB)) {
sync_in_progress = 0;
}
return rc;
}
static int
delete_cib_object(xmlNode *parent, xmlNode *delete_spec)
{
const char *object_name = NULL;
const char *object_id = NULL;
xmlNode *equiv_node = NULL;
int result = cib_ok;
if(delete_spec != NULL) {
object_name = crm_element_name(delete_spec);
}
object_id = crm_element_value(delete_spec, XML_ATTR_ID);
crm_debug_3("Processing: <%s id=%s>",
crm_str(object_name), crm_str(object_id));
if(delete_spec == NULL) {
result = cib_NOOBJECT;
} else if(parent == NULL) {
result = cib_NOPARENT;
} else if(object_id == NULL) {
/* placeholder object */
equiv_node = find_xml_node(parent, object_name, FALSE);
} else {
equiv_node = find_entity(parent, object_name, object_id);
}
if(result != cib_ok) {
; /* nothing */
} else if(equiv_node == NULL) {
result = cib_ok;
} else if(xml_has_children(delete_spec) == FALSE) {
/* only leaves are deleted */
crm_debug("Removing leaf: <%s id=%s>",
crm_str(object_name), crm_str(object_id));
zap_xml_from_parent(parent, equiv_node);
} else {
xml_child_iter(
delete_spec, child,
int tmp_result = delete_cib_object(equiv_node, child);
/* only the first error is likely to be interesting */
if(tmp_result != cib_ok && result == cib_ok) {
result = tmp_result;
}
);
}
return result;
}
enum cib_errors
cib_process_delete_absolute(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
xmlNode *failed = NULL;
enum cib_errors result = cib_ok;
xmlNode *update_section = NULL;
crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section));
if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
section = NULL;
} else if(safe_str_eq(XML_TAG_CIB, section)) {
section = NULL;
} else if(safe_str_eq(crm_element_name(input), XML_TAG_CIB)) {
section = NULL;
}
CRM_CHECK(strcasecmp(CIB_OP_DELETE, op) == 0, return cib_operation);
if(input == NULL) {
crm_err("Cannot perform modification with no data");
return cib_NOOBJECT;
}
failed = create_xml_node(NULL, XML_TAG_FAILED);
update_section = get_object_root(section, *result_cib);
result = delete_cib_object(update_section, input);
update_results(failed, input, op, result);
if(xml_has_children(failed)) {
CRM_CHECK(result != cib_ok, result = cib_unknown);
}
if (result != cib_ok) {
crm_log_xml_err(failed, "CIB Update failures");
*answer = failed;
} else {
free_xml(failed);
}
return result;
}
gboolean
check_generation(xmlNode *newCib, xmlNode *oldCib)
{
if(cib_compare_generation(newCib, oldCib) >= 0) {
return TRUE;
}
crm_warn("Generation from update is older than the existing one");
return FALSE;
}
#ifndef CIBPIPE
enum cib_errors
sync_our_cib(xmlNode *request, gboolean all)
{
enum cib_errors result = cib_ok;
const char *host = crm_element_value(request, F_ORIG);
const char *op = crm_element_value(request, F_CIB_OPERATION);
xmlNode *replace_request = cib_msg_copy(request, FALSE);
CRM_CHECK(the_cib != NULL, ;);
CRM_CHECK(replace_request != NULL, ;);
- crm_info("Syncing CIB to %s", all?"all peers":host);
+ crm_debug("Syncing CIB to %s", all?"all peers":host);
if(all == FALSE && host == NULL) {
crm_log_xml(LOG_ERR, "bad sync", request);
}
/* remove the "all == FALSE" condition
*
* sync_from was failing, the local client wasnt being notified
* because it didnt know it was a reply
* setting this does not prevent the other nodes from applying it
* if all == TRUE
*/
if(host != NULL) {
crm_xml_add(replace_request, F_CIB_ISREPLY, host);
}
crm_xml_add(replace_request, F_CIB_OPERATION, CIB_OP_REPLACE);
crm_xml_add(replace_request, "original_"F_CIB_OPERATION, op);
crm_xml_add(replace_request, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE);
add_message_xml(replace_request, F_CIB_CALLDATA, the_cib);
if(send_cluster_message(all?NULL:host, crm_msg_cib, replace_request, FALSE) == FALSE) {
result = cib_not_connected;
}
free_xml(replace_request);
return result;
}
#endif
diff --git a/lib/cib/cib_ops.c b/lib/cib/cib_ops.c
index a8e12e89a4..1eb744f0e3 100644
--- a/lib/cib/cib_ops.c
+++ b/lib/cib/cib_ops.c
@@ -1,996 +1,994 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <crm_internal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/msg.h>
#include <crm/common/xml.h>
enum cib_errors
cib_process_query(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
xmlNode *obj_root = NULL;
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event for section=%s",
op, crm_str(section));
if(options & cib_xpath) {
return cib_process_xpath(op, options, section, req, input,
existing_cib, result_cib, answer);
}
CRM_CHECK(*answer == NULL, free_xml(*answer));
*answer = NULL;
if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
section = NULL;
}
obj_root = get_object_root(section, existing_cib);
if(obj_root == NULL) {
result = cib_NOTEXISTS;
} else {
*answer = obj_root;
}
if(result == cib_ok && *answer == NULL) {
crm_err("Error creating query response");
result = cib_output_data;
}
return result;
}
enum cib_errors
cib_process_erase(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event", op);
*answer = NULL;
free_xml(*result_cib);
*result_cib = createEmptyCib();
copy_in_properties(*result_cib, existing_cib);
cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);
return result;
}
enum cib_errors
cib_process_upgrade(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
int rc = 0;
int new_version = 0;
int current_version = 0;
const char *value = NULL;
*answer = NULL;
crm_debug_2("Processing \"%s\" event", op);
value = crm_element_value_copy(existing_cib, XML_ATTR_VALIDATION);
if(value != NULL) {
current_version = get_schema_version(value);
}
rc = update_validation(result_cib, &new_version, TRUE, TRUE);
if(new_version > current_version) {
return cib_ok;
}
return rc;
}
enum cib_errors
cib_process_bump(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event for epoch=%s",
op, crm_str(crm_element_value(existing_cib, XML_ATTR_GENERATION)));
*answer = NULL;
cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);
return result;
}
enum cib_errors
cib_update_counter(xmlNode *xml_obj, const char *field, gboolean reset)
{
char *new_value = NULL;
char *old_value = NULL;
int int_value = -1;
if(reset == FALSE && crm_element_value(xml_obj, field) != NULL) {
old_value = crm_element_value_copy(xml_obj, field);
}
if(old_value != NULL) {
crm_malloc0(new_value, 128);
int_value = atoi(old_value);
sprintf(new_value, "%d", ++int_value);
} else {
new_value = crm_strdup("1");
}
crm_debug_4("%s %d(%s)->%s",
field, int_value, crm_str(old_value), crm_str(new_value));
crm_xml_add(xml_obj, field, new_value);
crm_free(new_value);
crm_free(old_value);
return cib_ok;
}
enum cib_errors
cib_process_replace(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
const char *tag = NULL;
gboolean verbose = FALSE;
enum cib_errors result = cib_ok;
crm_debug_2("Processing \"%s\" event for section=%s",
op, crm_str(section));
if(options & cib_xpath) {
return cib_process_xpath(op, options, section, req, input,
existing_cib, result_cib, answer);
}
*answer = NULL;
if (input == NULL) {
return cib_NOOBJECT;
}
tag = crm_element_name(input);
if (options & cib_verbose) {
verbose = TRUE;
}
if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
section = NULL;
} else if(safe_str_eq(tag, section)) {
section = NULL;
}
if(safe_str_eq(tag, XML_TAG_CIB)) {
int updates = 0;
int epoch = 0;
int admin_epoch = 0;
int replace_updates = 0;
int replace_epoch = 0;
int replace_admin_epoch = 0;
const char *reason = NULL;
cib_version_details(
existing_cib, &admin_epoch, &epoch, &updates);
cib_version_details(input, &replace_admin_epoch,
&replace_epoch, &replace_updates);
if(replace_admin_epoch < admin_epoch) {
reason = XML_ATTR_GENERATION_ADMIN;
} else if(replace_admin_epoch > admin_epoch) {
/* no more checks */
} else if(replace_epoch < epoch) {
reason = XML_ATTR_GENERATION;
} else if(replace_epoch > epoch) {
/* no more checks */
} else if(replace_updates < updates) {
reason = XML_ATTR_NUMUPDATES;
}
if(reason != NULL) {
crm_warn("Replacement %d.%d.%d not applied to %d.%d.%d:"
" current %s is greater than the replacement",
replace_admin_epoch, replace_epoch,
replace_updates, admin_epoch, epoch, updates,
reason);
result = cib_old_data;
}
free_xml(*result_cib);
*result_cib = copy_xml(input);
} else {
xmlNode *obj_root = NULL;
gboolean ok = TRUE;
obj_root = get_object_root(section, *result_cib);
ok = replace_xml_child(NULL, obj_root, input, FALSE);
if(ok == FALSE) {
crm_debug_2("No matching object to replace");
result = cib_NOTEXISTS;
}
}
return result;
}
enum cib_errors
cib_process_delete(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
xmlNode *obj_root = NULL;
crm_debug_2("Processing \"%s\" event", op);
if(options & cib_xpath) {
return cib_process_xpath(op, options, section, req, input,
existing_cib, result_cib, answer);
}
if(input == NULL) {
crm_err("Cannot perform modification with no data");
return cib_NOOBJECT;
}
obj_root = get_object_root(section, *result_cib);
crm_validate_data(input);
crm_validate_data(*result_cib);
if(replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) {
crm_debug_2("No matching object to delete");
}
return cib_ok;
}
enum cib_errors
cib_process_modify(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
xmlNode *obj_root = NULL;
crm_debug_2("Processing \"%s\" event", op);
if(options & cib_xpath) {
return cib_process_xpath(op, options, section, req, input,
existing_cib, result_cib, answer);
}
if(input == NULL) {
crm_err("Cannot perform modification with no data");
return cib_NOOBJECT;
}
obj_root = get_object_root(section, *result_cib);
crm_validate_data(input);
crm_validate_data(*result_cib);
if(obj_root == NULL) {
xmlNode *tmp_section = NULL;
const char *path = get_object_parent(section);
if(path == NULL) {
return cib_bad_section;
}
tmp_section = create_xml_node(NULL, section);
cib_process_xpath(
CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer);
free_xml(tmp_section);
obj_root = get_object_root(section, *result_cib);
}
CRM_CHECK(obj_root != NULL, return cib_unknown);
if(update_xml_child(obj_root, input) == FALSE) {
if(options & cib_can_create) {
add_node_copy(obj_root, input);
} else {
return cib_NOTEXISTS;
}
}
return cib_ok;
}
static int
update_cib_object(xmlNode *parent, xmlNode *update)
{
const char *replace = NULL;
const char *object_name = NULL;
const char *object_id = NULL;
xmlNode *target = NULL;
int result = cib_ok;
CRM_CHECK(update != NULL, return cib_NOOBJECT);
CRM_CHECK(parent != NULL, return cib_NOPARENT);
object_name = crm_element_name(update);
CRM_CHECK(object_name != NULL, return cib_NOOBJECT);
object_id = ID(update);
crm_debug_3("Processing: <%s id=%s>",
crm_str(object_name), crm_str(object_id));
if(object_id == NULL) {
/* placeholder object */
target = find_xml_node(parent, object_name, FALSE);
} else {
target = find_entity(parent, object_name, object_id);
}
if(target == NULL) {
target = create_xml_node(parent, object_name);
}
crm_debug_2("Found node <%s id=%s> to update",
crm_str(object_name), crm_str(object_id));
replace = crm_element_value(update, XML_CIB_ATTR_REPLACE);
if(replace != NULL) {
xmlNode *remove = NULL;
int last = 0, lpc = 0, len = 0;
len = strlen(replace);
while(lpc <= len) {
if(replace[lpc] == ',' || replace[lpc] == 0) {
char *replace_item = NULL;
if ( last == lpc ) {
/* nothing to do */
last = lpc+1;
goto incr;
}
crm_malloc0(replace_item, lpc - last + 1);
strncpy(replace_item, replace+last, lpc-last);
remove = find_xml_node(target, replace_item, FALSE);
if(remove != NULL) {
crm_debug_3("Replacing node <%s> in <%s>",
replace_item, crm_element_name(target));
zap_xml_from_parent(target, remove);
}
crm_free(replace_item);
last = lpc+1;
}
incr:
lpc++;
}
xml_remove_prop(update, XML_CIB_ATTR_REPLACE);
xml_remove_prop(target, XML_CIB_ATTR_REPLACE);
}
copy_in_properties(target, update);
crm_debug_3("Processing children of <%s id=%s>",
crm_str(object_name), crm_str(object_id));
xml_child_iter(
update, a_child,
int tmp_result = 0;
crm_debug_3("Updating child <%s id=%s>",
crm_element_name(a_child), ID(a_child));
tmp_result = update_cib_object(target, a_child);
/* only the first error is likely to be interesting */
if(tmp_result != cib_ok) {
crm_err("Error updating child <%s id=%s>",
crm_element_name(a_child), ID(a_child));
if(result == cib_ok) {
result = tmp_result;
}
}
);
crm_debug_3("Finished with <%s id=%s>",
crm_str(object_name), crm_str(object_id));
return result;
}
static int
add_cib_object(xmlNode *parent, xmlNode *new_obj)
{
enum cib_errors result = cib_ok;
const char *object_name = NULL;
const char *object_id = NULL;
xmlNode *equiv_node = NULL;
if(new_obj != NULL) {
object_name = crm_element_name(new_obj);
}
object_id = crm_element_value(new_obj, XML_ATTR_ID);
crm_debug_3("Processing: <%s id=%s>",
crm_str(object_name), crm_str(object_id));
if(new_obj == NULL || object_name == NULL) {
result = cib_NOOBJECT;
} else if(parent == NULL) {
result = cib_NOPARENT;
} else if(object_id == NULL) {
/* placeholder object */
equiv_node = find_xml_node(parent, object_name, FALSE);
} else {
equiv_node = find_entity(parent, object_name, object_id);
}
if(result != cib_ok) {
; /* do nothing */
} else if(equiv_node != NULL) {
result = cib_EXISTS;
} else {
result = update_cib_object(parent, new_obj);
}
return result;
}
enum cib_errors
cib_process_create(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
xmlNode *failed = NULL;
enum cib_errors result = cib_ok;
xmlNode *update_section = NULL;
crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section));
if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
section = NULL;
} else if(safe_str_eq(XML_TAG_CIB, section)) {
section = NULL;
} else if(safe_str_eq(crm_element_name(input), XML_TAG_CIB)) {
section = NULL;
}
CRM_CHECK(strcasecmp(CIB_OP_CREATE, op) == 0, return cib_operation);
if(input == NULL) {
crm_err("Cannot perform modification with no data");
return cib_NOOBJECT;
}
if(section == NULL) {
return cib_process_modify(op, options, section, req, input, existing_cib, result_cib, answer);
}
failed = create_xml_node(NULL, XML_TAG_FAILED);
update_section = get_object_root(section, *result_cib);
if(safe_str_eq(crm_element_name(input), section)) {
xml_child_iter(input, a_child,
result = add_cib_object(update_section, a_child);
if(update_results(failed, a_child, op, result)) {
break;
}
);
} else {
result = add_cib_object(update_section, input);
update_results(failed, input, op, result);
}
if(xml_has_children(failed)) {
CRM_CHECK(result != cib_ok, result = cib_unknown);
}
if (result != cib_ok) {
crm_log_xml_err(failed, "CIB Update failures");
*answer = failed;
} else {
free_xml(failed);
}
return result;
}
enum cib_errors
cib_process_diff(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
unsigned int log_level = LOG_DEBUG;
const char *reason = NULL;
gboolean apply_diff = TRUE;
enum cib_errors result = cib_ok;
int this_updates = 0;
int this_epoch = 0;
int this_admin_epoch = 0;
int diff_add_updates = 0;
int diff_add_epoch = 0;
int diff_add_admin_epoch = 0;
int diff_del_updates = 0;
int diff_del_epoch = 0;
int diff_del_admin_epoch = 0;
crm_debug_2("Processing \"%s\" event", op);
cib_diff_version_details(
input,
&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
crm_element_value_int(existing_cib, XML_ATTR_GENERATION, &this_epoch);
crm_element_value_int(existing_cib, XML_ATTR_NUMUPDATES, &this_updates);
crm_element_value_int(existing_cib, XML_ATTR_GENERATION_ADMIN, &this_admin_epoch);
if(this_epoch < 0) { this_epoch = 0; }
if(this_updates < 0) { this_updates = 0; }
if(this_admin_epoch < 0) { this_admin_epoch = 0; }
if(diff_del_admin_epoch == diff_add_admin_epoch
&& diff_del_epoch == diff_add_epoch
&& diff_del_updates == diff_add_updates) {
if(options & cib_force_diff) {
apply_diff = FALSE;
log_level = LOG_ERR;
reason = "+ and - versions in the diff did not change in global update";
crm_log_xml_warn(input, "Bad global update");
} else if(diff_add_admin_epoch == -1 && diff_add_epoch == -1 && diff_add_updates == -1) {
crm_err("Massaging diff versions");
diff_add_epoch = this_epoch;
diff_add_updates = this_updates + 1;
diff_add_admin_epoch = this_admin_epoch;
diff_del_epoch = this_epoch;
diff_del_updates = this_updates;
diff_del_admin_epoch = this_admin_epoch;
crm_log_xml_err(input, __FUNCTION__);
} else {
apply_diff = FALSE;
log_level = LOG_ERR;
reason = "+ and - versions in the diff did not change";
log_cib_diff(LOG_ERR, input, __FUNCTION__);
}
}
if(apply_diff && diff_del_admin_epoch > this_admin_epoch) {
result = cib_diff_resync;
apply_diff = FALSE;
log_level = LOG_INFO;
reason = "current \""XML_ATTR_GENERATION_ADMIN"\" is less than required";
} else if(apply_diff && diff_del_admin_epoch < this_admin_epoch) {
apply_diff = FALSE;
log_level = LOG_WARNING;
reason = "current \""XML_ATTR_GENERATION_ADMIN"\" is greater than required";
} else if(apply_diff && diff_del_epoch > this_epoch) {
result = cib_diff_resync;
apply_diff = FALSE;
log_level = LOG_INFO;
reason = "current \""XML_ATTR_GENERATION"\" is less than required";
} else if(apply_diff && diff_del_epoch < this_epoch) {
apply_diff = FALSE;
log_level = LOG_WARNING;
reason = "current \""XML_ATTR_GENERATION"\" is greater than required";
} else if(apply_diff && diff_del_updates > this_updates) {
result = cib_diff_resync;
apply_diff = FALSE;
log_level = LOG_INFO;
reason = "current \""XML_ATTR_NUMUPDATES"\" is less than required";
} else if(apply_diff && diff_del_updates < this_updates) {
apply_diff = FALSE;
log_level = LOG_WARNING;
reason = "current \""XML_ATTR_NUMUPDATES"\" is greater than required";
}
if(apply_diff) {
free_xml(*result_cib);
*result_cib = NULL;
if(apply_xml_diff(existing_cib, input, result_cib) == FALSE) {
log_level = LOG_NOTICE;
reason = "Failed application of an update diff";
if(options & cib_force_diff) {
result = cib_diff_resync;
}
}
}
if(reason != NULL) {
do_crm_log(
log_level,
"Diff %d.%d.%d -> %d.%d.%d not applied to %d.%d.%d: %s",
diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
diff_add_admin_epoch,diff_add_epoch,diff_add_updates,
this_admin_epoch,this_epoch,this_updates, reason);
if(result == cib_ok) {
result = cib_diff_failed;
}
} else if(apply_diff) {
crm_debug_2("Diff %d.%d.%d -> %d.%d.%d was applied to %d.%d.%d",
diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
diff_add_admin_epoch,diff_add_epoch,diff_add_updates,
this_admin_epoch,this_epoch,this_updates);
}
return result;
}
gboolean
apply_cib_diff(xmlNode *old, xmlNode *diff, xmlNode **new)
{
gboolean result = TRUE;
const char *value = NULL;
int this_updates = 0;
int this_epoch = 0;
int this_admin_epoch = 0;
int diff_add_updates = 0;
int diff_add_epoch = 0;
int diff_add_admin_epoch = 0;
int diff_del_updates = 0;
int diff_del_epoch = 0;
int diff_del_admin_epoch = 0;
CRM_CHECK(diff != NULL, return FALSE);
CRM_CHECK(old != NULL, return FALSE);
value = crm_element_value(old, XML_ATTR_GENERATION_ADMIN);
this_admin_epoch = crm_parse_int(value, "0");
crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION_ADMIN,
this_admin_epoch, value);
value = crm_element_value(old, XML_ATTR_GENERATION);
this_epoch = crm_parse_int(value, "0");
crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION, this_epoch, value);
value = crm_element_value(old, XML_ATTR_NUMUPDATES);
this_updates = crm_parse_int(value, "0");
crm_debug_3("%s=%d (%s)", XML_ATTR_NUMUPDATES, this_updates, value);
cib_diff_version_details(
diff,
&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
value = NULL;
if(result && diff_del_admin_epoch != this_admin_epoch) {
value = XML_ATTR_GENERATION_ADMIN;
result = FALSE;
crm_debug_3("%s=%d", value, diff_del_admin_epoch);
} else if(result && diff_del_epoch != this_epoch) {
value = XML_ATTR_GENERATION;
result = FALSE;
crm_debug_3("%s=%d", value, diff_del_epoch);
} else if(result && diff_del_updates != this_updates) {
value = XML_ATTR_NUMUPDATES;
result = FALSE;
crm_debug_3("%s=%d", value, diff_del_updates);
}
if(result) {
xmlNode *tmp = NULL;
xmlNode *diff_copy = copy_xml(diff);
tmp = find_xml_node(diff_copy, "diff-removed", TRUE);
if(tmp != NULL) {
xml_remove_prop(tmp, XML_ATTR_GENERATION_ADMIN);
xml_remove_prop(tmp, XML_ATTR_GENERATION);
xml_remove_prop(tmp, XML_ATTR_NUMUPDATES);
}
tmp = find_xml_node(diff_copy, "diff-added", TRUE);
if(tmp != NULL) {
xml_remove_prop(tmp, XML_ATTR_GENERATION_ADMIN);
xml_remove_prop(tmp, XML_ATTR_GENERATION);
xml_remove_prop(tmp, XML_ATTR_NUMUPDATES);
}
result = apply_xml_diff(old, diff_copy, new);
free_xml(diff_copy);
} else {
crm_err("target and diff %s values didnt match", value);
}
return result;
}
gboolean
cib_config_changed(xmlNode *diff)
{
gboolean config_changes = FALSE;
xmlXPathObject *xpathObj = NULL;
if(diff == NULL) {
goto done;
}
xpathObj = xpath_search(diff, "//"XML_CIB_TAG_CONFIGURATION);
if(xpathObj && xpathObj->nodesetval->nodeNr > 0) {
config_changes = TRUE;
goto done;
} else if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
xpathObj = xpath_search(diff, "//"XML_TAG_CIB);
if(xpathObj) {
int lpc = 0, max = xpathObj->nodesetval->nodeNr;
for(lpc = 0; lpc < max; lpc++) {
xmlNode *top = getXpathResult(xpathObj, lpc);
xml_prop_iter(top, name, value,
if(crm_str_eq(XML_ATTR_NUMUPDATES, name, TRUE) == FALSE) {
config_changes = TRUE;
goto done;
}
);
}
}
done:
if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
return config_changes;
}
xmlNode *
diff_cib_object(xmlNode *old_cib, xmlNode *new_cib, gboolean suppress)
{
xmlNode *dest = NULL;
xmlNode *src = NULL;
const char *name = NULL;
const char *value = NULL;
xmlNode *diff = diff_xml_object(old_cib, new_cib, suppress);
/* add complete version information */
src = old_cib;
dest = find_xml_node(diff, "diff-removed", FALSE);
if(src != NULL && dest != NULL) {
name = XML_ATTR_GENERATION_ADMIN;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_GENERATION;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_NUMUPDATES;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
}
src = new_cib;
dest = find_xml_node(diff, "diff-added", FALSE);
if(src != NULL && dest != NULL) {
name = XML_ATTR_GENERATION_ADMIN;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_GENERATION;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_NUMUPDATES;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
}
return diff;
}
enum cib_errors
cib_process_xpath(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
int lpc = 0;
int max = 0;
int rc = cib_ok;
gboolean is_query = safe_str_eq(op, CIB_OP_QUERY);
xmlXPathObjectPtr xpathObj = NULL;
crm_debug_2("Processing \"%s\" event", op);
if(is_query) {
xpathObj = xpath_search(existing_cib, section);
} else {
xpathObj = xpath_search(*result_cib, section);
}
if(xpathObj != NULL && xpathObj->nodesetval != NULL) {
max = xpathObj->nodesetval->nodeNr;
}
if(max < 1 && safe_str_eq(op, CIB_OP_DELETE)) {
crm_debug("%s was already removed", section);
} else if(max < 1) {
crm_debug("%s: %s does not exist", op, section);
rc = cib_NOTEXISTS;
} else if(is_query) {
if(max > 1) {
*answer = create_xml_node(NULL, "xpath-query");
}
}
for(lpc = 0; lpc < max; lpc++) {
xmlChar *path = NULL;
xmlNode *match = getXpathResult(xpathObj, lpc);
CRM_CHECK(match != NULL, goto out);
path = xmlGetNodePath(match);
- if(is_query == FALSE) {
- crm_info("Processing %s op for %s (%s)", op, section, path);
- }
+ crm_debug("Processing %s op for %s (%s)", op, section, path);
free(path);
if(safe_str_eq(op, CIB_OP_DELETE)) {
free_xml_from_parent(NULL, match);
break;
} else if(safe_str_eq(op, CIB_OP_MODIFY)) {
if(update_xml_child(match, input) == FALSE) {
rc = cib_NOTEXISTS;
} else {
rc = cib_ok;
if((options & cib_multiple) == 0) {
break;
}
}
} else if(safe_str_eq(op, CIB_OP_CREATE)) {
add_node_copy(match, input);
break;
} else if(safe_str_eq(op, CIB_OP_QUERY)) {
if(options & cib_no_children) {
const char *tag = TYPE(match);
*answer = create_xml_node(NULL, tag);
copy_in_properties(*answer, match);
break;
} else if(*answer) {
add_node_copy(*answer, match);
} else {
*answer = match;
}
} else if(safe_str_eq(op, CIB_OP_REPLACE)) {
xmlNode *parent = match->parent;
free_xml_from_parent(NULL, match);
if(input != NULL) {
add_node_copy(parent, input);
}
if((options & cib_multiple) == 0) {
break;
}
}
}
out:
if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
return rc;
}
/* remove this function */
gboolean
update_results(
xmlNode *failed, xmlNode *target, const char* operation, int return_code)
{
xmlNode *xml_node = NULL;
gboolean was_error = FALSE;
const char *error_msg = NULL;
if (return_code != cib_ok) {
error_msg = cib_error2string(return_code);
xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB);
was_error = TRUE;
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_OP, operation);
crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg);
crm_warn("Action %s failed: %s (cde=%d)",
operation, error_msg, return_code);
}
return was_error;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 3:21 AM (14 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009906
Default Alt Text
(38 KB)

Event Timeline