diff --git a/crm/cib/messages.c b/crm/cib/messages.c index 34b5625991..0763932eed 100644 --- a/crm/cib/messages.c +++ b/crm/cib/messages.c @@ -1,931 +1,938 @@ -/* $Id: messages.c,v 1.53 2005/07/21 17:29:15 andrew Exp $ */ +/* $Id: messages.c,v 1.54 2005/09/02 12:39:31 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_DIFF_RETRY 5 extern const char *cib_our_uname; extern gboolean syncd_once; enum cib_errors revision_check(crm_data_t *cib_update, crm_data_t *cib_copy, int flags); int get_revision(crm_data_t *xml_obj, int cur_revision); enum cib_errors updateList( crm_data_t *local_cib, crm_data_t *update_command, crm_data_t *failed, int operation, const char *section); crm_data_t *createCibFragmentAnswer(const char *section, crm_data_t *failed); enum cib_errors replace_section( const char *section, crm_data_t *tmpCib, crm_data_t *command); gboolean check_generation(crm_data_t *newCib, crm_data_t *oldCib); gboolean update_results( crm_data_t *failed, crm_data_t *target, int operation, int return_code); enum cib_errors cib_update_counter( crm_data_t *xml_obj, const char *field, gboolean reset); enum cib_errors sync_our_cib(HA_Message *request, gboolean all); enum cib_errors cib_process_default( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event", op); if(answer != NULL) { *answer = NULL; } if(op == NULL) { result = cib_operation; crm_err("No operation specified"); } else if(strcmp(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, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **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, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { 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; } enum cib_errors cib_process_ping( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event", op); if(answer != NULL) { *answer = createPingAnswerFragment(CRM_SYSTEM_CIB, "ok"); } return result; } enum cib_errors cib_process_query( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { crm_data_t *obj_root = NULL; enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); if(answer != NULL) { *answer = NULL; } else { return cib_output_ptr; } if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } *answer = create_xml_node(NULL, XML_TAG_FRAGMENT); /* crm_xml_add(*answer, XML_ATTR_SECTION, section); */ obj_root = get_object_root(section, existing_cib); if(obj_root == NULL) { result = cib_NOTEXISTS; } else if(obj_root == existing_cib) { crm_xml_add(obj_root, "origin", cib_our_uname); add_node_copy(*answer, obj_root); } else { crm_data_t *cib = createEmptyCib(); crm_data_t *query_obj_root = get_object_root(section, cib); copy_in_properties(cib, existing_cib); crm_xml_add(cib, "origin", cib_our_uname); xml_child_iter( obj_root, an_obj, NULL, add_node_copy(query_obj_root, an_obj); ); add_node_copy(*answer, cib); free_xml(cib); } 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, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event", op); if(answer != NULL) { *answer = NULL; } *result_cib = createEmptyCib(); result = revision_check(existing_cib, *result_cib, options); copy_in_properties(*result_cib, existing_cib); if(result == cib_ok && !(options & cib_inhibit_bcast)) { cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, TRUE); } if(answer != NULL) { *answer = createCibFragmentAnswer(NULL, NULL); } return result; } enum cib_errors cib_process_bump( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event for epoch=%s", op, crm_str(crm_element_value(the_cib, XML_ATTR_GENERATION))); if(answer != NULL) { *answer = NULL; } *result_cib = copy_xml(the_cib); cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE); cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, FALSE); if(answer != NULL) { *answer = createCibFragmentAnswer(NULL, NULL); } return result; } extern ll_cluster_t *hb_conn; extern HA_Message *cib_msg_copy(const HA_Message *msg, gboolean with_data); enum cib_errors cib_process_sync( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { return sync_our_cib(input, TRUE); } enum cib_errors cib_process_sync_one( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { return sync_our_cib(input, FALSE); } enum cib_errors cib_update_counter(crm_data_t *xml_obj, const char *field, gboolean reset) { char *new_value = NULL; char *old_value = NULL; int int_value = -1; /* modify the timestamp */ set_node_tstamp(xml_obj); 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*(sizeof(char))); 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; } int sync_in_progress = 0; enum cib_errors cib_process_diff( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { unsigned int log_level = LOG_DEBUG; const char *value = NULL; const char *reason = NULL; gboolean apply_diff = TRUE; gboolean do_resync = FALSE; 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); if(cib_is_master) { /* the master is never waiting for a resync */ sync_in_progress = 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); 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) { 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; } value = crm_element_value(existing_cib, XML_ATTR_GENERATION); this_epoch = atoi(value?value:"0"); value = crm_element_value(existing_cib, XML_ATTR_NUMUPDATES); this_updates = atoi(value?value:"0"); value = crm_element_value(existing_cib, XML_ATTR_GENERATION_ADMIN); this_admin_epoch = atoi(value?value:"0"); if(diff_del_admin_epoch == diff_add_admin_epoch && diff_del_epoch == diff_add_epoch && diff_del_updates == diff_add_updates) { 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) { do_resync = TRUE; 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"; } if(apply_diff && diff_del_epoch > this_epoch) { do_resync = TRUE; 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"; } if(apply_diff && diff_del_updates > this_updates) { do_resync = TRUE; 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 && apply_cib_diff(existing_cib, input, result_cib) == FALSE) { log_level = LOG_WARNING; reason = "Failed application of an update diff"; if(options & cib_force_diff && cib_is_master == FALSE) { log_level = LOG_INFO; reason = "Failed application of a global update. Requesting full refresh."; do_resync = TRUE; } else if(options & cib_force_diff) { reason = "Failed application of a global update. Not requesting full refresh."; } } if(reason != NULL) { crm_log_maybe( 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); result = cib_diff_failed; } else if(apply_diff) { crm_debug("Diff %d.%d.%d -> %d.%d.%d was applied", diff_del_admin_epoch,diff_del_epoch,diff_del_updates, diff_add_admin_epoch,diff_add_epoch,diff_add_updates); } if(do_resync && cib_is_master == FALSE) { HA_Message *sync_me = ha_msg_new(3); free_xml(*result_cib); *result_cib = NULL; result = cib_diff_resync; crm_info("Requesting re-sync from peer: %s", reason); sync_in_progress++; ha_msg_add(sync_me, F_TYPE, "cib"); ha_msg_add(sync_me, F_CIB_OPERATION, CIB_OP_SYNC_ONE); ha_msg_add(sync_me, F_CIB_DELEGATED, cib_our_uname); if(send_ha_message(hb_conn, sync_me, NULL, FALSE) == FALSE) { result = cib_not_connected; } ha_msg_del(sync_me); } else if(do_resync) { crm_err("Not resyncing in master mode"); } return result; } enum cib_errors cib_process_replace( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { gboolean verbose = FALSE; enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); if(answer != NULL) { *answer = NULL; } if (options & cib_verbose) { verbose = TRUE; } if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } if (input == NULL) { result = cib_NOOBJECT; } else if(section == NULL) { 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; } sync_in_progress = 0; *result_cib = copy_xml(input); } else { *result_cib = copy_xml(existing_cib); result = replace_section(section, *result_cib, input); } if(result == cib_ok && section != NULL) { cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, FALSE); } if (answer != NULL && (verbose || result != cib_ok)) { *answer = createCibFragmentAnswer(section, NULL); } return result; } enum cib_errors cib_process_delete( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { crm_debug_2("Processing \"%s\" event", op); if(input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } *result_cib = copy_xml(existing_cib); crm_validate_data(input); crm_validate_data(*result_cib); if(delete_xml_child(NULL, *result_cib, input) == FALSE) { return cib_NOTEXISTS; } cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, FALSE); return cib_ok; } enum cib_errors cib_process_modify( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { gboolean verbose = FALSE; crm_data_t *failed = NULL; enum cib_errors result = cib_ok; int cib_update_op = CIB_UPDATE_OP_NONE; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); failed = create_xml_node(NULL, XML_TAG_FAILED); if (strcmp(CIB_OP_CREATE, op) == 0) { cib_update_op = CIB_UPDATE_OP_ADD; } else if (strcmp(CIB_OP_UPDATE, op) == 0) { cib_update_op = CIB_UPDATE_OP_MODIFY; } else if (strcmp(CIB_OP_DELETE_ALT, op) == 0) { cib_update_op = CIB_UPDATE_OP_DELETE; } else { crm_err("Incorrect request handler invoked for \"%s\" op", crm_str(op)); return cib_operation; } result = cib_ok; if (options & cib_verbose) { verbose = TRUE; } if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } if(input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } *result_cib = copy_xml(existing_cib); crm_validate_data(input); crm_validate_data(*result_cib); /* make changes to a temp copy then activate */ if(section == NULL) { crm_data_t *sub_input = NULL; copy_in_properties(*result_cib, input); /* order is no longer important here */ if(result == cib_ok) { sub_input = get_object_root(XML_CIB_TAG_NODES, input); result = updateList( *result_cib, sub_input, failed, cib_update_op, XML_CIB_TAG_NODES); } if(result == cib_ok) { sub_input = get_object_root(XML_CIB_TAG_NODES, input); result = updateList( *result_cib, sub_input, failed, cib_update_op, XML_CIB_TAG_RESOURCES); } if(result == cib_ok) { sub_input = get_object_root(XML_CIB_TAG_NODES, input); result = updateList( *result_cib, sub_input, failed, cib_update_op, XML_CIB_TAG_CONSTRAINTS); } if(result == cib_ok) { sub_input = get_object_root(XML_CIB_TAG_NODES, input); result = updateList( *result_cib, sub_input, failed, cib_update_op, XML_CIB_TAG_STATUS); } } else { result = updateList( *result_cib, input, failed, cib_update_op, section); } if(result == cib_ok && !(options & cib_inhibit_bcast)) { cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, FALSE); } if (result != cib_ok || xml_has_children(failed)) { if(result == cib_ok) { result = cib_unknown; } crm_log_xml_err(failed, "CIB Update failures"); } if (verbose || xml_has_children(failed) || result != cib_ok) { *answer = createCibFragmentAnswer(section, failed); } free_xml(failed); return result; } enum cib_errors replace_section( const char *section, crm_data_t *tmpCib, crm_data_t *new_section) { crm_data_t *old_section = NULL; /* find the old and new versions of the section */ old_section = get_object_root(section, tmpCib); if(old_section == NULL) { crm_err("The CIB is corrupt, cannot replace missing section %s", section); return cib_NOSECTION; } else if(new_section == NULL) { crm_err("The CIB is corrupt, cannot set section %s to nothing", section); return cib_NOSECTION; } xml_child_iter( old_section, a_child, NULL, free_xml_from_parent(old_section, a_child); ); copy_in_properties(old_section, new_section); xml_child_iter( new_section, a_child, NULL, add_node_copy(old_section, a_child); ); return cib_ok; } enum cib_errors updateList(crm_data_t *local_cib, crm_data_t *xml_section, crm_data_t *failed, int operation, const char *section) { int rc = cib_ok; crm_data_t *this_section = get_object_root(section, local_cib); if (section == NULL || xml_section == NULL) { crm_err("Section %s not found in message." " CIB update is corrupt, ignoring.", crm_str(section)); return cib_NOSECTION; } if((CIB_UPDATE_OP_NONE > operation) || (operation > CIB_UPDATE_OP_MAX)){ crm_err("Invalid operation on section %s", crm_str(section)); return cib_operation; } set_node_tstamp(this_section); xml_child_iter( xml_section, a_child, NULL, rc = cib_ok; if(operation == CIB_UPDATE_OP_DELETE) { rc = delete_cib_object(this_section, a_child); update_results(failed, a_child, operation, rc); } else if(operation == CIB_UPDATE_OP_MODIFY) { rc = update_cib_object(this_section, a_child); update_results(failed, a_child, operation, rc); } else { rc = add_cib_object(this_section, a_child); update_results(failed, a_child, operation, rc); } ); if(rc == cib_ok && xml_has_children(failed)) { rc = cib_unknown; } return rc; } crm_data_t* createCibFragmentAnswer(const char *section, crm_data_t *failed) { crm_data_t *cib = NULL; crm_data_t *fragment = NULL; fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); if (section == NULL || strlen(section) == 0 || strcmp(XML_CIB_TAG_SECTION_ALL, section) == 0) { cib = get_the_CIB(); if(cib != NULL) { add_node_copy(fragment, get_the_CIB()); } } else { crm_data_t *obj_root = get_object_root(section, get_the_CIB()); if(obj_root != NULL) { cib = create_xml_node(fragment, XML_TAG_CIB); add_node_copy(cib, obj_root); copy_in_properties(cib, get_the_CIB()); } } if (failed != NULL && xml_has_children(failed)) { add_node_copy(fragment, failed); } crm_xml_add(fragment, XML_ATTR_SECTION, section); crm_xml_add(fragment, "generated_on", cib_our_uname); return fragment; } gboolean check_generation(crm_data_t *newCib, crm_data_t *oldCib) { if(cib_compare_generation(newCib, oldCib) >= 0) { return TRUE; } crm_warn("Generation from update is older than the existing one"); return FALSE; } gboolean update_results( crm_data_t *failed, crm_data_t *target, int operation, int return_code) { gboolean was_error = FALSE; const char *error_msg = NULL; const char *operation_msg = NULL; crm_data_t *xml_node = NULL; operation_msg = cib_op2string(operation); 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_msg); crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg); crm_warn("Action %s failed: %s (cde=%d)", operation_msg, error_msg, return_code); } else { crm_debug_3("CIB %s passed", operation_msg); } return was_error; } enum cib_errors revision_check(crm_data_t *cib_update, crm_data_t *cib_copy, int flags) { enum cib_errors rc = cib_ok; char *revision = crm_element_value_copy( cib_update, XML_ATTR_CIB_REVISION); const char *cur_revision = crm_element_value( cib_copy, XML_ATTR_CIB_REVISION); crm_validate_data(cib_update); crm_validate_data(cib_copy); if(revision == NULL) { return cib_ok; } else if(cur_revision == NULL || strcmp(revision, cur_revision) > 0) { crm_info("Updating CIB revision to %s", revision); crm_xml_add( cib_copy, XML_ATTR_CIB_REVISION, revision); } else { /* make sure we end up with the right value in the end */ crm_xml_add( cib_update, XML_ATTR_CIB_REVISION, cur_revision); } if(strcmp(revision, cib_feature_revision_s) > 0) { CRM_DEV_ASSERT(cib_is_master == FALSE); CRM_DEV_ASSERT((flags & cib_scope_local) == 0); if(cib_is_master) { crm_err("Update uses an unsupported tag/feature:" " %s vs %s", revision, cib_feature_revision_s); rc = cib_revision_unsupported; } else if(flags & cib_scope_local) { /* an admin has forced a local change using a tag we * dont understand... ERROR */ crm_err("Local update uses an unsupported tag/feature:" " %s vs %s", revision, cib_feature_revision_s); rc = cib_revision_unsupported; } } crm_free(revision); return rc; } enum cib_errors sync_our_cib(HA_Message *request, gboolean all) { enum cib_errors result = cib_ok; const char *host = cl_get_string(request, F_ORIG); const char *op = cl_get_string(request, F_CIB_OPERATION); crm_data_t *sync_data = create_cib_fragment(the_cib, NULL); HA_Message *replace_request = cib_msg_copy(request, FALSE); CRM_DEV_ASSERT(sync_data != NULL); CRM_DEV_ASSERT(replace_request != NULL); crm_info("Syncing CIB to %s", all?"all peers":host); if(all == FALSE && host == NULL) { crm_log_message(LOG_ERR, request); } - if(all == FALSE && host != NULL) { + /* 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) { ha_msg_add(replace_request, F_CIB_ISREPLY, host); } ha_msg_mod(replace_request, F_CIB_OPERATION, CIB_OP_REPLACE); ha_msg_add(replace_request, "original_"F_CIB_OPERATION, op); ha_msg_add(replace_request, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE); ha_msg_addstruct(replace_request, F_CIB_CALLDATA, sync_data); if(send_ha_message(hb_conn, replace_request, all?NULL:host, FALSE) == FALSE) { result = cib_not_connected; } ha_msg_del(replace_request); free_xml(sync_data); return result; }