Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624493
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
30 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/cib/cibmessages.h b/cib/cibmessages.h
index dc595cfa41..73e12ab6c4 100644
--- a/cib/cibmessages.h
+++ b/cib/cibmessages.h
@@ -1,63 +1,67 @@
/*
* 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
*/
#ifndef CIB_MESSAGES__H
#define CIB_MESSAGES__H
#include <crm/cib_ops.h>
extern xmlNode *createCibRequest(
gboolean isLocal, const char *operation, const char *section,
const char *verbose, xmlNode *data);
extern 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);
extern 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);
extern 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);
extern 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);
extern 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);
+extern 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);
+
extern 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);
extern 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);
extern 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);
extern enum cib_errors cib_process_change(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer);
#endif
diff --git a/cib/common.c b/cib/common.c
index 0483290d24..849c233714 100644
--- a/cib/common.c
+++ b/cib/common.c
@@ -1,380 +1,380 @@
/*
* Copyright (C) 2008 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 <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <clplumbing/uids.h>
#include <clplumbing/cl_uuid.h>
#include <clplumbing/cl_malloc.h>
#include <clplumbing/Gmain_timeout.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <crm/common/cluster.h>
#include <crm/common/ctrl.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
#include <cibio.h>
#include <callbacks.h>
#include <cibmessages.h>
#include <cibprimatives.h>
#include "common.h"
extern gboolean cib_is_master;
extern const char* cib_root;
gboolean stand_alone = FALSE;
extern enum cib_errors cib_status;
extern gboolean can_write(int flags);
extern enum cib_errors cib_perform_command(
xmlNode *request, xmlNode **reply, xmlNode **cib_diff, gboolean privileged);
static xmlNode *
cib_prepare_common(xmlNode *root, const char *section)
{
xmlNode *data = NULL;
/* extract the CIB from the fragment */
if(root == NULL) {
return NULL;
} else if(safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT)
|| safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) {
data = find_xml_node(root, XML_TAG_CIB, TRUE);
if(data != NULL) {
crm_debug_3("Extracted CIB from %s", TYPE(root));
} else {
crm_log_xml_debug_4(root, "No CIB");
}
} else {
data = root;
}
/* grab the section specified for the command */
if(section != NULL
&& data != NULL
&& safe_str_eq(crm_element_name(data), XML_TAG_CIB)){
int rc = revision_check(data, the_cib, 0/* call_options */);
if(rc == cib_ok) {
data = get_object_root(section, data);
if(data != NULL) {
crm_debug_3("Extracted %s from CIB", section);
} else {
crm_log_xml_debug_4(root, "No Section");
}
} else {
crm_debug_2("Revision check failed");
}
}
crm_log_xml_debug_4(root, "cib:input");
return copy_xml(data);
}
static gboolean
verify_section(const char *section)
{
if(section == NULL) {
return TRUE;
} else if(safe_str_eq(section, XML_TAG_CIB)) {
return TRUE;
} else if(safe_str_eq(section, XML_CIB_TAG_STATUS)) {
return TRUE;
} else if(safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) {
return TRUE;
} else if(safe_str_eq(section, XML_CIB_TAG_NODES)) {
return TRUE;
} else if(safe_str_eq(section, XML_CIB_TAG_RESOURCES)) {
return TRUE;
} else if(safe_str_eq(section, XML_CIB_TAG_CONSTRAINTS)) {
return TRUE;
}
return FALSE;
}
static enum cib_errors
cib_prepare_none(xmlNode *request, xmlNode **data, const char **section)
{
*data = NULL;
*section = crm_element_value(request, F_CIB_SECTION);
if(verify_section(*section) == FALSE) {
return cib_bad_section;
}
return cib_ok;
}
static enum cib_errors
cib_prepare_data(xmlNode *request, xmlNode **data, const char **section)
{
xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
*section = crm_element_value(request, F_CIB_SECTION);
*data = cib_prepare_common(input_fragment, *section);
- crm_log_xml_debug(*data, "data");
+ /* crm_log_xml_debug(*data, "data"); */
if(verify_section(*section) == FALSE) {
return cib_bad_section;
}
return cib_ok;
}
static enum cib_errors
cib_prepare_sync(xmlNode *request, xmlNode **data, const char **section)
{
*section = crm_element_value(request, F_CIB_SECTION);
*data = NULL;
if(verify_section(*section) == FALSE) {
return cib_bad_section;
}
return cib_ok;
}
static enum cib_errors
cib_prepare_diff(xmlNode *request, xmlNode **data, const char **section)
{
xmlNode *input_fragment = NULL;
const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
*data = NULL;
*section = NULL;
if(crm_is_true(update)) {
input_fragment = get_message_xml(request,F_CIB_UPDATE_DIFF);
} else {
input_fragment = get_message_xml(request, F_CIB_CALLDATA);
}
CRM_CHECK(input_fragment != NULL,crm_log_xml(LOG_WARNING, "no input", request));
*data = cib_prepare_common(input_fragment, NULL);
return cib_ok;
}
static enum cib_errors
cib_cleanup_query(const char *op, xmlNode **data, xmlNode **output)
{
CRM_DEV_ASSERT(*data == NULL);
return cib_ok;
}
static enum cib_errors
cib_cleanup_data(const char *op, xmlNode **data, xmlNode **output)
{
free_xml(*output);
free_xml(*data);
return cib_ok;
}
static enum cib_errors
cib_cleanup_output(const char *op, xmlNode **data, xmlNode **output)
{
free_xml(*output);
return cib_ok;
}
static enum cib_errors
cib_cleanup_none(const char *op, xmlNode **data, xmlNode **output)
{
CRM_DEV_ASSERT(*data == NULL);
CRM_DEV_ASSERT(*output == NULL);
return cib_ok;
}
static enum cib_errors
cib_cleanup_sync(const char *op, xmlNode **data, xmlNode **output)
{
/* data is non-NULL but doesnt need to be free'd */
CRM_DEV_ASSERT(*data == NULL);
CRM_DEV_ASSERT(*output == NULL);
return cib_ok;
}
/*
typedef struct cib_operation_s
{
const char* operation;
gboolean modifies_cib;
gboolean needs_privileges;
gboolean needs_quorum;
enum cib_errors (*prepare)(xmlNode *, xmlNode**, const char **);
enum cib_errors (*cleanup)(xmlNode**, xmlNode**);
enum cib_errors (*fn)(
const char *, int, const char *,
xmlNode*, xmlNode*, xmlNode**, xmlNode**);
} cib_operation_t;
*/
/* technically bump does modify the cib...
* but we want to split the "bump" from the "sync"
*/
static cib_operation_t cib_server_ops[] = {
{NULL, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_default},
{CIB_OP_QUERY, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query, cib_process_query},
{CIB_OP_MODIFY, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_modify},
{CIB_OP_UPDATE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_change},
{CIB_OP_APPLY_DIFF,TRUE, TRUE, TRUE, cib_prepare_diff, cib_cleanup_data, cib_server_process_diff},
{CIB_OP_SLAVE, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
{CIB_OP_SLAVEALL, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
{CIB_OP_SYNC_ONE, FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_sync_one},
{CIB_OP_MASTER, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
{CIB_OP_ISMASTER, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite},
{CIB_OP_BUMP, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_bump},
- {CIB_OP_REPLACE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_replace},
+ {CIB_OP_REPLACE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_replace_svr},
{CIB_OP_CREATE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_change},
{CIB_OP_DELETE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_delete},
{CIB_OP_DELETE_ALT,TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_change},
{CIB_OP_SYNC, FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_sync},
{CRM_OP_QUIT, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_quit},
{CRM_OP_PING, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping},
{CIB_OP_ERASE, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_erase},
{CRM_OP_NOOP, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_default},
{"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_shutdown_req},
};
enum cib_errors
cib_get_operation_id(const char *op, int *operation)
{
int lpc = 0;
int max_msg_types = DIMOF(cib_server_ops);
for (lpc = 0; lpc < max_msg_types; lpc++) {
if (safe_str_eq(op, cib_server_ops[lpc].operation)) {
*operation = lpc;
return cib_ok;
}
}
crm_err("Operation %s is not valid", op);
*operation = -1;
return cib_operation;
}
xmlNode *
cib_msg_copy(xmlNode *msg, gboolean with_data)
{
int lpc = 0;
const char *field = NULL;
const char *value = NULL;
xmlNode *value_struct = NULL;
static const char *field_list[] = {
F_XML_TAGNAME ,
F_TYPE ,
F_CIB_CLIENTID ,
F_CIB_CALLOPTS ,
F_CIB_CALLID ,
F_CIB_OPERATION ,
F_CIB_ISREPLY ,
F_CIB_SECTION ,
F_CIB_HOST ,
F_CIB_RC ,
F_CIB_DELEGATED ,
F_CIB_OBJID ,
F_CIB_OBJTYPE ,
F_CIB_EXISTING ,
F_CIB_SEENCOUNT ,
F_CIB_TIMEOUT ,
F_CIB_CALLBACK_TOKEN ,
F_CIB_GLOBAL_UPDATE ,
F_CIB_CLIENTNAME ,
F_CIB_NOTIFY_TYPE ,
F_CIB_NOTIFY_ACTIVATE
};
static const char *data_list[] = {
F_CIB_CALLDATA ,
F_CIB_UPDATE ,
F_CIB_UPDATE_RESULT
};
xmlNode *copy = create_xml_node(NULL, "copy");
CRM_ASSERT(copy != NULL);
for(lpc = 0; lpc < DIMOF(field_list); lpc++) {
field = field_list[lpc];
value = crm_element_value(msg, field);
if(value != NULL) {
crm_xml_add(copy, field, value);
}
}
for(lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) {
field = data_list[lpc];
value_struct = get_message_xml(msg, field);
if(value_struct != NULL) {
add_message_xml(copy, field, value_struct);
}
}
return copy;
}
cib_op_t *cib_op_func(int call_type)
{
return &(cib_server_ops[call_type].fn);
}
gboolean cib_op_modifies(int call_type)
{
return cib_server_ops[call_type].modifies_cib;
}
int cib_op_can_run(
int call_type, int call_options, gboolean privileged, gboolean global_update)
{
int rc = cib_ok;
if(rc == cib_ok &&
cib_server_ops[call_type].needs_privileges
&& privileged == FALSE) {
/* abort */
return cib_not_authorized;
}
if(rc == cib_ok
&& stand_alone == FALSE
&& global_update == FALSE
&& (call_options & cib_quorum_override) == 0
&& cib_server_ops[call_type].needs_quorum) {
return cib_no_quorum;
}
return cib_ok;
}
int cib_op_prepare(
int call_type, xmlNode *request, xmlNode **input, const char **section)
{
return cib_server_ops[call_type].prepare(request, input, section);
}
int cib_op_cleanup(
int call_type, const char *op, xmlNode **input, xmlNode **output)
{
return cib_server_ops[call_type].cleanup(op, input, output);
}
diff --git a/cib/messages.c b/cib/messages.c
index 92ae7d5a2e..b996aac208 100644
--- a/cib/messages.c
+++ b/cib/messages.c
@@ -1,608 +1,622 @@
/*
* 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 <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <heartbeat.h>
#include <clplumbing/cl_log.h>
#include <time.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 <cibprimatives.h>
#include <callbacks.h>
#define MAX_DIFF_RETRY 5
#ifdef CIBPIPE
gboolean cib_is_master = TRUE;
#else
gboolean cib_is_master = FALSE;
#endif
gboolean syncd_once = FALSE;
xmlNode *the_cib = NULL;
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, int 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;
+}
+
enum cib_errors
cib_process_change(
const char *op, int options, const char *section, xmlNode *req, xmlNode *input,
xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
{
gboolean verbose = FALSE;
xmlNode *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));
if (strcasecmp(CIB_OP_CREATE, op) == 0) {
cib_update_op = CIB_UPDATE_OP_ADD;
} else if (strcasecmp(CIB_OP_UPDATE, op) == 0) {
cib_update_op = CIB_UPDATE_OP_MODIFY;
} else if (strcasecmp(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;
} else if(safe_str_eq(XML_TAG_CIB, section)) {
section = NULL;
}
if(input == NULL) {
crm_err("Cannot perform modification with no data");
return cib_NOOBJECT;
}
crm_validate_data(input);
crm_validate_data(*result_cib);
failed = create_xml_node(NULL, XML_TAG_FAILED);
/* make changes to a temp copy then activate */
if(section == NULL) {
int lpc = 0;
const char *type = NULL;
xmlNode *sub_input = NULL;
/* order is no longer important here */
const char *type_list[] = {
XML_CIB_TAG_NODES,
XML_CIB_TAG_CONSTRAINTS,
XML_CIB_TAG_RESOURCES,
XML_CIB_TAG_STATUS,
XML_CIB_TAG_CRMCONFIG
};
copy_in_properties(*result_cib, input);
for(lpc = 0; lpc < DIMOF(type_list); lpc++) {
type = type_list[lpc];
if(result == cib_ok) {
crm_debug_2("Processing section=%s", type);
sub_input = get_object_root(type, input);
if(sub_input) {
result = updateList(
*result_cib, sub_input, failed,
cib_update_op, type);
}
}
}
} else {
result = updateList(
*result_cib, input, failed, cib_update_op, section);
}
if (result != cib_ok || xml_has_children(failed)) {
if(result == cib_ok) {
result = cib_unknown;
}
crm_log_xml_err(failed, "CIB Update failures");
*answer = failed;
} else {
free_xml(failed);
}
return result;
}
#define cib_update_xml_macro(parent, xml_update) \
if(operation == CIB_UPDATE_OP_DELETE) { \
rc = delete_cib_object(parent, xml_update); \
update_results(failed, xml_update, operation, rc); \
\
} else if(operation == CIB_UPDATE_OP_MODIFY) { \
rc = update_cib_object(parent, xml_update); \
update_results(failed, xml_update, operation, rc); \
\
} else { \
rc = add_cib_object(parent, xml_update); \
update_results(failed, xml_update, operation, rc); \
} \
enum cib_errors
updateList(xmlNode *local_cib, xmlNode *xml_section, xmlNode *failed,
int operation, const char *section)
{
int rc = cib_ok;
xmlNode *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;
}
if(safe_str_eq(crm_element_name(xml_section), section)) {
xml_child_iter(xml_section, a_child,
rc = cib_ok;
cib_update_xml_macro(this_section, a_child);
);
} else {
cib_update_xml_macro(this_section, xml_section);
}
if(rc == cib_ok && xml_has_children(failed)) {
rc = cib_unknown;
}
return rc;
}
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;
}
static const char *
cib_op2string(enum cib_update_op operation)
{
const char *operation_msg = NULL;
switch(operation) {
case 0:
operation_msg = "none";
break;
case 1:
operation_msg = "add";
break;
case 2:
operation_msg = "modify";
break;
case 3:
operation_msg = "delete";
break;
case CIB_UPDATE_OP_MAX:
operation_msg = "invalid operation";
break;
}
if(operation_msg == NULL) {
crm_err("Unknown CIB operation %d", operation);
operation_msg = "<unknown operation>";
}
return operation_msg;
}
gboolean
update_results(
xmlNode *failed, xmlNode *target, int operation, int return_code)
{
gboolean was_error = FALSE;
const char *error_msg = NULL;
const char *operation_msg = NULL;
xmlNode *xml_node = NULL;
if (return_code != cib_ok) {
operation_msg = cib_op2string(operation);
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);
}
return was_error;
}
enum cib_errors
revision_check(xmlNode *cib_update, xmlNode *cib_copy, int flags)
{
int cmp = 0;
enum cib_errors rc = cib_ok;
char *new_revision = NULL;
const char *cur_revision = crm_element_value(
cib_copy, XML_ATTR_CIB_REVISION);
crm_validate_data(cib_update);
crm_validate_data(cib_copy);
if(crm_element_value(cib_update, XML_ATTR_CIB_REVISION) == NULL) {
return cib_ok;
}
new_revision = crm_element_value_copy(cib_update,XML_ATTR_CIB_REVISION);
cmp = compare_version(new_revision, CIB_FEATURE_SET);
if(cmp > 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", new_revision,CIB_FEATURE_SET);
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", new_revision,CIB_FEATURE_SET);
rc = cib_revision_unsupported;
}
} else if(cur_revision == NULL) {
crm_info("Updating CIB revision to %s", new_revision);
crm_xml_add(cib_copy, XML_ATTR_CIB_REVISION, new_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);
}
crm_free(new_revision);
return rc;
}
#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);
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
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:27 PM (12 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002650
Default Alt Text
(30 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment