diff --git a/cib/callbacks.c b/cib/callbacks.c index 4f4818f876..988a5ec705 100644 --- a/cib/callbacks.c +++ b/cib/callbacks.c @@ -1,1403 +1,1388 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" -extern GMainLoop* mainloop; +extern GMainLoop *mainloop; extern gboolean cib_shutdown_flag; extern gboolean stand_alone; -extern const char* cib_root; +extern const char *cib_root; + #if SUPPORT_HEARTBEAT extern ll_cluster_t *hb_conn; #endif extern void cib_ha_connection_destroy(gpointer user_data); -extern enum cib_errors cib_update_counter( - xmlNode *xml_obj, const char *field, gboolean reset); +extern enum cib_errors cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset); -extern void GHFunc_count_peers( - gpointer key, gpointer value, gpointer user_data); +extern void GHFunc_count_peers(gpointer key, gpointer value, gpointer user_data); void initiate_exit(void); void terminate_cib(const char *caller); gint cib_GCompareFunc(gconstpointer a, gconstpointer b); gboolean can_write(int flags); -void send_cib_replace(const xmlNode *sync_request, const char *host); -void cib_process_request( - xmlNode *request, gboolean privileged, gboolean force_synchronous, - gboolean from_peer, cib_client_t *cib_client); -void cib_common_callback_worker(xmlNode *op_request, cib_client_t *cib_client, - gboolean force_synchronous, gboolean privileged); +void send_cib_replace(const xmlNode * sync_request, const char *host); +void cib_process_request(xmlNode * request, gboolean privileged, gboolean force_synchronous, + gboolean from_peer, cib_client_t * cib_client); +void cib_common_callback_worker(xmlNode * op_request, cib_client_t * cib_client, + gboolean force_synchronous, gboolean privileged); extern GHashTable *client_list; -int next_client_id = 0; +int next_client_id = 0; extern const char *cib_our_uname; extern unsigned long cib_num_ops, cib_num_local, cib_num_updates, cib_num_fail; extern unsigned long cib_bad_connects, cib_num_timeouts; extern longclock_t cib_call_time; extern enum cib_errors cib_status; +int send_via_callback_channel(xmlNode * msg, const char *token); -int send_via_callback_channel(xmlNode *msg, const char *token); - -enum cib_errors cib_process_command( - xmlNode *request, xmlNode **reply, - xmlNode **cib_diff, gboolean privileged); +enum cib_errors cib_process_command(xmlNode * request, xmlNode ** reply, + xmlNode ** cib_diff, gboolean privileged); -gboolean cib_common_callback(IPC_Channel *channel, cib_client_t *cib_client, - gboolean force_synchronous, gboolean privileged); +gboolean cib_common_callback(IPC_Channel * channel, cib_client_t * cib_client, + gboolean force_synchronous, gboolean privileged); -gboolean cib_process_disconnect(IPC_Channel *channel, cib_client_t *cib_client); +gboolean cib_process_disconnect(IPC_Channel * channel, cib_client_t * cib_client); int num_clients = 0; static void cib_ipc_connection_destroy(gpointer user_data) { - cib_client_t *cib_client = user_data; - - /* cib_process_disconnect */ - - if(cib_client == NULL) { - crm_debug_4("Destroying %p", user_data); - return; - } - - if(cib_client->source != NULL) { - /* Should this even be necessary? */ - crm_trace("Deleting %s (%p) from mainloop", - cib_client->name, cib_client->source); - G_main_del_IPC_Channel(cib_client->source); - cib_client->source = NULL; - } - - crm_debug_3("Destroying %s (%p)", cib_client->name, user_data); - num_clients--; - crm_debug_2("Num unfree'd clients: %d", num_clients); - crm_free(cib_client->name); - crm_free(cib_client->callback_id); - crm_free(cib_client->id); - crm_free(cib_client->user); - crm_free(cib_client); - crm_debug_4("Freed the cib client"); - - return; + cib_client_t *cib_client = user_data; + + /* cib_process_disconnect */ + + if (cib_client == NULL) { + crm_debug_4("Destroying %p", user_data); + return; + } + + if (cib_client->source != NULL) { + /* Should this even be necessary? */ + crm_trace("Deleting %s (%p) from mainloop", cib_client->name, cib_client->source); + G_main_del_IPC_Channel(cib_client->source); + cib_client->source = NULL; + } + + crm_debug_3("Destroying %s (%p)", cib_client->name, user_data); + num_clients--; + crm_debug_2("Num unfree'd clients: %d", num_clients); + crm_free(cib_client->name); + crm_free(cib_client->callback_id); + crm_free(cib_client->id); + crm_free(cib_client->user); + crm_free(cib_client); + crm_debug_4("Freed the cib client"); + + return; } gboolean -cib_client_connect(IPC_Channel *channel, gpointer user_data) +cib_client_connect(IPC_Channel * channel, gpointer user_data) { - cl_uuid_t client_id; - xmlNode *reg_msg = NULL; - cib_client_t *new_client = NULL; - char uuid_str[UU_UNPARSE_SIZEOF]; - const char *channel_name = user_data; - gboolean (*callback)(IPC_Channel *channel, gpointer user_data); - - crm_debug_3("Connecting channel"); - - if (channel == NULL) { - crm_err("Channel was NULL"); - cib_bad_connects++; - return FALSE; - - } else if (channel->ch_status != IPC_CONNECT) { - crm_err("Channel was disconnected"); - cib_bad_connects++; - return FALSE; - - } else if(channel_name == NULL) { - crm_err("user_data must contain channel name"); - cib_bad_connects++; - return FALSE; - - } else if(cib_shutdown_flag) { - crm_info("Ignoring new client [%d] during shutdown", - channel->farside_pid); - return FALSE; - } - - callback = cib_ro_callback; - if(safe_str_eq(channel_name, cib_channel_rw)) { - callback = cib_rw_callback; - } - - crm_malloc0(new_client, sizeof(cib_client_t)); - num_clients++; - new_client->channel = channel; - new_client->channel_name = channel_name; - - crm_debug_3("Created channel %p for channel %s", - new_client, new_client->channel_name); - - channel->ops->set_recv_qlen(channel, 1024); - channel->ops->set_send_qlen(channel, 1024); - - new_client->source = G_main_add_IPC_Channel( - G_PRIORITY_DEFAULT, channel, FALSE, callback, - new_client, cib_ipc_connection_destroy); - - crm_debug_3("Channel %s connected for client %s", - new_client->channel_name, new_client->id); - - cl_uuid_generate(&client_id); - cl_uuid_unparse(&client_id, uuid_str); - - CRM_CHECK(new_client->id == NULL, crm_free(new_client->id)); - new_client->id = crm_strdup(uuid_str); - - /* 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); - - reg_msg = create_xml_node(NULL, "callback"); - crm_xml_add(reg_msg, F_CIB_OPERATION, CRM_OP_REGISTER); - crm_xml_add(reg_msg, F_CIB_CLIENTID, new_client->id); - - send_ipc_message(channel, reg_msg); - free_xml(reg_msg); - - return TRUE; + cl_uuid_t client_id; + xmlNode *reg_msg = NULL; + cib_client_t *new_client = NULL; + char uuid_str[UU_UNPARSE_SIZEOF]; + const char *channel_name = user_data; + + gboolean(*callback) (IPC_Channel * channel, gpointer user_data); + + crm_debug_3("Connecting channel"); + + if (channel == NULL) { + crm_err("Channel was NULL"); + cib_bad_connects++; + return FALSE; + + } else if (channel->ch_status != IPC_CONNECT) { + crm_err("Channel was disconnected"); + cib_bad_connects++; + return FALSE; + + } else if (channel_name == NULL) { + crm_err("user_data must contain channel name"); + cib_bad_connects++; + return FALSE; + + } else if (cib_shutdown_flag) { + crm_info("Ignoring new client [%d] during shutdown", channel->farside_pid); + return FALSE; + } + + callback = cib_ro_callback; + if (safe_str_eq(channel_name, cib_channel_rw)) { + callback = cib_rw_callback; + } + + crm_malloc0(new_client, sizeof(cib_client_t)); + num_clients++; + new_client->channel = channel; + new_client->channel_name = channel_name; + + crm_debug_3("Created channel %p for channel %s", new_client, new_client->channel_name); + + channel->ops->set_recv_qlen(channel, 1024); + channel->ops->set_send_qlen(channel, 1024); + + new_client->source = G_main_add_IPC_Channel(G_PRIORITY_DEFAULT, channel, FALSE, callback, + new_client, cib_ipc_connection_destroy); + + crm_debug_3("Channel %s connected for client %s", new_client->channel_name, new_client->id); + + cl_uuid_generate(&client_id); + cl_uuid_unparse(&client_id, uuid_str); + + CRM_CHECK(new_client->id == NULL, crm_free(new_client->id)); + new_client->id = crm_strdup(uuid_str); + + /* 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); + + reg_msg = create_xml_node(NULL, "callback"); + crm_xml_add(reg_msg, F_CIB_OPERATION, CRM_OP_REGISTER); + crm_xml_add(reg_msg, F_CIB_CLIENTID, new_client->id); + + send_ipc_message(channel, reg_msg); + free_xml(reg_msg); + + return TRUE; } gboolean -cib_rw_callback(IPC_Channel *channel, gpointer user_data) +cib_rw_callback(IPC_Channel * channel, gpointer user_data) { - gboolean result = FALSE; - result = cib_common_callback(channel, user_data, FALSE, TRUE); - return result; + gboolean result = FALSE; + + result = cib_common_callback(channel, user_data, FALSE, TRUE); + return result; } gboolean -cib_ro_callback(IPC_Channel *channel, gpointer user_data) +cib_ro_callback(IPC_Channel * channel, gpointer user_data) { - gboolean result = FALSE; - result = cib_common_callback(channel, user_data, FALSE, FALSE); - return result; + gboolean result = FALSE; + + result = cib_common_callback(channel, user_data, FALSE, FALSE); + return result; } void -cib_common_callback_worker(xmlNode *op_request, cib_client_t *cib_client, - gboolean force_synchronous, gboolean privileged) +cib_common_callback_worker(xmlNode * op_request, cib_client_t * cib_client, + gboolean force_synchronous, gboolean privileged) { - longclock_t call_stop = 0; - longclock_t call_start = 0; - - const char *op = crm_element_value(op_request, F_CIB_OPERATION); - - if(crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { - return; - - } else if(crm_str_eq(op, T_CIB_NOTIFY, TRUE)) { - /* Update the notify filters for this client */ - int on_off = 0; - const char *type = crm_element_value(op_request, F_CIB_NOTIFY_TYPE);; - crm_element_value_int(op_request, F_CIB_NOTIFY_ACTIVATE, &on_off); - - crm_debug("Setting %s callbacks for %s (%s): %s", - type, cib_client->name, cib_client->id, on_off?"on":"off"); - - if(safe_str_eq(type, T_CIB_POST_NOTIFY)) { - cib_client->post_notify = on_off; - - } else if(safe_str_eq(type, T_CIB_PRE_NOTIFY)) { - cib_client->pre_notify = on_off; - - } else if(safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) { - cib_client->confirmations = on_off; - - } else if(safe_str_eq(type, T_CIB_DIFF_NOTIFY)) { - cib_client->diffs = on_off; - - } else if(safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) { - cib_client->replace = on_off; - } - return; - } - - cib_client->num_calls++; - call_start = time_longclock(); - cib_process_request( - op_request, force_synchronous, privileged, FALSE, cib_client); - - call_stop = time_longclock(); - cib_call_time += (call_stop - call_start); + longclock_t call_stop = 0; + longclock_t call_start = 0; + + const char *op = crm_element_value(op_request, F_CIB_OPERATION); + + if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { + return; + + } else if (crm_str_eq(op, T_CIB_NOTIFY, TRUE)) { + /* Update the notify filters for this client */ + int on_off = 0; + const char *type = crm_element_value(op_request, F_CIB_NOTIFY_TYPE);; + crm_element_value_int(op_request, F_CIB_NOTIFY_ACTIVATE, &on_off); + + crm_debug("Setting %s callbacks for %s (%s): %s", + type, cib_client->name, cib_client->id, on_off ? "on" : "off"); + + if (safe_str_eq(type, T_CIB_POST_NOTIFY)) { + cib_client->post_notify = on_off; + + } else if (safe_str_eq(type, T_CIB_PRE_NOTIFY)) { + cib_client->pre_notify = on_off; + + } else if (safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) { + cib_client->confirmations = on_off; + + } else if (safe_str_eq(type, T_CIB_DIFF_NOTIFY)) { + cib_client->diffs = on_off; + + } else if (safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) { + cib_client->replace = on_off; + } + return; + } + + cib_client->num_calls++; + call_start = time_longclock(); + cib_process_request(op_request, force_synchronous, privileged, FALSE, cib_client); + + call_stop = time_longclock(); + cib_call_time += (call_stop - call_start); } gboolean -cib_common_callback(IPC_Channel *channel, cib_client_t *cib_client, - gboolean force_synchronous, gboolean privileged) +cib_common_callback(IPC_Channel * channel, cib_client_t * cib_client, + gboolean force_synchronous, gboolean privileged) { - int lpc = 0; - const char *value = NULL; - xmlNode *op_request = NULL; - gboolean keep_channel = TRUE; - - CRM_CHECK(cib_client != NULL, crm_err("Invalid client"); return FALSE); - CRM_CHECK(cib_client->id != NULL, crm_err("Invalid client: %p", cib_client); return FALSE); - - /* - * Do enough work to make entering worthwhile - * But don't allow a single client to monopolize the CIB - */ - while(lpc < 5 - && IPC_ISRCONN(channel) - && channel->ops->is_message_pending(channel)) { - - lpc++; - op_request = xmlfromIPC(channel, MAX_IPC_DELAY); - if (op_request == NULL) { - break; - } - - if(cib_client->name == NULL) { - value = crm_element_value(op_request, F_CIB_CLIENTNAME); - if(value == NULL) { - cib_client->name = crm_itoa(channel->farside_pid); - } else { - cib_client->name = crm_strdup(value); - } - } - - crm_xml_add(op_request, F_CIB_CLIENTID, cib_client->id); - crm_xml_add(op_request, F_CIB_CLIENTNAME, cib_client->name); + int lpc = 0; + const char *value = NULL; + xmlNode *op_request = NULL; + gboolean keep_channel = TRUE; + + CRM_CHECK(cib_client != NULL, crm_err("Invalid client"); + return FALSE); + CRM_CHECK(cib_client->id != NULL, crm_err("Invalid client: %p", cib_client); + return FALSE); + + /* + * Do enough work to make entering worthwhile + * But don't allow a single client to monopolize the CIB + */ + while (lpc < 5 && IPC_ISRCONN(channel) + && channel->ops->is_message_pending(channel)) { + + lpc++; + op_request = xmlfromIPC(channel, MAX_IPC_DELAY); + if (op_request == NULL) { + break; + } + + if (cib_client->name == NULL) { + value = crm_element_value(op_request, F_CIB_CLIENTNAME); + if (value == NULL) { + cib_client->name = crm_itoa(channel->farside_pid); + } else { + cib_client->name = crm_strdup(value); + } + } + + crm_xml_add(op_request, F_CIB_CLIENTID, cib_client->id); + crm_xml_add(op_request, F_CIB_CLIENTNAME, cib_client->name); #if ENABLE_ACL - determine_request_user(&cib_client->user, channel, op_request, F_CIB_USER); + determine_request_user(&cib_client->user, channel, op_request, F_CIB_USER); #endif - /* crm_log_xml(LOG_MSG, "Client[inbound]", op_request); */ + /* crm_log_xml(LOG_MSG, "Client[inbound]", op_request); */ - if(cib_client->callback_id == NULL) { - value = crm_element_value(op_request, F_CIB_CALLBACK_TOKEN); - if(value != NULL) { - cib_client->callback_id = crm_strdup(value); + if (cib_client->callback_id == NULL) { + value = crm_element_value(op_request, F_CIB_CALLBACK_TOKEN); + if (value != NULL) { + cib_client->callback_id = crm_strdup(value); - } else { - cib_client->callback_id = crm_strdup(cib_client->id); - } - } - - cib_common_callback_worker( - op_request, cib_client, force_synchronous, privileged); + } else { + cib_client->callback_id = crm_strdup(cib_client->id); + } + } - free_xml(op_request); - } + cib_common_callback_worker(op_request, cib_client, force_synchronous, privileged); - if(channel->ch_status != IPC_CONNECT) { - crm_debug_2("Client disconnected"); - keep_channel = cib_process_disconnect(channel, cib_client); - } + free_xml(op_request); + } + + if (channel->ch_status != IPC_CONNECT) { + crm_debug_2("Client disconnected"); + keep_channel = cib_process_disconnect(channel, cib_client); + } - return keep_channel; + return keep_channel; } static void -do_local_notify(xmlNode *notify_src, const char *client_id, - gboolean sync_reply, gboolean from_peer) +do_local_notify(xmlNode * notify_src, const char *client_id, + gboolean sync_reply, gboolean from_peer) { - /* send callback to originating child */ - cib_client_t *client_obj = NULL; - enum cib_errors local_rc = cib_ok; - - if(client_id != NULL) { - client_obj = g_hash_table_lookup(client_list, client_id); - } else { - crm_trace("No client to sent the response to. F_CIB_CLIENTID not set."); - } - - if(client_obj == NULL) { - local_rc = cib_reply_failed; - - } else { - const char *client_id = client_obj->callback_id; - crm_trace("Sending %ssync response to %s %s", - sync_reply?"":"an a-", client_obj->name, - from_peer?"(originator of delegated request)":""); - - if(sync_reply) { - client_id = client_obj->id; - } - local_rc = send_via_callback_channel(notify_src, client_id); - } - - if(local_rc != cib_ok && client_obj != NULL) { - crm_warn("%sSync reply to %s failed: %s", - sync_reply?"":"A-", - client_obj?client_obj->name:"", cib_error2string(local_rc)); - } + /* send callback to originating child */ + cib_client_t *client_obj = NULL; + enum cib_errors local_rc = cib_ok; + + if (client_id != NULL) { + client_obj = g_hash_table_lookup(client_list, client_id); + } else { + crm_trace("No client to sent the response to. F_CIB_CLIENTID not set."); + } + + if (client_obj == NULL) { + local_rc = cib_reply_failed; + + } else { + const char *client_id = client_obj->callback_id; + + crm_trace("Sending %ssync response to %s %s", + sync_reply ? "" : "an a-", client_obj->name, + from_peer ? "(originator of delegated request)" : ""); + + if (sync_reply) { + client_id = client_obj->id; + } + local_rc = send_via_callback_channel(notify_src, client_id); + } + + if (local_rc != cib_ok && client_obj != NULL) { + crm_warn("%sSync reply to %s failed: %s", + sync_reply ? "" : "A-", + client_obj ? client_obj->name : "", cib_error2string(local_rc)); + } } static void -parse_local_options( - cib_client_t *cib_client, int call_type, int call_options, const char *host, const char *op, - gboolean *local_notify, gboolean *needs_reply, gboolean *process, gboolean *needs_forward) +parse_local_options(cib_client_t * cib_client, int call_type, int call_options, const char *host, + const char *op, gboolean * local_notify, gboolean * needs_reply, + gboolean * process, gboolean * needs_forward) { - if(cib_op_modifies(call_type) - && !(call_options & cib_inhibit_bcast)) { - /* we need to send an update anyway */ - *needs_reply = TRUE; - } else { - *needs_reply = FALSE; - } - - if(host == NULL && (call_options & cib_scope_local)) { - crm_debug_2("Processing locally scoped %s op from %s", - op, cib_client->name); - *local_notify = TRUE; - - } else if(host == NULL && cib_is_master) { - crm_debug_2("Processing master %s op locally from %s", - op, cib_client->name); - *local_notify = TRUE; - - } else if(safe_str_eq(host, cib_our_uname)) { - crm_debug_2("Processing locally addressed %s op from %s", - op, cib_client->name); - *local_notify = TRUE; - - } else if(stand_alone) { - *needs_forward = FALSE; - *local_notify = TRUE; - *process = TRUE; - - } else { - crm_debug_2("%s op from %s needs to be forwarded to %s", - op, cib_client->name, - host?host:"the master instance"); - *needs_forward = TRUE; - *process = FALSE; - } + if (cib_op_modifies(call_type) + && !(call_options & cib_inhibit_bcast)) { + /* we need to send an update anyway */ + *needs_reply = TRUE; + } else { + *needs_reply = FALSE; + } + + if (host == NULL && (call_options & cib_scope_local)) { + crm_debug_2("Processing locally scoped %s op from %s", op, cib_client->name); + *local_notify = TRUE; + + } else if (host == NULL && cib_is_master) { + crm_debug_2("Processing master %s op locally from %s", op, cib_client->name); + *local_notify = TRUE; + + } else if (safe_str_eq(host, cib_our_uname)) { + crm_debug_2("Processing locally addressed %s op from %s", op, cib_client->name); + *local_notify = TRUE; + + } else if (stand_alone) { + *needs_forward = FALSE; + *local_notify = TRUE; + *process = TRUE; + + } else { + crm_debug_2("%s op from %s needs to be forwarded to %s", + op, cib_client->name, host ? host : "the master instance"); + *needs_forward = TRUE; + *process = FALSE; + } } static gboolean -parse_peer_options( - int call_type, xmlNode *request, - gboolean *local_notify, gboolean *needs_reply, gboolean *process, gboolean *needs_forward) +parse_peer_options(int call_type, xmlNode * request, + gboolean * local_notify, gboolean * needs_reply, gboolean * process, + gboolean * needs_forward) { - const char *op = NULL; - const char *host = NULL; - const char *delegated = NULL; - const char *originator = crm_element_value(request, F_ORIG); - const char *reply_to = crm_element_value(request, F_CIB_ISREPLY); - const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE); - - gboolean is_reply = safe_str_eq(reply_to, cib_our_uname); - - if(crm_is_true(update)) { - *needs_reply = FALSE; - if(is_reply) { - *local_notify = TRUE; - crm_trace("Processing global/peer update from %s" - " that originated from us", originator); - } else { - crm_trace("Processing global/peer update from %s", originator); - } - return TRUE; - } - - host = crm_element_value(request, F_CIB_HOST); - if(host != NULL && safe_str_eq(host, cib_our_uname)) { - crm_trace("Processing request sent to us from %s", originator); - return TRUE; - - } else if(host == NULL && cib_is_master == TRUE) { - crm_trace("Processing request sent to master instance from %s", originator); - return TRUE; - } - - if(is_reply) { - crm_trace("Forward reply sent from %s to local clients", originator); - *process = FALSE; - *needs_reply = FALSE; - *local_notify = TRUE; - return TRUE; - } - - op = crm_element_value(request, F_CIB_OPERATION); - delegated = crm_element_value(request, F_CIB_DELEGATED); - if(delegated != NULL) { - crm_debug_2("Ignoring msg for master instance"); - - } else if(host != NULL) { - /* this is for a specific instance and we're not it */ - crm_debug_2("Ignoring msg for instance on %s", crm_str(host)); - - } else if(reply_to == NULL && cib_is_master == FALSE) { - /* this is for the master instance and we're not it */ - crm_debug_2("Ignoring reply to %s", crm_str(reply_to)); - - } else if(safe_str_eq(op, "cib_shutdown_req")) { - if(reply_to != NULL) { - crm_debug("Processing %s from %s", op, host); - *needs_reply = FALSE; - - } else { - crm_debug("Processing %s reply from %s", op, host); - } - return TRUE; - - } else { - crm_err("Nothing for us to do?"); - crm_log_xml(LOG_ERR, "Peer[inbound]", request); - } - - return FALSE; + const char *op = NULL; + const char *host = NULL; + const char *delegated = NULL; + const char *originator = crm_element_value(request, F_ORIG); + const char *reply_to = crm_element_value(request, F_CIB_ISREPLY); + const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE); + + gboolean is_reply = safe_str_eq(reply_to, cib_our_uname); + + if (crm_is_true(update)) { + *needs_reply = FALSE; + if (is_reply) { + *local_notify = TRUE; + crm_trace("Processing global/peer update from %s" + " that originated from us", originator); + } else { + crm_trace("Processing global/peer update from %s", originator); + } + return TRUE; + } + + host = crm_element_value(request, F_CIB_HOST); + if (host != NULL && safe_str_eq(host, cib_our_uname)) { + crm_trace("Processing request sent to us from %s", originator); + return TRUE; + + } else if (host == NULL && cib_is_master == TRUE) { + crm_trace("Processing request sent to master instance from %s", originator); + return TRUE; + } + + if (is_reply) { + crm_trace("Forward reply sent from %s to local clients", originator); + *process = FALSE; + *needs_reply = FALSE; + *local_notify = TRUE; + return TRUE; + } + + op = crm_element_value(request, F_CIB_OPERATION); + delegated = crm_element_value(request, F_CIB_DELEGATED); + if (delegated != NULL) { + crm_debug_2("Ignoring msg for master instance"); + + } else if (host != NULL) { + /* this is for a specific instance and we're not it */ + crm_debug_2("Ignoring msg for instance on %s", crm_str(host)); + + } else if (reply_to == NULL && cib_is_master == FALSE) { + /* this is for the master instance and we're not it */ + crm_debug_2("Ignoring reply to %s", crm_str(reply_to)); + + } else if (safe_str_eq(op, "cib_shutdown_req")) { + if (reply_to != NULL) { + crm_debug("Processing %s from %s", op, host); + *needs_reply = FALSE; + + } else { + crm_debug("Processing %s reply from %s", op, host); + } + return TRUE; + + } else { + crm_err("Nothing for us to do?"); + crm_log_xml(LOG_ERR, "Peer[inbound]", request); + } + + return FALSE; } - static void -forward_request(xmlNode *request, cib_client_t *cib_client, int call_options) +forward_request(xmlNode * request, cib_client_t * cib_client, int call_options) { - const char *op = crm_element_value(request, F_CIB_OPERATION); - const char *host = crm_element_value(request, F_CIB_HOST); - - crm_xml_add(request, F_CIB_DELEGATED, cib_our_uname); - - if(host != NULL) { - crm_debug_2("Forwarding %s op to %s", op, host); - send_cluster_message(host, crm_msg_cib, request, FALSE); - - } else { - crm_debug_2("Forwarding %s op to master instance", op); - send_cluster_message(NULL, crm_msg_cib, request, FALSE); - } - - /* Return the request to its original state */ - xml_remove_prop(request, F_CIB_DELEGATED); - - if(call_options & cib_discard_reply) { - crm_debug_2("Client not interested in reply"); - } + const char *op = crm_element_value(request, F_CIB_OPERATION); + const char *host = crm_element_value(request, F_CIB_HOST); + + crm_xml_add(request, F_CIB_DELEGATED, cib_our_uname); + + if (host != NULL) { + crm_debug_2("Forwarding %s op to %s", op, host); + send_cluster_message(host, crm_msg_cib, request, FALSE); + + } else { + crm_debug_2("Forwarding %s op to master instance", op); + send_cluster_message(NULL, crm_msg_cib, request, FALSE); + } + + /* Return the request to its original state */ + xml_remove_prop(request, F_CIB_DELEGATED); + + if (call_options & cib_discard_reply) { + crm_debug_2("Client not interested in reply"); + } } static void -send_peer_reply( - xmlNode *msg, xmlNode *result_diff, const char *originator, gboolean broadcast) +send_peer_reply(xmlNode * msg, xmlNode * result_diff, const char *originator, gboolean broadcast) { - CRM_ASSERT(msg != NULL); - - if(broadcast) { - /* this (successful) call modified the CIB _and_ the - * change needs to be broadcast... - * send via HA to other nodes - */ - int diff_add_updates = 0; - int diff_add_epoch = 0; - int diff_add_admin_epoch = 0; - - int diff_del_updates = 0; - int diff_del_epoch = 0; - int diff_del_admin_epoch = 0; - - char *digest = NULL; - - cib_diff_version_details( - result_diff, - &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, - &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); - - crm_debug_2("Sending update diff %d.%d.%d -> %d.%d.%d", - diff_del_admin_epoch,diff_del_epoch,diff_del_updates, - diff_add_admin_epoch,diff_add_epoch,diff_add_updates); - - crm_xml_add(msg, F_CIB_ISREPLY, originator); - crm_xml_add(msg, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE); - crm_xml_add(msg, F_CIB_OPERATION, CIB_OP_APPLY_DIFF); - - /* Its safe to always use the latest version since the election - * ensures the software on this node is the oldest node in the cluster - */ - digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET); - crm_xml_add(result_diff, XML_ATTR_DIGEST, digest); - crm_log_xml_trace(the_cib, digest); - crm_free(digest); - - add_message_xml(msg, F_CIB_UPDATE_DIFF, result_diff); - crm_log_xml(LOG_DEBUG_3, "copy", msg); - send_cluster_message(NULL, crm_msg_cib, msg, TRUE); - - } else if(originator != NULL) { - /* send reply via HA to originating node */ - crm_debug_2("Sending request result to originator only"); - crm_xml_add(msg, F_CIB_ISREPLY, originator); - send_cluster_message(originator, crm_msg_cib, msg, FALSE); - } + CRM_ASSERT(msg != NULL); + + if (broadcast) { + /* this (successful) call modified the CIB _and_ the + * change needs to be broadcast... + * send via HA to other nodes + */ + int diff_add_updates = 0; + int diff_add_epoch = 0; + int diff_add_admin_epoch = 0; + + int diff_del_updates = 0; + int diff_del_epoch = 0; + int diff_del_admin_epoch = 0; + + char *digest = NULL; + + cib_diff_version_details(result_diff, + &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, + &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); + + crm_debug_2("Sending update diff %d.%d.%d -> %d.%d.%d", + diff_del_admin_epoch, diff_del_epoch, diff_del_updates, + diff_add_admin_epoch, diff_add_epoch, diff_add_updates); + + crm_xml_add(msg, F_CIB_ISREPLY, originator); + crm_xml_add(msg, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE); + crm_xml_add(msg, F_CIB_OPERATION, CIB_OP_APPLY_DIFF); + + /* Its safe to always use the latest version since the election + * ensures the software on this node is the oldest node in the cluster + */ + digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET); + crm_xml_add(result_diff, XML_ATTR_DIGEST, digest); + crm_log_xml_trace(the_cib, digest); + crm_free(digest); + + add_message_xml(msg, F_CIB_UPDATE_DIFF, result_diff); + crm_log_xml(LOG_DEBUG_3, "copy", msg); + send_cluster_message(NULL, crm_msg_cib, msg, TRUE); + + } else if (originator != NULL) { + /* send reply via HA to originating node */ + crm_debug_2("Sending request result to originator only"); + crm_xml_add(msg, F_CIB_ISREPLY, originator); + send_cluster_message(originator, crm_msg_cib, msg, FALSE); + } } - + void -cib_process_request( - xmlNode *request, gboolean force_synchronous, gboolean privileged, - gboolean from_peer, cib_client_t *cib_client) +cib_process_request(xmlNode * request, gboolean force_synchronous, gboolean privileged, + gboolean from_peer, cib_client_t * cib_client) { - int call_type = 0; - int call_options = 0; - - gboolean process = TRUE; - gboolean is_update = TRUE; - gboolean needs_reply = TRUE; - gboolean local_notify = FALSE; - gboolean needs_forward = FALSE; - gboolean global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE)); - - xmlNode *op_reply = NULL; - xmlNode *result_diff = NULL; - - enum cib_errors rc = cib_ok; - const char *op = crm_element_value(request, F_CIB_OPERATION); - const char *originator = crm_element_value(request, F_ORIG); - const char *host = crm_element_value(request, F_CIB_HOST); - - crm_debug_4("%s Processing msg %s", - cib_our_uname, crm_element_value(request, F_SEQ)); - - cib_num_ops++; - if(cib_num_ops == 0) { - cib_num_fail = 0; - cib_num_local = 0; - cib_num_updates = 0; - crm_info("Stats wrapped around"); - } - - if(host != NULL && strlen(host) == 0) { - host = NULL; - } - - crm_element_value_int(request, F_CIB_CALLOPTS, &call_options); - if(force_synchronous) { - call_options |= cib_sync_call; - } - - crm_debug_2("Processing %s message (%s) for %s...", - from_peer?"peer":"local", - from_peer?originator:cib_our_uname, host?host:"master"); - - rc = cib_get_operation_id(op, &call_type); - if(rc != cib_ok) { - /* TODO: construct error reply? */ - crm_err("Pre-processing of command failed: %s", cib_error2string(rc)); - return; - } - - is_update = cib_op_modifies(call_type); - if(is_update) { - cib_num_updates++; - } - - if(from_peer == FALSE) { - parse_local_options(cib_client, call_type, call_options, host, op, - &local_notify, &needs_reply, &process, &needs_forward); - - } else if(parse_peer_options(call_type, request, &local_notify, - &needs_reply, &process, &needs_forward) == FALSE) { - return; - } - crm_debug_3("Finished determining processing actions"); - - if(call_options & cib_discard_reply) { - needs_reply = is_update; - local_notify = FALSE; - } - - if(needs_forward) { - forward_request(request, cib_client, call_options); - return; - } - - if(cib_status != cib_ok) { - rc = cib_status; - crm_err("Operation ignored, cluster configuration is invalid." - " Please repair and restart: %s", - cib_error2string(cib_status)); - op_reply = cib_construct_reply(request, the_cib, cib_status); - - } else if(process) { - int level = LOG_INFO; - const char *section = crm_element_value(request, F_CIB_SECTION); - - cib_num_local++; - rc = cib_process_command( - request, &op_reply, &result_diff, privileged); - - if(global_update) { - switch(rc) { - case cib_ok: - case cib_old_data: - case cib_diff_resync: - case cib_diff_failed: - level = LOG_DEBUG_2; - break; - default: - level = LOG_ERR; - } - - } else if(safe_str_eq(op, CIB_OP_QUERY)) { - level = LOG_DEBUG_2; - - } else if(rc != cib_ok) { - cib_num_fail++; - level = LOG_WARNING; - - } else if(safe_str_eq(op, CIB_OP_SLAVE)) { - level = LOG_DEBUG_2; - - } else if(safe_str_eq(section, XML_CIB_TAG_STATUS)) { - level = LOG_DEBUG_2; - } - - if(crm_log_level >= level) { - /* Avoid all the xml lookups if we're not going to print the results */ - do_crm_log(level, "Operation complete: op %s for section %s (origin=%s/%s/%s, version=%s.%s.%s): %s (rc=%d)", - op, section?section:"'all'", originator?originator:"local", - crm_element_value(request, F_CIB_CLIENTNAME), - crm_element_value(request, F_CIB_CALLID), - the_cib?crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN):"0", - the_cib?crm_element_value(the_cib, XML_ATTR_GENERATION):"0", - the_cib?crm_element_value(the_cib, XML_ATTR_NUMUPDATES):"0", - cib_error2string(rc), rc); - } - - if(op_reply == NULL && (needs_reply || local_notify)) { - crm_err("Unexpected NULL reply to message"); - crm_log_xml(LOG_ERR, "null reply", request); - needs_reply = FALSE; - local_notify = FALSE; - } - } - crm_debug_3("processing response cases"); - - if(local_notify) { - const char *client_id = crm_element_value(request, F_CIB_CLIENTID); - if(client_id && process == FALSE) { - do_local_notify(request, client_id, call_options & cib_sync_call, from_peer); - } else if(client_id) { - do_local_notify(op_reply, client_id, call_options & cib_sync_call, from_peer); - } - } - - /* from now on we are the server */ - if(needs_reply == FALSE || stand_alone) { - /* nothing more to do... - * this was a non-originating slave update - */ - crm_debug_2("Completed slave update"); - - } else if(rc == cib_ok - && result_diff != NULL - && !(call_options & cib_inhibit_bcast)) { - send_peer_reply(request, result_diff, originator, TRUE); - - } else if(call_options & cib_discard_reply) { - crm_debug_4("Caller isn't interested in reply"); - - } else if (from_peer) { - if(is_update == FALSE || result_diff == NULL) { - crm_debug_3("Request not broadcast: R/O call"); - - } else if(call_options & cib_inhibit_bcast) { - crm_debug_3("Request not broadcast: inhibited"); - - } else if(rc != cib_ok) { - crm_debug_3("Request not broadcast: call failed: %s", - cib_error2string(rc)); - } else { - crm_debug_2("Directing reply to %s", originator); - } - - send_peer_reply(op_reply, result_diff, originator, FALSE); - } - - free_xml(op_reply); - free_xml(result_diff); - - return; + int call_type = 0; + int call_options = 0; + + gboolean process = TRUE; + gboolean is_update = TRUE; + gboolean needs_reply = TRUE; + gboolean local_notify = FALSE; + gboolean needs_forward = FALSE; + gboolean global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE)); + + xmlNode *op_reply = NULL; + xmlNode *result_diff = NULL; + + enum cib_errors rc = cib_ok; + const char *op = crm_element_value(request, F_CIB_OPERATION); + const char *originator = crm_element_value(request, F_ORIG); + const char *host = crm_element_value(request, F_CIB_HOST); + + crm_debug_4("%s Processing msg %s", cib_our_uname, crm_element_value(request, F_SEQ)); + + cib_num_ops++; + if (cib_num_ops == 0) { + cib_num_fail = 0; + cib_num_local = 0; + cib_num_updates = 0; + crm_info("Stats wrapped around"); + } + + if (host != NULL && strlen(host) == 0) { + host = NULL; + } + + crm_element_value_int(request, F_CIB_CALLOPTS, &call_options); + if (force_synchronous) { + call_options |= cib_sync_call; + } + + crm_debug_2("Processing %s message (%s) for %s...", + from_peer ? "peer" : "local", + from_peer ? originator : cib_our_uname, host ? host : "master"); + + rc = cib_get_operation_id(op, &call_type); + if (rc != cib_ok) { + /* TODO: construct error reply? */ + crm_err("Pre-processing of command failed: %s", cib_error2string(rc)); + return; + } + + is_update = cib_op_modifies(call_type); + if (is_update) { + cib_num_updates++; + } + + if (from_peer == FALSE) { + parse_local_options(cib_client, call_type, call_options, host, op, + &local_notify, &needs_reply, &process, &needs_forward); + + } else if (parse_peer_options(call_type, request, &local_notify, + &needs_reply, &process, &needs_forward) == FALSE) { + return; + } + crm_debug_3("Finished determining processing actions"); + + if (call_options & cib_discard_reply) { + needs_reply = is_update; + local_notify = FALSE; + } + + if (needs_forward) { + forward_request(request, cib_client, call_options); + return; + } + + if (cib_status != cib_ok) { + rc = cib_status; + crm_err("Operation ignored, cluster configuration is invalid." + " Please repair and restart: %s", cib_error2string(cib_status)); + op_reply = cib_construct_reply(request, the_cib, cib_status); + + } else if (process) { + int level = LOG_INFO; + const char *section = crm_element_value(request, F_CIB_SECTION); + + cib_num_local++; + rc = cib_process_command(request, &op_reply, &result_diff, privileged); + + if (global_update) { + switch (rc) { + case cib_ok: + case cib_old_data: + case cib_diff_resync: + case cib_diff_failed: + level = LOG_DEBUG_2; + break; + default: + level = LOG_ERR; + } + + } else if (safe_str_eq(op, CIB_OP_QUERY)) { + level = LOG_DEBUG_2; + + } else if (rc != cib_ok) { + cib_num_fail++; + level = LOG_WARNING; + + } else if (safe_str_eq(op, CIB_OP_SLAVE)) { + level = LOG_DEBUG_2; + + } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) { + level = LOG_DEBUG_2; + } + + if (crm_log_level >= level) { + /* Avoid all the xml lookups if we're not going to print the results */ + do_crm_log(level, + "Operation complete: op %s for section %s (origin=%s/%s/%s, version=%s.%s.%s): %s (rc=%d)", + op, section ? section : "'all'", originator ? originator : "local", + crm_element_value(request, F_CIB_CLIENTNAME), crm_element_value(request, + F_CIB_CALLID), + the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN) : "0", + the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION) : "0", + the_cib ? crm_element_value(the_cib, XML_ATTR_NUMUPDATES) : "0", + cib_error2string(rc), rc); + } + + if (op_reply == NULL && (needs_reply || local_notify)) { + crm_err("Unexpected NULL reply to message"); + crm_log_xml(LOG_ERR, "null reply", request); + needs_reply = FALSE; + local_notify = FALSE; + } + } + crm_debug_3("processing response cases"); + + if (local_notify) { + const char *client_id = crm_element_value(request, F_CIB_CLIENTID); + + if (client_id && process == FALSE) { + do_local_notify(request, client_id, call_options & cib_sync_call, from_peer); + } else if (client_id) { + do_local_notify(op_reply, client_id, call_options & cib_sync_call, from_peer); + } + } + + /* from now on we are the server */ + if (needs_reply == FALSE || stand_alone) { + /* nothing more to do... + * this was a non-originating slave update + */ + crm_debug_2("Completed slave update"); + + } else if (rc == cib_ok && result_diff != NULL && !(call_options & cib_inhibit_bcast)) { + send_peer_reply(request, result_diff, originator, TRUE); + + } else if (call_options & cib_discard_reply) { + crm_debug_4("Caller isn't interested in reply"); + + } else if (from_peer) { + if (is_update == FALSE || result_diff == NULL) { + crm_debug_3("Request not broadcast: R/O call"); + + } else if (call_options & cib_inhibit_bcast) { + crm_debug_3("Request not broadcast: inhibited"); + + } else if (rc != cib_ok) { + crm_debug_3("Request not broadcast: call failed: %s", cib_error2string(rc)); + } else { + crm_debug_2("Directing reply to %s", originator); + } + + send_peer_reply(op_reply, result_diff, originator, FALSE); + } + + free_xml(op_reply); + free_xml(result_diff); + + return; } xmlNode * -cib_construct_reply(xmlNode *request, xmlNode *output, int rc) +cib_construct_reply(xmlNode * request, xmlNode * output, int rc) { - int lpc = 0; - xmlNode *reply = NULL; - const char *name = NULL; - const char *value = NULL; - const char *names[] = { - F_CIB_OPERATION, - F_CIB_CALLID, - F_CIB_CLIENTID, - F_CIB_CALLOPTS - }; - static int max = DIMOF(names); - - crm_debug_4("Creating a basic reply"); - reply = create_xml_node(NULL, "cib-reply"); - crm_xml_add(reply, F_TYPE, T_CIB); - - for(lpc = 0; lpc < max; lpc++) { - name = names[lpc]; - value = crm_element_value(request, name); - crm_xml_add(reply, name, value); - } - - crm_xml_add_int(reply, F_CIB_RC, rc); - - if(output != NULL) { - crm_debug_4("Attaching reply output"); - add_message_xml(reply, F_CIB_CALLDATA, output); - } - return reply; + int lpc = 0; + xmlNode *reply = NULL; + const char *name = NULL; + const char *value = NULL; + + const char *names[] = { + F_CIB_OPERATION, + F_CIB_CALLID, + F_CIB_CLIENTID, + F_CIB_CALLOPTS + }; + static int max = DIMOF(names); + + crm_debug_4("Creating a basic reply"); + reply = create_xml_node(NULL, "cib-reply"); + crm_xml_add(reply, F_TYPE, T_CIB); + + for (lpc = 0; lpc < max; lpc++) { + name = names[lpc]; + value = crm_element_value(request, name); + crm_xml_add(reply, name, value); + } + + crm_xml_add_int(reply, F_CIB_RC, rc); + + if (output != NULL) { + crm_debug_4("Attaching reply output"); + add_message_xml(reply, F_CIB_CALLDATA, output); + } + return reply; } enum cib_errors -cib_process_command(xmlNode *request, xmlNode **reply, - xmlNode **cib_diff, gboolean privileged) +cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged) { - xmlNode *input = NULL; - xmlNode *output = NULL; - xmlNode *result_cib = NULL; + xmlNode *input = NULL; + xmlNode *output = NULL; + xmlNode *result_cib = NULL; xmlNode *current_cib = NULL; + #if ENABLE_ACL xmlNode *filtered_current_cib = NULL; #endif - - int call_type = 0; + + int call_type = 0; int call_options = 0; - int log_level = LOG_DEBUG_4; + int log_level = LOG_DEBUG_4; const char *op = NULL; const char *section = NULL; enum cib_errors rc = cib_ok; enum cib_errors rc2 = cib_ok; - + gboolean send_r_notify = FALSE; gboolean global_update = FALSE; gboolean config_changed = FALSE; gboolean manage_counters = TRUE; - + CRM_ASSERT(cib_status == cib_ok); *reply = NULL; *cib_diff = NULL; current_cib = the_cib; - + /* Start processing the request... */ op = crm_element_value(request, F_CIB_OPERATION); crm_element_value_int(request, F_CIB_CALLOPTS, &call_options); rc = cib_get_operation_id(op, &call_type); - - if(rc == cib_ok && privileged == FALSE) { - rc = cib_op_can_run(call_type, call_options, privileged, global_update); + + if (rc == cib_ok && privileged == FALSE) { + rc = cib_op_can_run(call_type, call_options, privileged, global_update); } - + rc2 = cib_op_prepare(call_type, request, &input, §ion); - if(rc == cib_ok) { - rc = rc2; - } - - if(rc != cib_ok) { - crm_debug_2("Call setup failed: %s", cib_error2string(rc)); - goto done; - - } else if(cib_op_modifies(call_type) == FALSE) { + if (rc == cib_ok) { + rc = rc2; + } + + if (rc != cib_ok) { + crm_debug_2("Call setup failed: %s", cib_error2string(rc)); + goto done; + + } else if (cib_op_modifies(call_type) == FALSE) { #if ENABLE_ACL - if (acl_enabled(config_hash) == FALSE - || acl_filter_cib(request, current_cib, current_cib, &filtered_current_cib) == FALSE) { - rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, - section, request, input, FALSE, &config_changed, - current_cib, &result_cib, NULL, &output); - - } else if (filtered_current_cib == NULL) { - crm_debug("Pre-filtered the entire cib"); - rc = cib_permission_denied; - - } else { - crm_debug("Pre-filtered the queried cib according to the ACLs"); - rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, - section, request, input, FALSE, &config_changed, - filtered_current_cib, &result_cib, NULL, &output); - } + if (acl_enabled(config_hash) == FALSE + || acl_filter_cib(request, current_cib, current_cib, &filtered_current_cib) == FALSE) { + rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, + section, request, input, FALSE, &config_changed, + current_cib, &result_cib, NULL, &output); + + } else if (filtered_current_cib == NULL) { + crm_debug("Pre-filtered the entire cib"); + rc = cib_permission_denied; + + } else { + crm_debug("Pre-filtered the queried cib according to the ACLs"); + rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, + section, request, input, FALSE, &config_changed, + filtered_current_cib, &result_cib, NULL, &output); + } #else - rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, - section, request, input, FALSE, &config_changed, - current_cib, &result_cib, NULL, &output); - + rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, + section, request, input, FALSE, &config_changed, + current_cib, &result_cib, NULL, &output); + #endif - CRM_CHECK(result_cib == NULL, free_xml(result_cib)); - goto done; - } + CRM_CHECK(result_cib == NULL, free_xml(result_cib)); + goto done; + } /* Handle a valid write action */ global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE)); - if(global_update) { - manage_counters = FALSE; - call_options |= cib_force_diff; + if (global_update) { + manage_counters = FALSE; + call_options |= cib_force_diff; - CRM_CHECK(call_type == 3 || call_type == 4, - crm_err("Call type: %d", call_type); - crm_log_xml(LOG_ERR, "bad op", request)); + CRM_CHECK(call_type == 3 || call_type == 4, + crm_err("Call type: %d", call_type); crm_log_xml(LOG_ERR, "bad op", request)); } - #ifdef SUPPORT_PRENOTIFY - if((call_options & cib_inhibit_notify) == 0) { - cib_pre_notify(call_options, op, the_cib, input); + if ((call_options & cib_inhibit_notify) == 0) { + cib_pre_notify(call_options, op, the_cib, input); } #endif - - if(rc == cib_ok) { - if(call_options & cib_inhibit_bcast) { - /* skip */ - crm_debug_2("Skipping update: inhibit broadcast"); - manage_counters = FALSE; - } - - rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE, - section, request, input, manage_counters, &config_changed, - current_cib, &result_cib, cib_diff, &output); + + if (rc == cib_ok) { + if (call_options & cib_inhibit_bcast) { + /* skip */ + crm_debug_2("Skipping update: inhibit broadcast"); + manage_counters = FALSE; + } + + rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE, + section, request, input, manage_counters, &config_changed, + current_cib, &result_cib, cib_diff, &output); #if ENABLE_ACL - if (acl_enabled(config_hash) == TRUE - && acl_check_diff(request, current_cib, result_cib, *cib_diff) == FALSE) { - rc = cib_permission_denied; - } + if (acl_enabled(config_hash) == TRUE + && acl_check_diff(request, current_cib, result_cib, *cib_diff) == FALSE) { + rc = cib_permission_denied; + } #endif - if (rc == cib_ok && config_changed) { - time_t now; - char *now_str = NULL; - const char *validation = crm_element_value(result_cib, XML_ATTR_VALIDATION); - if (validation) { - int current_version = get_schema_version(validation); - int support_version = get_schema_version("pacemaker-1.1"); - /* Once the later schemas support the "update-*" attributes, change "==" to ">=" -- Changed */ - if (current_version >= support_version) { - const char *origin = crm_element_value(request, F_ORIG); - crm_xml_replace(result_cib, XML_ATTR_UPDATE_ORIG, origin?origin:cib_our_uname); - crm_xml_replace(result_cib, XML_ATTR_UPDATE_CLIENT, crm_element_value(request, F_CIB_CLIENTNAME)); + if (rc == cib_ok && config_changed) { + time_t now; + char *now_str = NULL; + const char *validation = crm_element_value(result_cib, XML_ATTR_VALIDATION); + + if (validation) { + int current_version = get_schema_version(validation); + int support_version = get_schema_version("pacemaker-1.1"); + + /* Once the later schemas support the "update-*" attributes, change "==" to ">=" -- Changed */ + if (current_version >= support_version) { + const char *origin = crm_element_value(request, F_ORIG); + + crm_xml_replace(result_cib, XML_ATTR_UPDATE_ORIG, + origin ? origin : cib_our_uname); + crm_xml_replace(result_cib, XML_ATTR_UPDATE_CLIENT, + crm_element_value(request, F_CIB_CLIENTNAME)); #if ENABLE_ACL - crm_xml_replace(result_cib, XML_ATTR_UPDATE_USER, crm_element_value(request, F_CIB_USER)); + crm_xml_replace(result_cib, XML_ATTR_UPDATE_USER, + crm_element_value(request, F_CIB_USER)); #endif - } - } - - now = time(NULL); - now_str = ctime(&now); - now_str[24] = EOS; /* replace the newline */ - crm_xml_replace(result_cib, XML_CIB_ATTR_WRITTEN, now_str); - } - - if(manage_counters == FALSE) { - config_changed = cib_config_changed(current_cib, result_cib, cib_diff); - } - - /* Always write to disk for replace ops, - * this negates the need to detect ordering changes - */ - if(config_changed == FALSE && crm_str_eq(CIB_OP_REPLACE, op, TRUE)) { - config_changed = TRUE; - } - } - - if(rc == cib_ok && (call_options & cib_dryrun) == 0) { - rc = activateCibXml(result_cib, config_changed, op); - if (rc == cib_ok && cib_internal_config_changed(*cib_diff)) { - cib_read_config(config_hash, result_cib); - } - - if(crm_str_eq(CIB_OP_REPLACE, op, TRUE)) { - if(section == NULL) { - send_r_notify = TRUE; - - } else if(safe_str_eq(section, XML_TAG_CIB)) { - send_r_notify = TRUE; - - } else if(safe_str_eq(section, XML_CIB_TAG_NODES)) { - send_r_notify = TRUE; - - } else if(safe_str_eq(section, XML_CIB_TAG_STATUS)) { - send_r_notify = TRUE; - } - - } else if(crm_str_eq(CIB_OP_ERASE, op, TRUE)) { - send_r_notify = TRUE; - } - - } else if(rc == cib_dtd_validation) { - if(output != NULL) { - crm_log_xml_info(output, "cib:output"); - free_xml(output); - } + } + } + + now = time(NULL); + now_str = ctime(&now); + now_str[24] = EOS; /* replace the newline */ + crm_xml_replace(result_cib, XML_CIB_ATTR_WRITTEN, now_str); + } + + if (manage_counters == FALSE) { + config_changed = cib_config_changed(current_cib, result_cib, cib_diff); + } + + /* Always write to disk for replace ops, + * this negates the need to detect ordering changes + */ + if (config_changed == FALSE && crm_str_eq(CIB_OP_REPLACE, op, TRUE)) { + config_changed = TRUE; + } + } + + if (rc == cib_ok && (call_options & cib_dryrun) == 0) { + rc = activateCibXml(result_cib, config_changed, op); + if (rc == cib_ok && cib_internal_config_changed(*cib_diff)) { + cib_read_config(config_hash, result_cib); + } + + if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) { + if (section == NULL) { + send_r_notify = TRUE; + + } else if (safe_str_eq(section, XML_TAG_CIB)) { + send_r_notify = TRUE; + } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) { + send_r_notify = TRUE; + + } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) { + send_r_notify = TRUE; + } + + } else if (crm_str_eq(CIB_OP_ERASE, op, TRUE)) { + send_r_notify = TRUE; + } + + } else if (rc == cib_dtd_validation) { + if (output != NULL) { + crm_log_xml_info(output, "cib:output"); + free_xml(output); + } #if ENABLE_ACL - { - xmlNode *filtered_result_cib = NULL; - if (acl_enabled(config_hash) == FALSE - || acl_filter_cib(request, current_cib, result_cib, &filtered_result_cib) == FALSE) { - output = result_cib; - - } else { - crm_debug("Filtered the result cib for output according to the ACLs"); - output = filtered_result_cib; - if (result_cib != NULL) { - free_xml(result_cib); - } - } - } + { + xmlNode *filtered_result_cib = NULL; + + if (acl_enabled(config_hash) == FALSE + || acl_filter_cib(request, current_cib, result_cib, + &filtered_result_cib) == FALSE) { + output = result_cib; + + } else { + crm_debug("Filtered the result cib for output according to the ACLs"); + output = filtered_result_cib; + if (result_cib != NULL) { + free_xml(result_cib); + } + } + } #else - output = result_cib; + output = result_cib; #endif } else { - free_xml(result_cib); + free_xml(result_cib); } - - if((call_options & cib_inhibit_notify) == 0) { - const char *call_id = crm_element_value(request, F_CIB_CALLID); - const char *client = crm_element_value(request, F_CIB_CLIENTNAME); + + if ((call_options & cib_inhibit_notify) == 0) { + const char *call_id = crm_element_value(request, F_CIB_CALLID); + const char *client = crm_element_value(request, F_CIB_CLIENTNAME); #ifdef SUPPORT_POSTNOTIFY - cib_post_notify(call_options, op, input, rc, the_cib); + cib_post_notify(call_options, op, input, rc, the_cib); #endif - cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff); - } - - if(send_r_notify) { - const char *origin = crm_element_value(request, F_ORIG); - cib_replace_notify(origin, the_cib, rc, *cib_diff); - } - - if(rc != cib_ok) { - log_level = LOG_DEBUG_4; - if(rc == cib_dtd_validation && global_update) { - log_level = LOG_WARNING; - crm_log_xml_info(input, "cib:global_update"); - } - - } else if(config_changed) { - log_level = LOG_DEBUG_3; - if(cib_is_master) { - log_level = LOG_INFO; - } - - } else if(cib_is_master) { - log_level = LOG_DEBUG_2; - } - - log_xml_diff(log_level, *cib_diff, "cib:diff"); + cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff); + } - done: - if((call_options & cib_discard_reply) == 0) { - *reply = cib_construct_reply(request, output, rc); - /* crm_log_xml_info(*reply, "cib:reply"); */ + if (send_r_notify) { + const char *origin = crm_element_value(request, F_ORIG); + + cib_replace_notify(origin, the_cib, rc, *cib_diff); } + if (rc != cib_ok) { + log_level = LOG_DEBUG_4; + if (rc == cib_dtd_validation && global_update) { + log_level = LOG_WARNING; + crm_log_xml_info(input, "cib:global_update"); + } + + } else if (config_changed) { + log_level = LOG_DEBUG_3; + if (cib_is_master) { + log_level = LOG_INFO; + } + + } else if (cib_is_master) { + log_level = LOG_DEBUG_2; + } + + log_xml_diff(log_level, *cib_diff, "cib:diff"); + + done: + if ((call_options & cib_discard_reply) == 0) { + *reply = cib_construct_reply(request, output, rc); + /* crm_log_xml_info(*reply, "cib:reply"); */ + } #if ENABLE_ACL if (filtered_current_cib != NULL) { - free_xml(filtered_current_cib); + free_xml(filtered_current_cib); } #endif - if(call_type >= 0) { - cib_op_cleanup(call_type, call_options, &input, &output); + if (call_type >= 0) { + cib_op_cleanup(call_type, call_options, &input, &output); } return rc; } int -send_via_callback_channel(xmlNode *msg, const char *token) +send_via_callback_channel(xmlNode * msg, const char *token) { - cib_client_t *hash_client = NULL; - enum cib_errors rc = cib_ok; - - crm_debug_3("Delivering msg %p to client %s", msg, token); - - if(token == NULL) { - crm_err("No client id token, cant send message"); - if(rc == cib_ok) { - rc = cib_missing; - } - - } else if(msg == NULL) { - crm_err("No message to send"); - rc = cib_reply_failed; - - } else { - /* A client that left before we could reply is not really - * _our_ error. Warn instead. - */ - hash_client = g_hash_table_lookup(client_list, token); - if(hash_client == NULL) { - crm_warn("Cannot find client for token %s", token); - rc = cib_client_gone; - - } else if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) { - /* just hope it's alive */ - - } else if(hash_client->channel == NULL) { - crm_err("Cannot find channel for client %s", token); - rc = cib_client_corrupt; - } - } - - if(rc == cib_ok) { - crm_debug_3("Delivering reply to client %s (%s)", - token, hash_client->channel_name); - if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) { - cib_send_remote_msg(hash_client->channel, msg, hash_client->encrypted); - - } else if(send_ipc_message(hash_client->channel, msg) == FALSE) { - crm_warn("Delivery of reply to client %s/%s failed", - hash_client->name, token); - rc = cib_reply_failed; - } - } - - return rc; + cib_client_t *hash_client = NULL; + enum cib_errors rc = cib_ok; + + crm_debug_3("Delivering msg %p to client %s", msg, token); + + if (token == NULL) { + crm_err("No client id token, cant send message"); + if (rc == cib_ok) { + rc = cib_missing; + } + + } else if (msg == NULL) { + crm_err("No message to send"); + rc = cib_reply_failed; + + } else { + /* A client that left before we could reply is not really + * _our_ error. Warn instead. + */ + hash_client = g_hash_table_lookup(client_list, token); + if (hash_client == NULL) { + crm_warn("Cannot find client for token %s", token); + rc = cib_client_gone; + + } else if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) { + /* just hope it's alive */ + + } else if (hash_client->channel == NULL) { + crm_err("Cannot find channel for client %s", token); + rc = cib_client_corrupt; + } + } + + if (rc == cib_ok) { + crm_debug_3("Delivering reply to client %s (%s)", token, hash_client->channel_name); + if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) { + cib_send_remote_msg(hash_client->channel, msg, hash_client->encrypted); + + } else if (send_ipc_message(hash_client->channel, msg) == FALSE) { + crm_warn("Delivery of reply to client %s/%s failed", hash_client->name, token); + rc = cib_reply_failed; + } + } + + return rc; } -gint cib_GCompareFunc(gconstpointer a, gconstpointer b) +gint +cib_GCompareFunc(gconstpointer a, gconstpointer b) { - const xmlNode *a_msg = a; - const xmlNode *b_msg = b; - - int msg_a_id = 0; - int msg_b_id = 0; - const char *value = NULL; - - value = crm_element_value_const(a_msg, F_CIB_CALLID); - msg_a_id = crm_parse_int(value, NULL); - - value = crm_element_value_const(b_msg, F_CIB_CALLID); - msg_b_id = crm_parse_int(value, NULL); - - if(msg_a_id == msg_b_id) { - return 0; - } else if(msg_a_id < msg_b_id) { - return -1; - } - return 1; + const xmlNode *a_msg = a; + const xmlNode *b_msg = b; + + int msg_a_id = 0; + int msg_b_id = 0; + const char *value = NULL; + + value = crm_element_value_const(a_msg, F_CIB_CALLID); + msg_a_id = crm_parse_int(value, NULL); + + value = crm_element_value_const(b_msg, F_CIB_CALLID); + msg_b_id = crm_parse_int(value, NULL); + + if (msg_a_id == msg_b_id) { + return 0; + } else if (msg_a_id < msg_b_id) { + return -1; + } + return 1; } gboolean -cib_process_disconnect(IPC_Channel *channel, cib_client_t *cib_client) +cib_process_disconnect(IPC_Channel * channel, cib_client_t * cib_client) { /* TODO: Move all this into cib_ipc_connection_destroy() and re-use with cib_remote_connection_destroy() */ - if (channel == NULL) { - CRM_LOG_ASSERT(cib_client == NULL); - - } else if (cib_client == NULL) { - crm_err("No client"); - - } else { - CRM_LOG_ASSERT(channel->ch_status != IPC_CONNECT); - crm_debug_2("Cleaning up after client disconnect: %s/%s/%s", - crm_str(cib_client->name), - cib_client->channel_name, - cib_client->id); - - if(cib_client->id != NULL) { - if(!g_hash_table_remove(client_list, cib_client->id)) { - crm_err("Client %s not found in the hashtable", - cib_client->name); - } - } - } - - if(cib_shutdown_flag && g_hash_table_size(client_list) == 0) { - crm_info("All clients disconnected..."); - initiate_exit(); - } - - return FALSE; + if (channel == NULL) { + CRM_LOG_ASSERT(cib_client == NULL); + + } else if (cib_client == NULL) { + crm_err("No client"); + + } else { + CRM_LOG_ASSERT(channel->ch_status != IPC_CONNECT); + crm_debug_2("Cleaning up after client disconnect: %s/%s/%s", + crm_str(cib_client->name), cib_client->channel_name, cib_client->id); + + if (cib_client->id != NULL) { + if (!g_hash_table_remove(client_list, cib_client->id)) { + crm_err("Client %s not found in the hashtable", cib_client->name); + } + } + } + + if (cib_shutdown_flag && g_hash_table_size(client_list) == 0) { + crm_info("All clients disconnected..."); + initiate_exit(); + } + + return FALSE; } void -cib_ha_peer_callback(HA_Message * msg, void* private_data) +cib_ha_peer_callback(HA_Message * msg, void *private_data) { xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__); + cib_peer_callback(xml, private_data); free_xml(xml); } void -cib_peer_callback(xmlNode * msg, void* private_data) +cib_peer_callback(xmlNode * msg, void *private_data) { crm_node_t *node = NULL; const char *reason = NULL; const char *originator = crm_element_value(msg, F_ORIG); - - if(originator == NULL || crm_str_eq(originator, cib_our_uname, TRUE)) { - /* message is from ourselves */ - return; - - } else if(crm_peer_cache == NULL) { - reason = "membership not established"; - goto bail; + + if (originator == NULL || crm_str_eq(originator, cib_our_uname, TRUE)) { + /* message is from ourselves */ + return; + + } else if (crm_peer_cache == NULL) { + reason = "membership not established"; + goto bail; } node = crm_get_peer(0, originator); - if(node == NULL || (node->processes & crm_proc_cib) == 0) { - reason = "not in our membership"; - goto bail; + if (node == NULL || (node->processes & crm_proc_cib) == 0) { + reason = "not in our membership"; + goto bail; } - - if(crm_element_value(msg, F_CIB_CLIENTNAME) == NULL) { - crm_xml_add(msg, F_CIB_CLIENTNAME, originator); + + if (crm_element_value(msg, F_CIB_CLIENTNAME) == NULL) { + crm_xml_add(msg, F_CIB_CLIENTNAME, originator); } - + /* crm_log_xml(LOG_MSG, "Peer[inbound]", msg); */ cib_process_request(msg, FALSE, TRUE, TRUE, NULL); return; - - bail: - if(reason) { - const char *seq = crm_element_value(msg, F_SEQ); - const char *op = crm_element_value(msg, F_CIB_OPERATION); - crm_warn("Discarding %s message (%s) from %s: %s", op, seq, originator, reason); + + bail: + if (reason) { + const char *seq = crm_element_value(msg, F_SEQ); + const char *op = crm_element_value(msg, F_CIB_OPERATION); + + crm_warn("Discarding %s message (%s) from %s: %s", op, seq, originator, reason); } } void -cib_client_status_callback(const char * node, const char * client, - const char * status, void * private) +cib_client_status_callback(const char *node, const char *client, const char *status, void *private) { crm_node_t *member = NULL; - if(safe_str_eq(client, CRM_SYSTEM_CIB)) { - crm_info("Status update: Client %s/%s now has status [%s]", - node, client, status); - - if(safe_str_eq(status, JOINSTATUS)){ - status = ONLINESTATUS; - - } else if(safe_str_eq(status, LEAVESTATUS)){ - status = OFFLINESTATUS; - } - - member = crm_get_peer(0, node); - if(member == NULL) { - /* Make sure it gets created */ - const char *uuid = get_uuid(node); - member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL); - CRM_ASSERT(member); - } - - crm_update_peer_proc(node, crm_proc_cib, status); + + if (safe_str_eq(client, CRM_SYSTEM_CIB)) { + crm_info("Status update: Client %s/%s now has status [%s]", node, client, status); + + if (safe_str_eq(status, JOINSTATUS)) { + status = ONLINESTATUS; + + } else if (safe_str_eq(status, LEAVESTATUS)) { + status = OFFLINESTATUS; + } + + member = crm_get_peer(0, node); + if (member == NULL) { + /* Make sure it gets created */ + const char *uuid = get_uuid(node); + + member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL); + CRM_ASSERT(member); + } + + crm_update_peer_proc(node, crm_proc_cib, status); } return; } #if SUPPORT_HEARTBEAT extern oc_ev_t *cib_ev_token; static void *ccm_library = NULL; -int (*ccm_api_callback_done)(void *cookie) = NULL; -int (*ccm_api_handle_event)(const oc_ev_t *token) = NULL; +int (*ccm_api_callback_done) (void *cookie) = NULL; +int (*ccm_api_handle_event) (const oc_ev_t * token) = NULL; -gboolean cib_ccm_dispatch(int fd, gpointer user_data) +gboolean +cib_ccm_dispatch(int fd, gpointer user_data) { - int rc = 0; - oc_ev_t *ccm_token = (oc_ev_t*)user_data; - crm_debug_2("received callback"); - - if(ccm_api_handle_event == NULL) { - ccm_api_handle_event = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_handle_event"); - } - - rc = (*ccm_api_handle_event)(ccm_token); - if(0 == rc) { - return TRUE; - } - - crm_err("CCM connection appears to have failed: rc=%d.", rc); - - /* eventually it might be nice to recover and reconnect... but until then... */ - crm_err("Exiting to recover from CCM connection failure"); - exit(2); - - return FALSE; + int rc = 0; + oc_ev_t *ccm_token = (oc_ev_t *) user_data; + + crm_debug_2("received callback"); + + if (ccm_api_handle_event == NULL) { + ccm_api_handle_event = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_handle_event"); + } + + rc = (*ccm_api_handle_event) (ccm_token); + if (0 == rc) { + return TRUE; + } + + crm_err("CCM connection appears to have failed: rc=%d.", rc); + + /* eventually it might be nice to recover and reconnect... but until then... */ + crm_err("Exiting to recover from CCM connection failure"); + exit(2); + + return FALSE; } int current_instance = 0; -void -cib_ccm_msg_callback( - oc_ed_t event, void *cookie, size_t size, const void *data) +void +cib_ccm_msg_callback(oc_ed_t event, void *cookie, size_t size, const void *data) { - gboolean update_id = FALSE; - const oc_ev_membership_t *membership = data; - - CRM_ASSERT(membership != NULL); - - crm_info("Processing CCM event=%s (id=%d)", - ccm_event_name(event), membership->m_instance); - - if(current_instance > membership->m_instance) { - crm_err("Membership instance ID went backwards! %d->%d", - current_instance, membership->m_instance); - CRM_ASSERT(current_instance <= membership->m_instance); - } - - switch(event) { - case OC_EV_MS_NEW_MEMBERSHIP: - case OC_EV_MS_INVALID: - update_id = TRUE; - break; - case OC_EV_MS_PRIMARY_RESTORED: - update_id = TRUE; - break; - case OC_EV_MS_NOT_PRIMARY: - crm_debug_2("Ignoring transitional CCM event: %s", - ccm_event_name(event)); - break; - case OC_EV_MS_EVICTED: - crm_err("Evicted from CCM: %s", ccm_event_name(event)); - break; - default: - crm_err("Unknown CCM event: %d", event); - } - - if(update_id) { - unsigned int lpc = 0; - CRM_CHECK(membership != NULL, return); - - current_instance = membership->m_instance; - - for(lpc=0; lpc < membership->m_n_out; lpc++) { - crm_update_ccm_node( - membership, lpc+membership->m_out_idx, CRM_NODE_LOST, current_instance); - } - - for(lpc=0; lpc < membership->m_n_member; lpc++) { - crm_update_ccm_node( - membership, lpc+membership->m_memb_idx,CRM_NODE_ACTIVE, current_instance); - } - } - - if(ccm_api_callback_done == NULL) { - ccm_api_callback_done = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_callback_done"); - } - (*ccm_api_callback_done)(cookie); - return; + gboolean update_id = FALSE; + const oc_ev_membership_t *membership = data; + + CRM_ASSERT(membership != NULL); + + crm_info("Processing CCM event=%s (id=%d)", ccm_event_name(event), membership->m_instance); + + if (current_instance > membership->m_instance) { + crm_err("Membership instance ID went backwards! %d->%d", + current_instance, membership->m_instance); + CRM_ASSERT(current_instance <= membership->m_instance); + } + + switch (event) { + case OC_EV_MS_NEW_MEMBERSHIP: + case OC_EV_MS_INVALID: + update_id = TRUE; + break; + case OC_EV_MS_PRIMARY_RESTORED: + update_id = TRUE; + break; + case OC_EV_MS_NOT_PRIMARY: + crm_debug_2("Ignoring transitional CCM event: %s", ccm_event_name(event)); + break; + case OC_EV_MS_EVICTED: + crm_err("Evicted from CCM: %s", ccm_event_name(event)); + break; + default: + crm_err("Unknown CCM event: %d", event); + } + + if (update_id) { + unsigned int lpc = 0; + + CRM_CHECK(membership != NULL, return); + + current_instance = membership->m_instance; + + for (lpc = 0; lpc < membership->m_n_out; lpc++) { + crm_update_ccm_node(membership, lpc + membership->m_out_idx, CRM_NODE_LOST, + current_instance); + } + + for (lpc = 0; lpc < membership->m_n_member; lpc++) { + crm_update_ccm_node(membership, lpc + membership->m_memb_idx, CRM_NODE_ACTIVE, + current_instance); + } + } + + if (ccm_api_callback_done == NULL) { + ccm_api_callback_done = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_callback_done"); + } + (*ccm_api_callback_done) (cookie); + return; } #endif gboolean can_write(int flags) { - return TRUE; + return TRUE; } static gboolean cib_force_exit(gpointer data) { - crm_notice("Forcing exit!"); - terminate_cib(__FUNCTION__); - return FALSE; + crm_notice("Forcing exit!"); + terminate_cib(__FUNCTION__); + return FALSE; } void initiate_exit(void) { - int active = 0; - xmlNode *leaving = NULL; - - active = crm_active_peers(crm_proc_cib); - if(active < 2) { - terminate_cib(__FUNCTION__); - return; - } - - crm_info("Sending disconnect notification to %d peers...", active); - - leaving = create_xml_node(NULL, "exit-notification"); - crm_xml_add(leaving, F_TYPE, "cib"); - crm_xml_add(leaving, F_CIB_OPERATION, "cib_shutdown_req"); - - send_cluster_message(NULL, crm_msg_cib, leaving, TRUE); - free_xml(leaving); - - g_timeout_add(crm_get_msec("5s"), cib_force_exit, NULL); + int active = 0; + xmlNode *leaving = NULL; + + active = crm_active_peers(crm_proc_cib); + if (active < 2) { + terminate_cib(__FUNCTION__); + return; + } + + crm_info("Sending disconnect notification to %d peers...", active); + + leaving = create_xml_node(NULL, "exit-notification"); + crm_xml_add(leaving, F_TYPE, "cib"); + crm_xml_add(leaving, F_CIB_OPERATION, "cib_shutdown_req"); + + send_cluster_message(NULL, crm_msg_cib, leaving, TRUE); + free_xml(leaving); + + g_timeout_add(crm_get_msec("5s"), cib_force_exit, NULL); } extern int remote_fd; extern int remote_tls_fd; void -terminate_cib(const char *caller) +terminate_cib(const char *caller) { - if(remote_fd > 0) { - close(remote_fd); + if (remote_fd > 0) { + close(remote_fd); } - if(remote_tls_fd > 0) { - close(remote_tls_fd); + if (remote_tls_fd > 0) { + close(remote_tls_fd); } - #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - cib_ha_connection_destroy(NULL); - return; - } + if (is_openais_cluster()) { + cib_ha_connection_destroy(NULL); + return; + } #endif #if SUPPORT_HEARTBEAT - if(hb_conn != NULL) { - crm_info("%s: Disconnecting heartbeat", caller); - hb_conn->llc_ops->signoff(hb_conn, FALSE); + if (hb_conn != NULL) { + crm_info("%s: Disconnecting heartbeat", caller); + hb_conn->llc_ops->signoff(hb_conn, FALSE); } else { - crm_err("%s: No heartbeat connection", caller); + crm_err("%s: No heartbeat connection", caller); } #endif - + uninitializeCib(); - + crm_info("Exiting..."); - + if (mainloop != NULL && g_main_is_running(mainloop)) { - g_main_quit(mainloop); - + g_main_quit(mainloop); + } else { - exit(LSB_EXIT_OK); + exit(LSB_EXIT_OK); } } diff --git a/cib/cibmon.c b/cib/cibmon.c index 787e5b0eaa..fdbbce638c 100644 --- a/cib/cibmon.c +++ b/cib/cibmon.c @@ -1,263 +1,253 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include - - #include #include #include #include #include <../lib/pengine/unpack.h> #include #ifdef HAVE_GETOPT_H # include #endif int max_failures = 30; int exit_code = cib_ok; gboolean log_diffs = FALSE; gboolean log_updates = FALSE; GMainLoop *mainloop = NULL; void usage(const char *cmd, int exit_status); void cib_connection_destroy(gpointer user_data); void cibmon_shutdown(int nsig); -void cibmon_diff(const char *event, xmlNode *msg); +void cibmon_diff(const char *event, xmlNode * msg); cib_t *cib = NULL; xmlNode *cib_copy = NULL; #define OPTARGS "V?m:du" int main(int argc, char **argv) { - int argerr = 0; - int flag; - int level = 0; - int attempts = 0; - + int argerr = 0; + int flag; + int level = 0; + int attempts = 0; + #ifdef HAVE_GETOPT_H - int option_index = 0; - static struct option long_options[] = { - /* Top-level Options */ - {"verbose", 0, 0, 'V'}, - {"help", 0, 0, '?'}, - {"log-diffs", 0, 0, 'd'}, - {"log-updates", 0, 0, 'u'}, - {"max-conn-fail",1, 0, 'm'}, - {0, 0, 0, 0} - }; + int option_index = 0; + + static struct option long_options[] = { + /* Top-level Options */ + {"verbose", 0, 0, 'V'}, + {"help", 0, 0, '?'}, + {"log-diffs", 0, 0, 'd'}, + {"log-updates", 0, 0, 'u'}, + {"max-conn-fail", 1, 0, 'm'}, + {0, 0, 0, 0} + }; #endif - crm_log_init_quiet(NULL, LOG_INFO, FALSE, FALSE, argc, argv); + crm_log_init_quiet(NULL, LOG_INFO, FALSE, FALSE, argc, argv); + + crm_signal(SIGTERM, cibmon_shutdown); - crm_signal(SIGTERM, cibmon_shutdown); - - while (1) { + while (1) { #ifdef HAVE_GETOPT_H - flag = getopt_long(argc, argv, OPTARGS, - long_options, &option_index); + flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index); #else - flag = getopt(argc, argv, OPTARGS); + flag = getopt(argc, argv, OPTARGS); #endif - if (flag == -1) - break; - - switch(flag) { - case 'V': - level = get_crm_log_level(); - cl_log_enable_stderr(TRUE); - set_crm_log_level(level+1); - break; - case '?': - usage(crm_system_name, LSB_EXIT_OK); - break; - case 'd': - log_diffs = TRUE; - break; - case 'u': - log_updates = TRUE; - break; - case 'm': - max_failures = crm_parse_int(optarg, "30"); - break; - default: - printf("Argument code 0%o (%c)" - " is not (?yet?) supported\n", - flag, flag); - ++argerr; - break; - } - } - - if (optind < argc) { - printf("non-option ARGV-elements: "); - while (optind < argc) - printf("%s ", argv[optind++]); - printf("\n"); - } - - if (optind > argc) { - ++argerr; - } - - if (argerr) { - usage(crm_system_name, LSB_EXIT_GENERIC); - } - - cib = cib_new(); - - do { - sleep(1); - exit_code = cib->cmds->signon( - cib, crm_system_name, cib_query); - - } while(exit_code == cib_connection && attempts++ < max_failures); - - if(exit_code != cib_ok) { - crm_err("Signon to CIB failed: %s", - cib_error2string(exit_code)); - } - - if(exit_code == cib_ok) { - crm_debug("Setting dnotify"); - exit_code = cib->cmds->set_connection_dnotify( - cib, cib_connection_destroy); - } - - crm_debug("Setting diff callback"); - exit_code = cib->cmds->add_notify_callback( - cib, T_CIB_DIFF_NOTIFY, cibmon_diff); - - if(exit_code != cib_ok) { - crm_err("Failed to set %s callback: %s", - T_CIB_DIFF_NOTIFY, cib_error2string(exit_code)); - } - - if(exit_code != cib_ok) { - crm_err("Setup failed, could not monitor CIB actions"); - return -exit_code; - } - - mainloop = g_main_new(FALSE); - crm_info("Starting mainloop"); - g_main_run(mainloop); - crm_debug_3("%s exiting normally", crm_system_name); - fflush(stderr); - return -exit_code; -} + if (flag == -1) + break; + + switch (flag) { + case 'V': + level = get_crm_log_level(); + cl_log_enable_stderr(TRUE); + set_crm_log_level(level + 1); + break; + case '?': + usage(crm_system_name, LSB_EXIT_OK); + break; + case 'd': + log_diffs = TRUE; + break; + case 'u': + log_updates = TRUE; + break; + case 'm': + max_failures = crm_parse_int(optarg, "30"); + break; + default: + printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag); + ++argerr; + break; + } + } + + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + + if (optind > argc) { + ++argerr; + } + + if (argerr) { + usage(crm_system_name, LSB_EXIT_GENERIC); + } + + cib = cib_new(); + + do { + sleep(1); + exit_code = cib->cmds->signon(cib, crm_system_name, cib_query); + + } while (exit_code == cib_connection && attempts++ < max_failures); + + if (exit_code != cib_ok) { + crm_err("Signon to CIB failed: %s", cib_error2string(exit_code)); + } + + if (exit_code == cib_ok) { + crm_debug("Setting dnotify"); + exit_code = cib->cmds->set_connection_dnotify(cib, cib_connection_destroy); + } + + crm_debug("Setting diff callback"); + exit_code = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, cibmon_diff); + + if (exit_code != cib_ok) { + crm_err("Failed to set %s callback: %s", T_CIB_DIFF_NOTIFY, cib_error2string(exit_code)); + } + + if (exit_code != cib_ok) { + crm_err("Setup failed, could not monitor CIB actions"); + return -exit_code; + } + mainloop = g_main_new(FALSE); + crm_info("Starting mainloop"); + g_main_run(mainloop); + crm_debug_3("%s exiting normally", crm_system_name); + fflush(stderr); + return -exit_code; +} void usage(const char *cmd, int exit_status) { - FILE *stream; + FILE *stream; - stream = exit_status != 0 ? stderr : stdout; - fflush(stream); + stream = exit_status != 0 ? stderr : stdout; + fflush(stream); - exit(exit_status); + exit(exit_status); } void cib_connection_destroy(gpointer user_data) { - crm_err("Connection to the CIB terminated... exiting"); - g_main_quit(mainloop); - return; + crm_err("Connection to the CIB terminated... exiting"); + g_main_quit(mainloop); + return; } void -cibmon_diff(const char *event, xmlNode *msg) +cibmon_diff(const char *event, xmlNode * msg) { int rc = -1; const char *op = NULL; unsigned int log_level = LOG_INFO; xmlNode *diff = NULL; xmlNode *cib_last = NULL; - xmlNode *update = get_message_xml(msg, F_CIB_UPDATE); - - if(msg == NULL) { - crm_err("NULL update"); - return; + xmlNode *update = get_message_xml(msg, F_CIB_UPDATE); + + if (msg == NULL) { + crm_err("NULL update"); + return; } - - crm_element_value_int(msg, F_CIB_RC, &rc); + + crm_element_value_int(msg, F_CIB_RC, &rc); op = crm_element_value(msg, F_CIB_OPERATION); diff = get_message_xml(msg, F_CIB_UPDATE_RESULT); - if(rc < cib_ok) { - log_level = LOG_WARNING; - do_crm_log(log_level, "[%s] %s ABORTED: %s", - event, op, cib_error2string(rc)); - return; - } + if (rc < cib_ok) { + log_level = LOG_WARNING; + do_crm_log(log_level, "[%s] %s ABORTED: %s", event, op, cib_error2string(rc)); + return; + } - if(log_diffs) { - log_cib_diff(log_level, diff, op); + if (log_diffs) { + log_cib_diff(log_level, diff, op); } - - if(log_updates && update != NULL) { - do_crm_log_xml(log_level+2, "raw_update", update); + + if (log_updates && update != NULL) { + do_crm_log_xml(log_level + 2, "raw_update", update); } - - if(cib_copy != NULL) { - cib_last = cib_copy; cib_copy = NULL; - rc = cib_process_diff(op, cib_force_diff, NULL, NULL, diff, cib_last, &cib_copy, NULL); - - if(rc != cib_ok) { - crm_debug("Update didn't apply, requesting full copy: %s", cib_error2string(rc)); - free_xml(cib_copy); - cib_copy = NULL; - } + + if (cib_copy != NULL) { + cib_last = cib_copy; + cib_copy = NULL; + rc = cib_process_diff(op, cib_force_diff, NULL, NULL, diff, cib_last, &cib_copy, NULL); + + if (rc != cib_ok) { + crm_debug("Update didn't apply, requesting full copy: %s", cib_error2string(rc)); + free_xml(cib_copy); + cib_copy = NULL; + } } - - if(cib_copy == NULL) { - cib_copy = get_cib_copy(cib); + + if (cib_copy == NULL) { + cib_copy = get_cib_copy(cib); } free_xml(cib_last); } void cibmon_shutdown(int nsig) { exit(LSB_EXIT_OK); } diff --git a/cib/cibpipe.c b/cib/cibpipe.c index bd32da00da..0364beb99f 100644 --- a/cib/cibpipe.c +++ b/cib/cibpipe.c @@ -1,363 +1,355 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #ifdef HAVE_GETOPT_H # include #endif -void usage(const char* cmd, int exit_status); +void usage(const char *cmd, int exit_status); -struct cib_func_entry -{ - const char *op; - gboolean read_only; - cib_op_t fn; +struct cib_func_entry { + const char *op; + gboolean read_only; + cib_op_t fn; }; /* *INDENT-OFF* */ static struct cib_func_entry cib_pipe_ops[] = { {CIB_OP_QUERY, TRUE, cib_process_query}, {CIB_OP_MODIFY, FALSE, cib_process_modify}, {CIB_OP_APPLY_DIFF, FALSE, cib_process_diff}, {CIB_OP_BUMP, FALSE, cib_process_bump}, {CIB_OP_REPLACE, FALSE, cib_process_replace}, {CIB_OP_CREATE, FALSE, cib_process_create}, {CIB_OP_DELETE, FALSE, cib_process_delete}, {CIB_OP_ERASE, FALSE, cib_process_erase}, }; /* *INDENT-ON* */ #define OPTARGS "V?o:QDUCEX:t:MBfRx:P5S$" int -main(int argc, char ** argv) +main(int argc, char **argv) { int lpc; int flag; int rc = 0; int argerr = 0; int max_msg_types = DIMOF(cib_pipe_ops); int command_options = 0; gboolean changed = FALSE; gboolean force_flag = FALSE; gboolean dangerous_cmd = FALSE; - + char *buffer = NULL; const char *section = NULL; const char *input_xml = NULL; const char *input_file = NULL; const char *cib_action = NULL; - + xmlNode *input = NULL; xmlNode *output = NULL; xmlNode *result_cib = NULL; xmlNode *current_cib = NULL; gboolean query = FALSE; cib_op_t *fn = NULL; - + #ifdef HAVE_GETOPT_H int option_index = 0; + static struct option long_options[] = { - {CIB_OP_ERASE, 0, 0, 'E'}, - {CIB_OP_QUERY, 0, 0, 'Q'}, - {CIB_OP_CREATE, 0, 0, 'C'}, - {CIB_OP_REPLACE, 0, 0, 'R'}, - {CIB_OP_UPDATE, 0, 0, 'U'}, - {CIB_OP_MODIFY, 0, 0, 'M'}, - {"patch", 0, 0, 'P'}, - {CIB_OP_DELETE, 0, 0, 'D'}, - {CIB_OP_BUMP, 0, 0, 'B'}, - {"md5-sum", 0, 0, '5'}, - - {"force", 0, 0, 'f'}, - {"xml-file", 1, 0, 'x'}, - {"xml-text", 1, 0, 'X'}, - {"xml-save", 1, 0, 'S'}, - {"obj_type", 1, 0, 'o'}, - - {"version", 0, 0, '$'}, - {"verbose", 0, 0, 'V'}, - {"help", 0, 0, '?'}, - - {0, 0, 0, 0} + {CIB_OP_ERASE, 0, 0, 'E'}, + {CIB_OP_QUERY, 0, 0, 'Q'}, + {CIB_OP_CREATE, 0, 0, 'C'}, + {CIB_OP_REPLACE, 0, 0, 'R'}, + {CIB_OP_UPDATE, 0, 0, 'U'}, + {CIB_OP_MODIFY, 0, 0, 'M'}, + {"patch", 0, 0, 'P'}, + {CIB_OP_DELETE, 0, 0, 'D'}, + {CIB_OP_BUMP, 0, 0, 'B'}, + {"md5-sum", 0, 0, '5'}, + + {"force", 0, 0, 'f'}, + {"xml-file", 1, 0, 'x'}, + {"xml-text", 1, 0, 'X'}, + {"xml-save", 1, 0, 'S'}, + {"obj_type", 1, 0, 'o'}, + + {"version", 0, 0, '$'}, + {"verbose", 0, 0, 'V'}, + {"help", 0, 0, '?'}, + + {0, 0, 0, 0} }; #endif - + crm_log_init_quiet(NULL, LOG_ERR, FALSE, FALSE, argc, argv); while (1) { #ifdef HAVE_GETOPT_H - flag = getopt_long(argc, argv, OPTARGS, - long_options, &option_index); + flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index); #else - flag = getopt(argc, argv, OPTARGS); + flag = getopt(argc, argv, OPTARGS); #endif - if (flag == -1) - break; - - switch(flag) { - case 'E': - cib_action = CIB_OP_ERASE; - dangerous_cmd = TRUE; - break; - case 'Q': - cib_action = CIB_OP_QUERY; - break; - case 'P': - cib_action = CIB_OP_APPLY_DIFF; - break; - case 'S': - cib_action = CIB_OP_SYNC; - break; - case 'U': - case 'M': - cib_action = CIB_OP_MODIFY; - break; - case 'R': - cib_action = CIB_OP_REPLACE; - break; - case 'C': - cib_action = CIB_OP_CREATE; - break; - case 'D': - cib_action = CIB_OP_DELETE; - break; - case '5': - cib_action = "md5-sum"; - break; - case 'd': - cib_action = CIB_OP_DELETE_ALT; - break; - case 'm': - cib_action = CIB_OP_ISMASTER; - command_options |= cib_scope_local; - break; - case 'B': - cib_action = CIB_OP_BUMP; - break; - case 'o': - crm_debug_2("Option %c => %s", flag, optarg); - section = crm_strdup(optarg); - break; - case 'x': - crm_debug_2("Option %c => %s", flag, optarg); - input_file = crm_strdup(optarg); - break; - case 'X': - crm_debug_2("Option %c => %s", flag, optarg); - input_xml = crm_strdup(optarg); - break; - case 'f': - force_flag = TRUE; - command_options |= cib_quorum_override; - break; - case 'V': - alter_debug(DEBUG_INC); - cl_log_enable_stderr(1); - break; - case '?': /* Help message */ - usage(crm_system_name, LSB_EXIT_OK); - break; - case '$': /* Version message */ - crm_help(flag, LSB_EXIT_OK); - break; - default: - ++argerr; - break; - } + if (flag == -1) + break; + + switch (flag) { + case 'E': + cib_action = CIB_OP_ERASE; + dangerous_cmd = TRUE; + break; + case 'Q': + cib_action = CIB_OP_QUERY; + break; + case 'P': + cib_action = CIB_OP_APPLY_DIFF; + break; + case 'S': + cib_action = CIB_OP_SYNC; + break; + case 'U': + case 'M': + cib_action = CIB_OP_MODIFY; + break; + case 'R': + cib_action = CIB_OP_REPLACE; + break; + case 'C': + cib_action = CIB_OP_CREATE; + break; + case 'D': + cib_action = CIB_OP_DELETE; + break; + case '5': + cib_action = "md5-sum"; + break; + case 'd': + cib_action = CIB_OP_DELETE_ALT; + break; + case 'm': + cib_action = CIB_OP_ISMASTER; + command_options |= cib_scope_local; + break; + case 'B': + cib_action = CIB_OP_BUMP; + break; + case 'o': + crm_debug_2("Option %c => %s", flag, optarg); + section = crm_strdup(optarg); + break; + case 'x': + crm_debug_2("Option %c => %s", flag, optarg); + input_file = crm_strdup(optarg); + break; + case 'X': + crm_debug_2("Option %c => %s", flag, optarg); + input_xml = crm_strdup(optarg); + break; + case 'f': + force_flag = TRUE; + command_options |= cib_quorum_override; + break; + case 'V': + alter_debug(DEBUG_INC); + cl_log_enable_stderr(1); + break; + case '?': /* Help message */ + usage(crm_system_name, LSB_EXIT_OK); + break; + case '$': /* Version message */ + crm_help(flag, LSB_EXIT_OK); + break; + default: + ++argerr; + break; + } } if (cib_action == NULL) { - ++argerr; + ++argerr; } - + if (optind > argc) { - ++argerr; + ++argerr; } - + if (argerr) { - usage(crm_system_name, LSB_EXIT_GENERIC); + usage(crm_system_name, LSB_EXIT_GENERIC); } - - if(dangerous_cmd && force_flag == FALSE) { - fprintf(stderr, "The supplied command is considered dangerous." - " To prevent accidental destruction of the cluster," - " the --force flag is required in order to proceed.\n"); - fflush(stderr); - usage(crm_system_name, LSB_EXIT_GENERIC); + + if (dangerous_cmd && force_flag == FALSE) { + fprintf(stderr, "The supplied command is considered dangerous." + " To prevent accidental destruction of the cluster," + " the --force flag is required in order to proceed.\n"); + fflush(stderr); + usage(crm_system_name, LSB_EXIT_GENERIC); } - if(input_file != NULL) { - input = filename2xml(input_file); - if(input == NULL) { - fprintf(stderr, "Couldn't parse input file: %s\n", input_file); - return 1; - } - - } else if(input_xml != NULL) { - input = string2xml(input_xml); - if(input == NULL) { - fprintf(stderr, "Couldn't parse input string: %s\n", input_xml); - return 1; - } + if (input_file != NULL) { + input = filename2xml(input_file); + if (input == NULL) { + fprintf(stderr, "Couldn't parse input file: %s\n", input_file); + return 1; + } + + } else if (input_xml != NULL) { + input = string2xml(input_xml); + if (input == NULL) { + fprintf(stderr, "Couldn't parse input string: %s\n", input_xml); + return 1; + } } - if(input && safe_str_eq(cib_action, CIB_OP_QUERY)) { - current_cib = copy_xml(input); + if (input && safe_str_eq(cib_action, CIB_OP_QUERY)) { + current_cib = copy_xml(input); } else { - current_cib = stdin2xml(); - if(current_cib == NULL && safe_str_neq(cib_action, CIB_OP_ERASE)) { - fprintf(stderr, "Couldn't parse existing CIB from STDIN.\n"); - return 1; - } + current_cib = stdin2xml(); + if (current_cib == NULL && safe_str_neq(cib_action, CIB_OP_ERASE)) { + fprintf(stderr, "Couldn't parse existing CIB from STDIN.\n"); + return 1; + } } - - - if(current_cib == NULL) { - current_cib = createEmptyCib(); + + if (current_cib == NULL) { + current_cib = createEmptyCib(); } result_cib = copy_xml(current_cib); - if(safe_str_eq(cib_action, "md5-sum")) { - char *digest = NULL; - digest = calculate_on_disk_digest(current_cib); - fprintf(stdout, "%s\n", crm_str(digest)); - crm_free(digest); - return 0; + if (safe_str_eq(cib_action, "md5-sum")) { + char *digest = NULL; + + digest = calculate_on_disk_digest(current_cib); + fprintf(stdout, "%s\n", crm_str(digest)); + crm_free(digest); + return 0; } - /* read local config file */ - if(cib_action == NULL) { - crm_err("No operation specified"); - return cib_operation; + if (cib_action == NULL) { + crm_err("No operation specified"); + return cib_operation; } for (lpc = 0; lpc < max_msg_types; lpc++) { - if (safe_str_eq(cib_action, cib_pipe_ops[lpc].op)) { - fn = &(cib_pipe_ops[lpc].fn); - query = cib_pipe_ops[lpc].read_only; - break; - } + if (safe_str_eq(cib_action, cib_pipe_ops[lpc].op)) { + fn = &(cib_pipe_ops[lpc].fn); + query = cib_pipe_ops[lpc].read_only; + break; + } } - - if(fn == NULL) { - rc = cib_NOTSUPPORTED; + + if (fn == NULL) { + rc = cib_NOTSUPPORTED; } else { - rc = cib_perform_op(cib_action, command_options, fn, query, - section, NULL, input, TRUE, &changed, - current_cib, &result_cib, NULL, &output); + rc = cib_perform_op(cib_action, command_options, fn, query, + section, NULL, input, TRUE, &changed, + current_cib, &result_cib, NULL, &output); } - if(rc != cib_ok) { - fprintf(stderr, "Call failed: %s\n", cib_error2string(rc)); - fprintf(stdout, "%c", 0); - return -rc; + if (rc != cib_ok) { + fprintf(stderr, "Call failed: %s\n", cib_error2string(rc)); + fprintf(stdout, "%c", 0); + return -rc; } cl_log_args(argc, argv); - - if(output) { - buffer = dump_xml_formatted(output); + + if (output) { + buffer = dump_xml_formatted(output); } else { - buffer = dump_xml_formatted(result_cib); + buffer = dump_xml_formatted(result_cib); } fprintf(stdout, "%s\n", buffer); fflush(stdout); - + crm_info("Done"); return 0; } - - void -usage(const char* cmd, int exit_status) +usage(const char *cmd, int exit_status) { - FILE* stream; + FILE *stream; stream = exit_status ? stderr : stdout; fprintf(stream, "usage: %s -Q -(x|X)\n", cmd); fprintf(stream, "usage: %s -Q -(x|X) | %s [-%s] | %s [-%s] | ...\n", - cmd, cmd, OPTARGS, cmd, OPTARGS); + cmd, cmd, OPTARGS, cmd, OPTARGS); fprintf(stream, "usage: cibadmin -Q | %s [-%s] | %s [-%s] | ...\n", - cmd, OPTARGS, cmd, OPTARGS); + cmd, OPTARGS, cmd, OPTARGS); fprintf(stream, "\nOptions\n"); - fprintf(stream, "\t--%s (-%c) \tobject type being operated on\n", - "obj_type", 'o'); - fprintf(stream, "\t\tValid values are:" - " nodes, resources, constraints, crm_config, status\n"); + fprintf(stream, "\t--%s (-%c) \tobject type being operated on\n", "obj_type", 'o'); + fprintf(stream, "\t\tValid values are:" " nodes, resources, constraints, crm_config, status\n"); fprintf(stream, "\t--%s (-%c)\tturn on debug info." - " additional instance increase verbosity\n", "verbose", 'V'); + " additional instance increase verbosity\n", "verbose", 'V'); fprintf(stream, "\t--%s (-%c)\tthis help message\n", "help", '?'); - + fprintf(stream, "\nCommands\n"); - fprintf(stream, "\t--%s (-%c)\tErase the contents of the whole CIB\n", - CIB_OP_ERASE, 'E'); - fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_QUERY, 'Q'); + fprintf(stream, "\t--%s (-%c)\tErase the contents of the whole CIB\n", CIB_OP_ERASE, 'E'); + fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_QUERY, 'Q'); fprintf(stream, "\t--%s (-%c)\tCreate an object that does not yet exist\n", CIB_OP_CREATE, 'C'); - fprintf(stream, "\t--%s (-%c)\tRecursivly update an object in the CIB\n", - CIB_OP_UPDATE, 'U'); - fprintf(stream, "\t--%s (-%c)\tFind the object somewhere in the CIB's XML tree and update it as --"CIB_OP_UPDATE" would\n", CIB_OP_MODIFY, 'M'); - fprintf(stream, "\t--%s (-%c)\tRecursivly replace an object in the CIB\n", - CIB_OP_REPLACE,'R'); + fprintf(stream, "\t--%s (-%c)\tRecursivly update an object in the CIB\n", CIB_OP_UPDATE, 'U'); + fprintf(stream, + "\t--%s (-%c)\tFind the object somewhere in the CIB's XML tree and update it as --" + CIB_OP_UPDATE " would\n", CIB_OP_MODIFY, 'M'); + fprintf(stream, "\t--%s (-%c)\tRecursivly replace an object in the CIB\n", CIB_OP_REPLACE, 'R'); fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_DELETE, 'D'); fprintf(stream, "\t\t\tDelete the first object matching the supplied criteria\n"); fprintf(stream, "\t\t\tEg. \n"); - fprintf(stream, "\t\t\tThe tagname and all attributes must match in order for the element to be deleted\n"); - - fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_BUMP, 'B'); - fprintf(stream, "\t--%s (-%c)\t\tCalculate the configuration's digest.\n", - "md5-sum", '5'); + fprintf(stream, + "\t\t\tThe tagname and all attributes must match in order for the element to be deleted\n"); + + fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_BUMP, 'B'); + fprintf(stream, "\t--%s (-%c)\t\tCalculate the configuration's digest.\n", "md5-sum", '5'); fprintf(stream, "\nXML data\n"); - fprintf(stream, "\t--%s (-%c) \tRetrieve XML from the named file\n", - "xml-file", 'x'); + fprintf(stream, "\t--%s (-%c) \tRetrieve XML from the named file\n", "xml-file", 'x'); fprintf(stream, "\t--%s (-%c) \tRetrieve XML from the supplied string\n", - "xml-text", 'X'); + "xml-text", 'X'); fprintf(stream, "\t--%s (-%c) \tSave the XML output to the named file\n", - "xml-save", 'S'); + "xml-save", 'S'); fprintf(stream, "\nNOTE: The current CIB is assumed to be passed in via stdin," - " unless -Q is used in which case -x or -X are also acceptable\n"); + " unless -Q is used in which case -x or -X are also acceptable\n"); fflush(stream); - + exit(exit_status); } diff --git a/cib/common.c b/cib/common.c index bd85b70753..95472aae92 100644 --- a/cib/common.c +++ b/cib/common.c @@ -1,346 +1,347 @@ /* * Copyright (C) 2008 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" extern gboolean cib_is_master; -extern const char* cib_root; +extern const char *cib_root; gboolean stand_alone = FALSE; extern enum cib_errors cib_status; extern gboolean can_write(int flags); -extern enum cib_errors cib_perform_command( - xmlNode *request, xmlNode **reply, xmlNode **cib_diff, gboolean privileged); +extern enum cib_errors cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, + gboolean privileged); static xmlNode * -cib_prepare_common(xmlNode *root, const char *section) +cib_prepare_common(xmlNode * root, const char *section) { xmlNode *data = NULL; - + /* extract the CIB from the fragment */ - if(root == NULL) { - return NULL; + if (root == NULL) { + return NULL; - } else if(safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT) - || safe_str_eq(crm_element_name(root), F_CRM_DATA) - || safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) { - data = first_named_child(root, XML_TAG_CIB); + } else if (safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT) + || safe_str_eq(crm_element_name(root), F_CRM_DATA) + || safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) { + data = first_named_child(root, XML_TAG_CIB); } else { - data = root; + data = root; } /* grab the section specified for the command */ - if(section != NULL - && data != NULL - && crm_str_eq(crm_element_name(data), XML_TAG_CIB, TRUE)){ - data = get_object_root(section, data); + if (section != NULL && data != NULL && crm_str_eq(crm_element_name(data), XML_TAG_CIB, TRUE)) { + data = get_object_root(section, data); } /* crm_log_xml_debug_4(root, "cib:input"); */ return data; } static enum cib_errors -cib_prepare_none(xmlNode *request, xmlNode **data, const char **section) +cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section) { *data = NULL; *section = crm_element_value(request, F_CIB_SECTION); return cib_ok; } static enum cib_errors -cib_prepare_data(xmlNode *request, xmlNode **data, const char **section) +cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section) { xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA); + *section = crm_element_value(request, F_CIB_SECTION); *data = cib_prepare_common(input_fragment, *section); /* crm_log_xml_debug(*data, "data"); */ return cib_ok; } static enum cib_errors -cib_prepare_sync(xmlNode *request, xmlNode **data, const char **section) +cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section) { *data = NULL; *section = crm_element_value(request, F_CIB_SECTION); return cib_ok; } static enum cib_errors -cib_prepare_diff(xmlNode *request, xmlNode **data, const char **section) +cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section) { xmlNode *input_fragment = NULL; const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE); *data = NULL; *section = NULL; - if(crm_is_true(update)) { - input_fragment = get_message_xml(request,F_CIB_UPDATE_DIFF); - + if (crm_is_true(update)) { + input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF); + } else { - input_fragment = get_message_xml(request, F_CIB_CALLDATA); + input_fragment = get_message_xml(request, F_CIB_CALLDATA); } - CRM_CHECK(input_fragment != NULL,crm_log_xml(LOG_WARNING, "no input", request)); + CRM_CHECK(input_fragment != NULL, crm_log_xml(LOG_WARNING, "no input", request)); *data = cib_prepare_common(input_fragment, NULL); return cib_ok; } static enum cib_errors -cib_cleanup_query(int options, xmlNode **data, xmlNode **output) +cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output) { CRM_LOG_ASSERT(*data == NULL); - if((options & cib_no_children) - || safe_str_eq(crm_element_name(*output), "xpath-query")) { - free_xml(*output); + if ((options & cib_no_children) + || safe_str_eq(crm_element_name(*output), "xpath-query")) { + free_xml(*output); } return cib_ok; } static enum cib_errors -cib_cleanup_data(int options, xmlNode **data, xmlNode **output) +cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output) { free_xml(*output); *data = NULL; return cib_ok; } static enum cib_errors -cib_cleanup_output(int options, xmlNode **data, xmlNode **output) +cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output) { free_xml(*output); return cib_ok; } static enum cib_errors -cib_cleanup_none(int options, xmlNode **data, xmlNode **output) +cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output) { CRM_LOG_ASSERT(*data == NULL); CRM_LOG_ASSERT(*output == NULL); return cib_ok; } static enum cib_errors -cib_cleanup_sync(int options, xmlNode **data, xmlNode **output) +cib_cleanup_sync(int options, xmlNode ** data, xmlNode ** output) { /* data is non-NULL but doesnt need to be free'd */ CRM_LOG_ASSERT(*data == NULL); CRM_LOG_ASSERT(*output == NULL); return cib_ok; } /* typedef struct cib_operation_s { const char* operation; gboolean modifies_cib; gboolean needs_privileges; gboolean needs_quorum; enum cib_errors (*prepare)(xmlNode *, xmlNode**, const char **); enum cib_errors (*cleanup)(xmlNode**, xmlNode**); enum cib_errors (*fn)( const char *, int, const char *, xmlNode*, xmlNode*, xmlNode**, xmlNode**); } cib_operation_t; */ /* technically bump does modify the cib... * but we want to split the "bump" from the "sync" */ /* *INDENT-OFF* */ static cib_operation_t cib_server_ops[] = { {NULL, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_default}, {CIB_OP_QUERY, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query, cib_process_query}, {CIB_OP_MODIFY, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_modify}, {CIB_OP_APPLY_DIFF,TRUE, TRUE, TRUE, cib_prepare_diff, cib_cleanup_data, cib_server_process_diff}, {CIB_OP_REPLACE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_replace_svr}, {CIB_OP_CREATE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_create}, {CIB_OP_DELETE, TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_delete}, {CIB_OP_SYNC, FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_sync}, {CIB_OP_BUMP, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_bump}, {CIB_OP_ERASE, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_erase}, {CRM_OP_NOOP, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_default}, {CIB_OP_DELETE_ALT,TRUE, TRUE, TRUE, cib_prepare_data, cib_cleanup_data, cib_process_delete_absolute}, {CIB_OP_UPGRADE, TRUE, TRUE, TRUE, cib_prepare_none, cib_cleanup_output, cib_process_upgrade}, {CIB_OP_SLAVE, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite}, {CIB_OP_SLAVEALL, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite}, {CIB_OP_SYNC_ONE, FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_sync_one}, {CIB_OP_MASTER, TRUE, TRUE, FALSE, cib_prepare_data, cib_cleanup_data, cib_process_readwrite}, {CIB_OP_ISMASTER, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_readwrite}, {"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync, cib_process_shutdown_req}, {CRM_OP_QUIT, FALSE, TRUE, FALSE, cib_prepare_none, cib_cleanup_none, cib_process_quit}, {CRM_OP_PING, FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping}, }; /* *INDENT-ON* */ enum cib_errors -cib_get_operation_id(const char *op, int *operation) +cib_get_operation_id(const char *op, int *operation) { static GHashTable *operation_hash = NULL; - if(operation_hash == NULL) { - int lpc = 0; - int max_msg_types = DIMOF(cib_server_ops); + if (operation_hash == NULL) { + int lpc = 0; + int max_msg_types = DIMOF(cib_server_ops); - operation_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); - for (lpc = 1; lpc < max_msg_types; lpc++) { - int *value = malloc(sizeof(int)); - *value = lpc; - g_hash_table_insert(operation_hash, (gpointer)cib_server_ops[lpc].operation, value); - } + operation_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); + for (lpc = 1; lpc < max_msg_types; lpc++) { + int *value = malloc(sizeof(int)); + + *value = lpc; + g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value); + } } - - if(op != NULL) { - int *value = g_hash_table_lookup(operation_hash, op); - if(value) { - *operation = *value; - return cib_ok; - } + + if (op != NULL) { + int *value = g_hash_table_lookup(operation_hash, op); + + if (value) { + *operation = *value; + return cib_ok; + } } crm_err("Operation %s is not valid", op); *operation = -1; return cib_operation; } xmlNode * -cib_msg_copy(xmlNode *msg, gboolean with_data) +cib_msg_copy(xmlNode * msg, gboolean with_data) { - int lpc = 0; - const char *field = NULL; - const char *value = NULL; - xmlNode *value_struct = NULL; - - static const char *field_list[] = { - F_XML_TAGNAME , - F_TYPE , - F_CIB_CLIENTID , - F_CIB_CALLOPTS , - F_CIB_CALLID , - F_CIB_OPERATION , - F_CIB_ISREPLY , - F_CIB_SECTION , - F_CIB_HOST , - F_CIB_RC , - F_CIB_DELEGATED , - F_CIB_OBJID , - F_CIB_OBJTYPE , - F_CIB_EXISTING , - F_CIB_SEENCOUNT , - F_CIB_TIMEOUT , - F_CIB_CALLBACK_TOKEN , - F_CIB_GLOBAL_UPDATE , - F_CIB_CLIENTNAME , + int lpc = 0; + const char *field = NULL; + const char *value = NULL; + xmlNode *value_struct = NULL; + + static const char *field_list[] = { + F_XML_TAGNAME, + F_TYPE, + F_CIB_CLIENTID, + F_CIB_CALLOPTS, + F_CIB_CALLID, + F_CIB_OPERATION, + F_CIB_ISREPLY, + F_CIB_SECTION, + F_CIB_HOST, + F_CIB_RC, + F_CIB_DELEGATED, + F_CIB_OBJID, + F_CIB_OBJTYPE, + F_CIB_EXISTING, + F_CIB_SEENCOUNT, + F_CIB_TIMEOUT, + F_CIB_CALLBACK_TOKEN, + F_CIB_GLOBAL_UPDATE, + F_CIB_CLIENTNAME, #if ENABLE_ACL - F_CIB_USER , + F_CIB_USER, #endif - F_CIB_NOTIFY_TYPE , - F_CIB_NOTIFY_ACTIVATE - }; - - static const char *data_list[] = { - F_CIB_CALLDATA , - F_CIB_UPDATE , - F_CIB_UPDATE_RESULT - }; - - xmlNode *copy = create_xml_node(NULL, "copy"); - CRM_ASSERT(copy != NULL); - - for(lpc = 0; lpc < DIMOF(field_list); lpc++) { - field = field_list[lpc]; - value = crm_element_value(msg, field); - if(value != NULL) { - crm_xml_add(copy, field, value); - } - } - for(lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) { - field = data_list[lpc]; - value_struct = get_message_xml(msg, field); - if(value_struct != NULL) { - add_message_xml(copy, field, value_struct); - } - } - - return copy; + F_CIB_NOTIFY_TYPE, + F_CIB_NOTIFY_ACTIVATE + }; + + static const char *data_list[] = { + F_CIB_CALLDATA, + F_CIB_UPDATE, + F_CIB_UPDATE_RESULT + }; + + xmlNode *copy = create_xml_node(NULL, "copy"); + + CRM_ASSERT(copy != NULL); + + for (lpc = 0; lpc < DIMOF(field_list); lpc++) { + field = field_list[lpc]; + value = crm_element_value(msg, field); + if (value != NULL) { + crm_xml_add(copy, field, value); + } + } + for (lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) { + field = data_list[lpc]; + value_struct = get_message_xml(msg, field); + if (value_struct != NULL) { + add_message_xml(copy, field, value_struct); + } + } + + return copy; } -cib_op_t *cib_op_func(int call_type) +cib_op_t * +cib_op_func(int call_type) { return &(cib_server_ops[call_type].fn); } -gboolean cib_op_modifies(int call_type) +gboolean +cib_op_modifies(int call_type) { return cib_server_ops[call_type].modifies_cib; } -int cib_op_can_run( - int call_type, int call_options, gboolean privileged, gboolean global_update) +int +cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update) { - if(privileged == FALSE && cib_server_ops[call_type].needs_privileges) { - /* abort */ - return cib_not_authorized; + if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) { + /* abort */ + return cib_not_authorized; } #if 0 - if(rc == cib_ok - && stand_alone == FALSE - && global_update == FALSE - && (call_options & cib_quorum_override) == 0 - && cib_server_ops[call_type].needs_quorum) { - return cib_no_quorum; + if (rc == cib_ok + && stand_alone == FALSE + && global_update == FALSE + && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) { + return cib_no_quorum; } #endif return cib_ok; } - -int cib_op_prepare( - int call_type, xmlNode *request, xmlNode **input, const char **section) +int +cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section) { return cib_server_ops[call_type].prepare(request, input, section); } -int cib_op_cleanup( - int call_type, int options, xmlNode **input, xmlNode **output) +int +cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output) { return cib_server_ops[call_type].cleanup(options, input, output); } - diff --git a/cib/io.c b/cib/io.c index 297d764171..b51b122560 100644 --- a/cib/io.c +++ b/cib/io.c @@ -1,692 +1,686 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CIB_SERIES "cib" extern const char *cib_root; -static int cib_wrap=100; - +static int cib_wrap = 100; #define CIB_WRITE_PARANOIA 0 -const char * local_resource_path[] = -{ - XML_CIB_TAG_STATUS, +const char *local_resource_path[] = { + XML_CIB_TAG_STATUS, }; -const char * resource_path[] = -{ - XML_CIB_TAG_RESOURCES, +const char *resource_path[] = { + XML_CIB_TAG_RESOURCES, }; -const char * node_path[] = -{ - XML_CIB_TAG_NODES, +const char *node_path[] = { + XML_CIB_TAG_NODES, }; -const char * constraint_path[] = -{ - XML_CIB_TAG_CONSTRAINTS, +const char *constraint_path[] = { + XML_CIB_TAG_CONSTRAINTS, }; gboolean initialized = FALSE; xmlNode *node_search = NULL; xmlNode *resource_search = NULL; xmlNode *constraint_search = NULL; xmlNode *status_search = NULL; extern gboolean cib_writes_enabled; extern GTRIGSource *cib_writer; extern enum cib_errors cib_status; -int set_connected_peers(xmlNode *xml_obj); +int set_connected_peers(xmlNode * xml_obj); void GHFunc_count_peers(gpointer key, gpointer value, gpointer user_data); int write_cib_contents(gpointer p); extern void cib_cleanup(void); - static gboolean -validate_cib_digest(xmlNode *local_cib, const char *sigfile) +validate_cib_digest(xmlNode * local_cib, const char *sigfile) { - int s_res = -1; - struct stat buf; - char *digest = NULL; - char *expected = NULL; - gboolean passed = FALSE; - FILE *expected_strm = NULL; - int start = 0, length = 0, read_len = 0; - - CRM_ASSERT(sigfile != NULL); - s_res = stat(sigfile, &buf); - - if (s_res != 0) { - crm_warn("No on-disk digest present"); - return TRUE; - } - - if(local_cib != NULL) { - digest = calculate_on_disk_digest(local_cib); - } - - expected_strm = fopen(sigfile, "r"); - if(expected_strm == NULL) { - crm_perror(LOG_ERR,"Could not open signature file %s for reading", sigfile); - goto bail; - } - - start = ftell(expected_strm); - fseek(expected_strm, 0L, SEEK_END); - length = ftell(expected_strm); - fseek(expected_strm, 0L, start); - - CRM_ASSERT(length >= 0); - CRM_ASSERT(start == ftell(expected_strm)); - - if(length > 0) { - crm_debug_3("Reading %d bytes from file", length); - crm_malloc0(expected, (length+1)); - read_len = fread(expected, 1, length, expected_strm); /* Coverity: False positive */ - CRM_ASSERT(read_len == length); - } - fclose(expected_strm); - - bail: - if(expected == NULL) { - crm_err("On-disk digest is empty"); - - } else if(safe_str_eq(expected, digest)) { - crm_debug_2("Digest comparision passed: %s", digest); - passed = TRUE; - - } else { - crm_err("Digest comparision failed: expected %s (%s), calculated %s", - expected, sigfile, digest); - } - - crm_free(digest); - crm_free(expected); - return passed; + int s_res = -1; + struct stat buf; + char *digest = NULL; + char *expected = NULL; + gboolean passed = FALSE; + FILE *expected_strm = NULL; + int start = 0, length = 0, read_len = 0; + + CRM_ASSERT(sigfile != NULL); + s_res = stat(sigfile, &buf); + + if (s_res != 0) { + crm_warn("No on-disk digest present"); + return TRUE; + } + + if (local_cib != NULL) { + digest = calculate_on_disk_digest(local_cib); + } + + expected_strm = fopen(sigfile, "r"); + if (expected_strm == NULL) { + crm_perror(LOG_ERR, "Could not open signature file %s for reading", sigfile); + goto bail; + } + + start = ftell(expected_strm); + fseek(expected_strm, 0L, SEEK_END); + length = ftell(expected_strm); + fseek(expected_strm, 0L, start); + + CRM_ASSERT(length >= 0); + CRM_ASSERT(start == ftell(expected_strm)); + + if (length > 0) { + crm_debug_3("Reading %d bytes from file", length); + crm_malloc0(expected, (length + 1)); + read_len = fread(expected, 1, length, expected_strm); /* Coverity: False positive */ + CRM_ASSERT(read_len == length); + } + fclose(expected_strm); + + bail: + if (expected == NULL) { + crm_err("On-disk digest is empty"); + + } else if (safe_str_eq(expected, digest)) { + crm_debug_2("Digest comparision passed: %s", digest); + passed = TRUE; + + } else { + crm_err("Digest comparision failed: expected %s (%s), calculated %s", + expected, sigfile, digest); + } + + crm_free(digest); + crm_free(expected); + return passed; } static int -write_cib_digest(xmlNode *local_cib, const char *digest_file, char *digest) +write_cib_digest(xmlNode * local_cib, const char *digest_file, char *digest) { - int rc = 0; - char *local_digest = NULL; - FILE *digest_strm = fopen(digest_file, "w"); - - if(digest_strm == NULL) { - crm_perror(LOG_ERR,"Cannot open signature file %s for writing", digest_file); - return -1; - } - - if(digest == NULL) { - local_digest = calculate_on_disk_digest(local_cib); - CRM_ASSERT(digest != NULL); - digest = local_digest; - } - - rc = fprintf(digest_strm, "%s", digest); - if(rc < 0) { - crm_perror(LOG_ERR,"Cannot write to signature file %s", digest_file); - } - - CRM_ASSERT(digest_strm != NULL); - if(fflush(digest_strm) != 0) { - crm_perror(LOG_ERR,"Couldnt flush the contents of %s", digest_file); - rc = -1; - } - - if(fsync(fileno(digest_strm)) < 0) { - crm_perror(LOG_ERR,"Couldnt sync the contents of %s", digest_file); - rc = -1; - } - - fclose(digest_strm); - crm_free(local_digest); - return rc; + int rc = 0; + char *local_digest = NULL; + FILE *digest_strm = fopen(digest_file, "w"); + + if (digest_strm == NULL) { + crm_perror(LOG_ERR, "Cannot open signature file %s for writing", digest_file); + return -1; + } + + if (digest == NULL) { + local_digest = calculate_on_disk_digest(local_cib); + CRM_ASSERT(digest != NULL); + digest = local_digest; + } + + rc = fprintf(digest_strm, "%s", digest); + if (rc < 0) { + crm_perror(LOG_ERR, "Cannot write to signature file %s", digest_file); + } + + CRM_ASSERT(digest_strm != NULL); + if (fflush(digest_strm) != 0) { + crm_perror(LOG_ERR, "Couldnt flush the contents of %s", digest_file); + rc = -1; + } + + if (fsync(fileno(digest_strm)) < 0) { + crm_perror(LOG_ERR, "Couldnt sync the contents of %s", digest_file); + rc = -1; + } + + fclose(digest_strm); + crm_free(local_digest); + return rc; } static gboolean -validate_on_disk_cib(const char *filename, xmlNode **on_disk_cib) +validate_on_disk_cib(const char *filename, xmlNode ** on_disk_cib) { - int s_res = -1; - struct stat buf; - gboolean passed = TRUE; - xmlNode *root = NULL; - - CRM_ASSERT(filename != NULL); - - s_res = stat(filename, &buf); - if (s_res == 0) { - char *sigfile = NULL; - size_t fnsize; - crm_debug_2("Reading cluster configuration from: %s", filename); - root = filename2xml(filename); - - fnsize = strlen(filename) + 5; - crm_malloc0(sigfile, fnsize); - snprintf(sigfile, fnsize, "%s.sig", filename); - if(validate_cib_digest(root, sigfile) == FALSE) { - passed = FALSE; - } - crm_free(sigfile); - } - - if(on_disk_cib != NULL) { - *on_disk_cib = root; - } else { - free_xml(root); - } - - return passed; + int s_res = -1; + struct stat buf; + gboolean passed = TRUE; + xmlNode *root = NULL; + + CRM_ASSERT(filename != NULL); + + s_res = stat(filename, &buf); + if (s_res == 0) { + char *sigfile = NULL; + size_t fnsize; + + crm_debug_2("Reading cluster configuration from: %s", filename); + root = filename2xml(filename); + + fnsize = strlen(filename) + 5; + crm_malloc0(sigfile, fnsize); + snprintf(sigfile, fnsize, "%s.sig", filename); + if (validate_cib_digest(root, sigfile) == FALSE) { + passed = FALSE; + } + crm_free(sigfile); + } + + if (on_disk_cib != NULL) { + *on_disk_cib = root; + } else { + free_xml(root); + } + + return passed; } static int -cib_rename(const char *old, const char *new) +cib_rename(const char *old, const char *new) { int rc = 0; char *automatic = NULL; - if(new == NULL) { - automatic = crm_concat(cib_root, "cib.auto.XXXXXX", '/'); - automatic = mktemp(automatic); - new = automatic; - crm_err("Archiving corrupt or unusable file %s as %s", old, automatic); + if (new == NULL) { + automatic = crm_concat(cib_root, "cib.auto.XXXXXX", '/'); + automatic = mktemp(automatic); + new = automatic; + + crm_err("Archiving corrupt or unusable file %s as %s", old, automatic); } rc = rename(old, new); - if(rc < 0) { - crm_perror(LOG_ERR, "Couldn't rename %s as %s - Disabling disk writes and continuing", old, new); - cib_writes_enabled = FALSE; + if (rc < 0) { + crm_perror(LOG_ERR, "Couldn't rename %s as %s - Disabling disk writes and continuing", old, + new); + cib_writes_enabled = FALSE; } crm_free(automatic); return rc; } /* * It is the callers responsibility to free the output of this function */ -static xmlNode* +static xmlNode * retrieveCib(const char *filename, const char *sigfile, gboolean archive_invalid) { struct stat buf; xmlNode *root = NULL; - - crm_info("Reading cluster configuration from: %s (digest: %s)", - filename, sigfile); - - if(stat(filename, &buf) != 0) { - crm_warn("Cluster configuration not found: %s", filename); - return NULL; - } - - root = filename2xml(filename); - if(root == NULL) { - crm_err("%s exists but does NOT contain valid XML. ", filename); - crm_warn("Continuing but %s will NOT used.", filename); - - } else if(validate_cib_digest(root, sigfile) == FALSE) { - crm_err("Checksum of %s failed! Configuration contents ignored!", filename); - crm_err("Usually this is caused by manual changes, " - "please refer to http://clusterlabs.org/wiki/FAQ#cib_changes_detected"); - crm_warn("Continuing but %s will NOT used.", filename); - free_xml(root); - root = NULL; - - if(archive_invalid) { - /* Archive the original files so the contents are not lost */ - cib_rename(filename, NULL); - cib_rename(sigfile, NULL); - } + + crm_info("Reading cluster configuration from: %s (digest: %s)", filename, sigfile); + + if (stat(filename, &buf) != 0) { + crm_warn("Cluster configuration not found: %s", filename); + return NULL; + } + + root = filename2xml(filename); + if (root == NULL) { + crm_err("%s exists but does NOT contain valid XML. ", filename); + crm_warn("Continuing but %s will NOT used.", filename); + + } else if (validate_cib_digest(root, sigfile) == FALSE) { + crm_err("Checksum of %s failed! Configuration contents ignored!", filename); + crm_err("Usually this is caused by manual changes, " + "please refer to http://clusterlabs.org/wiki/FAQ#cib_changes_detected"); + crm_warn("Continuing but %s will NOT used.", filename); + free_xml(root); + root = NULL; + + if (archive_invalid) { + /* Archive the original files so the contents are not lost */ + cib_rename(filename, NULL); + cib_rename(sigfile, NULL); + } } return root; } -xmlNode* +xmlNode * readCibXmlFile(const char *dir, const char *file, gboolean discard_status) { - int seq = 0; - char *backup_file = NULL; - char *filename = NULL, *sigfile = NULL; - const char *name = NULL; - const char *value = NULL; - const char *validation = NULL; - const char *use_valgrind = getenv("HA_VALGRIND_ENABLED"); - - xmlNode *root = NULL; - xmlNode *status = NULL; - - if(!crm_is_writable(dir, file, CRM_DAEMON_USER, NULL, FALSE)) { - cib_status = cib_bad_permissions; - return NULL; - } - - filename = crm_concat(dir, file, '/'); - sigfile = crm_concat(filename, "sig", '.'); - - cib_status = cib_ok; - root = retrieveCib(filename, sigfile, TRUE); - - if(root == NULL) { - crm_warn("Primary configuration corrupt or unusable, trying backup..."); - seq = get_last_sequence(cib_root, CIB_SERIES); - } - - while(root == NULL) { - struct stat buf; - crm_free(sigfile); - - if(seq == 0) { - seq += cib_wrap; /* unwrap */ - } - - backup_file = generate_series_filename(cib_root, CIB_SERIES, seq-1, FALSE); - sigfile = crm_concat(filename, "sig", '.'); - - if(stat(backup_file, &buf) != 0) { - crm_debug("Backup file %s not found", backup_file); - break; - } - crm_warn("Attempting to load: %s", backup_file); - root = retrieveCib(backup_file, sigfile, FALSE); - seq--; - } - crm_free(backup_file); - - if(root == NULL) { - root = createEmptyCib(); - crm_xml_add(root, XML_ATTR_GENERATION, "0"); - crm_xml_add(root, XML_ATTR_NUMUPDATES, "0"); - crm_xml_add(root, XML_ATTR_GENERATION_ADMIN, "0"); - crm_xml_add(root, XML_ATTR_VALIDATION, LATEST_SCHEMA_VERSION); - crm_warn("Continuing with an empty configuration."); - } - - if(cib_writes_enabled && use_valgrind) { - if(crm_is_true(use_valgrind) || strstr(use_valgrind, "cib")) { - cib_writes_enabled = FALSE; - crm_err("*********************************************************"); - crm_err("*** Disabling disk writes to avoid confusing Valgrind ***"); - crm_err("*********************************************************"); - } - } - - status = find_xml_node(root, XML_CIB_TAG_STATUS, FALSE); - if(discard_status && status != NULL) { - /* strip out the status section if there is one */ - free_xml_from_parent(root, status); - status = NULL; - } - if(status == NULL) { - create_xml_node(root, XML_CIB_TAG_STATUS); - } - - /* Do this before DTD validation happens */ - - /* fill in some defaults */ - name = XML_ATTR_GENERATION_ADMIN; - value = crm_element_value(root, name); - if(value == NULL) { - crm_warn("No value for %s was specified in the configuration.", - name); - crm_warn("The reccomended course of action is to shutdown," - " run crm_verify and fix any errors it reports."); - crm_warn("We will default to zero and continue but may get" - " confused about which configuration to use if" - " multiple nodes are powered up at the same time."); - crm_xml_add_int(root, name, 0); - } - - name = XML_ATTR_GENERATION; - value = crm_element_value(root, name); - if(value == NULL) { - crm_xml_add_int(root, name, 0); - } - - name = XML_ATTR_NUMUPDATES; - value = crm_element_value(root, name); - if(value == NULL) { - crm_xml_add_int(root, name, 0); - } - - /* unset these and require the DC/CCM to update as needed */ - xml_remove_prop(root, XML_ATTR_DC_UUID); - - if(discard_status) { - crm_log_xml_debug(root, "[on-disk]"); - } - - validation = crm_element_value(root, XML_ATTR_VALIDATION); - if(validate_xml(root, NULL, TRUE) == FALSE) { - crm_err("CIB does not validate with %s", crm_str(validation)); - cib_status = cib_dtd_validation; - - } else if(validation == NULL) { - int version = 0; - update_validation(&root, &version, FALSE, FALSE); - if(version > 0) { - crm_notice("Enabling %s validation on" - " the existing (sane) configuration", - get_schema_name(version)); - } else { - crm_err("CIB does not validate with any known DTD or schema"); - cib_status = cib_dtd_validation; - } - } - - crm_free(filename); - crm_free(sigfile); - return root; + int seq = 0; + char *backup_file = NULL; + char *filename = NULL, *sigfile = NULL; + const char *name = NULL; + const char *value = NULL; + const char *validation = NULL; + const char *use_valgrind = getenv("HA_VALGRIND_ENABLED"); + + xmlNode *root = NULL; + xmlNode *status = NULL; + + if (!crm_is_writable(dir, file, CRM_DAEMON_USER, NULL, FALSE)) { + cib_status = cib_bad_permissions; + return NULL; + } + + filename = crm_concat(dir, file, '/'); + sigfile = crm_concat(filename, "sig", '.'); + + cib_status = cib_ok; + root = retrieveCib(filename, sigfile, TRUE); + + if (root == NULL) { + crm_warn("Primary configuration corrupt or unusable, trying backup..."); + seq = get_last_sequence(cib_root, CIB_SERIES); + } + + while (root == NULL) { + struct stat buf; + + crm_free(sigfile); + + if (seq == 0) { + seq += cib_wrap; /* unwrap */ + } + + backup_file = generate_series_filename(cib_root, CIB_SERIES, seq - 1, FALSE); + sigfile = crm_concat(filename, "sig", '.'); + + if (stat(backup_file, &buf) != 0) { + crm_debug("Backup file %s not found", backup_file); + break; + } + crm_warn("Attempting to load: %s", backup_file); + root = retrieveCib(backup_file, sigfile, FALSE); + seq--; + } + crm_free(backup_file); + + if (root == NULL) { + root = createEmptyCib(); + crm_xml_add(root, XML_ATTR_GENERATION, "0"); + crm_xml_add(root, XML_ATTR_NUMUPDATES, "0"); + crm_xml_add(root, XML_ATTR_GENERATION_ADMIN, "0"); + crm_xml_add(root, XML_ATTR_VALIDATION, LATEST_SCHEMA_VERSION); + crm_warn("Continuing with an empty configuration."); + } + + if (cib_writes_enabled && use_valgrind) { + if (crm_is_true(use_valgrind) || strstr(use_valgrind, "cib")) { + cib_writes_enabled = FALSE; + crm_err("*********************************************************"); + crm_err("*** Disabling disk writes to avoid confusing Valgrind ***"); + crm_err("*********************************************************"); + } + } + + status = find_xml_node(root, XML_CIB_TAG_STATUS, FALSE); + if (discard_status && status != NULL) { + /* strip out the status section if there is one */ + free_xml_from_parent(root, status); + status = NULL; + } + if (status == NULL) { + create_xml_node(root, XML_CIB_TAG_STATUS); + } + + /* Do this before DTD validation happens */ + + /* fill in some defaults */ + name = XML_ATTR_GENERATION_ADMIN; + value = crm_element_value(root, name); + if (value == NULL) { + crm_warn("No value for %s was specified in the configuration.", name); + crm_warn("The reccomended course of action is to shutdown," + " run crm_verify and fix any errors it reports."); + crm_warn("We will default to zero and continue but may get" + " confused about which configuration to use if" + " multiple nodes are powered up at the same time."); + crm_xml_add_int(root, name, 0); + } + + name = XML_ATTR_GENERATION; + value = crm_element_value(root, name); + if (value == NULL) { + crm_xml_add_int(root, name, 0); + } + + name = XML_ATTR_NUMUPDATES; + value = crm_element_value(root, name); + if (value == NULL) { + crm_xml_add_int(root, name, 0); + } + + /* unset these and require the DC/CCM to update as needed */ + xml_remove_prop(root, XML_ATTR_DC_UUID); + + if (discard_status) { + crm_log_xml_debug(root, "[on-disk]"); + } + + validation = crm_element_value(root, XML_ATTR_VALIDATION); + if (validate_xml(root, NULL, TRUE) == FALSE) { + crm_err("CIB does not validate with %s", crm_str(validation)); + cib_status = cib_dtd_validation; + + } else if (validation == NULL) { + int version = 0; + + update_validation(&root, &version, FALSE, FALSE); + if (version > 0) { + crm_notice("Enabling %s validation on" + " the existing (sane) configuration", get_schema_name(version)); + } else { + crm_err("CIB does not validate with any known DTD or schema"); + cib_status = cib_dtd_validation; + } + } + + crm_free(filename); + crm_free(sigfile); + return root; } /* * The caller should never free the return value */ -xmlNode* +xmlNode * get_the_CIB(void) { - return the_cib; + return the_cib; } gboolean uninitializeCib(void) { - xmlNode *tmp_cib = the_cib; - - - if(tmp_cib == NULL) { - crm_debug("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_debug("Deallocating the CIB."); - - free_xml(tmp_cib); - - crm_debug("The CIB has been deallocated."); - - return TRUE; + xmlNode *tmp_cib = the_cib; + + if (tmp_cib == NULL) { + crm_debug("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_debug("Deallocating the CIB."); + + free_xml(tmp_cib); + + crm_debug("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(xmlNode *new_cib) +initializeCib(xmlNode * new_cib) { - if(new_cib == NULL) { - return FALSE; - } - - the_cib = new_cib; - initialized = TRUE; - return TRUE; + if (new_cib == NULL) { + return FALSE; + } + + the_cib = new_cib; + initialized = TRUE; + return TRUE; } static void -sync_directory(const char *name) +sync_directory(const char *name) { int fd = 0; DIR *directory = NULL; - + directory = opendir(name); - if(directory == NULL) { - crm_perror(LOG_ERR, "Could not open %s for syncing", name); - return; + if (directory == NULL) { + crm_perror(LOG_ERR, "Could not open %s for syncing", name); + return; } fd = dirfd(directory); - if(fd < 0) { - crm_perror(LOG_ERR,"Could not obtain file descriptor for %s", name); + if (fd < 0) { + crm_perror(LOG_ERR, "Could not obtain file descriptor for %s", name); - } else if(fsync(fd) < 0) { - crm_perror(LOG_ERR,"Could not sync %s", name); + } else if (fsync(fd) < 0) { + crm_perror(LOG_ERR, "Could not sync %s", name); } - if(closedir(directory) < 0) { - crm_perror(LOG_ERR,"Could not close %s after fsync", name); + if (closedir(directory) < 0) { + crm_perror(LOG_ERR, "Could not close %s after fsync", name); } } /* * This method will free the old CIB pointer on success and the new one * on failure. */ int -activateCibXml(xmlNode *new_cib, gboolean to_disk, const char *op) +activateCibXml(xmlNode * new_cib, gboolean to_disk, const char *op) { - xmlNode *saved_cib = the_cib; - - CRM_ASSERT(new_cib != saved_cib); - if(initializeCib(new_cib) == FALSE) { - free_xml(new_cib); - crm_err("Ignoring invalid or NULL CIB"); - - if(saved_cib != NULL) { - crm_warn("Reverting to last known CIB"); - if (initializeCib(saved_cib) == FALSE) { - /* oh we are so dead */ - crm_crit("Couldn't re-initialize the old CIB!"); - cl_flush_logs(); - exit(1); - } - - } else { - crm_crit("Could not write out new CIB and no saved" - " version to revert to"); - } - return cib_ACTIVATION; - } - - free_xml(saved_cib); - if(cib_writes_enabled && cib_status == cib_ok && to_disk) { - crm_debug("Triggering CIB write for %s op", op); - G_main_set_trigger(cib_writer); - } - - return cib_ok; + xmlNode *saved_cib = the_cib; + + CRM_ASSERT(new_cib != saved_cib); + if (initializeCib(new_cib) == FALSE) { + free_xml(new_cib); + crm_err("Ignoring invalid or NULL CIB"); + + if (saved_cib != NULL) { + crm_warn("Reverting to last known CIB"); + if (initializeCib(saved_cib) == FALSE) { + /* oh we are so dead */ + crm_crit("Couldn't re-initialize the old CIB!"); + cl_flush_logs(); + exit(1); + } + + } else { + crm_crit("Could not write out new CIB and no saved" " version to revert to"); + } + return cib_ACTIVATION; + } + + free_xml(saved_cib); + if (cib_writes_enabled && cib_status == cib_ok && to_disk) { + crm_debug("Triggering CIB write for %s op", op); + G_main_set_trigger(cib_writer); + } + + return cib_ok; } void crm_set_env_options(void); int -write_cib_contents(gpointer p) +write_cib_contents(gpointer p) { - int exit_rc = LSB_EXIT_OK; - gboolean need_archive = FALSE; - struct stat buf; - char *digest = NULL; - xmlNode *cib_status_root = NULL; - - xmlNode *local_cib = NULL; - - char *tmp1 = NULL; - char *tmp2 = NULL; - char *digest_file = NULL; - char *primary_file = NULL; - - const char *epoch = NULL; - const char *admin_epoch = NULL; - - if(p) { - /* Synchronous write out */ - local_cib = copy_xml(p); - - } else { - /* A-synchronous write out after a fork() */ - - /* Do nothing until we've re-setup logging */ - crm_set_env_options(); - - /* Don't log anything unless strictly necessary */ - crm_log_level = LOG_ERR; - - /* In theory we can scribble on "the_cib" here and not affect the parent - * But lets be safe anyway - */ - local_cib = copy_xml(the_cib); - } - - epoch = crm_element_value(local_cib, XML_ATTR_GENERATION); - admin_epoch = crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN); - - tmp1 = crm_concat(cib_root, "cib.XXXXXX", '/'); - tmp2 = crm_concat(cib_root, "cib.XXXXXX", '/'); - - primary_file = crm_concat(cib_root, "cib.xml", '/'); - digest_file = crm_concat(primary_file, "sig", '.'); - - /* Always write out with num_updates=0 */ - crm_xml_add(local_cib, XML_ATTR_NUMUPDATES, "0"); - - need_archive = (stat(primary_file, &buf) == 0); - if (need_archive) { - char *backup_file = NULL; - char *backup_digest = NULL; - int seq = get_last_sequence(cib_root, CIB_SERIES); - - /* check the admin didnt modify it underneath us */ - if(validate_on_disk_cib(primary_file, NULL) == FALSE) { - crm_err("%s was manually modified while the cluster was active!", primary_file); - exit_rc = 1; - goto cleanup; - } - - backup_file = generate_series_filename(cib_root, CIB_SERIES, seq, FALSE); - backup_digest = crm_concat(backup_file, "sig", '.'); - - unlink(backup_file); - unlink(backup_digest); - link(primary_file, backup_file); - link(digest_file, backup_digest); - write_last_sequence(cib_root, CIB_SERIES, seq+1, cib_wrap); - sync_directory(cib_root); - - crm_info("Archived previous version as %s", backup_file); - - crm_free(backup_digest); - crm_free(backup_file); - } - - /* Given that we discard the status section on startup - * there is no point writing it out in the first place - * since users just get confused by it - * - * So delete the status section before we write it out - */ - crm_debug("Writing CIB to disk"); - if(p == NULL) { - cib_status_root = find_xml_node(local_cib, XML_CIB_TAG_STATUS, TRUE); - CRM_LOG_ASSERT(cib_status_root != NULL); - - if(cib_status_root != NULL) { - free_xml_from_parent(local_cib, cib_status_root); - } - } - - tmp1 = mktemp(tmp1); /* cib */ - tmp2 = mktemp(tmp2); /* digest */ - - if(write_xml_file(local_cib, tmp1, FALSE) <= 0) { - crm_err("Changes couldn't be written to %s", tmp1); - exit_rc = 2; - goto cleanup; - } - - /* Must calculate the digest after writing as write_xml_file() updates the last-written field */ - digest = calculate_on_disk_digest(local_cib); - crm_info("Wrote version %s.%s.0 of the CIB to disk (digest: %s)", - admin_epoch?admin_epoch:"0", - epoch?epoch:"0", digest); - - if(write_cib_digest(local_cib, tmp2, digest) <= 0) { - crm_err("Digest couldn't be written to %s", tmp2); - exit_rc = 3; - goto cleanup; - } - crm_debug("Wrote digest %s to disk", digest); - CRM_ASSERT(retrieveCib(tmp1, tmp2, FALSE) != NULL); - sync_directory(cib_root); - - crm_debug("Activating %s", tmp1); - cib_rename(tmp1, primary_file); - cib_rename(tmp2, digest_file); - sync_directory(cib_root); - - cleanup: - crm_free(primary_file); - crm_free(digest_file); - crm_free(digest); - crm_free(tmp2); - crm_free(tmp1); - - free_xml(local_cib); - - if(p == NULL) { - /* exit() could potentially affect the parent by closing things it shouldn't - * Use _exit instead - */ - _exit(exit_rc); - } - return exit_rc; + int exit_rc = LSB_EXIT_OK; + gboolean need_archive = FALSE; + struct stat buf; + char *digest = NULL; + xmlNode *cib_status_root = NULL; + + xmlNode *local_cib = NULL; + + char *tmp1 = NULL; + char *tmp2 = NULL; + char *digest_file = NULL; + char *primary_file = NULL; + + const char *epoch = NULL; + const char *admin_epoch = NULL; + + if (p) { + /* Synchronous write out */ + local_cib = copy_xml(p); + + } else { + /* A-synchronous write out after a fork() */ + + /* Do nothing until we've re-setup logging */ + crm_set_env_options(); + + /* Don't log anything unless strictly necessary */ + crm_log_level = LOG_ERR; + + /* In theory we can scribble on "the_cib" here and not affect the parent + * But lets be safe anyway + */ + local_cib = copy_xml(the_cib); + } + + epoch = crm_element_value(local_cib, XML_ATTR_GENERATION); + admin_epoch = crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN); + + tmp1 = crm_concat(cib_root, "cib.XXXXXX", '/'); + tmp2 = crm_concat(cib_root, "cib.XXXXXX", '/'); + + primary_file = crm_concat(cib_root, "cib.xml", '/'); + digest_file = crm_concat(primary_file, "sig", '.'); + + /* Always write out with num_updates=0 */ + crm_xml_add(local_cib, XML_ATTR_NUMUPDATES, "0"); + + need_archive = (stat(primary_file, &buf) == 0); + if (need_archive) { + char *backup_file = NULL; + char *backup_digest = NULL; + int seq = get_last_sequence(cib_root, CIB_SERIES); + + /* check the admin didnt modify it underneath us */ + if (validate_on_disk_cib(primary_file, NULL) == FALSE) { + crm_err("%s was manually modified while the cluster was active!", primary_file); + exit_rc = 1; + goto cleanup; + } + + backup_file = generate_series_filename(cib_root, CIB_SERIES, seq, FALSE); + backup_digest = crm_concat(backup_file, "sig", '.'); + + unlink(backup_file); + unlink(backup_digest); + link(primary_file, backup_file); + link(digest_file, backup_digest); + write_last_sequence(cib_root, CIB_SERIES, seq + 1, cib_wrap); + sync_directory(cib_root); + + crm_info("Archived previous version as %s", backup_file); + + crm_free(backup_digest); + crm_free(backup_file); + } + + /* Given that we discard the status section on startup + * there is no point writing it out in the first place + * since users just get confused by it + * + * So delete the status section before we write it out + */ + crm_debug("Writing CIB to disk"); + if (p == NULL) { + cib_status_root = find_xml_node(local_cib, XML_CIB_TAG_STATUS, TRUE); + CRM_LOG_ASSERT(cib_status_root != NULL); + + if (cib_status_root != NULL) { + free_xml_from_parent(local_cib, cib_status_root); + } + } + + tmp1 = mktemp(tmp1); /* cib */ + tmp2 = mktemp(tmp2); /* digest */ + + if (write_xml_file(local_cib, tmp1, FALSE) <= 0) { + crm_err("Changes couldn't be written to %s", tmp1); + exit_rc = 2; + goto cleanup; + } + + /* Must calculate the digest after writing as write_xml_file() updates the last-written field */ + digest = calculate_on_disk_digest(local_cib); + crm_info("Wrote version %s.%s.0 of the CIB to disk (digest: %s)", + admin_epoch ? admin_epoch : "0", epoch ? epoch : "0", digest); + + if (write_cib_digest(local_cib, tmp2, digest) <= 0) { + crm_err("Digest couldn't be written to %s", tmp2); + exit_rc = 3; + goto cleanup; + } + crm_debug("Wrote digest %s to disk", digest); + CRM_ASSERT(retrieveCib(tmp1, tmp2, FALSE) != NULL); + sync_directory(cib_root); + + crm_debug("Activating %s", tmp1); + cib_rename(tmp1, primary_file); + cib_rename(tmp2, digest_file); + sync_directory(cib_root); + + cleanup: + crm_free(primary_file); + crm_free(digest_file); + crm_free(digest); + crm_free(tmp2); + crm_free(tmp1); + + free_xml(local_cib); + + if (p == NULL) { + /* exit() could potentially affect the parent by closing things it shouldn't + * Use _exit instead + */ + _exit(exit_rc); + } + return exit_rc; } -void GHFunc_count_peers(gpointer key, gpointer value, gpointer user_data) +void +GHFunc_count_peers(gpointer key, gpointer value, gpointer user_data) { - int *active = user_data; - if(safe_str_eq(value, ONLINESTATUS)) { - (*active)++; - - } else if(safe_str_eq(value, JOINSTATUS)) { - (*active)++; - } -} + int *active = user_data; + + if (safe_str_eq(value, ONLINESTATUS)) { + (*active)++; + } else if (safe_str_eq(value, JOINSTATUS)) { + (*active)++; + } +} diff --git a/cib/main.c b/cib/main.c index 3e4c450b56..f6b8e7861d 100644 --- a/cib/main.c +++ b/cib/main.c @@ -1,683 +1,668 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_LIBXML2 # include #endif #ifdef HAVE_GETOPT_H # include #endif #if HAVE_BZLIB_H # include #endif extern int init_remote_listener(int port, gboolean encrypted); extern gboolean stand_alone; gboolean cib_shutdown_flag = FALSE; enum cib_errors cib_status = cib_ok; #if SUPPORT_HEARTBEAT oc_ev_t *cib_ev_token; ll_cluster_t *hb_conn = NULL; -extern void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int ); -gboolean cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name); +extern void oc_ev_special(const oc_ev_t *, oc_ev_class_t, int); +gboolean cib_register_ha(ll_cluster_t * hb_cluster, const char *client_name); #endif -GMainLoop* mainloop = NULL; -const char* cib_root = CRM_CONFIG_DIR; +GMainLoop *mainloop = NULL; +const char *cib_root = CRM_CONFIG_DIR; char *cib_our_uname = NULL; gboolean preserve_status = FALSE; gboolean cib_writes_enabled = TRUE; int remote_fd = 0; int remote_tls_fd = 0; -void usage(const char* cmd, int exit_status); +void usage(const char *cmd, int exit_status); int cib_init(void); void cib_shutdown(int nsig); void cib_ha_connection_destroy(gpointer user_data); gboolean startCib(const char *filename); extern int write_cib_contents(gpointer p); GTRIGSource *cib_writer = NULL; GHashTable *client_list = NULL; GHashTable *config_hash = NULL; char *channel1 = NULL; char *channel2 = NULL; char *channel3 = NULL; char *channel4 = NULL; char *channel5 = NULL; #define OPTARGS "maswr:V?" void cib_cleanup(void); static void cib_enable_writes(int nsig) { crm_info("(Re)enabling disk writes"); cib_writes_enabled = TRUE; } static void cib_diskwrite_complete(gpointer userdata, int status, int signo, int exitcode) { - if(exitcode != LSB_EXIT_OK || signo != 0 || status != 0) { - crm_err("Disk write failed: status=%d, signo=%d, exitcode=%d", - status, signo, exitcode); - - if(cib_writes_enabled) { - crm_err("Disabling disk writes after write failure"); - cib_writes_enabled = FALSE; - } - - } else { - crm_debug_2("Disk write passed"); - } + if (exitcode != LSB_EXIT_OK || signo != 0 || status != 0) { + crm_err("Disk write failed: status=%d, signo=%d, exitcode=%d", status, signo, exitcode); + + if (cib_writes_enabled) { + crm_err("Disabling disk writes after write failure"); + cib_writes_enabled = FALSE; + } + + } else { + crm_debug_2("Disk write passed"); + } } int -main(int argc, char ** argv) +main(int argc, char **argv) { - int flag; - int rc = 0; - int argerr = 0; + int flag; + int rc = 0; + int argerr = 0; + #ifdef HAVE_GETOPT_H - int option_index = 0; + int option_index = 0; /* *INDENT-OFF* */ static struct option long_options[] = { {"per-action-cib", 0, 0, 'a'}, {"stand-alone", 0, 0, 's'}, {"disk-writes", 0, 0, 'w'}, {"cib-root", 1, 0, 'r'}, {"verbose", 0, 0, 'V'}, {"help", 0, 0, '?'}, {"metadata", 0, 0, 'm'}, {0, 0, 0, 0} }; /* *INDENT-ON* */ #endif - struct passwd *pwentry = NULL; - crm_log_init("cib", LOG_INFO, TRUE, FALSE, 0, NULL); - mainloop_add_signal(SIGTERM, cib_shutdown); - mainloop_add_signal(SIGPIPE, cib_enable_writes); - - cib_writer = G_main_add_tempproc_trigger( - G_PRIORITY_LOW, write_cib_contents, "write_cib_contents", - NULL, NULL, NULL, cib_diskwrite_complete); - - /* EnableProcLogging(); */ - set_sigchld_proctrack(G_PRIORITY_HIGH,DEFAULT_MAXDISPATCHTIME); - - crm_peer_init(); - client_list = g_hash_table_new(crm_str_hash, g_str_equal); - - while (1) { + struct passwd *pwentry = NULL; + + crm_log_init("cib", LOG_INFO, TRUE, FALSE, 0, NULL); + mainloop_add_signal(SIGTERM, cib_shutdown); + mainloop_add_signal(SIGPIPE, cib_enable_writes); + + cib_writer = + G_main_add_tempproc_trigger(G_PRIORITY_LOW, write_cib_contents, "write_cib_contents", NULL, + NULL, NULL, cib_diskwrite_complete); + + /* EnableProcLogging(); */ + set_sigchld_proctrack(G_PRIORITY_HIGH, DEFAULT_MAXDISPATCHTIME); + + crm_peer_init(); + client_list = g_hash_table_new(crm_str_hash, g_str_equal); + + while (1) { #ifdef HAVE_GETOPT_H - flag = getopt_long(argc, argv, OPTARGS, - long_options, &option_index); + flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index); #else - flag = getopt(argc, argv, OPTARGS); + flag = getopt(argc, argv, OPTARGS); #endif - if (flag == -1) - break; - - switch(flag) { - case 'V': - alter_debug(DEBUG_INC); - break; - case 's': - stand_alone = TRUE; - preserve_status = TRUE; - cib_writes_enabled = FALSE; - - pwentry = getpwnam(CRM_DAEMON_USER); - CRM_CHECK(pwentry != NULL, - crm_perror(LOG_ERR,"Invalid uid (%s) specified", CRM_DAEMON_USER); - return 100); - - rc = setgid(pwentry->pw_gid); - if(rc < 0) { - crm_perror(LOG_ERR,"Could not set group to %d", pwentry->pw_gid); - return 100; - } - - rc = setuid(pwentry->pw_uid); - if(rc < 0) { - crm_perror(LOG_ERR,"Could not set user to %d", pwentry->pw_uid); - return 100; - } - cl_log_enable_stderr(1); - break; - case '?': /* Help message */ - usage(crm_system_name, LSB_EXIT_OK); - break; - case 'w': - cib_writes_enabled = TRUE; - break; - case 'r': - cib_root = optarg; - break; - case 'm': - cib_metadata(); - return 0; - default: - ++argerr; - break; - } - } - if(argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { - cib_metadata(); - return 0; - } - - if (optind > argc) { - ++argerr; - } - - if (argerr) { - usage(crm_system_name,LSB_EXIT_GENERIC); - } - - if(crm_is_writable(cib_root, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { - crm_err("Bad permissions on %s. Terminating", cib_root); - fprintf(stderr,"ERROR: Bad permissions on %s. See logs for details\n", cib_root); - fflush(stderr); - return 100; - } - - /* read local config file */ - rc = cib_init(); - - CRM_CHECK(g_hash_table_size(client_list) == 0, - crm_warn("Not all clients gone at exit")); - cib_cleanup(); + if (flag == -1) + break; + + switch (flag) { + case 'V': + alter_debug(DEBUG_INC); + break; + case 's': + stand_alone = TRUE; + preserve_status = TRUE; + cib_writes_enabled = FALSE; + + pwentry = getpwnam(CRM_DAEMON_USER); + CRM_CHECK(pwentry != NULL, + crm_perror(LOG_ERR, "Invalid uid (%s) specified", CRM_DAEMON_USER); + return 100); + + rc = setgid(pwentry->pw_gid); + if (rc < 0) { + crm_perror(LOG_ERR, "Could not set group to %d", pwentry->pw_gid); + return 100; + } + + rc = setuid(pwentry->pw_uid); + if (rc < 0) { + crm_perror(LOG_ERR, "Could not set user to %d", pwentry->pw_uid); + return 100; + } + cl_log_enable_stderr(1); + break; + case '?': /* Help message */ + usage(crm_system_name, LSB_EXIT_OK); + break; + case 'w': + cib_writes_enabled = TRUE; + break; + case 'r': + cib_root = optarg; + break; + case 'm': + cib_metadata(); + return 0; + default: + ++argerr; + break; + } + } + if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { + cib_metadata(); + return 0; + } + + if (optind > argc) { + ++argerr; + } + + if (argerr) { + usage(crm_system_name, LSB_EXIT_GENERIC); + } + + if (crm_is_writable(cib_root, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { + crm_err("Bad permissions on %s. Terminating", cib_root); + fprintf(stderr, "ERROR: Bad permissions on %s. See logs for details\n", cib_root); + fflush(stderr); + return 100; + } + + /* read local config file */ + rc = cib_init(); + + CRM_CHECK(g_hash_table_size(client_list) == 0, crm_warn("Not all clients gone at exit")); + cib_cleanup(); #if SUPPORT_HEARTBEAT - if(hb_conn) { - hb_conn->llc_ops->delete(hb_conn); - } + if (hb_conn) { + hb_conn->llc_ops->delete(hb_conn); + } #endif - - crm_info("Done"); - return rc; + + crm_info("Done"); + return rc; } void -cib_cleanup(void) +cib_cleanup(void) { - crm_peer_destroy(); - g_hash_table_destroy(config_hash); - g_hash_table_destroy(client_list); - crm_free(cib_our_uname); + crm_peer_destroy(); + g_hash_table_destroy(config_hash); + g_hash_table_destroy(client_list); + crm_free(cib_our_uname); #if HAVE_LIBXML2 - crm_xml_cleanup(); + crm_xml_cleanup(); #endif - crm_free(channel1); - crm_free(channel2); - crm_free(channel3); - crm_free(channel4); - crm_free(channel5); + crm_free(channel1); + crm_free(channel2); + crm_free(channel3); + crm_free(channel4); + crm_free(channel5); } unsigned long cib_num_ops = 0; const char *cib_stat_interval = "10min"; unsigned long cib_num_local = 0, cib_num_updates = 0, cib_num_fail = 0; unsigned long cib_bad_connects = 0, cib_num_timeouts = 0; longclock_t cib_call_time = 0; gboolean cib_stats(gpointer data); gboolean cib_stats(gpointer data) { - int local_log_level = LOG_DEBUG; - static unsigned long last_stat = 0; - unsigned int cib_calls_ms = 0; - static unsigned long cib_stat_interval_ms = 0; - - if(cib_stat_interval_ms == 0) { - cib_stat_interval_ms = crm_get_msec(cib_stat_interval); - } - - cib_calls_ms = longclockto_ms(cib_call_time); - - if((cib_num_ops - last_stat) > 0) { - unsigned long calls_diff = cib_num_ops - last_stat; - double stat_1 = (1000*cib_calls_ms)/calls_diff; - - local_log_level = LOG_INFO; - do_crm_log(local_log_level, - "Processed %lu operations" - " (%.2fus average, %lu%% utilization) in the last %s", - calls_diff, stat_1, - (100*cib_calls_ms)/cib_stat_interval_ms, - cib_stat_interval); - } - - do_crm_log_unlikely(local_log_level+1, - "\tDetail: %lu operations (%ums total)" - " (%lu local, %lu updates, %lu failures," - " %lu timeouts, %lu bad connects)", - cib_num_ops, cib_calls_ms, cib_num_local, cib_num_updates, - cib_num_fail, cib_bad_connects, cib_num_timeouts); - - last_stat = cib_num_ops; - cib_call_time = 0; - return TRUE; + int local_log_level = LOG_DEBUG; + static unsigned long last_stat = 0; + unsigned int cib_calls_ms = 0; + static unsigned long cib_stat_interval_ms = 0; + + if (cib_stat_interval_ms == 0) { + cib_stat_interval_ms = crm_get_msec(cib_stat_interval); + } + + cib_calls_ms = longclockto_ms(cib_call_time); + + if ((cib_num_ops - last_stat) > 0) { + unsigned long calls_diff = cib_num_ops - last_stat; + double stat_1 = (1000 * cib_calls_ms) / calls_diff; + + local_log_level = LOG_INFO; + do_crm_log(local_log_level, + "Processed %lu operations" + " (%.2fus average, %lu%% utilization) in the last %s", + calls_diff, stat_1, + (100 * cib_calls_ms) / cib_stat_interval_ms, cib_stat_interval); + } + + do_crm_log_unlikely(local_log_level + 1, + "\tDetail: %lu operations (%ums total)" + " (%lu local, %lu updates, %lu failures," + " %lu timeouts, %lu bad connects)", + cib_num_ops, cib_calls_ms, cib_num_local, cib_num_updates, + cib_num_fail, cib_bad_connects, cib_num_timeouts); + + last_stat = cib_num_ops; + cib_call_time = 0; + return TRUE; } #if SUPPORT_HEARTBEAT gboolean ccm_connect(void); -static void ccm_connection_destroy(gpointer user_data) +static void +ccm_connection_destroy(gpointer user_data) { crm_err("CCM connection failed... blocking while we reconnect"); CRM_ASSERT(ccm_connect()); return; } static void *ccm_library = NULL; -gboolean ccm_connect(void) +gboolean +ccm_connect(void) { gboolean did_fail = TRUE; int num_ccm_fails = 0; int max_ccm_fails = 30; int ret; int cib_ev_fd; - int (*ccm_api_register)(oc_ev_t **token) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_register"); - - int (*ccm_api_set_callback)(const oc_ev_t *token, - oc_ev_class_t class, - oc_ev_callback_t *fn, - oc_ev_callback_t **prev_fn) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_set_callback"); - - - void (*ccm_api_special)(const oc_ev_t *, oc_ev_class_t , int ) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_special"); - int (*ccm_api_activate)(const oc_ev_t *token, int *fd) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_activate"); - int (*ccm_api_unregister)(oc_ev_t *token) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_unregister"); - - while(did_fail) { - did_fail = FALSE; - crm_info("Registering with CCM..."); - ret = (*ccm_api_register)(&cib_ev_token); - if (ret != 0) { - did_fail = TRUE; - } - - if(did_fail == FALSE) { - crm_debug_3("Setting up CCM callbacks"); - ret = (*ccm_api_set_callback)( - cib_ev_token, OC_EV_MEMB_CLASS, - cib_ccm_msg_callback, NULL); - if (ret != 0) { - crm_warn("CCM callback not set"); - did_fail = TRUE; - } - } - if(did_fail == FALSE) { - (*ccm_api_special)(cib_ev_token, OC_EV_MEMB_CLASS, 0); - - crm_debug_3("Activating CCM token"); - ret = (*ccm_api_activate)(cib_ev_token, &cib_ev_fd); - if (ret != 0){ - crm_warn("CCM Activation failed"); - did_fail = TRUE; - } - } - - if(did_fail) { - num_ccm_fails++; - (*ccm_api_unregister)(cib_ev_token); - - if(num_ccm_fails < max_ccm_fails){ - crm_warn("CCM Connection failed %d times (%d max)", - num_ccm_fails, max_ccm_fails); - sleep(3); - - } else { - crm_err("CCM Activation failed %d (max) times", - num_ccm_fails); - return FALSE; - } - } + int (*ccm_api_register) (oc_ev_t ** token) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_register"); + + int (*ccm_api_set_callback) (const oc_ev_t * token, + oc_ev_class_t class, + oc_ev_callback_t * fn, + oc_ev_callback_t ** prev_fn) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_set_callback"); + + void (*ccm_api_special) (const oc_ev_t *, oc_ev_class_t, int) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_special"); + int (*ccm_api_activate) (const oc_ev_t * token, int *fd) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_activate"); + int (*ccm_api_unregister) (oc_ev_t * token) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_unregister"); + + while (did_fail) { + did_fail = FALSE; + crm_info("Registering with CCM..."); + ret = (*ccm_api_register) (&cib_ev_token); + if (ret != 0) { + did_fail = TRUE; + } + + if (did_fail == FALSE) { + crm_debug_3("Setting up CCM callbacks"); + ret = (*ccm_api_set_callback) (cib_ev_token, OC_EV_MEMB_CLASS, + cib_ccm_msg_callback, NULL); + if (ret != 0) { + crm_warn("CCM callback not set"); + did_fail = TRUE; + } + } + if (did_fail == FALSE) { + (*ccm_api_special) (cib_ev_token, OC_EV_MEMB_CLASS, 0); + + crm_debug_3("Activating CCM token"); + ret = (*ccm_api_activate) (cib_ev_token, &cib_ev_fd); + if (ret != 0) { + crm_warn("CCM Activation failed"); + did_fail = TRUE; + } + } + + if (did_fail) { + num_ccm_fails++; + (*ccm_api_unregister) (cib_ev_token); + + if (num_ccm_fails < max_ccm_fails) { + crm_warn("CCM Connection failed %d times (%d max)", num_ccm_fails, max_ccm_fails); + sleep(3); + + } else { + crm_err("CCM Activation failed %d (max) times", num_ccm_fails); + return FALSE; + } + } } - + crm_debug("CCM Activation passed... all set to go!"); G_main_add_fd(G_PRIORITY_HIGH, cib_ev_fd, FALSE, - cib_ccm_dispatch, cib_ev_token, - ccm_connection_destroy); - - return TRUE; + cib_ccm_dispatch, cib_ev_token, ccm_connection_destroy); + + return TRUE; } #endif -#if SUPPORT_COROSYNC -static gboolean cib_ais_dispatch(AIS_Message *wrapper, char *data, int sender) +#if SUPPORT_COROSYNC +static gboolean +cib_ais_dispatch(AIS_Message * wrapper, char *data, int sender) { xmlNode *xml = NULL; - if(wrapper->header.id == crm_class_cluster) { - xml = string2xml(data); - if(xml == NULL) { - goto bail; - } - crm_xml_add(xml, F_ORIG, wrapper->sender.uname); - crm_xml_add_int(xml, F_SEQ, wrapper->id); - cib_peer_callback(xml, NULL); + if (wrapper->header.id == crm_class_cluster) { + xml = string2xml(data); + if (xml == NULL) { + goto bail; + } + crm_xml_add(xml, F_ORIG, wrapper->sender.uname); + crm_xml_add_int(xml, F_SEQ, wrapper->id); + cib_peer_callback(xml, NULL); } free_xml(xml); return TRUE; - bail: + bail: crm_err("Invalid XML: '%.120s'", data); return TRUE; } static void cib_ais_destroy(gpointer user_data) { crm_err("AIS connection terminated"); ais_fd_sync = -1; exit(1); } #endif int cib_init(void) { - gboolean was_error = FALSE; - - config_hash = g_hash_table_new_full( - crm_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str); - - if(startCib("cib.xml") == FALSE){ - crm_crit("Cannot start CIB... terminating"); - exit(1); - } - - if(stand_alone == FALSE) { - void *dispatch = cib_ha_peer_callback; - void *destroy = cib_ha_connection_destroy; - - if(is_openais_cluster()) { + gboolean was_error = FALSE; + + config_hash = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + + if (startCib("cib.xml") == FALSE) { + crm_crit("Cannot start CIB... terminating"); + exit(1); + } + + if (stand_alone == FALSE) { + void *dispatch = cib_ha_peer_callback; + void *destroy = cib_ha_connection_destroy; + + if (is_openais_cluster()) { #if SUPPORT_COROSYNC - destroy = cib_ais_destroy; - dispatch = cib_ais_dispatch; + destroy = cib_ais_destroy; + dispatch = cib_ais_dispatch; #endif - } - - if(crm_cluster_connect(&cib_our_uname, NULL, dispatch, destroy, + } + + if (crm_cluster_connect(&cib_our_uname, NULL, dispatch, destroy, #if SUPPORT_HEARTBEAT - &hb_conn + &hb_conn #else - NULL + NULL #endif - ) == FALSE){ - crm_crit("Cannot sign in to the cluster... terminating"); - exit(100); - } + ) == FALSE) { + crm_crit("Cannot sign in to the cluster... terminating"); + exit(100); + } #if 0 - if(is_openais_cluster()) { - crm_info("Requesting the list of configured nodes"); - send_ais_text( - crm_class_members, __FUNCTION__, TRUE, NULL, crm_msg_ais); - } + if (is_openais_cluster()) { + crm_info("Requesting the list of configured nodes"); + send_ais_text(crm_class_members, __FUNCTION__, TRUE, NULL, crm_msg_ais); + } #endif #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - - if(was_error == FALSE) { - if (HA_OK != hb_conn->llc_ops->set_cstatus_callback( - hb_conn, cib_client_status_callback, hb_conn)) { - - crm_err("Cannot set cstatus callback: %s", - hb_conn->llc_ops->errmsg(hb_conn)); - was_error = TRUE; - } - } - - if(was_error == FALSE) { - was_error = (ccm_connect() == FALSE); - } - - if(was_error == FALSE) { - /* Async get client status information in the cluster */ - crm_info("Requesting the list of configured nodes"); - hb_conn->llc_ops->client_status( - hb_conn, NULL, CRM_SYSTEM_CIB, -1); - } - } + if (is_heartbeat_cluster()) { + + if (was_error == FALSE) { + if (HA_OK != + hb_conn->llc_ops->set_cstatus_callback(hb_conn, cib_client_status_callback, + hb_conn)) { + + crm_err("Cannot set cstatus callback: %s", hb_conn->llc_ops->errmsg(hb_conn)); + was_error = TRUE; + } + } + + if (was_error == FALSE) { + was_error = (ccm_connect() == FALSE); + } + + if (was_error == FALSE) { + /* Async get client status information in the cluster */ + crm_info("Requesting the list of configured nodes"); + hb_conn->llc_ops->client_status(hb_conn, NULL, CRM_SYSTEM_CIB, -1); + } + } #endif - - } else { - cib_our_uname = crm_strdup("localhost"); - } - - channel1 = crm_strdup(cib_channel_callback); - was_error = init_server_ipc_comms( - channel1, cib_client_connect, - default_ipc_connection_destroy); - - channel2 = crm_strdup(cib_channel_ro); - was_error = was_error || init_server_ipc_comms( - channel2, cib_client_connect, - default_ipc_connection_destroy); - - channel3 = crm_strdup(cib_channel_rw); - was_error = was_error || init_server_ipc_comms( - channel3, cib_client_connect, - default_ipc_connection_destroy); - - if(stand_alone) { - if(was_error) { - crm_err("Couldnt start"); - return 1; - } - cib_is_master = TRUE; - - /* Create the mainloop and run it... */ - mainloop = g_main_new(FALSE); - crm_info("Starting %s mainloop", crm_system_name); - - g_main_run(mainloop); - return 0; - } - - if(was_error == FALSE) { - /* Create the mainloop and run it... */ - mainloop = g_main_new(FALSE); - crm_info("Starting %s mainloop", crm_system_name); - - g_timeout_add( - crm_get_msec(cib_stat_interval), cib_stats, NULL); - - g_main_run(mainloop); - - } else { - crm_err("Couldnt start all communication channels, exiting."); - } - - return 0; + + } else { + cib_our_uname = crm_strdup("localhost"); + } + + channel1 = crm_strdup(cib_channel_callback); + was_error = init_server_ipc_comms(channel1, cib_client_connect, default_ipc_connection_destroy); + + channel2 = crm_strdup(cib_channel_ro); + was_error = was_error || init_server_ipc_comms(channel2, cib_client_connect, + default_ipc_connection_destroy); + + channel3 = crm_strdup(cib_channel_rw); + was_error = was_error || init_server_ipc_comms(channel3, cib_client_connect, + default_ipc_connection_destroy); + + if (stand_alone) { + if (was_error) { + crm_err("Couldnt start"); + return 1; + } + cib_is_master = TRUE; + + /* Create the mainloop and run it... */ + mainloop = g_main_new(FALSE); + crm_info("Starting %s mainloop", crm_system_name); + + g_main_run(mainloop); + return 0; + } + + if (was_error == FALSE) { + /* Create the mainloop and run it... */ + mainloop = g_main_new(FALSE); + crm_info("Starting %s mainloop", crm_system_name); + + g_timeout_add(crm_get_msec(cib_stat_interval), cib_stats, NULL); + + g_main_run(mainloop); + + } else { + crm_err("Couldnt start all communication channels, exiting."); + } + + return 0; } void -usage(const char* cmd, int exit_status) +usage(const char *cmd, int exit_status) { - FILE* stream; - - stream = exit_status ? stderr : stdout; - - fprintf(stream, "usage: %s [-%s]\n", cmd, OPTARGS); - fprintf(stream, "\t--%s (-%c)\t\tTurn on debug info." - " Additional instances increase verbosity\n", "verbose", 'V'); - fprintf(stream, "\t--%s (-%c)\t\tThis help message\n", "help", '?'); - fprintf(stream, "\t--%s (-%c)\t\tShow configurable cib options\n", "metadata", 'm'); - fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "per-action-cib", 'a'); - fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "stand-alone", 's'); - fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "disk-writes", 'w'); - fprintf(stream, "\t--%s (-%c)\t\tAdvanced use only\n", "cib-root", 'r'); - fflush(stream); - - exit(exit_status); + FILE *stream; + + stream = exit_status ? stderr : stdout; + + fprintf(stream, "usage: %s [-%s]\n", cmd, OPTARGS); + fprintf(stream, "\t--%s (-%c)\t\tTurn on debug info." + " Additional instances increase verbosity\n", "verbose", 'V'); + fprintf(stream, "\t--%s (-%c)\t\tThis help message\n", "help", '?'); + fprintf(stream, "\t--%s (-%c)\t\tShow configurable cib options\n", "metadata", 'm'); + fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "per-action-cib", 'a'); + fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "stand-alone", 's'); + fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "disk-writes", 'w'); + fprintf(stream, "\t--%s (-%c)\t\tAdvanced use only\n", "cib-root", 'r'); + fflush(stream); + + exit(exit_status); } void cib_ha_connection_destroy(gpointer user_data) { - if(cib_shutdown_flag) { - crm_info("Heartbeat disconnection complete... exiting"); - } else { - crm_err("Heartbeat connection lost! Exiting."); - } - - uninitializeCib(); - - crm_info("Exiting..."); - if (mainloop != NULL && g_main_is_running(mainloop)) { - g_main_quit(mainloop); - - } else { - exit(LSB_EXIT_OK); - } -} + if (cib_shutdown_flag) { + crm_info("Heartbeat disconnection complete... exiting"); + } else { + crm_err("Heartbeat connection lost! Exiting."); + } + + uninitializeCib(); + crm_info("Exiting..."); + if (mainloop != NULL && g_main_is_running(mainloop)) { + g_main_quit(mainloop); + + } else { + exit(LSB_EXIT_OK); + } +} static void -disconnect_cib_client(gpointer key, gpointer value, gpointer user_data) +disconnect_cib_client(gpointer key, gpointer value, gpointer user_data) { - cib_client_t *a_client = value; - crm_debug_2("Processing client %s/%s... send=%d, recv=%d", - crm_str(a_client->name), crm_str(a_client->channel_name), - (int)a_client->channel->send_queue->current_qlen, - (int)a_client->channel->recv_queue->current_qlen); - - if(a_client->channel->ch_status == IPC_CONNECT) { - a_client->channel->ops->resume_io(a_client->channel); - if(a_client->channel->send_queue->current_qlen != 0 - || a_client->channel->recv_queue->current_qlen != 0) { - crm_info("Flushed messages to/from %s/%s... send=%d, recv=%d", - crm_str(a_client->name), - crm_str(a_client->channel_name), - (int)a_client->channel->send_queue->current_qlen, - (int)a_client->channel->recv_queue->current_qlen); - } - } - - if(a_client->channel->ch_status == IPC_CONNECT) { - crm_warn("Disconnecting %s/%s...", - crm_str(a_client->name), - crm_str(a_client->channel_name)); - a_client->channel->ops->disconnect(a_client->channel); - } + cib_client_t *a_client = value; + + crm_debug_2("Processing client %s/%s... send=%d, recv=%d", + crm_str(a_client->name), crm_str(a_client->channel_name), + (int)a_client->channel->send_queue->current_qlen, + (int)a_client->channel->recv_queue->current_qlen); + + if (a_client->channel->ch_status == IPC_CONNECT) { + a_client->channel->ops->resume_io(a_client->channel); + if (a_client->channel->send_queue->current_qlen != 0 + || a_client->channel->recv_queue->current_qlen != 0) { + crm_info("Flushed messages to/from %s/%s... send=%d, recv=%d", + crm_str(a_client->name), + crm_str(a_client->channel_name), + (int)a_client->channel->send_queue->current_qlen, + (int)a_client->channel->recv_queue->current_qlen); + } + } + + if (a_client->channel->ch_status == IPC_CONNECT) { + crm_warn("Disconnecting %s/%s...", + crm_str(a_client->name), crm_str(a_client->channel_name)); + a_client->channel->ops->disconnect(a_client->channel); + } } -extern gboolean cib_process_disconnect( - IPC_Channel *channel, cib_client_t *cib_client); +extern gboolean cib_process_disconnect(IPC_Channel * channel, cib_client_t * cib_client); void cib_shutdown(int nsig) { - if(cib_shutdown_flag == FALSE) { - cib_shutdown_flag = TRUE; - crm_debug("Disconnecting %d clients", - g_hash_table_size(client_list)); - g_hash_table_foreach(client_list, disconnect_cib_client, NULL); - crm_info("Disconnected %d clients", - g_hash_table_size(client_list)); - cib_process_disconnect(NULL, NULL); - - } else { - crm_info("Waiting for %d clients to disconnect...", - g_hash_table_size(client_list)); - } + if (cib_shutdown_flag == FALSE) { + cib_shutdown_flag = TRUE; + crm_debug("Disconnecting %d clients", g_hash_table_size(client_list)); + g_hash_table_foreach(client_list, disconnect_cib_client, NULL); + crm_info("Disconnected %d clients", g_hash_table_size(client_list)); + cib_process_disconnect(NULL, NULL); + + } else { + crm_info("Waiting for %d clients to disconnect...", g_hash_table_size(client_list)); + } } gboolean startCib(const char *filename) { - gboolean active = FALSE; - xmlNode *cib = readCibXmlFile(cib_root, filename, !preserve_status); - - CRM_ASSERT(cib != NULL); - - if(activateCibXml(cib, TRUE, "start") == 0) { - int port = 0; - const char *port_s = NULL; - active = TRUE; - - cib_read_config(config_hash, cib); - - port_s = crm_element_value(cib, "remote-tls-port"); - if(port_s) { - port = crm_parse_int(port_s, "0"); - remote_tls_fd = init_remote_listener(port, TRUE); - } - - port_s = crm_element_value(cib, "remote-clear-port"); - if(port_s) { - port = crm_parse_int(port_s, "0"); - remote_fd = init_remote_listener(port, FALSE); - } - - crm_info("CIB Initialization completed successfully"); - } - - return active; + gboolean active = FALSE; + xmlNode *cib = readCibXmlFile(cib_root, filename, !preserve_status); + + CRM_ASSERT(cib != NULL); + + if (activateCibXml(cib, TRUE, "start") == 0) { + int port = 0; + const char *port_s = NULL; + + active = TRUE; + + cib_read_config(config_hash, cib); + + port_s = crm_element_value(cib, "remote-tls-port"); + if (port_s) { + port = crm_parse_int(port_s, "0"); + remote_tls_fd = init_remote_listener(port, TRUE); + } + + port_s = crm_element_value(cib, "remote-clear-port"); + if (port_s) { + port = crm_parse_int(port_s, "0"); + remote_fd = init_remote_listener(port, FALSE); + } + + crm_info("CIB Initialization completed successfully"); + } + + return active; } diff --git a/cib/messages.c b/cib/messages.c index b43dc15f87..72288aa05e 100644 --- a/cib/messages.c +++ b/cib/messages.c @@ -1,459 +1,457 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_DIFF_RETRY 5 #ifdef CIBPIPE gboolean cib_is_master = TRUE; #else gboolean cib_is_master = FALSE; #endif xmlNode *the_cib = NULL; gboolean syncd_once = FALSE; extern const char *cib_our_uname; -enum cib_errors revision_check(xmlNode *cib_update, xmlNode *cib_copy, int flags); -int get_revision(xmlNode *xml_obj, int cur_revision); +enum cib_errors revision_check(xmlNode * cib_update, xmlNode * cib_copy, int flags); +int get_revision(xmlNode * xml_obj, int cur_revision); -enum cib_errors updateList( - xmlNode *local_cib, xmlNode *update_command, xmlNode *failed, - int operation, const char *section); +enum cib_errors updateList(xmlNode * local_cib, xmlNode * update_command, xmlNode * failed, + int operation, const char *section); -gboolean check_generation(xmlNode *newCib, xmlNode *oldCib); +gboolean check_generation(xmlNode * newCib, xmlNode * oldCib); -gboolean update_results( - xmlNode *failed, xmlNode *target, const char *operation, int return_code); +gboolean update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code); -enum cib_errors cib_update_counter( - xmlNode *xml_obj, const char *field, gboolean reset); +enum cib_errors cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset); -enum cib_errors sync_our_cib(xmlNode *request, gboolean all); +enum cib_errors sync_our_cib(xmlNode * request, gboolean all); -extern xmlNode *cib_msg_copy(const xmlNode *msg, gboolean with_data); +extern xmlNode *cib_msg_copy(const xmlNode * msg, gboolean with_data); extern gboolean cib_shutdown_flag; extern void terminate_cib(const char *caller); -enum cib_errors -cib_process_shutdown_req( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_shutdown_req(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { #ifdef CIBPIPE return cib_invalid_argument; #else enum cib_errors result = cib_ok; const char *host = crm_element_value(req, F_ORIG); - + *answer = NULL; - if(crm_element_value(req, F_CIB_ISREPLY) == NULL) { - crm_info("Shutdown REQ from %s", host); - return cib_ok; + if (crm_element_value(req, F_CIB_ISREPLY) == NULL) { + crm_info("Shutdown REQ from %s", host); + return cib_ok; - } else if(cib_shutdown_flag) { - crm_info("Shutdown ACK from %s", host); - terminate_cib(__FUNCTION__); - return cib_ok; + } else if (cib_shutdown_flag) { + crm_info("Shutdown ACK from %s", host); + terminate_cib(__FUNCTION__); + return cib_ok; } else { - crm_err("Shutdown ACK from %s - not shutting down",host); - result = cib_unknown; + crm_err("Shutdown ACK from %s - not shutting down", host); + result = cib_unknown; } - + return result; #endif } -enum cib_errors -cib_process_default( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_default(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { enum cib_errors result = cib_ok; + crm_debug_2("Processing \"%s\" event", op); *answer = NULL; - if(op == NULL) { - result = cib_operation; - crm_err("No operation specified"); - - } else if(strcasecmp(CRM_OP_NOOP, op) == 0) { - ; + if (op == NULL) { + result = cib_operation; + crm_err("No operation specified"); + + } else if (strcasecmp(CRM_OP_NOOP, op) == 0) { + ; } else { - result = cib_NOTSUPPORTED; - crm_err("Action [%s] is not supported by the CIB", op); + result = cib_NOTSUPPORTED; + crm_err("Action [%s] is not supported by the CIB", op); } return result; } -enum cib_errors -cib_process_quit( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_quit(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { enum cib_errors result = cib_ok; + crm_debug_2("Processing \"%s\" event", op); crm_warn("The CRMd has asked us to exit... complying"); exit(0); return result; } -enum cib_errors -cib_process_readwrite( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_readwrite(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { #ifdef CIBPIPE return cib_invalid_argument; #else enum cib_errors result = cib_ok; + crm_debug_2("Processing \"%s\" event", op); - if(safe_str_eq(op, CIB_OP_ISMASTER)) { - if(cib_is_master == TRUE) { - result = cib_ok; - } else { - result = cib_not_master; - } - return result; + if (safe_str_eq(op, CIB_OP_ISMASTER)) { + if (cib_is_master == TRUE) { + result = cib_ok; + } else { + result = cib_not_master; + } + return result; } - if(safe_str_eq(op, CIB_OP_MASTER)) { - if(cib_is_master == FALSE) { - crm_info("We are now in R/W mode"); - cib_is_master = TRUE; - syncd_once = TRUE; - - } else { - crm_debug("We are still in R/W mode"); - } - - } else if(cib_is_master) { - crm_info("We are now in R/O mode"); - cib_is_master = FALSE; + if (safe_str_eq(op, CIB_OP_MASTER)) { + if (cib_is_master == FALSE) { + crm_info("We are now in R/W mode"); + cib_is_master = TRUE; + syncd_once = TRUE; + + } else { + crm_debug("We are still in R/W mode"); + } + + } else if (cib_is_master) { + crm_info("We are now in R/O mode"); + cib_is_master = FALSE; } return result; #endif } -enum cib_errors -cib_process_ping( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_ping(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { #ifdef CIBPIPE return cib_invalid_argument; #else enum cib_errors result = cib_ok; + crm_debug_2("Processing \"%s\" event", op); *answer = createPingAnswerFragment(CRM_SYSTEM_CIB, "ok"); return result; #endif } - -enum cib_errors -cib_process_sync( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_sync(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { #ifdef CIBPIPE return cib_invalid_argument; #else return sync_our_cib(req, TRUE); #endif } -enum cib_errors -cib_process_sync_one( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_sync_one(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { #ifdef CIBPIPE return cib_invalid_argument; #else return sync_our_cib(req, FALSE); #endif } int sync_in_progress = 0; -enum cib_errors -cib_server_process_diff( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_server_process_diff(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { int rc = cib_ok; - if(cib_is_master) { - /* the master is never waiting for a resync */ - sync_in_progress = 0; + if (cib_is_master) { + /* the master is never waiting for a resync */ + sync_in_progress = 0; + } + + if (sync_in_progress > MAX_DIFF_RETRY) { + /* request another full-sync, + * the last request may have been lost + */ + sync_in_progress = 0; } - - if(sync_in_progress > MAX_DIFF_RETRY) { - /* request another full-sync, - * the last request may have been lost - */ - sync_in_progress = 0; - } - - if(sync_in_progress) { - int diff_add_updates = 0; - int diff_add_epoch = 0; - int diff_add_admin_epoch = 0; - - int diff_del_updates = 0; - int diff_del_epoch = 0; - int diff_del_admin_epoch = 0; - - cib_diff_version_details( - input, - &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, - &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); - - sync_in_progress++; - crm_notice("Not applying diff %d.%d.%d -> %d.%d.%d (sync in progress)", - diff_del_admin_epoch,diff_del_epoch,diff_del_updates, - diff_add_admin_epoch,diff_add_epoch,diff_add_updates); - return cib_diff_resync; + + if (sync_in_progress) { + int diff_add_updates = 0; + int diff_add_epoch = 0; + int diff_add_admin_epoch = 0; + + int diff_del_updates = 0; + int diff_del_epoch = 0; + int diff_del_admin_epoch = 0; + + cib_diff_version_details(input, + &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, + &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); + + sync_in_progress++; + crm_notice("Not applying diff %d.%d.%d -> %d.%d.%d (sync in progress)", + diff_del_admin_epoch, diff_del_epoch, diff_del_updates, + diff_add_admin_epoch, diff_add_epoch, diff_add_updates); + return cib_diff_resync; } - rc = cib_process_diff(op, options, section, req, input, existing_cib, result_cib, answer); - - if(rc == cib_diff_resync && cib_is_master == FALSE) { - xmlNode *sync_me = create_xml_node(NULL, "sync-me"); - free_xml(*result_cib); - *result_cib = NULL; - crm_info("Requesting re-sync from peer"); - sync_in_progress++; - - crm_xml_add(sync_me, F_TYPE, "cib"); - crm_xml_add(sync_me, F_CIB_OPERATION, CIB_OP_SYNC_ONE); - crm_xml_add(sync_me, F_CIB_DELEGATED, cib_our_uname); - - if(send_cluster_message(NULL, crm_msg_cib, sync_me, FALSE) == FALSE) { - rc = cib_not_connected; - } - free_xml(sync_me); - - } else if(rc == cib_diff_resync) { - rc = cib_diff_failed; - if(options & cib_force_diff) { - crm_warn("Not requesting full refresh in R/W mode"); - } + + if (rc == cib_diff_resync && cib_is_master == FALSE) { + xmlNode *sync_me = create_xml_node(NULL, "sync-me"); + + free_xml(*result_cib); + *result_cib = NULL; + crm_info("Requesting re-sync from peer"); + sync_in_progress++; + + crm_xml_add(sync_me, F_TYPE, "cib"); + crm_xml_add(sync_me, F_CIB_OPERATION, CIB_OP_SYNC_ONE); + crm_xml_add(sync_me, F_CIB_DELEGATED, cib_our_uname); + + if (send_cluster_message(NULL, crm_msg_cib, sync_me, FALSE) == FALSE) { + rc = cib_not_connected; + } + free_xml(sync_me); + + } else if (rc == cib_diff_resync) { + rc = cib_diff_failed; + if (options & cib_force_diff) { + crm_warn("Not requesting full refresh in R/W mode"); + } } - + return rc; } -enum cib_errors -cib_process_replace_svr( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_replace_svr(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { const char *tag = crm_element_name(input); - enum cib_errors rc = cib_process_replace( - op, options, section, req, input, existing_cib, result_cib, answer); - if(rc == cib_ok && safe_str_eq(tag, XML_TAG_CIB)) { - sync_in_progress = 0; + enum cib_errors rc = + cib_process_replace(op, options, section, req, input, existing_cib, result_cib, answer); + if (rc == cib_ok && safe_str_eq(tag, XML_TAG_CIB)) { + sync_in_progress = 0; } return rc; } static int -delete_cib_object(xmlNode *parent, xmlNode *delete_spec) +delete_cib_object(xmlNode * parent, xmlNode * delete_spec) { const char *object_name = NULL; const char *object_id = NULL; xmlNode *equiv_node = NULL; int result = cib_ok; - - if(delete_spec != NULL) { - object_name = crm_element_name(delete_spec); + + if (delete_spec != NULL) { + object_name = crm_element_name(delete_spec); } object_id = crm_element_value(delete_spec, XML_ATTR_ID); - crm_debug_3("Processing: <%s id=%s>", - crm_str(object_name), crm_str(object_id)); - - if(delete_spec == NULL) { - result = cib_NOOBJECT; + crm_debug_3("Processing: <%s id=%s>", crm_str(object_name), crm_str(object_id)); - } else if(parent == NULL) { - result = cib_NOPARENT; + if (delete_spec == NULL) { + result = cib_NOOBJECT; + + } else if (parent == NULL) { + result = cib_NOPARENT; + + } else if (object_id == NULL) { + /* placeholder object */ + equiv_node = find_xml_node(parent, object_name, FALSE); - } else if(object_id == NULL) { - /* placeholder object */ - equiv_node = find_xml_node(parent, object_name, FALSE); - } else { - equiv_node = find_entity(parent, object_name, object_id); + equiv_node = find_entity(parent, object_name, object_id); } - if(result != cib_ok) { - ; /* nothing */ - - } else if(equiv_node == NULL) { - result = cib_ok; + if (result != cib_ok) { + ; /* nothing */ + + } else if (equiv_node == NULL) { + result = cib_ok; - } else if(xml_has_children(delete_spec) == FALSE) { - /* only leaves are deleted */ - crm_debug("Removing leaf: <%s id=%s>", - crm_str(object_name), crm_str(object_id)); - zap_xml_from_parent(parent, equiv_node); + } else if (xml_has_children(delete_spec) == FALSE) { + /* only leaves are deleted */ + crm_debug("Removing leaf: <%s id=%s>", crm_str(object_name), crm_str(object_id)); + zap_xml_from_parent(parent, equiv_node); } else { - xmlNode *child = NULL; - for(child = __xml_first_child(delete_spec); child != NULL; child = __xml_next(child)) { - int tmp_result = delete_cib_object(equiv_node, child); - /* only the first error is likely to be interesting */ - if(tmp_result != cib_ok && result == cib_ok) { - result = tmp_result; - } - } + xmlNode *child = NULL; + + for (child = __xml_first_child(delete_spec); child != NULL; child = __xml_next(child)) { + int tmp_result = delete_cib_object(equiv_node, child); + + /* only the first error is likely to be interesting */ + if (tmp_result != cib_ok && result == cib_ok) { + result = tmp_result; + } + } } return result; } -enum cib_errors -cib_process_delete_absolute( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_delete_absolute(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { xmlNode *failed = NULL; enum cib_errors result = cib_ok; xmlNode *update_section = NULL; - + crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); - if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { - section = NULL; + if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { + section = NULL; - } else if(safe_str_eq(XML_TAG_CIB, section)) { - section = NULL; + } else if (safe_str_eq(XML_TAG_CIB, section)) { + section = NULL; - } else if(safe_str_eq(crm_element_name(input), XML_TAG_CIB)) { - section = NULL; + } else if (safe_str_eq(crm_element_name(input), XML_TAG_CIB)) { + section = NULL; } CRM_CHECK(strcasecmp(CIB_OP_DELETE, op) == 0, return cib_operation); - - if(input == NULL) { - crm_err("Cannot perform modification with no data"); - return cib_NOOBJECT; + + if (input == NULL) { + crm_err("Cannot perform modification with no data"); + return cib_NOOBJECT; } - + failed = create_xml_node(NULL, XML_TAG_FAILED); update_section = get_object_root(section, *result_cib); result = delete_cib_object(update_section, input); update_results(failed, input, op, result); - - if(xml_has_children(failed)) { - CRM_CHECK(result != cib_ok, result = cib_unknown); + + if (xml_has_children(failed)) { + CRM_CHECK(result != cib_ok, result = cib_unknown); } if (result != cib_ok) { - crm_log_xml_err(failed, "CIB Update failures"); - *answer = failed; - + crm_log_xml_err(failed, "CIB Update failures"); + *answer = failed; + } else { - free_xml(failed); + free_xml(failed); } - + return result; } gboolean -check_generation(xmlNode *newCib, xmlNode *oldCib) +check_generation(xmlNode * newCib, xmlNode * oldCib) { - if(cib_compare_generation(newCib, oldCib) >= 0) { - return TRUE; + if (cib_compare_generation(newCib, oldCib) >= 0) { + return TRUE; } crm_warn("Generation from update is older than the existing one"); return FALSE; } #ifndef CIBPIPE enum cib_errors -sync_our_cib(xmlNode *request, gboolean all) +sync_our_cib(xmlNode * request, gboolean all) { - enum cib_errors result = cib_ok; - const char *host = crm_element_value(request, F_ORIG); - const char *op = crm_element_value(request, F_CIB_OPERATION); + enum cib_errors result = cib_ok; + const char *host = crm_element_value(request, F_ORIG); + const char *op = crm_element_value(request, F_CIB_OPERATION); xmlNode *replace_request = cib_msg_copy(request, FALSE); - - CRM_CHECK(the_cib != NULL, ;); - CRM_CHECK(replace_request != NULL, ;); - - crm_debug("Syncing CIB to %s", all?"all peers":host); - if(all == FALSE && host == NULL) { - crm_log_xml(LOG_ERR, "bad sync", request); + + CRM_CHECK(the_cib != NULL,; + ); + CRM_CHECK(replace_request != NULL,; + ); + + crm_debug("Syncing CIB to %s", all ? "all peers" : host); + if (all == FALSE && host == NULL) { + crm_log_xml(LOG_ERR, "bad sync", request); } - + /* remove the "all == FALSE" condition * * sync_from was failing, the local client wasnt being notified * because it didnt know it was a reply * setting this does not prevent the other nodes from applying it * if all == TRUE */ - if(host != NULL) { - crm_xml_add(replace_request, F_CIB_ISREPLY, host); + if (host != NULL) { + crm_xml_add(replace_request, F_CIB_ISREPLY, host); } crm_xml_add(replace_request, F_CIB_OPERATION, CIB_OP_REPLACE); - crm_xml_add(replace_request, "original_"F_CIB_OPERATION, op); + crm_xml_add(replace_request, "original_" F_CIB_OPERATION, op); crm_xml_add(replace_request, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE); add_message_xml(replace_request, F_CIB_CALLDATA, the_cib); - - if(send_cluster_message(all?NULL:host, crm_msg_cib, replace_request, FALSE) == FALSE) { - result = cib_not_connected; + + if (send_cluster_message(all ? NULL : host, crm_msg_cib, replace_request, FALSE) == FALSE) { + result = cib_not_connected; } free_xml(replace_request); return result; } #endif diff --git a/cib/notify.c b/cib/notify.c index e1e1793933..a4531a12a6 100644 --- a/cib/notify.c +++ b/cib/notify.c @@ -1,389 +1,370 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include - - #include #include #include #include #include #include #include #include #include - int pending_updates = 0; extern GHashTable *client_list; gboolean cib_notify_client(gpointer key, gpointer value, gpointer user_data); -void attach_cib_generation(xmlNode *msg, const char *field, xmlNode *a_cib); +void attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib); -void do_cib_notify( - int options, const char *op, xmlNode *update, - enum cib_errors result, xmlNode *result_data, const char *msg_type); +void do_cib_notify(int options, const char *op, xmlNode * update, + enum cib_errors result, xmlNode * result_data, const char *msg_type); static void need_pre_notify(gpointer key, gpointer value, gpointer user_data) { cib_client_t *client = value; - if(client->pre_notify) { - gboolean *needed = user_data; - *needed = TRUE; + + if (client->pre_notify) { + gboolean *needed = user_data; + + *needed = TRUE; } } static void need_post_notify(gpointer key, gpointer value, gpointer user_data) { cib_client_t *client = value; - if(client->post_notify) { - gboolean *needed = user_data; - *needed = TRUE; + + if (client->post_notify) { + gboolean *needed = user_data; + + *needed = TRUE; } } gboolean cib_notify_client(gpointer key, gpointer value, gpointer user_data) { - int qlen = 0; - int max_qlen = 500; - const char *type = NULL; - gboolean do_send = FALSE; - gboolean do_remote = FALSE; - IPC_Channel *ipc_client = NULL; - - cib_client_t *client = value; - xmlNode *update_msg = user_data; - - CRM_CHECK(client != NULL, return TRUE); - CRM_CHECK(update_msg != NULL, return TRUE); - - if(client == NULL) { - crm_warn("Skipping NULL client"); - return TRUE; - - } else if(client->channel == NULL) { - crm_warn("Skipping client with NULL channel"); - return FALSE; - - } else if(client->name == NULL) { - crm_debug_2("Skipping unnammed client / comamnd channel"); - return FALSE; - } - - type = crm_element_value(update_msg, F_SUBTYPE); - - ipc_client = client->channel; - do_remote = crm_str_eq(client->channel_name, "remote", FALSE); - - if (do_remote == FALSE) { - qlen = ipc_client->send_queue->current_qlen; - max_qlen = ipc_client->send_queue->max_qlen; - } - - CRM_LOG_ASSERT(type != NULL); - if(client->diffs && safe_str_eq(type, T_CIB_DIFF_NOTIFY)) { - do_send = TRUE; - - } else if(client->replace && safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) { - do_send = TRUE; - - } else if(client->confirmations && safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) { - do_send = TRUE; - - } else if(client->pre_notify && safe_str_eq(type, T_CIB_PRE_NOTIFY)) { - if(qlen < (int)(0.4 * max_qlen)) { - do_send = TRUE; - } else { - crm_warn("Throttling pre-notifications due to" - " high load: queue=%d (max=%d)", - qlen, max_qlen); - } - - } else if(client->post_notify && safe_str_eq(type, T_CIB_POST_NOTIFY)) { - if(qlen < (int)(0.7 * max_qlen)) { - do_send = TRUE; - } else { - crm_warn("Throttling post-notifications due to" - " extreme load: queue=%d (max=%d)", - qlen, max_qlen); - } - } - - if(do_send) { - if (do_remote) { - crm_debug("Sent %s notification to client %s/%s", - type, client->name, client->id); - cib_send_remote_msg(client->channel, update_msg, client->encrypted); - - } else if(ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) { - /* We never want the CIB to exit because our client is slow */ - crm_crit("%s-notification of client %s/%s failed - queue saturated", - type, client->name, client->id); - - } else if(send_ipc_message(ipc_client, update_msg) == FALSE) { - crm_warn("Notification of client %s/%s failed", - client->name, client->id); - return FALSE; - } - } - return FALSE; + int qlen = 0; + int max_qlen = 500; + const char *type = NULL; + gboolean do_send = FALSE; + gboolean do_remote = FALSE; + IPC_Channel *ipc_client = NULL; + + cib_client_t *client = value; + xmlNode *update_msg = user_data; + + CRM_CHECK(client != NULL, return TRUE); + CRM_CHECK(update_msg != NULL, return TRUE); + + if (client == NULL) { + crm_warn("Skipping NULL client"); + return TRUE; + + } else if (client->channel == NULL) { + crm_warn("Skipping client with NULL channel"); + return FALSE; + + } else if (client->name == NULL) { + crm_debug_2("Skipping unnammed client / comamnd channel"); + return FALSE; + } + + type = crm_element_value(update_msg, F_SUBTYPE); + + ipc_client = client->channel; + do_remote = crm_str_eq(client->channel_name, "remote", FALSE); + + if (do_remote == FALSE) { + qlen = ipc_client->send_queue->current_qlen; + max_qlen = ipc_client->send_queue->max_qlen; + } + + CRM_LOG_ASSERT(type != NULL); + if (client->diffs && safe_str_eq(type, T_CIB_DIFF_NOTIFY)) { + do_send = TRUE; + + } else if (client->replace && safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) { + do_send = TRUE; + + } else if (client->confirmations && safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) { + do_send = TRUE; + + } else if (client->pre_notify && safe_str_eq(type, T_CIB_PRE_NOTIFY)) { + if (qlen < (int)(0.4 * max_qlen)) { + do_send = TRUE; + } else { + crm_warn("Throttling pre-notifications due to" + " high load: queue=%d (max=%d)", qlen, max_qlen); + } + + } else if (client->post_notify && safe_str_eq(type, T_CIB_POST_NOTIFY)) { + if (qlen < (int)(0.7 * max_qlen)) { + do_send = TRUE; + } else { + crm_warn("Throttling post-notifications due to" + " extreme load: queue=%d (max=%d)", qlen, max_qlen); + } + } + + if (do_send) { + if (do_remote) { + crm_debug("Sent %s notification to client %s/%s", type, client->name, client->id); + cib_send_remote_msg(client->channel, update_msg, client->encrypted); + + } else if (ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) { + /* We never want the CIB to exit because our client is slow */ + crm_crit("%s-notification of client %s/%s failed - queue saturated", + type, client->name, client->id); + + } else if (send_ipc_message(ipc_client, update_msg) == FALSE) { + crm_warn("Notification of client %s/%s failed", client->name, client->id); + return FALSE; + } + } + return FALSE; } void -cib_pre_notify( - int options, const char *op, xmlNode *existing, xmlNode *update) +cib_pre_notify(int options, const char *op, xmlNode * existing, xmlNode * update) { - xmlNode *update_msg = NULL; - const char *type = NULL; - const char *id = NULL; - gboolean needed = FALSE; - - g_hash_table_foreach(client_list, need_pre_notify, &needed); - if(needed == FALSE) { - return; - } - - /* TODO: consider pre-notification for removal */ - update_msg = create_xml_node(NULL, "pre-notify"); - - if(update != NULL) { - id = crm_element_value(update, XML_ATTR_ID); - } - - crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY); - crm_xml_add(update_msg, F_SUBTYPE, T_CIB_PRE_NOTIFY); - crm_xml_add(update_msg, F_CIB_OPERATION, op); - - if(id != NULL) { - crm_xml_add(update_msg, F_CIB_OBJID, id); - } - - if(update != NULL) { - crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update)); - } else if(existing != NULL) { - crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(existing)); - } - - type = crm_element_value(update_msg, F_CIB_OBJTYPE); - attach_cib_generation(update_msg, "cib_generation", the_cib); - - if(existing != NULL) { - add_message_xml(update_msg, F_CIB_EXISTING, existing); - } - if(update != NULL) { - add_message_xml(update_msg, F_CIB_UPDATE, update); - } - - g_hash_table_foreach_remove(client_list, cib_notify_client, update_msg); - - if(update == NULL) { - crm_debug_2("Performing operation %s (on section=%s)", - op, type); - - } else { - crm_debug_2("Performing %s on <%s%s%s>", - op, type, id?" id=":"", id?id:""); - } - - free_xml(update_msg); + xmlNode *update_msg = NULL; + const char *type = NULL; + const char *id = NULL; + gboolean needed = FALSE; + + g_hash_table_foreach(client_list, need_pre_notify, &needed); + if (needed == FALSE) { + return; + } + + /* TODO: consider pre-notification for removal */ + update_msg = create_xml_node(NULL, "pre-notify"); + + if (update != NULL) { + id = crm_element_value(update, XML_ATTR_ID); + } + + crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY); + crm_xml_add(update_msg, F_SUBTYPE, T_CIB_PRE_NOTIFY); + crm_xml_add(update_msg, F_CIB_OPERATION, op); + + if (id != NULL) { + crm_xml_add(update_msg, F_CIB_OBJID, id); + } + + if (update != NULL) { + crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update)); + } else if (existing != NULL) { + crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(existing)); + } + + type = crm_element_value(update_msg, F_CIB_OBJTYPE); + attach_cib_generation(update_msg, "cib_generation", the_cib); + + if (existing != NULL) { + add_message_xml(update_msg, F_CIB_EXISTING, existing); + } + if (update != NULL) { + add_message_xml(update_msg, F_CIB_UPDATE, update); + } + + g_hash_table_foreach_remove(client_list, cib_notify_client, update_msg); + + if (update == NULL) { + crm_debug_2("Performing operation %s (on section=%s)", op, type); + + } else { + crm_debug_2("Performing %s on <%s%s%s>", op, type, id ? " id=" : "", id ? id : ""); + } + + free_xml(update_msg); } void -cib_post_notify(int options, const char *op, xmlNode *update, - enum cib_errors result, xmlNode *new_obj) +cib_post_notify(int options, const char *op, xmlNode * update, + enum cib_errors result, xmlNode * new_obj) { - gboolean needed = FALSE; - g_hash_table_foreach(client_list, need_post_notify, &needed); - if(needed == FALSE) { - return; - } - - do_cib_notify( - options, op, update, result, new_obj, T_CIB_UPDATE_CONFIRM); + gboolean needed = FALSE; + + g_hash_table_foreach(client_list, need_post_notify, &needed); + if (needed == FALSE) { + return; + } + + do_cib_notify(options, op, update, result, new_obj, T_CIB_UPDATE_CONFIRM); } void -cib_diff_notify( - int options, const char *client, const char *call_id, const char *op, - xmlNode *update, enum cib_errors result, xmlNode *diff) +cib_diff_notify(int options, const char *client, const char *call_id, const char *op, + xmlNode * update, enum cib_errors result, xmlNode * diff) { - int add_updates = 0; - int add_epoch = 0; - int add_admin_epoch = 0; - - int del_updates = 0; - int del_epoch = 0; - int del_admin_epoch = 0; - - int log_level = LOG_DEBUG_2; - - if(diff == NULL) { - return; - } - - if(result != cib_ok) { - log_level = LOG_WARNING; - } - - cib_diff_version_details( - diff, &add_admin_epoch, &add_epoch, &add_updates, - &del_admin_epoch, &del_epoch, &del_updates); - - if(add_updates != del_updates) { - do_crm_log(log_level, - "Update (client: %s%s%s): %d.%d.%d -> %d.%d.%d (%s)", - client, call_id?", call:":"", call_id?call_id:"", - del_admin_epoch, del_epoch, del_updates, - add_admin_epoch, add_epoch, add_updates, - cib_error2string(result)); - - } else if(diff != NULL) { - do_crm_log(log_level, - "Local-only Change (client:%s%s%s): %d.%d.%d (%s)", - client, call_id?", call: ":"", call_id?call_id:"", - add_admin_epoch, add_epoch, add_updates, - cib_error2string(result)); - } - - do_cib_notify(options, op, update, result, diff, T_CIB_DIFF_NOTIFY); + int add_updates = 0; + int add_epoch = 0; + int add_admin_epoch = 0; + + int del_updates = 0; + int del_epoch = 0; + int del_admin_epoch = 0; + + int log_level = LOG_DEBUG_2; + + if (diff == NULL) { + return; + } + + if (result != cib_ok) { + log_level = LOG_WARNING; + } + + cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates, + &del_admin_epoch, &del_epoch, &del_updates); + + if (add_updates != del_updates) { + do_crm_log(log_level, + "Update (client: %s%s%s): %d.%d.%d -> %d.%d.%d (%s)", + client, call_id ? ", call:" : "", call_id ? call_id : "", + del_admin_epoch, del_epoch, del_updates, + add_admin_epoch, add_epoch, add_updates, cib_error2string(result)); + + } else if (diff != NULL) { + do_crm_log(log_level, + "Local-only Change (client:%s%s%s): %d.%d.%d (%s)", + client, call_id ? ", call: " : "", call_id ? call_id : "", + add_admin_epoch, add_epoch, add_updates, cib_error2string(result)); + } + + do_cib_notify(options, op, update, result, diff, T_CIB_DIFF_NOTIFY); } void -do_cib_notify( - int options, const char *op, xmlNode *update, - enum cib_errors result, xmlNode *result_data, const char *msg_type) +do_cib_notify(int options, const char *op, xmlNode * update, + enum cib_errors result, xmlNode * result_data, const char *msg_type) { - xmlNode *update_msg = NULL; - const char *id = NULL; - - update_msg = create_xml_node(NULL, "notify"); - - if(result_data != NULL) { - id = crm_element_value(result_data, XML_ATTR_ID); - } - - crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY); - crm_xml_add(update_msg, F_SUBTYPE, msg_type); - crm_xml_add(update_msg, F_CIB_OPERATION, op); - crm_xml_add_int(update_msg, F_CIB_RC, result); - - if(id != NULL) { - crm_xml_add(update_msg, F_CIB_OBJID, id); - } - - if(update != NULL) { - crm_debug_4("Setting type to update->name: %s", - crm_element_name(update)); - crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update)); - - } else if(result_data != NULL) { - crm_debug_4("Setting type to new_obj->name: %s", - crm_element_name(result_data)); - crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data)); - - } else { - crm_debug_4("Not Setting type"); - } - - attach_cib_generation(update_msg, "cib_generation", the_cib); - if(update != NULL) { - add_message_xml(update_msg, F_CIB_UPDATE, update); - } - if(result_data != NULL) { - add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data); - } - - crm_debug_3("Notifying clients"); - g_hash_table_foreach_remove(client_list, cib_notify_client, update_msg); - free_xml(update_msg); - crm_debug_3("Notify complete"); -} + xmlNode *update_msg = NULL; + const char *id = NULL; + + update_msg = create_xml_node(NULL, "notify"); + + if (result_data != NULL) { + id = crm_element_value(result_data, XML_ATTR_ID); + } + + crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY); + crm_xml_add(update_msg, F_SUBTYPE, msg_type); + crm_xml_add(update_msg, F_CIB_OPERATION, op); + crm_xml_add_int(update_msg, F_CIB_RC, result); + + if (id != NULL) { + crm_xml_add(update_msg, F_CIB_OBJID, id); + } + if (update != NULL) { + crm_debug_4("Setting type to update->name: %s", crm_element_name(update)); + crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update)); + + } else if (result_data != NULL) { + crm_debug_4("Setting type to new_obj->name: %s", crm_element_name(result_data)); + crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data)); + + } else { + crm_debug_4("Not Setting type"); + } + + attach_cib_generation(update_msg, "cib_generation", the_cib); + if (update != NULL) { + add_message_xml(update_msg, F_CIB_UPDATE, update); + } + if (result_data != NULL) { + add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data); + } + + crm_debug_3("Notifying clients"); + g_hash_table_foreach_remove(client_list, cib_notify_client, update_msg); + free_xml(update_msg); + crm_debug_3("Notify complete"); +} void -attach_cib_generation(xmlNode *msg, const char *field, xmlNode *a_cib) +attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib) { - xmlNode *generation = create_xml_node( - NULL, XML_CIB_TAG_GENERATION_TUPPLE); - - if(a_cib != NULL) { - copy_in_properties(generation, a_cib); - } - add_message_xml(msg, field, generation); - free_xml(generation); + xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE); + + if (a_cib != NULL) { + copy_in_properties(generation, a_cib); + } + add_message_xml(msg, field, generation); + free_xml(generation); } void -cib_replace_notify(const char *origin, xmlNode *update, enum cib_errors result, xmlNode *diff) +cib_replace_notify(const char *origin, xmlNode * update, enum cib_errors result, xmlNode * diff) { - xmlNode *replace_msg = NULL; - - int add_updates = 0; - int add_epoch = 0; - int add_admin_epoch = 0; - - int del_updates = 0; - int del_epoch = 0; - int del_admin_epoch = 0; - - if(diff == NULL) { - return; - } - - cib_diff_version_details( - diff, &add_admin_epoch, &add_epoch, &add_updates, - &del_admin_epoch, &del_epoch, &del_updates); - - if(add_updates != del_updates) { - crm_info("Replaced: %d.%d.%d -> %d.%d.%d from %s", - del_admin_epoch, del_epoch, del_updates, - add_admin_epoch, add_epoch, add_updates, - crm_str(origin)); - } else if(diff != NULL) { - crm_info("Local-only Replace: %d.%d.%d from %s", - add_admin_epoch, add_epoch, add_updates, - crm_str(origin)); - } - - replace_msg = create_xml_node(NULL, "notify-replace"); - crm_xml_add(replace_msg, F_TYPE, T_CIB_NOTIFY); - crm_xml_add(replace_msg, F_SUBTYPE, T_CIB_REPLACE_NOTIFY); - crm_xml_add(replace_msg, F_CIB_OPERATION, CIB_OP_REPLACE); - crm_xml_add_int(replace_msg, F_CIB_RC, result); - attach_cib_generation(replace_msg, "cib-replace-generation", update); - - crm_log_xml(LOG_DEBUG_2,"CIB Replaced", replace_msg); - - g_hash_table_foreach_remove(client_list, cib_notify_client, replace_msg); - free_xml(replace_msg); + xmlNode *replace_msg = NULL; + + int add_updates = 0; + int add_epoch = 0; + int add_admin_epoch = 0; + + int del_updates = 0; + int del_epoch = 0; + int del_admin_epoch = 0; + + if (diff == NULL) { + return; + } + + cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates, + &del_admin_epoch, &del_epoch, &del_updates); + + if (add_updates != del_updates) { + crm_info("Replaced: %d.%d.%d -> %d.%d.%d from %s", + del_admin_epoch, del_epoch, del_updates, + add_admin_epoch, add_epoch, add_updates, crm_str(origin)); + } else if (diff != NULL) { + crm_info("Local-only Replace: %d.%d.%d from %s", + add_admin_epoch, add_epoch, add_updates, crm_str(origin)); + } + + replace_msg = create_xml_node(NULL, "notify-replace"); + crm_xml_add(replace_msg, F_TYPE, T_CIB_NOTIFY); + crm_xml_add(replace_msg, F_SUBTYPE, T_CIB_REPLACE_NOTIFY); + crm_xml_add(replace_msg, F_CIB_OPERATION, CIB_OP_REPLACE); + crm_xml_add_int(replace_msg, F_CIB_RC, result); + attach_cib_generation(replace_msg, "cib-replace-generation", update); + + crm_log_xml(LOG_DEBUG_2, "CIB Replaced", replace_msg); + + g_hash_table_foreach_remove(client_list, cib_notify_client, replace_msg); + free_xml(replace_msg); } diff --git a/cib/remote.c b/cib/remote.c index c2a82a675d..1d0f8ce2d5 100644 --- a/cib/remote.c +++ b/cib/remote.c @@ -1,613 +1,609 @@ /* * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "callbacks.h" /* #undef HAVE_PAM_PAM_APPL_H */ /* #undef HAVE_GNUTLS_GNUTLS_H */ #ifdef HAVE_GNUTLS_GNUTLS_H # undef KEYFILE # include #endif #include #include #if HAVE_SECURITY_PAM_APPL_H # include # define HAVE_PAM 1 #else # if HAVE_PAM_PAM_APPL_H # include # define HAVE_PAM 1 # endif #endif #ifdef HAVE_DECL_NANOSLEEP # include #endif extern int remote_tls_fd; extern gboolean cib_shutdown_flag; extern void initiate_exit(void); int init_remote_listener(int port, gboolean encrypted); void cib_remote_connection_destroy(gpointer user_data); - #ifdef HAVE_GNUTLS_GNUTLS_H # define DH_BITS 1024 gnutls_dh_params dh_params; extern gnutls_anon_server_credentials anon_cred_s; -static void debug_log(int level, const char *str) +static void +debug_log(int level, const char *str) { - fputs (str, stderr); + fputs(str, stderr); } + extern gnutls_session *create_tls_session(int csock, int type); #endif extern int num_clients; -int authenticate_user(const char* user, const char* passwd); +int authenticate_user(const char *user, const char *passwd); gboolean cib_remote_listen(int ssock, gpointer data); gboolean cib_remote_msg(int csock, gpointer data); -extern void cib_common_callback_worker( - xmlNode *op_request, cib_client_t *cib_client, gboolean force_synchronous, gboolean privileged); - - +extern void cib_common_callback_worker(xmlNode * op_request, cib_client_t * cib_client, + gboolean force_synchronous, gboolean privileged); #define ERROR_SUFFIX " Shutting down remote listener" int -init_remote_listener(int port, gboolean encrypted) +init_remote_listener(int port, gboolean encrypted) { - int ssock; - struct sockaddr_in saddr; - int optval; + int ssock; + struct sockaddr_in saddr; + int optval; - if(port <= 0) { - /* dont start it */ - return 0; - } + if (port <= 0) { + /* dont start it */ + return 0; + } - if(encrypted) { + if (encrypted) { #ifndef HAVE_GNUTLS_GNUTLS_H - crm_warn("TLS support is not available"); - return 0; + crm_warn("TLS support is not available"); + return 0; #else - crm_notice("Starting a tls listener on port %d.", port); - gnutls_global_init(); + crm_notice("Starting a tls listener on port %d.", port); + gnutls_global_init(); /* gnutls_global_set_log_level (10); */ - gnutls_global_set_log_function (debug_log); - gnutls_dh_params_init(&dh_params); - gnutls_dh_params_generate2(dh_params, DH_BITS); - gnutls_anon_allocate_server_credentials (&anon_cred_s); - gnutls_anon_set_server_dh_params (anon_cred_s, dh_params); + gnutls_global_set_log_function(debug_log); + gnutls_dh_params_init(&dh_params); + gnutls_dh_params_generate2(dh_params, DH_BITS); + gnutls_anon_allocate_server_credentials(&anon_cred_s); + gnutls_anon_set_server_dh_params(anon_cred_s, dh_params); #endif - } else { - crm_warn("Starting a plain_text listener on port %d.", port); - } + } else { + crm_warn("Starting a plain_text listener on port %d.", port); + } #ifndef HAVE_PAM - crm_warn("PAM is _not_ enabled!"); + crm_warn("PAM is _not_ enabled!"); #endif - /* create server socket */ - ssock = socket(AF_INET, SOCK_STREAM, 0); - if (ssock == -1) { - crm_perror(LOG_ERR,"Can not create server socket."ERROR_SUFFIX); - return -1; - } - - /* reuse address */ - optval = 1; - setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - - /* bind server socket*/ - memset(&saddr, '\0', sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = INADDR_ANY; - saddr.sin_port = htons(port); - if (bind(ssock, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { - crm_perror(LOG_ERR,"Can not bind server socket."ERROR_SUFFIX); - return -2; - } - if (listen(ssock, 10) == -1) { - crm_perror(LOG_ERR,"Can not start listen."ERROR_SUFFIX); - return -3; - } - - G_main_add_fd(G_PRIORITY_HIGH, ssock, FALSE, - cib_remote_listen, NULL, - default_ipc_connection_destroy); - - return ssock; + /* create server socket */ + ssock = socket(AF_INET, SOCK_STREAM, 0); + if (ssock == -1) { + crm_perror(LOG_ERR, "Can not create server socket." ERROR_SUFFIX); + return -1; + } + + /* reuse address */ + optval = 1; + setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + /* bind server socket */ + memset(&saddr, '\0', sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; + saddr.sin_port = htons(port); + if (bind(ssock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) { + crm_perror(LOG_ERR, "Can not bind server socket." ERROR_SUFFIX); + return -2; + } + if (listen(ssock, 10) == -1) { + crm_perror(LOG_ERR, "Can not start listen." ERROR_SUFFIX); + return -3; + } + + G_main_add_fd(G_PRIORITY_HIGH, ssock, FALSE, + cib_remote_listen, NULL, default_ipc_connection_destroy); + + return ssock; } static int -check_group_membership(const char* usr, const char* grp) +check_group_membership(const char *usr, const char *grp) { - int index = 0; - struct passwd *pwd = NULL; - struct group *group = NULL; - - CRM_CHECK(usr != NULL, return FALSE); - CRM_CHECK(grp != NULL, return FALSE); - - pwd = getpwnam(usr); - if (pwd == NULL) { - crm_err("No user named '%s' exists!", usr); - return FALSE; - } - - group = getgrgid(pwd->pw_gid); - if (group != NULL && crm_str_eq(grp, group->gr_name, TRUE)) { - return TRUE; - } - - group = getgrnam(grp); - if (group == NULL) { - crm_err("No group named '%s' exists!", grp); - return FALSE; - } - - while (TRUE) { - char* member = group->gr_mem[index++]; - if(member == NULL) { - break; - - } else if (crm_str_eq(usr, member, TRUE)) { - return TRUE; - } - }; - - return FALSE; + int index = 0; + struct passwd *pwd = NULL; + struct group *group = NULL; + + CRM_CHECK(usr != NULL, return FALSE); + CRM_CHECK(grp != NULL, return FALSE); + + pwd = getpwnam(usr); + if (pwd == NULL) { + crm_err("No user named '%s' exists!", usr); + return FALSE; + } + + group = getgrgid(pwd->pw_gid); + if (group != NULL && crm_str_eq(grp, group->gr_name, TRUE)) { + return TRUE; + } + + group = getgrnam(grp); + if (group == NULL) { + crm_err("No group named '%s' exists!", grp); + return FALSE; + } + + while (TRUE) { + char *member = group->gr_mem[index++]; + + if (member == NULL) { + break; + + } else if (crm_str_eq(usr, member, TRUE)) { + return TRUE; + } + }; + + return FALSE; } gboolean cib_remote_listen(int ssock, gpointer data) { - int lpc = 0; - int csock = 0; - unsigned laddr; - time_t now = 0; - time_t start = time(NULL); - struct sockaddr_in addr; + int lpc = 0; + int csock = 0; + unsigned laddr; + time_t now = 0; + time_t start = time(NULL); + struct sockaddr_in addr; + #ifdef HAVE_GNUTLS_GNUTLS_H - gnutls_session *session = NULL; + gnutls_session *session = NULL; #endif - cib_client_t *new_client = NULL; + cib_client_t *new_client = NULL; - xmlNode *login = NULL; - const char *user = NULL; - const char *pass = NULL; - const char *tmp = NULL; + xmlNode *login = NULL; + const char *user = NULL; + const char *pass = NULL; + const char *tmp = NULL; + + cl_uuid_t client_id; + char uuid_str[UU_UNPARSE_SIZEOF]; - cl_uuid_t client_id; - char uuid_str[UU_UNPARSE_SIZEOF]; - #ifdef HAVE_DECL_NANOSLEEP - const struct timespec sleepfast = { 0, 10000000 }; /* 10 millisec */ + const struct timespec sleepfast = { 0, 10000000 }; /* 10 millisec */ #endif - /* accept the connection */ - laddr = sizeof(addr); - csock = accept(ssock, (struct sockaddr*)&addr, &laddr); - crm_debug("New %s connection from %s", - ssock == remote_tls_fd?"secure":"clear-text", - inet_ntoa(addr.sin_addr)); + /* accept the connection */ + laddr = sizeof(addr); + csock = accept(ssock, (struct sockaddr *)&addr, &laddr); + crm_debug("New %s connection from %s", + ssock == remote_tls_fd ? "secure" : "clear-text", inet_ntoa(addr.sin_addr)); - if (csock == -1) { - crm_err("accept socket failed"); - return TRUE; - } + if (csock == -1) { + crm_err("accept socket failed"); + return TRUE; + } - if(ssock == remote_tls_fd) { + if (ssock == remote_tls_fd) { #ifdef HAVE_GNUTLS_GNUTLS_H - /* create gnutls session for the server socket */ - session = create_tls_session(csock, GNUTLS_SERVER); - if (session == NULL) { - crm_err("TLS session creation failed"); - close(csock); - return TRUE; - } + /* create gnutls session for the server socket */ + session = create_tls_session(csock, GNUTLS_SERVER); + if (session == NULL) { + crm_err("TLS session creation failed"); + close(csock); + return TRUE; + } #endif - } + } - do { - crm_trace("Iter: %d", lpc++); - if(ssock == remote_tls_fd) { + do { + crm_trace("Iter: %d", lpc++); + if (ssock == remote_tls_fd) { #ifdef HAVE_GNUTLS_GNUTLS_H - login = cib_recv_remote_msg(session, TRUE); + login = cib_recv_remote_msg(session, TRUE); #endif - } else { - login = cib_recv_remote_msg(GINT_TO_POINTER(csock), FALSE); - } - if (login != NULL) { - break; - } + } else { + login = cib_recv_remote_msg(GINT_TO_POINTER(csock), FALSE); + } + if (login != NULL) { + break; + } #ifdef HAVE_DECL_NANOSLEEP - nanosleep(&sleepfast, NULL); + nanosleep(&sleepfast, NULL); #else - sleep(1); + sleep(1); #endif - now = time(NULL); - - /* Peers have 3s to connect */ - } while(login == NULL && (start - now) < 4); - - crm_log_xml_info(login, "Login: "); - if(login == NULL) { - goto bail; - } - - tmp = crm_element_name(login); - if(safe_str_neq(tmp, "cib_command")) { - crm_err("Wrong tag: %s", tmp); - goto bail; - } - - tmp = crm_element_value(login, "op"); - if(safe_str_neq(tmp, "authenticate")) { - crm_err("Wrong operation: %s", tmp); - goto bail; - } - - user = crm_element_value(login, "user"); - pass = crm_element_value(login, "password"); - - /* Non-root daemons can only validate the password of the - * user they're running as - */ - if(check_group_membership(user, CRM_DAEMON_GROUP) == FALSE) { - crm_err("User is not a member of the required group"); - goto bail; - - } else if (authenticate_user(user, pass) == FALSE) { - crm_err("PAM auth failed"); - goto bail; - } - - /* send ACK */ - crm_malloc0(new_client, sizeof(cib_client_t)); - num_clients++; - new_client->channel_name = "remote"; - new_client->name = crm_element_value_copy(login, "name"); - - cl_uuid_generate(&client_id); - cl_uuid_unparse(&client_id, uuid_str); - - CRM_CHECK(new_client->id == NULL, crm_free(new_client->id)); - new_client->id = crm_strdup(uuid_str); + now = time(NULL); + + /* Peers have 3s to connect */ + } while (login == NULL && (start - now) < 4); + + crm_log_xml_info(login, "Login: "); + if (login == NULL) { + goto bail; + } + + tmp = crm_element_name(login); + if (safe_str_neq(tmp, "cib_command")) { + crm_err("Wrong tag: %s", tmp); + goto bail; + } + + tmp = crm_element_value(login, "op"); + if (safe_str_neq(tmp, "authenticate")) { + crm_err("Wrong operation: %s", tmp); + goto bail; + } + + user = crm_element_value(login, "user"); + pass = crm_element_value(login, "password"); + + /* Non-root daemons can only validate the password of the + * user they're running as + */ + if (check_group_membership(user, CRM_DAEMON_GROUP) == FALSE) { + crm_err("User is not a member of the required group"); + goto bail; + + } else if (authenticate_user(user, pass) == FALSE) { + crm_err("PAM auth failed"); + goto bail; + } + + /* send ACK */ + crm_malloc0(new_client, sizeof(cib_client_t)); + num_clients++; + new_client->channel_name = "remote"; + new_client->name = crm_element_value_copy(login, "name"); + + cl_uuid_generate(&client_id); + cl_uuid_unparse(&client_id, uuid_str); + + CRM_CHECK(new_client->id == NULL, crm_free(new_client->id)); + new_client->id = crm_strdup(uuid_str); #if ENABLE_ACL - new_client->user = crm_strdup(user); + new_client->user = crm_strdup(user); #endif - - new_client->callback_id = NULL; - if(ssock == remote_tls_fd) { + + new_client->callback_id = NULL; + if (ssock == remote_tls_fd) { #ifdef HAVE_GNUTLS_GNUTLS_H - new_client->encrypted = TRUE; - new_client->channel = (void*)session; + new_client->encrypted = TRUE; + new_client->channel = (void *)session; #endif - } else { - new_client->channel = GINT_TO_POINTER(csock); - } + } else { + new_client->channel = GINT_TO_POINTER(csock); + } - free_xml(login); - login = create_xml_node(NULL, "cib_result"); - crm_xml_add(login, F_CIB_OPERATION, CRM_OP_REGISTER); - crm_xml_add(login, F_CIB_CLIENTID, new_client->id); - cib_send_remote_msg(new_client->channel, login, new_client->encrypted); - free_xml(login); + free_xml(login); + login = create_xml_node(NULL, "cib_result"); + crm_xml_add(login, F_CIB_OPERATION, CRM_OP_REGISTER); + crm_xml_add(login, F_CIB_CLIENTID, new_client->id); + cib_send_remote_msg(new_client->channel, login, new_client->encrypted); + free_xml(login); - new_client->source = (void*)G_main_add_fd( - G_PRIORITY_DEFAULT, csock, FALSE, cib_remote_msg, new_client, - cib_remote_connection_destroy); + new_client->source = + (void *)G_main_add_fd(G_PRIORITY_DEFAULT, csock, FALSE, cib_remote_msg, new_client, + cib_remote_connection_destroy); - g_hash_table_insert(client_list, new_client->id, new_client); + g_hash_table_insert(client_list, new_client->id, new_client); - return TRUE; + return TRUE; - bail: - if(ssock == remote_tls_fd) { + bail: + if (ssock == remote_tls_fd) { #ifdef HAVE_GNUTLS_GNUTLS_H - gnutls_bye(*session, GNUTLS_SHUT_RDWR); - gnutls_deinit(*session); - gnutls_free(session); + gnutls_bye(*session, GNUTLS_SHUT_RDWR); + gnutls_deinit(*session); + gnutls_free(session); #endif - } - close(csock); - free_xml(login); - return TRUE; + } + close(csock); + free_xml(login); + return TRUE; } void cib_remote_connection_destroy(gpointer user_data) { cib_client_t *client = user_data; - if(client == NULL) { - return; + if (client == NULL) { + return; } crm_trace("Cleaning up after client disconnect: %s/%s/%s", - crm_str(client->name), client->channel_name, client->id); - - if(client->id != NULL) { - if(!g_hash_table_remove(client_list, client->id)) { - crm_err("Client %s not found in the hashtable", client->name); - } + crm_str(client->name), client->channel_name, client->id); + + if (client->id != NULL) { + if (!g_hash_table_remove(client_list, client->id)) { + crm_err("Client %s not found in the hashtable", client->name); + } } - if(client->source != NULL) { - /* Should this even be necessary? */ - crm_trace("Deleting %s (%p) from mainloop", client->name, client->source); - G_main_del_fd((GFDSource *)client->source); - client->source = NULL; + if (client->source != NULL) { + /* Should this even be necessary? */ + crm_trace("Deleting %s (%p) from mainloop", client->name, client->source); + G_main_del_fd((GFDSource *) client->source); + client->source = NULL; } - + crm_trace("Destroying %s (%p)", client->name, user_data); num_clients--; crm_trace("Num unfree'd clients: %d", num_clients); crm_free(client->name); crm_free(client->callback_id); crm_free(client->id); crm_free(client->user); crm_free(client); crm_trace("Freed the cib client"); - if(cib_shutdown_flag && g_hash_table_size(client_list) == 0) { - crm_info("All clients disconnected..."); - initiate_exit(); + if (cib_shutdown_flag && g_hash_table_size(client_list) == 0) { + crm_info("All clients disconnected..."); + initiate_exit(); } - + return; } gboolean cib_remote_msg(int csock, gpointer data) { - const char *value = NULL; - xmlNode *command = NULL; - cib_client_t *client = data; - crm_trace("%s callback", client->encrypted?"secure":"clear-text"); - - command = cib_recv_remote_msg(client->channel, client->encrypted); - if(command == NULL) { - return FALSE; - } - - value = crm_element_name(command); - if(safe_str_neq(value, "cib_command")) { - crm_log_xml(LOG_MSG, "Bad command: ", command); - goto bail; - } - - if(client->name == NULL) { - value = crm_element_value(command, F_CLIENTNAME); - if(value == NULL) { - client->name = crm_strdup(client->id); - } else { - client->name = crm_strdup(value); - } - } - - if(client->callback_id == NULL) { - value = crm_element_value(command, F_CIB_CALLBACK_TOKEN); - if(value != NULL) { - client->callback_id = crm_strdup(value); - crm_debug_2("Callback channel for %s is %s", - client->id, client->callback_id); - - } else { - client->callback_id = crm_strdup(client->id); - } - } - - - /* unset dangerous options */ - xml_remove_prop(command, F_ORIG); - xml_remove_prop(command, F_CIB_HOST); - xml_remove_prop(command, F_CIB_GLOBAL_UPDATE); - - crm_xml_add(command, F_TYPE, T_CIB); - crm_xml_add(command, F_CIB_CLIENTID, client->id); - crm_xml_add(command, F_CIB_CLIENTNAME, client->name); + const char *value = NULL; + xmlNode *command = NULL; + cib_client_t *client = data; + + crm_trace("%s callback", client->encrypted ? "secure" : "clear-text"); + + command = cib_recv_remote_msg(client->channel, client->encrypted); + if (command == NULL) { + return FALSE; + } + + value = crm_element_name(command); + if (safe_str_neq(value, "cib_command")) { + crm_log_xml(LOG_MSG, "Bad command: ", command); + goto bail; + } + + if (client->name == NULL) { + value = crm_element_value(command, F_CLIENTNAME); + if (value == NULL) { + client->name = crm_strdup(client->id); + } else { + client->name = crm_strdup(value); + } + } + + if (client->callback_id == NULL) { + value = crm_element_value(command, F_CIB_CALLBACK_TOKEN); + if (value != NULL) { + client->callback_id = crm_strdup(value); + crm_debug_2("Callback channel for %s is %s", client->id, client->callback_id); + + } else { + client->callback_id = crm_strdup(client->id); + } + } + + /* unset dangerous options */ + xml_remove_prop(command, F_ORIG); + xml_remove_prop(command, F_CIB_HOST); + xml_remove_prop(command, F_CIB_GLOBAL_UPDATE); + + crm_xml_add(command, F_TYPE, T_CIB); + crm_xml_add(command, F_CIB_CLIENTID, client->id); + crm_xml_add(command, F_CIB_CLIENTNAME, client->name); #if ENABLE_ACL - crm_xml_add(command, F_CIB_USER, client->user); + crm_xml_add(command, F_CIB_USER, client->user); #endif - - if(crm_element_value(command, F_CIB_CALLID) == NULL) { - cl_uuid_t call_id; - char call_uuid[UU_UNPARSE_SIZEOF]; - - /* fix the command */ - cl_uuid_generate(&call_id); - cl_uuid_unparse(&call_id, call_uuid); - crm_xml_add(command, F_CIB_CALLID, call_uuid); - } - - if(crm_element_value(command, F_CIB_CALLOPTS) == NULL) { - crm_xml_add_int(command, F_CIB_CALLOPTS, 0); - } - - crm_log_xml(LOG_MSG, "Remote command: ", command); - cib_common_callback_worker(command, client, FALSE, TRUE); - bail: - free_xml(command); - command = NULL; - return TRUE; + + if (crm_element_value(command, F_CIB_CALLID) == NULL) { + cl_uuid_t call_id; + char call_uuid[UU_UNPARSE_SIZEOF]; + + /* fix the command */ + cl_uuid_generate(&call_id); + cl_uuid_unparse(&call_id, call_uuid); + crm_xml_add(command, F_CIB_CALLID, call_uuid); + } + + if (crm_element_value(command, F_CIB_CALLOPTS) == NULL) { + crm_xml_add_int(command, F_CIB_CALLOPTS, 0); + } + + crm_log_xml(LOG_MSG, "Remote command: ", command); + cib_common_callback_worker(command, client, FALSE, TRUE); + bail: + free_xml(command); + command = NULL; + return TRUE; } #ifdef HAVE_PAM /* * Useful Examples: * http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html * http://developer.apple.com/samplecode/CryptNoMore/index.html */ static int construct_pam_passwd(int num_msg, const struct pam_message **msg, - struct pam_response **response, void *data) + struct pam_response **response, void *data) { int count = 0; struct pam_response *reply; - char *string = (char*)data; + char *string = (char *)data; CRM_CHECK(data, return PAM_CONV_ERR); - CRM_CHECK(num_msg == 1, return PAM_CONV_ERR); /* We only want to handle one message */ + CRM_CHECK(num_msg == 1, return PAM_CONV_ERR); /* We only want to handle one message */ reply = calloc(1, sizeof(struct pam_response)); CRM_ASSERT(reply != NULL); - - for (count=0; count < num_msg; ++count) { - switch (msg[count]->msg_style) { - case PAM_TEXT_INFO: - crm_info("PAM: %s\n", msg[count]->msg); - break; - case PAM_PROMPT_ECHO_OFF: - case PAM_PROMPT_ECHO_ON: - reply[count].resp_retcode = 0; - reply[count].resp = string; /* We already made a copy */ - case PAM_ERROR_MSG: - /* In theory we'd want to print this, but then - * we see the password prompt in the logs - */ - /* crm_err("PAM error: %s\n", msg[count]->msg); */ - break; - default: - crm_err("Unhandled conversation type: %d", msg[count]->msg_style); - goto bail; - } + + for (count = 0; count < num_msg; ++count) { + switch (msg[count]->msg_style) { + case PAM_TEXT_INFO: + crm_info("PAM: %s\n", msg[count]->msg); + break; + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + reply[count].resp_retcode = 0; + reply[count].resp = string; /* We already made a copy */ + case PAM_ERROR_MSG: + /* In theory we'd want to print this, but then + * we see the password prompt in the logs + */ + /* crm_err("PAM error: %s\n", msg[count]->msg); */ + break; + default: + crm_err("Unhandled conversation type: %d", msg[count]->msg_style); + goto bail; + } } *response = reply; reply = NULL; return PAM_SUCCESS; -bail: - for (count=0; count < num_msg; ++count) { - if(reply[count].resp != NULL) { - switch (msg[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: - case PAM_PROMPT_ECHO_OFF: - /* Erase the data - it contained a password */ - while (*(reply[count].resp)) { - *(reply[count].resp)++ = '\0'; - } - free(reply[count].resp); - break; - } - reply[count].resp = NULL; - } + bail: + for (count = 0; count < num_msg; ++count) { + if (reply[count].resp != NULL) { + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + case PAM_PROMPT_ECHO_OFF: + /* Erase the data - it contained a password */ + while (*(reply[count].resp)) { + *(reply[count].resp)++ = '\0'; + } + free(reply[count].resp); + break; + } + reply[count].resp = NULL; + } } free(reply); reply = NULL; return PAM_CONV_ERR; } #endif -int -authenticate_user(const char* user, const char* passwd) +int +authenticate_user(const char *user, const char *passwd) { #ifndef HAVE_PAM - gboolean pass = TRUE; + gboolean pass = TRUE; #else - int rc = 0; - gboolean pass = FALSE; - const void *p_user = NULL; - - struct pam_conv p_conv; - struct pam_handle *pam_h = NULL; - static const char *pam_name = NULL; - - if(pam_name == NULL) { - pam_name = getenv("CIB_pam_service"); - } - if(pam_name == NULL) { - pam_name = "login"; - } - - p_conv.conv = construct_pam_passwd; - p_conv.appdata_ptr = strdup(passwd); - - rc = pam_start (pam_name, user, &p_conv, &pam_h); - if (rc != PAM_SUCCESS) { - crm_err("Could not initialize PAM: %s (%d)", pam_strerror(pam_h, rc), rc); - goto bail; - } - - rc = pam_authenticate (pam_h, 0); - if(rc != PAM_SUCCESS) { - crm_err("Authentication failed for %s: %s (%d)", - user, pam_strerror(pam_h, rc), rc); - goto bail; - } - - /* Make sure we authenticated the user we wanted to authenticate. - * Since we also run as non-root, it might be worth pre-checking - * the user has the same EID as us, since that the only user we - * can authenticate. - */ - rc = pam_get_item(pam_h, PAM_USER, &p_user); - if(rc != PAM_SUCCESS) { - crm_err("Internal PAM error: %s (%d)", pam_strerror(pam_h, rc), rc); - goto bail; - - } else if (p_user == NULL) { - crm_err("Unknown user authenticated."); - goto bail; - - } else if (safe_str_neq(p_user, user)) { - crm_err("User mismatch: %s vs. %s.", (const char*)p_user, (const char*)user); - goto bail; - } - - rc = pam_acct_mgmt(pam_h, 0); - if(rc != PAM_SUCCESS) { - crm_err("Access denied: %s (%d)", pam_strerror(pam_h, rc), rc); - goto bail; - } - pass = TRUE; - - bail: - rc = pam_end (pam_h, rc); + int rc = 0; + gboolean pass = FALSE; + const void *p_user = NULL; + + struct pam_conv p_conv; + struct pam_handle *pam_h = NULL; + static const char *pam_name = NULL; + + if (pam_name == NULL) { + pam_name = getenv("CIB_pam_service"); + } + if (pam_name == NULL) { + pam_name = "login"; + } + + p_conv.conv = construct_pam_passwd; + p_conv.appdata_ptr = strdup(passwd); + + rc = pam_start(pam_name, user, &p_conv, &pam_h); + if (rc != PAM_SUCCESS) { + crm_err("Could not initialize PAM: %s (%d)", pam_strerror(pam_h, rc), rc); + goto bail; + } + + rc = pam_authenticate(pam_h, 0); + if (rc != PAM_SUCCESS) { + crm_err("Authentication failed for %s: %s (%d)", user, pam_strerror(pam_h, rc), rc); + goto bail; + } + + /* Make sure we authenticated the user we wanted to authenticate. + * Since we also run as non-root, it might be worth pre-checking + * the user has the same EID as us, since that the only user we + * can authenticate. + */ + rc = pam_get_item(pam_h, PAM_USER, &p_user); + if (rc != PAM_SUCCESS) { + crm_err("Internal PAM error: %s (%d)", pam_strerror(pam_h, rc), rc); + goto bail; + + } else if (p_user == NULL) { + crm_err("Unknown user authenticated."); + goto bail; + + } else if (safe_str_neq(p_user, user)) { + crm_err("User mismatch: %s vs. %s.", (const char *)p_user, (const char *)user); + goto bail; + } + + rc = pam_acct_mgmt(pam_h, 0); + if (rc != PAM_SUCCESS) { + crm_err("Access denied: %s (%d)", pam_strerror(pam_h, rc), rc); + goto bail; + } + pass = TRUE; + + bail: + rc = pam_end(pam_h, rc); #endif - return pass; + return pass; } -