diff --git a/crm/cib/Makefile.am b/crm/cib/Makefile.am index 5e81b2cb5a..dd1ef02c4e 100644 --- a/crm/cib/Makefile.am +++ b/crm/cib/Makefile.am @@ -1,78 +1,72 @@ # # 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 # of the License, or (at your option) any later version. # # This program 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 program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in - - INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_builddir)/libltdl -I$(top_srcdir)/libltdl \ -I$(top_builddir)/linux-ha -I$(top_srcdir)/linux-ha \ -I$(top_builddir) -I$(top_srcdir) hadir = $(sysconfdir)/ha.d halibdir = $(libdir)/@HB_PKG@ commmoddir = $(halibdir)/modules/comm havarlibdir = $(localstatedir)/lib/@HB_PKG@ PIDFILE = $(localstatedir)/run/crmd.pid XML_FLAGS = `xml2-config --cflags` XML_LIBS = `xml2-config --libs` # sockets with path crmdir = $(havarlibdir)/crm apigid = @HA_APIGID@ crmuid = @HA_CCMUID@ crmreqsocket = $(havarlibdir)/api/crm.req crmressocket = $(havarlibdir)/api/crm.rsp COMMONLIBS = $(CRM_DEBUG_LIBS) \ $(top_builddir)/lib/clplumbing/libplumb.la \ $(top_builddir)/$(CRM_DIR)/common/libcrmcommon.la \ $(top_builddir)/lib/apphb/libapphb.la \ $(top_builddir)/lib/hbclient/libhbclient.la \ + $(top_builddir)/lib/crm/cib/libcib.la \ $(GLIBLIB) \ $(LIBRT) LIBRT = @LIBRT@ AM_CFLAGS = @CFLAGS@ -DPIDFILE='"$(PIDFILE)"' $(CRM_DEBUG_FLAGS) -## libraries -lib_LTLIBRARIES = libcib.la - ## binary progs halib_PROGRAMS = cib ## SOURCES #noinst_HEADERS = config.h control.h crmd.h -noinst_HEADERS = cibio.h cibmessages.h cibprimatives.h - -libcib_la_SOURCES = io.c primatives.c messages.c cib.c -libcib_la_LDFLAGS = -version-info 0:0:0 -libcib_la_CFLAGS = -I$(top_builddir) +noinst_HEADERS = cibio.h cibmessages.h cibprimatives.h notify.h \ + callbacks.h -cib_SOURCES = main.c +cib_SOURCES = io.c primatives.c messages.c cib.c notify.c \ + callbacks.c main.c cib_CFLAGS = $(XML_FLAGS) -DHA_VARLIBDIR='"@HA_VARLIBDIR@"' cib_LDFLAGS = $(XML_LIBS) -cib_LDADD = $(COMMONLIBS) libcib.la +cib_LDADD = $(COMMONLIBS) clean-generic: rm -f *.log *.debug *.xml *~ install-exec-local: uninstall-local: diff --git a/crm/cib/callbacks.c b/crm/cib/callbacks.c new file mode 100644 index 0000000000..a5f04592f3 --- /dev/null +++ b/crm/cib/callbacks.c @@ -0,0 +1,720 @@ +/* $Id: callbacks.c,v 1.1 2004/12/05 16:14:07 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 + + +int next_client_id = 0; +gboolean cib_is_master = FALSE; +GHashTable *client_list = NULL; +extern const char *cib_our_uname; +extern ll_cluster_t *hb_conn; +extern FILE *msg_cib_strm; + +cib_operation_t cib_server_ops[] = { + {NULL, FALSE, FALSE, FALSE, FALSE, cib_process_default}, + {CRM_OP_NOOP, FALSE, FALSE, FALSE, FALSE, cib_process_default}, + {CRM_OP_RETRIVE_CIB, FALSE, FALSE, FALSE, FALSE, cib_process_query}, + {CRM_OP_CIB_SLAVE, FALSE, TRUE, FALSE, FALSE, cib_process_readwrite}, + {CRM_OP_CIB_MASTER, FALSE, TRUE, FALSE, FALSE, cib_process_readwrite}, + {CRM_OP_CIB_BUMP, TRUE, TRUE, TRUE, FALSE, cib_process_bump}, + {CRM_OP_CIB_REPLACE, TRUE, TRUE, TRUE, TRUE, cib_process_replace}, + {CRM_OP_CIB_CREATE, TRUE, TRUE, TRUE, TRUE, cib_process_modify}, + {CRM_OP_CIB_UPDATE, TRUE, TRUE, TRUE, TRUE, cib_process_modify}, + {CRM_OP_JOINACK, TRUE, TRUE, TRUE, TRUE, cib_process_modify}, + {CRM_OP_SHUTDOWN_REQ,TRUE, TRUE, TRUE, TRUE, cib_process_modify}, + {CRM_OP_CIB_DELETE, TRUE, TRUE, TRUE, TRUE, cib_process_modify}, + {CRM_OP_CIB_QUERY, FALSE, FALSE, TRUE, FALSE, cib_process_query}, + {CRM_OP_QUIT, FALSE, TRUE, FALSE, FALSE, cib_process_quit}, + {CRM_OP_PING, FALSE, FALSE, FALSE, FALSE, cib_process_ping}, + {CRM_OP_CIB_ERASE, TRUE, TRUE, TRUE, FALSE, cib_process_erase} +}; + +int send_via_callback_channel(struct ha_msg *msg, const char *token); + +enum cib_errors cib_process_command( + const struct ha_msg *request, struct ha_msg **reply, gboolean privileged); + +gboolean cib_common_callback( + IPC_Channel *channel, gpointer user_data, gboolean privileged); + +enum cib_errors cib_get_operation_id(const struct ha_msg* msg, int *operation); + +gboolean cib_process_disconnect(IPC_Channel *channel, cib_client_t *cib_client); + +gboolean +cib_client_connect(IPC_Channel *channel, gpointer user_data) +{ + gboolean auth_failed = FALSE; + gboolean can_connect = TRUE; + gboolean (*client_callback)(IPC_Channel *channel, gpointer user_data) = NULL; + + cib_client_t *new_client = NULL; + crm_debug("Connecting channel"); + + if (channel == NULL) { + crm_err("Channel was NULL"); + can_connect = FALSE; + + } else if (channel->ch_status == IPC_DISCONNECT) { + crm_err("Channel was disconnected"); + can_connect = FALSE; + + } else if(user_data == NULL) { + crm_err("user_data must contain channel name"); + can_connect = FALSE; + + } else { + crm_malloc(new_client, sizeof(crmd_client_t)); + new_client->id = NULL; + new_client->callback_id = NULL; + new_client->source = NULL; + new_client->channel = channel; + new_client->channel_name = user_data; + + client_callback = NULL; + + /* choose callback and do auth based on channel_name */ + if(safe_str_eq(new_client->channel_name, "cib_callback")) { + client_callback = cib_null_callback; + + } else { + uuid_t client_id; + + uuid_generate(client_id); + crm_malloc(new_client->id, sizeof(char)*36); + uuid_unparse(client_id, new_client->id); + new_client->id[35] = EOS; + + uuid_generate(client_id); + crm_malloc(new_client->callback_id, sizeof(char)*30); + uuid_unparse(client_id, new_client->callback_id); + new_client->callback_id[35] = EOS; + + client_callback = cib_ro_callback; + if(safe_str_eq(new_client->channel_name, "cib_rw")) { + client_callback = cib_rw_callback; + } + } + } + + if(auth_failed) { + crm_err("Connection to %s channel failed authentication", + (char *)user_data); + can_connect = FALSE; + } + + if(can_connect == FALSE) { + if(new_client) { + crm_free(new_client->id); + crm_free(new_client->callback_id); + } + crm_free(new_client); + return FALSE; + } + + + channel->ops->set_recv_qlen(channel, 100); + channel->ops->set_send_qlen(channel, 100); + + if(client_callback != NULL) { + new_client->source = G_main_add_IPC_Channel( + G_PRIORITY_LOW, channel, FALSE, client_callback, + new_client, default_ipc_connection_destroy); + } + if(client_callback != cib_null_callback) { + /* send msg to client with uuid to use when signing up for + * callback channel + */ + + struct ha_msg *reg_msg = ha_msg_new(3); + ha_msg_add(reg_msg, F_CIB_OPERATION, CRM_OP_REGISTER); + ha_msg_add(reg_msg, F_CIB_CLIENTID, new_client->id); + ha_msg_add( + reg_msg, F_CIB_CALLBACK_TOKEN, new_client->callback_id); + + msg2ipcchan(reg_msg, channel); + ha_msg_del(reg_msg); + + /* make sure we can find ourselves later for sync calls + * redirected to the master instance + */ + g_hash_table_insert(client_list, new_client->id, new_client); + } + + crm_info("Channel %s connected for client %s", + new_client->channel_name, new_client->id); + + return TRUE; +} + +gboolean +cib_rw_callback(IPC_Channel *channel, gpointer user_data) +{ + return cib_common_callback(channel, user_data, TRUE); +} + +gboolean +cib_ro_callback(IPC_Channel *channel, gpointer user_data) +{ + return cib_common_callback(channel, user_data, FALSE); +} + +gboolean +cib_null_callback(IPC_Channel *channel, gpointer user_data) +{ + struct ha_msg *op_request = NULL; + cib_client_t *cib_client = user_data; + cib_client_t *hash_client = NULL; + const char *type = NULL; + const char *uuid_ticket = NULL; + + if(cib_client == NULL) { + crm_err("Discarding IPC message from unknown source" + " on callback channel."); + return FALSE; + } + + while(channel->ops->is_message_pending(channel)) { + if (channel->ch_status == IPC_DISCONNECT) { + /* The message which was pending for us is that + * the IPC status is now IPC_DISCONNECT + */ + break; + } + op_request = msgfromIPC_noauth(channel); + + type = cl_get_string(op_request, F_CIB_OPERATION); + if(safe_str_neq(type, CRM_OP_REGISTER) ) { + crm_warn("Discarding IPC message from %s on callback channel", + cib_client->id); + ha_msg_del(op_request); + continue; + } + + uuid_ticket = cl_get_string(op_request, F_CIB_CALLBACK_TOKEN); + hash_client = g_hash_table_lookup(client_list, uuid_ticket); + + if(hash_client != NULL) { + crm_err("Duplicate registration request... disconnecting"); + ha_msg_del(op_request); + return FALSE; + } + + + cib_client->id = crm_strdup(uuid_ticket); + g_hash_table_insert(client_list, cib_client->id, cib_client); + crm_info("Registered %s on %s channel", + cib_client->id, cib_client->channel_name); + + ha_msg_del(op_request); + + op_request = ha_msg_new(2); + ha_msg_add(op_request, F_CIB_OPERATION, CRM_OP_REGISTER); + ha_msg_add(op_request, F_CIB_CLIENTID, cib_client->id); + + msg2ipcchan(op_request, channel); + ha_msg_del(op_request); + + } + return cib_process_disconnect(channel, cib_client); +} + +gboolean +cib_common_callback( + IPC_Channel *channel, gpointer user_data, gboolean privileged) +{ + int rc = cib_ok; + int lpc = 0; + int call_type = 0; + int call_options = 0; + + const char *op = NULL; + + struct ha_msg *op_request = NULL; + struct ha_msg *op_reply = NULL; + + cib_client_t *cib_client = user_data; + + if(cib_client == NULL) { + crm_err("Receieved call from unknown source. Discarding."); + return FALSE; + } + + crm_verbose("Callback for %s on %s channel", + cib_client->id, cib_client->channel_name); + + while(channel->ops->is_message_pending(channel)) { + if (channel->ch_status == IPC_DISCONNECT) { + /* The message which was pending for us is that + * the IPC status is now IPC_DISCONNECT */ + break; + } + op_request = msgfromIPC(channel); + if (op_request == NULL) { + perror("Receive failure:"); + break; + } + + crm_verbose("Processing IPC message from %s on %s channel", + cib_client->id, cib_client->channel_name); + cl_log_message(op_request); + + lpc++; + + if(ha_msg_add(op_request, F_CIB_CLIENTID, cib_client->id) != HA_OK) { + crm_err("Couldnt add F_CIB_CLIENTID to message"); + rc = cib_msg_field_add; + } + + if(rc == cib_ok) { + crm_trace("Checking call options"); + cl_get_int(op_request, F_CIB_CALLOPTS, &call_options); + crm_trace("Call options: %.8lx", (long)call_options); + + crm_trace("Retrieving command"); + op = cl_get_string(op_request, F_CIB_OPERATION); + crm_trace("Calculating command offset"); + rc = cib_get_operation_id(op_request, &call_type); + } + + if(rc == cib_ok + && cib_server_ops[call_type].needs_privileges + && privileged == FALSE) { + rc = cib_not_authorized; + } + + if(rc != cib_ok) { + /* construct error reply */ + crm_err("Pre-processing of command failed: %s", + cib_error2string(rc)); + + } else if( !(call_options & cib_scope_local) + && cib_is_master == FALSE) { + /* send via HA to other nodes */ + crm_info("Forwarding %s op to master instance", op); + hb_conn->llc_ops->sendclustermsg(hb_conn, op_request); + ha_msg_del(op_request); + continue; + + } else { + crm_info("Processing %s op locally", op); + cl_log_message(op_request); + rc = cib_process_command( + op_request, &op_reply, privileged); + } + + if(call_options & cib_sync_call) { + crm_info("Sending sync reply to %s op", op); + if(msg2ipcchan(op_reply, channel) != HA_OK) { + rc = cib_reply_failed; + } + + } else { + /* send reply via client's callback channel */ + crm_info("Sending async reply to %s op", op); + rc = send_via_callback_channel( + op_reply, cib_client->callback_id); + } + + if(rc == cib_ok + && cib_server_ops[call_type].modifies_cib + && !(call_options & cib_scope_local)) { + /* send via HA to other nodes */ + crm_info("Forwarding %s op to all instances", op); + hb_conn->llc_ops->sendclustermsg(hb_conn, op_request); + + } else { + if(call_options & cib_scope_local ) { + crm_debug("Request not broadcast : local scope"); + } + if(cib_server_ops[call_type].modifies_cib == FALSE) { + crm_debug("Request not broadcast : R/O call"); + } + if(rc != cib_ok) { + crm_debug("Request not broadcast : call failed : %s", + cib_error2string(rc)); + } + } + + ha_msg_del(op_request); + ha_msg_del(op_reply); + } + + crm_verbose("Processed %d messages", lpc); + + return cib_process_disconnect(channel, cib_client); +} + +enum cib_errors +cib_process_command(const struct ha_msg *request, struct ha_msg **reply, + gboolean privileged) +{ + xmlNodePtr input = NULL; + const char *input_s = NULL; + + char *output_s = NULL; + xmlNodePtr output = NULL; + + int call_type = 0; + int call_options = 0; + enum cib_errors rc = cib_ok; + + const char *op = NULL; + const char *call_id = NULL; + const char *section = NULL; + + /* Start processing the request... */ + op = cl_get_string(request, F_CIB_OPERATION); + call_id = cl_get_string(request, F_CIB_CALLID); + cl_get_int(request, F_CIB_CALLOPTS, &call_options); + + crm_trace("Processing call id: %s", call_id); + + rc = cib_get_operation_id(request, &call_type); + + if(rc == cib_ok && + cib_server_ops[call_type].needs_privileges + && privileged == FALSE) { + /* abort */ + rc = cib_not_authorized; + } + + if(rc == cib_ok && cib_server_ops[call_type].needs_section) { + crm_trace("Unpacking section"); + section = cl_get_string(request, F_CIB_SECTION); + } + + if(rc == cib_ok && cib_server_ops[call_type].needs_data) { + crm_trace("Unpacking data in %s", F_CIB_CALLDATA); + input_s = cl_get_string(request, F_CIB_CALLDATA); + if(input_s != NULL) { + crm_trace("Converting to xmlNodePtr"); + input = string2xml(input_s); + if(input == NULL) { + crm_err("Invalid XML input"); + rc = CIBRES_CORRUPT; + } + } + } + + if(rc == cib_ok) { +#ifdef MSG_LOG + if(msg_cib_strm == NULL) { + msg_cib_strm = fopen(DEVEL_DIR"/cib.log", "w"); + } + fprintf(msg_cib_strm, "\n====================\n"); + fprintf(msg_cib_strm, "[Input %s]\t%s\n", op, + dump_xml_formatted(input)); + fflush(msg_cib_strm); +#endif + + rc = cib_server_ops[call_type].fn( + op, call_options, section, input, &output); + +#ifdef MSG_LOG + fprintf(msg_cib_strm, "[Reply (%s:%s)]\t%s\n", + op, cib_error2string(rc), + dump_xml_formatted(output)); + fflush(msg_cib_strm); +#endif + } + + if(call_options & cib_discard_reply || reply == NULL) { + if(reply) *reply = NULL; + return rc; + } + + /* make the basic reply */ + *reply = ha_msg_new(8); + ha_msg_add(*reply, F_TYPE, "cib"); + ha_msg_add(*reply, F_CIB_OPERATION, op); + ha_msg_add(*reply, F_CIB_CALLID, call_id); + + { + char *tmp = crm_itoa(rc); + ha_msg_add(*reply, F_CIB_RC, tmp); + crm_free(tmp); + } + { + const char *tmp = cl_get_string(request, F_CIB_CLIENTID); + ha_msg_add(*reply, F_CIB_CLIENTID, tmp); + + tmp = cl_get_string(request, F_CIB_CALLOPTS); + ha_msg_add(*reply, F_CIB_CALLOPTS, tmp); + + tmp = cl_get_string(request, F_CIB_CALLID); + ha_msg_add(*reply, F_CIB_CALLID, tmp); + } + + /* attach the output if necessary */ + output_s = dump_xml_unformatted(output); + if(output != NULL && output_s == NULL) { + crm_err("Currupt output in reply to \"%s\" op",op); + rc = cib_output_data; + + } else if(output_s != NULL + && ha_msg_add(*reply, F_CIB_CALLDATA, output_s) != HA_OK) { + rc = cib_msg_field_add; + } + + crm_free(output_s); + free_xml(output); + free_xml(input); + return rc; +} + +int +send_via_callback_channel(struct ha_msg *msg, const char *token) +{ + cib_client_t *hash_client = NULL; + + if(token == NULL) { + crm_err("No client id token, cant send message"); + return cib_missing; + } + + hash_client = g_hash_table_lookup(client_list, token); + + if(hash_client == NULL) { + crm_err("Cannot find client for token %s", token); + return cib_client_gone; + } + + crm_debug("Delivering reply to client %s", token); + if(msg2ipcchan(msg, hash_client->channel) != HA_OK) { + crm_err("Delivery of reply to client %s failed", token); + return cib_reply_failed; + } + return cib_ok; +} + + +gboolean +cib_process_disconnect(IPC_Channel *channel, cib_client_t *cib_client) +{ + if (channel->ch_status == IPC_DISCONNECT && cib_client != NULL) { + crm_info("Cleaning up after %s channel disconnect from client %s", + cib_client->channel_name, cib_client->id); + + g_hash_table_remove(client_list, cib_client->id); + + if(cib_client->source != NULL) { + G_main_del_IPC_Channel(cib_client->source); + cib_client->source = NULL; + } + +/* crm_free(cib_client->callback_id); */ +/* crm_free(cib_client->id); */ + crm_free(cib_client); + + return FALSE; + + } else if (channel->ch_status == IPC_DISCONNECT) { + crm_warn("Unknown client disconnected"); + return FALSE; + } + + return TRUE; +} + + +gboolean +cib_ha_dispatch(IPC_Channel *channel, gpointer user_data) +{ + int lpc = 0; + ll_cluster_t *hb_cluster = (ll_cluster_t*)user_data; + + while(hb_cluster->llc_ops->msgready(hb_cluster)) { + lpc++; + /* invoke the callbacks but dont block */ + hb_cluster->llc_ops->rcvmsg(hb_cluster, 0); + } + + crm_trace("%d HA messages dispatched", lpc); + + if (channel && (channel->ch_status == IPC_DISCONNECT)) { + crm_crit("Lost connection to heartbeat service... exiting"); + exit(100); + return FALSE; + } + return TRUE; +} + +void +cib_peer_callback(const struct ha_msg* msg, void* private_data) +{ + int is_done = 1; + int call_type = 0; + int call_options = 0; + + enum cib_errors rc = cib_ok; + struct ha_msg *op_reply = NULL; + + const char *originator = cl_get_string(msg, F_ORIG); + const char *reply_to = cl_get_string(msg, F_CIB_ISREPLY); + const char *client_id = NULL; + + if(cib_get_operation_id(msg, &call_type) != cib_ok) { + crm_err("Invalid operation... discarding msg"); + return; + } + + if(cib_server_ops[call_type].modifies_cib + || (reply_to == NULL && cib_is_master)) { + is_done = 0; + } + + crm_info("Processing message from peer..."); + cl_log_message(msg); + + if(reply_to == NULL && cib_is_master == FALSE) { + /* this is for the master instance and we're not it */ + crm_debug("Ignoring msg for master instance"); + return; + + } else if(is_done == 0) { + crm_debug("Processing msg for result"); + rc = cib_process_command(msg, &op_reply, TRUE); + + } else if(safe_str_eq(reply_to, cib_our_uname)) { + crm_debug("Nothing for us to do..." + " just send reply back to the client"); + + } else { + crm_warn("Nothing for us to do?"); + } + + if(op_reply == NULL) { + crm_trace("copy original message"); + op_reply = ha_msg_copy(msg); + } + if(reply_to == NULL) { + crm_trace("add the originator to message"); + ha_msg_add(op_reply, F_CIB_ISREPLY, originator); + } + + cl_get_int(msg, F_CIB_CALLOPTS, &call_options); + crm_trace("Retrieved call options: %d", call_options); + + + if(safe_str_eq(reply_to, cib_our_uname)) { + /* send callback to originator */ + cib_client_t *client_obj = NULL; + crm_trace("find the client"); + + client_id = cl_get_string(msg, F_CIB_CLIENTID); + if(client_id != NULL) { + client_obj = g_hash_table_lookup( + client_list, client_id); + } else { + crm_err("No client to sent the responce to." + " F_CIB_CLIENTID not set."); + } + + crm_debug("Sending callback to originator of delegated request"); + if(client_obj != NULL) { + if(is_done == 0) { + crm_debug("Sending local modify response"); + + } else { + crm_debug("Sending master response"); + } + if(call_options & cib_sync_call) { + crm_debug("Sending sync response: %d", call_options); + msg2ipcchan(op_reply, client_obj->channel); + + } else { + crm_debug("Sending async response"); + send_via_callback_channel( + op_reply, client_obj->callback_id); + } + + } else { + crm_warn("Client %s may have left us", client_id); + } + + } else if(reply_to != NULL && safe_str_eq(reply_to, cib_our_uname)) { + /* nothing more to do... + * this was a non-originating slave update + */ + crm_debug("Completed non-originating slave update"); + + /* from now on we are the server */ + } else if(rc == cib_ok + && cib_server_ops[call_type].modifies_cib + && !(call_options & cib_scope_local)) { + /* this (successful) call modified the CIB _and_ the + * change needs to be broadcast... + * send via HA to other nodes + */ + crm_debug("Sending update request to everyone"); + hb_conn->llc_ops->sendclustermsg(hb_conn, op_reply); + + } else { + /* send reply via HA to originating node */ + crm_debug("Sending request result to originator only"); + hb_conn->llc_ops->send_ordered_nodemsg( + hb_conn, op_reply, originator); + } + + return; +} + +enum cib_errors +cib_get_operation_id(const struct ha_msg* msg, int *operation) +{ + int lpc = 0; + int max_msg_types = DIMOF(cib_server_ops); + const char *op = cl_get_string(msg, F_CIB_OPERATION); + + 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; +} diff --git a/crm/cib/callbacks.h b/crm/cib/callbacks.h new file mode 100644 index 0000000000..d29d69bbec --- /dev/null +++ b/crm/cib/callbacks.h @@ -0,0 +1,66 @@ +/* $Id: callbacks.h,v 1.1 2004/12/05 16:14:07 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 + +extern gboolean cib_is_master; +extern GHashTable *client_list; + +typedef struct cib_client_s +{ + char *id; + char *callback_id; + + const char *channel_name; + + IPC_Channel *channel; + GCHSource *source; + +} cib_client_t; + +typedef struct cib_operation_s +{ + const char* operation; + gboolean modifies_cib; + gboolean needs_privileges; + gboolean needs_section; + gboolean needs_data; + enum cib_errors (*fn)( + const char *, int, const char *, xmlNodePtr, xmlNodePtr*); +} cib_operation_t; + +extern cib_operation_t cib_server_ops[]; + +extern gboolean cib_client_connect(IPC_Channel *channel, gpointer user_data); +extern gboolean cib_null_callback (IPC_Channel *channel, gpointer user_data); +extern gboolean cib_rw_callback (IPC_Channel *channel, gpointer user_data); +extern gboolean cib_ro_callback (IPC_Channel *channel, gpointer user_data); +extern gboolean cib_ha_dispatch (IPC_Channel *channel, gpointer user_data); + +extern void cib_peer_callback(const struct ha_msg* msg, void* private_data); + diff --git a/crm/cib/cib.c b/crm/cib/cib.c index cdc16f7d7c..85f42f6835 100644 --- a/crm/cib/cib.c +++ b/crm/cib/cib.c @@ -1,396 +1,44 @@ -/* $Id: cib.c,v 1.55 2004/11/08 08:20:04 andrew Exp $ */ +/* $Id: cib.c,v 1.56 2004/12/05 16:14:07 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 -gboolean -startCib(const char *filename) -{ - xmlNodePtr cib = readCibXmlFile(filename); - if (initializeCib(cib)) { - crm_info("CIB Initialization completed successfully"); - } else { - /* free_xml(cib); */ - crm_warn("CIB Initialization failed, " - "starting with an empty default."); - activateCibXml(createEmptyCib(), filename); - } - return TRUE; -} -xmlNodePtr -get_cib_copy(void) -{ - return copy_xml_node_recursive(get_the_CIB()); -} - -xmlNodePtr -cib_get_generation(void) -{ - xmlNodePtr generation = create_xml_node(NULL, "generation_tuple"); - copy_in_properties(generation, get_the_CIB()); - return generation; -} - -/* - * The caller should never free the return value - */ -xmlNodePtr -get_object_root(const char *object_type, xmlNodePtr the_root) -{ - const char *node_stack[2]; - xmlNodePtr tmp_node = NULL; - - if(the_root == NULL) { - crm_err("CIB root object was NULL"); - return NULL; - } - - node_stack[0] = XML_CIB_TAG_CONFIGURATION; - node_stack[1] = object_type; - - if(object_type == NULL - || strlen(object_type) == 0 - || safe_str_eq("all", object_type)) { - return the_root; - /* get the whole cib */ - - } else if(strcmp(object_type, XML_CIB_TAG_STATUS) == 0) { - /* these live in a different place */ - tmp_node = find_xml_node(the_root, XML_CIB_TAG_STATUS); - - node_stack[0] = XML_CIB_TAG_STATUS; - node_stack[1] = NULL; - -/* } else if(strcmp(object_type, XML_CIB_TAG_CRMCONFIG) == 0) { */ -/* /\* these live in a different place too *\/ */ -/* tmp_node = find_xml_node(the_root, XML_CIB_TAG_CRMCONFIG); */ - -/* node_stack[0] = XML_CIB_TAG_CRMCONFIG; */ -/* node_stack[1] = NULL; */ - - } else { - tmp_node = find_xml_node_nested(the_root, node_stack, 2); - } - - if (tmp_node == NULL) { - crm_err("[cib] Section %s [%s [%s]] not present", - the_root->name, - node_stack[0], - node_stack[1]?node_stack[1]:""); - } - return tmp_node; -} - -xmlNodePtr -process_cib_message(xmlNodePtr message, gboolean auto_reply) -{ - xmlNodePtr data; - xmlNodePtr reply; - enum cib_result result = CIBRES_OK; - xmlNodePtr fragment = find_xml_node(message, XML_TAG_FRAGMENT); - xmlNodePtr options = find_xml_node(message, XML_TAG_OPTIONS); - const char *section = xmlGetProp(fragment, XML_ATTR_SECTION); - const char *op = xmlGetProp(options , XML_ATTR_OP); - - if(section != NULL) { - set_xml_property_copy( - options, XML_ATTR_FILTER_TYPE, section); - } - - data = cib_process_request(op, options, fragment, &result); - - crm_debug("[cib] operation returned result %d", result); - - if(auto_reply) { - reply = create_reply(message, data); - free_xml(data); - - set_xml_attr(reply, XML_TAG_OPTIONS, - XML_ATTR_RESULT, cib_error2string(result), TRUE); - - return reply; - } - - return data; -} - -xmlNodePtr -process_cib_request( - const char *op, const xmlNodePtr options, const xmlNodePtr fragment) -{ - enum cib_result result = CIBRES_OK; - - const char *section = xmlGetProp(fragment, XML_ATTR_SECTION); - - if(section != NULL) { - set_xml_property_copy( - options, XML_ATTR_FILTER_TYPE, section); - } - - return cib_process_request(op, options, fragment, &result); -} - - -xmlNodePtr -create_cib_fragment_adv( - xmlNodePtr update, const char *section, const char *source) -{ - gboolean whole_cib = FALSE; - xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); - xmlNodePtr cib = NULL; - xmlNodePtr object_root = NULL; - char *auto_section = pluralSection(update?update->name:NULL); - - if(update == NULL) { - crm_err("No update to create a fragment for"); - crm_free(auto_section); - return NULL; - - } else if(section == NULL) { - section = auto_section; - - } else if(strcmp(auto_section, section) != 0) { - crm_err("Values for update (tag=%s) and section (%s)" - " were not consistent", update->name, section); - crm_free(auto_section); - return NULL; - - } - - if(strcmp(section, "all")==0 && strcmp(update->name, XML_TAG_CIB)==0) { - whole_cib = TRUE; - } - - set_xml_property_copy(fragment, XML_ATTR_SECTION, section); - - if(whole_cib == FALSE) { - cib = createEmptyCib(); - object_root = get_object_root(section, cib); - xmlAddChildList(object_root, xmlCopyNodeList(update)); - - } else { - cib = xmlCopyNodeList(update); - } - - xmlAddChild(fragment, cib); - set_xml_property_copy(cib, "debug_source", source); - - crm_free(auto_section); - - crm_debug("Verifying created fragment"); - if(verifyCibXml(cib) == FALSE) { - crm_err("Fragment creation failed"); - crm_err("[src] %s", dump_xml_formatted(update)); - crm_err("[created] %s", dump_xml_formatted(fragment)); - free_xml(fragment); - fragment = NULL; - } - - - - return fragment; -} - - -char * -pluralSection(const char *a_section) -{ - char *a_section_parent = NULL; - if (a_section == NULL) { - a_section_parent = crm_strdup("all"); - - } else if(strcmp(a_section, XML_TAG_CIB) == 0) { - a_section_parent = crm_strdup("all"); - - } else if(strcmp(a_section, XML_CIB_TAG_NODE) == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_NODES); - - } else if(strcmp(a_section, XML_CIB_TAG_STATE) == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_STATUS); - - } else if(strcmp(a_section, XML_CIB_TAG_CONSTRAINT) == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS); - - } else if(strcmp(a_section, "rsc_location") == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS); - - } else if(strcmp(a_section, "rsc_dependancy") == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS); - - } else if(strcmp(a_section, "rsc_order") == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS); - - } else if(strcmp(a_section, XML_CIB_TAG_RESOURCE) == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES); - - } else if(strcmp(a_section, XML_CIB_TAG_NVPAIR) == 0) { - a_section_parent = crm_strdup(XML_CIB_TAG_CRMCONFIG); - - } else { - crm_err("Unknown section %s", a_section); - a_section_parent = crm_strdup("all"); - } - - crm_verbose("Plural of %s is %s", - crm_str(a_section), a_section_parent); - - return a_section_parent; -} - -const char * -cib_error2string(enum cib_result return_code) -{ - const char *error_msg = NULL; - switch(return_code) { - case CIBRES_MISSING_ID: - error_msg = "The id field is missing"; - break; - case CIBRES_MISSING_TYPE: - error_msg = "The type field is missing"; - break; - case CIBRES_MISSING_FIELD: - error_msg = "A required field is missing"; - break; - case CIBRES_OBJTYPE_MISMATCH: - error_msg = "CIBRES_OBJTYPE_MISMATCH"; - break; - case CIBRES_FAILED_EXISTS: - error_msg = "The object already exists"; - break; - case CIBRES_FAILED_NOTEXISTS: - error_msg = "The object does not exist"; - break; - case CIBRES_CORRUPT: - error_msg = "The CIB is corrupt"; - break; - case CIBRES_FAILED_NOOBJECT: - error_msg = "The update was empty"; - break; - case CIBRES_FAILED_NOPARENT: - error_msg = "The parent object does not exist"; - break; - case CIBRES_FAILED_NODECOPY: - error_msg = "Failed while copying update"; - break; - case CIBRES_OTHER: - error_msg = "CIBRES_OTHER"; - break; - case CIBRES_OK: - error_msg = "ok"; - break; - case CIBRES_FAILED: - error_msg = "Failed"; - break; - case CIBRES_FAILED_STALE: - error_msg = "Discarded old update"; - break; - case CIBRES_FAILED_ACTIVATION: - error_msg = "Activation Failed"; - break; - case CIBRES_FAILED_NOSECTION: - error_msg = "Required section was missing"; - break; - case CIBRES_FAILED_NOTSUPPORTED: - error_msg = "Supplied information is not supported"; - break; - } - - if(error_msg == NULL) { - crm_err("Unknown CIB Error %d", return_code); - error_msg = ""; - } - - return error_msg; -} - -const char * -cib_op2string(enum cib_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_OP_MAX: - operation_msg = "invalid operation"; - break; - - } - - if(operation_msg == NULL) { - crm_err("Unknown CIB operation %d", operation); - operation_msg = ""; - } - - return operation_msg; -} - -int -compare_cib_generation(xmlNodePtr left, xmlNodePtr right) -{ - int int_gen_l = -1; - int int_gen_r = -1; - const char *gen_l = xmlGetProp(left, XML_ATTR_GENERATION); - const char *gen_r = xmlGetProp(right, XML_ATTR_GENERATION); - - if(gen_l != NULL) int_gen_l = atoi(gen_l); - if(gen_r != NULL) int_gen_r = atoi(gen_r); - - if(int_gen_l < int_gen_r) { - return -1; - - } else if(int_gen_l > int_gen_r) { - return 1; - } - - return 0; -} - diff --git a/crm/cib/cibio.c b/crm/cib/cibio.c deleted file mode 100644 index 28dcf9abd2..0000000000 --- a/crm/cib/cibio.c +++ /dev/null @@ -1,396 +0,0 @@ -/* $Id: cibio.c,v 1.34 2004/08/30 03:17:37 msoffen 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 - -const char * local_resource_path[] = -{ - XML_CIB_TAG_STATUS, -}; - -const char * resource_path[] = -{ - XML_CIB_TAG_RESOURCES, -}; - -const char * node_path[] = -{ - XML_CIB_TAG_NODES, -}; - -const char * constraint_path[] = -{ - XML_CIB_TAG_CONSTRAINTS, -}; - -gboolean initialized = FALSE; -xmlNodePtr the_cib = NULL; -xmlNodePtr node_search = NULL; -xmlNodePtr resource_search = NULL; -xmlNodePtr constraint_search = NULL; -xmlNodePtr status_search = NULL; - -/* - * It is the callers responsibility to free both the new CIB (output) - * and the new CIB (input) - */ -xmlNodePtr -createEmptyCib(void) -{ - xmlNodePtr cib_root = NULL, config = NULL, status = NULL; - - cib_root = create_xml_node(NULL, XML_TAG_CIB); - - config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION); - status = create_xml_node(cib_root, XML_CIB_TAG_STATUS); - create_xml_node(cib_root, XML_CIB_TAG_CRMCONFIG); - - set_node_tstamp(cib_root); - set_node_tstamp(config); - set_node_tstamp(status); - - set_xml_property_copy(cib_root, "version", "1"); - set_xml_property_copy(cib_root, "generated", XML_BOOLEAN_TRUE); - - create_xml_node(config, XML_CIB_TAG_NODES); - create_xml_node(config, XML_CIB_TAG_RESOURCES); - create_xml_node(config, XML_CIB_TAG_CONSTRAINTS); - - if (verifyCibXml(cib_root)) { - return cib_root; - } - crm_crit("The generated CIB did not pass integrity testing!!" - " All hope is lost."); - return NULL; -} - -gboolean -verifyCibXml(xmlNodePtr cib) -{ - gboolean is_valid = TRUE; - xmlNodePtr tmp_node = NULL; - - if (cib == NULL) { - crm_err("XML Buffer was empty."); - return FALSE; - } - - tmp_node = get_object_root(XML_CIB_TAG_NODES, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_RESOURCES, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_STATUS, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_CRMCONFIG, cib); - if (tmp_node == NULL) is_valid = FALSE; - - /* more integrity tests */ - - return is_valid; -} - -/* - * It is the callers responsibility to free the output of this function - */ -xmlNodePtr -readCibXml(char *buffer) -{ - xmlNodePtr root = string2xml(buffer); - if (verifyCibXml(root) == FALSE) { - free_xml(root); - return createEmptyCib(); - } - return root; -} - -/* - * It is the callers responsibility to free the output of this function - */ -xmlNodePtr -readCibXmlFile(const char *filename) -{ - int s_res = -1; - struct stat buf; - xmlNodePtr root = NULL; - - - if(filename != NULL) { - s_res = stat(filename, &buf); - } - - if (s_res == 0) { - FILE *cib_file = fopen(filename, "r"); - root = file2xml(cib_file); - set_xml_property_copy(root, "generated", XML_BOOLEAN_FALSE); - fclose(cib_file); - - } else { - crm_warn("Stat of (%s) failed, file does not exist.", - CIB_FILENAME); - } - - if (verifyCibXml(root) == FALSE) { - free_xml(root); -/* return createEmptyCib(); */ - root = NULL; - } - - return root; -} - -/* - * The caller should never free the return value - */ -xmlNodePtr -get_the_CIB(void) -{ - return the_cib; -} - -gboolean -uninitializeCib(void) -{ - xmlNodePtr tmp_cib = the_cib; - - - if(tmp_cib == NULL) { - crm_err("The CIB has already been deallocated."); - return FALSE; - } - - initialized = FALSE; - the_cib = NULL; - node_search = NULL; - resource_search = NULL; - constraint_search = NULL; - status_search = NULL; - - crm_err("Deallocating the CIB."); - - free_xml(tmp_cib); - - crm_err("The CIB has been deallocated."); - - return TRUE; -} - - - - -/* - * This method will not free the old CIB pointer or the new one. - * We rely on the caller to have saved a pointer to the old CIB - * and to free the old/bad one depending on what is appropriate. - */ -gboolean -initializeCib(xmlNodePtr new_cib) -{ - if (verifyCibXml(new_cib)) { - - initialized = FALSE; - the_cib = new_cib; - - /* update search paths */ - /* not used yet... - node_search = - get_object_root(XML_CIB_TAG_NODES, new_cib); - resource_search = - get_object_root(XML_CIB_TAG_RESOURCES, new_cib); - constraint_search = - get_object_root(XML_CIB_TAG_CONSTRAINTS, new_cib); - status_search = - get_object_root(XML_CIB_TAG_STATUS, new_cib); - */ - initialized = TRUE; - - crm_trace("CIB initialized"); - return TRUE; - } - else { - crm_err("CIB Verification failed"); - } - - return FALSE; - -} - -int -moveFile(const char *oldname, - const char *newname, - gboolean backup, - char *ext) -{ - /* move 'oldname' to 'newname' by creating a hard link to it - * and then removing the original hard link - */ - int res = 0; - struct stat tmp; - int s_res = stat(newname, &tmp); - - - if (s_res >= 0) - { - if (backup == TRUE) { - char backname[1024]; - static const char *back_ext = "bak"; - if (ext != NULL) back_ext = (char*)ext; - - snprintf(backname, sizeof(backname)-1, - "%s.%s", newname, back_ext); - moveFile(newname, backname, FALSE, NULL); - } else { - res = unlink(newname); - if (res < 0) { - perror("Could not remove the current backup of Cib"); - return -1; - } - } - } - - s_res = stat(oldname, &tmp); - - if (s_res >= 0) { - res = link(oldname, newname); - if (res < 0) { - perror("Could not create backup of current Cib"); - return -2; - } - res = unlink(oldname); - if (res < 0) { - perror("Could not unlink the current Cib"); - return -3; - } - } - - return 0; - -} - - -int -activateCibBuffer(char *buffer, const char *filename) -{ - int result = -1; - xmlNodePtr local_cib = NULL; - - - local_cib = readCibXml(buffer); - result = activateCibXml(local_cib, filename); - - return result; -} - -/* - * This method will free the old CIB pointer on success and the new one - * on failure. - */ -int -activateCibXml(xmlNodePtr new_cib, const char *filename) -{ - int error_code = 0; - xmlNodePtr saved_cib = get_the_CIB(); - const char *filename_bak = CIB_BACKUP; /* calculate */ - - if (initializeCib(new_cib) == TRUE) { - int res = moveFile(filename, filename_bak, FALSE, NULL); - - if (res < 0) { - crm_info("Could not make backup of the current Cib " - "(code: %d)... aborting update.", res); - error_code = -1; - } else { - crm_info("Writing CIB out to %s", CIB_FILENAME); - res = write_xml_file(new_cib, CIB_FILENAME); -#ifdef DEVEL_CIB_COPY - write_xml_file(new_cib, DEVEL_DIR"/cib.xml"); -#endif - if (res < 0) { - /* assume 0 is good */ - if (moveFile(filename_bak, - filename, - FALSE, - NULL) < -1) { - crm_crit("Could not restore the " - "backup of the current Cib " - "(code: %d)... panic!", - res); - error_code = -2; - /* should probably exit here */ - } else if (initializeCib(saved_cib) == FALSE) { - /* oh we are so dead */ - crm_crit("Could not re-initialize " - "with the old CIB. " - "Everything is about to go " - "pear shaped"); - error_code = -3; - } else { - crm_crit("Update of Cib failed " - "(code: %d)... reverted to " - "last known valid version", - res); - - error_code = -4; - } - } - } - } - else - { - crm_info("Ignoring invalid or NULL Cib"); - error_code = -5; - } - - /* Make sure memory is cleaned up appropriately */ - if (error_code != 0) { - crm_trace("Freeing new CIB %p", new_cib); - free_xml(new_cib); - } else { - crm_trace("Freeing saved CIB %p", saved_cib); - free_xml(saved_cib); - } - - return error_code; - -} diff --git a/crm/cib/cibio.h b/crm/cib/cibio.h index 74bc6152e5..b105107bfe 100644 --- a/crm/cib/cibio.h +++ b/crm/cib/cibio.h @@ -1,60 +1,59 @@ -/* $Id: cibio.h,v 1.8 2004/06/02 16:03:34 andrew Exp $ */ +/* $Id: cibio.h,v 1.9 2004/12/05 16:14:07 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 */ #ifndef CIB_IO__H #define CIB_IO__H #include #include #include #include #include #include #include #include #include #include extern gboolean initialized; extern xmlNodePtr the_cib; extern xmlNodePtr node_search; extern xmlNodePtr resource_search; extern xmlNodePtr constraint_search; extern xmlNodePtr status_search; extern xmlNodePtr get_the_CIB(void); extern int initializeCib(xmlNodePtr cib); extern gboolean uninitializeCib(void); extern xmlNodePtr createEmptyCib(void); extern gboolean verifyCibXml(xmlNodePtr cib); extern xmlNodePtr readCibXml(char *buffer); extern xmlNodePtr readCibXmlFile(const char *filename); extern int activateCibBuffer(char *buffer, const char *filename); extern int activateCibXml(xmlNodePtr doc, const char *filename); -extern int moveFile(const char *oldname, - const char *newname, - gboolean backup, - char *ext); +extern int moveFile(const char *oldname, const char *newname, + gboolean backup, char *ext); +/* extern xmlNodePtr server_get_cib_copy(void); */ #endif diff --git a/crm/cib/cibmessages.c b/crm/cib/cibmessages.c deleted file mode 100644 index b89de4448c..0000000000 --- a/crm/cib/cibmessages.c +++ /dev/null @@ -1,468 +0,0 @@ -/* $Id: cibmessages.c,v 1.52 2004/10/20 13:48:53 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 - -FILE *msg_cib_strm = NULL; - -enum cib_result updateList(xmlNodePtr local_cib, - xmlNodePtr update_command, - xmlNodePtr failed, - int operation, - const char *section); - -xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed); - -gboolean replace_section(const char *section, - xmlNodePtr tmpCib, - xmlNodePtr command); - -gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib); - -gboolean update_results(xmlNodePtr failed, - xmlNodePtr target, - int operation, - int return_code); - -xmlNodePtr -cib_process_request(const char *op, - const xmlNodePtr options, - const xmlNodePtr fragment, - enum cib_result *result) -{ - const char *verbose = NULL; - const char *section = NULL; - const char *id = NULL; - const char *output_section = NULL; - xmlNodePtr failed = NULL; - xmlNodePtr cib_answer = NULL; - - gboolean update_the_cib = FALSE; - int cib_update_op = CIB_OP_NONE; - xmlNodePtr tmpCib; - char *new_value = NULL; - char *old_value = NULL; - int int_value = -1; - char *xml_text = NULL; - - *result = CIBRES_OK; - verbose = xmlGetProp(options, XML_ATTR_VERBOSE); - section = xmlGetProp(options, XML_ATTR_FILTER_TYPE); - id = xmlGetProp(options, XML_ATTR_FILTER_ID); - failed = create_xml_node(NULL, XML_TAG_FAILED); - -#ifdef MSG_LOG - if(msg_cib_strm == NULL) { - msg_cib_strm = fopen(DEVEL_DIR"/cib.log", "w"); - } - fprintf(msg_cib_strm, "\n====================\n"); - xml_text = dump_xml_formatted(fragment); - fprintf(msg_cib_strm, "[Input %s]\t%s\n", op, xml_text); - fflush(msg_cib_strm); - crm_free(xml_text); -#endif - - crm_debug("[cib] Processing \"%s\" event", op); - - if(op == NULL) { - *result = CIBRES_FAILED; - crm_err("No operation specified\n"); - - } else if(strcmp("noop", op) == 0) { - ; - - } else if(strcmp(CRM_OP_QUIT, op) == 0) { - crm_warn( - "The CRMd has asked us to exit... complying"); - exit(0); - - } else if (strcmp(CRM_OP_PING, op) == 0) { - cib_answer = - createPingAnswerFragment(CRM_SYSTEM_CIB, "ok"); - - } else if (strcmp(CRM_OP_BUMP, op) == 0) { - tmpCib = get_cib_copy(); - crm_verbose("Handling a %s for section=%s of the cib", - CRM_OP_BUMP, section); - - /* modify the timestamp */ - set_node_tstamp(tmpCib); - old_value = - xmlGetProp(get_the_CIB(), XML_ATTR_GENERATION); - - if(old_value != NULL) { - new_value = (char*)crm_malloc(128*(sizeof(char))); - int_value = atoi(old_value); - sprintf(new_value, "%d", ++int_value); - } else { - new_value = crm_strdup("0"); - } - - crm_debug("Generation %d(%s)->%s", - int_value, old_value, new_value); - - set_xml_property_copy(tmpCib, XML_ATTR_GENERATION, new_value); - crm_free(new_value); - - if(activateCibXml(tmpCib, CIB_FILENAME) >= 0) { - verbose = XML_BOOLEAN_TRUE; - } else { - *result = CIBRES_FAILED; - } - - } else if (strcmp("query", op) == 0) { - crm_verbose("Handling a query for section=%s of the cib", - section); - - /* grab the whole section by forcing a pick-up of - * the relevant section before returning - */ - verbose = XML_BOOLEAN_TRUE; - - } else if (strcmp(CRM_OP_ERASE, op) == 0) { - - crm_err("Op %s is not currently supported", op); - *result = CIBRES_FAILED_NOTSUPPORTED; - - } else if (strcmp(CRM_OP_CREATE, op) == 0) { - update_the_cib = TRUE; - cib_update_op = CIB_OP_ADD; - - } else if (strcmp(CRM_OP_UPDATE, op) == 0 - || strcmp(CRM_OP_WELCOME, op) == 0 - || strcmp(CRM_OP_SHUTDOWN_REQ, op) == 0) { - update_the_cib = TRUE; - cib_update_op = CIB_OP_MODIFY; - - } else if (strcmp(CRM_OP_DELETE, op) == 0) { - update_the_cib = TRUE; - cib_update_op = CIB_OP_DELETE; - - } else if (strcmp(CRM_OP_REPLACE, op) == 0) { - crm_verbose("Replacing section=%s of the cib", section); - - if (section == NULL - || strlen(section) == 0 - || strcmp("all", section) == 0) { - tmpCib = copy_xml_node_recursive( - find_xml_node(fragment, XML_TAG_CIB)); - - } else { - tmpCib = copy_xml_node_recursive(get_the_CIB()); - replace_section(section, tmpCib, fragment); - } - - /*if(check_generation(cib_updates, tmpCib) == FALSE) - *result = "discarded old update"; - else */ - if (activateCibXml(tmpCib, CIB_FILENAME) < 0) - *result = CIBRES_FAILED; - } else { - *result = CIBRES_FAILED_NOTSUPPORTED; - crm_err("Action [%s] is not supported by the CIB", op); - } - - if (update_the_cib) { - tmpCib = copy_xml_node_recursive(get_the_CIB()); - - crm_verbose("Updating section=%s of the cib (op=%s)", - section, op); - - /* should we be doing this? */ - /* do logging */ - - /* make changes to a temp copy then activate */ - if(section == NULL) { - crm_err("No section specified in %s", - XML_ATTR_FILTER_TYPE); - *result = CIBRES_FAILED_NOSECTION; - - } else if(strcmp("all", section) == 0) { - /* order is no longer important here */ - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_NODES); - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_RESOURCES); - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_CONSTRAINTS); - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_STATUS); - } else { - *result = updateList(tmpCib, fragment, failed, - cib_update_op, section); - } - - crm_trace("Activating temporary CIB"); - xml_text = dump_xml_formatted(tmpCib); - fprintf(msg_cib_strm, "[Activating CIB (%s - %s)]\t%s\n", op, - cib_error2string(*result), - xml_text); - crm_free(xml_text); - /* if(check_generation(cib_updates, tmpCib) == FALSE) */ -/* status = "discarded old update"; */ -/* else */ - if (activateCibXml(tmpCib, CIB_FILENAME) < 0) { - *result = CIBRES_FAILED_ACTIVATION; - - } else if (failed->children != NULL) { - *result = CIBRES_FAILED; - - } - - xml_text = dump_xml_formatted(get_the_CIB()); - fprintf(msg_cib_strm, "[New CIB (%s - %s)]\t%s\n", op, - cib_error2string(*result), - xml_text); - fflush(msg_cib_strm); - crm_free(xml_text); - - crm_verbose("CIB update status: %d", *result); - } - - output_section = section; - - if (failed->children != NULL || *result != CIBRES_OK) { - cib_answer = createCibFragmentAnswer(NULL /*"all"*/, failed); - - } else if (verbose != NULL && strcmp(XML_BOOLEAN_TRUE, verbose) == 0) { - cib_answer = createCibFragmentAnswer(output_section, failed); - - } - - free_xml(failed); - -#ifdef MSG_LOG - xml_text = dump_xml_formatted(cib_answer); - fprintf(msg_cib_strm, "[Reply (%s:%s)]\t%s\n", - op, cib_error2string(*result), - xml_text); - fflush(msg_cib_strm); -#endif - - return cib_answer; -} - -gboolean -replace_section(const char *section, xmlNodePtr tmpCib, xmlNodePtr fragment) -{ - xmlNodePtr parent = NULL, - cib_updates = NULL, - new_section = NULL, - old_section = NULL; - - cib_updates = find_xml_node(fragment, XML_TAG_CIB); - - /* find the old and new versions of the section */ - new_section = get_object_root(section, cib_updates); - old_section = get_object_root(section, tmpCib); - - if(old_section == NULL) { - crm_err("The CIB is corrupt, cannot replace missing section %s", - section); - return FALSE; - - } else if(new_section == NULL) { - crm_err("The CIB is corrupt, cannot set section %s to nothing", - section); - return FALSE; - } - - parent = old_section->parent; - - /* unlink and free the old one */ - unlink_xml_node(old_section); - free_xml(old_section); - - /* add the new copy */ - add_node_copy(parent, new_section); - - return TRUE; -} - - - -enum cib_result -updateList(xmlNodePtr local_cib, xmlNodePtr update_fragment, xmlNodePtr failed, - int operation, const char *section) -{ - xmlNodePtr this_section = get_object_root(section, local_cib); - xmlNodePtr cib_updates = NULL; - xmlNodePtr xml_section = NULL; - const char *obj_id = NULL; - - cib_updates = find_xml_node(update_fragment, XML_TAG_CIB); - xml_section = get_object_root(section, cib_updates); - - if (section == NULL || xml_section == NULL) { - crm_err("Section %s not found in message." - " CIB update is corrupt, ignoring.", section); - return CIBRES_FAILED_NOSECTION; - } - - if(CIB_OP_NONE > operation > CIB_OP_MAX) { - crm_err("Invalid operation on section %s", section); - return CIBRES_FAILED; - } - - set_node_tstamp(this_section); - - xml_child_iter( - xml_section, a_child, NULL, - - obj_id = xmlGetProp(a_child, "id"); - crm_info("%s to %s with id=%s", cib_op2string(operation), a_child->name, obj_id); - - if(operation == CIB_OP_DELETE) { - update_results( - failed, a_child, operation, - delete_cib_object(this_section, a_child)); - - } else if(operation == CIB_OP_MODIFY) { - - update_results( - failed, a_child, operation, - update_cib_object(this_section, a_child, FALSE)); - - } else { - update_results( - failed, a_child, operation, - add_cib_object(this_section, a_child)); - } - - ); - - if (failed->children != NULL) { - return CIBRES_FAILED; - } else { - return CIBRES_OK; - } -} - -xmlNodePtr -createCibFragmentAnswer(const char *section, xmlNodePtr failed) -{ - xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); - - set_xml_property_copy(fragment, XML_ATTR_SECTION, section); - - if (section == NULL - || strlen(section) == 0 - || strcmp("all", section) == 0) { - add_node_copy(fragment, get_the_CIB()); - - } else { - xmlNodePtr cib = create_xml_node(fragment, XML_TAG_CIB); - add_node_copy(cib, get_object_root(section, get_the_CIB())); - copy_in_properties(cib, get_the_CIB()); - - } - - if (failed != NULL && failed->children != NULL) { - add_node_copy(fragment, failed); - } - - return fragment; -} - - -gboolean -check_generation(xmlNodePtr newCib, xmlNodePtr oldCib) -{ - char *new_value = xmlGetProp(newCib, XML_ATTR_GENERATION); - char *old_value = xmlGetProp(oldCib, XML_ATTR_GENERATION); - int int_new_value = -1; - int int_old_value = -1; - if(old_value != NULL) int_old_value = atoi(old_value); - if(new_value != NULL) int_new_value = atoi(new_value); - - if(int_new_value >= int_old_value) { - return TRUE; - } else { - crm_err("Generation from update (%d) is older than %d", - int_new_value, int_old_value); - } - - return FALSE; -} - -gboolean -update_results(xmlNodePtr failed, - xmlNodePtr target, - int operation, - int return_code) -{ - gboolean was_error = FALSE; - const char *error_msg = NULL; - const char *operation_msg = NULL; - xmlNodePtr xml_node; - - operation_msg = cib_op2string(operation); - - if (return_code != CIBRES_OK) { - error_msg = cib_error2string(return_code); - - xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB); - - was_error = TRUE; - - set_xml_property_copy( - xml_node, XML_FAILCIB_ATTR_ID, ID(target)); - - set_xml_property_copy( - xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target)); - - set_xml_property_copy( - xml_node, XML_FAILCIB_ATTR_OP, operation_msg); - - set_xml_property_copy( - xml_node, XML_FAILCIB_ATTR_REASON, error_msg); - - crm_debug("Action %s failed: %s (cde=%d)", - operation_msg, error_msg, return_code); - - } else { - crm_debug("CIB %s passed", operation_msg); - } - - return was_error; -} - diff --git a/crm/cib/cibmessages.h b/crm/cib/cibmessages.h index 110c8dcc6c..bed816db13 100644 --- a/crm/cib/cibmessages.h +++ b/crm/cib/cibmessages.h @@ -1,32 +1,64 @@ -/* $Id: cibmessages.h,v 1.4 2004/03/24 12:08:04 andrew Exp $ */ +/* $Id: cibmessages.h,v 1.5 2004/12/05 16:14:07 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 */ #ifndef CIB_MESSAGES__H #define CIB_MESSAGES__H -extern xmlNodePtr cib_process_request(const char *op, - const xmlNodePtr options, - const xmlNodePtr fragment, - enum cib_result *result); -extern xmlNodePtr createCibRequest(gboolean isLocal, const char *operation, - const char *section, const char *verbose, - xmlNodePtr data); +extern xmlNodePtr createCibRequest( + gboolean isLocal, const char *operation, const char *section, + const char *verbose, xmlNodePtr data); + +extern enum cib_errors cib_process_default( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_quit( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_ping( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_query( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_erase( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_bump( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_replace( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_modify( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); + +extern enum cib_errors cib_process_readwrite( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer); #endif diff --git a/crm/cib/cibprimatives.c b/crm/cib/cibprimatives.c deleted file mode 100644 index dadbfe13a6..0000000000 --- a/crm/cib/cibprimatives.c +++ /dev/null @@ -1,604 +0,0 @@ -/* $Id: cibprimatives.c,v 1.42 2004/10/21 16:18:42 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 - - -/* - * In case of confusion, this is the memory management policy for - * all functions in this file. - * - * All add/modify functions use copies of supplied data. - * It is therefore appropriate that the callers free the supplied data - * at some point after the function has finished. - * - * All delete functions will handle the freeing of deleted data - * but not the function arguments. - */ - - -void update_node_state(xmlNodePtr existing_node, xmlNodePtr update); - - - -/* --- Resource */ - -int -addResource(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Adding " XML_CIB_TAG_RESOURCE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_RESOURCES, cib); - return add_cib_object(root, anXmlNode); -} - - -xmlNodePtr -findResource(xmlNodePtr cib, const char *id) -{ - xmlNodePtr root = NULL, ret = NULL; - - - root = get_object_root(XML_CIB_TAG_RESOURCES, cib); - ret = find_entity(root, XML_CIB_TAG_RESOURCE, id, FALSE); - - return ret; -} - -int -updateResource(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Updating " XML_CIB_TAG_RESOURCE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_RESOURCES, cib); - return update_cib_object(root, anXmlNode, FALSE); -} - -int -delResource(xmlNodePtr cib, xmlNodePtr delete_spec) -{ - const char *id = ID(delete_spec); - xmlNodePtr root; - - if(id == NULL || strlen(id) == 0) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Deleting " XML_CIB_TAG_RESOURCE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_RESOURCES, cib); - return delete_cib_object(root, delete_spec); -} - - -/* --- Constraint */ - -int -addConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Adding " XML_CIB_TAG_CONSTRAINT " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - return add_cib_object(root, anXmlNode); -} - -xmlNodePtr -findConstraint(xmlNodePtr cib, const char *id) -{ - xmlNodePtr root = NULL, ret = NULL; - - - root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - ret = find_entity(root, XML_CIB_TAG_CONSTRAINT, id, FALSE); - - return ret; -} - - -int -updateConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Updating " XML_CIB_TAG_CONSTRAINT " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - return update_cib_object(root, anXmlNode, FALSE); -} - -int -delConstraint(xmlNodePtr cib, xmlNodePtr delete_spec) -{ - const char *id = ID(delete_spec); - xmlNodePtr root; - - if(id == NULL || strlen(id) == 0) { - return CIBRES_MISSING_ID; - } - crm_verbose("Deleting " XML_CIB_TAG_CONSTRAINT " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - return delete_cib_object(root, delete_spec); -} - -/* --- HaNode */ - -int -addHaNode(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Adding " XML_CIB_TAG_NODE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_NODES, cib); - return add_cib_object(root, anXmlNode); -} - -xmlNodePtr -findHaNode(xmlNodePtr cib, const char *id) -{ - xmlNodePtr root = NULL, ret = NULL; - - - root = get_object_root(XML_CIB_TAG_NODES, cib); - ret = find_entity(root, XML_CIB_TAG_NODE, id, FALSE); - - return ret; -} - - - -int -updateHaNode(xmlNodePtr cib, cibHaNode *anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Updating " XML_CIB_TAG_NODE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_NODES, cib); - return update_cib_object(root, anXmlNode, FALSE); -} - -int -delHaNode(xmlNodePtr cib, xmlNodePtr delete_spec) -{ - const char *id = ID(delete_spec); - xmlNodePtr root; - - if(id == NULL || strlen(id) == 0) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Deleting " XML_CIB_TAG_NODE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - return delete_cib_object(root, delete_spec); -} - -/* --- Status */ - -int -addStatus(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Adding " XML_CIB_TAG_NODE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_STATUS, cib); - return add_cib_object(root, anXmlNode); -} - -xmlNodePtr -findStatus(xmlNodePtr cib, const char *id) -{ - xmlNodePtr root = NULL, ret = NULL; - - root = get_object_root(XML_CIB_TAG_STATUS, cib); - ret = find_entity(root, XML_CIB_TAG_STATE, id, FALSE); - - return ret; -} - -int -updateStatus(xmlNodePtr cib, xmlNodePtr anXmlNode) -{ - const char *id = ID(anXmlNode); - xmlNodePtr root; - - if (id == NULL || strlen(id) < 1) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Updating " XML_CIB_TAG_NODE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_STATUS, cib); - return update_cib_object(root, anXmlNode, FALSE); -} - -int -delStatus(xmlNodePtr cib, xmlNodePtr delete_spec) -{ - const char *id = ID(delete_spec); - xmlNodePtr root; - - if(id == NULL || strlen(id) == 0) { - return CIBRES_MISSING_ID; - } - - crm_verbose("Deleting " XML_CIB_TAG_STATE " (%s)...", id); - - root = get_object_root(XML_CIB_TAG_STATUS, cib); - return delete_cib_object(root, delete_spec); -} - - - - - -int -delete_cib_object(xmlNodePtr parent, xmlNodePtr delete_spec) -{ - const char *object_name = NULL; - const char *object_id = NULL; - xmlNodePtr equiv_node = NULL; - int result = CIBRES_OK; - - if(delete_spec == NULL) { - return CIBRES_FAILED_NOOBJECT; - } else if(parent == NULL) { - return CIBRES_FAILED_NOPARENT; - } - - object_name = delete_spec->name; - object_id = xmlGetProp(delete_spec, XML_ATTR_ID); - - if(object_id == NULL) { - /* placeholder object */ - equiv_node = find_xml_node(parent, object_name); - - } else { - equiv_node = - find_entity(parent, object_name, object_id, FALSE); - - } - - if(equiv_node == NULL) { - return CIBRES_FAILED_NOTEXISTS; - - } else if(delete_spec->children == NULL) { - - /* only leaves are deleted */ - unlink_xml_node(equiv_node); - free_xml(equiv_node); - - } else { - - xml_child_iter( - delete_spec, child, NULL, - - int tmp_result = delete_cib_object(equiv_node, child); - - /* only the first error is likely to be interesting */ - if(tmp_result != CIBRES_OK && result == CIBRES_OK) { - result = tmp_result; - } - ); - } - - return result; -} - -int -add_cib_object(xmlNodePtr parent, xmlNodePtr new_obj) -{ - const char *object_name = NULL; - const char *object_id = NULL; - xmlNodePtr equiv_node = NULL; - - if(new_obj == NULL) { - return CIBRES_FAILED_NOOBJECT; - } else if(parent == NULL) { - return CIBRES_FAILED_NOPARENT; - } - - object_name = new_obj->name; - object_id = xmlGetProp(new_obj, XML_ATTR_ID); - - if(object_id == NULL) { - /* placeholder object */ - equiv_node = find_xml_node(parent, object_name); - - } else { - equiv_node = - find_entity(parent, object_name, object_id, FALSE); - - } - - if(equiv_node != NULL) { - return CIBRES_FAILED_EXISTS; - - } else if(add_node_copy(parent, new_obj) == NULL) { - return CIBRES_FAILED_NODECOPY; - - } - - return CIBRES_OK; -} - - -int -update_cib_object(xmlNodePtr parent, xmlNodePtr new_obj, gboolean force) -{ - const char *replace = NULL; - const char *object_name = NULL; - const char *object_id = NULL; - xmlNodePtr equiv_node = NULL; - int result = CIBRES_OK; - - if(new_obj == NULL) { - return CIBRES_FAILED_NOOBJECT; - - } else if(parent == NULL) { - return CIBRES_FAILED_NOPARENT; - - } - - object_name = new_obj->name; - object_id = xmlGetProp(new_obj, XML_ATTR_ID); - - crm_debug("Processing update to <%s id=%s>", object_name, object_id); - - if(object_id == NULL) { - /* placeholder object */ - equiv_node = find_xml_node(parent, object_name); - - } else { - equiv_node = find_entity(parent, object_name, object_id, FALSE); - } - - if(equiv_node == NULL) { - crm_debug("No node to update, creating %s instead", new_obj->name); - if(parent == NULL) { - crm_warn("Failed to add <%s id=%s> (NULL parent)", - object_name, object_id); - return CIBRES_FAILED_NODECOPY; - - } else if(add_node_copy(parent, new_obj) == NULL) { - crm_warn("Failed to add <%s id=%s>", object_name, object_id); - return CIBRES_FAILED_NODECOPY; - } else { - crm_debug("Added <%s id=%s>", object_name, object_id); - - if(object_id == NULL) { - /* placeholder object */ - equiv_node = find_xml_node(parent, object_name); - - } else { - equiv_node = find_entity(parent, object_name, object_id, FALSE); - } - } - - } else { - crm_verbose("Found node <%s id=%s> to update", object_name, object_id); - - replace = xmlGetProp(new_obj, "replace"); - - if(force == FALSE) { - const char *ts_existing = NULL; - const char *ts_new = NULL; - - /* default to false? - * - * that would mean every node would have to - * carry a timestamp - */ - gboolean is_update = TRUE; - - ts_existing = TSTAMP(equiv_node); - ts_new = TSTAMP(new_obj); - - if(ts_new != NULL && ts_existing != NULL) { - is_update = (strcmp(ts_new, ts_existing) > 0); - } - - if(is_update == FALSE) { - crm_err( - "Ignoring old update to <%s id=\"%s\">" - "(%s vs. %s)", - object_name, object_id, - ts_new, ts_existing); - return CIBRES_FAILED_STALE; - } - } - - if(replace != NULL) { - xmlNodePtr remove = find_xml_node(equiv_node, replace); - if(remove != NULL) { - crm_debug("Replacing node <%s> in <%s>", - replace, equiv_node->name); - xmlUnlinkNode(remove); - remove->doc = NULL; - free_xml(remove); - } - xmlUnsetProp(new_obj, "replace"); - xmlUnsetProp(equiv_node, "replace"); - } - - if(safe_str_eq(XML_CIB_TAG_STATE, object_name)){ - update_node_state(equiv_node, new_obj); - - } else { - copy_in_properties(equiv_node, new_obj); - - } - - crm_debug("Processing children of <%s id=%s>", - object_name, object_id); - - xml_child_iter( - new_obj, a_child, NULL, - int tmp_result = 0; - crm_debug("Updating child <%s id=%s>", - a_child->name, - xmlGetProp(a_child, XML_ATTR_ID)); - - tmp_result = - update_cib_object(equiv_node, a_child, force); - - /* only the first error is likely to be interesting */ - if(tmp_result != CIBRES_OK) { - crm_err("Error updating child <%s id=%s>", - a_child->name, - xmlGetProp(a_child, XML_ATTR_ID)); - - if(result == CIBRES_OK) { - result = tmp_result; - } - } - ); - - } - crm_debug("Finished with <%s id=%s>", object_name, object_id); - - return result; -} - - -void -update_node_state(xmlNodePtr target, xmlNodePtr update) -{ - const char *source = NULL; - xmlAttrPtr prop_iter = NULL; - gboolean any_updates = FALSE; - gboolean clear_stonith = FALSE; - gboolean clear_shutdown = FALSE; - - prop_iter = update->properties; - while(prop_iter != NULL) { - const char *local_prop_name = prop_iter->name; - const char *local_prop_value = - xmlGetProp(update, local_prop_name); - - if(local_prop_name == NULL) { - /* error */ - - } else if(strcmp(local_prop_name, XML_ATTR_ID) == 0) { - - } else if(strcmp(local_prop_name, XML_ATTR_TSTAMP) == 0) { - - } else if(strcmp(local_prop_name, XML_CIB_ATTR_CLEAR_SHUTDOWN) == 0) { - clear_shutdown = TRUE; - - } else if(strcmp(local_prop_name, XML_CIB_ATTR_CLEAR_STONITH) == 0) { - clear_stonith = TRUE; - clear_shutdown = TRUE; - - } else if(strcmp(local_prop_name, "source") == 0) { - source = local_prop_value; - - } else { - any_updates = TRUE; - set_xml_property_copy(target, - local_prop_name, - local_prop_value); - } - - prop_iter = prop_iter->next; - } - - if(clear_shutdown) { - /* unset XML_CIB_ATTR_SHUTDOWN */ - crm_verbose("Clearing %s", XML_CIB_ATTR_SHUTDOWN); - xmlUnsetProp(target, XML_CIB_ATTR_SHUTDOWN); - any_updates = TRUE; - } - - if(clear_stonith) { - /* unset XML_CIB_ATTR_STONITH */ - crm_verbose("Clearing %s", XML_CIB_ATTR_STONITH); - xmlUnsetProp(target, XML_CIB_ATTR_STONITH); - any_updates = TRUE; - } - - xmlUnsetProp(target, XML_CIB_ATTR_CLEAR_STONITH); - xmlUnsetProp(target, XML_CIB_ATTR_CLEAR_SHUTDOWN); - - if(any_updates) { - set_node_tstamp(target); - set_xml_property_copy(target, "source", source); - } - -} diff --git a/crm/cib/io.c b/crm/cib/io.c index a508c239e1..ca671ce173 100644 --- a/crm/cib/io.c +++ b/crm/cib/io.c @@ -1,396 +1,332 @@ -/* $Id: io.c,v 1.3 2004/09/20 14:28:34 andrew Exp $ */ +/* $Id: io.c,v 1.4 2004/12/05 16:14:07 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 const char * local_resource_path[] = { XML_CIB_TAG_STATUS, }; const char * resource_path[] = { XML_CIB_TAG_RESOURCES, }; const char * node_path[] = { XML_CIB_TAG_NODES, }; const char * constraint_path[] = { XML_CIB_TAG_CONSTRAINTS, }; gboolean initialized = FALSE; xmlNodePtr the_cib = NULL; xmlNodePtr node_search = NULL; xmlNodePtr resource_search = NULL; xmlNodePtr constraint_search = NULL; xmlNodePtr status_search = NULL; -/* - * It is the callers responsibility to free both the new CIB (output) - * and the new CIB (input) - */ -xmlNodePtr -createEmptyCib(void) -{ - xmlNodePtr cib_root = NULL, config = NULL, status = NULL; - - cib_root = create_xml_node(NULL, XML_TAG_CIB); - - config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION); - status = create_xml_node(cib_root, XML_CIB_TAG_STATUS); - - set_node_tstamp(cib_root); - set_node_tstamp(config); - set_node_tstamp(status); - - set_xml_property_copy(cib_root, "version", "1"); - set_xml_property_copy(cib_root, "generated", XML_BOOLEAN_TRUE); - - create_xml_node(config, XML_CIB_TAG_CRMCONFIG); - create_xml_node(config, XML_CIB_TAG_NODES); - create_xml_node(config, XML_CIB_TAG_RESOURCES); - create_xml_node(config, XML_CIB_TAG_CONSTRAINTS); - - if (verifyCibXml(cib_root)) { - return cib_root; - } - crm_crit("The generated CIB did not pass integrity testing!!" - " All hope is lost."); - return NULL; -} - -gboolean -verifyCibXml(xmlNodePtr cib) -{ - gboolean is_valid = TRUE; - xmlNodePtr tmp_node = NULL; - - if (cib == NULL) { - crm_warn("XML Buffer was empty."); - return FALSE; - } - - tmp_node = get_object_root(XML_CIB_TAG_NODES, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_RESOURCES, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_STATUS, cib); - if (tmp_node == NULL) is_valid = FALSE; - - tmp_node = get_object_root(XML_CIB_TAG_CRMCONFIG, cib); - if (tmp_node == NULL) is_valid = FALSE; - - /* more integrity tests */ - - return is_valid; -} /* * It is the callers responsibility to free the output of this function */ xmlNodePtr readCibXml(char *buffer) { xmlNodePtr root = string2xml(buffer); if (verifyCibXml(root) == FALSE) { free_xml(root); return createEmptyCib(); } return root; } /* * It is the callers responsibility to free the output of this function */ xmlNodePtr readCibXmlFile(const char *filename) { int s_res = -1; struct stat buf; xmlNodePtr root = NULL; if(filename != NULL) { s_res = stat(filename, &buf); } if (s_res == 0) { FILE *cib_file = fopen(filename, "r"); root = file2xml(cib_file); set_xml_property_copy(root, "generated", XML_BOOLEAN_FALSE); fclose(cib_file); } else { crm_warn("Stat of (%s) failed, file does not exist.", CIB_FILENAME); } if (verifyCibXml(root) == FALSE) { free_xml(root); /* return createEmptyCib(); */ root = NULL; } return root; } /* * The caller should never free the return value */ xmlNodePtr get_the_CIB(void) { return the_cib; } gboolean uninitializeCib(void) { xmlNodePtr tmp_cib = the_cib; if(tmp_cib == NULL) { crm_err("The CIB has already been deallocated."); return FALSE; } initialized = FALSE; the_cib = NULL; node_search = NULL; resource_search = NULL; constraint_search = NULL; status_search = NULL; crm_err("Deallocating the CIB."); free_xml(tmp_cib); crm_err("The CIB has been deallocated."); return TRUE; } /* * This method will not free the old CIB pointer or the new one. * We rely on the caller to have saved a pointer to the old CIB * and to free the old/bad one depending on what is appropriate. */ gboolean initializeCib(xmlNodePtr new_cib) { if (verifyCibXml(new_cib)) { initialized = FALSE; the_cib = new_cib; /* update search paths */ /* not used yet... node_search = get_object_root(XML_CIB_TAG_NODES, new_cib); resource_search = get_object_root(XML_CIB_TAG_RESOURCES, new_cib); constraint_search = get_object_root(XML_CIB_TAG_CONSTRAINTS, new_cib); status_search = get_object_root(XML_CIB_TAG_STATUS, new_cib); */ initialized = TRUE; crm_trace("CIB initialized"); return TRUE; } else { crm_warn("CIB Verification failed"); } return FALSE; } int moveFile(const char *oldname, const char *newname, gboolean backup, char *ext) { /* move 'oldname' to 'newname' by creating a hard link to it * and then removing the original hard link */ int res = 0; struct stat tmp; int s_res = stat(newname, &tmp); if (s_res >= 0) { if (backup == TRUE) { char backname[1024]; static const char *back_ext = "bak"; if (ext != NULL) back_ext = (char*)ext; snprintf(backname, sizeof(backname)-1, "%s.%s", newname, back_ext); moveFile(newname, backname, FALSE, NULL); } else { res = unlink(newname); if (res < 0) { perror("Could not remove the current backup of Cib"); return -1; } } } s_res = stat(oldname, &tmp); if (s_res >= 0) { res = link(oldname, newname); if (res < 0) { perror("Could not create backup of current Cib"); return -2; } res = unlink(oldname); if (res < 0) { perror("Could not unlink the current Cib"); return -3; } } return 0; } int activateCibBuffer(char *buffer, const char *filename) { int result = -1; xmlNodePtr local_cib = NULL; local_cib = readCibXml(buffer); result = activateCibXml(local_cib, filename); return result; } /* * This method will free the old CIB pointer on success and the new one * on failure. */ int activateCibXml(xmlNodePtr new_cib, const char *filename) { int error_code = 0; xmlNodePtr saved_cib = get_the_CIB(); const char *filename_bak = CIB_BACKUP; /* calculate */ if (initializeCib(new_cib) == TRUE) { int res = moveFile(filename, filename_bak, FALSE, NULL); if (res < 0) { crm_info("Could not make backup of the current Cib " "(code: %d)... aborting update.", res); error_code = -1; } else { crm_info("Writing CIB out to %s", CIB_FILENAME); res = write_xml_file(new_cib, CIB_FILENAME); #ifdef DEVEL_CIB_COPY write_xml_file(new_cib, DEVEL_DIR"/cib.xml"); #endif if (res < 0) { /* assume 0 is good */ if (moveFile(filename_bak, filename, FALSE, NULL) < -1) { crm_crit("Could not restore the " "backup of the current Cib " "(code: %d)... panic!", res); error_code = -2; /* should probably exit here */ } else if (initializeCib(saved_cib) == FALSE) { /* oh we are so dead */ crm_crit("Could not re-initialize " "with the old CIB. " "Everything is about to go " "pear shaped"); error_code = -3; } else { crm_crit("Update of Cib failed " "(code: %d)... reverted to " "last known valid version", res); error_code = -4; } } } } else { crm_info("Ignoring invalid or NULL Cib"); error_code = -5; } /* Make sure memory is cleaned up appropriately */ if (error_code != 0) { crm_trace("Freeing new CIB %p", new_cib); free_xml(new_cib); } else { crm_trace("Freeing saved CIB %p", saved_cib); free_xml(saved_cib); } return error_code; } diff --git a/crm/cib/main.c b/crm/cib/main.c index afd6a325da..a6fb95da6d 100644 --- a/crm/cib/main.c +++ b/crm/cib/main.c @@ -1,274 +1,318 @@ -/* $Id: main.c,v 1.2 2004/10/21 18:25:42 andrew Exp $ */ +/* $Id: main.c,v 1.3 2004/12/05 16:14:07 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 #include /* #define REALTIME_SUPPORT 0 */ -#define PID_FILE WORKING_DIR"/cib.pid" -#define DAEMON_LOG LOG_DIR"/cib.log" -#define DAEMON_DEBUG LOG_DIR"/cib.debug" +#define PID_FILE WORKING_DIR"/"CRM_SYSTEM_CIB".pid" +#define DAEMON_LOG LOG_DIR"/"CRM_SYSTEM_CIB".log" +#define DAEMON_DEBUG LOG_DIR"/"CRM_SYSTEM_CIB".debug" GMainLoop* mainloop = NULL; const char* crm_system_name = CRM_SYSTEM_CIB; +const char *cib_our_uname = NULL; void usage(const char* cmd, int exit_status); int init_start(void); +gboolean cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name); void cib_shutdown(int nsig); -gboolean cib_msg_callback(IPC_Channel *client, gpointer user_data); -gboolean process_maincib_message(xmlNodePtr msg, IPC_Channel *sender); +void cib_ha_connection_destroy(gpointer user_data); +gboolean startCib(const char *filename); -#define OPTARGS "skrh" +ll_cluster_t *hb_conn = NULL; + +#define OPTARGS "skrhV" int main(int argc, char ** argv) { - int req_comms_restart = FALSE; - int req_restart = FALSE; - int req_status = FALSE; - int req_stop = FALSE; - int argerr = 0; + int req_comms_restart = FALSE; + int req_restart = FALSE; + int req_status = FALSE; + int req_stop = FALSE; + int argerr = 0; int flag; +#ifdef DEVEL_DIR + mkdir(DEVEL_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); +#endif + /* Redirect messages from glib functions to our handler */ g_log_set_handler(NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG | G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL, cl_glib_msg_handler, NULL); /* and for good measure... */ g_log_set_always_fatal((GLogLevelFlags)0); - cl_log_set_entity(crm_system_name); - cl_log_set_facility(LOG_USER); - cl_log_set_logfile(DAEMON_LOG); + cl_log_set_entity (crm_system_name); + cl_log_set_facility (LOG_USER); + cl_log_set_logfile (DAEMON_LOG); cl_log_set_debugfile(DAEMON_DEBUG); + CL_SIGNAL(DEBUG_INC, alter_debug); CL_SIGNAL(DEBUG_DEC, alter_debug); + CL_SIGNAL(SIGTERM, cib_shutdown); + + client_list = g_hash_table_new(&g_str_hash, &g_str_equal); while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { switch(flag) { + case 'V': + alter_debug(DEBUG_INC); + break; case 's': /* Status */ req_status = TRUE; break; - case 'k': /* Stop (kill) */ - req_stop = TRUE; - break; case 'r': /* Restart */ req_restart = TRUE; break; case 'c': /* Restart */ req_comms_restart = TRUE; break; case 'h': /* Help message */ usage(crm_system_name, LSB_EXIT_OK); break; default: ++argerr; break; } } - + + set_crm_log_level(LOG_TRACE); + + cl_set_corerootdir(DEVEL_DIR); + cl_enable_coredumps(1); + cl_cdtocoredir(); + if (optind > argc) { ++argerr; } if (argerr) { usage(crm_system_name,LSB_EXIT_GENERIC); } /* read local config file */ if (req_status){ return init_status(PID_FILE, crm_system_name); } if (req_stop){ return init_stop(PID_FILE); } if (req_restart) { init_stop(PID_FILE); } return init_start(); } int init_start(void) { - long pid; - ll_cluster_t *hb_fd; - int facility; - IPC_Channel *crm_ch = NULL; + gboolean was_error = FALSE; #ifdef REALTIME_SUPPORT static int crm_realtime = 1; #endif - if ((pid = get_running_pid(PID_FILE, NULL)) > 0) { - crm_crit("already running: [pid %ld].", pid); - exit(LSB_EXIT_OK); - } - - crm_info("Register PID"); - register_pid(PID_FILE, FALSE, cib_shutdown); - - cl_log_set_logfile(DAEMON_LOG); -/* if (crm_verbose()) { */ - cl_log_set_debugfile(DAEMON_DEBUG); -/* } */ - - hb_fd = ll_cluster_new("heartbeat"); - - crm_info("Switching to Heartbeat logger"); - if ((facility = hb_fd->llc_ops->get_logfacility(hb_fd))>0) { - cl_log_set_facility(facility); - } + hb_conn = ll_cluster_new("heartbeat"); + cib_register_ha(hb_conn, CRM_SYSTEM_CIB); if(startCib(CIB_FILENAME) == FALSE){ crm_crit("Cannot start CIB... terminating"); exit(1); } - crm_ch = init_client_ipc_comms(CRM_SYSTEM_CRMD, - subsystem_msg_dispatch, - (void*)process_maincib_message); + was_error = init_server_ipc_comms( + crm_strdup("cib_callback"), cib_client_connect, + default_ipc_connection_destroy); - if(crm_ch != NULL) { - send_hello_message(crm_ch, "-", CRM_SYSTEM_CIB, "0", "1"); + was_error = was_error || init_server_ipc_comms( + crm_strdup("cib_ro"), cib_client_connect, + default_ipc_connection_destroy); - /* Create the mainloop and run it... */ + was_error = was_error || init_server_ipc_comms( + crm_strdup("cib_rw"), cib_client_connect, + default_ipc_connection_destroy); + + if(was_error == FALSE) { + /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); - crm_info("Starting %s", crm_system_name); - + crm_info("Starting %s mainloop", crm_system_name); + #ifdef REALTIME_SUPPORT if (crm_realtime == 1) { cl_enable_realtime(); + } else if (crm_realtime == 0) { cl_disable_realtime(); } cl_make_realtime(SCHED_RR, 5, 64, 64); #endif - g_main_run(mainloop); return_to_orig_privs(); + } else { - crm_err("Connection to CRM not valid, exiting."); + crm_err("Couldnt start all communication channels, exiting."); } - - if (unlink(PID_FILE) == 0) { - crm_info("[%s] stopped", crm_system_name); - } return 0; } -gboolean -process_maincib_message(xmlNodePtr msg, IPC_Channel *sender) -{ - const char *op = get_xml_attr (msg, XML_TAG_OPTIONS, - XML_ATTR_OP, FALSE); - - const char *sys_to = xmlGetProp(msg, XML_ATTR_SYSTO); - - crm_debug("Processing %s message", op); - - if(safe_str_eq(xmlGetProp(msg, XML_ATTR_MSGTYPE), XML_ATTR_REQUEST)) { - crm_info("Message was a response not a request." - " Discarding"); - - } else if (strcmp(sys_to, CRM_SYSTEM_CIB) == 0 - || strcmp(sys_to, CRM_SYSTEM_DCIB) == 0) { - - xmlNodePtr answer = process_cib_message(msg, TRUE); - if (send_xmlipc_message(sender, answer)==FALSE) - crm_warn("Cib answer could not be sent"); - free_xml(answer); - - } else { - crm_warn("Received a message destined for %s by mistake", - sys_to); - return FALSE; - } - - return TRUE; -} - - - void usage(const char* cmd, int exit_status) { FILE* stream; stream = exit_status ? stderr : stdout; fprintf(stream, "usage: %s [-srkh]" "[-c configure file]\n", cmd); /* fprintf(stream, "\t-d\tsets debug level\n"); */ /* fprintf(stream, "\t-s\tgets daemon status\n"); */ /* fprintf(stream, "\t-r\trestarts daemon\n"); */ /* fprintf(stream, "\t-k\tstops daemon\n"); */ /* fprintf(stream, "\t-h\thelp message\n"); */ fflush(stream); exit(exit_status); } + +gboolean +cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name) +{ + int facility; + + if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) { + crm_crit("cluster errmsg function unavailable"); + } + + crm_info("Signing in with Heartbeat"); + if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) { + + crm_err("Cannot sign on with heartbeat: %s", + hb_cluster->llc_ops->errmsg(hb_cluster)); + return FALSE; + } + + /* change the logging facility to the one used by heartbeat daemon */ + crm_info("Switching to Heartbeat logger"); + if (( facility = + hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) { + cl_log_set_facility(facility); + } + crm_verbose("Facility: %d", facility); + + crm_debug("Be informed of CIB messages"); + if (HA_OK != hb_cluster->llc_ops->set_msg_callback( + hb_cluster, T_CIB, cib_peer_callback, hb_cluster)){ + + crm_err("Cannot set msg callback: %s", + hb_cluster->llc_ops->errmsg(hb_cluster)); + return FALSE; + } + + crm_debug("Finding our node name"); + if ((cib_our_uname = + hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) { + crm_err("get_mynodeid() failed"); + return FALSE; + } + crm_info("FSA Hostname: %s", cib_our_uname); + + crm_debug("Adding channel to mainloop"); + G_main_add_IPC_Channel( + G_PRIORITY_HIGH, hb_cluster->llc_ops->ipcchan(hb_cluster), + FALSE, cib_ha_dispatch, hb_cluster /* userdata */, + cib_ha_connection_destroy); + + return TRUE; + +} + +void +cib_ha_connection_destroy(gpointer user_data) +{ +} + void cib_shutdown(int nsig) { - static int shuttingdown = 0; + static int shuttingdown = 0; CL_SIGNAL(nsig, cib_shutdown); if (!shuttingdown) { shuttingdown = 1; } if (mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); } else { exit(LSB_EXIT_OK); } } + +gboolean +startCib(const char *filename) +{ + xmlNodePtr cib = readCibXmlFile(filename); + if (initializeCib(cib)) { + crm_info("CIB Initialization completed successfully"); + } else { + /* free_xml(cib); */ + crm_warn("CIB Initialization failed, " + "starting with an empty default."); + activateCibXml(createEmptyCib(), filename); + } + return TRUE; +} diff --git a/crm/cib/messages.c b/crm/cib/messages.c index 808a12dc2f..0df9ee6fa5 100644 --- a/crm/cib/messages.c +++ b/crm/cib/messages.c @@ -1,461 +1,602 @@ -/* $Id: messages.c,v 1.5 2004/09/28 18:35:37 andrew Exp $ */ +/* $Id: messages.c,v 1.6 2004/12/05 16:14:07 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 -FILE *msg_cib_strm = NULL; - -enum cib_result updateList(xmlNodePtr local_cib, - xmlNodePtr update_command, - xmlNodePtr failed, - int operation, - const char *section); +enum cib_errors updateList( + xmlNodePtr local_cib, xmlNodePtr update_command, xmlNodePtr failed, + int operation, const char *section); xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed); -gboolean replace_section(const char *section, - xmlNodePtr tmpCib, - xmlNodePtr command); +gboolean replace_section( + const char *section, xmlNodePtr tmpCib, xmlNodePtr command); gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib); -gboolean update_results(xmlNodePtr failed, - xmlNodePtr target, - int operation, - int return_code); +gboolean update_results( + xmlNodePtr failed, xmlNodePtr target, int operation, int return_code); -xmlNodePtr -cib_process_request(const char *op, - const xmlNodePtr options, - const xmlNodePtr fragment, - enum cib_result *result) -{ - const char *verbose = NULL; - const char *section = NULL; - const char *id = NULL; - const char *output_section = NULL; - xmlNodePtr failed = NULL; - xmlNodePtr cib_answer = NULL; - - gboolean update_the_cib = FALSE; - int cib_update_op = CIB_OP_NONE; - xmlNodePtr tmpCib; - char *new_value = NULL; - char *old_value = NULL; - int int_value = -1; - char *xml_text = NULL; - - *result = CIBRES_OK; - verbose = xmlGetProp(options, XML_ATTR_VERBOSE); - section = xmlGetProp(options, XML_ATTR_FILTER_TYPE); - id = xmlGetProp(options, XML_ATTR_FILTER_ID); - failed = create_xml_node(NULL, XML_TAG_FAILED); +enum cib_errors cib_update_counter( + xmlNodePtr xml_obj, const char *field, gboolean reset); -#ifdef MSG_LOG - if(msg_cib_strm == NULL) { - msg_cib_strm = fopen(DEVEL_DIR"/cib.log", "w"); - } - fprintf(msg_cib_strm, "\n====================\n"); - fprintf(msg_cib_strm, "[Input %s]\t%s\n", op, dump_xml_formatted(fragment)); - fflush(msg_cib_strm); -#endif - crm_debug("[cib] Processing \"%s\" event", op); - +enum cib_errors +cib_process_default( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + enum cib_errors result = cib_ok; + crm_debug("Processing \"%s\" event", op); + if(answer != NULL) *answer = NULL; + if(op == NULL) { - *result = CIBRES_FAILED; + result = cib_operation; crm_err("No operation specified\n"); - } else if(strcmp("noop", op) == 0) { + } else if(strcmp(CRM_OP_NOOP, op) == 0) { ; - - } else if(strcmp(CRM_OP_QUIT, op) == 0) { - crm_warn( - "The CRMd has asked us to exit... complying"); - exit(0); - - } else if (strcmp(CRM_OP_PING, op) == 0) { - cib_answer = - createPingAnswerFragment(CRM_SYSTEM_CIB, "ok"); - - } else if (strcmp(CRM_OP_BUMP, op) == 0) { - tmpCib = get_cib_copy(); - crm_verbose("Handling a %s for section=%s of the cib", - CRM_OP_BUMP, section); - - /* modify the timestamp */ - set_node_tstamp(tmpCib); - old_value = xmlGetProp(get_the_CIB(), XML_ATTR_GENERATION); - - if(old_value != NULL) { - crm_malloc(new_value, 128*(sizeof(char))); - if(new_value != NULL) { - int_value = atoi(old_value); - sprintf(new_value, "%d", ++int_value); - } - - } else { - new_value = crm_strdup("0"); - } - crm_trace("Generation %d(%s)->%s", - int_value, crm_str(old_value), crm_str(new_value)); - - set_xml_property_copy(tmpCib, XML_ATTR_GENERATION, new_value); - crm_free(new_value); + } 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, xmlNodePtr input, + xmlNodePtr *answer) +{ + enum cib_errors result = cib_ok; + crm_debug("Processing \"%s\" event", op); + + cib_pre_notify(op, NULL, NULL, get_the_CIB()); + 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, xmlNodePtr input, + xmlNodePtr *answer) +{ + enum cib_errors result = cib_ok; + crm_debug("Processing \"%s\" event", op); + + cib_pre_notify(op, NULL, NULL, NULL); + if(safe_str_eq(op, CRM_OP_CIB_MASTER)) { + crm_info("We are now in R/W mode"); + cib_is_master = TRUE; + } else { + crm_info("We are now in R/O mode"); + cib_is_master = FALSE; + } + cib_post_notify(op, NULL, NULL, NULL, result, NULL); + + return result; +} + +enum cib_errors +cib_process_ping( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + enum cib_errors result = cib_ok; + crm_debug("Processing \"%s\" event", op); + if(answer != NULL) *answer = NULL; + + *answer = createPingAnswerFragment(CRM_SYSTEM_CIB, "ok"); + return result; +} + + +enum cib_errors +cib_process_query( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + xmlNodePtr cib = NULL; + xmlNodePtr obj_root = NULL; + enum cib_errors result = cib_ok; + + if(answer != NULL) *answer = NULL; + + crm_debug("Processing \"%s\" event", op); + crm_verbose("Handling a query for section=%s of the cib", section); + + *answer = create_xml_node(NULL, XML_TAG_FRAGMENT); + set_xml_property_copy(*answer, XML_ATTR_SECTION, section); + + if (safe_str_eq("all", section)) { + section = NULL; + } + + obj_root = get_object_root(section, get_the_CIB()); + + if(obj_root == NULL) { + result = cib_NOTEXISTS; + + } else if(obj_root == get_the_CIB()) { + add_node_copy(*answer, obj_root); + + } else { + cib = create_xml_node(*answer, XML_TAG_CIB); + add_node_copy(cib, obj_root); + copy_in_properties(cib, get_the_CIB()); + } + + return result; +} + +enum cib_errors +cib_process_erase( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + crm_debug("Processing \"%s\" event", op); + if(answer != NULL) *answer = NULL; + + crm_err("Op %s is not currently supported", op); + return cib_NOTSUPPORTED; +} + +enum cib_errors +cib_process_bump( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + xmlNodePtr tmpCib = NULL; + enum cib_errors result = cib_ok; + + crm_debug("Processing \"%s\" event", op); + if(answer != NULL) *answer = NULL; + + tmpCib = copy_xml_node_recursive(the_cib); + + cib_pre_notify(op, tmpCib->name, NULL, NULL); + + crm_verbose("Handling a %s for section=%s of the cib", + CRM_OP_CIB_BUMP, section); + + cib_update_counter(tmpCib, XML_ATTR_GENERATION, FALSE); + cib_update_counter(tmpCib, XML_ATTR_NUMUPDATES, TRUE); - if(activateCibXml(tmpCib, CIB_FILENAME) >= 0) { - verbose = XML_BOOLEAN_TRUE; - } else { - *result = CIBRES_FAILED; - } + if(activateCibXml(tmpCib, CIB_FILENAME) < 0) { + result = cib_ACTIVATION; + } + + cib_post_notify(op, tmpCib->name, NULL, NULL, result, get_the_CIB()); + *answer = createCibFragmentAnswer(NULL, NULL); + + return result; +} + +enum cib_errors +cib_update_counter(xmlNodePtr 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) { + old_value = xmlGetProp(xml_obj, field); + } + if(old_value != NULL) { + crm_malloc(new_value, 128*(sizeof(char))); + int_value = atoi(old_value); + sprintf(new_value, "%d", ++int_value); + } else { + new_value = crm_strdup("0"); + } + + crm_trace("%s %d(%s)->%s", + field, int_value, crm_str(old_value), crm_str(new_value)); + set_xml_property_copy(xml_obj, field, new_value); + crm_free(new_value); + + return cib_ok; +} + +enum cib_errors +cib_process_replace( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + gboolean verbose = FALSE; + xmlNodePtr tmpCib = NULL; + xmlNodePtr cib_update = NULL; + xmlNodePtr the_update = NULL; + const char *section_name = section; + enum cib_errors result = cib_ok; + + crm_debug("Processing \"%s\" event", op); + if(answer != NULL) *answer = NULL; + + if (options & cib_verbose) { + verbose = TRUE; + } + if(safe_str_eq("all", section)) { + section = NULL; + } + + cib_update = find_xml_node(input, XML_TAG_CIB); + + if (cib_update == NULL) { + result = cib_NOOBJECT; - } else if (strcmp(CRM_OP_RETRIVE_CIB, op) == 0 - || strcmp(CRM_OP_QUERY, op) == 0) { - crm_verbose("Handling a query for section=%s of the cib", - section); - - /* grab the whole section by forcing a pick-up of - * the relevant section before returning - */ - verbose = XML_BOOLEAN_TRUE; + } else if (section == NULL) { + tmpCib = copy_xml_node_recursive(cib_update); + the_update = cib_update; + section_name = tmpCib->name; - } else if (strcmp(CRM_OP_ERASE, op) == 0) { + } else { + tmpCib = copy_xml_node_recursive(get_the_CIB()); + replace_section(section, tmpCib, input); + the_update = get_object_root(section, cib_update); + } + + cib_pre_notify(op, section_name, NULL, the_update); + cib_update_counter(tmpCib, XML_ATTR_NUMUPDATES, FALSE); + + if (result == cib_ok && activateCibXml(tmpCib, CIB_FILENAME) < 0) { + crm_warn("Replacment of section=%s failed", section); + result = cib_ACTIVATION; + } + + if (verbose || result != cib_ok) { + *answer = createCibFragmentAnswer(section, NULL); + } + + cib_post_notify(op, section_name, NULL, the_update, + result, get_object_root(section, get_the_CIB())); + + return result; +} + +enum cib_errors +cib_process_modify( + const char *op, int options, const char *section, xmlNodePtr input, + xmlNodePtr *answer) +{ + gboolean verbose = FALSE; + enum cib_errors result = cib_ok; + const char *section_name = section; + + xmlNodePtr failed = NULL; + xmlNodePtr cib_update = NULL; + xmlNodePtr the_update = NULL; + + int cib_update_op = CIB_OP_NONE; + + xmlNodePtr tmpCib = NULL; + + char *xml_text = NULL; - crm_err("Op %s is not currently supported", op); - *result = CIBRES_FAILED_NOTSUPPORTED; + crm_debug("Processing \"%s\" event", op); - } else if (strcmp(CRM_OP_CREATE, op) == 0) { - update_the_cib = TRUE; + failed = create_xml_node(NULL, XML_TAG_FAILED); + + if (strcmp(CRM_OP_CIB_CREATE, op) == 0) { cib_update_op = CIB_OP_ADD; - } else if (strcmp(CRM_OP_UPDATE, op) == 0 + } else if (strcmp(CRM_OP_CIB_UPDATE, op) == 0 || strcmp(CRM_OP_JOINACK, op) == 0 || strcmp(CRM_OP_SHUTDOWN_REQ, op) == 0) { - update_the_cib = TRUE; cib_update_op = CIB_OP_MODIFY; - } else if (strcmp(CRM_OP_DELETE, op) == 0) { - update_the_cib = TRUE; + } else if (strcmp(CRM_OP_CIB_DELETE, op) == 0) { cib_update_op = CIB_OP_DELETE; - - } else if (strcmp(CRM_OP_REPLACE, op) == 0) { - crm_verbose("Replacing section=%s of the cib", section); - - if (section == NULL - || strlen(section) == 0 - || strcmp("all", section) == 0) { - tmpCib = copy_xml_node_recursive( - find_xml_node(fragment, XML_TAG_CIB)); - - } else { - tmpCib = copy_xml_node_recursive(get_the_CIB()); - replace_section(section, tmpCib, fragment); - } - - /*if(check_generation(cib_updates, tmpCib) == FALSE) - *result = "discarded old update"; - else */ - if (activateCibXml(tmpCib, CIB_FILENAME) < 0) - *result = CIBRES_FAILED; + } else { - *result = CIBRES_FAILED_NOTSUPPORTED; - crm_err("Action [%s] is not supported by the CIB", op); + crm_err("Incorrect request handler invoked for \"%s\" op", + crm_str(op)); + return cib_operation; } - - if (update_the_cib) { - tmpCib = copy_xml_node_recursive(get_the_CIB()); - crm_verbose("Updating section=%s of the cib (op=%s)", - section, op); + result = cib_ok; + if (options & cib_verbose) { + verbose = TRUE; + } + if(safe_str_eq("all", section)) { + section = NULL; + } - /* should we be doing this? */ - /* do logging */ + if(input == NULL) { + crm_err("Cannot perform modification with no data"); + return cib_NOOBJECT; + } + + tmpCib = copy_xml_node_recursive(get_the_CIB()); + cib_update = find_xml_node(input, XML_TAG_CIB); + + /* should we be doing this? */ + /* do logging */ - /* make changes to a temp copy then activate */ - if(section == NULL) { - crm_err("No section specified in %s", - XML_ATTR_FILTER_TYPE); - *result = CIBRES_FAILED_NOSECTION; - - } else if(strcmp("all", section) == 0) { - /* order is no longer important here */ - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_NODES); - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_RESOURCES); - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_CONSTRAINTS); - updateList(tmpCib, fragment, failed, cib_update_op, - XML_CIB_TAG_STATUS); - } else { - *result = updateList(tmpCib, fragment, failed, - cib_update_op, section); + /* make changes to a temp copy then activate */ + if(section == NULL) { + /* order is no longer important here */ + section_name = tmpCib->name; + the_update = cib_update; + cib_pre_notify(op, tmpCib->name, NULL, the_update); + + result = updateList(tmpCib, input, failed, cib_update_op, + XML_CIB_TAG_NODES); + + if(result == cib_ok) { + result = updateList( + tmpCib, input, failed, + cib_update_op, XML_CIB_TAG_RESOURCES); + } + if(result == cib_ok) { + result = updateList( + tmpCib, input, failed, + cib_update_op, XML_CIB_TAG_CONSTRAINTS); + } + if(result == cib_ok) { + result = updateList(tmpCib, input, failed, + cib_update_op, XML_CIB_TAG_STATUS); } - crm_trace("Activating temporary CIB"); - - fprintf(msg_cib_strm, "[Activating CIB (%s - %s)]\t%s\n", op, - cib_error2string(*result), - dump_xml_formatted(tmpCib)); - /* if(check_generation(cib_updates, tmpCib) == FALSE) */ -/* status = "discarded old update"; */ -/* else */ - if (activateCibXml(tmpCib, CIB_FILENAME) < 0) { - *result = CIBRES_FAILED_ACTIVATION; + } else { + the_update = get_object_root(section, cib_update); - } else if (failed->children != NULL) { - *result = CIBRES_FAILED; - crm_xml_info(failed, "CIB Update failures"); - - xml_text = dump_xml_formatted(failed); - fprintf(msg_cib_strm, "[CIB %s failures]\t%s\n", - op, xml_text); - crm_free(xml_text); + cib_pre_notify(op, section, NULL, the_update); + result = updateList(tmpCib, input, failed, + cib_update_op, section); + } + + crm_trace("Activating temporary CIB"); + cib_update_counter(tmpCib, XML_ATTR_NUMUPDATES, FALSE); + + if (result == cib_ok && activateCibXml(tmpCib, CIB_FILENAME) < 0) { + result = cib_ACTIVATION; + } else if (result != cib_ok || failed->children != NULL) { + if(result == cib_ok) { + result = cib_unknown; } - xml_text = dump_xml_formatted(get_the_CIB()); - fprintf(msg_cib_strm, "[New CIB (%s - %s)]\t%s\n", op, - cib_error2string(*result), xml_text); - crm_free(xml_text); - fflush(msg_cib_strm); + crm_xml_info(failed, "CIB Update failures"); - crm_verbose("CIB update status: %d", *result); + xml_text = dump_xml_formatted(failed); + fprintf(msg_cib_strm, "[CIB %s failures]\t%s\n", + op, xml_text); + crm_free(xml_text); } - - output_section = section; - - if (failed->children != NULL || *result != CIBRES_OK) { - cib_answer = createCibFragmentAnswer(NULL /*"all"*/, failed); - - } else if (verbose != NULL && strcmp(XML_BOOLEAN_TRUE, verbose) == 0) { - cib_answer = createCibFragmentAnswer(output_section, failed); + if (verbose || failed->children != NULL || result != cib_ok) { + *answer = createCibFragmentAnswer(section, failed); } - free_xml(failed); + cib_post_notify(op, section_name, NULL, the_update, + result, get_object_root(section, get_the_CIB())); -#ifdef MSG_LOG - fprintf(msg_cib_strm, "[Reply (%s:%s)]\t%s\n", - op, cib_error2string(*result), - dump_xml_formatted(cib_answer)); - fflush(msg_cib_strm); -#endif + free_xml(failed); - return cib_answer; + return result; } + gboolean replace_section(const char *section, xmlNodePtr tmpCib, xmlNodePtr fragment) { xmlNodePtr parent = NULL, cib_updates = NULL, new_section = NULL, old_section = NULL; cib_updates = find_xml_node(fragment, XML_TAG_CIB); /* find the old and new versions of the section */ new_section = get_object_root(section, cib_updates); old_section = get_object_root(section, tmpCib); - + if(old_section == NULL) { crm_err("The CIB is corrupt, cannot replace missing section %s", section); return FALSE; } else if(new_section == NULL) { crm_err("The CIB is corrupt, cannot set section %s to nothing", section); return FALSE; } parent = old_section->parent; /* unlink and free the old one */ unlink_xml_node(old_section); free_xml(old_section); /* add the new copy */ add_node_copy(parent, new_section); - + return TRUE; } -enum cib_result +enum cib_errors updateList(xmlNodePtr local_cib, xmlNodePtr update_fragment, xmlNodePtr failed, int operation, const char *section) { + int rc = cib_ok; xmlNodePtr this_section = get_object_root(section, local_cib); xmlNodePtr cib_updates = NULL; xmlNodePtr xml_section = NULL; cib_updates = find_xml_node(update_fragment, XML_TAG_CIB); xml_section = get_object_root(section, cib_updates); if (section == NULL || xml_section == NULL) { crm_err("Section %s not found in message." " CIB update is corrupt, ignoring.", crm_str(section)); - return CIBRES_FAILED_NOSECTION; + return cib_NOSECTION; } if(CIB_OP_NONE > operation > CIB_OP_MAX) { crm_err("Invalid operation on section %s", crm_str(section)); - return CIBRES_FAILED; + return cib_operation; } set_node_tstamp(this_section); xml_child_iter( xml_section, a_child, NULL, - crm_debug("%s to section %s with <%s id=%s>", - cib_op2string(operation), section, a_child->name, xmlGetProp(a_child, "id")); - + rc = cib_ok; if(operation == CIB_OP_DELETE) { - update_results( - failed, a_child, operation, - delete_cib_object(this_section, a_child)); + rc = delete_cib_object(this_section, a_child); + update_results(failed, a_child, operation, rc); } else if(operation == CIB_OP_MODIFY) { - - update_results( - failed, a_child, operation, - update_cib_object(this_section, a_child, FALSE)); + rc = update_cib_object(this_section, a_child, FALSE); + update_results(failed, a_child, operation, rc); } else { - update_results( - failed, a_child, operation, - add_cib_object(this_section, a_child)); + rc = add_cib_object(this_section, a_child); + update_results(failed, a_child, operation, rc); } - ); - if (failed->children != NULL) { - return CIBRES_FAILED; - } else { - return CIBRES_OK; + if(rc == cib_ok && failed->children != NULL) { + rc = cib_unknown; } + return rc; } xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed) { - xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); + xmlNodePtr cib = NULL; + xmlNodePtr fragment = NULL; - set_xml_property_copy(fragment, XML_ATTR_SECTION, section); + fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); if (section == NULL || strlen(section) == 0 || strcmp("all", section) == 0) { - add_node_copy(fragment, get_the_CIB()); + + cib = get_the_CIB(); + if(cib != NULL) { + add_node_copy(fragment, get_the_CIB()); + } } else { - xmlNodePtr cib = create_xml_node(fragment, XML_TAG_CIB); - add_node_copy(cib, get_object_root(section, get_the_CIB())); - copy_in_properties(cib, get_the_CIB()); - + xmlNodePtr 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 && failed->children != NULL) { add_node_copy(fragment, failed); } + set_xml_property_copy(fragment, XML_ATTR_SECTION, section); return fragment; } gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib) { - if(compare_cib_generation(newCib, oldCib) >= 0) { + 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( xmlNodePtr failed, xmlNodePtr target, int operation, int return_code) { gboolean was_error = FALSE; const char *error_msg = NULL; const char *operation_msg = NULL; xmlNodePtr xml_node = NULL; operation_msg = cib_op2string(operation); - if (return_code != CIBRES_OK) { + 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); set_xml_property_copy( xml_node, XML_FAILCIB_ATTR_ID, ID(target)); set_xml_property_copy( xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target)); set_xml_property_copy( xml_node, XML_FAILCIB_ATTR_OP, operation_msg); set_xml_property_copy( xml_node, XML_FAILCIB_ATTR_REASON, error_msg); crm_debug("Action %s failed: %s (cde=%d)", operation_msg, error_msg, return_code); } else { crm_debug("CIB %s passed", operation_msg); } return was_error; } diff --git a/crm/cib/notify.c b/crm/cib/notify.c new file mode 100644 index 0000000000..401ca6e68f --- /dev/null +++ b/crm/cib/notify.c @@ -0,0 +1,117 @@ +/* $Id: notify.c,v 1.1 2004/12/05 16:14:07 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 + +FILE *msg_cib_strm = NULL; + +void +cib_pre_notify( + const char *op, const char *type, const char *id, xmlNodePtr update) +{ + char *xml_text = NULL; + + if(update == NULL) { + crm_verbose("Performing oeration %s (on section=%s)", op, type); + + } else { + crm_verbose("Performing %s on <%s %s%s>", + op, type, id?"id=":"", id); + } + + if(msg_cib_strm == NULL) { + msg_cib_strm = fopen(DEVEL_DIR"/cib.log", "w"); + } + + xml_text = dump_xml_formatted(update); + fprintf(msg_cib_strm, "[Request (%s : %s : %s)]\t%s\n", + op, crm_str(type), crm_str(id), xml_text); + crm_free(xml_text); + + xml_text = dump_xml_formatted(get_the_CIB()); + fprintf(msg_cib_strm, "[CIB before %s]\t%s\n", op, xml_text); + crm_free(xml_text); + + fflush(msg_cib_strm); +} + +void +cib_post_notify( + const char *op, const char *type, const char *id, xmlNodePtr update, + enum cib_errors result, xmlNodePtr new_obj) +{ + char *xml_text = NULL; + + if(update == NULL) { + if(result == cib_ok) { + crm_verbose("Operation %s (on section=%s) completed", + op, type); + + } else { + crm_warn("Operation %s (on section=%s) FAILED: (%d) %s", + op, type, result, cib_error2string(result)); + } + + } else { + if(result == cib_ok) { + crm_verbose("Completed %s of <%s %s%s>", + op, type, id?"id=":"", id); + + } else { + crm_warn("%s of <%s %s%s> FAILED: %s", op, type, + id?"id=":"", id, cib_error2string(result)); + } + } + + if(msg_cib_strm == NULL) { + msg_cib_strm = fopen(DEVEL_DIR"/cib.log", "w"); + } + + if(new_obj != NULL) { + xml_text = dump_xml_formatted(new_obj); + } + + fprintf(msg_cib_strm, "[Response (%s : %s : %s)]\t%s\n%s\n", + op, crm_str(type), crm_str(id), + cib_error2string(result), xml_text); + crm_free(xml_text); + + fflush(msg_cib_strm); +} diff --git a/crm/cib/cibmessages.h b/crm/cib/notify.h similarity index 64% copy from crm/cib/cibmessages.h copy to crm/cib/notify.h index 110c8dcc6c..c006c19a97 100644 --- a/crm/cib/cibmessages.h +++ b/crm/cib/notify.h @@ -1,32 +1,38 @@ -/* $Id: cibmessages.h,v 1.4 2004/03/24 12:08:04 andrew Exp $ */ +/* $Id: notify.h,v 1.1 2004/12/05 16:14:07 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 */ -#ifndef CIB_MESSAGES__H -#define CIB_MESSAGES__H -extern xmlNodePtr cib_process_request(const char *op, - const xmlNodePtr options, - const xmlNodePtr fragment, - enum cib_result *result); +#include +#include -extern xmlNodePtr createCibRequest(gboolean isLocal, const char *operation, - const char *section, const char *verbose, - xmlNodePtr data); +#include + +#include +#include + +extern FILE *msg_cib_strm; + + +void cib_pre_notify( + const char *op, const char *type, const char *id, xmlNodePtr update); + +void cib_post_notify( + const char *op, const char *type, const char *id, xmlNodePtr update, + enum cib_errors result, xmlNodePtr new_obj); -#endif diff --git a/crm/cib/primatives.c b/crm/cib/primatives.c index bc2e3b8f09..d01557eae0 100644 --- a/crm/cib/primatives.c +++ b/crm/cib/primatives.c @@ -1,571 +1,591 @@ -/* $Id: primatives.c,v 1.2 2004/09/21 19:40:18 andrew Exp $ */ +/* $Id: primatives.c,v 1.3 2004/12/05 16:14:07 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 /* * In case of confusion, this is the memory management policy for * all functions in this file. * * All add/modify functions use copies of supplied data. * It is therefore appropriate that the callers free the supplied data * at some point after the function has finished. * * All delete functions will handle the freeing of deleted data * but not the function arguments. */ void update_node_state(xmlNodePtr existing_node, xmlNodePtr update); /* --- Resource */ int addResource(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Adding " XML_CIB_TAG_RESOURCE " (%s)...", id); root = get_object_root(XML_CIB_TAG_RESOURCES, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findResource(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; root = get_object_root(XML_CIB_TAG_RESOURCES, cib); ret = find_entity(root, XML_CIB_TAG_RESOURCE, id, FALSE); return ret; } int updateResource(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Updating " XML_CIB_TAG_RESOURCE " (%s)...", id); root = get_object_root(XML_CIB_TAG_RESOURCES, cib); return update_cib_object(root, anXmlNode, FALSE); } int delResource(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); xmlNodePtr root; if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } crm_verbose("Deleting " XML_CIB_TAG_RESOURCE " (%s)...", id); root = get_object_root(XML_CIB_TAG_RESOURCES, cib); return delete_cib_object(root, delete_spec); } /* --- Constraint */ int addConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Adding " XML_CIB_TAG_CONSTRAINT " (%s)...", id); root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findConstraint(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); ret = find_entity(root, XML_CIB_TAG_CONSTRAINT, id, FALSE); return ret; } int updateConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Updating " XML_CIB_TAG_CONSTRAINT " (%s)...", id); root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return update_cib_object(root, anXmlNode, FALSE); } int delConstraint(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); xmlNodePtr root; if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } crm_verbose("Deleting " XML_CIB_TAG_CONSTRAINT " (%s)...", id); root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return delete_cib_object(root, delete_spec); } /* --- HaNode */ int addHaNode(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Adding " XML_CIB_TAG_NODE " (%s)...", id); root = get_object_root(XML_CIB_TAG_NODES, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findHaNode(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; root = get_object_root(XML_CIB_TAG_NODES, cib); ret = find_entity(root, XML_CIB_TAG_NODE, id, FALSE); return ret; } int updateHaNode(xmlNodePtr cib, cibHaNode *anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Updating " XML_CIB_TAG_NODE " (%s)...", id); root = get_object_root(XML_CIB_TAG_NODES, cib); return update_cib_object(root, anXmlNode, FALSE); } int delHaNode(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); xmlNodePtr root; if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } crm_verbose("Deleting " XML_CIB_TAG_NODE " (%s)...", id); root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return delete_cib_object(root, delete_spec); } /* --- Status */ int addStatus(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Adding " XML_CIB_TAG_NODE " (%s)...", id); root = get_object_root(XML_CIB_TAG_STATUS, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findStatus(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; root = get_object_root(XML_CIB_TAG_STATUS, cib); ret = find_entity(root, XML_CIB_TAG_STATE, id, FALSE); return ret; } int updateStatus(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } crm_verbose("Updating " XML_CIB_TAG_NODE " (%s)...", id); root = get_object_root(XML_CIB_TAG_STATUS, cib); return update_cib_object(root, anXmlNode, FALSE); } int delStatus(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); xmlNodePtr root; if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } crm_verbose("Deleting " XML_CIB_TAG_STATE " (%s)...", id); root = get_object_root(XML_CIB_TAG_STATUS, cib); return delete_cib_object(root, delete_spec); } - - - - int delete_cib_object(xmlNodePtr parent, xmlNodePtr delete_spec) { const char *object_name = NULL; const char *object_id = NULL; xmlNodePtr equiv_node = NULL; - int result = CIBRES_OK; + int result = cib_ok; + if(delete_spec != NULL) { + object_name = delete_spec->name; + } + object_id = xmlGetProp(delete_spec, XML_ATTR_ID); + cib_pre_notify(CRM_OP_CIB_DELETE, object_name, object_id, delete_spec); + if(delete_spec == NULL) { - return CIBRES_FAILED_NOOBJECT; + result = cib_NOOBJECT; + } else if(parent == NULL) { - return CIBRES_FAILED_NOPARENT; - } + result = cib_NOPARENT; - object_name = delete_spec->name; - object_id = xmlGetProp(delete_spec, XML_ATTR_ID); - - if(object_id == NULL) { + } else if(object_id == NULL) { /* placeholder object */ equiv_node = find_xml_node(parent, object_name); } else { - equiv_node = - find_entity(parent, object_name, object_id, FALSE); - + equiv_node = find_entity( + parent, object_name, object_id, FALSE); } - if(equiv_node == NULL) { - return CIBRES_FAILED_NOTEXISTS; + if(result != cib_ok) { + ; /* nothing */ + + } else if(equiv_node == NULL) { + result = cib_NOTEXISTS; } else if(delete_spec->children == NULL) { - /* only leaves are deleted */ unlink_xml_node(equiv_node); free_xml(equiv_node); + equiv_node = NULL; } else { xml_child_iter( delete_spec, child, NULL, int tmp_result = delete_cib_object(equiv_node, child); /* only the first error is likely to be interesting */ - if(tmp_result != CIBRES_OK && result == CIBRES_OK) { + if(tmp_result != cib_ok && result == cib_ok) { result = tmp_result; } ); } + cib_post_notify(CRM_OP_CIB_DELETE, delete_spec->name, object_id, + delete_spec, result, equiv_node); + return result; } int add_cib_object(xmlNodePtr parent, xmlNodePtr new_obj) { + enum cib_errors result = cib_ok; const char *object_name = NULL; const char *object_id = NULL; xmlNodePtr equiv_node = NULL; + if(new_obj != NULL) { + object_name = new_obj->name; + } + object_id = xmlGetProp(new_obj, XML_ATTR_ID); + cib_pre_notify(CRM_OP_CIB_CREATE, object_name, object_id, new_obj); + if(new_obj == NULL) { - return CIBRES_FAILED_NOOBJECT; + result = cib_NOOBJECT; + } else if(parent == NULL) { - return CIBRES_FAILED_NOPARENT; - } + result = cib_NOPARENT; - object_name = new_obj->name; - object_id = xmlGetProp(new_obj, XML_ATTR_ID); - - if(object_id == NULL) { + } else if(object_id == NULL) { /* placeholder object */ equiv_node = find_xml_node(parent, object_name); } else { - equiv_node = - find_entity(parent, object_name, object_id, FALSE); - + equiv_node = find_entity( + parent, object_name, object_id, FALSE); } - - if(equiv_node != NULL) { - return CIBRES_FAILED_EXISTS; + + if(result != cib_ok) { + ; /* do nothing */ + + } else if(equiv_node != NULL) { + result = cib_EXISTS; } else if(add_node_copy(parent, new_obj) == NULL) { - return CIBRES_FAILED_NODECOPY; + result = cib_NODECOPY; } - return CIBRES_OK; + cib_post_notify(CRM_OP_CIB_CREATE, object_name, object_id, + new_obj, result, new_obj); + + return cib_ok; } int update_cib_object(xmlNodePtr parent, xmlNodePtr new_obj, gboolean force) { const char *replace = NULL; const char *object_name = NULL; const char *object_id = NULL; xmlNodePtr equiv_node = NULL; - int result = CIBRES_OK; + int result = cib_ok; - if(new_obj == NULL) { - return CIBRES_FAILED_NOOBJECT; - - } else if(parent == NULL) { - return CIBRES_FAILED_NOPARENT; - + if(new_obj != NULL) { + object_name = new_obj->name; } - - object_name = new_obj->name; object_id = xmlGetProp(new_obj, XML_ATTR_ID); + cib_pre_notify(CRM_OP_CIB_UPDATE, object_name, object_id, + new_obj); + + if(new_obj == NULL) { + result = cib_NOOBJECT; - crm_debug("Processing update to <%s id=%s>", object_name, object_id); + } else if(parent == NULL) { + result = cib_NOPARENT; - if(object_id == NULL) { + } else if(object_id == NULL) { /* placeholder object */ equiv_node = find_xml_node(parent, object_name); } else { equiv_node = find_entity(parent, object_name, object_id, FALSE); } - - if(equiv_node == NULL) { + + if(result != cib_ok) { + ; /* nothing */ + + } else if(equiv_node == NULL) { crm_debug("No node to update, creating %s instead", new_obj->name); if(parent == NULL) { crm_warn("Failed to add <%s id=%s> (NULL parent)", object_name, object_id); - return CIBRES_FAILED_NODECOPY; + result = cib_NODECOPY; } else if(add_node_copy(parent, new_obj) == NULL) { crm_warn("Failed to add <%s id=%s>", object_name, object_id); - return CIBRES_FAILED_NODECOPY; + result = cib_NODECOPY; } else { crm_debug("Added <%s id=%s>", object_name, object_id); if(object_id == NULL) { /* placeholder object */ equiv_node = find_xml_node(parent, object_name); } else { equiv_node = find_entity(parent, object_name, object_id, FALSE); } } } else { crm_verbose("Found node <%s id=%s> to update", object_name, object_id); replace = xmlGetProp(new_obj, "replace"); if(replace != NULL) { xmlNodePtr remove = find_xml_node(equiv_node, replace); if(remove != NULL) { crm_debug("Replacing node <%s> in <%s>", replace, equiv_node->name); xmlUnlinkNode(remove); remove->doc = NULL; free_xml(remove); } xmlUnsetProp(new_obj, "replace"); xmlUnsetProp(equiv_node, "replace"); } if(safe_str_eq(XML_CIB_TAG_STATE, object_name)){ update_node_state(equiv_node, new_obj); } else { copy_in_properties(equiv_node, new_obj); } crm_debug("Processing children of <%s id=%s>", object_name, object_id); xml_child_iter( new_obj, a_child, NULL, int tmp_result = 0; crm_debug("Updating child <%s id=%s>", a_child->name, xmlGetProp(a_child, XML_ATTR_ID)); tmp_result = update_cib_object(equiv_node, a_child, force); /* only the first error is likely to be interesting */ - if(tmp_result != CIBRES_OK) { + if(tmp_result != cib_ok) { crm_err("Error updating child <%s id=%s>", a_child->name, xmlGetProp(a_child, XML_ATTR_ID)); - if(result == CIBRES_OK) { + if(result == cib_ok) { result = tmp_result; } } ); } crm_debug("Finished with <%s id=%s>", object_name, object_id); + cib_post_notify(CRM_OP_CIB_UPDATE, object_name, object_id, + new_obj, result, equiv_node); + return result; } void update_node_state(xmlNodePtr target, xmlNodePtr update) { const char *source = NULL; xmlAttrPtr prop_iter = NULL; gboolean any_updates = FALSE; gboolean clear_stonith = FALSE; gboolean clear_shutdown = FALSE; prop_iter = update->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(update, local_prop_name); if(local_prop_name == NULL) { /* error */ } else if(strcmp(local_prop_name, XML_ATTR_ID) == 0) { } else if(strcmp(local_prop_name, XML_ATTR_TSTAMP) == 0) { } else if(strcmp(local_prop_name, XML_CIB_ATTR_CLEAR_SHUTDOWN) == 0) { clear_shutdown = TRUE; } else if(strcmp(local_prop_name, XML_CIB_ATTR_CLEAR_STONITH) == 0) { clear_stonith = TRUE; clear_shutdown = TRUE; } else if(strcmp(local_prop_name, "source") == 0) { source = local_prop_value; } else { any_updates = TRUE; set_xml_property_copy(target, local_prop_name, local_prop_value); } prop_iter = prop_iter->next; } if(clear_shutdown) { /* unset XML_CIB_ATTR_SHUTDOWN */ crm_verbose("Clearing %s", XML_CIB_ATTR_SHUTDOWN); xmlUnsetProp(target, XML_CIB_ATTR_SHUTDOWN); any_updates = TRUE; } if(clear_stonith) { /* unset XML_CIB_ATTR_STONITH */ crm_verbose("Clearing %s", XML_CIB_ATTR_STONITH); xmlUnsetProp(target, XML_CIB_ATTR_STONITH); any_updates = TRUE; } if(any_updates) { set_node_tstamp(target); set_xml_property_copy(target, "source", source); } }