diff --git a/lib/ais/ipc_bridge.c b/lib/ais/ipc_bridge.c index 69c24bf327..e4efd6aea3 100644 --- a/lib/ais/ipc_bridge.c +++ b/lib/ais/ipc_bridge.c @@ -1,225 +1,214 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 int num_clients = 0; GHashTable *ipc_client_list = NULL; gboolean ais_shutdown_flag = FALSE; -typedef struct ais_client_s -{ - char *id; - char *name; - char *callback_id; +typedef struct ais_client_s { + char *id; + char *name; + char *callback_id; - const char *channel_name; + const char *channel_name; - IPC_Channel *channel; - GCHSource *source; - unsigned long num_calls; + IPC_Channel *channel; + GCHSource *source; + unsigned long num_calls; } ais_client_t; - static void ais_ipc_connection_destroy(gpointer user_data) { - ais_client_t *ais_client = user_data; - - if(ais_client == NULL) { - return; - } - - if(ais_client->source != NULL) { - crm_debug_4("Deleting %s (%p) from mainloop", - ais_client->name, ais_client->source); - G_main_del_IPC_Channel(ais_client->source); - ais_client->source = NULL; - } - - crm_debug_3("Destroying %s (%p)", ais_client->name, user_data); - num_clients--; - crm_debug("Num unfree'd clients: %d", num_clients); - crm_free(ais_client->name); - crm_free(ais_client->callback_id); - crm_free(ais_client->id); - crm_free(ais_client); - crm_debug_4("Freed the cib client"); - - return; + ais_client_t *ais_client = user_data; + + if (ais_client == NULL) { + return; + } + + if (ais_client->source != NULL) { + crm_debug_4("Deleting %s (%p) from mainloop", ais_client->name, ais_client->source); + G_main_del_IPC_Channel(ais_client->source); + ais_client->source = NULL; + } + + crm_debug_3("Destroying %s (%p)", ais_client->name, user_data); + num_clients--; + crm_debug("Num unfree'd clients: %d", num_clients); + crm_free(ais_client->name); + crm_free(ais_client->callback_id); + crm_free(ais_client->id); + crm_free(ais_client); + crm_debug_4("Freed the cib client"); + + return; } static gboolean -ais_process_disconnect(IPC_Channel *channel, ais_client_t *ais_client) +ais_process_disconnect(IPC_Channel * channel, ais_client_t * ais_client) { - if (channel == NULL) { - CRM_LOG_ASSERT(ais_client == NULL); - - } else if (ais_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(ais_client->name), - ais_client->channel_name, - ais_client->id); - - if(ais_client->id != NULL) { - if(!g_hash_table_remove(ipc_client_list, ais_client->id)) { - crm_err("Client %s not found in the hashtable", - ais_client->name); - } - } - } - - if(ais_shutdown_flag && g_hash_table_size(ipc_client_list) == 0) { - crm_info("All clients disconnected..."); - exit(0); - } - - return FALSE; + if (channel == NULL) { + CRM_LOG_ASSERT(ais_client == NULL); + + } else if (ais_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(ais_client->name), ais_client->channel_name, ais_client->id); + + if (ais_client->id != NULL) { + if (!g_hash_table_remove(ipc_client_list, ais_client->id)) { + crm_err("Client %s not found in the hashtable", ais_client->name); + } + } + } + + if (ais_shutdown_flag && g_hash_table_size(ipc_client_list) == 0) { + crm_info("All clients disconnected..."); + exit(0); + } + + return FALSE; } static gboolean -ais_ipc_callback(IPC_Channel *channel, gpointer user_data) +ais_ipc_callback(IPC_Channel * channel, gpointer user_data) { - int lpc = 0; - xmlNode *op_request = NULL; - gboolean keep_channel = TRUE; - ais_client_t *ais_client = user_data; - - if(ais_client == NULL) { - crm_err("Receieved call from unknown source. Discarding."); - return FALSE; - } - - if(ais_client->name == NULL) { - ais_client->name = crm_itoa(channel->farside_pid); - } - if(ais_client->id == NULL) { - ais_client->id = crm_strdup(ais_client->name); - g_hash_table_insert(ipc_client_list, ais_client->id, ais_client); - } - - crm_err("Callback for %s on %s channel", - ais_client->id, ais_client->channel_name); - - while(IPC_ISRCONN(channel)) { - if(channel->ops->is_message_pending(channel) == 0) { - break; - } - - op_request = msgfromIPC_noauth(channel); - if (op_request == NULL) { - perror("Receive failure:"); - break; - } - - lpc++; - crm_assert_failed = FALSE; - - ha_msg_add(op_request, "client-id", ais_client->id); - ha_msg_add(op_request, "client-name", ais_client->name); - crm_log_xml(LOG_ERR, "Client[inbound]", op_request); - + int lpc = 0; + xmlNode *op_request = NULL; + gboolean keep_channel = TRUE; + ais_client_t *ais_client = user_data; + + if (ais_client == NULL) { + crm_err("Receieved call from unknown source. Discarding."); + return FALSE; + } + + if (ais_client->name == NULL) { + ais_client->name = crm_itoa(channel->farside_pid); + } + if (ais_client->id == NULL) { + ais_client->id = crm_strdup(ais_client->name); + g_hash_table_insert(ipc_client_list, ais_client->id, ais_client); + } + + crm_err("Callback for %s on %s channel", ais_client->id, ais_client->channel_name); + + while (IPC_ISRCONN(channel)) { + if (channel->ops->is_message_pending(channel) == 0) { + break; + } + + op_request = msgfromIPC_noauth(channel); + if (op_request == NULL) { + perror("Receive failure:"); + break; + } + + lpc++; + crm_assert_failed = FALSE; + + ha_msg_add(op_request, "client-id", ais_client->id); + ha_msg_add(op_request, "client-name", ais_client->name); + crm_log_xml(LOG_ERR, "Client[inbound]", op_request); + /* cib_common_callback_worker( */ /* op_request, cib_client, force_synchronous, privileged); */ - crm_msg_del(op_request); + crm_msg_del(op_request); - if(channel->ch_status == IPC_CONNECT) { - break; - } - } + if (channel->ch_status == IPC_CONNECT) { + break; + } + } - crm_debug_2("Processed %d messages", lpc); + crm_debug_2("Processed %d messages", lpc); - if(channel->ch_status != IPC_CONNECT) { - crm_debug_2("Client disconnected"); - keep_channel = ais_process_disconnect(channel, ais_client); - } + if (channel->ch_status != IPC_CONNECT) { + crm_debug_2("Client disconnected"); + keep_channel = ais_process_disconnect(channel, ais_client); + } - return keep_channel; + return keep_channel; } gboolean -ais_client_connect(IPC_Channel *channel, gpointer user_data) +ais_client_connect(IPC_Channel * channel, gpointer user_data) { - const char *channel_name = user_data; - ais_client_t *new_client = NULL; - crm_debug_3("Connecting channel"); - - if (channel == NULL) { - crm_err("Channel was NULL"); - - } else if (channel->ch_status != IPC_CONNECT) { - crm_err("Channel was disconnected"); - - } else if(channel_name == NULL) { - crm_err("user_data must contain channel name"); - - } else if(ais_shutdown_flag) { - crm_info("Ignoring new client [%d] during shutdown", - channel->farside_pid); - - } else { - crm_malloc0(new_client, sizeof(ais_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, 500); - channel->ops->set_send_qlen(channel, 500); - - new_client->source = G_main_add_IPC_Channel( - G_PRIORITY_DEFAULT, channel, FALSE, ais_ipc_callback, - new_client, ais_ipc_connection_destroy); - - crm_debug_3("Channel %s connected for client %s", - new_client->channel_name, new_client->id); - } - - if(new_client == NULL) { - return FALSE; - } - return TRUE; -} + const char *channel_name = user_data; + ais_client_t *new_client = NULL; + + crm_debug_3("Connecting channel"); + + if (channel == NULL) { + crm_err("Channel was NULL"); + + } else if (channel->ch_status != IPC_CONNECT) { + crm_err("Channel was disconnected"); + } else if (channel_name == NULL) { + crm_err("user_data must contain channel name"); + } else if (ais_shutdown_flag) { + crm_info("Ignoring new client [%d] during shutdown", channel->farside_pid); + + } else { + crm_malloc0(new_client, sizeof(ais_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, 500); + channel->ops->set_send_qlen(channel, 500); + + new_client->source = + G_main_add_IPC_Channel(G_PRIORITY_DEFAULT, channel, FALSE, ais_ipc_callback, new_client, + ais_ipc_connection_destroy); + + crm_debug_3("Channel %s connected for client %s", new_client->channel_name, new_client->id); + } + + if (new_client == NULL) { + return FALSE; + } + return TRUE; +} diff --git a/lib/ais/plugin.c b/lib/ais/plugin.c index ad4919014e..ad9693c3d1 100644 --- a/lib/ais/plugin.c +++ b/lib/ais/plugin.c @@ -1,1688 +1,1752 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 USAA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "plugin.h" #include "utils.h" #include #include #include #include #include #include #include #include #include struct corosync_api_v1 *pcmk_api = NULL; uint32_t plugin_has_votes = 0; uint32_t plugin_expected_votes = 2; int use_mgmtd = 0; int plugin_log_level = LOG_DEBUG; char *local_uname = NULL; int local_uname_len = 0; char *local_cname = NULL; int local_cname_len = 0; uint32_t local_nodeid = 0; char *ipc_channel_name = NULL; static uint64_t local_born_on = 0; uint64_t membership_seq = 0; pthread_t pcmk_wait_thread; gboolean use_mcp = FALSE; gboolean wait_active = TRUE; gboolean have_reliable_membership_id = FALSE; GHashTable *ipc_client_list = NULL; GHashTable *membership_list = NULL; GHashTable *membership_notify_list = NULL; #define MAX_RESPAWN 100 #define LOOPBACK_ID 16777343 #define crm_flag_none 0x00000000 #define crm_flag_members 0x00000001 -struct crm_identify_msg_s -{ - coroipc_request_header_t header __attribute__((aligned(8))); - uint32_t id; - uint32_t pid; - int32_t votes; - uint32_t processes; - char uname[256]; - char version[256]; - uint64_t born_on; -} __attribute__((packed)); +struct crm_identify_msg_s { + coroipc_request_header_t header __attribute__ ((aligned(8))); + uint32_t id; + uint32_t pid; + int32_t votes; + uint32_t processes; + char uname[256]; + char version[256]; + uint64_t born_on; +} __attribute__ ((packed)); /* *INDENT-OFF* */ static crm_child_t pcmk_children[] = { { 0, crm_proc_none, crm_flag_none, 0, 0, FALSE, "none", NULL, NULL, NULL, NULL }, { 0, crm_proc_ais, crm_flag_none, 0, 0, FALSE, "ais", NULL, NULL, NULL, NULL }, { 0, crm_proc_lrmd, crm_flag_none, 3, 0, TRUE, "lrmd", NULL, HB_DAEMON_DIR"/lrmd", NULL, NULL }, { 0, crm_proc_cib, crm_flag_members, 2, 0, TRUE, "cib", CRM_DAEMON_USER, CRM_DAEMON_DIR"/cib", NULL, NULL }, { 0, crm_proc_crmd, crm_flag_members, 6, 0, TRUE, "crmd", CRM_DAEMON_USER, CRM_DAEMON_DIR"/crmd", NULL, NULL }, { 0, crm_proc_attrd, crm_flag_none, 4, 0, TRUE, "attrd", CRM_DAEMON_USER, CRM_DAEMON_DIR"/attrd", NULL, NULL }, { 0, crm_proc_stonithd, crm_flag_none, 0, 0, TRUE, "stonithd", NULL, "/bin/false", NULL, NULL }, { 0, crm_proc_pe, crm_flag_none, 5, 0, TRUE, "pengine", CRM_DAEMON_USER, CRM_DAEMON_DIR"/pengine", NULL, NULL }, { 0, crm_proc_mgmtd, crm_flag_none, 7, 0, TRUE, "mgmtd", NULL, HB_DAEMON_DIR"/mgmtd", NULL, NULL }, { 0, crm_proc_stonith_ng, crm_flag_none, 1, 0, TRUE, "stonith-ng", NULL, CRM_DAEMON_DIR"/stonithd", NULL, NULL }, }; /* *INDENT-ON* */ void send_cluster_id(void); -int send_cluster_msg_raw(const AIS_Message *ais_msg); +int send_cluster_msg_raw(const AIS_Message * ais_msg); char *pcmk_generate_membership_data(void); -gboolean check_message_sanity(const AIS_Message *msg, const char *data); +gboolean check_message_sanity(const AIS_Message * msg, const char *data); typedef const void ais_void_ptr; int pcmk_shutdown(void); void pcmk_peer_update(enum totem_configuration_type configuration_type, - const unsigned int *member_list, size_t member_list_entries, - const unsigned int *left_list, size_t left_list_entries, - const unsigned int *joined_list, size_t joined_list_entries, - const struct memb_ring_id *ring_id); + const unsigned int *member_list, size_t member_list_entries, + const unsigned int *left_list, size_t left_list_entries, + const unsigned int *joined_list, size_t joined_list_entries, + const struct memb_ring_id *ring_id); -int pcmk_startup (struct corosync_api_v1 *corosync_api); +int pcmk_startup(struct corosync_api_v1 *corosync_api); int pcmk_config_init(struct corosync_api_v1 *corosync_api); -int pcmk_ipc_exit (void *conn); -int pcmk_ipc_connect (void *conn); -void pcmk_ipc(void *conn, ais_void_ptr *msg); +int pcmk_ipc_exit(void *conn); +int pcmk_ipc_connect(void *conn); +void pcmk_ipc(void *conn, ais_void_ptr * msg); void pcmk_exec_dump(void); void pcmk_cluster_swab(void *msg); -void pcmk_cluster_callback(ais_void_ptr *message, unsigned int nodeid); +void pcmk_cluster_callback(ais_void_ptr * message, unsigned int nodeid); -void pcmk_nodeid(void *conn, ais_void_ptr *msg); -void pcmk_nodes(void *conn, ais_void_ptr *msg); -void pcmk_notify(void *conn, ais_void_ptr *msg); -void pcmk_remove_member(void *conn, ais_void_ptr *msg); -void pcmk_quorum(void *conn, ais_void_ptr *msg); +void pcmk_nodeid(void *conn, ais_void_ptr * msg); +void pcmk_nodes(void *conn, ais_void_ptr * msg); +void pcmk_notify(void *conn, ais_void_ptr * msg); +void pcmk_remove_member(void *conn, ais_void_ptr * msg); +void pcmk_quorum(void *conn, ais_void_ptr * msg); void pcmk_cluster_id_swab(void *msg); -void pcmk_cluster_id_callback(ais_void_ptr *message, unsigned int nodeid); +void pcmk_cluster_id_callback(ais_void_ptr * message, unsigned int nodeid); void ais_remove_peer(char *node_id); -static uint32_t get_process_list(void) +static uint32_t +get_process_list(void) { int lpc = 0; uint32_t procs = crm_proc_ais; - if(use_mcp) { - return 0; + if (use_mcp) { + return 0; } - + for (lpc = 0; lpc < SIZEOF(pcmk_children); lpc++) { - if(pcmk_children[lpc].pid != 0) { - procs |= pcmk_children[lpc].flag; - } + if (pcmk_children[lpc].pid != 0) { + procs |= pcmk_children[lpc].flag; + } } return procs; } -static struct corosync_lib_handler pcmk_lib_service[] = -{ - { /* 0 */ - .lib_handler_fn = pcmk_ipc, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, - }, - { /* 1 */ - .lib_handler_fn = pcmk_nodes, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, - }, - { /* 2 */ - .lib_handler_fn = pcmk_notify, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, - }, - { /* 3 */ - .lib_handler_fn = pcmk_nodeid, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, - }, - { /* 4 */ - .lib_handler_fn = pcmk_remove_member, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, - }, - { /* 5 */ - .lib_handler_fn = pcmk_quorum, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, - }, +static struct corosync_lib_handler pcmk_lib_service[] = { + { /* 0 */ + .lib_handler_fn = pcmk_ipc, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + }, + { /* 1 */ + .lib_handler_fn = pcmk_nodes, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + }, + { /* 2 */ + .lib_handler_fn = pcmk_notify, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + }, + { /* 3 */ + .lib_handler_fn = pcmk_nodeid, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + }, + { /* 4 */ + .lib_handler_fn = pcmk_remove_member, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + }, + { /* 5 */ + .lib_handler_fn = pcmk_quorum, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + }, }; -static struct corosync_exec_handler pcmk_exec_service[] = -{ - { /* 0 */ - .exec_handler_fn = pcmk_cluster_callback, - .exec_endian_convert_fn = pcmk_cluster_swab - }, - { /* 1 */ - .exec_handler_fn = pcmk_cluster_id_callback, - .exec_endian_convert_fn = pcmk_cluster_id_swab - } +static struct corosync_exec_handler pcmk_exec_service[] = { + { /* 0 */ + .exec_handler_fn = pcmk_cluster_callback, + .exec_endian_convert_fn = pcmk_cluster_swab}, + { /* 1 */ + .exec_handler_fn = pcmk_cluster_id_callback, + .exec_endian_convert_fn = pcmk_cluster_id_swab} }; /* * Exports the interface for the service */ +/* *INDENT-OFF* */ struct corosync_service_engine pcmk_service_handler = { .name = (unsigned char *)"Pacemaker Cluster Manager "PACKAGE_VERSION, .id = PCMK_SERVICE_ID, .private_data_size = 0, .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, .allow_inquorate = CS_LIB_ALLOW_INQUORATE, .lib_init_fn = pcmk_ipc_connect, .lib_exit_fn = pcmk_ipc_exit, .exec_init_fn = pcmk_startup, .exec_exit_fn = pcmk_shutdown, .config_init_fn = pcmk_config_init, .priority = 50, .lib_engine = pcmk_lib_service, .lib_engine_count = sizeof (pcmk_lib_service) / sizeof (struct corosync_lib_handler), .exec_engine = pcmk_exec_service, .exec_engine_count = sizeof (pcmk_exec_service) / sizeof (struct corosync_exec_handler), .confchg_fn = pcmk_peer_update, .exec_dump_fn = pcmk_exec_dump, /* void (*sync_init) (void); */ /* int (*sync_process) (void); */ /* void (*sync_activate) (void); */ /* void (*sync_abort) (void); */ }; /* * Dynamic Loader definition */ struct corosync_service_engine *pcmk_get_handler_ver0 (void); struct corosync_service_engine_iface_ver0 pcmk_service_handler_iface = { .corosync_get_service_engine_ver0 = pcmk_get_handler_ver0 }; static struct lcr_iface openais_pcmk_ver0[2] = { { .name = "pacemaker", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = NULL }, { .name = "pacemaker", .version = 1, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = NULL } }; static struct lcr_comp pcmk_comp_ver0 = { - .iface_count = 2, - .ifaces = openais_pcmk_ver0 + .iface_count = 2, + .ifaces = openais_pcmk_ver0 }; +/* *INDENT-ON* */ -struct corosync_service_engine *pcmk_get_handler_ver0 (void) +struct corosync_service_engine * +pcmk_get_handler_ver0(void) { return (&pcmk_service_handler); } -__attribute__ ((constructor)) static void register_this_component (void) { - lcr_interfaces_set (&openais_pcmk_ver0[0], &pcmk_service_handler_iface); - lcr_interfaces_set (&openais_pcmk_ver0[1], &pcmk_service_handler_iface); +__attribute__ ((constructor)) +static void +register_this_component(void) +{ + lcr_interfaces_set(&openais_pcmk_ver0[0], &pcmk_service_handler_iface); + lcr_interfaces_set(&openais_pcmk_ver0[1], &pcmk_service_handler_iface); - lcr_component_register (&pcmk_comp_ver0); + lcr_component_register(&pcmk_comp_ver0); } -static int plugin_has_quorum(void) +static int +plugin_has_quorum(void) { - if((plugin_expected_votes >> 1) < plugin_has_votes) { - return 1; + if ((plugin_expected_votes >> 1) < plugin_has_votes) { + return 1; } return 0; } -static void update_expected_votes(int value) +static void +update_expected_votes(int value) { - if(value < plugin_has_votes) { - /* Never drop below the number of connected nodes */ - ais_info("Cannot update expected quorum votes %d -> %d:" - " value cannot be less that the current number of votes", - plugin_expected_votes, value); + if (value < plugin_has_votes) { + /* Never drop below the number of connected nodes */ + ais_info("Cannot update expected quorum votes %d -> %d:" + " value cannot be less that the current number of votes", + plugin_expected_votes, value); - } else if(plugin_expected_votes != value) { - ais_info("Expected quorum votes %d -> %d", - plugin_expected_votes, value); - plugin_expected_votes = value; + } else if (plugin_expected_votes != value) { + ais_info("Expected quorum votes %d -> %d", plugin_expected_votes, value); + plugin_expected_votes = value; } } /* Create our own local copy of the config so we can navigate it */ -static void process_ais_conf(void) +static void +process_ais_conf(void) { char *value = NULL; gboolean any_log = FALSE; hdb_handle_t top_handle = 0; hdb_handle_t local_handle = 0; - + ais_info("Reading configure"); top_handle = config_find_init(pcmk_api, "logging"); local_handle = config_find_next(pcmk_api, "logging", top_handle); - + get_config_opt(pcmk_api, local_handle, "debug", &value, "on"); - if(ais_get_boolean(value)) { - plugin_log_level = LOG_DEBUG; - pcmk_env.debug = "1"; - + if (ais_get_boolean(value)) { + plugin_log_level = LOG_DEBUG; + pcmk_env.debug = "1"; + } else { - plugin_log_level = LOG_INFO; - pcmk_env.debug = "0"; - } - + plugin_log_level = LOG_INFO; + pcmk_env.debug = "0"; + } + get_config_opt(pcmk_api, local_handle, "to_logfile", &value, "off"); - if(ais_get_boolean(value)) { - get_config_opt(pcmk_api, local_handle, "logfile", &value, NULL); + if (ais_get_boolean(value)) { + get_config_opt(pcmk_api, local_handle, "logfile", &value, NULL); - if(value == NULL) { - ais_err("Logging to a file requested but no log file specified"); + if (value == NULL) { + ais_err("Logging to a file requested but no log file specified"); - } else { - uid_t pcmk_uid = geteuid(); - uid_t pcmk_gid = getegid(); + } else { + uid_t pcmk_uid = geteuid(); + uid_t pcmk_gid = getegid(); - FILE *logfile = fopen(value, "a"); - if(logfile) { - int logfd = fileno(logfile); + FILE *logfile = fopen(value, "a"); - pcmk_env.logfile = value; - - /* Ensure the file has the correct permissions */ - fchown(logfd, pcmk_uid, pcmk_gid); - fchmod(logfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); - - fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n", - pcmk_uid, pcmk_gid, value); - fflush(logfile); - fsync(logfd); - fclose(logfile); - any_log = TRUE; - - } else { - ais_err("Couldn't create logfile: %s", value); - } - } + if (logfile) { + int logfd = fileno(logfile); + + pcmk_env.logfile = value; + + /* Ensure the file has the correct permissions */ + fchown(logfd, pcmk_uid, pcmk_gid); + fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + + fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n", + pcmk_uid, pcmk_gid, value); + fflush(logfile); + fsync(logfd); + fclose(logfile); + any_log = TRUE; + + } else { + ais_err("Couldn't create logfile: %s", value); + } + } } get_config_opt(pcmk_api, local_handle, "to_syslog", &value, "on"); - if(any_log && ais_get_boolean(value) == FALSE) { - ais_info("User configured file based logging and explicitly disabled syslog."); - value = "none"; + if (any_log && ais_get_boolean(value) == FALSE) { + ais_info("User configured file based logging and explicitly disabled syslog."); + value = "none"; } else { - if(ais_get_boolean(value) == FALSE) { - ais_err("Please enable some sort of logging, either 'to_file: on' or 'to_syslog: on'."); - ais_err("If you use file logging, be sure to also define a value for 'logfile'"); - } - get_config_opt(pcmk_api, local_handle, "syslog_facility", &value, "daemon"); + if (ais_get_boolean(value) == FALSE) { + ais_err + ("Please enable some sort of logging, either 'to_file: on' or 'to_syslog: on'."); + ais_err("If you use file logging, be sure to also define a value for 'logfile'"); + } + get_config_opt(pcmk_api, local_handle, "syslog_facility", &value, "daemon"); } pcmk_env.syslog = value; config_find_done(pcmk_api, local_handle); top_handle = config_find_init(pcmk_api, "quorum"); local_handle = config_find_next(pcmk_api, "quorum", top_handle); get_config_opt(pcmk_api, local_handle, "provider", &value, NULL); - if(value && ais_str_eq("quorum_cman", value)) { - pcmk_env.quorum = "cman"; + if (value && ais_str_eq("quorum_cman", value)) { + pcmk_env.quorum = "cman"; } - + top_handle = config_find_init(pcmk_api, "service"); local_handle = config_find_next(pcmk_api, "service", top_handle); - while(local_handle) { - value = NULL; - pcmk_api->object_key_get(local_handle, "name", strlen("name"), (void**)&value, NULL); - if(ais_str_eq("pacemaker", value)) { - break; - } - local_handle = config_find_next(pcmk_api, "service", top_handle); + while (local_handle) { + value = NULL; + pcmk_api->object_key_get(local_handle, "name", strlen("name"), (void **)&value, NULL); + if (ais_str_eq("pacemaker", value)) { + break; + } + local_handle = config_find_next(pcmk_api, "service", top_handle); } get_config_opt(pcmk_api, local_handle, "ver", &value, "0"); - if(ais_str_eq(value, "1")) { - ais_info("Enabling MCP mode: Use the Pacemaker init script to complete Pacemaker startup"); - use_mcp = TRUE; + if (ais_str_eq(value, "1")) { + ais_info("Enabling MCP mode: Use the Pacemaker init script to complete Pacemaker startup"); + use_mcp = TRUE; } - + get_config_opt(pcmk_api, local_handle, "clustername", &local_cname, "pcmk"); local_cname_len = strlen(local_cname); - + get_config_opt(pcmk_api, local_handle, "use_logd", &value, "no"); pcmk_env.use_logd = value; get_config_opt(pcmk_api, local_handle, "use_mgmtd", &value, "no"); - if(ais_get_boolean(value) == FALSE) { - int lpc = 0; - for (; lpc < SIZEOF(pcmk_children); lpc++) { - if(crm_proc_mgmtd & pcmk_children[lpc].flag) { - /* Disable mgmtd startup */ - pcmk_children[lpc].start_seq = 0; - break; - } - } - } - + if (ais_get_boolean(value) == FALSE) { + int lpc = 0; + + for (; lpc < SIZEOF(pcmk_children); lpc++) { + if (crm_proc_mgmtd & pcmk_children[lpc].flag) { + /* Disable mgmtd startup */ + pcmk_children[lpc].start_seq = 0; + break; + } + } + } + config_find_done(pcmk_api, local_handle); } -int pcmk_config_init(struct corosync_api_v1 *unused) +int +pcmk_config_init(struct corosync_api_v1 *unused) { return 0; } -static void *pcmk_wait_dispatch (void *arg) +static void * +pcmk_wait_dispatch(void *arg) { struct timespec waitsleep = { - .tv_sec = 1, - .tv_nsec = 0 + .tv_sec = 1, + .tv_nsec = 0 }; - - while(wait_active) { - int lpc = 0; - for (; lpc < SIZEOF(pcmk_children); lpc++) { - if(pcmk_children[lpc].pid > 0) { - int status; - pid_t pid = wait4( - pcmk_children[lpc].pid, &status, WNOHANG, NULL); - - if(pid == 0) { - continue; - - } else if(pid < 0) { - ais_perror("Call to wait4(%s) failed", pcmk_children[lpc].name); - continue; - } - - /* cleanup */ - pcmk_children[lpc].pid = 0; - pcmk_children[lpc].conn = NULL; - pcmk_children[lpc].async_conn = NULL; - - if(WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - ais_err("Child process %s terminated with signal %d" - " (pid=%d, core=%s)", - pcmk_children[lpc].name, sig, pid, - WCOREDUMP(status)?"true":"false"); - - } else if (WIFEXITED(status)) { - int rc = WEXITSTATUS(status); - do_ais_log(rc==0?LOG_NOTICE:LOG_ERR, "Child process %s exited (pid=%d, rc=%d)", - pcmk_children[lpc].name, pid, rc); - - if(rc == 100) { - ais_notice("Child process %s no longer wishes" - " to be respawned", pcmk_children[lpc].name); - pcmk_children[lpc].respawn = FALSE; - } - } - - /* Broadcast the fact that one of our processes died - * - * Try to get some logging of the cause out first though - * because we're probably about to get fenced - * - * Potentially do this only if respawn_count > N - * to allow for local recovery - */ - send_cluster_id(); - - pcmk_children[lpc].respawn_count += 1; - if(pcmk_children[lpc].respawn_count > MAX_RESPAWN) { - ais_err("Child respawn count exceeded by %s", - pcmk_children[lpc].name); - pcmk_children[lpc].respawn = FALSE; - } - if(pcmk_children[lpc].respawn) { - ais_notice("Respawning failed child process: %s", - pcmk_children[lpc].name); - spawn_child(&(pcmk_children[lpc])); - } - send_cluster_id(); - } - } - sched_yield (); - nanosleep (&waitsleep, 0); + + while (wait_active) { + int lpc = 0; + + for (; lpc < SIZEOF(pcmk_children); lpc++) { + if (pcmk_children[lpc].pid > 0) { + int status; + pid_t pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL); + + if (pid == 0) { + continue; + + } else if (pid < 0) { + ais_perror("Call to wait4(%s) failed", pcmk_children[lpc].name); + continue; + } + + /* cleanup */ + pcmk_children[lpc].pid = 0; + pcmk_children[lpc].conn = NULL; + pcmk_children[lpc].async_conn = NULL; + + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + + ais_err("Child process %s terminated with signal %d" + " (pid=%d, core=%s)", + pcmk_children[lpc].name, sig, pid, + WCOREDUMP(status) ? "true" : "false"); + + } else if (WIFEXITED(status)) { + int rc = WEXITSTATUS(status); + + do_ais_log(rc == 0 ? LOG_NOTICE : LOG_ERR, + "Child process %s exited (pid=%d, rc=%d)", pcmk_children[lpc].name, + pid, rc); + + if (rc == 100) { + ais_notice("Child process %s no longer wishes" + " to be respawned", pcmk_children[lpc].name); + pcmk_children[lpc].respawn = FALSE; + } + } + + /* Broadcast the fact that one of our processes died + * + * Try to get some logging of the cause out first though + * because we're probably about to get fenced + * + * Potentially do this only if respawn_count > N + * to allow for local recovery + */ + send_cluster_id(); + + pcmk_children[lpc].respawn_count += 1; + if (pcmk_children[lpc].respawn_count > MAX_RESPAWN) { + ais_err("Child respawn count exceeded by %s", pcmk_children[lpc].name); + pcmk_children[lpc].respawn = FALSE; + } + if (pcmk_children[lpc].respawn) { + ais_notice("Respawning failed child process: %s", pcmk_children[lpc].name); + spawn_child(&(pcmk_children[lpc])); + } + send_cluster_id(); + } + } + sched_yield(); + nanosleep(&waitsleep, 0); } return 0; } -static uint32_t pcmk_update_nodeid(void) +static uint32_t +pcmk_update_nodeid(void) { int last = local_nodeid; + local_nodeid = pcmk_api->totem_nodeid_get(); - if(last != local_nodeid) { - if(last == 0) { - ais_info("Local node id: %u", local_nodeid); - - } else { - char *last_s = NULL; - ais_malloc0(last_s, 32); - ais_warn("Detected local node id change: %u -> %u", last, local_nodeid); - snprintf(last_s, 31, "%u", last); - ais_remove_peer(last_s); - ais_free(last_s); - } - update_member(local_nodeid, 0, 0, 1, 0, local_uname, CRM_NODE_MEMBER, NULL); - } - + if (last != local_nodeid) { + if (last == 0) { + ais_info("Local node id: %u", local_nodeid); + + } else { + char *last_s = NULL; + + ais_malloc0(last_s, 32); + ais_warn("Detected local node id change: %u -> %u", last, local_nodeid); + snprintf(last_s, 31, "%u", last); + ais_remove_peer(last_s); + ais_free(last_s); + } + update_member(local_nodeid, 0, 0, 1, 0, local_uname, CRM_NODE_MEMBER, NULL); + } + return local_nodeid; } -static void build_path(const char *path_c, mode_t mode) +static void +build_path(const char *path_c, mode_t mode) { int offset = 1, len = 0; char *path = ais_strdup(path_c); AIS_CHECK(path != NULL, return); - for(len = strlen(path); offset < len; offset++) { - if(path[offset] == '/') { - path[offset] = 0; - if(mkdir(path, mode) < 0 && errno != EEXIST) { - ais_perror("Could not create directory '%s'", path); - break; - } - path[offset] = '/'; - } - } - if(mkdir(path, mode) < 0 && errno != EEXIST) { - ais_perror("Could not create directory '%s'", path); + for (len = strlen(path); offset < len; offset++) { + if (path[offset] == '/') { + path[offset] = 0; + if (mkdir(path, mode) < 0 && errno != EEXIST) { + ais_perror("Could not create directory '%s'", path); + break; + } + path[offset] = '/'; + } + } + if (mkdir(path, mode) < 0 && errno != EEXIST) { + ais_perror("Could not create directory '%s'", path); } ais_free(path); } -int pcmk_startup(struct corosync_api_v1 *init_with) +int +pcmk_startup(struct corosync_api_v1 *init_with) { int rc = 0; int lpc = 0; int start_seq = 1; struct utsname us; struct rlimit cores; static int max = SIZEOF(pcmk_children); uid_t pcmk_uid = 0; gid_t pcmk_gid = 0; uid_t root_uid = -1; uid_t cs_uid = geteuid(); + pcmk_user_lookup("root", &root_uid, NULL); pcmk_api = init_with; - pcmk_env.debug = "0"; - pcmk_env.logfile = NULL; + pcmk_env.debug = "0"; + pcmk_env.logfile = NULL; pcmk_env.use_logd = "false"; - pcmk_env.syslog = "daemon"; - - if(cs_uid != root_uid) { - ais_err("Corosync must be configured to start as 'root'," - " otherwise Pacemaker cannot manage services." - " Expected %d got %d", root_uid, cs_uid); - return -1; - } - + pcmk_env.syslog = "daemon"; + + if (cs_uid != root_uid) { + ais_err("Corosync must be configured to start as 'root'," + " otherwise Pacemaker cannot manage services." + " Expected %d got %d", root_uid, cs_uid); + return -1; + } + process_ais_conf(); - - membership_list = g_hash_table_new_full( - g_direct_hash, g_direct_equal, NULL, destroy_ais_node); + + membership_list = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_ais_node); membership_notify_list = g_hash_table_new(g_direct_hash, g_direct_equal); ipc_client_list = g_hash_table_new(g_direct_hash, g_direct_equal); - + ais_info("CRM: Initialized"); log_printf(LOG_INFO, "Logging: Initialized %s\n", __PRETTY_FUNCTION__); - + rc = getrlimit(RLIMIT_CORE, &cores); - if(rc < 0) { - ais_perror("Cannot determine current maximum core size."); + if (rc < 0) { + ais_perror("Cannot determine current maximum core size."); } else { - if (cores.rlim_max == 0 && geteuid() == 0) { - cores.rlim_max = RLIM_INFINITY; - } else { - ais_info("Maximum core file size is: %lu", cores.rlim_max); - } - cores.rlim_cur = cores.rlim_max; - - rc = setrlimit(RLIMIT_CORE, &cores); - if(rc < 0) { - ais_perror("Core file generation will remain disabled." - " Core files are an important diagnositic tool," - " please consider enabling them by default."); - } + if (cores.rlim_max == 0 && geteuid() == 0) { + cores.rlim_max = RLIM_INFINITY; + } else { + ais_info("Maximum core file size is: %lu", cores.rlim_max); + } + cores.rlim_cur = cores.rlim_max; + + rc = setrlimit(RLIMIT_CORE, &cores); + if (rc < 0) { + ais_perror("Core file generation will remain disabled." + " Core files are an important diagnositic tool," + " please consider enabling them by default."); + } #if 0 - /* system() is not thread-safe, can't call from here - * Actually, its a pretty hacky way to try and achieve this anyway - */ - if(system("echo 1 > /proc/sys/kernel/core_uses_pid") != 0) { - ais_perror("Could not enable /proc/sys/kernel/core_uses_pid"); - } + /* system() is not thread-safe, can't call from here + * Actually, its a pretty hacky way to try and achieve this anyway + */ + if (system("echo 1 > /proc/sys/kernel/core_uses_pid") != 0) { + ais_perror("Could not enable /proc/sys/kernel/core_uses_pid"); + } #endif } - if(pcmk_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) < 0) { - ais_err("Cluster user %s does not exist, aborting Pacemaker startup", CRM_DAEMON_USER); - return TRUE; + if (pcmk_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) < 0) { + ais_err("Cluster user %s does not exist, aborting Pacemaker startup", CRM_DAEMON_USER); + return TRUE; } - + mkdir(CRM_STATE_DIR, 0750); chown(CRM_STATE_DIR, pcmk_uid, pcmk_gid); - + /* Used by stonithd */ - build_path(HA_STATE_DIR"/heartbeat", 0755); + build_path(HA_STATE_DIR "/heartbeat", 0755); /* Used by RAs - Leave owned by root */ - build_path(CRM_RSCTMP_DIR, 0755); + build_path(CRM_RSCTMP_DIR, 0755); rc = uname(&us); AIS_ASSERT(rc == 0); local_uname = ais_strdup(us.nodename); - local_uname_len = strlen(local_uname); - + local_uname_len = strlen(local_uname); + ais_info("Service: %d", PCMK_SERVICE_ID); ais_info("Local hostname: %s", local_uname); - pcmk_update_nodeid(); - - if(use_mcp == FALSE) { - pthread_create (&pcmk_wait_thread, NULL, pcmk_wait_dispatch, NULL); - for (start_seq = 1; start_seq < max; start_seq++) { - /* dont start anything with start_seq < 1 */ - for (lpc = 0; lpc < max; lpc++) { - if(start_seq == pcmk_children[lpc].start_seq) { - spawn_child(&(pcmk_children[lpc])); - } - } + pcmk_update_nodeid(); + + if (use_mcp == FALSE) { + pthread_create(&pcmk_wait_thread, NULL, pcmk_wait_dispatch, NULL); + for (start_seq = 1; start_seq < max; start_seq++) { + /* dont start anything with start_seq < 1 */ + for (lpc = 0; lpc < max; lpc++) { + if (start_seq == pcmk_children[lpc].start_seq) { + spawn_child(&(pcmk_children[lpc])); + } + } + } } - } return 0; } /* static void ais_print_node(const char *prefix, struct totem_ip_address *host) { int len = 0; char *buffer = NULL; ais_malloc0(buffer, INET6_ADDRSTRLEN+1); inet_ntop(host->family, host->addr, buffer, INET6_ADDRSTRLEN); len = strlen(buffer); ais_info("%s: %.*s", prefix, len, buffer); ais_free(buffer); } */ #if 0 /* copied here for reference from exec/totempg.c */ -char *totempg_ifaces_print (unsigned int nodeid) +char * +totempg_ifaces_print(unsigned int nodeid) { static char iface_string[256 * INTERFACE_MAX]; char one_iface[64]; struct totem_ip_address interfaces[INTERFACE_MAX]; char **status; unsigned int iface_count; unsigned int i; int res; iface_string[0] = '\0'; - res = totempg_ifaces_get (nodeid, interfaces, &status, &iface_count); + res = totempg_ifaces_get(nodeid, interfaces, &status, &iface_count); if (res == -1) { - return ("no interface found for nodeid"); + return ("no interface found for nodeid"); } for (i = 0; i < iface_count; i++) { - sprintf (one_iface, "r(%d) ip(%s), ", - i, totemip_print (&interfaces[i])); - strcat (iface_string, one_iface); + sprintf(one_iface, "r(%d) ip(%s), ", i, totemip_print(&interfaces[i])); + strcat(iface_string, one_iface); } return (iface_string); } #endif -static void ais_mark_unseen_peer_dead( - gpointer key, gpointer value, gpointer user_data) +static void +ais_mark_unseen_peer_dead(gpointer key, gpointer value, gpointer user_data) { int *changed = user_data; crm_node_t *node = value; - if(node->last_seen != membership_seq - && ais_str_eq(CRM_NODE_LOST, node->state) == FALSE) { - ais_info("Node %s was not seen in the previous transition", node->uname); - *changed += update_member(node->id, 0, membership_seq, node->votes, - node->processes, node->uname, CRM_NODE_LOST, NULL); + + if (node->last_seen != membership_seq && ais_str_eq(CRM_NODE_LOST, node->state) == FALSE) { + ais_info("Node %s was not seen in the previous transition", node->uname); + *changed += update_member(node->id, 0, membership_seq, node->votes, + node->processes, node->uname, CRM_NODE_LOST, NULL); } } -void pcmk_peer_update ( - enum totem_configuration_type configuration_type, - const unsigned int *member_list, size_t member_list_entries, - const unsigned int *left_list, size_t left_list_entries, - const unsigned int *joined_list, size_t joined_list_entries, - const struct memb_ring_id *ring_id - ) +void +pcmk_peer_update(enum totem_configuration_type configuration_type, + const unsigned int *member_list, size_t member_list_entries, + const unsigned int *left_list, size_t left_list_entries, + const unsigned int *joined_list, size_t joined_list_entries, + const struct memb_ring_id *ring_id) { int lpc = 0; int changed = 0; int do_update = 0; - + AIS_ASSERT(ring_id != NULL); - switch(configuration_type) { - case TOTEM_CONFIGURATION_REGULAR: - do_update = 1; - break; - case TOTEM_CONFIGURATION_TRANSITIONAL: - break; + switch (configuration_type) { + case TOTEM_CONFIGURATION_REGULAR: + do_update = 1; + break; + case TOTEM_CONFIGURATION_TRANSITIONAL: + break; } membership_seq = ring_id->seq; ais_notice("%s membership event on ring %lld: memb=%ld, new=%ld, lost=%ld", - do_update?"Stable":"Transitional", ring_id->seq, - (long)member_list_entries, (long)joined_list_entries, (long)left_list_entries); - - if(do_update == 0) { - for(lpc = 0; lpc < joined_list_entries; lpc++) { - const char *prefix = "new: "; - uint32_t nodeid = joined_list[lpc]; - ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); - } - for(lpc = 0; lpc < member_list_entries; lpc++) { - const char *prefix = "memb:"; - uint32_t nodeid = member_list[lpc]; - ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); - } - for(lpc = 0; lpc < left_list_entries; lpc++) { - const char *prefix = "lost:"; - uint32_t nodeid = left_list[lpc]; - ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); - } - return; - } - - for(lpc = 0; lpc < joined_list_entries; lpc++) { - const char *prefix = "NEW: "; - uint32_t nodeid = joined_list[lpc]; - crm_node_t *node = NULL; - changed += update_member( - nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL); - - ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); - - node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(nodeid)); - if(node->addr == NULL) { - const char *addr = totempg_ifaces_print(nodeid); - node->addr = ais_strdup(addr); - ais_debug("Node %u has address %s", nodeid, node->addr); - } - } - - for(lpc = 0; lpc < member_list_entries; lpc++) { - const char *prefix = "MEMB:"; - uint32_t nodeid = member_list[lpc]; - changed += update_member( - nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL); - - ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); - } - - for(lpc = 0; lpc < left_list_entries; lpc++) { - const char *prefix = "LOST:"; - uint32_t nodeid = left_list[lpc]; - changed += update_member( - nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_LOST, NULL); - ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); - } - - if(changed && joined_list_entries == 0 && left_list_entries == 0) { - ais_err("Something strange happened: %d", changed); - changed = 0; - } - + do_update ? "Stable" : "Transitional", ring_id->seq, + (long)member_list_entries, (long)joined_list_entries, (long)left_list_entries); + + if (do_update == 0) { + for (lpc = 0; lpc < joined_list_entries; lpc++) { + const char *prefix = "new: "; + uint32_t nodeid = joined_list[lpc]; + + ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); + } + for (lpc = 0; lpc < member_list_entries; lpc++) { + const char *prefix = "memb:"; + uint32_t nodeid = member_list[lpc]; + + ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); + } + for (lpc = 0; lpc < left_list_entries; lpc++) { + const char *prefix = "lost:"; + uint32_t nodeid = left_list[lpc]; + + ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); + } + return; + } + + for (lpc = 0; lpc < joined_list_entries; lpc++) { + const char *prefix = "NEW: "; + uint32_t nodeid = joined_list[lpc]; + crm_node_t *node = NULL; + + changed += update_member(nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL); + + ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); + + node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(nodeid)); + if (node->addr == NULL) { + const char *addr = totempg_ifaces_print(nodeid); + + node->addr = ais_strdup(addr); + ais_debug("Node %u has address %s", nodeid, node->addr); + } + } + + for (lpc = 0; lpc < member_list_entries; lpc++) { + const char *prefix = "MEMB:"; + uint32_t nodeid = member_list[lpc]; + + changed += update_member(nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL); + + ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); + } + + for (lpc = 0; lpc < left_list_entries; lpc++) { + const char *prefix = "LOST:"; + uint32_t nodeid = left_list[lpc]; + + changed += update_member(nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_LOST, NULL); + ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid); + } + + if (changed && joined_list_entries == 0 && left_list_entries == 0) { + ais_err("Something strange happened: %d", changed); + changed = 0; + } + ais_debug_2("Reaping unseen nodes..."); g_hash_table_foreach(membership_list, ais_mark_unseen_peer_dead, &changed); - if(member_list_entries > 1) { - /* Used to set born-on in send_cluster_id()) - * We need to wait until we have at least one peer since first - * membership id is based on the one before we stopped and isn't reliable - */ - have_reliable_membership_id = TRUE; + if (member_list_entries > 1) { + /* Used to set born-on in send_cluster_id()) + * We need to wait until we have at least one peer since first + * membership id is based on the one before we stopped and isn't reliable + */ + have_reliable_membership_id = TRUE; } - - if(changed) { - ais_debug("%d nodes changed", changed); - pcmk_update_nodeid(); - send_member_notification(); + + if (changed) { + ais_debug("%d nodes changed", changed); + pcmk_update_nodeid(); + send_member_notification(); } - + send_cluster_id(); } -int pcmk_ipc_exit (void *conn) +int +pcmk_ipc_exit(void *conn) { int lpc = 0; const char *client = NULL; void *async_conn = conn; - + for (; lpc < SIZEOF(pcmk_children); lpc++) { - if(pcmk_children[lpc].conn == conn) { - if(wait_active == FALSE) { - /* Make sure the shutdown loop exits */ - pcmk_children[lpc].pid = 0; - } - pcmk_children[lpc].conn = NULL; - pcmk_children[lpc].async_conn = NULL; - client = pcmk_children[lpc].name; - break; - } + if (pcmk_children[lpc].conn == conn) { + if (wait_active == FALSE) { + /* Make sure the shutdown loop exits */ + pcmk_children[lpc].pid = 0; + } + pcmk_children[lpc].conn = NULL; + pcmk_children[lpc].async_conn = NULL; + client = pcmk_children[lpc].name; + break; + } } g_hash_table_remove(membership_notify_list, async_conn); g_hash_table_remove(ipc_client_list, async_conn); - do_ais_log(client?LOG_INFO:(LOG_DEBUG+1), "Client %s (conn=%p, async-conn=%p) left", - client?client:"unknown-transient", conn, async_conn); + do_ais_log(client ? LOG_INFO : (LOG_DEBUG + 1), "Client %s (conn=%p, async-conn=%p) left", + client ? client : "unknown-transient", conn, async_conn); return (0); } -int pcmk_ipc_connect (void *conn) +int +pcmk_ipc_connect(void *conn) { /* OpenAIS hasn't finished setting up the connection at this point * Sending messages now messes up the protocol! */ return (0); } /* * Executive message handlers */ -void pcmk_cluster_swab(void *msg) +void +pcmk_cluster_swab(void *msg) { AIS_Message *ais_msg = msg; ais_debug_3("Performing endian conversion..."); - ais_msg->id = swab32 (ais_msg->id); - ais_msg->size = swab32 (ais_msg->size); - ais_msg->is_compressed = swab32 (ais_msg->is_compressed); - ais_msg->compressed_size = swab32 (ais_msg->compressed_size); - - ais_msg->host.id = swab32 (ais_msg->host.id); - ais_msg->host.pid = swab32 (ais_msg->host.pid); - ais_msg->host.type = swab32 (ais_msg->host.type); - ais_msg->host.size = swab32 (ais_msg->host.size); - ais_msg->host.local = swab32 (ais_msg->host.local); - - ais_msg->sender.id = swab32 (ais_msg->sender.id); - ais_msg->sender.pid = swab32 (ais_msg->sender.pid); - ais_msg->sender.type = swab32 (ais_msg->sender.type); - ais_msg->sender.size = swab32 (ais_msg->sender.size); - ais_msg->sender.local = swab32 (ais_msg->sender.local); - - ais_msg->header.size = swab32 (ais_msg->header.size); - ais_msg->header.id = swab32 (ais_msg->header.id); - ais_msg->header.error = swab32 (ais_msg->header.error); + ais_msg->id = swab32(ais_msg->id); + ais_msg->size = swab32(ais_msg->size); + ais_msg->is_compressed = swab32(ais_msg->is_compressed); + ais_msg->compressed_size = swab32(ais_msg->compressed_size); + + ais_msg->host.id = swab32(ais_msg->host.id); + ais_msg->host.pid = swab32(ais_msg->host.pid); + ais_msg->host.type = swab32(ais_msg->host.type); + ais_msg->host.size = swab32(ais_msg->host.size); + ais_msg->host.local = swab32(ais_msg->host.local); + + ais_msg->sender.id = swab32(ais_msg->sender.id); + ais_msg->sender.pid = swab32(ais_msg->sender.pid); + ais_msg->sender.type = swab32(ais_msg->sender.type); + ais_msg->sender.size = swab32(ais_msg->sender.size); + ais_msg->sender.local = swab32(ais_msg->sender.local); + + ais_msg->header.size = swab32(ais_msg->header.size); + ais_msg->header.id = swab32(ais_msg->header.id); + ais_msg->header.error = swab32(ais_msg->header.error); } -void pcmk_cluster_callback ( - ais_void_ptr *message, unsigned int nodeid) +void +pcmk_cluster_callback(ais_void_ptr * message, unsigned int nodeid) { const AIS_Message *ais_msg = message; - ais_debug_2("Message from node %u (%s)", - nodeid, nodeid==local_nodeid?"local":"remote"); + ais_debug_2("Message from node %u (%s)", nodeid, nodeid == local_nodeid ? "local" : "remote"); /* Shouldn't be required... update_member( ais_msg->sender.id, membership_seq, -1, 0, ais_msg->sender.uname, NULL); */ - if(ais_msg->host.size == 0 - || ais_str_eq(ais_msg->host.uname, local_uname)) { - route_ais_message(ais_msg, FALSE); + if (ais_msg->host.size == 0 || ais_str_eq(ais_msg->host.uname, local_uname)) { + route_ais_message(ais_msg, FALSE); } else { - ais_debug_3("Discarding Msg[%d] (dest=%s:%s, from=%s:%s)", - ais_msg->id, ais_dest(&(ais_msg->host)), - msg_type2text(ais_msg->host.type), - ais_dest(&(ais_msg->sender)), - msg_type2text(ais_msg->sender.type)); + ais_debug_3("Discarding Msg[%d] (dest=%s:%s, from=%s:%s)", + ais_msg->id, ais_dest(&(ais_msg->host)), + msg_type2text(ais_msg->host.type), + ais_dest(&(ais_msg->sender)), msg_type2text(ais_msg->sender.type)); } } -void pcmk_cluster_id_swab(void *msg) +void +pcmk_cluster_id_swab(void *msg) { struct crm_identify_msg_s *ais_msg = msg; ais_debug_3("Performing endian conversion..."); - ais_msg->id = swab32 (ais_msg->id); - ais_msg->pid = swab32 (ais_msg->pid); - ais_msg->votes = swab32 (ais_msg->votes); - ais_msg->processes = swab32 (ais_msg->processes); - ais_msg->born_on = swab64 (ais_msg->born_on); - - ais_msg->header.size = swab32 (ais_msg->header.size); - ais_msg->header.id = swab32 (ais_msg->header.id); + ais_msg->id = swab32(ais_msg->id); + ais_msg->pid = swab32(ais_msg->pid); + ais_msg->votes = swab32(ais_msg->votes); + ais_msg->processes = swab32(ais_msg->processes); + ais_msg->born_on = swab64(ais_msg->born_on); + + ais_msg->header.size = swab32(ais_msg->header.size); + ais_msg->header.id = swab32(ais_msg->header.id); } -void pcmk_cluster_id_callback (ais_void_ptr *message, unsigned int nodeid) +void +pcmk_cluster_id_callback(ais_void_ptr * message, unsigned int nodeid) { int changed = 0; const struct crm_identify_msg_s *msg = message; - if(nodeid != msg->id) { - ais_err("Invalid message: Node %u claimed to be node %d", - nodeid, msg->id); - return; + + if (nodeid != msg->id) { + ais_err("Invalid message: Node %u claimed to be node %d", nodeid, msg->id); + return; } ais_debug("Node update: %s (%s)", msg->uname, msg->version); - changed = update_member( - nodeid, msg->born_on, membership_seq, msg->votes, msg->processes, msg->uname, NULL, msg->version); + changed = + update_member(nodeid, msg->born_on, membership_seq, msg->votes, msg->processes, msg->uname, + NULL, msg->version); - if(changed) { - send_member_notification(); + if (changed) { + send_member_notification(); } } struct res_overlay { - coroipc_response_header_t header __attribute((aligned(8))); - char buf[4096]; + coroipc_response_header_t header __attribute((aligned(8))); + char buf[4096]; }; struct res_overlay *res_overlay = NULL; -static void send_ipc_ack(void *conn) +static void +send_ipc_ack(void *conn) { - if(res_overlay == NULL) { - ais_malloc0(res_overlay, sizeof(struct res_overlay)); + if (res_overlay == NULL) { + ais_malloc0(res_overlay, sizeof(struct res_overlay)); } - + res_overlay->header.id = CRM_MESSAGE_IPC_ACK; - res_overlay->header.size = sizeof (coroipc_response_header_t); + res_overlay->header.size = sizeof(coroipc_response_header_t); res_overlay->header.error = CS_OK; - pcmk_api->ipc_response_send (conn, res_overlay, res_overlay->header.size); + pcmk_api->ipc_response_send(conn, res_overlay, res_overlay->header.size); } - /* local callbacks */ -void pcmk_ipc(void *conn, ais_void_ptr *msg) +void +pcmk_ipc(void *conn, ais_void_ptr * msg) { AIS_Message *mutable; int type = 0, size = 0; gboolean transient = TRUE; - const AIS_Message *ais_msg = (const AIS_Message*)msg; + const AIS_Message *ais_msg = (const AIS_Message *)msg; void *async_conn = conn; + ais_debug_2("Message from client %p", conn); - if(check_message_sanity(msg, ((const AIS_Message*)msg)->data) == FALSE) { - /* The message is corrupted - ignore */ - send_ipc_ack(conn); msg = NULL; - return; + if (check_message_sanity(msg, ((const AIS_Message *)msg)->data) == FALSE) { + /* The message is corrupted - ignore */ + send_ipc_ack(conn); + msg = NULL; + return; } /* Make a copy of the message here and ACK it * The message is only valid until a response is sent * but the response must also be sent _before_ we send anything else */ mutable = ais_msg_copy(ais_msg); AIS_ASSERT(check_message_sanity(mutable, mutable->data)); - + size = mutable->header.size; /* ais_malloc0(ais_msg, size); */ - /* memcpy(ais_msg, msg, size); */ - + /* memcpy(ais_msg, msg, size); */ + type = mutable->sender.type; - ais_debug_3("type: %d local: %d conn: %p host type: %d ais: %d sender pid: %d child pid: %d size: %d", - type, mutable->host.local, pcmk_children[type].conn, mutable->host.type, crm_msg_ais, - mutable->sender.pid, pcmk_children[type].pid, ((int)SIZEOF(pcmk_children))); - - if(type > crm_msg_none && type < SIZEOF(pcmk_children)) { - /* known child process */ - transient = FALSE; - } - + ais_debug_3 + ("type: %d local: %d conn: %p host type: %d ais: %d sender pid: %d child pid: %d size: %d", + type, mutable->host.local, pcmk_children[type].conn, mutable->host.type, crm_msg_ais, + mutable->sender.pid, pcmk_children[type].pid, ((int)SIZEOF(pcmk_children))); + + if (type > crm_msg_none && type < SIZEOF(pcmk_children)) { + /* known child process */ + transient = FALSE; + } #if 0 /* If this check fails, the order of pcmk_children probably * doesn't match that of the crm_ais_msg_types enum */ AIS_CHECK(transient || mutable->sender.pid == pcmk_children[type].pid, - ais_err("Sender: %d, child[%d]: %d", mutable->sender.pid, type, pcmk_children[type].pid); - ais_free(mutable); - return); + ais_err("Sender: %d, child[%d]: %d", mutable->sender.pid, type, + pcmk_children[type].pid); + ais_free(mutable); + return); #endif - - if(transient == FALSE - && type > crm_msg_none - && mutable->host.local - && pcmk_children[type].conn == NULL - && mutable->host.type == crm_msg_ais) { - AIS_CHECK(mutable->sender.type != mutable->sender.pid, - ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type)); - - ais_info("Recorded connection %p for %s/%d", - conn, pcmk_children[type].name, pcmk_children[type].pid); - pcmk_children[type].conn = conn; - pcmk_children[type].async_conn = async_conn; - - /* Make sure they have the latest membership */ - if(pcmk_children[type].flags & crm_flag_members) { - char *update = pcmk_generate_membership_data(); - g_hash_table_replace(membership_notify_list, async_conn, async_conn); - ais_info("Sending membership update "U64T" to %s", - membership_seq, pcmk_children[type].name); - send_client_msg(async_conn, crm_class_members, crm_msg_none,update); - } - - } else if(transient) { - AIS_CHECK(mutable->sender.type == mutable->sender.pid, - ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type)); - g_hash_table_replace(ipc_client_list, async_conn, GUINT_TO_POINTER(mutable->sender.pid)); + + if (transient == FALSE + && type > crm_msg_none + && mutable->host.local + && pcmk_children[type].conn == NULL && mutable->host.type == crm_msg_ais) { + AIS_CHECK(mutable->sender.type != mutable->sender.pid, + ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type)); + + ais_info("Recorded connection %p for %s/%d", + conn, pcmk_children[type].name, pcmk_children[type].pid); + pcmk_children[type].conn = conn; + pcmk_children[type].async_conn = async_conn; + + /* Make sure they have the latest membership */ + if (pcmk_children[type].flags & crm_flag_members) { + char *update = pcmk_generate_membership_data(); + + g_hash_table_replace(membership_notify_list, async_conn, async_conn); + ais_info("Sending membership update " U64T " to %s", + membership_seq, pcmk_children[type].name); + send_client_msg(async_conn, crm_class_members, crm_msg_none, update); + } + + } else if (transient) { + AIS_CHECK(mutable->sender.type == mutable->sender.pid, + ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type)); + g_hash_table_replace(ipc_client_list, async_conn, GUINT_TO_POINTER(mutable->sender.pid)); } mutable->sender.id = local_nodeid; mutable->sender.size = local_uname_len; memset(mutable->sender.uname, 0, MAX_NAME); memcpy(mutable->sender.uname, local_uname, mutable->sender.size); route_ais_message(mutable, TRUE); - send_ipc_ack(conn); msg = NULL; + send_ipc_ack(conn); + msg = NULL; ais_free(mutable); } -int pcmk_shutdown (void) +int +pcmk_shutdown(void) { int lpc = 0; static int phase = 0; static int max_wait = 0; static time_t next_log = 0; static int max = SIZEOF(pcmk_children); - if(use_mcp) { - if(pcmk_children[crm_msg_crmd].conn || pcmk_children[crm_msg_stonith_ng].conn) { - time_t now = time(NULL); - if(now > next_log) { - next_log = now + 300; - ais_notice("Preventing Corosync shutdown. Please ensure Pacemaker is stopped first."); - } - return -1; - } - ais_notice("Unloading Pacemaker plugin"); - return 0; + if (use_mcp) { + if (pcmk_children[crm_msg_crmd].conn || pcmk_children[crm_msg_stonith_ng].conn) { + time_t now = time(NULL); + + if (now > next_log) { + next_log = now + 300; + ais_notice + ("Preventing Corosync shutdown. Please ensure Pacemaker is stopped first."); + } + return -1; + } + ais_notice("Unloading Pacemaker plugin"); + return 0; } - - if(phase == 0) { - ais_notice("Shuting down Pacemaker"); - phase = max; + + if (phase == 0) { + ais_notice("Shuting down Pacemaker"); + phase = max; } - wait_active = FALSE; /* stop the wait loop */ + wait_active = FALSE; /* stop the wait loop */ for (; phase > 0; phase--) { - /* dont stop anything with start_seq < 1 */ - - for (lpc = max - 1; lpc >= 0; lpc--) { - if(phase != pcmk_children[lpc].start_seq) { - continue; - } - - if(pcmk_children[lpc].pid) { - pid_t pid = 0; - int status = 0; - time_t now = time(NULL); - - if(pcmk_children[lpc].respawn) { - max_wait = 5; /* 5 * 30s = 2.5 minutes... plenty once the crmd is gone */ - next_log = now + 30; - pcmk_children[lpc].respawn = FALSE; - stop_child(&(pcmk_children[lpc]), SIGTERM); - } - - pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL); - if(pid < 0) { - ais_perror("Call to wait4(%s/%d) failed - treating it as stopped", - pcmk_children[lpc].name, pcmk_children[lpc].pid); - - } else if(pid == 0) { - if(now >= next_log) { - max_wait--; - next_log = now + 30; - ais_notice("Still waiting for %s (pid=%d, seq=%d) to terminate...", - pcmk_children[lpc].name, pcmk_children[lpc].pid, pcmk_children[lpc].start_seq); - if(max_wait <= 0 && phase < pcmk_children[crm_msg_crmd].start_seq) { - ais_err("Child %s taking too long to terminate, sending SIGKILL", pcmk_children[lpc].name); - stop_child(&(pcmk_children[lpc]), SIGKILL); - } - } - /* Return control to corosync */ - return -1; - } - } - - /* cleanup */ - ais_notice("%s confirmed stopped", pcmk_children[lpc].name); - pcmk_children[lpc].async_conn = NULL; - pcmk_children[lpc].conn = NULL; - pcmk_children[lpc].pid = 0; - } - } - + /* dont stop anything with start_seq < 1 */ + + for (lpc = max - 1; lpc >= 0; lpc--) { + if (phase != pcmk_children[lpc].start_seq) { + continue; + } + + if (pcmk_children[lpc].pid) { + pid_t pid = 0; + int status = 0; + time_t now = time(NULL); + + if (pcmk_children[lpc].respawn) { + max_wait = 5; /* 5 * 30s = 2.5 minutes... plenty once the crmd is gone */ + next_log = now + 30; + pcmk_children[lpc].respawn = FALSE; + stop_child(&(pcmk_children[lpc]), SIGTERM); + } + + pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL); + if (pid < 0) { + ais_perror("Call to wait4(%s/%d) failed - treating it as stopped", + pcmk_children[lpc].name, pcmk_children[lpc].pid); + + } else if (pid == 0) { + if (now >= next_log) { + max_wait--; + next_log = now + 30; + ais_notice("Still waiting for %s (pid=%d, seq=%d) to terminate...", + pcmk_children[lpc].name, pcmk_children[lpc].pid, + pcmk_children[lpc].start_seq); + if (max_wait <= 0 && phase < pcmk_children[crm_msg_crmd].start_seq) { + ais_err("Child %s taking too long to terminate, sending SIGKILL", + pcmk_children[lpc].name); + stop_child(&(pcmk_children[lpc]), SIGKILL); + } + } + /* Return control to corosync */ + return -1; + } + } + + /* cleanup */ + ais_notice("%s confirmed stopped", pcmk_children[lpc].name); + pcmk_children[lpc].async_conn = NULL; + pcmk_children[lpc].conn = NULL; + pcmk_children[lpc].pid = 0; + } + } + send_cluster_id(); ais_notice("Shutdown complete"); /* TODO: Add back the logsys flush call once its written */ - + return 0; } -struct member_loop_data -{ - char *string; +struct member_loop_data { + char *string; }; -void member_vote_count_fn(gpointer key, gpointer value, gpointer user_data) +void +member_vote_count_fn(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; + if (ais_str_eq(CRM_NODE_MEMBER, node->state)) { plugin_has_votes += node->votes; } } - -void member_loop_fn(gpointer key, gpointer value, gpointer user_data) +void +member_loop_fn(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; - struct member_loop_data *data = user_data; + struct member_loop_data *data = user_data; ais_debug_2("Dumping node %u", node->id); data->string = append_member(data->string, node); } -char *pcmk_generate_membership_data(void) +char * +pcmk_generate_membership_data(void) { int size = 0; struct member_loop_data data; - size = 256; + + size = 256; ais_malloc0(data.string, size); /* Ensure the list of active processes is up-to-date */ update_member(local_nodeid, 0, 0, -1, get_process_list(), local_uname, CRM_NODE_MEMBER, NULL); - + plugin_has_votes = 0; g_hash_table_foreach(membership_list, member_vote_count_fn, NULL); - if(plugin_has_votes > plugin_expected_votes) { - update_expected_votes(plugin_has_votes); + if (plugin_has_votes > plugin_expected_votes) { + update_expected_votes(plugin_has_votes); } - + snprintf(data.string, size, - "", - membership_seq, plugin_has_quorum()?"true":"false", - plugin_expected_votes, plugin_has_votes); + "", + membership_seq, plugin_has_quorum()? "true" : "false", + plugin_expected_votes, plugin_has_votes); g_hash_table_foreach(membership_list, member_loop_fn, &data); size = strlen(data.string); - data.string = realloc(data.string, size + 9) ;/* 9 = + nul */ + data.string = realloc(data.string, size + 9); /* 9 = + nul */ sprintf(data.string + size, ""); return data.string; } -void pcmk_nodes(void *conn, ais_void_ptr *msg) +void +pcmk_nodes(void *conn, ais_void_ptr * msg) { char *data = pcmk_generate_membership_data(); void *async_conn = conn; /* send the ACK before we send any other messages * - but after we no longer need to access the message */ - send_ipc_ack(conn); msg = NULL; + send_ipc_ack(conn); + msg = NULL; - if(async_conn) { - send_client_msg(async_conn, crm_class_members, crm_msg_none, data); + if (async_conn) { + send_client_msg(async_conn, crm_class_members, crm_msg_none, data); } ais_free(data); } -void pcmk_remove_member(void *conn, ais_void_ptr *msg) +void +pcmk_remove_member(void *conn, ais_void_ptr * msg) { const AIS_Message *ais_msg = msg; char *data = get_ais_data(ais_msg); - send_ipc_ack(conn); msg = NULL; - - if(data != NULL) { - char *bcast = ais_concat("remove-peer", data, ':'); - send_cluster_msg(crm_msg_ais, NULL, bcast); - ais_info("Sent: %s", bcast); - ais_free(bcast); - } - + + send_ipc_ack(conn); + msg = NULL; + + if (data != NULL) { + char *bcast = ais_concat("remove-peer", data, ':'); + + send_cluster_msg(crm_msg_ais, NULL, bcast); + ais_info("Sent: %s", bcast); + ais_free(bcast); + } + ais_free(data); } -static void send_quorum_details(void *conn) +static void +send_quorum_details(void *conn) { int size = 256; char *data = NULL; + ais_malloc0(data, size); - - snprintf(data, size, "", - membership_seq, plugin_has_quorum()?"true":"false", - plugin_expected_votes, plugin_has_votes); + + snprintf(data, size, "", + membership_seq, plugin_has_quorum()? "true" : "false", + plugin_expected_votes, plugin_has_votes); send_client_msg(conn, crm_class_quorum, crm_msg_none, data); ais_free(data); } -void pcmk_quorum(void *conn, ais_void_ptr *msg) +void +pcmk_quorum(void *conn, ais_void_ptr * msg) { char *dummy = NULL; const AIS_Message *ais_msg = msg; char *data = get_ais_data(ais_msg); - send_ipc_ack(conn); msg = NULL; + + send_ipc_ack(conn); + msg = NULL; /* Make sure the current number of votes is accurate */ dummy = pcmk_generate_membership_data(); ais_free(dummy); /* Calls without data just want the current quorum details */ - if(data != NULL && strlen(data) > 0) { - int value = ais_get_int(data, NULL); - update_expected_votes(value); + if (data != NULL && strlen(data) > 0) { + int value = ais_get_int(data, NULL); + + update_expected_votes(value); } send_quorum_details(conn); ais_free(data); } -void pcmk_notify(void *conn, ais_void_ptr *msg) +void +pcmk_notify(void *conn, ais_void_ptr * msg) { const AIS_Message *ais_msg = msg; char *data = get_ais_data(ais_msg); void *async_conn = conn; int enable = 0; int sender = ais_msg->sender.pid; - - send_ipc_ack(conn); msg = NULL; - if(ais_str_eq("true", data)) { - enable = 1; + send_ipc_ack(conn); + msg = NULL; + + if (ais_str_eq("true", data)) { + enable = 1; } - + ais_info("%s node notifications for child %d (%p)", - enable?"Enabling":"Disabling", sender, async_conn); - if(enable) { - g_hash_table_replace(membership_notify_list, async_conn, async_conn); + enable ? "Enabling" : "Disabling", sender, async_conn); + if (enable) { + g_hash_table_replace(membership_notify_list, async_conn, async_conn); } else { - g_hash_table_remove(membership_notify_list, async_conn); + g_hash_table_remove(membership_notify_list, async_conn); } ais_free(data); } -void pcmk_nodeid(void *conn, ais_void_ptr *msg) +void +pcmk_nodeid(void *conn, ais_void_ptr * msg) { static int counter = 0; struct crm_ais_nodeid_resp_s resp; + ais_debug_2("Sending local nodeid: %d to %p[%d]", local_nodeid, conn, counter); - + resp.header.id = crm_class_nodeid; - resp.header.size = sizeof (struct crm_ais_nodeid_resp_s); + resp.header.size = sizeof(struct crm_ais_nodeid_resp_s); resp.header.error = CS_OK; resp.id = local_nodeid; resp.counter = counter++; memset(resp.uname, 0, MAX_NAME); memcpy(resp.uname, local_uname, local_uname_len); memset(resp.cname, 0, MAX_NAME); memcpy(resp.cname, local_cname, local_cname_len); - - pcmk_api->ipc_response_send (conn, &resp, resp.header.size); + + pcmk_api->ipc_response_send(conn, &resp, resp.header.size); } static gboolean ghash_send_update(gpointer key, gpointer value, gpointer data) { - if(send_client_msg(value, crm_class_members, crm_msg_none, data) != 0) { - /* remove it */ - return TRUE; + if (send_client_msg(value, crm_class_members, crm_msg_none, data) != 0) { + /* remove it */ + return TRUE; } return FALSE; } -void send_member_notification(void) +void +send_member_notification(void) { char *update = pcmk_generate_membership_data(); - ais_info("Sending membership update "U64T" to %d children", - membership_seq, - g_hash_table_size(membership_notify_list)); + ais_info("Sending membership update " U64T " to %d children", + membership_seq, g_hash_table_size(membership_notify_list)); g_hash_table_foreach_remove(membership_notify_list, ghash_send_update, update); ais_free(update); } -gboolean check_message_sanity(const AIS_Message *msg, const char *data) +gboolean +check_message_sanity(const AIS_Message * msg, const char *data) { gboolean sane = TRUE; gboolean repaired = FALSE; int dest = msg->host.type; int tmp_size = msg->header.size - sizeof(AIS_Message); - if(sane && msg->header.size == 0) { - ais_err("Message with no size"); - sane = FALSE; + if (sane && msg->header.size == 0) { + ais_err("Message with no size"); + sane = FALSE; } - if(sane && msg->header.error != CS_OK) { - ais_err("Message header contains an error: %d", msg->header.error); - sane = FALSE; + if (sane && msg->header.error != CS_OK) { + ais_err("Message header contains an error: %d", msg->header.error); + sane = FALSE; } AIS_CHECK(msg->header.size > sizeof(AIS_Message), - ais_err("Message %d size too small: %d < %zu", - msg->header.id, msg->header.size, sizeof(AIS_Message)); - return FALSE); - - if(sane && ais_data_len(msg) != tmp_size) { - ais_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg), tmp_size); - sane = TRUE; - } - - if(sane && ais_data_len(msg) == 0) { - ais_err("Message with no payload"); - sane = FALSE; - } - - if(sane && data && msg->is_compressed == FALSE) { - int str_size = strlen(data) + 1; - if(ais_data_len(msg) != str_size) { - int lpc = 0; - ais_err("Message payload is corrupted: expected %d bytes, got %d", - ais_data_len(msg), str_size); - sane = FALSE; - for(lpc = (str_size - 10); lpc < msg->size; lpc++) { - if(lpc < 0) { - lpc = 0; - } - ais_debug_2("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]); - } - } - } - - if(sane == FALSE) { - AIS_CHECK(sane, - ais_err("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", - msg->id, ais_dest(&(msg->host)), msg_type2text(dest), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, msg->is_compressed, ais_data_len(msg), - msg->header.size)); - - } else if(repaired) { - ais_err("Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", - msg->id, ais_dest(&(msg->host)), msg_type2text(dest), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, msg->is_compressed, ais_data_len(msg), - msg->header.size); + ais_err("Message %d size too small: %d < %zu", + msg->header.id, msg->header.size, sizeof(AIS_Message)); + return FALSE); + + if (sane && ais_data_len(msg) != tmp_size) { + ais_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg), + tmp_size); + sane = TRUE; + } + + if (sane && ais_data_len(msg) == 0) { + ais_err("Message with no payload"); + sane = FALSE; + } + + if (sane && data && msg->is_compressed == FALSE) { + int str_size = strlen(data) + 1; + + if (ais_data_len(msg) != str_size) { + int lpc = 0; + + ais_err("Message payload is corrupted: expected %d bytes, got %d", + ais_data_len(msg), str_size); + sane = FALSE; + for (lpc = (str_size - 10); lpc < msg->size; lpc++) { + if (lpc < 0) { + lpc = 0; + } + ais_debug_2("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]); + } + } + } + + if (sane == FALSE) { + AIS_CHECK(sane, + ais_err + ("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", + msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)), + msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed, + ais_data_len(msg), msg->header.size)); + + } else if (repaired) { + ais_err + ("Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", + msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)), + msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed, + ais_data_len(msg), msg->header.size); } else { - ais_debug_3("Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", - msg->id, ais_dest(&(msg->host)), msg_type2text(dest), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, msg->is_compressed, ais_data_len(msg), - msg->header.size); + ais_debug_3 + ("Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", + msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)), + msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed, + ais_data_len(msg), msg->header.size); } return sane; } static int delivered_transient = 0; -static void deliver_transient_msg(gpointer key, gpointer value, gpointer user_data) +static void +deliver_transient_msg(gpointer key, gpointer value, gpointer user_data) { - int pid = GPOINTER_TO_INT(value); + int pid = GPOINTER_TO_INT(value); AIS_Message *mutable = user_data; - if(pid == mutable->host.type) { - int rc = send_client_ipc(key, mutable); - delivered_transient++; - - ais_info("Sent message to %s.%d (rc=%d)", - ais_dest(&(mutable->host)), pid, rc); - if(rc != 0) { - ais_warn("Sending message to %s.%d failed (rc=%d)", - ais_dest(&(mutable->host)), pid, rc); - log_ais_message(LOG_DEBUG, mutable); - } + if (pid == mutable->host.type) { + int rc = send_client_ipc(key, mutable); + + delivered_transient++; + + ais_info("Sent message to %s.%d (rc=%d)", ais_dest(&(mutable->host)), pid, rc); + if (rc != 0) { + ais_warn("Sending message to %s.%d failed (rc=%d)", + ais_dest(&(mutable->host)), pid, rc); + log_ais_message(LOG_DEBUG, mutable); + } } } -gboolean route_ais_message(const AIS_Message *msg, gboolean local_origin) +gboolean +route_ais_message(const AIS_Message * msg, gboolean local_origin) { int rc = 0; int dest = msg->host.type; const char *reason = "unknown"; AIS_Message *mutable = ais_msg_copy(msg); - static int service_id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0); + static int service_id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0); ais_debug_3("Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d)", - mutable->id, ais_dest(&(mutable->host)), msg_type2text(dest), - ais_dest(&(mutable->sender)), msg_type2text(mutable->sender.type), - mutable->sender.pid, local_origin?"false":"true", ais_data_len((mutable))); - - if(local_origin == FALSE) { - if(mutable->host.size == 0 - || ais_str_eq(local_uname, mutable->host.uname)) { - mutable->host.local = TRUE; - } - } - - if(check_message_sanity(mutable, mutable->data) == FALSE) { - /* Dont send this message to anyone */ - rc = 1; - goto bail; - } - - if(mutable->host.local) { - void *conn = NULL; - const char *lookup = NULL; - - if(dest == crm_msg_ais) { - process_ais_message(mutable); - goto bail; - - } else if(dest == crm_msg_lrmd) { - /* lrmd messages are routed via the crm */ - dest = crm_msg_crmd; - - } else if(dest == crm_msg_te) { - /* te messages are routed via the crm */ - dest = crm_msg_crmd; - - } else if(dest >= SIZEOF(pcmk_children)) { - /* Transient client */ - - delivered_transient = 0; - g_hash_table_foreach(ipc_client_list, deliver_transient_msg, mutable); - if(delivered_transient) { - ais_debug_2("Sent message to %d transient clients: %d", delivered_transient, dest); - goto bail; - - } else { - /* try the crmd */ - ais_debug_2("Sending message to transient client %d via crmd", dest); - dest = crm_msg_crmd; - } - - } else if(dest == 0) { - ais_err("Invalid destination: %d", dest); - log_ais_message(LOG_ERR, mutable); - log_printf(LOG_ERR, "%s", get_ais_data(mutable)); - rc = 1; - goto bail; - } - - lookup = msg_type2text(dest); - conn = pcmk_children[dest].async_conn; + mutable->id, ais_dest(&(mutable->host)), msg_type2text(dest), + ais_dest(&(mutable->sender)), msg_type2text(mutable->sender.type), + mutable->sender.pid, local_origin ? "false" : "true", ais_data_len((mutable))); - /* the cluster fails in weird and wonderfully obscure ways when this is not true */ - AIS_ASSERT(ais_str_eq(lookup, pcmk_children[dest].name)); + if (local_origin == FALSE) { + if (mutable->host.size == 0 || ais_str_eq(local_uname, mutable->host.uname)) { + mutable->host.local = TRUE; + } + } - if(mutable->header.id == service_id) { - mutable->header.id = 0; /* reset this back to zero for IPC messages */ + if (check_message_sanity(mutable, mutable->data) == FALSE) { + /* Dont send this message to anyone */ + rc = 1; + goto bail; + } + + if (mutable->host.local) { + void *conn = NULL; + const char *lookup = NULL; + + if (dest == crm_msg_ais) { + process_ais_message(mutable); + goto bail; + + } else if (dest == crm_msg_lrmd) { + /* lrmd messages are routed via the crm */ + dest = crm_msg_crmd; + + } else if (dest == crm_msg_te) { + /* te messages are routed via the crm */ + dest = crm_msg_crmd; + + } else if (dest >= SIZEOF(pcmk_children)) { + /* Transient client */ + + delivered_transient = 0; + g_hash_table_foreach(ipc_client_list, deliver_transient_msg, mutable); + if (delivered_transient) { + ais_debug_2("Sent message to %d transient clients: %d", delivered_transient, dest); + goto bail; + + } else { + /* try the crmd */ + ais_debug_2("Sending message to transient client %d via crmd", dest); + dest = crm_msg_crmd; + } + + } else if (dest == 0) { + ais_err("Invalid destination: %d", dest); + log_ais_message(LOG_ERR, mutable); + log_printf(LOG_ERR, "%s", get_ais_data(mutable)); + rc = 1; + goto bail; + } + + lookup = msg_type2text(dest); + conn = pcmk_children[dest].async_conn; + + /* the cluster fails in weird and wonderfully obscure ways when this is not true */ + AIS_ASSERT(ais_str_eq(lookup, pcmk_children[dest].name)); + + if (mutable->header.id == service_id) { + mutable->header.id = 0; /* reset this back to zero for IPC messages */ + + } else if (mutable->header.id != 0) { + ais_err("reset header id back to zero from %d", mutable->header.id); + mutable->header.id = 0; /* reset this back to zero for IPC messages */ + } + + reason = "ipc delivery failed"; + rc = send_client_ipc(conn, mutable); + + } else if (local_origin) { + /* forward to other hosts */ + ais_debug_3("Forwarding to cluster"); + reason = "cluster delivery failed"; + rc = send_cluster_msg_raw(mutable); + } + + if (rc != 0) { + ais_warn("Sending message to %s.%s failed: %s (rc=%d)", + ais_dest(&(mutable->host)), msg_type2text(dest), reason, rc); + log_ais_message(LOG_DEBUG, mutable); + } - } else if(mutable->header.id != 0) { - ais_err("reset header id back to zero from %d", mutable->header.id); - mutable->header.id = 0; /* reset this back to zero for IPC messages */ - } - - reason = "ipc delivery failed"; - rc = send_client_ipc(conn, mutable); - - } else if(local_origin) { - /* forward to other hosts */ - ais_debug_3("Forwarding to cluster"); - reason = "cluster delivery failed"; - rc = send_cluster_msg_raw(mutable); - } - - if(rc != 0) { - ais_warn("Sending message to %s.%s failed: %s (rc=%d)", - ais_dest(&(mutable->host)), msg_type2text(dest), reason, rc); - log_ais_message(LOG_DEBUG, mutable); - } - bail: ais_free(mutable); - return rc==0?TRUE:FALSE; + return rc == 0 ? TRUE : FALSE; } -int send_cluster_msg_raw(const AIS_Message *ais_msg) +int +send_cluster_msg_raw(const AIS_Message * ais_msg) { int rc = 0; struct iovec iovec; static uint32_t msg_id = 0; AIS_Message *mutable = ais_msg_copy(ais_msg); AIS_ASSERT(local_nodeid != 0); AIS_ASSERT(ais_msg->header.size == (sizeof(AIS_Message) + ais_data_len(ais_msg))); - if(mutable->id == 0) { - msg_id++; - AIS_CHECK(msg_id != 0 /* detect wrap-around */, - msg_id++; ais_err("Message ID wrapped around")); - mutable->id = msg_id; + if (mutable->id == 0) { + msg_id++; + AIS_CHECK(msg_id != 0 /* detect wrap-around */ , + msg_id++; ais_err("Message ID wrapped around")); + mutable->id = msg_id; } - + mutable->header.error = CS_OK; - mutable->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0); + mutable->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0); mutable->sender.id = local_nodeid; mutable->sender.size = local_uname_len; memset(mutable->sender.uname, 0, MAX_NAME); memcpy(mutable->sender.uname, local_uname, mutable->sender.size); iovec.iov_base = (char *)mutable; iovec.iov_len = mutable->header.size; ais_debug_3("Sending message (size=%u)", (unsigned int)iovec.iov_len); rc = pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE); - if(rc == 0 && mutable->is_compressed == FALSE) { - ais_debug_2("Message sent: %.80s", mutable->data); + if (rc == 0 && mutable->is_compressed == FALSE) { + ais_debug_2("Message sent: %.80s", mutable->data); } - + AIS_CHECK(rc == 0, ais_err("Message not sent (%d): %.120s", rc, mutable->data)); ais_free(mutable); - return rc; + return rc; } #define min(x,y) (x)<(y)?(x):(y) -void send_cluster_id(void) +void +send_cluster_id(void) { int rc = 0; int lpc = 0; int len = 0; time_t now = time(NULL); struct iovec iovec; struct crm_identify_msg_s *msg = NULL; static time_t started = 0; static uint64_t first_seq = 0; - + AIS_ASSERT(local_nodeid != 0); - if(started == 0) { - started = now; - first_seq = membership_seq; + if (started == 0) { + started = now; + first_seq = membership_seq; } - if(local_born_on == 0) { - if(started + 15 < now) { - ais_debug("Born-on set to: "U64T" (age)", first_seq); - local_born_on = first_seq; + if (local_born_on == 0) { + if (started + 15 < now) { + ais_debug("Born-on set to: " U64T " (age)", first_seq); + local_born_on = first_seq; - } else if(have_reliable_membership_id) { - ais_debug("Born-on set to: "U64T" (peer)", membership_seq); - local_born_on = membership_seq; + } else if (have_reliable_membership_id) { + ais_debug("Born-on set to: " U64T " (peer)", membership_seq); + local_born_on = membership_seq; - } else { - ais_debug("Leaving born-on unset: "U64T, membership_seq); - } + } else { + ais_debug("Leaving born-on unset: " U64T, membership_seq); + } } - + ais_malloc0(msg, sizeof(struct crm_identify_msg_s)); msg->header.size = sizeof(struct crm_identify_msg_s); msg->id = local_nodeid; /* msg->header.error = CS_OK; */ - msg->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 1); + msg->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 1); - len = min(local_uname_len, MAX_NAME-1); + len = min(local_uname_len, MAX_NAME - 1); memset(msg->uname, 0, MAX_NAME); memcpy(msg->uname, local_uname, len); - len = min(strlen(VERSION), MAX_NAME-1); + len = min(strlen(VERSION), MAX_NAME - 1); memset(msg->version, 0, MAX_NAME); memcpy(msg->version, VERSION, len); - + msg->votes = 1; msg->pid = getpid(); msg->processes = get_process_list(); msg->born_on = local_born_on; - ais_debug("Local update: id=%u, born="U64T", seq="U64T"", - local_nodeid, local_born_on, membership_seq); - update_member( - local_nodeid, local_born_on, membership_seq, msg->votes, msg->processes, NULL, NULL, VERSION); + ais_debug("Local update: id=%u, born=" U64T ", seq=" U64T "", + local_nodeid, local_born_on, membership_seq); + update_member(local_nodeid, local_born_on, membership_seq, msg->votes, msg->processes, NULL, + NULL, VERSION); iovec.iov_base = (char *)msg; iovec.iov_len = msg->header.size; - + rc = pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE); AIS_CHECK(rc == 0, ais_err("Message not sent (%d)", rc)); ais_free(msg); } static gboolean ghash_send_removal(gpointer key, gpointer value, gpointer data) { send_quorum_details(value); - if(send_client_msg(value, crm_class_rmpeer, crm_msg_none, data) != 0) { - /* remove it */ - return TRUE; + if (send_client_msg(value, crm_class_rmpeer, crm_msg_none, data) != 0) { + /* remove it */ + return TRUE; } return FALSE; } -void ais_remove_peer(char *node_id) +void +ais_remove_peer(char *node_id) { - uint32_t id = ais_get_int(node_id, NULL); + uint32_t id = ais_get_int(node_id, NULL); crm_node_t *node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id)); - if(node == NULL) { - ais_info("Peer %u is unknown", id); - } else if(ais_str_eq(CRM_NODE_MEMBER, node->state)) { - ais_warn("Peer %u/%s is still active", id, node->uname); + if (node == NULL) { + ais_info("Peer %u is unknown", id); + + } else if (ais_str_eq(CRM_NODE_MEMBER, node->state)) { + ais_warn("Peer %u/%s is still active", id, node->uname); + + } else if (g_hash_table_remove(membership_list, GUINT_TO_POINTER(id))) { + plugin_expected_votes--; + ais_notice("Removed dead peer %u from the membership list", id); + ais_info("Sending removal of %u to %d children", + id, g_hash_table_size(membership_notify_list)); + + g_hash_table_foreach_remove(membership_notify_list, ghash_send_removal, node_id); - } else if(g_hash_table_remove(membership_list, GUINT_TO_POINTER(id))) { - plugin_expected_votes--; - ais_notice("Removed dead peer %u from the membership list", id); - ais_info("Sending removal of %u to %d children", - id, g_hash_table_size(membership_notify_list)); - - g_hash_table_foreach_remove(membership_notify_list, ghash_send_removal, node_id); - } else { - ais_warn("Peer %u/%s was not removed", id, node->uname); + ais_warn("Peer %u/%s was not removed", id, node->uname); } } -gboolean process_ais_message(const AIS_Message *msg) +gboolean +process_ais_message(const AIS_Message * msg) { int len = ais_data_len(msg); char *data = get_ais_data(msg); + do_ais_log(LOG_DEBUG, - "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", - msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, - msg->sender.uname==local_uname?"false":"true", - ais_data_len(msg), data); - - if(data && len > 12 && strncmp("remove-peer:", data, 12) == 0) { - char *node = data+12; - ais_remove_peer(node); - } - + "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", + msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), + ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), + msg->sender.pid, + msg->sender.uname == local_uname ? "false" : "true", ais_data_len(msg), data); + + if (data && len > 12 && strncmp("remove-peer:", data, 12) == 0) { + char *node = data + 12; + + ais_remove_peer(node); + } + ais_free(data); return TRUE; } -static void member_dump_fn(gpointer key, gpointer value, gpointer user_data) +static void +member_dump_fn(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; - ais_info(" node id:%u, uname=%s state=%s processes=%.16x born="U64T" seen="U64T" addr=%s version=%s", - node->id, node->uname?node->uname:"-unknown-", - node->state, node->processes, node->born, node->last_seen, - node->addr?node->addr:"-unknown-", node->version?node->version:"-unknown-"); + + ais_info(" node id:%u, uname=%s state=%s processes=%.16x born=" U64T " seen=" U64T + " addr=%s version=%s", node->id, node->uname ? node->uname : "-unknown-", node->state, + node->processes, node->born, node->last_seen, node->addr ? node->addr : "-unknown-", + node->version ? node->version : "-unknown-"); } -void pcmk_exec_dump(void) +void +pcmk_exec_dump(void) { /* Called after SIG_USR2 */ process_ais_conf(); - ais_info("Local id: %u, uname: %s, born: "U64T, local_nodeid, local_uname, local_born_on); - ais_info("Membership id: "U64T", quorate: %s, expected: %u, actual: %u", - membership_seq, plugin_has_quorum()?"true":"false", - plugin_expected_votes, plugin_has_votes); + ais_info("Local id: %u, uname: %s, born: " U64T, local_nodeid, local_uname, local_born_on); + ais_info("Membership id: " U64T ", quorate: %s, expected: %u, actual: %u", + membership_seq, plugin_has_quorum()? "true" : "false", + plugin_expected_votes, plugin_has_votes); g_hash_table_foreach(membership_list, member_dump_fn, NULL); } diff --git a/lib/ais/utils.c b/lib/ais/utils.c index 51c5c77b0c..1273157429 100644 --- a/lib/ais/utils.c +++ b/lib/ais/utils.c @@ -1,722 +1,740 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "./utils.h" #include "./plugin.h" struct pcmk_env_s pcmk_env; -void log_ais_message(int level, const AIS_Message *msg) +void +log_ais_message(int level, const AIS_Message * msg) { char *data = get_ais_data(msg); + log_printf(level, - "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", - msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, - msg->sender.uname==local_uname?"false":"true", - ais_data_len(msg), data); + "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", + msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), + ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), + msg->sender.pid, + msg->sender.uname == local_uname ? "false" : "true", ais_data_len(msg), data); /* do_ais_log(level, */ /* "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", */ /* msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), */ /* ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), */ /* msg->sender.pid, */ /* msg->sender.uname==local_uname?"false":"true", */ /* ais_data_len(msg), data); */ ais_free(data); } + /* static gboolean ghash_find_by_uname(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; int id = GPOINTER_TO_INT(user_data); if (node->id == id) { return TRUE; } return FALSE; } */ static int -ais_string_to_boolean(const char * s) +ais_string_to_boolean(const char *s) { int rc = 0; - if(s == NULL) { - return rc; + + if (s == NULL) { + return rc; } - - if(strcasecmp(s, "true") == 0 - || strcasecmp(s, "on") == 0 - || strcasecmp(s, "yes") == 0 - || strcasecmp(s, "y") == 0 - || strcasecmp(s, "1") == 0) { - rc = 1; + + if (strcasecmp(s, "true") == 0 + || strcasecmp(s, "on") == 0 + || strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0) { + rc = 1; } return rc; } static char *opts_default[] = { NULL, NULL }; -static char *opts_vgrind[] = { NULL, NULL, NULL, NULL, NULL }; +static char *opts_vgrind[] = { NULL, NULL, NULL, NULL, NULL }; -gboolean spawn_child(crm_child_t *child) +gboolean +spawn_child(crm_child_t * child) { int lpc = 0; uid_t uid = 0; struct rlimit oflimits; struct passwd *pwentry = NULL; gboolean use_valgrind = FALSE; gboolean use_callgrind = FALSE; const char *devnull = "/dev/null"; const char *env_valgrind = getenv("PCMK_valgrind_enabled"); const char *env_callgrind = getenv("PCMK_callgrind_enabled"); - - if(child->command == NULL) { - ais_info("Nothing to do for child \"%s\"", child->name); - return TRUE; + + if (child->command == NULL) { + ais_info("Nothing to do for child \"%s\"", child->name); + return TRUE; } - - if(ais_string_to_boolean(env_callgrind)) { - use_callgrind = TRUE; - use_valgrind = TRUE; - } else if(env_callgrind != NULL && strstr(env_callgrind, child->name)) { - use_callgrind = TRUE; - use_valgrind = TRUE; + if (ais_string_to_boolean(env_callgrind)) { + use_callgrind = TRUE; + use_valgrind = TRUE; + + } else if (env_callgrind != NULL && strstr(env_callgrind, child->name)) { + use_callgrind = TRUE; + use_valgrind = TRUE; - } else if(ais_string_to_boolean(env_valgrind)) { - use_valgrind = TRUE; + } else if (ais_string_to_boolean(env_valgrind)) { + use_valgrind = TRUE; - } else if(env_valgrind != NULL && strstr(env_valgrind, child->name)) { - use_valgrind = TRUE; + } else if (env_valgrind != NULL && strstr(env_valgrind, child->name)) { + use_valgrind = TRUE; } - if(use_valgrind && strlen(VALGRIND_BIN) == 0) { - ais_warn("Cannot enable valgrind for %s:" - " The location of the valgrind binary is unknown", child->name); - use_valgrind = FALSE; + if (use_valgrind && strlen(VALGRIND_BIN) == 0) { + ais_warn("Cannot enable valgrind for %s:" + " The location of the valgrind binary is unknown", child->name); + use_valgrind = FALSE; } - if(child->uid) { - if(pcmk_user_lookup(child->uid, &uid, NULL) < 0) { - ais_err("Invalid uid (%s) specified for %s", - child->uid, child->name); - return FALSE; - } + if (child->uid) { + if (pcmk_user_lookup(child->uid, &uid, NULL) < 0) { + ais_err("Invalid uid (%s) specified for %s", child->uid, child->name); + return FALSE; + } } - + child->pid = fork(); AIS_ASSERT(child->pid != -1); - if(child->pid > 0) { - /* parent */ - ais_info("Forked child %d for process %s%s", child->pid, child->name, - use_valgrind?" (valgrind enabled: "VALGRIND_BIN")":""); + if (child->pid > 0) { + /* parent */ + ais_info("Forked child %d for process %s%s", child->pid, child->name, + use_valgrind ? " (valgrind enabled: " VALGRIND_BIN ")" : ""); } else { - /* Setup the two alternate arg arrarys */ - opts_vgrind[0] = ais_strdup(VALGRIND_BIN); - if(use_callgrind) { - opts_vgrind[1] = ais_strdup("--tool=callgrind"); - opts_vgrind[2] = ais_strdup("--callgrind-out-file="CRM_STATE_DIR"/callgrind.out.%p"); - opts_vgrind[3] = ais_strdup(child->command); - opts_vgrind[4] = NULL; - } else { - opts_vgrind[1] = ais_strdup(child->command); - opts_vgrind[2] = NULL; - opts_vgrind[3] = NULL; - opts_vgrind[4] = NULL; - } - opts_default[0] = ais_strdup(child->command);; - + /* Setup the two alternate arg arrarys */ + opts_vgrind[0] = ais_strdup(VALGRIND_BIN); + if (use_callgrind) { + opts_vgrind[1] = ais_strdup("--tool=callgrind"); + opts_vgrind[2] = ais_strdup("--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p"); + opts_vgrind[3] = ais_strdup(child->command); + opts_vgrind[4] = NULL; + } else { + opts_vgrind[1] = ais_strdup(child->command); + opts_vgrind[2] = NULL; + opts_vgrind[3] = NULL; + opts_vgrind[4] = NULL; + } + opts_default[0] = ais_strdup(child->command);; + #if 0 - /* Dont set the group for now - it prevents connection to the cluster */ - if(gid && setgid(gid) < 0) { - ais_perror("Could not set group to %d", gid); - } + /* Dont set the group for now - it prevents connection to the cluster */ + if (gid && setgid(gid) < 0) { + ais_perror("Could not set group to %d", gid); + } #endif - if(uid && setuid(uid) < 0) { - ais_perror("Could not set user to %d (%s)", uid, child->uid); - } - - /* Close all open file descriptors */ - getrlimit(RLIMIT_NOFILE, &oflimits); - for (; lpc < oflimits.rlim_cur; lpc++) { - close(lpc); - } - - (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ - (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ - (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ + if (uid && setuid(uid) < 0) { + ais_perror("Could not set user to %d (%s)", uid, child->uid); + } + /* Close all open file descriptors */ + getrlimit(RLIMIT_NOFILE, &oflimits); + for (; lpc < oflimits.rlim_cur; lpc++) { + close(lpc); + } + + (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ + (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ + (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ + +/* *INDENT-OFF* */ setenv("HA_COMPRESSION", "bz2", 1); setenv("HA_cluster_type", "openais", 1); setenv("HA_debug", pcmk_env.debug, 1); setenv("HA_logfacility", pcmk_env.syslog, 1); setenv("HA_LOGFACILITY", pcmk_env.syslog, 1); setenv("HA_use_logd", pcmk_env.use_logd, 1); setenv("HA_quorum_type", pcmk_env.quorum, 1); - - if(pcmk_env.logfile) { - setenv("HA_debugfile", pcmk_env.logfile, 1); - } - - if(use_valgrind) { - (void)execvp(VALGRIND_BIN, opts_vgrind); - } else { - (void)execvp(child->command, opts_default); - } - ais_perror("FATAL: Cannot exec %s", child->command); - exit(100); +/* *INDENT-ON* */ + + if (pcmk_env.logfile) { + setenv("HA_debugfile", pcmk_env.logfile, 1); + } + + if (use_valgrind) { + (void)execvp(VALGRIND_BIN, opts_vgrind); + } else { + (void)execvp(child->command, opts_default); + } + ais_perror("FATAL: Cannot exec %s", child->command); + exit(100); } return TRUE; } gboolean -stop_child(crm_child_t *child, int signal) +stop_child(crm_child_t * child, int signal) { - if(signal == 0) { - signal = SIGTERM; + if (signal == 0) { + signal = SIGTERM; } - if(child->command == NULL) { - ais_info("Nothing to do for child \"%s\"", child->name); - return TRUE; + if (child->command == NULL) { + ais_info("Nothing to do for child \"%s\"", child->name); + return TRUE; } - + ais_debug("Stopping CRM child \"%s\"", child->name); - + if (child->pid <= 0) { - ais_debug_2("Client %s not running", child->name); - return TRUE; + ais_debug_2("Client %s not running", child->name); + return TRUE; } - + errno = 0; - if(kill(child->pid, signal) == 0) { - ais_notice("Sent -%d to %s: [%d]", signal, child->name, child->pid); - + if (kill(child->pid, signal) == 0) { + ais_notice("Sent -%d to %s: [%d]", signal, child->name, child->pid); + } else { - ais_perror("Sent -%d to %s: [%d]", signal, child->name, child->pid); + ais_perror("Sent -%d to %s: [%d]", signal, child->name, child->pid); } - + return TRUE; } -void destroy_ais_node(gpointer data) +void +destroy_ais_node(gpointer data) { crm_node_t *node = data; + ais_info("Destroying entry for node %u", node->id); ais_free(node->addr); ais_free(node->uname); ais_free(node->state); ais_free(node); } -int update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes, - uint32_t procs, const char *uname, const char *state, const char *version) +int +update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes, + uint32_t procs, const char *uname, const char *state, const char *version) { int changed = 0; crm_node_t *node = NULL; - - node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id)); - - if(node == NULL) { - ais_malloc0(node, sizeof(crm_node_t)); - ais_info("Creating entry for node %u born on "U64T"", id, seq); - node->id = id; - node->addr = NULL; - node->state = ais_strdup("unknown"); - - g_hash_table_insert(membership_list, GUINT_TO_POINTER(id), node); - node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id)); + + node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id)); + + if (node == NULL) { + ais_malloc0(node, sizeof(crm_node_t)); + ais_info("Creating entry for node %u born on " U64T "", id, seq); + node->id = id; + node->addr = NULL; + node->state = ais_strdup("unknown"); + + g_hash_table_insert(membership_list, GUINT_TO_POINTER(id), node); + node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id)); } AIS_ASSERT(node != NULL); - if(seq != 0) { - node->last_seen = seq; + if (seq != 0) { + node->last_seen = seq; } - if(born != 0 && node->born != born) { - changed = TRUE; - node->born = born; - ais_info("%p Node %u (%s) born on: "U64T, node, id, uname, born); + if (born != 0 && node->born != born) { + changed = TRUE; + node->born = born; + ais_info("%p Node %u (%s) born on: " U64T, node, id, uname, born); } - if(version != NULL) { - ais_free(node->version); - node->version = ais_strdup(version); + if (version != NULL) { + ais_free(node->version); + node->version = ais_strdup(version); } - - if(uname != NULL) { - if(node->uname == NULL || ais_str_eq(node->uname, uname) == FALSE) { - ais_info("%p Node %u now known as %s (was: %s)", - node, id, uname, node->uname); - ais_free(node->uname); - node->uname = ais_strdup(uname); - changed = TRUE; - } + + if (uname != NULL) { + if (node->uname == NULL || ais_str_eq(node->uname, uname) == FALSE) { + ais_info("%p Node %u now known as %s (was: %s)", node, id, uname, node->uname); + ais_free(node->uname); + node->uname = ais_strdup(uname); + changed = TRUE; + } } - if(procs != 0 && procs != node->processes) { - ais_info("Node %s now has process list: %.32x (%u)", - node->uname, procs, procs); - node->processes = procs; - changed = TRUE; + if (procs != 0 && procs != node->processes) { + ais_info("Node %s now has process list: %.32x (%u)", node->uname, procs, procs); + node->processes = procs; + changed = TRUE; } - if(votes >= 0 && votes != node->votes) { - ais_info("Node %s now has %d quorum votes (was %d)", - node->uname, votes, node->votes); - node->votes = votes; - changed = TRUE; + if (votes >= 0 && votes != node->votes) { + ais_info("Node %s now has %d quorum votes (was %d)", node->uname, votes, node->votes); + node->votes = votes; + changed = TRUE; } - - if(state != NULL) { - if(node->state == NULL || ais_str_eq(node->state, state) == FALSE) { - ais_free(node->state); - node->state = ais_strdup(state); - ais_info("Node %u/%s is now: %s", - id, node->uname?node->uname:"unknown", state); - changed = TRUE; - } + + if (state != NULL) { + if (node->state == NULL || ais_str_eq(node->state, state) == FALSE) { + ais_free(node->state); + node->state = ais_strdup(state); + ais_info("Node %u/%s is now: %s", id, node->uname ? node->uname : "unknown", state); + changed = TRUE; + } } - + return changed; } -void delete_member(uint32_t id, const char *uname) +void +delete_member(uint32_t id, const char *uname) { - if(uname == NULL) { - g_hash_table_remove(membership_list, GUINT_TO_POINTER(id)); - return; + if (uname == NULL) { + g_hash_table_remove(membership_list, GUINT_TO_POINTER(id)); + return; } ais_err("Deleting by uname is not yet supported"); } -const char *member_uname(uint32_t id) +const char * +member_uname(uint32_t id) { - crm_node_t *node = g_hash_table_lookup( - membership_list, GUINT_TO_POINTER(id)); - if(node == NULL) { - return ".unknown."; - } - if(node->uname == NULL) { - return ".pending."; - } - return node->uname; + crm_node_t *node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id)); + + if (node == NULL) { + return ".unknown."; + } + if (node->uname == NULL) { + return ".pending."; + } + return node->uname; } -char *append_member(char *data, crm_node_t *node) +char * +append_member(char *data, crm_node_t * node) { - int size = 1; /* nul */ + int size = 1; /* nul */ int offset = 0; static int fixed_len = 4 + 8 + 7 + 6 + 6 + 7 + 11; - if(data) { - size = strlen(data); + if (data) { + size = strlen(data); } offset = size; size += fixed_len; - size += 32; /* node->id */ - size += 100; /* node->seq, node->born */ + size += 32; /* node->id */ + size += 100; /* node->seq, node->born */ size += strlen(node->state); - if(node->uname) { - size += (7 + strlen(node->uname)); + if (node->uname) { + size += (7 + strlen(node->uname)); } - if(node->addr) { - size += (6 + strlen(node->addr)); + if (node->addr) { + size += (6 + strlen(node->addr)); } - if(node->version) { - size += (9 + strlen(node->version)); + if (node->version) { + size += (9 + strlen(node->version)); } data = realloc(data, size); offset += snprintf(data + offset, size - offset, "id); - if(node->uname) { - offset += snprintf(data + offset, size - offset, "uname=\"%s\" ", node->uname); + if (node->uname) { + offset += snprintf(data + offset, size - offset, "uname=\"%s\" ", node->uname); } offset += snprintf(data + offset, size - offset, "state=\"%s\" ", node->state); - offset += snprintf(data + offset, size - offset, "born=\""U64T"\" ", node->born); - offset += snprintf(data + offset, size - offset, "seen=\""U64T"\" ", node->last_seen); + offset += snprintf(data + offset, size - offset, "born=\"" U64T "\" ", node->born); + offset += snprintf(data + offset, size - offset, "seen=\"" U64T "\" ", node->last_seen); offset += snprintf(data + offset, size - offset, "votes=\"%d\" ", node->votes); offset += snprintf(data + offset, size - offset, "processes=\"%u\" ", node->processes); - if(node->addr) { - offset += snprintf(data + offset, size - offset, "addr=\"%s\" ", node->addr); + if (node->addr) { + offset += snprintf(data + offset, size - offset, "addr=\"%s\" ", node->addr); } - if(node->version) { - offset += snprintf(data + offset, size - offset, "version=\"%s\" ", node->version); + if (node->version) { + offset += snprintf(data + offset, size - offset, "version=\"%s\" ", node->version); } offset += snprintf(data + offset, size - offset, "/>"); return data; } -void swap_sender(AIS_Message *msg) +void +swap_sender(AIS_Message * msg) { int tmp = 0; char tmp_s[256]; + tmp = msg->host.type; msg->host.type = msg->sender.type; msg->sender.type = tmp; tmp = msg->host.type; msg->host.size = msg->sender.type; msg->sender.type = tmp; memcpy(tmp_s, msg->host.uname, 256); memcpy(msg->host.uname, msg->sender.uname, 256); memcpy(msg->sender.uname, tmp_s, 256); } -char *get_ais_data(const AIS_Message *msg) +char * +get_ais_data(const AIS_Message * msg) { int rc = BZ_OK; char *uncompressed = NULL; unsigned int new_size = msg->size + 1; - - if(msg->is_compressed == FALSE) { - uncompressed = strdup(msg->data); + + if (msg->is_compressed == FALSE) { + uncompressed = strdup(msg->data); } else { - ais_malloc0(uncompressed, new_size); - - rc = BZ2_bzBuffToBuffDecompress( - uncompressed, &new_size, (char*)msg->data, msg->compressed_size, 1, 0); - if(rc != BZ_OK) { - ais_info("rc=%d, new=%u expected=%u", rc, new_size, msg->size); - } - AIS_ASSERT(rc == BZ_OK); - AIS_ASSERT(new_size == msg->size); - } - + ais_malloc0(uncompressed, new_size); + + rc = BZ2_bzBuffToBuffDecompress(uncompressed, &new_size, (char *)msg->data, + msg->compressed_size, 1, 0); + if (rc != BZ_OK) { + ais_info("rc=%d, new=%u expected=%u", rc, new_size, msg->size); + } + AIS_ASSERT(rc == BZ_OK); + AIS_ASSERT(new_size == msg->size); + } + return uncompressed; } -int send_cluster_msg( - enum crm_ais_msg_types type, const char *host, const char *data) +int +send_cluster_msg(enum crm_ais_msg_types type, const char *host, const char *data) { int rc = 0; int data_len = 0; AIS_Message *ais_msg = NULL; int total_size = sizeof(AIS_Message); AIS_ASSERT(local_nodeid != 0); - if(data != NULL) { - data_len = 1 + strlen(data); - total_size += data_len; - } + if (data != NULL) { + data_len = 1 + strlen(data); + total_size += data_len; + } ais_malloc0(ais_msg, total_size); - + ais_msg->header.size = total_size; ais_msg->header.error = CS_OK; ais_msg->header.id = 0; - + ais_msg->size = data_len; ais_msg->sender.type = crm_msg_ais; - if(data != NULL) { - memcpy(ais_msg->data, data, data_len); + if (data != NULL) { + memcpy(ais_msg->data, data, data_len); } ais_msg->host.type = type; ais_msg->host.id = 0; - if(host) { - ais_msg->host.size = strlen(host); - memset(ais_msg->host.uname, 0, MAX_NAME); - memcpy(ais_msg->host.uname, host, ais_msg->host.size); + if (host) { + ais_msg->host.size = strlen(host); + memset(ais_msg->host.uname, 0, MAX_NAME); + memcpy(ais_msg->host.uname, host, ais_msg->host.size); /* ais_msg->host.id = nodeid_lookup(host); */ - + } else { - ais_msg->host.type = type; - ais_msg->host.size = 0; - memset(ais_msg->host.uname, 0, MAX_NAME); + ais_msg->host.type = type; + ais_msg->host.size = 0; + memset(ais_msg->host.uname, 0, MAX_NAME); } - + rc = send_cluster_msg_raw(ais_msg); ais_free(ais_msg); - - return rc; + + return rc; } extern struct corosync_api_v1 *pcmk_api; -int send_client_ipc(void *conn, const AIS_Message *ais_msg) +int +send_client_ipc(void *conn, const AIS_Message * ais_msg) { int rc = -1; + if (conn == NULL) { - rc = -2; - + rc = -2; + } else if (!libais_connection_active(conn)) { - ais_warn("Connection no longer active"); - rc = -3; - + ais_warn("Connection no longer active"); + rc = -3; + /* } else if ((queue->size - 1) == queue->used) { */ /* ais_err("Connection is throttled: %d", queue->size); */ } else { #ifdef SUPPORT_COROSYNC - rc = pcmk_api->ipc_dispatch_send (conn, ais_msg, ais_msg->header.size); + rc = pcmk_api->ipc_dispatch_send(conn, ais_msg, ais_msg->header.size); #endif } return rc; } -int send_client_msg( - void *conn, enum crm_ais_msg_class class, enum crm_ais_msg_types type, const char *data) +int +send_client_msg(void *conn, enum crm_ais_msg_class class, enum crm_ais_msg_types type, + const char *data) { int rc = 0; int data_len = 0; int total_size = sizeof(AIS_Message); AIS_Message *ais_msg = NULL; static int msg_id = 0; AIS_ASSERT(local_nodeid != 0); msg_id++; - AIS_ASSERT(msg_id != 0 /* wrap-around */); + AIS_ASSERT(msg_id != 0 /* wrap-around */ ); - if(data != NULL) { - data_len = 1 + strlen(data); + if (data != NULL) { + data_len = 1 + strlen(data); } total_size += data_len; - + ais_malloc0(ais_msg, total_size); - + ais_msg->id = msg_id; ais_msg->header.id = class; ais_msg->header.size = total_size; ais_msg->header.error = CS_OK; - + ais_msg->size = data_len; - if(data != NULL) { - memcpy(ais_msg->data, data, data_len); + if (data != NULL) { + memcpy(ais_msg->data, data, data_len); } - + ais_msg->host.size = 0; ais_msg->host.type = type; memset(ais_msg->host.uname, 0, MAX_NAME); ais_msg->host.id = 0; ais_msg->sender.type = crm_msg_ais; ais_msg->sender.size = local_uname_len; memset(ais_msg->sender.uname, 0, MAX_NAME); memcpy(ais_msg->sender.uname, local_uname, ais_msg->sender.size); ais_msg->sender.id = local_nodeid; rc = send_client_ipc(conn, ais_msg); - if(rc != 0) { - ais_warn("Sending message to %s failed: %d", msg_type2text(type), rc); - log_ais_message(LOG_DEBUG, ais_msg); + if (rc != 0) { + ais_warn("Sending message to %s failed: %d", msg_type2text(type), rc); + log_ais_message(LOG_DEBUG, ais_msg); } ais_free(ais_msg); - return rc; + return rc; } char * -ais_concat(const char *prefix, const char *suffix, char join) +ais_concat(const char *prefix, const char *suffix, char join) { - int len = 0; - char *new_str = NULL; - AIS_ASSERT(prefix != NULL); - AIS_ASSERT(suffix != NULL); - len = strlen(prefix) + strlen(suffix) + 2; - - ais_malloc0(new_str, (len)); - sprintf(new_str, "%s%c%s", prefix, join, suffix); - new_str[len-1] = 0; - return new_str; + int len = 0; + char *new_str = NULL; + + AIS_ASSERT(prefix != NULL); + AIS_ASSERT(suffix != NULL); + len = strlen(prefix) + strlen(suffix) + 2; + + ais_malloc0(new_str, (len)); + sprintf(new_str, "%s%c%s", prefix, join, suffix); + new_str[len - 1] = 0; + return new_str; } -hdb_handle_t config_find_init(struct corosync_api_v1 *config, char *name) +hdb_handle_t +config_find_init(struct corosync_api_v1 * config, char *name) { hdb_handle_t local_handle = 0; + #ifdef SUPPORT_COROSYNC config->object_find_create(OBJECT_PARENT_HANDLE, name, strlen(name), &local_handle); ais_info("Local handle: %lld for %s", local_handle, name); #endif - + return local_handle; } -hdb_handle_t config_find_next(struct corosync_api_v1 *config, char *name, hdb_handle_t top_handle) +hdb_handle_t +config_find_next(struct corosync_api_v1 * config, char *name, hdb_handle_t top_handle) { int rc = 0; hdb_handle_t local_handle = 0; #ifdef SUPPORT_COROSYNC - rc = config->object_find_next (top_handle, &local_handle); + rc = config->object_find_next(top_handle, &local_handle); #endif - - if(rc < 0) { - ais_info("No additional configuration supplied for: %s", name); - local_handle = 0; + + if (rc < 0) { + ais_info("No additional configuration supplied for: %s", name); + local_handle = 0; } else { - ais_info("Processing additional %s options...", name); + ais_info("Processing additional %s options...", name); } return local_handle; } -void config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle) +void +config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle) { #ifdef SUPPORT_COROSYNC - config->object_find_destroy (local_handle); + config->object_find_destroy(local_handle); #endif } -int get_config_opt( - struct corosync_api_v1 *config, - hdb_handle_t object_service_handle, - char *key, char **value, const char *fallback) +int +get_config_opt(struct corosync_api_v1 *config, + hdb_handle_t object_service_handle, char *key, char **value, const char *fallback) { char *env_key = NULL; + *value = NULL; - if(object_service_handle > 0) { - config->object_key_get( - object_service_handle, key, strlen(key), (void**)value, NULL); + if (object_service_handle > 0) { + config->object_key_get(object_service_handle, key, strlen(key), (void **)value, NULL); } - + if (*value) { - ais_info("Found '%s' for option: %s", *value, key); - return 0; + ais_info("Found '%s' for option: %s", *value, key); + return 0; } env_key = ais_concat("HA", key, '_'); *value = getenv(env_key); ais_free(env_key); if (*value) { - ais_info("Found '%s' in ENV for option: %s", *value, key); - return 0; + ais_info("Found '%s' in ENV for option: %s", *value, key); + return 0; } - if(fallback) { - ais_info("Defaulting to '%s' for option: %s", fallback, key); - *value = ais_strdup(fallback); + if (fallback) { + ais_info("Defaulting to '%s' for option: %s", fallback, key); + *value = ais_strdup(fallback); } else { - ais_info("No default for option: %s", key); + ais_info("No default for option: %s", key); } - + return -1; } int -ais_get_boolean(const char * value) +ais_get_boolean(const char *value) { - if(value == NULL) { - return 0; - - } else if (strcasecmp(value, "true") == 0 - || strcasecmp(value, "on") == 0 - || strcasecmp(value, "yes") == 0 - || strcasecmp(value, "y") == 0 - || strcasecmp(value, "1") == 0){ - return 1; - } - return 0; + if (value == NULL) { + return 0; + + } else if (strcasecmp(value, "true") == 0 + || strcasecmp(value, "on") == 0 + || strcasecmp(value, "yes") == 0 + || strcasecmp(value, "y") == 0 || strcasecmp(value, "1") == 0) { + return 1; + } + return 0; } long long ais_get_int(const char *text, char **end_text) { long long result = -1; char *local_end_text = NULL; - + errno = 0; - - if(text != NULL) { + + if (text != NULL) { #ifdef ANSI_ONLY - if(end_text != NULL) { - result = strtol(text, end_text, 10); - } else { - result = strtol(text, &local_end_text, 10); - } + if (end_text != NULL) { + result = strtol(text, end_text, 10); + } else { + result = strtol(text, &local_end_text, 10); + } #else - if(end_text != NULL) { - result = strtoll(text, end_text, 10); - } else { - result = strtoll(text, &local_end_text, 10); - } + if (end_text != NULL) { + result = strtoll(text, end_text, 10); + } else { + result = strtoll(text, &local_end_text, 10); + } #endif - - if(errno == EINVAL) { - ais_err("Conversion of %s failed", text); - result = -1; - - } else if(errno == ERANGE) { - ais_err("Conversion of %s was clipped: %lld", text, result); - - } else if(errno != 0) { - ais_perror("Conversion of %s failed:", text); - } - - if(local_end_text != NULL && local_end_text[0] != '\0') { - ais_err("Characters left over after parsing '%s': '%s'", text, local_end_text); - } + + if (errno == EINVAL) { + ais_err("Conversion of %s failed", text); + result = -1; + + } else if (errno == ERANGE) { + ais_err("Conversion of %s was clipped: %lld", text, result); + + } else if (errno != 0) { + ais_perror("Conversion of %s failed:", text); + } + + if (local_end_text != NULL && local_end_text[0] != '\0') { + ais_err("Characters left over after parsing '%s': '%s'", text, local_end_text); + } } return result; } #define PW_BUFFER_LEN 500 -int pcmk_user_lookup(const char *name, uid_t *uid, gid_t *gid) +int +pcmk_user_lookup(const char *name, uid_t * uid, gid_t * gid) { int rc = -1; char *buffer = NULL; struct passwd pwd; struct passwd *pwentry = NULL; ais_malloc0(buffer, PW_BUFFER_LEN); getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry); - if(pwentry) { - rc = 0; - if(uid) { *uid = pwentry->pw_uid; } - if(gid) { *gid = pwentry->pw_gid; } - ais_debug("Cluster user %s has uid=%d gid=%d", - name, pwentry->pw_uid, pwentry->pw_gid); + if (pwentry) { + rc = 0; + if (uid) { + *uid = pwentry->pw_uid; + } + if (gid) { + *gid = pwentry->pw_gid; + } + ais_debug("Cluster user %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid); } else { - ais_err("Cluster user %s does not exist", name); + ais_err("Cluster user %s does not exist", name); } ais_free(buffer); return rc; } diff --git a/lib/cib/cib_acl.c b/lib/cib/cib_acl.c index 86bc498783..24ffeb95fb 100644 --- a/lib/cib/cib_acl.c +++ b/lib/cib/cib_acl.c @@ -1,802 +1,816 @@ /* * Copyright (C) 2009 Yan Gao * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include -typedef struct acl_obj_s -{ - const char *mode; - const char *tag; - const char *ref; - const char *xpath; - const char *attribute; +typedef struct acl_obj_s { + const char *mode; + const char *tag; + const char *ref; + const char *xpath; + const char *attribute; } acl_obj_t; -typedef struct xml_perm_s -{ - const char *mode; - GHashTable *attribute_perms; +typedef struct xml_perm_s { + const char *mode; + GHashTable *attribute_perms; } xml_perm_t; -static gboolean req_by_privileged(xmlNode *request); -static xmlNode *diff_xml_object_orig(xmlNode *old, xmlNode *new, gboolean suppress, xmlNode *new_diff); +static gboolean req_by_privileged(xmlNode * request); +static xmlNode *diff_xml_object_orig(xmlNode * old, xmlNode * new, gboolean suppress, + xmlNode * new_diff); -static gboolean unpack_user_acl(xmlNode *xml_acls, const char *user, GListPtr *user_acl); +static gboolean unpack_user_acl(xmlNode * xml_acls, const char *user, GListPtr * user_acl); static gboolean user_match(const char *user, const char *uid); -static gboolean unpack_acl(xmlNode *xml_acls, xmlNode *xml_acl, GListPtr *acl); -static gboolean unpack_role_acl(xmlNode *xml_acls, const char *role, GListPtr *acl); -static gboolean acl_append(xmlNode *acl_child, GListPtr *acl); +static gboolean unpack_acl(xmlNode * xml_acls, xmlNode * xml_acl, GListPtr * acl); +static gboolean unpack_role_acl(xmlNode * xml_acls, const char *role, GListPtr * acl); +static gboolean acl_append(xmlNode * acl_child, GListPtr * acl); static void free_acl(GListPtr acl); -static gboolean parse_acl_xpath(xmlNode *xml, GListPtr acl, GListPtr *parsed_acl); - -static gboolean gen_xml_perms(xmlNode *xml, GListPtr acl, GHashTable **xml_perms); -static int search_xml_children(GListPtr *children, xmlNode *root, - const char *tag, const char *field, const char *value, - gboolean search_matches); -static int search_xpath_objects(GListPtr *objects, xmlNode *xml_obj, const char *xpath); -static gboolean update_xml_perms(xmlNode *xml, acl_obj_t *acl_obj, GHashTable *xml_perms); -static gboolean update_xml_children_perms(xmlNode *xml, const char *mode, GHashTable *xml_perms); +static gboolean parse_acl_xpath(xmlNode * xml, GListPtr acl, GListPtr * parsed_acl); + +static gboolean gen_xml_perms(xmlNode * xml, GListPtr acl, GHashTable ** xml_perms); +static int search_xml_children(GListPtr * children, xmlNode * root, + const char *tag, const char *field, const char *value, + gboolean search_matches); +static int search_xpath_objects(GListPtr * objects, xmlNode * xml_obj, const char *xpath); +static gboolean update_xml_perms(xmlNode * xml, acl_obj_t * acl_obj, GHashTable * xml_perms); +static gboolean update_xml_children_perms(xmlNode * xml, const char *mode, GHashTable * xml_perms); static void free_xml_perm(gpointer xml_perm); -static gboolean acl_filter_xml(xmlNode *xml, GHashTable *xml_perms); -static gboolean acl_check_diff_xml(xmlNode *xml, GHashTable *xml_perms); +static gboolean acl_filter_xml(xmlNode * xml, GHashTable * xml_perms); +static gboolean acl_check_diff_xml(xmlNode * xml, GHashTable * xml_perms); gboolean -acl_enabled(GHashTable *config_hash) +acl_enabled(GHashTable * config_hash) { - const char *value = NULL; - gboolean rc = FALSE; + const char *value = NULL; + gboolean rc = FALSE; - value = cib_pref(config_hash, "enable-acl"); - rc = crm_is_true(value); + value = cib_pref(config_hash, "enable-acl"); + rc = crm_is_true(value); - crm_debug("CIB ACL is %s", rc?"enabled":"disabled"); - return rc; + crm_debug("CIB ACL is %s", rc ? "enabled" : "disabled"); + return rc; } /* rc = TRUE if orig_cib has been filtered*/ /* That means *filtered_cib rather than orig_cib should be exploited afterwards*/ gboolean -acl_filter_cib(xmlNode *request, xmlNode *current_cib, xmlNode *orig_cib, xmlNode **filtered_cib) +acl_filter_cib(xmlNode * request, xmlNode * current_cib, xmlNode * orig_cib, + xmlNode ** filtered_cib) { - const char *user = NULL; - xmlNode *xml_acls = NULL; - xmlNode *tmp_cib = NULL; - GListPtr user_acl = NULL; - GHashTable *xml_perms = NULL; + const char *user = NULL; + xmlNode *xml_acls = NULL; + xmlNode *tmp_cib = NULL; + GListPtr user_acl = NULL; + GHashTable *xml_perms = NULL; - *filtered_cib = NULL; + *filtered_cib = NULL; - if (req_by_privileged(request)) { - return FALSE; - } + if (req_by_privileged(request)) { + return FALSE; + } + + if (orig_cib == NULL) { + return FALSE; + } - if (orig_cib == NULL) { - return FALSE; - } + if (current_cib == NULL) { + return TRUE; + } - if (current_cib == NULL) { - return TRUE; - } + xml_acls = get_object_root(XML_CIB_TAG_ACLS, current_cib); + if (xml_acls == NULL) { + crm_warn("Ordinary users cannot access the CIB without any defined ACLs: '%s'", user); + return TRUE; + } - xml_acls = get_object_root(XML_CIB_TAG_ACLS, current_cib); - if (xml_acls == NULL) { - crm_warn("Ordinary users cannot access the CIB without any defined ACLs: '%s'", user); - return TRUE; - } + user = crm_element_value(request, F_CIB_USER); + unpack_user_acl(xml_acls, user, &user_acl); - user = crm_element_value(request, F_CIB_USER); - unpack_user_acl(xml_acls, user, &user_acl); + tmp_cib = copy_xml(orig_cib); - tmp_cib = copy_xml(orig_cib); + gen_xml_perms(tmp_cib, user_acl, &xml_perms); - gen_xml_perms(tmp_cib, user_acl, &xml_perms); + if (acl_filter_xml(tmp_cib, xml_perms)) { + crm_warn("User '%s' doesn't have the permission for the whole CIB", user); + tmp_cib = NULL; + } - if (acl_filter_xml(tmp_cib, xml_perms)) { - crm_warn("User '%s' doesn't have the permission for the whole CIB", user); - tmp_cib = NULL; - } + g_hash_table_destroy(xml_perms); + free_acl(user_acl); - g_hash_table_destroy(xml_perms); - free_acl(user_acl); - - *filtered_cib = tmp_cib; - return TRUE; + *filtered_cib = tmp_cib; + return TRUE; } /* rc = TRUE if the request passes the ACL check */ /* rc = FALSE if the permission is denied */ gboolean -acl_check_diff(xmlNode *request, xmlNode *current_cib, xmlNode *result_cib, xmlNode *diff) +acl_check_diff(xmlNode * request, xmlNode * current_cib, xmlNode * result_cib, xmlNode * diff) { - const char *user = NULL; - xmlNode *xml_acls = NULL; - GListPtr user_acl = NULL; - xmlNode *orig_diff = NULL; - xmlNode *diff_child = NULL; - int rc = FALSE; - - if (req_by_privileged(request)) { - return TRUE; - } - - if (diff == NULL) { - return TRUE; - } - - if (current_cib == NULL) { - return FALSE; - } - - xml_acls = get_object_root(XML_CIB_TAG_ACLS, current_cib); - if (xml_acls == NULL) { - crm_warn("Ordinary users cannot access the CIB without any defined ACLs: '%s'", user); - return FALSE; - } - - user = crm_element_value(request, F_CIB_USER); - unpack_user_acl(xml_acls, user, &user_acl); - - orig_diff = diff_xml_object_orig(current_cib, result_cib, FALSE, diff); - - for (diff_child = __xml_first_child(orig_diff); diff_child; diff_child = __xml_next(diff_child)) { - const char *tag = crm_element_name(diff_child); - GListPtr parsed_acl = NULL; - xmlNode *diff_cib = NULL; - - crm_debug("Preparing ACL checking on '%s'", tag); - - if (crm_str_eq(tag, XML_TAG_DIFF_REMOVED, TRUE)) { - crm_debug("Parsing any xpaths under the ACL according to the current CIB"); - parse_acl_xpath(current_cib, user_acl, &parsed_acl); - } else if (crm_str_eq(tag, XML_TAG_DIFF_ADDED, TRUE)) { - crm_debug("Parsing any xpaths under the ACL according to the result CIB"); - parse_acl_xpath(result_cib, user_acl, &parsed_acl); - } else { - continue; - } - - for (diff_cib = __xml_first_child(diff_child); diff_cib; diff_cib = __xml_next(diff_cib)) { - GHashTable *xml_perms = NULL; - - gen_xml_perms(diff_cib, parsed_acl, &xml_perms); - rc = acl_check_diff_xml(diff_cib, xml_perms); - g_hash_table_destroy(xml_perms); - - if (rc == FALSE) { - crm_warn("User '%s' doesn't have enough permission to modify the CIB objects", user); - goto done; - } - } - free_acl(parsed_acl); - } - -done: - free_xml(orig_diff); - free_acl(user_acl); - return rc; + const char *user = NULL; + xmlNode *xml_acls = NULL; + GListPtr user_acl = NULL; + xmlNode *orig_diff = NULL; + xmlNode *diff_child = NULL; + int rc = FALSE; + + if (req_by_privileged(request)) { + return TRUE; + } + + if (diff == NULL) { + return TRUE; + } + + if (current_cib == NULL) { + return FALSE; + } + + xml_acls = get_object_root(XML_CIB_TAG_ACLS, current_cib); + if (xml_acls == NULL) { + crm_warn("Ordinary users cannot access the CIB without any defined ACLs: '%s'", user); + return FALSE; + } + + user = crm_element_value(request, F_CIB_USER); + unpack_user_acl(xml_acls, user, &user_acl); + + orig_diff = diff_xml_object_orig(current_cib, result_cib, FALSE, diff); + + for (diff_child = __xml_first_child(orig_diff); diff_child; diff_child = __xml_next(diff_child)) { + const char *tag = crm_element_name(diff_child); + GListPtr parsed_acl = NULL; + xmlNode *diff_cib = NULL; + + crm_debug("Preparing ACL checking on '%s'", tag); + + if (crm_str_eq(tag, XML_TAG_DIFF_REMOVED, TRUE)) { + crm_debug("Parsing any xpaths under the ACL according to the current CIB"); + parse_acl_xpath(current_cib, user_acl, &parsed_acl); + } else if (crm_str_eq(tag, XML_TAG_DIFF_ADDED, TRUE)) { + crm_debug("Parsing any xpaths under the ACL according to the result CIB"); + parse_acl_xpath(result_cib, user_acl, &parsed_acl); + } else { + continue; + } + + for (diff_cib = __xml_first_child(diff_child); diff_cib; diff_cib = __xml_next(diff_cib)) { + GHashTable *xml_perms = NULL; + + gen_xml_perms(diff_cib, parsed_acl, &xml_perms); + rc = acl_check_diff_xml(diff_cib, xml_perms); + g_hash_table_destroy(xml_perms); + + if (rc == FALSE) { + crm_warn("User '%s' doesn't have enough permission to modify the CIB objects", + user); + goto done; + } + } + free_acl(parsed_acl); + } + + done: + free_xml(orig_diff); + free_acl(user_acl); + return rc; } static gboolean -req_by_privileged(xmlNode *request) +req_by_privileged(xmlNode * request) { - const char *user = crm_element_value(request, F_CIB_USER); - - if (user == NULL || strcmp(user, "") == 0) { - crm_debug("Request without an explicit client user: op=%s, origin=%s, client=%s", - crm_element_value(request, F_CIB_OPERATION), - crm_element_value(request, F_ORIG)?crm_element_value(request, F_ORIG):"local", - crm_element_value(request, F_CIB_CLIENTNAME)); - return TRUE; - } - - if (is_privileged(user)) { - return TRUE; - } - return FALSE; + const char *user = crm_element_value(request, F_CIB_USER); + + if (user == NULL || strcmp(user, "") == 0) { + crm_debug("Request without an explicit client user: op=%s, origin=%s, client=%s", + crm_element_value(request, F_CIB_OPERATION), + crm_element_value(request, F_ORIG) ? crm_element_value(request, F_ORIG) : "local", + crm_element_value(request, F_CIB_CLIENTNAME)); + return TRUE; + } + + if (is_privileged(user)) { + return TRUE; + } + return FALSE; } /* Borrowed from lib/common/xml.c: diff_xml_object() */ /* But if a new format of diff ("new_diff") exists, we could reuse its "diff-removed" part */ /* So it would be more time-saving than generating the diff from start */ static xmlNode * -diff_xml_object_orig(xmlNode *old, xmlNode *new, gboolean suppress, xmlNode *new_diff) +diff_xml_object_orig(xmlNode * old, xmlNode * new, gboolean suppress, xmlNode * new_diff) { - xmlNode *tmp1 = NULL; - xmlNode *diff = create_xml_node(NULL, "diff"); + xmlNode *tmp1 = NULL; + xmlNode *diff = create_xml_node(NULL, "diff"); xmlNode *removed = NULL; - xmlNode *added = NULL; + xmlNode *added = NULL; crm_xml_add(diff, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); - + if (new_diff && (tmp1 = find_xml_node(new_diff, "diff-removed", FALSE))) { - removed = add_node_copy(diff, tmp1); + removed = add_node_copy(diff, tmp1); } else { - removed = create_xml_node(diff, "diff-removed"); + removed = create_xml_node(diff, "diff-removed"); - tmp1 = subtract_xml_object(removed, old, new, FALSE, "removed:top"); - if(suppress && tmp1 != NULL && can_prune_leaf(tmp1)) { - free_xml_from_parent(removed, tmp1); - } + tmp1 = subtract_xml_object(removed, old, new, FALSE, "removed:top"); + if (suppress && tmp1 != NULL && can_prune_leaf(tmp1)) { + free_xml_from_parent(removed, tmp1); + } } added = create_xml_node(diff, "diff-added"); - + tmp1 = subtract_xml_object(added, new, old, FALSE, "added:top"); - if(suppress && tmp1 != NULL && can_prune_leaf(tmp1)) { - free_xml_from_parent(added, tmp1); + if (suppress && tmp1 != NULL && can_prune_leaf(tmp1)) { + free_xml_from_parent(added, tmp1); } - - if(added->children == NULL && removed->children == NULL) { - free_xml(diff); - diff = NULL; + + if (added->children == NULL && removed->children == NULL) { + free_xml(diff); + diff = NULL; } - + return diff; } static gboolean -unpack_user_acl(xmlNode *xml_acls, const char *user, GListPtr *user_acl) +unpack_user_acl(xmlNode * xml_acls, const char *user, GListPtr * user_acl) { - xmlNode *xml_acl = NULL; - - if (xml_acls == NULL) { - return FALSE; - } - - for (xml_acl = __xml_first_child(xml_acls); xml_acl; xml_acl = __xml_next(xml_acl)) { - const char *tag = crm_element_name(xml_acl); - const char *id = crm_element_value(xml_acl, XML_ATTR_ID); - - if (crm_str_eq(tag, XML_ACL_TAG_USER, TRUE)) { - if (user_match(user, id)) { - crm_debug("Unpacking ACL of user: '%s'", id); - unpack_acl(xml_acls, xml_acl, user_acl); - return TRUE; - } - } - } - return FALSE; + xmlNode *xml_acl = NULL; + + if (xml_acls == NULL) { + return FALSE; + } + + for (xml_acl = __xml_first_child(xml_acls); xml_acl; xml_acl = __xml_next(xml_acl)) { + const char *tag = crm_element_name(xml_acl); + const char *id = crm_element_value(xml_acl, XML_ATTR_ID); + + if (crm_str_eq(tag, XML_ACL_TAG_USER, TRUE)) { + if (user_match(user, id)) { + crm_debug("Unpacking ACL of user: '%s'", id); + unpack_acl(xml_acls, xml_acl, user_acl); + return TRUE; + } + } + } + return FALSE; } static gboolean user_match(const char *user, const char *uid) { - CRM_CHECK(user != NULL && user[0] != '\0' - && uid != NULL && uid[0] != '\0', return FALSE); + CRM_CHECK(user != NULL && user[0] != '\0' && uid != NULL && uid[0] != '\0', return FALSE); - if (crm_str_eq(user, uid, TRUE)) { - return TRUE; - } + if (crm_str_eq(user, uid, TRUE)) { + return TRUE; + } - return FALSE; + return FALSE; } static gboolean -unpack_acl(xmlNode *xml_acls, xmlNode *xml_acl, GListPtr *acl) +unpack_acl(xmlNode * xml_acls, xmlNode * xml_acl, GListPtr * acl) { - xmlNode *acl_child = NULL; - - for (acl_child = __xml_first_child(xml_acl); acl_child; acl_child = __xml_next(acl_child)) { - const char *tag = crm_element_name(acl_child); - - if (crm_str_eq(XML_ACL_TAG_ROLE_REF, tag, TRUE)) { - const char *ref_role = crm_element_value(acl_child, XML_ATTR_ID); - if (ref_role) { - unpack_role_acl(xml_acls, ref_role, acl); - } - } else if (crm_str_eq(XML_ACL_TAG_READ, tag, TRUE) - || crm_str_eq(XML_ACL_TAG_WRITE, tag, TRUE) - || crm_str_eq(XML_ACL_TAG_DENY, tag, TRUE)) { - acl_append(acl_child, acl); - } - } - - return TRUE; + xmlNode *acl_child = NULL; + + for (acl_child = __xml_first_child(xml_acl); acl_child; acl_child = __xml_next(acl_child)) { + const char *tag = crm_element_name(acl_child); + + if (crm_str_eq(XML_ACL_TAG_ROLE_REF, tag, TRUE)) { + const char *ref_role = crm_element_value(acl_child, XML_ATTR_ID); + + if (ref_role) { + unpack_role_acl(xml_acls, ref_role, acl); + } + } else if (crm_str_eq(XML_ACL_TAG_READ, tag, TRUE) + || crm_str_eq(XML_ACL_TAG_WRITE, tag, TRUE) + || crm_str_eq(XML_ACL_TAG_DENY, tag, TRUE)) { + acl_append(acl_child, acl); + } + } + + return TRUE; } static gboolean -unpack_role_acl(xmlNode *xml_acls, const char *role, GListPtr *acl) +unpack_role_acl(xmlNode * xml_acls, const char *role, GListPtr * acl) { - xmlNode *xml_acl = NULL; - - for (xml_acl = __xml_first_child(xml_acls); xml_acl; xml_acl = __xml_next(xml_acl)) { - if(crm_str_eq(XML_ACL_TAG_ROLE, (const char *)xml_acl->name, TRUE)) { - const char *role_id = crm_element_value(xml_acl, XML_ATTR_ID); - - if (role_id && crm_str_eq(role, role_id, TRUE)) { - crm_debug("Unpacking ACL of the referenced role: '%s'", role); - unpack_acl(xml_acls, xml_acl, acl); - return TRUE; - } - } - } - return FALSE; + xmlNode *xml_acl = NULL; + + for (xml_acl = __xml_first_child(xml_acls); xml_acl; xml_acl = __xml_next(xml_acl)) { + if (crm_str_eq(XML_ACL_TAG_ROLE, (const char *)xml_acl->name, TRUE)) { + const char *role_id = crm_element_value(xml_acl, XML_ATTR_ID); + + if (role_id && crm_str_eq(role, role_id, TRUE)) { + crm_debug("Unpacking ACL of the referenced role: '%s'", role); + unpack_acl(xml_acls, xml_acl, acl); + return TRUE; + } + } + } + return FALSE; } static gboolean -acl_append(xmlNode *acl_child, GListPtr *acl) +acl_append(xmlNode * acl_child, GListPtr * acl) { - acl_obj_t *acl_obj = NULL; + acl_obj_t *acl_obj = NULL; - const char *tag = crm_element_value(acl_child, XML_ACL_ATTR_TAG); - const char *ref = crm_element_value(acl_child, XML_ACL_ATTR_REF); - const char *xpath = crm_element_value(acl_child, XML_ACL_ATTR_XPATH); + const char *tag = crm_element_value(acl_child, XML_ACL_ATTR_TAG); + const char *ref = crm_element_value(acl_child, XML_ACL_ATTR_REF); + const char *xpath = crm_element_value(acl_child, XML_ACL_ATTR_XPATH); - if (tag == NULL && ref == NULL && xpath == NULL) { - return FALSE; - } + if (tag == NULL && ref == NULL && xpath == NULL) { + return FALSE; + } - crm_malloc0(acl_obj, sizeof(acl_obj_t)); - if (acl_obj == NULL) { - return FALSE; - } + crm_malloc0(acl_obj, sizeof(acl_obj_t)); + if (acl_obj == NULL) { + return FALSE; + } - acl_obj->mode = crm_element_name(acl_child); - acl_obj->tag = tag; - acl_obj->ref = ref; - acl_obj->xpath = xpath; - acl_obj->attribute = crm_element_value(acl_child, XML_ACL_ATTR_ATTRIBUTE); + acl_obj->mode = crm_element_name(acl_child); + acl_obj->tag = tag; + acl_obj->ref = ref; + acl_obj->xpath = xpath; + acl_obj->attribute = crm_element_value(acl_child, XML_ACL_ATTR_ATTRIBUTE); - *acl = g_list_append(*acl, acl_obj); + *acl = g_list_append(*acl, acl_obj); - crm_debug_3("ACL object appended: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", - acl_obj->mode, acl_obj->tag, acl_obj->ref, acl_obj->xpath, acl_obj->attribute); + crm_debug_3("ACL object appended: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", + acl_obj->mode, acl_obj->tag, acl_obj->ref, acl_obj->xpath, acl_obj->attribute); - return TRUE; + return TRUE; } static void free_acl(GListPtr acl) { - GListPtr iterator = acl; - while(iterator != NULL) { - crm_free(iterator->data); - iterator = iterator->next; - } - if(acl != NULL) { - g_list_free(acl); - } + GListPtr iterator = acl; + + while (iterator != NULL) { + crm_free(iterator->data); + iterator = iterator->next; + } + if (acl != NULL) { + g_list_free(acl); + } } static gboolean -parse_acl_xpath(xmlNode *xml, GListPtr acl, GListPtr *parsed_acl) +parse_acl_xpath(xmlNode * xml, GListPtr acl, GListPtr * parsed_acl) { - GListPtr acl_iterator = acl; - acl_obj_t *new_acl_obj = NULL; - - *parsed_acl = NULL; + GListPtr acl_iterator = acl; + acl_obj_t *new_acl_obj = NULL; - while (acl_iterator != NULL) { - acl_obj_t *acl_obj = acl_iterator->data; + *parsed_acl = NULL; - if (acl_obj->tag || acl_obj->ref) { - crm_malloc0(new_acl_obj, sizeof(acl_obj_t)); - if (new_acl_obj == NULL) { - return FALSE; - } + while (acl_iterator != NULL) { + acl_obj_t *acl_obj = acl_iterator->data; - memcpy(new_acl_obj, acl_obj, sizeof(acl_obj_t)); + if (acl_obj->tag || acl_obj->ref) { + crm_malloc0(new_acl_obj, sizeof(acl_obj_t)); + if (new_acl_obj == NULL) { + return FALSE; + } - *parsed_acl = g_list_append(*parsed_acl, new_acl_obj); + memcpy(new_acl_obj, acl_obj, sizeof(acl_obj_t)); - crm_debug_3("Copied ACL object: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", - new_acl_obj->mode, new_acl_obj->tag, new_acl_obj->ref, - new_acl_obj->xpath, new_acl_obj->attribute); + *parsed_acl = g_list_append(*parsed_acl, new_acl_obj); - } else if (acl_obj->xpath) { - GListPtr children = NULL; - GListPtr children_iterator = NULL; + crm_debug_3("Copied ACL object: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", + new_acl_obj->mode, new_acl_obj->tag, new_acl_obj->ref, + new_acl_obj->xpath, new_acl_obj->attribute); - search_xpath_objects(&children, xml, acl_obj->xpath); + } else if (acl_obj->xpath) { + GListPtr children = NULL; + GListPtr children_iterator = NULL; - children_iterator = children; - while (children_iterator != NULL) { - crm_malloc0(new_acl_obj, sizeof(acl_obj_t)); - if (new_acl_obj == NULL) { - return FALSE; - } + search_xpath_objects(&children, xml, acl_obj->xpath); - new_acl_obj->mode = acl_obj->mode; - new_acl_obj->tag = crm_element_name((xmlNode*)children_iterator->data); - new_acl_obj->ref = crm_element_value(children_iterator->data, XML_ATTR_ID); - new_acl_obj->attribute = acl_obj->attribute; + children_iterator = children; + while (children_iterator != NULL) { + crm_malloc0(new_acl_obj, sizeof(acl_obj_t)); + if (new_acl_obj == NULL) { + return FALSE; + } - *parsed_acl = g_list_append(*parsed_acl, new_acl_obj); + new_acl_obj->mode = acl_obj->mode; + new_acl_obj->tag = crm_element_name((xmlNode *) children_iterator->data); + new_acl_obj->ref = crm_element_value(children_iterator->data, XML_ATTR_ID); + new_acl_obj->attribute = acl_obj->attribute; - crm_debug_3("Parsed the ACL object with xpath '%s' to: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", - acl_obj->xpath, new_acl_obj->mode, new_acl_obj->tag, - new_acl_obj->ref, new_acl_obj->xpath, new_acl_obj->attribute); + *parsed_acl = g_list_append(*parsed_acl, new_acl_obj); - children_iterator = children_iterator->next; - } - g_list_free(children); - } - acl_iterator = acl_iterator->next; - } + crm_debug_3 + ("Parsed the ACL object with xpath '%s' to: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", + acl_obj->xpath, new_acl_obj->mode, new_acl_obj->tag, new_acl_obj->ref, + new_acl_obj->xpath, new_acl_obj->attribute); + + children_iterator = children_iterator->next; + } + g_list_free(children); + } + acl_iterator = acl_iterator->next; + } - return TRUE; + return TRUE; } static gboolean -gen_xml_perms(xmlNode *xml, GListPtr acl, GHashTable **xml_perms) +gen_xml_perms(xmlNode * xml, GListPtr acl, GHashTable ** xml_perms) { - GListPtr acl_iterator = acl; - - if (*xml_perms == NULL) { - *xml_perms = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_xml_perm); - } - - while (acl_iterator != NULL) { - acl_obj_t *acl_obj = acl_iterator->data; - GListPtr children = NULL; - GListPtr children_iterator = NULL; - - crm_debug("Generating permissions with ACL: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", - acl_obj->mode, acl_obj->tag, acl_obj->ref, acl_obj->xpath, acl_obj->attribute); - if (acl_obj->tag || acl_obj->ref) { - search_xml_children(&children, xml, acl_obj->tag, XML_ATTR_ID, acl_obj->ref, TRUE); - - } else if (acl_obj->xpath) { - /* Never be here for a modification operation */ - /* Already parse_acl_xpath() previously */ - search_xpath_objects(&children, xml, acl_obj->xpath); - } - - children_iterator = children; - while (children_iterator != NULL) { - update_xml_perms(children_iterator->data, acl_obj, *xml_perms); - - children_iterator = children_iterator->next; - } - g_list_free(children); - - acl_iterator = acl_iterator->next; - } - - return TRUE; + GListPtr acl_iterator = acl; + + if (*xml_perms == NULL) { + *xml_perms = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_xml_perm); + } + + while (acl_iterator != NULL) { + acl_obj_t *acl_obj = acl_iterator->data; + GListPtr children = NULL; + GListPtr children_iterator = NULL; + + crm_debug + ("Generating permissions with ACL: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s", + acl_obj->mode, acl_obj->tag, acl_obj->ref, acl_obj->xpath, acl_obj->attribute); + if (acl_obj->tag || acl_obj->ref) { + search_xml_children(&children, xml, acl_obj->tag, XML_ATTR_ID, acl_obj->ref, TRUE); + + } else if (acl_obj->xpath) { + /* Never be here for a modification operation */ + /* Already parse_acl_xpath() previously */ + search_xpath_objects(&children, xml, acl_obj->xpath); + } + + children_iterator = children; + while (children_iterator != NULL) { + update_xml_perms(children_iterator->data, acl_obj, *xml_perms); + + children_iterator = children_iterator->next; + } + g_list_free(children); + + acl_iterator = acl_iterator->next; + } + + return TRUE; } /* Borrowed from lib/common/xml.c: find_xml_children() */ /* But adding the original xmlNode pointers into a GList */ static int -search_xml_children(GListPtr *children, xmlNode *root, - const char *tag, const char *field, const char *value, - gboolean search_matches) +search_xml_children(GListPtr * children, xmlNode * root, + const char *tag, const char *field, const char *value, gboolean search_matches) { - int match_found = 0; - - CRM_CHECK(root != NULL, return FALSE); - CRM_CHECK(children != NULL, return FALSE); - - if(tag != NULL && safe_str_neq(tag, crm_element_name(root))) { - - } else if(value != NULL - && safe_str_neq(value, crm_element_value(root, field))) { - - } else { - *children = g_list_append(*children, root); - match_found = 1; - } - - if(search_matches || match_found == 0) { - xmlNode *child = NULL; - - for (child = __xml_first_child(root); child; child = __xml_next(child)) { - match_found += search_xml_children( - children, child, tag, field, value, - search_matches); - } - } - - return match_found; + int match_found = 0; + + CRM_CHECK(root != NULL, return FALSE); + CRM_CHECK(children != NULL, return FALSE); + + if (tag != NULL && safe_str_neq(tag, crm_element_name(root))) { + + } else if (value != NULL && safe_str_neq(value, crm_element_value(root, field))) { + + } else { + *children = g_list_append(*children, root); + match_found = 1; + } + + if (search_matches || match_found == 0) { + xmlNode *child = NULL; + + for (child = __xml_first_child(root); child; child = __xml_next(child)) { + match_found += search_xml_children(children, child, tag, field, value, search_matches); + } + } + + return match_found; } static int -search_xpath_objects(GListPtr *objects, xmlNode *xml_obj, const char *xpath) +search_xpath_objects(GListPtr * objects, xmlNode * xml_obj, const char *xpath) { - int match_found = 0; - xmlXPathObjectPtr xpathObj = NULL; + int match_found = 0; + xmlXPathObjectPtr xpathObj = NULL; + + if (xpath == NULL) { + return 0; + } - if(xpath == NULL) { - return 0; - } + xpathObj = xpath_search(xml_obj, xpath); - xpathObj = xpath_search(xml_obj, xpath); + if (xpathObj == NULL || xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr < 1) { + crm_debug("No match for %s in %s", xpath, xmlGetNodePath(xml_obj)); - if(xpathObj == NULL || xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr < 1) { - crm_debug("No match for %s in %s", xpath, xmlGetNodePath(xml_obj)); + } else if (xpathObj->nodesetval->nodeNr > 0) { + int lpc = 0, max = xpathObj->nodesetval->nodeNr; - } else if(xpathObj->nodesetval->nodeNr > 0) { - int lpc = 0, max = xpathObj->nodesetval->nodeNr; + for (lpc = 0; lpc < max; lpc++) { + xmlNode *match = getXpathResult(xpathObj, lpc); - for(lpc = 0; lpc < max; lpc++) { - xmlNode *match = getXpathResult(xpathObj, lpc); - if (match == NULL) { - continue; - } + if (match == NULL) { + continue; + } - *objects = g_list_append(*objects, match); - match_found++; - } - } + *objects = g_list_append(*objects, match); + match_found++; + } + } - if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - return match_found; + if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + return match_found; } static gboolean -update_xml_perms(xmlNode *xml, acl_obj_t *acl_obj, GHashTable *xml_perms) +update_xml_perms(xmlNode * xml, acl_obj_t * acl_obj, GHashTable * xml_perms) { - xml_perm_t *perm = NULL; - - if (g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm)) { - if (perm->mode != NULL) { - return FALSE; - } - } else { - crm_malloc0(perm, sizeof(xml_perm_t)); - if (perm == NULL) { - return FALSE; - } - g_hash_table_insert(xml_perms, xml, perm); - } - - if (acl_obj->attribute == NULL) { - xmlNode *child = NULL; - - perm->mode = acl_obj->mode; - crm_debug_3("Permission for element: element_mode=%s, tag=%s, id=%s", - perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); - - for (child = __xml_first_child(xml); child; child = __xml_next(child)) { - update_xml_children_perms(child, perm->mode, xml_perms); - } - - } else { - if (perm->attribute_perms == NULL - || (g_hash_table_lookup_extended(perm->attribute_perms, - acl_obj->attribute, NULL, NULL) == FALSE)) { - - if (perm->attribute_perms == NULL) { - perm->attribute_perms = g_hash_table_new_full( - crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); - } - - g_hash_table_insert(perm->attribute_perms, - crm_strdup(acl_obj->attribute), crm_strdup(acl_obj->mode)); - crm_debug_3("Permission for attribute: attribute_mode=%s, tag=%s, id=%s attribute=%s", - acl_obj->mode, crm_element_name(xml), - crm_element_value(xml, XML_ATTR_ID), acl_obj->attribute); - } - } - - return TRUE; + xml_perm_t *perm = NULL; + + if (g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer) & perm)) { + if (perm->mode != NULL) { + return FALSE; + } + } else { + crm_malloc0(perm, sizeof(xml_perm_t)); + if (perm == NULL) { + return FALSE; + } + g_hash_table_insert(xml_perms, xml, perm); + } + + if (acl_obj->attribute == NULL) { + xmlNode *child = NULL; + + perm->mode = acl_obj->mode; + crm_debug_3("Permission for element: element_mode=%s, tag=%s, id=%s", + perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); + + for (child = __xml_first_child(xml); child; child = __xml_next(child)) { + update_xml_children_perms(child, perm->mode, xml_perms); + } + + } else { + if (perm->attribute_perms == NULL + || (g_hash_table_lookup_extended(perm->attribute_perms, + acl_obj->attribute, NULL, NULL) == FALSE)) { + + if (perm->attribute_perms == NULL) { + perm->attribute_perms = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, + g_hash_destroy_str); + } + + g_hash_table_insert(perm->attribute_perms, + crm_strdup(acl_obj->attribute), crm_strdup(acl_obj->mode)); + crm_debug_3("Permission for attribute: attribute_mode=%s, tag=%s, id=%s attribute=%s", + acl_obj->mode, crm_element_name(xml), + crm_element_value(xml, XML_ATTR_ID), acl_obj->attribute); + } + } + + return TRUE; } static gboolean -update_xml_children_perms(xmlNode *xml, const char *mode, GHashTable *xml_perms) +update_xml_children_perms(xmlNode * xml, const char *mode, GHashTable * xml_perms) { - xml_perm_t *perm = NULL; - xmlNode *child = NULL; - - if (g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm)) { - if (perm->mode != NULL) { - return FALSE; - } - } else { - crm_malloc0(perm, sizeof(xml_perm_t)); - if (perm == NULL) { - return FALSE; - } - g_hash_table_insert(xml_perms, xml, perm); - } - - perm->mode = mode; - crm_debug_4("Permission for child element: element_mode=%s, tag=%s, id=%s", - mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); - - for (child = __xml_first_child(xml); child; child = __xml_next(child)) { - update_xml_children_perms(child, mode, xml_perms); - } - - return TRUE; + xml_perm_t *perm = NULL; + xmlNode *child = NULL; + + if (g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer) & perm)) { + if (perm->mode != NULL) { + return FALSE; + } + } else { + crm_malloc0(perm, sizeof(xml_perm_t)); + if (perm == NULL) { + return FALSE; + } + g_hash_table_insert(xml_perms, xml, perm); + } + + perm->mode = mode; + crm_debug_4("Permission for child element: element_mode=%s, tag=%s, id=%s", + mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); + + for (child = __xml_first_child(xml); child; child = __xml_next(child)) { + update_xml_children_perms(child, mode, xml_perms); + } + + return TRUE; } static void free_xml_perm(gpointer xml_perm) { - xml_perm_t *perm = xml_perm; + xml_perm_t *perm = xml_perm; - if (perm == NULL) { - return; - } + if (perm == NULL) { + return; + } - if (perm->attribute_perms != NULL) { - g_hash_table_destroy(perm->attribute_perms); - } + if (perm->attribute_perms != NULL) { + g_hash_table_destroy(perm->attribute_perms); + } - crm_free(perm); + crm_free(perm); } #define can_read(mode) (crm_str_eq(mode, XML_ACL_TAG_READ, TRUE) \ || crm_str_eq(mode, XML_ACL_TAG_WRITE, TRUE)) #define can_write(mode) crm_str_eq(mode, XML_ACL_TAG_WRITE, TRUE) /* rc = TRUE if the xml is filtered out*/ static gboolean -acl_filter_xml(xmlNode *xml, GHashTable *xml_perms) +acl_filter_xml(xmlNode * xml, GHashTable * xml_perms) { - int children_counter = 0; - xml_perm_t *perm = NULL; - int allow_counter = 0; - xmlNode *child = NULL; - - for (child = __xml_first_child(xml); child; child = __xml_next(child)) { - if (acl_filter_xml(child, xml_perms) == FALSE) { - children_counter++; - } - } - - g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm); - - if (perm == NULL) { - crm_debug_4("No ACL defined to read the element: tag=%s, id=%s", - crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); - goto end_filter; - } - - if (perm->attribute_perms == NULL) { - if (can_read(perm->mode)) { - return FALSE; - } else { - crm_debug_4("No enough permission to read the element: element_mode=%s, tag=%s, id=%s", - perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); - goto end_filter; - } - } - - if(xml) { - xmlAttrPtr xIter = param_set->properties; - while(xIter) { - const char *prop_name = (const char *)xIter->name; - const char *prop_value = crm_element_value(xml, prop_name); - gpointer mode = NULL; - - xIter = xIter->next; - if (g_hash_table_lookup_extended(perm->attribute_perms, prop_name, NULL, &mode)) { - if (can_read(mode)) { - allow_counter++; - } else { - xml_remove_prop(xml, prop_name); - crm_debug_4("Filtered out the attribute: attribute_mode=%s, tag=%s, id=%s, attribute=%s", - (char *)mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); - } - } else { - if (can_read(perm->mode)) { - allow_counter++; - } else if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE) == FALSE) { - xml_remove_prop(xml, prop_name); - crm_debug_4("Filtered out the attribute: element_mode=%s, tag=%s, id=%s, attribute=%s", - perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); - } - } + int children_counter = 0; + xml_perm_t *perm = NULL; + int allow_counter = 0; + xmlNode *child = NULL; + + for (child = __xml_first_child(xml); child; child = __xml_next(child)) { + if (acl_filter_xml(child, xml_perms) == FALSE) { + children_counter++; + } + } + + g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer) & perm); + + if (perm == NULL) { + crm_debug_4("No ACL defined to read the element: tag=%s, id=%s", + crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); + goto end_filter; + } + + if (perm->attribute_perms == NULL) { + if (can_read(perm->mode)) { + return FALSE; + } else { + crm_debug_4("No enough permission to read the element: element_mode=%s, tag=%s, id=%s", + perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); + goto end_filter; + } + } + + if (xml) { + xmlAttrPtr xIter = param_set->properties; + + while (xIter) { + const char *prop_name = (const char *)xIter->name; + const char *prop_value = crm_element_value(xml, prop_name); + gpointer mode = NULL; + + xIter = xIter->next; + if (g_hash_table_lookup_extended(perm->attribute_perms, prop_name, NULL, &mode)) { + if (can_read(mode)) { + allow_counter++; + } else { + xml_remove_prop(xml, prop_name); + crm_debug_4 + ("Filtered out the attribute: attribute_mode=%s, tag=%s, id=%s, attribute=%s", + (char *)mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), + prop_name); + } + } else { + if (can_read(perm->mode)) { + allow_counter++; + } else if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE) == FALSE) { + xml_remove_prop(xml, prop_name); + crm_debug_4 + ("Filtered out the attribute: element_mode=%s, tag=%s, id=%s, attribute=%s", + perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), + prop_name); + } } } + } + + if (allow_counter) { + return FALSE; + } + + if (can_read(perm->mode)) { + return FALSE; + } + + end_filter: + if (children_counter) { + crm_debug_4 + ("Don't filter out the element (tag=%s, id=%s) because user can read its children", + crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); + return FALSE; + } - if (allow_counter) { - return FALSE; - } - - if (can_read(perm->mode)) { - return FALSE; - } - -end_filter: - if (children_counter) { - crm_debug_4("Don't filter out the element (tag=%s, id=%s) because user can read its children", - crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); - return FALSE; - } - - free_xml_from_parent(NULL, xml); - crm_debug_4("Filtered out the element: tag=%s, id=%s", - crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); - return TRUE; + free_xml_from_parent(NULL, xml); + crm_debug_4("Filtered out the element: tag=%s, id=%s", + crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID)); + return TRUE; } static gboolean -acl_check_diff_xml(xmlNode *xml, GHashTable *xml_perms) +acl_check_diff_xml(xmlNode * xml, GHashTable * xml_perms) { - xml_perm_t *perm = NULL; - xmlNode *child = NULL; - - for (child = __xml_first_child(xml); child; child = __xml_next(child)) { - if (acl_check_diff_xml(child, xml_perms) == FALSE) { - return FALSE; - } - } - - g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm); - - if(xml) { - xmlAttrPtr xIter = NULL; - for(xIter = xml->properties; xIter; xIter = xIter->next) { - const char *prop_name = (const char *)xIter->name; - const char *prop_value = crm_element_value(xml, prop_name); - gpointer mode = NULL; - - if (crm_str_eq(crm_element_name(xml), XML_TAG_CIB, TRUE)) { - if (crm_str_eq(prop_name, XML_ATTR_GENERATION, TRUE) - || crm_str_eq(prop_name, XML_ATTR_NUMUPDATES, TRUE) - || crm_str_eq(prop_name, XML_ATTR_GENERATION_ADMIN, TRUE)) { - continue; - } - } - - if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE)) { - continue; - } - - if (crm_str_eq(prop_name, XML_DIFF_MARKER, TRUE) && xml_has_children(xml)) { - continue; - } - - if (perm == NULL) { - crm_warn("No ACL defined to modify the element: tag=%s, id=%s, attribute=%s", - crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); - return FALSE; - } - - if (perm->attribute_perms == NULL) { - if (can_write(perm->mode)) { - return TRUE; - } else { - crm_warn("No enough permission to modify the element: element_mode=%s, tag=%s, id=%s, attribute=%s", - perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); - return FALSE; - } - } - - if (g_hash_table_lookup_extended(perm->attribute_perms, prop_name, NULL, &mode)) { - if (can_write(mode) == FALSE) { - crm_warn("No enough permission to modify the attribute: attribute_mode=%s, tag=%s, id=%s, attribute=%s", - (char *)mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); - return FALSE; - } - } else if (can_write(perm->mode) == FALSE) { - crm_warn("No enough permission to modify the element and the attribute: element_mode=%s, tag=%s, id=%s, attribute=%s", - perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); - return FALSE; - } + xml_perm_t *perm = NULL; + xmlNode *child = NULL; + + for (child = __xml_first_child(xml); child; child = __xml_next(child)) { + if (acl_check_diff_xml(child, xml_perms) == FALSE) { + return FALSE; + } + } + + g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer) & perm); + + if (xml) { + xmlAttrPtr xIter = NULL; + + for (xIter = xml->properties; xIter; xIter = xIter->next) { + const char *prop_name = (const char *)xIter->name; + const char *prop_value = crm_element_value(xml, prop_name); + gpointer mode = NULL; + + if (crm_str_eq(crm_element_name(xml), XML_TAG_CIB, TRUE)) { + if (crm_str_eq(prop_name, XML_ATTR_GENERATION, TRUE) + || crm_str_eq(prop_name, XML_ATTR_NUMUPDATES, TRUE) + || crm_str_eq(prop_name, XML_ATTR_GENERATION_ADMIN, TRUE)) { + continue; + } + } + + if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE)) { + continue; + } + + if (crm_str_eq(prop_name, XML_DIFF_MARKER, TRUE) && xml_has_children(xml)) { + continue; + } + + if (perm == NULL) { + crm_warn("No ACL defined to modify the element: tag=%s, id=%s, attribute=%s", + crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name); + return FALSE; + } + + if (perm->attribute_perms == NULL) { + if (can_write(perm->mode)) { + return TRUE; + } else { + crm_warn + ("No enough permission to modify the element: element_mode=%s, tag=%s, id=%s, attribute=%s", + perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), + prop_name); + return FALSE; + } + } + + if (g_hash_table_lookup_extended(perm->attribute_perms, prop_name, NULL, &mode)) { + if (can_write(mode) == FALSE) { + crm_warn + ("No enough permission to modify the attribute: attribute_mode=%s, tag=%s, id=%s, attribute=%s", + (char *)mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), + prop_name); + return FALSE; + } + } else if (can_write(perm->mode) == FALSE) { + crm_warn + ("No enough permission to modify the element and the attribute: element_mode=%s, tag=%s, id=%s, attribute=%s", + perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), + prop_name); + return FALSE; } } + } - return TRUE; + return TRUE; } - diff --git a/lib/cib/cib_attrs.c b/lib/cib/cib_attrs.c index 91894edb44..0dc6809bde 100644 --- a/lib/cib/cib_attrs.c +++ b/lib/cib/cib_attrs.c @@ -1,538 +1,546 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 - #define attr_msg(level, fmt, args...) do { \ if(to_console) { \ printf(fmt"\n", ##args); \ } else { \ do_crm_log(level, fmt , ##args); \ } \ } while(0) extern enum cib_errors -find_nvpair_attr_delegate( - cib_t *the_cib, const char *attr, const char *section, const char *node_uuid, const char *attr_set_type, - const char *set_name, const char *attr_id, const char *attr_name, gboolean to_console, char **value, - const char *user_name) +find_nvpair_attr_delegate(cib_t * the_cib, const char *attr, const char *section, + const char *node_uuid, const char *attr_set_type, const char *set_name, + const char *attr_id, const char *attr_name, gboolean to_console, + char **value, const char *user_name) { int offset = 0; static int xpath_max = 1024; enum cib_errors rc = cib_ok; char *xpath_string = NULL; xmlNode *xml_search = NULL; const char *set_type = NULL; const char *node_type = NULL; if (attr_set_type) { - set_type = attr_set_type; + set_type = attr_set_type; } else { - set_type = XML_TAG_ATTR_SETS; + set_type = XML_TAG_ATTR_SETS; } CRM_ASSERT(value != NULL); *value = NULL; - - if(safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { - node_uuid = NULL; - set_type = XML_CIB_TAG_PROPSET; - - } else if(safe_str_eq(section, XML_CIB_TAG_OPCONFIG) - || safe_str_eq(section, XML_CIB_TAG_RSCCONFIG)) { - node_uuid = NULL; - set_type = XML_TAG_META_SETS; - - } else if(safe_str_eq(section, XML_CIB_TAG_TICKETS)) { - node_uuid = NULL; - section = XML_CIB_TAG_STATUS; - node_type = XML_CIB_TAG_TICKETS; - - } else if(node_uuid == NULL) { - return cib_missing_data; + + if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { + node_uuid = NULL; + set_type = XML_CIB_TAG_PROPSET; + + } else if (safe_str_eq(section, XML_CIB_TAG_OPCONFIG) + || safe_str_eq(section, XML_CIB_TAG_RSCCONFIG)) { + node_uuid = NULL; + set_type = XML_TAG_META_SETS; + + } else if (safe_str_eq(section, XML_CIB_TAG_TICKETS)) { + node_uuid = NULL; + section = XML_CIB_TAG_STATUS; + node_type = XML_CIB_TAG_TICKETS; + + } else if (node_uuid == NULL) { + return cib_missing_data; } - + crm_malloc0(xpath_string, xpath_max); offset += snprintf(xpath_string + offset, xpath_max - offset, "%s", get_object_path(section)); - if(safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) { - offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s", node_type); + if (safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) { + offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s", node_type); + + } else if (node_uuid) { + const char *node_type = XML_CIB_TAG_NODE; - } else if(node_uuid) { - const char *node_type = XML_CIB_TAG_NODE; - if(safe_str_eq(section, XML_CIB_TAG_STATUS)) { - node_type = XML_CIB_TAG_STATE; - set_type = XML_TAG_TRANSIENT_NODEATTRS; - } - offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", node_type, node_uuid); + if (safe_str_eq(section, XML_CIB_TAG_STATUS)) { + node_type = XML_CIB_TAG_STATE; + set_type = XML_TAG_TRANSIENT_NODEATTRS; + } + offset += + snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", node_type, + node_uuid); } - if(set_name) { - offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", set_type, set_name); + if (set_name) { + offset += + snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", set_type, + set_name); } else { - offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s", set_type); - } - + offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s", set_type); + } + offset += snprintf(xpath_string + offset, xpath_max - offset, "//nvpair["); - if(attr_id) { - offset += snprintf(xpath_string + offset, xpath_max - offset, "@id='%s'", attr_id); + if (attr_id) { + offset += snprintf(xpath_string + offset, xpath_max - offset, "@id='%s'", attr_id); + } + + if (attr_name) { + if (attr_id) { + offset += snprintf(xpath_string + offset, xpath_max - offset, " and "); + } + offset += snprintf(xpath_string + offset, xpath_max - offset, "@name='%s'", attr_name); } - - if(attr_name) { - if(attr_id) { - offset += snprintf(xpath_string + offset, xpath_max - offset, " and "); - } - offset += snprintf(xpath_string + offset, xpath_max - offset, "@name='%s'", attr_name); - } offset += snprintf(xpath_string + offset, xpath_max - offset, "]"); - - rc = the_cib->cmds->delegated_variant_op( - the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL, &xml_search, cib_sync_call|cib_scope_local|cib_xpath, user_name); - - - if(rc != cib_ok) { - do_crm_log(LOG_DEBUG_2, "Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s", - attr_name, section, crm_str(node_uuid), crm_str(set_name), xpath_string, - cib_error2string(rc)); - goto done; + + rc = the_cib->cmds->delegated_variant_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL, + &xml_search, + cib_sync_call | cib_scope_local | cib_xpath, + user_name); + + if (rc != cib_ok) { + do_crm_log(LOG_DEBUG_2, + "Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s", + attr_name, section, crm_str(node_uuid), crm_str(set_name), xpath_string, + cib_error2string(rc)); + goto done; } crm_log_xml_debug(xml_search, "Match"); - if(xml_has_children(xml_search)) { - xmlNode *child = NULL; - rc = cib_missing_data; - attr_msg(LOG_WARNING, "Multiple attributes match name=%s", attr_name); - - for(child = __xml_first_child(xml_search); child != NULL; child = __xml_next(child)) { - attr_msg(LOG_INFO, " Value: %s \t(id=%s)", - crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child)); - } + if (xml_has_children(xml_search)) { + xmlNode *child = NULL; + + rc = cib_missing_data; + attr_msg(LOG_WARNING, "Multiple attributes match name=%s", attr_name); + + for (child = __xml_first_child(xml_search); child != NULL; child = __xml_next(child)) { + attr_msg(LOG_INFO, " Value: %s \t(id=%s)", + crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child)); + } } else { - const char *tmp = crm_element_value(xml_search, attr); - if(tmp) { - *value = crm_strdup(tmp); - } + const char *tmp = crm_element_value(xml_search, attr); + + if (tmp) { + *value = crm_strdup(tmp); + } } done: crm_free(xpath_string); free_xml(xml_search); return rc; } - -enum cib_errors -update_attr_delegate(cib_t *the_cib, int call_options, - const char *section, const char *node_uuid, const char *set_type, const char *set_name, - const char *attr_id, const char *attr_name, const char *attr_value, gboolean to_console, - const char *user_name) +enum cib_errors +update_attr_delegate(cib_t * the_cib, int call_options, + const char *section, const char *node_uuid, const char *set_type, + const char *set_name, const char *attr_id, const char *attr_name, + const char *attr_value, gboolean to_console, const char *user_name) { const char *tag = NULL; enum cib_errors rc = cib_ok; xmlNode *xml_top = NULL; xmlNode *xml_obj = NULL; char *local_attr_id = NULL; char *local_set_name = NULL; gboolean use_attributes_tag = FALSE; - + CRM_CHECK(section != NULL, return cib_missing); CRM_CHECK(attr_value != NULL, return cib_missing); CRM_CHECK(attr_name != NULL || attr_id != NULL, return cib_missing); - - rc = find_nvpair_attr_delegate(the_cib, XML_ATTR_ID, section, node_uuid, set_type, set_name, attr_id, attr_name, FALSE, &local_attr_id, user_name); - if(rc == cib_ok) { - attr_id = local_attr_id; - goto do_modify; - } else if(rc != cib_NOTEXISTS) { - return rc; + rc = find_nvpair_attr_delegate(the_cib, XML_ATTR_ID, section, node_uuid, set_type, set_name, + attr_id, attr_name, FALSE, &local_attr_id, user_name); + if (rc == cib_ok) { + attr_id = local_attr_id; + goto do_modify; - /* } else if(attr_id == NULL) { */ - /* return cib_missing; */ + } else if (rc != cib_NOTEXISTS) { + return rc; + + /* } else if(attr_id == NULL) { */ + /* return cib_missing; */ } else { - const char *value = NULL; - const char *node_type = NULL; - xmlNode *cib_top = NULL; - rc = the_cib->cmds->delegated_variant_op( - the_cib, CIB_OP_QUERY, NULL, "/cib", NULL, &cib_top, cib_sync_call|cib_scope_local|cib_xpath|cib_no_children, user_name); - - value = crm_element_value(cib_top, "ignore_dtd"); - if(value != NULL) { - use_attributes_tag = TRUE; - - } else { - value = crm_element_value(cib_top, XML_ATTR_VALIDATION); - if(value && strstr(value, "-0.6")) { - use_attributes_tag = TRUE; - } - } - free_xml(cib_top); - - if(safe_str_eq(section, XML_CIB_TAG_TICKETS)) { - node_uuid = NULL; - section = XML_CIB_TAG_STATUS; - node_type = XML_CIB_TAG_TICKETS; - - xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_STATUS); - if(xml_top == NULL) { - xml_top = xml_obj; - } - - xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_TICKETS); - - } else if(safe_str_eq(section, XML_CIB_TAG_NODES)) { - tag = XML_CIB_TAG_NODE; - if(node_uuid == NULL) { - return cib_missing; - } - - } else if(safe_str_eq(section, XML_CIB_TAG_STATUS)) { - tag = XML_TAG_TRANSIENT_NODEATTRS; - if(node_uuid == NULL) { - return cib_missing; - } - - xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_STATE); - crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid); - if(xml_top == NULL) { - xml_top = xml_obj; - } - - } else { - tag = section; - node_uuid = NULL; - } - - if(set_name == NULL) { - if(safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { - local_set_name = crm_strdup(CIB_OPTIONS_FIRST); - - } else if(safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) { - local_set_name = crm_concat(section, XML_CIB_TAG_TICKETS, '-'); - - } else if(node_uuid) { - local_set_name = crm_concat(section, node_uuid, '-'); - - if(set_type) { - char *tmp_set_name = local_set_name; - local_set_name = crm_concat(tmp_set_name, set_type, '-'); - crm_free(tmp_set_name); - } - } else { - local_set_name = crm_concat(section, "options", '-'); - } - set_name = local_set_name; - } - - if(attr_id == NULL) { - int lpc = 0; - - local_attr_id = crm_concat(set_name, attr_name, '-'); - attr_id = local_attr_id; - - /* Minimal attempt at sanitizing automatic IDs */ - for(lpc = 0; local_attr_id[lpc] != 0; lpc++) { - switch(local_attr_id[lpc]) { - case ':': - local_attr_id[lpc] = '.'; - } - } - - } else if(attr_name == NULL) { - attr_name = attr_id; - } - - crm_debug_2("Creating %s/%s", section, tag); - if(tag != NULL) { - xml_obj = create_xml_node(xml_obj, tag); - crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid); - if(xml_top == NULL) { - xml_top = xml_obj; - } - } - - if(node_uuid == NULL && safe_str_neq(node_type, XML_CIB_TAG_TICKETS)) { - if(safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { - xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET); - } else { - xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS); - } - - } else if(set_type) { - xml_obj = create_xml_node(xml_obj, set_type); - - } else { - xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS); - } - crm_xml_add(xml_obj, XML_ATTR_ID, set_name); - - if(xml_top == NULL) { - xml_top = xml_obj; - } - - if(use_attributes_tag) { - xml_obj = create_xml_node(xml_obj, XML_TAG_ATTRS); - } + const char *value = NULL; + const char *node_type = NULL; + xmlNode *cib_top = NULL; + + rc = the_cib->cmds->delegated_variant_op(the_cib, CIB_OP_QUERY, NULL, "/cib", NULL, + &cib_top, + cib_sync_call | cib_scope_local | cib_xpath | + cib_no_children, user_name); + + value = crm_element_value(cib_top, "ignore_dtd"); + if (value != NULL) { + use_attributes_tag = TRUE; + + } else { + value = crm_element_value(cib_top, XML_ATTR_VALIDATION); + if (value && strstr(value, "-0.6")) { + use_attributes_tag = TRUE; + } + } + free_xml(cib_top); + + if (safe_str_eq(section, XML_CIB_TAG_TICKETS)) { + node_uuid = NULL; + section = XML_CIB_TAG_STATUS; + node_type = XML_CIB_TAG_TICKETS; + + xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_STATUS); + if (xml_top == NULL) { + xml_top = xml_obj; + } + + xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_TICKETS); + + } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) { + tag = XML_CIB_TAG_NODE; + if (node_uuid == NULL) { + return cib_missing; + } + + } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) { + tag = XML_TAG_TRANSIENT_NODEATTRS; + if (node_uuid == NULL) { + return cib_missing; + } + + xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_STATE); + crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid); + if (xml_top == NULL) { + xml_top = xml_obj; + } + + } else { + tag = section; + node_uuid = NULL; + } + + if (set_name == NULL) { + if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { + local_set_name = crm_strdup(CIB_OPTIONS_FIRST); + + } else if (safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) { + local_set_name = crm_concat(section, XML_CIB_TAG_TICKETS, '-'); + + } else if (node_uuid) { + local_set_name = crm_concat(section, node_uuid, '-'); + + if (set_type) { + char *tmp_set_name = local_set_name; + + local_set_name = crm_concat(tmp_set_name, set_type, '-'); + crm_free(tmp_set_name); + } + } else { + local_set_name = crm_concat(section, "options", '-'); + } + set_name = local_set_name; + } + + if (attr_id == NULL) { + int lpc = 0; + + local_attr_id = crm_concat(set_name, attr_name, '-'); + attr_id = local_attr_id; + + /* Minimal attempt at sanitizing automatic IDs */ + for (lpc = 0; local_attr_id[lpc] != 0; lpc++) { + switch (local_attr_id[lpc]) { + case ':': + local_attr_id[lpc] = '.'; + } + } + + } else if (attr_name == NULL) { + attr_name = attr_id; + } + + crm_debug_2("Creating %s/%s", section, tag); + if (tag != NULL) { + xml_obj = create_xml_node(xml_obj, tag); + crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid); + if (xml_top == NULL) { + xml_top = xml_obj; + } + } + + if (node_uuid == NULL && safe_str_neq(node_type, XML_CIB_TAG_TICKETS)) { + if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { + xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET); + } else { + xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS); + } + + } else if (set_type) { + xml_obj = create_xml_node(xml_obj, set_type); + + } else { + xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS); + } + crm_xml_add(xml_obj, XML_ATTR_ID, set_name); + + if (xml_top == NULL) { + xml_top = xml_obj; + } + + if (use_attributes_tag) { + xml_obj = create_xml_node(xml_obj, XML_TAG_ATTRS); + } } do_modify: xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_NVPAIR); - if(xml_top == NULL) { - xml_top = xml_obj; + if (xml_top == NULL) { + xml_top = xml_obj; } crm_xml_add(xml_obj, XML_ATTR_ID, attr_id); crm_xml_add(xml_obj, XML_NVPAIR_ATTR_NAME, attr_name); crm_xml_add(xml_obj, XML_NVPAIR_ATTR_VALUE, attr_value); - + crm_log_xml_debug_2(xml_top, "update_attr"); - rc = the_cib->cmds->delegated_variant_op( - the_cib, CIB_OP_MODIFY, NULL, section, xml_top, NULL, call_options|cib_quorum_override, user_name); - - if(rc < cib_ok) { - attr_msg(LOG_ERR, "Error setting %s=%s (section=%s, set=%s): %s", - attr_name, attr_value, section, crm_str(set_name), - cib_error2string(rc)); - crm_log_xml_info(xml_top, "Update"); + rc = the_cib->cmds->delegated_variant_op(the_cib, CIB_OP_MODIFY, NULL, section, xml_top, NULL, + call_options | cib_quorum_override, user_name); + + if (rc < cib_ok) { + attr_msg(LOG_ERR, "Error setting %s=%s (section=%s, set=%s): %s", + attr_name, attr_value, section, crm_str(set_name), cib_error2string(rc)); + crm_log_xml_info(xml_top, "Update"); } - + crm_free(local_set_name); crm_free(local_attr_id); free_xml(xml_top); - + return rc; } -enum cib_errors -read_attr_delegate(cib_t *the_cib, - const char *section, const char *node_uuid, const char *set_type, const char *set_name, - const char *attr_id, const char *attr_name, char **attr_value, gboolean to_console, - const char *user_name) +enum cib_errors +read_attr_delegate(cib_t * the_cib, + const char *section, const char *node_uuid, const char *set_type, + const char *set_name, const char *attr_id, const char *attr_name, + char **attr_value, gboolean to_console, const char *user_name) { enum cib_errors rc = cib_ok; CRM_ASSERT(attr_value != NULL); CRM_CHECK(section != NULL, return cib_missing); CRM_CHECK(attr_name != NULL || attr_id != NULL, return cib_missing); *attr_value = NULL; rc = find_nvpair_attr_delegate(the_cib, XML_NVPAIR_ATTR_VALUE, section, node_uuid, set_type, - set_name, attr_id, attr_name, to_console, attr_value, user_name); - if(rc != cib_ok) { - do_crm_log(LOG_DEBUG_2, "Query failed for attribute %s (section=%s, node=%s, set=%s): %s", - attr_name, section, crm_str(set_name), crm_str(node_uuid), - cib_error2string(rc)); + set_name, attr_id, attr_name, to_console, attr_value, user_name); + if (rc != cib_ok) { + do_crm_log(LOG_DEBUG_2, "Query failed for attribute %s (section=%s, node=%s, set=%s): %s", + attr_name, section, crm_str(set_name), crm_str(node_uuid), cib_error2string(rc)); } return rc; } - -enum cib_errors -delete_attr_delegate(cib_t *the_cib, int options, - const char *section, const char *node_uuid, const char *set_type, const char *set_name, - const char *attr_id, const char *attr_name, const char *attr_value, gboolean to_console, - const char *user_name) +enum cib_errors +delete_attr_delegate(cib_t * the_cib, int options, + const char *section, const char *node_uuid, const char *set_type, + const char *set_name, const char *attr_id, const char *attr_name, + const char *attr_value, gboolean to_console, const char *user_name) { enum cib_errors rc = cib_ok; xmlNode *xml_obj = NULL; char *local_attr_id = NULL; CRM_CHECK(section != NULL, return cib_missing); CRM_CHECK(attr_name != NULL || attr_id != NULL, return cib_missing); - if(attr_id == NULL) { - rc = find_nvpair_attr_delegate(the_cib, XML_ATTR_ID, section, node_uuid, set_type, - set_name, attr_id, attr_name, to_console, &local_attr_id, user_name); - if(rc != cib_ok) { - return rc; - } - attr_id = local_attr_id; + if (attr_id == NULL) { + rc = find_nvpair_attr_delegate(the_cib, XML_ATTR_ID, section, node_uuid, set_type, + set_name, attr_id, attr_name, to_console, &local_attr_id, + user_name); + if (rc != cib_ok) { + return rc; + } + attr_id = local_attr_id; } - + xml_obj = create_xml_node(NULL, XML_CIB_TAG_NVPAIR); crm_xml_add(xml_obj, XML_ATTR_ID, attr_id); crm_xml_add(xml_obj, XML_NVPAIR_ATTR_NAME, attr_name); crm_xml_add(xml_obj, XML_NVPAIR_ATTR_VALUE, attr_value); - - rc = the_cib->cmds->delegated_variant_op( - the_cib, CIB_OP_DELETE, NULL, section, xml_obj, NULL, options|cib_quorum_override, user_name); - - if(rc == cib_ok) { - attr_msg(LOG_DEBUG, "Deleted %s %s: id=%s%s%s%s%s\n", - section, node_uuid?"attribute":"option", local_attr_id, - set_name?" set=":"", set_name?set_name:"", - attr_name?" name=":"", attr_name?attr_name:""); + + rc = the_cib->cmds->delegated_variant_op(the_cib, CIB_OP_DELETE, NULL, section, xml_obj, NULL, + options | cib_quorum_override, user_name); + + if (rc == cib_ok) { + attr_msg(LOG_DEBUG, "Deleted %s %s: id=%s%s%s%s%s\n", + section, node_uuid ? "attribute" : "option", local_attr_id, + set_name ? " set=" : "", set_name ? set_name : "", + attr_name ? " name=" : "", attr_name ? attr_name : ""); } crm_free(local_attr_id); free_xml(xml_obj); return rc; } -enum cib_errors -query_node_uuid(cib_t *the_cib, const char *uname, char **uuid) +enum cib_errors +query_node_uuid(cib_t * the_cib, const char *uname, char **uuid) { enum cib_errors rc = cib_ok; xmlNode *a_child = NULL; xmlNode *xml_obj = NULL; xmlNode *fragment = NULL; const char *child_name = NULL; CRM_ASSERT(uname != NULL); CRM_ASSERT(uuid != NULL); - + rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment, - cib_sync_call|cib_scope_local); - if(rc != cib_ok) { - return rc; + cib_sync_call | cib_scope_local); + if (rc != cib_ok) { + return rc; } xml_obj = fragment; - CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), - return cib_output_data); + CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), return cib_output_data); CRM_ASSERT(xml_obj != NULL); crm_log_xml_debug(xml_obj, "Result section"); rc = cib_NOTEXISTS; *uuid = NULL; - - for(a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { - if(crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) { - child_name = crm_element_value(a_child, XML_ATTR_UNAME); - if(safe_str_eq(uname, child_name)) { - child_name = ID(a_child); - if(child_name != NULL) { - *uuid = crm_strdup(child_name); - rc = cib_ok; - } - break; - } - } + + for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { + if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) { + child_name = crm_element_value(a_child, XML_ATTR_UNAME); + if (safe_str_eq(uname, child_name)) { + child_name = ID(a_child); + if (child_name != NULL) { + *uuid = crm_strdup(child_name); + rc = cib_ok; + } + break; + } + } } free_xml(fragment); return rc; } -enum cib_errors -query_node_uname(cib_t *the_cib, const char *uuid, char **uname) +enum cib_errors +query_node_uname(cib_t * the_cib, const char *uuid, char **uname) { enum cib_errors rc = cib_ok; xmlNode *a_child = NULL; xmlNode *xml_obj = NULL; xmlNode *fragment = NULL; const char *child_name = NULL; CRM_ASSERT(uname != NULL); CRM_ASSERT(uuid != NULL); - + rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment, - cib_sync_call|cib_scope_local); - if(rc != cib_ok) { - return rc; + cib_sync_call | cib_scope_local); + if (rc != cib_ok) { + return rc; } xml_obj = fragment; - CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), - return cib_output_data); + CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), return cib_output_data); CRM_ASSERT(xml_obj != NULL); crm_log_xml_debug_2(xml_obj, "Result section"); rc = cib_NOTEXISTS; *uname = NULL; - - for(a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { - if(crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) { - child_name = ID(a_child); - if(safe_str_eq(uuid, child_name)) { - child_name = crm_element_value(a_child, XML_ATTR_UNAME); - if(child_name != NULL) { - *uname = crm_strdup(child_name); - rc = cib_ok; - } - break; - } - } + + for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { + if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) { + child_name = ID(a_child); + if (safe_str_eq(uuid, child_name)) { + child_name = crm_element_value(a_child, XML_ATTR_UNAME); + if (child_name != NULL) { + *uname = crm_strdup(child_name); + rc = cib_ok; + } + break; + } + } } - + free_xml(fragment); return rc; } -enum cib_errors -set_standby(cib_t *the_cib, const char *uuid, const char *scope, const char *standby_value) +enum cib_errors +set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value) { enum cib_errors rc = cib_ok; int str_length = 3; - char *attr_id = NULL; + char *attr_id = NULL; char *set_name = NULL; - const char *attr_name = "standby"; + const char *attr_name = "standby"; + CRM_CHECK(standby_value != NULL, return cib_missing_data); - if(scope == NULL) { - scope = XML_CIB_TAG_NODES; + if (scope == NULL) { + scope = XML_CIB_TAG_NODES; } - CRM_CHECK(uuid != NULL, return cib_missing_data); str_length += strlen(attr_name); str_length += strlen(uuid); - - if(safe_str_eq(scope, "reboot") || safe_str_eq(scope, XML_CIB_TAG_STATUS)) { - const char *extra = "transient"; - scope = XML_CIB_TAG_STATUS; - - str_length += strlen(extra); - crm_malloc0(attr_id, str_length); - sprintf(attr_id, "%s-%s-%s", extra, attr_name, uuid); - + + if (safe_str_eq(scope, "reboot") || safe_str_eq(scope, XML_CIB_TAG_STATUS)) { + const char *extra = "transient"; + + scope = XML_CIB_TAG_STATUS; + + str_length += strlen(extra); + crm_malloc0(attr_id, str_length); + sprintf(attr_id, "%s-%s-%s", extra, attr_name, uuid); + } else { - scope = XML_CIB_TAG_NODES; - crm_malloc0(attr_id, str_length); - sprintf(attr_id, "%s-%s", attr_name, uuid); + scope = XML_CIB_TAG_NODES; + crm_malloc0(attr_id, str_length); + sprintf(attr_id, "%s-%s", attr_name, uuid); } - + rc = update_attr(the_cib, cib_sync_call, scope, uuid, NULL, set_name, - attr_id, attr_name, standby_value, TRUE); + attr_id, attr_name, standby_value, TRUE); crm_free(attr_id); crm_free(set_name); return rc; } - diff --git a/lib/cib/cib_client.c b/lib/cib/cib_client.c index 0721bee9de..26c0205134 100644 --- a/lib/cib/cib_client.c +++ b/lib/cib/cib_client.c @@ -1,632 +1,622 @@ /* * Copyright (c) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 - GHashTable *cib_op_callback_table = NULL; -int cib_client_set_op_callback( - cib_t *cib, void (*callback)(const xmlNode *msg, int call_id, - int rc, xmlNode *output)); +int cib_client_set_op_callback(cib_t * cib, void (*callback) (const xmlNode * msg, int call_id, + int rc, xmlNode * output)); -int cib_client_add_notify_callback( - cib_t *cib, const char *event, void (*callback)( - const char *event, xmlNode *msg)); +int cib_client_add_notify_callback(cib_t * cib, const char *event, + void (*callback) (const char *event, xmlNode * msg)); -int cib_client_del_notify_callback( - cib_t *cib, const char *event, void (*callback)( - const char *event, xmlNode *msg)); +int cib_client_del_notify_callback(cib_t * cib, const char *event, + void (*callback) (const char *event, xmlNode * msg)); gint ciblib_GCompareFunc(gconstpointer a, gconstpointer b); -#define op_common(cib) \ - if(cib == NULL) { \ - return cib_missing; \ - } else if(cib->cmds->variant_op == NULL) { \ - return cib_variant; \ - } +#define op_common(cib) do { \ + if(cib == NULL) { \ + return cib_missing; \ + } else if(cib->cmds->variant_op == NULL) { \ + return cib_variant; \ + } \ + } while(0) -static int cib_client_noop(cib_t *cib, int call_options) +static int +cib_client_noop(cib_t * cib, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CRM_OP_NOOP, NULL, NULL, NULL, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CRM_OP_NOOP, NULL, NULL, NULL, NULL, call_options); } -static int cib_client_ping(cib_t *cib, xmlNode **output_data, int call_options) +static int +cib_client_ping(cib_t * cib, xmlNode ** output_data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CRM_OP_PING, NULL,NULL,NULL, output_data, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CRM_OP_PING, NULL, NULL, NULL, output_data, call_options); } - -static int cib_client_query(cib_t *cib, const char *section, - xmlNode **output_data, int call_options) +static int +cib_client_query(cib_t * cib, const char *section, xmlNode ** output_data, int call_options) { - return cib->cmds->query_from( - cib, NULL, section, output_data, call_options); + return cib->cmds->query_from(cib, NULL, section, output_data, call_options); } -static int cib_client_query_from(cib_t *cib, const char *host, const char *section, - xmlNode **output_data, int call_options) +static int +cib_client_query_from(cib_t * cib, const char *host, const char *section, + xmlNode ** output_data, int call_options) { - op_common(cib) - return cib->cmds->variant_op(cib, CIB_OP_QUERY, host, section, - NULL, output_data, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_QUERY, host, section, NULL, output_data, call_options); } -static int cib_client_is_master(cib_t *cib) +static int +cib_client_is_master(cib_t * cib) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_ISMASTER, NULL, NULL,NULL,NULL, - cib_scope_local|cib_sync_call); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_ISMASTER, NULL, NULL, NULL, NULL, + cib_scope_local | cib_sync_call); } -static int cib_client_set_slave(cib_t *cib, int call_options) +static int +cib_client_set_slave(cib_t * cib, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_SLAVE, NULL,NULL,NULL,NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_SLAVE, NULL, NULL, NULL, NULL, call_options); } -static int cib_client_set_slave_all(cib_t *cib, int call_options) +static int +cib_client_set_slave_all(cib_t * cib, int call_options) { - return cib_NOTSUPPORTED; + return cib_NOTSUPPORTED; } -static int cib_client_set_master(cib_t *cib, int call_options) +static int +cib_client_set_master(cib_t * cib, int call_options) { - op_common(cib) - crm_debug_3("Adding cib_scope_local to options"); - return cib->cmds->variant_op( - cib, CIB_OP_MASTER, NULL,NULL,NULL,NULL, - call_options|cib_scope_local); + op_common(cib); + crm_debug_3("Adding cib_scope_local to options"); + return cib->cmds->variant_op(cib, CIB_OP_MASTER, NULL, NULL, NULL, NULL, + call_options | cib_scope_local); } -static int cib_client_bump_epoch(cib_t *cib, int call_options) +static int +cib_client_bump_epoch(cib_t * cib, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_BUMP, NULL, NULL, NULL, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_BUMP, NULL, NULL, NULL, NULL, call_options); } -static int cib_client_upgrade(cib_t *cib, int call_options) +static int +cib_client_upgrade(cib_t * cib, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_UPGRADE, NULL, NULL, NULL, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_UPGRADE, NULL, NULL, NULL, NULL, call_options); } -static int cib_client_sync(cib_t *cib, const char *section, int call_options) +static int +cib_client_sync(cib_t * cib, const char *section, int call_options) { - return cib->cmds->sync_from(cib, NULL, section, call_options); + return cib->cmds->sync_from(cib, NULL, section, call_options); } -static int cib_client_sync_from( - cib_t *cib, const char *host, const char *section, int call_options) +static int +cib_client_sync_from(cib_t * cib, const char *host, const char *section, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_SYNC, host, section, NULL, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_SYNC, host, section, NULL, NULL, call_options); } -static int cib_client_create( - cib_t *cib, const char *section, xmlNode *data, int call_options) +static int +cib_client_create(cib_t * cib, const char *section, xmlNode * data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_CREATE, NULL, section, data, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_CREATE, NULL, section, data, NULL, call_options); } -static int cib_client_modify( - cib_t *cib, const char *section, xmlNode *data, int call_options) +static int +cib_client_modify(cib_t * cib, const char *section, xmlNode * data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_MODIFY, NULL, section, data, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_MODIFY, NULL, section, data, NULL, call_options); } -static int cib_client_update( - cib_t *cib, const char *section, xmlNode *data, int call_options) +static int +cib_client_update(cib_t * cib, const char *section, xmlNode * data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_MODIFY, NULL, section, data, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_MODIFY, NULL, section, data, NULL, call_options); } -static int cib_client_replace( - cib_t *cib, const char *section, xmlNode *data, int call_options) +static int +cib_client_replace(cib_t * cib, const char *section, xmlNode * data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_REPLACE, NULL, section, data, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_REPLACE, NULL, section, data, NULL, call_options); } -static int cib_client_delete( - cib_t *cib, const char *section, xmlNode *data, int call_options) +static int +cib_client_delete(cib_t * cib, const char *section, xmlNode * data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_DELETE, NULL, section, data, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_DELETE, NULL, section, data, NULL, call_options); } -static int cib_client_delete_absolute( - cib_t *cib, const char *section, xmlNode *data, int call_options) +static int +cib_client_delete_absolute(cib_t * cib, const char *section, xmlNode * data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_DELETE_ALT, NULL, section, data, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_DELETE_ALT, NULL, section, data, NULL, call_options); } -static int cib_client_erase( - cib_t *cib, xmlNode **output_data, int call_options) +static int +cib_client_erase(cib_t * cib, xmlNode ** output_data, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CIB_OP_ERASE, NULL, NULL, NULL, output_data, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CIB_OP_ERASE, NULL, NULL, NULL, output_data, call_options); } -static int cib_client_quit(cib_t *cib, int call_options) +static int +cib_client_quit(cib_t * cib, int call_options) { - op_common(cib) - return cib->cmds->variant_op( - cib, CRM_OP_QUIT, NULL, NULL, NULL, NULL, call_options); + op_common(cib); + return cib->cmds->variant_op(cib, CRM_OP_QUIT, NULL, NULL, NULL, NULL, call_options); } - -static void cib_destroy_op_callback(gpointer data) +static void +cib_destroy_op_callback(gpointer data) { cib_callback_client_t *blob = data; - if(blob->timer && blob->timer->ref > 0) { - g_source_remove(blob->timer->ref); + + if (blob->timer && blob->timer->ref > 0) { + g_source_remove(blob->timer->ref); } crm_free(blob->timer); crm_free(blob); } -char *get_shadow_file(const char *suffix) +char * +get_shadow_file(const char *suffix) { char *cib_home = NULL; char *fullname = NULL; char *name = crm_concat("shadow", suffix, '.'); const char *dir = getenv("CIB_shadow_dir"); - if(dir == NULL) { - uid_t uid = geteuid(); - struct passwd *pwent = getpwuid(uid); - const char *user = NULL; - - if(pwent) { - user = pwent->pw_name; - } else { - crm_perror(LOG_ERR, "Cannot get password entry for uid: %d", uid); - user = getenv("USER"); - } - - if(safe_str_eq(user, "root") || safe_str_eq(user, CRM_DAEMON_USER)) { - dir = CRM_CONFIG_DIR; - - } else { - const char *home = NULL; - if((home = getenv("HOME")) == NULL) { - if(pwent) { - home = pwent->pw_dir; - } - } - - if((dir = getenv("TMPDIR")) == NULL) { - dir = "/tmp"; - } - if(home && home[0] == '/') { - int rc = 0; - cib_home = crm_concat(home, ".cib", '/'); - - rc = mkdir(cib_home, 0700); - if(rc < 0 && errno != EEXIST) { - crm_perror(LOG_ERR, "Couldn't create user-specific shadow directory: %s", cib_home); - errno = 0; - - } else { - dir = cib_home; - } - } - } + if (dir == NULL) { + uid_t uid = geteuid(); + struct passwd *pwent = getpwuid(uid); + const char *user = NULL; + + if (pwent) { + user = pwent->pw_name; + } else { + crm_perror(LOG_ERR, "Cannot get password entry for uid: %d", uid); + user = getenv("USER"); + } + + if (safe_str_eq(user, "root") || safe_str_eq(user, CRM_DAEMON_USER)) { + dir = CRM_CONFIG_DIR; + + } else { + const char *home = NULL; + + if ((home = getenv("HOME")) == NULL) { + if (pwent) { + home = pwent->pw_dir; + } + } + + if ((dir = getenv("TMPDIR")) == NULL) { + dir = "/tmp"; + } + if (home && home[0] == '/') { + int rc = 0; + + cib_home = crm_concat(home, ".cib", '/'); + + rc = mkdir(cib_home, 0700); + if (rc < 0 && errno != EEXIST) { + crm_perror(LOG_ERR, "Couldn't create user-specific shadow directory: %s", + cib_home); + errno = 0; + + } else { + dir = cib_home; + } + } + } } - + fullname = crm_concat(dir, name, '/'); crm_free(cib_home); crm_free(name); - + return fullname; } - -cib_t* -cib_shadow_new(const char *shadow) +cib_t * +cib_shadow_new(const char *shadow) { cib_t *new_cib = NULL; char *shadow_file = NULL; + CRM_CHECK(shadow != NULL, return NULL); - + shadow_file = get_shadow_file(shadow); new_cib = cib_file_new(shadow_file); crm_free(shadow_file); - + return new_cib; } -cib_t *cib_new_no_shadow(void) +cib_t * +cib_new_no_shadow(void) { unsetenv("CIB_shadow"); return cib_new(); } - -cib_t* -cib_new(void) +cib_t * +cib_new(void) { const char *value = getenv("CIB_shadow"); - if(value) { - return cib_shadow_new(value); + + if (value) { + return cib_shadow_new(value); } value = getenv("CIB_file"); - if(value) { - return cib_file_new(value); + if (value) { + return cib_file_new(value); } value = getenv("CIB_port"); - if(value) { - gboolean encrypted = TRUE; - int port = crm_parse_int(value, NULL); - const char *server = getenv("CIB_server"); - const char *user = getenv("CIB_user"); - const char *pass = getenv("CIB_passwd"); - value = getenv("CIB_encrypted"); - if(value && crm_is_true(value) == FALSE) { - crm_info("Disabling TLS"); - encrypted = FALSE; - } - - if(user == NULL) { - user = CRM_DAEMON_USER; - crm_info("Defaulting to user: %s", user); - } - - if(server == NULL) { - server = "localhost"; - crm_info("Defaulting to localhost"); - } - - return cib_remote_new(server, user, pass, port, encrypted); + if (value) { + gboolean encrypted = TRUE; + int port = crm_parse_int(value, NULL); + const char *server = getenv("CIB_server"); + const char *user = getenv("CIB_user"); + const char *pass = getenv("CIB_passwd"); + + value = getenv("CIB_encrypted"); + if (value && crm_is_true(value) == FALSE) { + crm_info("Disabling TLS"); + encrypted = FALSE; + } + + if (user == NULL) { + user = CRM_DAEMON_USER; + crm_info("Defaulting to user: %s", user); + } + + if (server == NULL) { + server = "localhost"; + crm_info("Defaulting to localhost"); + } + + return cib_remote_new(server, user, pass, port, encrypted); } - + return cib_native_new(); } /* this is backwards... cib_*_new should call this not the other way around */ -cib_t* +cib_t * cib_new_variant(void) { - cib_t* new_cib = NULL; - crm_malloc0(new_cib, sizeof(cib_t)); - - if(cib_op_callback_table != NULL) { - g_hash_table_destroy(cib_op_callback_table); - cib_op_callback_table = NULL; - } - if(cib_op_callback_table == NULL) { - cib_op_callback_table = g_hash_table_new_full( - g_direct_hash, g_direct_equal, - NULL, cib_destroy_op_callback); - } - - new_cib->call_id = 1; - new_cib->variant = cib_undefined; - - new_cib->type = cib_none; - new_cib->state = cib_disconnected; - - new_cib->op_callback = NULL; - new_cib->variant_opaque = NULL; - new_cib->notify_list = NULL; - - /* the rest will get filled in by the variant constructor */ - crm_malloc0(new_cib->cmds, sizeof(cib_api_operations_t)); - - new_cib->cmds->set_op_callback = cib_client_set_op_callback; - new_cib->cmds->add_notify_callback = cib_client_add_notify_callback; - new_cib->cmds->del_notify_callback = cib_client_del_notify_callback; - new_cib->cmds->register_callback = cib_client_register_callback; - - new_cib->cmds->noop = cib_client_noop; - new_cib->cmds->ping = cib_client_ping; - new_cib->cmds->query = cib_client_query; - new_cib->cmds->sync = cib_client_sync; - - new_cib->cmds->query_from = cib_client_query_from; - new_cib->cmds->sync_from = cib_client_sync_from; - - new_cib->cmds->is_master = cib_client_is_master; - new_cib->cmds->set_master = cib_client_set_master; - new_cib->cmds->set_slave = cib_client_set_slave; - new_cib->cmds->set_slave_all = cib_client_set_slave_all; - - new_cib->cmds->upgrade = cib_client_upgrade; - new_cib->cmds->bump_epoch = cib_client_bump_epoch; - - new_cib->cmds->create = cib_client_create; - new_cib->cmds->modify = cib_client_modify; - new_cib->cmds->update = cib_client_update; - new_cib->cmds->replace = cib_client_replace; - new_cib->cmds->delete = cib_client_delete; - new_cib->cmds->erase = cib_client_erase; - new_cib->cmds->quit = cib_client_quit; - - new_cib->cmds->delete_absolute = cib_client_delete_absolute; - - return new_cib; + cib_t *new_cib = NULL; + + crm_malloc0(new_cib, sizeof(cib_t)); + + if (cib_op_callback_table != NULL) { + g_hash_table_destroy(cib_op_callback_table); + cib_op_callback_table = NULL; + } + if (cib_op_callback_table == NULL) { + cib_op_callback_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, cib_destroy_op_callback); + } + + new_cib->call_id = 1; + new_cib->variant = cib_undefined; + + new_cib->type = cib_none; + new_cib->state = cib_disconnected; + + new_cib->op_callback = NULL; + new_cib->variant_opaque = NULL; + new_cib->notify_list = NULL; + + /* the rest will get filled in by the variant constructor */ + crm_malloc0(new_cib->cmds, sizeof(cib_api_operations_t)); + + new_cib->cmds->set_op_callback = cib_client_set_op_callback; + new_cib->cmds->add_notify_callback = cib_client_add_notify_callback; + new_cib->cmds->del_notify_callback = cib_client_del_notify_callback; + new_cib->cmds->register_callback = cib_client_register_callback; + + new_cib->cmds->noop = cib_client_noop; + new_cib->cmds->ping = cib_client_ping; + new_cib->cmds->query = cib_client_query; + new_cib->cmds->sync = cib_client_sync; + + new_cib->cmds->query_from = cib_client_query_from; + new_cib->cmds->sync_from = cib_client_sync_from; + + new_cib->cmds->is_master = cib_client_is_master; + new_cib->cmds->set_master = cib_client_set_master; + new_cib->cmds->set_slave = cib_client_set_slave; + new_cib->cmds->set_slave_all = cib_client_set_slave_all; + + new_cib->cmds->upgrade = cib_client_upgrade; + new_cib->cmds->bump_epoch = cib_client_bump_epoch; + + new_cib->cmds->create = cib_client_create; + new_cib->cmds->modify = cib_client_modify; + new_cib->cmds->update = cib_client_update; + new_cib->cmds->replace = cib_client_replace; + new_cib->cmds->delete = cib_client_delete; + new_cib->cmds->erase = cib_client_erase; + new_cib->cmds->quit = cib_client_quit; + + new_cib->cmds->delete_absolute = cib_client_delete_absolute; + + return new_cib; } void -cib_delete(cib_t *cib) +cib_delete(cib_t * cib) { - GList *list = cib->notify_list; - while(list != NULL) { - cib_notify_client_t *client = g_list_nth_data(list, 0); - list = g_list_remove(list, client); - crm_free(client); - } - - g_hash_table_destroy(cib_op_callback_table); - cib->cmds->free(cib); - cib = NULL; + GList *list = cib->notify_list; + + while (list != NULL) { + cib_notify_client_t *client = g_list_nth_data(list, 0); + + list = g_list_remove(list, client); + crm_free(client); + } + + g_hash_table_destroy(cib_op_callback_table); + cib->cmds->free(cib); + cib = NULL; +} + +int +cib_client_set_op_callback(cib_t * cib, void (*callback) (const xmlNode * msg, int call_id, + int rc, xmlNode * output)) +{ + if (callback == NULL) { + crm_info("Un-Setting operation callback"); + + } else { + crm_debug_3("Setting operation callback"); + } + cib->op_callback = callback; + return cib_ok; } +int +cib_client_add_notify_callback(cib_t * cib, const char *event, + void (*callback) (const char *event, xmlNode * msg)) +{ + GList *list_item = NULL; + cib_notify_client_t *new_client = NULL; + + if (cib->variant != cib_native && cib->variant != cib_remote) { + return cib_NOTSUPPORTED; + } + + crm_debug_2("Adding callback for %s events (%d)", event, g_list_length(cib->notify_list)); + + crm_malloc0(new_client, sizeof(cib_notify_client_t)); + new_client->event = event; + new_client->callback = callback; + + list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc); + + if (list_item != NULL) { + crm_warn("Callback already present"); + crm_free(new_client); + return cib_EXISTS; + + } else { + cib->notify_list = g_list_append(cib->notify_list, new_client); + + cib->cmds->register_notification(cib, event, 1); + + crm_debug_3("Callback added (%d)", g_list_length(cib->notify_list)); + } + return cib_ok; +} int -cib_client_set_op_callback( - cib_t *cib, void (*callback)(const xmlNode *msg, int call_id, - int rc, xmlNode *output)) -{ - if(callback == NULL) { - crm_info("Un-Setting operation callback"); - - } else { - crm_debug_3("Setting operation callback"); - } - cib->op_callback = callback; - return cib_ok; -} - -int cib_client_add_notify_callback( - cib_t *cib, const char *event, void (*callback)( - const char *event, xmlNode *msg)) -{ - GList *list_item = NULL; - cib_notify_client_t *new_client = NULL; - - if(cib->variant != cib_native - && cib->variant != cib_remote) { - return cib_NOTSUPPORTED; - } - - crm_debug_2("Adding callback for %s events (%d)", - event, g_list_length(cib->notify_list)); - - crm_malloc0(new_client, sizeof(cib_notify_client_t)); - new_client->event = event; - new_client->callback = callback; - - list_item = g_list_find_custom( - cib->notify_list, new_client, ciblib_GCompareFunc); - - if(list_item != NULL) { - crm_warn("Callback already present"); - crm_free(new_client); - return cib_EXISTS; - - } else { - cib->notify_list = g_list_append( - cib->notify_list, new_client); - - cib->cmds->register_notification(cib, event, 1); - - crm_debug_3("Callback added (%d)", g_list_length(cib->notify_list)); - } - return cib_ok; -} - - -int cib_client_del_notify_callback( - cib_t *cib, const char *event, void (*callback)( - const char *event, xmlNode *msg)) -{ - GList *list_item = NULL; - cib_notify_client_t *new_client = NULL; - - if(cib->variant != cib_native - && cib->variant != cib_remote) { - return cib_NOTSUPPORTED; - } - - crm_debug("Removing callback for %s events", event); - - crm_malloc0(new_client, sizeof(cib_notify_client_t)); - new_client->event = event; - new_client->callback = callback; - - list_item = g_list_find_custom( - cib->notify_list, new_client, ciblib_GCompareFunc); - - cib->cmds->register_notification(cib, event, 0); - - if(list_item != NULL) { - cib_notify_client_t *list_client = list_item->data; - cib->notify_list = - g_list_remove(cib->notify_list, list_client); - crm_free(list_client); - - crm_debug_3("Removed callback"); - - } else { - crm_debug_3("Callback not present"); - } - crm_free(new_client); - return cib_ok; -} - -gint ciblib_GCompareFunc(gconstpointer a, gconstpointer b) +cib_client_del_notify_callback(cib_t * cib, const char *event, + void (*callback) (const char *event, xmlNode * msg)) +{ + GList *list_item = NULL; + cib_notify_client_t *new_client = NULL; + + if (cib->variant != cib_native && cib->variant != cib_remote) { + return cib_NOTSUPPORTED; + } + + crm_debug("Removing callback for %s events", event); + + crm_malloc0(new_client, sizeof(cib_notify_client_t)); + new_client->event = event; + new_client->callback = callback; + + list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc); + + cib->cmds->register_notification(cib, event, 0); + + if (list_item != NULL) { + cib_notify_client_t *list_client = list_item->data; + + cib->notify_list = g_list_remove(cib->notify_list, list_client); + crm_free(list_client); + + crm_debug_3("Removed callback"); + + } else { + crm_debug_3("Callback not present"); + } + crm_free(new_client); + return cib_ok; +} + +gint +ciblib_GCompareFunc(gconstpointer a, gconstpointer b) { int rc = 0; const cib_notify_client_t *a_client = a; const cib_notify_client_t *b_client = b; - + CRM_CHECK(a_client->event != NULL && b_client->event != NULL, return 0); rc = strcmp(a_client->event, b_client->event); - if(rc == 0) { - if(a_client->callback == b_client->callback) { - return 0; - } else if(((long)a_client->callback) < ((long)b_client->callback)) { - crm_trace("callbacks for %s are not equal: %p < %p", - a_client->event, a_client->callback, b_client->callback); - return -1; - } - crm_trace("callbacks for %s are not equal: %p > %p", - a_client->event, a_client->callback, b_client->callback); - return 1; + if (rc == 0) { + if (a_client->callback == b_client->callback) { + return 0; + } else if (((long)a_client->callback) < ((long)b_client->callback)) { + crm_trace("callbacks for %s are not equal: %p < %p", + a_client->event, a_client->callback, b_client->callback); + return -1; + } + crm_trace("callbacks for %s are not equal: %p > %p", + a_client->event, a_client->callback, b_client->callback); + return 1; } return rc; } - -static gboolean cib_async_timeout_handler(gpointer data) +static gboolean +cib_async_timeout_handler(gpointer data) { struct timer_rec_s *timer = data; + crm_debug("Async call %d timed out after %ds", timer->call_id, timer->timeout); cib_native_callback(timer->cib, NULL, timer->call_id, cib_remote_timeout); /* Always return TRUE, never remove the handler * We do that in remove_cib_op_callback() */ return TRUE; } gboolean -cib_client_register_callback( - cib_t *cib, int call_id, int timeout, gboolean only_success, void *user_data, - const char *callback_name, void (*callback)(xmlNode*, int, int, xmlNode*,void*)) -{ - cib_callback_client_t *blob = NULL; - - if(call_id < 0) { - if(only_success == FALSE) { - callback(NULL, call_id, call_id, NULL, user_data); - } else { - crm_warn("CIB call failed: %s", cib_error2string(call_id)); - } - return FALSE; - } - - - crm_malloc0(blob, sizeof(cib_callback_client_t)); - blob->id = callback_name; - blob->only_success = only_success; - blob->user_data = user_data; - blob->callback = callback; - - if(timeout > 0) { - struct timer_rec_s *async_timer = NULL; - - crm_malloc0(async_timer, sizeof(struct timer_rec_s)); - blob->timer = async_timer; - - async_timer->cib = cib; - async_timer->call_id = call_id; - async_timer->timeout = timeout*1000; - async_timer->ref = g_timeout_add( - async_timer->timeout, cib_async_timeout_handler, async_timer); - } - - g_hash_table_insert(cib_op_callback_table, GINT_TO_POINTER(call_id), blob); - - return TRUE; +cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean only_success, + void *user_data, const char *callback_name, + void (*callback) (xmlNode *, int, int, xmlNode *, void *)) +{ + cib_callback_client_t *blob = NULL; + + if (call_id < 0) { + if (only_success == FALSE) { + callback(NULL, call_id, call_id, NULL, user_data); + } else { + crm_warn("CIB call failed: %s", cib_error2string(call_id)); + } + return FALSE; + } + + crm_malloc0(blob, sizeof(cib_callback_client_t)); + blob->id = callback_name; + blob->only_success = only_success; + blob->user_data = user_data; + blob->callback = callback; + + if (timeout > 0) { + struct timer_rec_s *async_timer = NULL; + + crm_malloc0(async_timer, sizeof(struct timer_rec_s)); + blob->timer = async_timer; + + async_timer->cib = cib; + async_timer->call_id = call_id; + async_timer->timeout = timeout * 1000; + async_timer->ref = + g_timeout_add(async_timer->timeout, cib_async_timeout_handler, async_timer); + } + + g_hash_table_insert(cib_op_callback_table, GINT_TO_POINTER(call_id), blob); + + return TRUE; } void -remove_cib_op_callback(int call_id, gboolean all_callbacks) +remove_cib_op_callback(int call_id, gboolean all_callbacks) { - if(all_callbacks) { - if(cib_op_callback_table != NULL) { - g_hash_table_destroy(cib_op_callback_table); - } + if (all_callbacks) { + if (cib_op_callback_table != NULL) { + g_hash_table_destroy(cib_op_callback_table); + } - cib_op_callback_table = g_hash_table_new_full( - g_direct_hash, g_direct_equal, - NULL, cib_destroy_op_callback); + cib_op_callback_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, cib_destroy_op_callback); } else { - g_hash_table_remove(cib_op_callback_table, GINT_TO_POINTER(call_id)); + g_hash_table_remove(cib_op_callback_table, GINT_TO_POINTER(call_id)); } } int num_cib_op_callbacks(void) { - if(cib_op_callback_table == NULL) { - return 0; + if (cib_op_callback_table == NULL) { + return 0; } return g_hash_table_size(cib_op_callback_table); } -static void cib_dump_pending_op(gpointer key, gpointer value, gpointer user_data) +static void +cib_dump_pending_op(gpointer key, gpointer value, gpointer user_data) { int call = GPOINTER_TO_INT(key); cib_callback_client_t *blob = value; crm_debug("Call %d (%s): pending", call, crm_str(blob->id)); } -void cib_dump_pending_callbacks(void) +void +cib_dump_pending_callbacks(void) { - if(cib_op_callback_table == NULL) { - return; + if (cib_op_callback_table == NULL) { + return; } return g_hash_table_foreach(cib_op_callback_table, cib_dump_pending_op, NULL); } - diff --git a/lib/cib/cib_file.c b/lib/cib/cib_file.c index 7bdc2cb7e5..e70f54cd01 100644 --- a/lib/cib/cib_file.c +++ b/lib/cib/cib_file.c @@ -1,329 +1,328 @@ /* * Copyright (c) 2004 International Business Machines * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 +typedef struct cib_file_opaque_s { + int flags; + char *filename; -typedef struct cib_file_opaque_s -{ - int flags; - char *filename; - } cib_file_opaque_t; -int cib_file_perform_op( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options); - -int cib_file_perform_op_delegate( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options, const char *user_name); +int cib_file_perform_op(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options); -int cib_file_signon(cib_t* cib, const char *name, enum cib_conn_type type); -int cib_file_signoff(cib_t* cib); -int cib_file_free(cib_t* cib); +int cib_file_perform_op_delegate(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options, + const char *user_name); -static int cib_file_inputfd(cib_t* cib) { return cib_NOTSUPPORTED; } +int cib_file_signon(cib_t * cib, const char *name, enum cib_conn_type type); +int cib_file_signoff(cib_t * cib); +int cib_file_free(cib_t * cib); -static int cib_file_set_connection_dnotify( - cib_t *cib, void (*dnotify)(gpointer user_data)) +static int +cib_file_inputfd(cib_t * cib) { return cib_NOTSUPPORTED; } +static int +cib_file_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data)) +{ + return cib_NOTSUPPORTED; +} -static int cib_file_register_notification(cib_t* cib, const char *callback, int enabled) +static int +cib_file_register_notification(cib_t * cib, const char *callback, int enabled) { return cib_NOTSUPPORTED; } -cib_t* -cib_file_new (const char *cib_location) +cib_t * +cib_file_new(const char *cib_location) { cib_file_opaque_t *private = NULL; cib_t *cib = cib_new_variant(); crm_malloc0(private, sizeof(cib_file_opaque_t)); cib->variant = cib_file; cib->variant_opaque = private; - if(cib_location == NULL) { - cib_location = getenv("CIB_file"); + if (cib_location == NULL) { + cib_location = getenv("CIB_file"); } private->filename = crm_strdup(cib_location); - /* assign variant specific ops*/ + /* assign variant specific ops */ cib->cmds->variant_op = cib_file_perform_op; cib->cmds->delegated_variant_op = cib_file_perform_op_delegate; - cib->cmds->signon = cib_file_signon; - cib->cmds->signoff = cib_file_signoff; - cib->cmds->free = cib_file_free; - cib->cmds->inputfd = cib_file_inputfd; + cib->cmds->signon = cib_file_signon; + cib->cmds->signoff = cib_file_signoff; + cib->cmds->free = cib_file_free; + cib->cmds->inputfd = cib_file_inputfd; cib->cmds->register_notification = cib_file_register_notification; cib->cmds->set_connection_dnotify = cib_file_set_connection_dnotify; return cib; } static xmlNode *in_mem_cib = NULL; -static int load_file_cib(const char *filename) +static int +load_file_cib(const char *filename) { int rc = cib_ok; struct stat buf; xmlNode *root = NULL; gboolean dtd_ok = TRUE; const char *ignore_dtd = NULL; xmlNode *status = NULL; - + rc = stat(filename, &buf); if (rc == 0) { - root = filename2xml(filename); - if(root == NULL) { - return cib_dtd_validation; - } + root = filename2xml(filename); + if (root == NULL) { + return cib_dtd_validation; + } } else { - return cib_NOTEXISTS; + return cib_NOTEXISTS; } rc = 0; - + status = find_xml_node(root, XML_CIB_TAG_STATUS, FALSE); - if(status == NULL) { - create_xml_node(root, XML_CIB_TAG_STATUS); + if (status == NULL) { + create_xml_node(root, XML_CIB_TAG_STATUS); } ignore_dtd = crm_element_value(root, XML_ATTR_VALIDATION); dtd_ok = validate_xml(root, NULL, TRUE); - if(dtd_ok == FALSE) { - crm_err("CIB does not validate against %s", ignore_dtd); - rc = cib_dtd_validation; - goto bail; - } - + if (dtd_ok == FALSE) { + crm_err("CIB does not validate against %s", ignore_dtd); + rc = cib_dtd_validation; + goto bail; + } + in_mem_cib = root; return rc; bail: free_xml(root); root = NULL; return rc; } int -cib_file_signon(cib_t* cib, const char *name, enum cib_conn_type type) +cib_file_signon(cib_t * cib, const char *name, enum cib_conn_type type) { int rc = cib_ok; cib_file_opaque_t *private = cib->variant_opaque; - if(private->filename == FALSE) { - rc = cib_missing; + if (private->filename == FALSE) { + rc = cib_missing; } else { - rc = load_file_cib(private->filename); + rc = load_file_cib(private->filename); } - - if(rc == cib_ok) { - crm_debug("%s: Opened connection to local file '%s'", name, private->filename); - cib->state = cib_connected_command; - cib->type = cib_command; + + if (rc == cib_ok) { + crm_debug("%s: Opened connection to local file '%s'", name, private->filename); + cib->state = cib_connected_command; + cib->type = cib_command; } else { - fprintf(stderr, "%s: Connection to local file '%s' failed: %s\n", - name, private->filename, cib_error2string(rc)); + fprintf(stderr, "%s: Connection to local file '%s' failed: %s\n", + name, private->filename, cib_error2string(rc)); } - + return rc; } - + int -cib_file_signoff(cib_t* cib) +cib_file_signoff(cib_t * cib) { int rc = cib_ok; cib_file_opaque_t *private = cib->variant_opaque; crm_debug("Signing out of the CIB Service"); - - if(strstr(private->filename, ".bz2") != NULL) { - rc = write_xml_file(in_mem_cib, private->filename, TRUE); - + + if (strstr(private->filename, ".bz2") != NULL) { + rc = write_xml_file(in_mem_cib, private->filename, TRUE); + } else { - rc = write_xml_file(in_mem_cib, private->filename, FALSE); + rc = write_xml_file(in_mem_cib, private->filename, FALSE); } - if(rc > 0) { - crm_info("Wrote CIB to %s", private->filename); - rc = cib_ok; - + if (rc > 0) { + crm_info("Wrote CIB to %s", private->filename); + rc = cib_ok; + } else { - crm_err("Could not write CIB to %s", private->filename); + crm_err("Could not write CIB to %s", private->filename); } free_xml(in_mem_cib); - + cib->state = cib_disconnected; - cib->type = cib_none; - + cib->type = cib_none; + return rc; } int -cib_file_free (cib_t* cib) +cib_file_free(cib_t * cib) { int rc = cib_ok; - if(cib->state != cib_disconnected) { - rc = cib_file_signoff(cib); + if (cib->state != cib_disconnected) { + rc = cib_file_signoff(cib); } - - if(rc == cib_ok) { - cib_file_opaque_t *private = cib->variant_opaque; - crm_free(private->filename); - crm_free(cib->cmds); - crm_free(private); - crm_free(cib); + + if (rc == cib_ok) { + cib_file_opaque_t *private = cib->variant_opaque; + + crm_free(private->filename); + crm_free(cib->cmds); + crm_free(private); + crm_free(cib); } else { - fprintf(stderr, "Couldn't sign off: %d\n", rc); + fprintf(stderr, "Couldn't sign off: %d\n", rc); } - + return rc; } -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_file_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}, {CIB_OP_UPGRADE, FALSE, cib_process_upgrade}, }; /* *INDENT-ON* */ - int -cib_file_perform_op( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options) +cib_file_perform_op(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options) { - return cib_file_perform_op_delegate( - cib, op, host, section, data, output_data, call_options, NULL); + return cib_file_perform_op_delegate(cib, op, host, section, data, output_data, call_options, + NULL); } int -cib_file_perform_op_delegate( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options, const char *user_name) +cib_file_perform_op_delegate(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options, + const char *user_name) { int rc = cib_ok; gboolean query = FALSE; gboolean changed = FALSE; xmlNode *output = NULL; xmlNode *cib_diff = NULL; xmlNode *result_cib = NULL; cib_op_t *fn = NULL; int lpc = 0; static int max_msg_types = DIMOF(cib_file_ops); crm_info("%s on %s", op, section); - - if(cib->state == cib_disconnected) { - return cib_not_connected; + + if (cib->state == cib_disconnected) { + return cib_not_connected; } - if(output_data != NULL) { - *output_data = NULL; + if (output_data != NULL) { + *output_data = NULL; } - - if(op == NULL) { - return cib_operation; + + if (op == NULL) { + return cib_operation; } for (lpc = 0; lpc < max_msg_types; lpc++) { - if (safe_str_eq(op, cib_file_ops[lpc].op)) { - fn = &(cib_file_ops[lpc].fn); - query = cib_file_ops[lpc].read_only; - break; - } + if (safe_str_eq(op, cib_file_ops[lpc].op)) { + fn = &(cib_file_ops[lpc].fn); + query = cib_file_ops[lpc].read_only; + break; + } } - - if(fn == NULL) { - return cib_NOTSUPPORTED; + + if (fn == NULL) { + return cib_NOTSUPPORTED; } cib->call_id++; - rc = cib_perform_op(op, call_options|cib_inhibit_bcast, fn, query, - section, NULL, data, TRUE, &changed, in_mem_cib, &result_cib, &cib_diff, &output); + rc = cib_perform_op(op, call_options | cib_inhibit_bcast, fn, query, + section, NULL, data, TRUE, &changed, in_mem_cib, &result_cib, &cib_diff, + &output); - if(rc == cib_dtd_validation) { - validate_xml_verbose(result_cib); + if (rc == cib_dtd_validation) { + validate_xml_verbose(result_cib); } - - if(rc != cib_ok) { - free_xml(result_cib); - - } else if(query == FALSE) { - log_xml_diff(LOG_DEBUG, cib_diff, "cib:diff"); - free_xml(in_mem_cib); - in_mem_cib = result_cib; + + if (rc != cib_ok) { + free_xml(result_cib); + + } else if (query == FALSE) { + log_xml_diff(LOG_DEBUG, cib_diff, "cib:diff"); + free_xml(in_mem_cib); + in_mem_cib = result_cib; } free_xml(cib_diff); - if(cib->op_callback != NULL) { - cib->op_callback(NULL, cib->call_id, rc, output); + if (cib->op_callback != NULL) { + cib->op_callback(NULL, cib->call_id, rc, output); } - - if(output_data && output) { - *output_data = copy_xml(output); + + if (output_data && output) { + *output_data = copy_xml(output); } - if(query == FALSE || (call_options & cib_no_children)) { - free_xml(output); - } else if(safe_str_eq(crm_element_name(output), "xpath-query")) { - free_xml(output); + if (query == FALSE || (call_options & cib_no_children)) { + free_xml(output); + } else if (safe_str_eq(crm_element_name(output), "xpath-query")) { + free_xml(output); } - + return rc; } - - diff --git a/lib/cib/cib_native.c b/lib/cib/cib_native.c index 631b80e80f..deb90edd86 100644 --- a/lib/cib/cib_native.c +++ b/lib/cib/cib_native.c @@ -1,687 +1,681 @@ /* * Copyright (c) 2004 International Business Machines * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 +typedef struct cib_native_opaque_s { + IPC_Channel *command_channel; + IPC_Channel *callback_channel; + GCHSource *callback_source; + char *token; -typedef struct cib_native_opaque_s -{ - IPC_Channel *command_channel; - IPC_Channel *callback_channel; - GCHSource *callback_source; - char *token; - } cib_native_opaque_t; -int cib_native_perform_op( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options); +int cib_native_perform_op(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options); -int cib_native_perform_op_delegate( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options, const char *user_name); +int cib_native_perform_op_delegate(cib_t * cib, const char *op, const char *host, + const char *section, xmlNode * data, xmlNode ** output_data, + int call_options, const char *user_name); -int cib_native_free(cib_t* cib); -int cib_native_signoff(cib_t* cib); -int cib_native_signon(cib_t* cib, const char *name, enum cib_conn_type type); -int cib_native_signon_raw(cib_t* cib, const char *name, enum cib_conn_type type, int *async_fd, int *sync_fd); +int cib_native_free(cib_t * cib); +int cib_native_signoff(cib_t * cib); +int cib_native_signon(cib_t * cib, const char *name, enum cib_conn_type type); +int cib_native_signon_raw(cib_t * cib, const char *name, enum cib_conn_type type, int *async_fd, + int *sync_fd); -IPC_Channel *cib_native_channel(cib_t* cib); -gboolean cib_native_msgready(cib_t* cib); -gboolean cib_native_dispatch(IPC_Channel *channel, gpointer user_data); +IPC_Channel *cib_native_channel(cib_t * cib); +gboolean cib_native_msgready(cib_t * cib); +gboolean cib_native_dispatch(IPC_Channel * channel, gpointer user_data); -int cib_native_inputfd(cib_t* cib); -int cib_native_rcvmsg(cib_t* cib, int blocking); -int cib_native_set_connection_dnotify(cib_t *cib, void (*dnotify)(gpointer user_data)); +int cib_native_inputfd(cib_t * cib); +int cib_native_rcvmsg(cib_t * cib, int blocking); +int cib_native_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data)); -cib_t* -cib_native_new (void) +cib_t * +cib_native_new(void) { - cib_native_opaque_t *native = NULL; - cib_t *cib = cib_new_variant(); - - crm_malloc0(native, sizeof(cib_native_opaque_t)); - - cib->variant = cib_native; - cib->variant_opaque = native; - - native->command_channel = NULL; - native->callback_channel = NULL; - - /* assign variant specific ops*/ - cib->cmds->variant_op = cib_native_perform_op; - cib->cmds->delegated_variant_op = cib_native_perform_op_delegate; - cib->cmds->signon = cib_native_signon; - cib->cmds->signon_raw = cib_native_signon_raw; - cib->cmds->signoff = cib_native_signoff; - cib->cmds->free = cib_native_free; - cib->cmds->inputfd = cib_native_inputfd; - - cib->cmds->register_notification = cib_native_register_notification; - cib->cmds->set_connection_dnotify = cib_native_set_connection_dnotify; - - return cib; + cib_native_opaque_t *native = NULL; + cib_t *cib = cib_new_variant(); + + crm_malloc0(native, sizeof(cib_native_opaque_t)); + + cib->variant = cib_native; + cib->variant_opaque = native; + + native->command_channel = NULL; + native->callback_channel = NULL; + + /* assign variant specific ops */ + cib->cmds->variant_op = cib_native_perform_op; + cib->cmds->delegated_variant_op = cib_native_perform_op_delegate; + cib->cmds->signon = cib_native_signon; + cib->cmds->signon_raw = cib_native_signon_raw; + cib->cmds->signoff = cib_native_signoff; + cib->cmds->free = cib_native_free; + cib->cmds->inputfd = cib_native_inputfd; + + cib->cmds->register_notification = cib_native_register_notification; + cib->cmds->set_connection_dnotify = cib_native_set_connection_dnotify; + + return cib; } int -cib_native_signon(cib_t* cib, const char *name, enum cib_conn_type type) +cib_native_signon(cib_t * cib, const char *name, enum cib_conn_type type) { return cib_native_signon_raw(cib, name, type, NULL, NULL); } int -cib_native_signon_raw(cib_t* cib, const char *name, enum cib_conn_type type, int *async_fd, int *sync_fd) +cib_native_signon_raw(cib_t * cib, const char *name, enum cib_conn_type type, int *async_fd, + int *sync_fd) { - int rc = cib_ok; - xmlNode *hello = NULL; - char *uuid_ticket = NULL; - cib_native_opaque_t *native = cib->variant_opaque; - - crm_debug_4("Connecting command channel"); - - if(type == cib_command) { - cib->state = cib_connected_command; - native->command_channel = init_client_ipc_comms_nodispatch( - cib_channel_rw); - - } else if(type == cib_query) { - cib->state = cib_connected_query; - native->command_channel = init_client_ipc_comms_nodispatch( - cib_channel_ro); - - } else { - return cib_not_connected; - } - - if(native->command_channel == NULL) { - crm_debug("Connection to command channel failed"); - rc = cib_connection; - - } else if(native->command_channel->ch_status != IPC_CONNECT) { - crm_err("Connection may have succeeded," - " but authentication to command channel failed"); - rc = cib_authentication; - } - - if(rc == cib_ok) { - rc = get_channel_token(native->command_channel, &uuid_ticket); - if(rc == cib_ok) { - native->token = uuid_ticket; - uuid_ticket = NULL; - } - } - - native->callback_channel = init_client_ipc_comms_nodispatch(cib_channel_callback); - if(native->callback_channel == NULL) { - crm_debug("Connection to callback channel failed"); - rc = cib_connection; - - } else if(native->callback_channel->ch_status != IPC_CONNECT) { - crm_err("Connection may have succeeded," - " but authentication to command channel failed"); - rc = cib_authentication; - } - - if(rc == cib_ok) { - native->callback_channel->send_queue->max_qlen = 500; - rc = get_channel_token(native->callback_channel, &uuid_ticket); - if(rc == cib_ok) { - crm_free(native->token); - native->token = uuid_ticket; - } - } - - if(rc == cib_ok) { - CRM_CHECK(native->token != NULL, ;); - hello = cib_create_op(0, native->token, CRM_OP_REGISTER, NULL, NULL, NULL, 0, NULL); - crm_xml_add(hello, F_CIB_CLIENTNAME, name); - - if(send_ipc_message(native->command_channel, hello) == FALSE) { - rc = cib_callback_register; - } - - free_xml(hello); - } - - if(rc == cib_ok) { - gboolean do_mainloop = TRUE; - if(async_fd != NULL) { - do_mainloop = FALSE; - *async_fd = native->callback_channel->ops->get_recv_select_fd(native->callback_channel); - } - - if(sync_fd != NULL) { - do_mainloop = FALSE; - *sync_fd = native->callback_channel->ops->get_send_select_fd(native->callback_channel); - } - - if(do_mainloop) { - crm_debug_4("Connecting callback channel"); - native->callback_source = G_main_add_IPC_Channel( - G_PRIORITY_HIGH, native->callback_channel, FALSE, cib_native_dispatch, - cib, default_ipc_connection_destroy); - - if(native->callback_source == NULL) { - crm_err("Callback source not recorded"); - rc = cib_connection; - } - } - } - - if(rc == cib_ok) { + int rc = cib_ok; + xmlNode *hello = NULL; + char *uuid_ticket = NULL; + cib_native_opaque_t *native = cib->variant_opaque; + + crm_debug_4("Connecting command channel"); + + if (type == cib_command) { + cib->state = cib_connected_command; + native->command_channel = init_client_ipc_comms_nodispatch(cib_channel_rw); + + } else if (type == cib_query) { + cib->state = cib_connected_query; + native->command_channel = init_client_ipc_comms_nodispatch(cib_channel_ro); + + } else { + return cib_not_connected; + } + + if (native->command_channel == NULL) { + crm_debug("Connection to command channel failed"); + rc = cib_connection; + + } else if (native->command_channel->ch_status != IPC_CONNECT) { + crm_err("Connection may have succeeded," " but authentication to command channel failed"); + rc = cib_authentication; + } + + if (rc == cib_ok) { + rc = get_channel_token(native->command_channel, &uuid_ticket); + if (rc == cib_ok) { + native->token = uuid_ticket; + uuid_ticket = NULL; + } + } + + native->callback_channel = init_client_ipc_comms_nodispatch(cib_channel_callback); + if (native->callback_channel == NULL) { + crm_debug("Connection to callback channel failed"); + rc = cib_connection; + + } else if (native->callback_channel->ch_status != IPC_CONNECT) { + crm_err("Connection may have succeeded," " but authentication to command channel failed"); + rc = cib_authentication; + } + + if (rc == cib_ok) { + native->callback_channel->send_queue->max_qlen = 500; + rc = get_channel_token(native->callback_channel, &uuid_ticket); + if (rc == cib_ok) { + crm_free(native->token); + native->token = uuid_ticket; + } + } + + if (rc == cib_ok) { + CRM_CHECK(native->token != NULL,; + ); + hello = cib_create_op(0, native->token, CRM_OP_REGISTER, NULL, NULL, NULL, 0, NULL); + crm_xml_add(hello, F_CIB_CLIENTNAME, name); + + if (send_ipc_message(native->command_channel, hello) == FALSE) { + rc = cib_callback_register; + } + + free_xml(hello); + } + + if (rc == cib_ok) { + gboolean do_mainloop = TRUE; + + if (async_fd != NULL) { + do_mainloop = FALSE; + *async_fd = native->callback_channel->ops->get_recv_select_fd(native->callback_channel); + } + + if (sync_fd != NULL) { + do_mainloop = FALSE; + *sync_fd = native->callback_channel->ops->get_send_select_fd(native->callback_channel); + } + + if (do_mainloop) { + crm_debug_4("Connecting callback channel"); + native->callback_source = + G_main_add_IPC_Channel(G_PRIORITY_HIGH, native->callback_channel, FALSE, + cib_native_dispatch, cib, default_ipc_connection_destroy); + + if (native->callback_source == NULL) { + crm_err("Callback source not recorded"); + rc = cib_connection; + } + } + } + + if (rc == cib_ok) { #if HAVE_MSGFROMIPC_TIMEOUT - cib->call_timeout = MAX_IPC_DELAY; + cib->call_timeout = MAX_IPC_DELAY; #endif - crm_debug("Connection to CIB successful"); - return cib_ok; - } + crm_debug("Connection to CIB successful"); + return cib_ok; + } - crm_debug("Connection to CIB failed: %s", cib_error2string(rc)); - cib_native_signoff(cib); - return rc; + crm_debug("Connection to CIB failed: %s", cib_error2string(rc)); + cib_native_signoff(cib); + return rc; } - + int -cib_native_signoff(cib_t* cib) +cib_native_signoff(cib_t * cib) { - cib_native_opaque_t *native = cib->variant_opaque; - - crm_debug("Signing out of the CIB Service"); - - /* close channels */ - if (native->command_channel != NULL) { - native->command_channel->ops->destroy( - native->command_channel); - native->command_channel = NULL; - } - - if (native->callback_source != NULL) { - G_main_del_IPC_Channel(native->callback_source); - native->callback_source = NULL; - } - - if (native->callback_channel != NULL) { + cib_native_opaque_t *native = cib->variant_opaque; + + crm_debug("Signing out of the CIB Service"); + + /* close channels */ + if (native->command_channel != NULL) { + native->command_channel->ops->destroy(native->command_channel); + native->command_channel = NULL; + } + + if (native->callback_source != NULL) { + G_main_del_IPC_Channel(native->callback_source); + native->callback_source = NULL; + } + + if (native->callback_channel != NULL) { #ifdef BUG - native->callback_channel->ops->destroy( - native->callback_channel); + native->callback_channel->ops->destroy(native->callback_channel); #endif - native->callback_channel = NULL; - } + native->callback_channel = NULL; + } - cib->state = cib_disconnected; - cib->type = cib_none; + cib->state = cib_disconnected; + cib->type = cib_none; - return cib_ok; + return cib_ok; } int -cib_native_free (cib_t* cib) +cib_native_free(cib_t * cib) { - int rc = cib_ok; - - if(cib->state != cib_disconnected) { - rc = cib_native_signoff(cib); - } - - if(cib->state == cib_disconnected) { - cib_native_opaque_t *native = cib->variant_opaque; - crm_free(native->token); - crm_free(cib->variant_opaque); - crm_free(cib->cmds); - crm_free(cib); - } - - return rc; + int rc = cib_ok; + + if (cib->state != cib_disconnected) { + rc = cib_native_signoff(cib); + } + + if (cib->state == cib_disconnected) { + cib_native_opaque_t *native = cib->variant_opaque; + + crm_free(native->token); + crm_free(cib->variant_opaque); + crm_free(cib->cmds); + crm_free(cib); + } + + return rc; } IPC_Channel * -cib_native_channel(cib_t* cib) +cib_native_channel(cib_t * cib) { - cib_native_opaque_t *native = NULL; - if(cib == NULL) { - crm_err("Missing cib object"); - return NULL; - } - - native = cib->variant_opaque; - - if(native != NULL) { - return native->callback_channel; - } - - crm_err("couldnt find variant specific data in %p", cib); - return NULL; + cib_native_opaque_t *native = NULL; + + if (cib == NULL) { + crm_err("Missing cib object"); + return NULL; + } + + native = cib->variant_opaque; + + if (native != NULL) { + return native->callback_channel; + } + + crm_err("couldnt find variant specific data in %p", cib); + return NULL; } int -cib_native_inputfd(cib_t* cib) +cib_native_inputfd(cib_t * cib) { - IPC_Channel *ch = cib_native_channel(cib); - return ch->ops->get_recv_select_fd(ch); + IPC_Channel *ch = cib_native_channel(cib); + + return ch->ops->get_recv_select_fd(ch); } static gboolean timer_expired = FALSE; + #ifndef HAVE_MSGFROMIPC_TIMEOUT static struct timer_rec_s sync_timer; -static gboolean cib_timeout_handler(gpointer data) +static gboolean +cib_timeout_handler(gpointer data) { struct timer_rec_s *timer = data; + timer_expired = TRUE; crm_err("Call %d timed out after %ds", timer->call_id, timer->timeout); /* Always return TRUE, never remove the handler * We do that after the while-loop in cib_native_perform_op() */ return TRUE; } #endif int -cib_native_perform_op( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options) +cib_native_perform_op(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options) { - return cib_native_perform_op_delegate(cib, op, host, section, - data, output_data, call_options, NULL); + return cib_native_perform_op_delegate(cib, op, host, section, + data, output_data, call_options, NULL); } int -cib_native_perform_op_delegate( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options, const char *user_name) +cib_native_perform_op_delegate(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options, + const char *user_name) { - int rc = HA_OK; - - xmlNode *op_msg = NULL; - xmlNode *op_reply = NULL; - - cib_native_opaque_t *native = cib->variant_opaque; - - if(cib->state == cib_disconnected) { - return cib_not_connected; - } - - if(output_data != NULL) { - *output_data = NULL; - } - - if(op == NULL) { - crm_err("No operation specified"); - return cib_operation; - } - - cib->call_id++; - /* prevent call_id from being negative (or zero) and conflicting - * with the cib_errors enum - * use 2 because we use it as (cib->call_id - 1) below - */ - if(cib->call_id < 1) { - cib->call_id = 1; - } - - CRM_CHECK(native->token != NULL, ;); - op_msg = cib_create_op( - cib->call_id, native->token, op, host, section, data, call_options, user_name); - if(op_msg == NULL) { - return cib_create_msg; - } - - crm_debug_3("Sending %s message to CIB service", op); - if(send_ipc_message(native->command_channel, op_msg) == FALSE) { - crm_err("Sending message to CIB service FAILED"); - free_xml(op_msg); - return cib_send_failed; - - } else { - crm_debug_3("Message sent"); - } - - free_xml(op_msg); - - if((call_options & cib_discard_reply)) { - crm_debug_3("Discarding reply"); - return cib_ok; - - } else if(!(call_options & cib_sync_call)) { - crm_debug_3("Async call, returning"); - CRM_CHECK(cib->call_id != 0, return cib_reply_failed); - - return cib->call_id; - } - - rc = IPC_OK; - crm_debug_3("Waiting for a syncronous reply"); + int rc = HA_OK; + + xmlNode *op_msg = NULL; + xmlNode *op_reply = NULL; + + cib_native_opaque_t *native = cib->variant_opaque; + + if (cib->state == cib_disconnected) { + return cib_not_connected; + } + + if (output_data != NULL) { + *output_data = NULL; + } + + if (op == NULL) { + crm_err("No operation specified"); + return cib_operation; + } + + cib->call_id++; + /* prevent call_id from being negative (or zero) and conflicting + * with the cib_errors enum + * use 2 because we use it as (cib->call_id - 1) below + */ + if (cib->call_id < 1) { + cib->call_id = 1; + } + + CRM_CHECK(native->token != NULL,; + ); + op_msg = + cib_create_op(cib->call_id, native->token, op, host, section, data, call_options, + user_name); + if (op_msg == NULL) { + return cib_create_msg; + } + + crm_debug_3("Sending %s message to CIB service", op); + if (send_ipc_message(native->command_channel, op_msg) == FALSE) { + crm_err("Sending message to CIB service FAILED"); + free_xml(op_msg); + return cib_send_failed; + + } else { + crm_debug_3("Message sent"); + } + + free_xml(op_msg); + + if ((call_options & cib_discard_reply)) { + crm_debug_3("Discarding reply"); + return cib_ok; + + } else if (!(call_options & cib_sync_call)) { + crm_debug_3("Async call, returning"); + CRM_CHECK(cib->call_id != 0, return cib_reply_failed); + + return cib->call_id; + } + + rc = IPC_OK; + crm_debug_3("Waiting for a syncronous reply"); #ifndef HAVE_MSGFROMIPC_TIMEOUT - sync_timer.ref = 0; - if(cib->call_timeout > 0) { - timer_expired = FALSE; - sync_timer.call_id = cib->call_id; - sync_timer.timeout = cib->call_timeout*1000; - sync_timer.ref = g_timeout_add( - sync_timer.timeout, cib_timeout_handler, &sync_timer); - } + sync_timer.ref = 0; + if (cib->call_timeout > 0) { + timer_expired = FALSE; + sync_timer.call_id = cib->call_id; + sync_timer.timeout = cib->call_timeout * 1000; + sync_timer.ref = g_timeout_add(sync_timer.timeout, cib_timeout_handler, &sync_timer); + } #endif - rc = cib_ok; - while(timer_expired == FALSE && IPC_ISRCONN(native->command_channel)) { - int reply_id = -1; - int msg_id = cib->call_id; - - op_reply = xmlfromIPC(native->command_channel, cib->call_timeout); - if(op_reply == NULL) { - rc = cib_remote_timeout; - break; - } - - crm_element_value_int(op_reply, F_CIB_CALLID, &reply_id); - if(reply_id <= 0) { - rc = cib_reply_failed; - break; - - } else if(reply_id == msg_id) { - crm_debug_3("Syncronous reply received"); - if(crm_element_value_int(op_reply, F_CIB_RC, &rc) != 0) { - rc = cib_return_code; - } - - if(output_data != NULL && is_not_set(call_options, cib_discard_reply)) { - xmlNode *tmp = get_message_xml(op_reply, F_CIB_CALLDATA); - if(tmp != NULL) { - *output_data = copy_xml(tmp); - } - } - - break; - - } else if(reply_id < msg_id) { - crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id); - crm_log_xml(LOG_MSG, "Old reply", op_reply); - - } else if((reply_id - 10000) > msg_id) { - /* wrap-around case */ - crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id); - crm_log_xml(LOG_MSG, "Old reply", op_reply); - - } else { - crm_err("Received a __future__ reply:" - " %d (wanted %d)", reply_id, msg_id); - } - free_xml(op_reply); - op_reply = NULL; - } - - if(IPC_ISRCONN(native->command_channel) == FALSE) { - crm_err("CIB disconnected: %d", native->command_channel->ch_status); - cib->state = cib_disconnected; - } - - if(op_reply == NULL && cib->state == cib_disconnected) { - rc = cib_not_connected; - - } else if(rc == cib_ok && op_reply == NULL) { - rc = cib_remote_timeout; - } - - switch(rc) { - case cib_ok: - case cib_not_master: - break; - - /* This is an internal value that clients do not and should not care about */ - case cib_diff_resync: - rc = cib_ok; - break; - - /* These indicate internal problems */ - case cib_return_code: - case cib_reply_failed: - case cib_master_timeout: - crm_err("Call failed: %s", cib_error2string(rc)); - if(op_reply) { - crm_log_xml(LOG_ERR, "Invalid reply", op_reply); - } - break; - - default: - if(safe_str_neq(op, CIB_OP_QUERY)) { - crm_warn("Call failed: %s", cib_error2string(rc)); - } - } - + rc = cib_ok; + while (timer_expired == FALSE && IPC_ISRCONN(native->command_channel)) { + int reply_id = -1; + int msg_id = cib->call_id; + + op_reply = xmlfromIPC(native->command_channel, cib->call_timeout); + if (op_reply == NULL) { + rc = cib_remote_timeout; + break; + } + + crm_element_value_int(op_reply, F_CIB_CALLID, &reply_id); + if (reply_id <= 0) { + rc = cib_reply_failed; + break; + + } else if (reply_id == msg_id) { + crm_debug_3("Syncronous reply received"); + if (crm_element_value_int(op_reply, F_CIB_RC, &rc) != 0) { + rc = cib_return_code; + } + + if (output_data != NULL && is_not_set(call_options, cib_discard_reply)) { + xmlNode *tmp = get_message_xml(op_reply, F_CIB_CALLDATA); + + if (tmp != NULL) { + *output_data = copy_xml(tmp); + } + } + + break; + + } else if (reply_id < msg_id) { + crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id); + crm_log_xml(LOG_MSG, "Old reply", op_reply); + + } else if ((reply_id - 10000) > msg_id) { + /* wrap-around case */ + crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id); + crm_log_xml(LOG_MSG, "Old reply", op_reply); + + } else { + crm_err("Received a __future__ reply:" " %d (wanted %d)", reply_id, msg_id); + } + free_xml(op_reply); + op_reply = NULL; + } + + if (IPC_ISRCONN(native->command_channel) == FALSE) { + crm_err("CIB disconnected: %d", native->command_channel->ch_status); + cib->state = cib_disconnected; + } + + if (op_reply == NULL && cib->state == cib_disconnected) { + rc = cib_not_connected; + + } else if (rc == cib_ok && op_reply == NULL) { + rc = cib_remote_timeout; + } + + switch (rc) { + case cib_ok: + case cib_not_master: + break; + + /* This is an internal value that clients do not and should not care about */ + case cib_diff_resync: + rc = cib_ok; + break; + + /* These indicate internal problems */ + case cib_return_code: + case cib_reply_failed: + case cib_master_timeout: + crm_err("Call failed: %s", cib_error2string(rc)); + if (op_reply) { + crm_log_xml(LOG_ERR, "Invalid reply", op_reply); + } + break; + + default: + if (safe_str_neq(op, CIB_OP_QUERY)) { + crm_warn("Call failed: %s", cib_error2string(rc)); + } + } + #ifndef HAVE_MSGFROMIPC_TIMEOUT - if(sync_timer.ref > 0) { - g_source_remove(sync_timer.ref); - sync_timer.ref = 0; - } + if (sync_timer.ref > 0) { + g_source_remove(sync_timer.ref); + sync_timer.ref = 0; + } #endif - - free_xml(op_reply); - return rc; + + free_xml(op_reply); + return rc; } gboolean -cib_native_msgready(cib_t* cib) +cib_native_msgready(cib_t * cib) { - cib_native_opaque_t *native = NULL; - - if (cib == NULL) { - crm_err("No CIB!"); - return FALSE; - } - - native = cib->variant_opaque; - - if(native->command_channel != NULL) { - /* drain the channel */ - IPC_Channel *cmd_ch = native->command_channel; - xmlNode *cmd_msg = NULL; - while(cmd_ch->ch_status != IPC_DISCONNECT - && cmd_ch->ops->is_message_pending(cmd_ch)) { - /* this will happen when the CIB exited from beneath us */ - cmd_msg = xmlfromIPC(cmd_ch, MAX_IPC_DELAY); - free_xml(cmd_msg); - } - - } else { - crm_err("No command channel"); - } - - if(native->callback_channel == NULL) { - crm_err("No callback channel"); - return FALSE; - - } else if(native->callback_channel->ch_status == IPC_DISCONNECT) { - crm_info("Lost connection to the CIB service [%d].", - native->callback_channel->farside_pid); - return FALSE; - - } else if(native->callback_channel->ops->is_message_pending( - native->callback_channel)) { - crm_debug_4("Message pending on command channel [%d]", - native->callback_channel->farside_pid); - return TRUE; - } - - crm_debug_3("No message pending"); - return FALSE; + cib_native_opaque_t *native = NULL; + + if (cib == NULL) { + crm_err("No CIB!"); + return FALSE; + } + + native = cib->variant_opaque; + + if (native->command_channel != NULL) { + /* drain the channel */ + IPC_Channel *cmd_ch = native->command_channel; + xmlNode *cmd_msg = NULL; + + while (cmd_ch->ch_status != IPC_DISCONNECT && cmd_ch->ops->is_message_pending(cmd_ch)) { + /* this will happen when the CIB exited from beneath us */ + cmd_msg = xmlfromIPC(cmd_ch, MAX_IPC_DELAY); + free_xml(cmd_msg); + } + + } else { + crm_err("No command channel"); + } + + if (native->callback_channel == NULL) { + crm_err("No callback channel"); + return FALSE; + + } else if (native->callback_channel->ch_status == IPC_DISCONNECT) { + crm_info("Lost connection to the CIB service [%d].", native->callback_channel->farside_pid); + return FALSE; + + } else if (native->callback_channel->ops->is_message_pending(native->callback_channel)) { + crm_debug_4("Message pending on command channel [%d]", + native->callback_channel->farside_pid); + return TRUE; + } + + crm_debug_3("No message pending"); + return FALSE; } int -cib_native_rcvmsg(cib_t* cib, int blocking) +cib_native_rcvmsg(cib_t * cib, int blocking) { - const char *type = NULL; - xmlNode* msg = NULL; - cib_native_opaque_t *native = NULL; - - if (cib == NULL) { - crm_err("No CIB!"); - return FALSE; - } - - native = cib->variant_opaque; - - /* if it is not blocking mode and no message in the channel, return */ - if (blocking == 0 && cib_native_msgready(cib) == FALSE) { - crm_debug_3("No message ready and non-blocking..."); - return 0; - - } else if (cib_native_msgready(cib) == FALSE) { - crm_debug("Waiting for message from CIB service..."); - if(native->callback_channel == NULL) { - return -1; - - } else if(native->callback_channel->ch_status != IPC_CONNECT) { - return -2; - - } else if(native->command_channel - && native->command_channel->ch_status != IPC_CONNECT){ - return -3; - } - native->callback_channel->ops->waitin(native->callback_channel); - } - - /* IPC_INTR is not a factor here */ - msg = xmlfromIPC(native->callback_channel, MAX_IPC_DELAY); - if (msg == NULL) { - crm_warn("Received a NULL msg from CIB service."); - return 0; - } - - /* do callbacks */ - type = crm_element_value(msg, F_TYPE); - crm_debug_4("Activating %s callbacks...", type); - - if(safe_str_eq(type, T_CIB)) { - cib_native_callback(cib, msg, 0, 0); - - } else if(safe_str_eq(type, T_CIB_NOTIFY)) { - g_list_foreach(cib->notify_list, cib_native_notify, msg); - - } else { - crm_err("Unknown message type: %s", type); - } - - free_xml(msg); - - return 1; + const char *type = NULL; + xmlNode *msg = NULL; + cib_native_opaque_t *native = NULL; + + if (cib == NULL) { + crm_err("No CIB!"); + return FALSE; + } + + native = cib->variant_opaque; + + /* if it is not blocking mode and no message in the channel, return */ + if (blocking == 0 && cib_native_msgready(cib) == FALSE) { + crm_debug_3("No message ready and non-blocking..."); + return 0; + + } else if (cib_native_msgready(cib) == FALSE) { + crm_debug("Waiting for message from CIB service..."); + if (native->callback_channel == NULL) { + return -1; + + } else if (native->callback_channel->ch_status != IPC_CONNECT) { + return -2; + + } else if (native->command_channel && native->command_channel->ch_status != IPC_CONNECT) { + return -3; + } + native->callback_channel->ops->waitin(native->callback_channel); + } + + /* IPC_INTR is not a factor here */ + msg = xmlfromIPC(native->callback_channel, MAX_IPC_DELAY); + if (msg == NULL) { + crm_warn("Received a NULL msg from CIB service."); + return 0; + } + + /* do callbacks */ + type = crm_element_value(msg, F_TYPE); + crm_debug_4("Activating %s callbacks...", type); + + if (safe_str_eq(type, T_CIB)) { + cib_native_callback(cib, msg, 0, 0); + + } else if (safe_str_eq(type, T_CIB_NOTIFY)) { + g_list_foreach(cib->notify_list, cib_native_notify, msg); + + } else { + crm_err("Unknown message type: %s", type); + } + + free_xml(msg); + + return 1; } gboolean -cib_native_dispatch(IPC_Channel *channel, gpointer user_data) +cib_native_dispatch(IPC_Channel * channel, gpointer user_data) { cib_t *cib = user_data; cib_native_opaque_t *native = NULL; gboolean stay_connected = TRUE; - + CRM_CHECK(cib != NULL, return FALSE); - + native = cib->variant_opaque; CRM_CHECK(native->callback_channel == channel, return FALSE); - - while(cib_native_msgready(cib)) { - /* invoke the callbacks but dont block */ - int rc = cib_native_rcvmsg(cib, 0); - if( rc < 0) { - crm_err("Message acquisition failed: %d", rc); - break; - - } else if(rc == 0) { - break; - } - } - - if(native->callback_channel - && native->callback_channel->ch_status != IPC_CONNECT) { - crm_crit("Lost connection to the CIB service [%d/callback].", - channel->farside_pid); - native->callback_source = NULL; - stay_connected = FALSE; - } - - if(native->command_channel - && native->command_channel->ch_status != IPC_CONNECT) { - crm_crit("Lost connection to the CIB service [%d/command].", - channel->farside_pid); - native->callback_source = NULL; - stay_connected = FALSE; + + while (cib_native_msgready(cib)) { + /* invoke the callbacks but dont block */ + int rc = cib_native_rcvmsg(cib, 0); + + if (rc < 0) { + crm_err("Message acquisition failed: %d", rc); + break; + + } else if (rc == 0) { + break; + } + } + + if (native->callback_channel && native->callback_channel->ch_status != IPC_CONNECT) { + crm_crit("Lost connection to the CIB service [%d/callback].", channel->farside_pid); + native->callback_source = NULL; + stay_connected = FALSE; + } + + if (native->command_channel && native->command_channel->ch_status != IPC_CONNECT) { + crm_crit("Lost connection to the CIB service [%d/command].", channel->farside_pid); + native->callback_source = NULL; + stay_connected = FALSE; } return stay_connected; } static void default_cib_connection_destroy(gpointer user_data) { cib_t *cib = user_data; + cib->state = cib_disconnected; } -int cib_native_set_connection_dnotify( - cib_t *cib, void (*dnotify)(gpointer user_data)) +int +cib_native_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data)) { - cib_native_opaque_t *native = NULL; - - if (cib == NULL) { - crm_err("No CIB!"); - return FALSE; - } - - native = cib->variant_opaque; - - if(dnotify == NULL) { - crm_warn("Setting dnotify back to default value"); - set_IPC_Channel_dnotify( - native->callback_source, default_cib_connection_destroy); - - } else { - crm_debug_3("Setting dnotify"); - set_IPC_Channel_dnotify(native->callback_source, dnotify); - } - return cib_ok; + cib_native_opaque_t *native = NULL; + + if (cib == NULL) { + crm_err("No CIB!"); + return FALSE; + } + + native = cib->variant_opaque; + + if (dnotify == NULL) { + crm_warn("Setting dnotify back to default value"); + set_IPC_Channel_dnotify(native->callback_source, default_cib_connection_destroy); + + } else { + crm_debug_3("Setting dnotify"); + set_IPC_Channel_dnotify(native->callback_source, dnotify); + } + return cib_ok; } int -cib_native_register_notification(cib_t* cib, const char *callback, int enabled) +cib_native_register_notification(cib_t * cib, const char *callback, int enabled) { - xmlNode *notify_msg = create_xml_node(NULL, "cib-callback"); - cib_native_opaque_t *native = cib->variant_opaque; - - if(cib->state != cib_disconnected) { - crm_xml_add(notify_msg, F_CIB_OPERATION, T_CIB_NOTIFY); - crm_xml_add(notify_msg, F_CIB_NOTIFY_TYPE, callback); - crm_xml_add_int(notify_msg, F_CIB_NOTIFY_ACTIVATE, enabled); - send_ipc_message(native->callback_channel, notify_msg); - } - - free_xml(notify_msg); - return cib_ok; -} + xmlNode *notify_msg = create_xml_node(NULL, "cib-callback"); + cib_native_opaque_t *native = cib->variant_opaque; + + if (cib->state != cib_disconnected) { + crm_xml_add(notify_msg, F_CIB_OPERATION, T_CIB_NOTIFY); + crm_xml_add(notify_msg, F_CIB_NOTIFY_TYPE, callback); + crm_xml_add_int(notify_msg, F_CIB_NOTIFY_ACTIVATE, enabled); + send_ipc_message(native->callback_channel, notify_msg); + } + free_xml(notify_msg); + return cib_ok; +} diff --git a/lib/cib/cib_ops.c b/lib/cib/cib_ops.c index a8d1101c76..b0d74a11b9 100644 --- a/lib/cib/cib_ops.c +++ b/lib/cib/cib_ops.c @@ -1,1010 +1,996 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 -enum cib_errors -cib_process_query( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; enum cib_errors result = cib_ok; - - crm_debug_2("Processing \"%s\" event for section=%s", - op, crm_str(section)); - if(options & cib_xpath) { - return cib_process_xpath(op, options, section, req, input, - existing_cib, result_cib, answer); + crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); + + if (options & cib_xpath) { + return cib_process_xpath(op, options, section, req, input, + existing_cib, result_cib, answer); } CRM_CHECK(*answer == NULL, free_xml(*answer)); *answer = NULL; - + if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { - section = NULL; + section = NULL; } obj_root = get_object_root(section, existing_cib); - - if(obj_root == NULL) { - result = cib_NOTEXISTS; + + if (obj_root == NULL) { + result = cib_NOTEXISTS; } else { - *answer = obj_root; + *answer = obj_root; } - if(result == cib_ok && *answer == NULL) { - crm_err("Error creating query response"); - result = cib_output_data; + if (result == cib_ok && *answer == NULL) { + crm_err("Error creating query response"); + result = cib_output_data; } - + return result; } -enum cib_errors -cib_process_erase( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_erase(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event", op); *answer = NULL; free_xml(*result_cib); *result_cib = createEmptyCib(); - copy_in_properties(*result_cib, existing_cib); + copy_in_properties(*result_cib, existing_cib); cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE); - + return result; } -enum cib_errors -cib_process_upgrade( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { int rc = 0; int new_version = 0; int current_version = 0; const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);; *answer = NULL; crm_debug_2("Processing \"%s\" event", op); - - if(value != NULL) { - current_version = get_schema_version(value); + + if (value != NULL) { + current_version = get_schema_version(value); } rc = update_validation(result_cib, &new_version, TRUE, TRUE); - if(new_version > current_version) { - return cib_ok; + if (new_version > current_version) { + return cib_ok; } - + return rc; } -enum cib_errors -cib_process_bump( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_bump(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event for epoch=%s", - op, crm_str(crm_element_value(existing_cib, XML_ATTR_GENERATION))); - + op, crm_str(crm_element_value(existing_cib, XML_ATTR_GENERATION))); + *answer = NULL; cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE); - + return result; } - -enum cib_errors -cib_update_counter(xmlNode *xml_obj, const char *field, gboolean reset) +enum cib_errors +cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset) { char *new_value = NULL; char *old_value = NULL; - int int_value = -1; - - if(reset == FALSE && crm_element_value(xml_obj, field) != NULL) { - old_value = crm_element_value_copy(xml_obj, field); - } - if(old_value != NULL) { - crm_malloc0(new_value, 128); - int_value = atoi(old_value); - sprintf(new_value, "%d", ++int_value); + int int_value = -1; + + if (reset == FALSE && crm_element_value(xml_obj, field) != NULL) { + old_value = crm_element_value_copy(xml_obj, field); + } + if (old_value != NULL) { + crm_malloc0(new_value, 128); + int_value = atoi(old_value); + sprintf(new_value, "%d", ++int_value); } else { - new_value = crm_strdup("1"); + new_value = crm_strdup("1"); } - crm_debug_4("%s %d(%s)->%s", - field, int_value, crm_str(old_value), crm_str(new_value)); + crm_debug_4("%s %d(%s)->%s", field, int_value, crm_str(old_value), crm_str(new_value)); crm_xml_add(xml_obj, field, new_value); crm_free(new_value); crm_free(old_value); return cib_ok; } -enum cib_errors -cib_process_replace( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_replace(const char *op, int options, const char *section, xmlNode * req, + xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, + xmlNode ** answer) { const char *tag = NULL; - gboolean verbose = FALSE; + gboolean verbose = FALSE; enum cib_errors result = cib_ok; - - crm_debug_2("Processing \"%s\" event for section=%s", - op, crm_str(section)); - if(options & cib_xpath) { - return cib_process_xpath(op, options, section, req, input, - existing_cib, result_cib, answer); + crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); + + if (options & cib_xpath) { + return cib_process_xpath(op, options, section, req, input, + existing_cib, result_cib, answer); } *answer = NULL; if (input == NULL) { - return cib_NOOBJECT; + return cib_NOOBJECT; } tag = crm_element_name(input); if (options & cib_verbose) { - verbose = TRUE; - } - if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { - section = NULL; - - } else if(safe_str_eq(tag, section)) { - section = NULL; - } - - if(safe_str_eq(tag, XML_TAG_CIB)) { - int updates = 0; - int epoch = 0; - int admin_epoch = 0; - - int replace_updates = 0; - int replace_epoch = 0; - int replace_admin_epoch = 0; - const char *reason = NULL; - - cib_version_details( - existing_cib, &admin_epoch, &epoch, &updates); - cib_version_details(input, &replace_admin_epoch, - &replace_epoch, &replace_updates); - - if(replace_admin_epoch < admin_epoch) { - reason = XML_ATTR_GENERATION_ADMIN; - - } else if(replace_admin_epoch > admin_epoch) { - /* no more checks */ - - } else if(replace_epoch < epoch) { - reason = XML_ATTR_GENERATION; - - } else if(replace_epoch > epoch) { - /* no more checks */ - - } else if(replace_updates < updates) { - reason = XML_ATTR_NUMUPDATES; - } - - if(reason != NULL) { - crm_warn("Replacement %d.%d.%d not applied to %d.%d.%d:" - " current %s is greater than the replacement", - replace_admin_epoch, replace_epoch, - replace_updates, admin_epoch, epoch, updates, - reason); - result = cib_old_data; - } - - free_xml(*result_cib); - *result_cib = copy_xml(input); - + verbose = TRUE; + } + if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { + section = NULL; + + } else if (safe_str_eq(tag, section)) { + section = NULL; + } + + if (safe_str_eq(tag, XML_TAG_CIB)) { + int updates = 0; + int epoch = 0; + int admin_epoch = 0; + + int replace_updates = 0; + int replace_epoch = 0; + int replace_admin_epoch = 0; + const char *reason = NULL; + + cib_version_details(existing_cib, &admin_epoch, &epoch, &updates); + cib_version_details(input, &replace_admin_epoch, &replace_epoch, &replace_updates); + + if (replace_admin_epoch < admin_epoch) { + reason = XML_ATTR_GENERATION_ADMIN; + + } else if (replace_admin_epoch > admin_epoch) { + /* no more checks */ + + } else if (replace_epoch < epoch) { + reason = XML_ATTR_GENERATION; + + } else if (replace_epoch > epoch) { + /* no more checks */ + + } else if (replace_updates < updates) { + reason = XML_ATTR_NUMUPDATES; + } + + if (reason != NULL) { + crm_warn("Replacement %d.%d.%d not applied to %d.%d.%d:" + " current %s is greater than the replacement", + replace_admin_epoch, replace_epoch, + replace_updates, admin_epoch, epoch, updates, reason); + result = cib_old_data; + } + + free_xml(*result_cib); + *result_cib = copy_xml(input); + } else { - xmlNode *obj_root = NULL; - gboolean ok = TRUE; - obj_root = get_object_root(section, *result_cib); - ok = replace_xml_child(NULL, obj_root, input, FALSE); - if(ok == FALSE) { - crm_debug_2("No matching object to replace"); - result = cib_NOTEXISTS; - } + xmlNode *obj_root = NULL; + gboolean ok = TRUE; + + obj_root = get_object_root(section, *result_cib); + ok = replace_xml_child(NULL, obj_root, input, FALSE); + if (ok == FALSE) { + crm_debug_2("No matching object to replace"); + result = cib_NOTEXISTS; + } } return result; } -enum cib_errors -cib_process_delete( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; + crm_debug_2("Processing \"%s\" event", op); - if(options & cib_xpath) { - return cib_process_xpath(op, options, section, req, input, - existing_cib, result_cib, answer); + if (options & cib_xpath) { + return cib_process_xpath(op, options, section, req, input, + existing_cib, result_cib, answer); } - if(input == NULL) { - crm_err("Cannot perform modification with no data"); - return cib_NOOBJECT; + if (input == NULL) { + crm_err("Cannot perform modification with no data"); + return cib_NOOBJECT; } - + obj_root = get_object_root(section, *result_cib); - + crm_validate_data(input); crm_validate_data(*result_cib); - if(replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) { - crm_debug_2("No matching object to delete"); + if (replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) { + crm_debug_2("No matching object to delete"); } - + return cib_ok; } -enum cib_errors -cib_process_modify( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; + crm_debug_2("Processing \"%s\" event", op); - if(options & cib_xpath) { - return cib_process_xpath(op, options, section, req, input, - existing_cib, result_cib, answer); + if (options & cib_xpath) { + return cib_process_xpath(op, options, section, req, input, + existing_cib, result_cib, answer); } - if(input == NULL) { - crm_err("Cannot perform modification with no data"); - return cib_NOOBJECT; + if (input == NULL) { + crm_err("Cannot perform modification with no data"); + return cib_NOOBJECT; } - + obj_root = get_object_root(section, *result_cib); - + crm_validate_data(input); crm_validate_data(*result_cib); - if(obj_root == NULL) { - xmlNode *tmp_section = NULL; - const char *path = get_object_parent(section); - if(path == NULL) { - return cib_bad_section; - } + if (obj_root == NULL) { + xmlNode *tmp_section = NULL; + const char *path = get_object_parent(section); + + if (path == NULL) { + return cib_bad_section; + } - tmp_section = create_xml_node(NULL, section); - cib_process_xpath( - CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer); - free_xml(tmp_section); - - obj_root = get_object_root(section, *result_cib); + tmp_section = create_xml_node(NULL, section); + cib_process_xpath(CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer); + free_xml(tmp_section); + + obj_root = get_object_root(section, *result_cib); } CRM_CHECK(obj_root != NULL, return cib_unknown); - - if(update_xml_child(obj_root, input) == FALSE) { - if(options & cib_can_create) { - add_node_copy(obj_root, input); - } else { - return cib_NOTEXISTS; - } - } - + + if (update_xml_child(obj_root, input) == FALSE) { + if (options & cib_can_create) { + add_node_copy(obj_root, input); + } else { + return cib_NOTEXISTS; + } + } + return cib_ok; } static int -update_cib_object(xmlNode *parent, xmlNode *update) +update_cib_object(xmlNode * parent, xmlNode * update) { int result = cib_ok; xmlNode *target = NULL; xmlNode *a_child = NULL; const char *replace = NULL; const char *object_id = NULL; const char *object_name = NULL; CRM_CHECK(update != NULL, return cib_NOOBJECT); CRM_CHECK(parent != NULL, return cib_NOPARENT); object_name = crm_element_name(update); CRM_CHECK(object_name != NULL, return cib_NOOBJECT); object_id = ID(update); - crm_debug_3("Processing: <%s id=%s>", - crm_str(object_name), crm_str(object_id)); - - if(object_id == NULL) { - /* placeholder object */ - target = find_xml_node(parent, object_name, FALSE); + crm_debug_3("Processing: <%s id=%s>", crm_str(object_name), crm_str(object_id)); + + if (object_id == NULL) { + /* placeholder object */ + target = find_xml_node(parent, object_name, FALSE); } else { - target = find_entity(parent, object_name, object_id); + target = find_entity(parent, object_name, object_id); } - if(target == NULL) { - target = create_xml_node(parent, object_name); - } + if (target == NULL) { + target = create_xml_node(parent, object_name); + } + + crm_debug_2("Found node <%s id=%s> to update", crm_str(object_name), crm_str(object_id)); - crm_debug_2("Found node <%s id=%s> to update", - crm_str(object_name), crm_str(object_id)); - replace = crm_element_value(update, XML_CIB_ATTR_REPLACE); - if(replace != NULL) { - xmlNode *remove = NULL; - int last = 0, lpc = 0, len = 0; - - len = strlen(replace); - while(lpc <= len) { - if(replace[lpc] == ',' || replace[lpc] == 0) { - char *replace_item = NULL; - if ( last == lpc ) { - /* nothing to do */ - last = lpc+1; - goto incr; - } - - crm_malloc0(replace_item, lpc - last + 1); - strncpy(replace_item, replace+last, lpc-last); - - remove = find_xml_node(target, replace_item, FALSE); - if(remove != NULL) { - crm_debug_3("Replacing node <%s> in <%s>", - replace_item, crm_element_name(target)); - zap_xml_from_parent(target, remove); - } - crm_free(replace_item); - last = lpc+1; - } - incr: - lpc++; - } - xml_remove_prop(update, XML_CIB_ATTR_REPLACE); - xml_remove_prop(target, XML_CIB_ATTR_REPLACE); - } - + if (replace != NULL) { + xmlNode *remove = NULL; + int last = 0, lpc = 0, len = 0; + + len = strlen(replace); + while (lpc <= len) { + if (replace[lpc] == ',' || replace[lpc] == 0) { + char *replace_item = NULL; + + if (last == lpc) { + /* nothing to do */ + last = lpc + 1; + goto incr; + } + + crm_malloc0(replace_item, lpc - last + 1); + strncpy(replace_item, replace + last, lpc - last); + + remove = find_xml_node(target, replace_item, FALSE); + if (remove != NULL) { + crm_debug_3("Replacing node <%s> in <%s>", + replace_item, crm_element_name(target)); + zap_xml_from_parent(target, remove); + } + crm_free(replace_item); + last = lpc + 1; + } + incr: + lpc++; + } + xml_remove_prop(update, XML_CIB_ATTR_REPLACE); + xml_remove_prop(target, XML_CIB_ATTR_REPLACE); + } + copy_in_properties(target, update); - crm_debug_3("Processing children of <%s id=%s>", - crm_str(object_name), crm_str(object_id)); - - for(a_child = __xml_first_child(update); a_child != NULL; a_child = __xml_next(a_child)) { - int tmp_result = 0; - crm_debug_3("Updating child <%s id=%s>", - crm_element_name(a_child), ID(a_child)); - - tmp_result = update_cib_object(target, a_child); - - /* only the first error is likely to be interesting */ - if(tmp_result != cib_ok) { - crm_err("Error updating child <%s id=%s>", - crm_element_name(a_child), ID(a_child)); - - if(result == cib_ok) { - result = tmp_result; - } - } - } - - crm_debug_3("Finished with <%s id=%s>", - crm_str(object_name), crm_str(object_id)); + crm_debug_3("Processing children of <%s id=%s>", crm_str(object_name), crm_str(object_id)); + + for (a_child = __xml_first_child(update); a_child != NULL; a_child = __xml_next(a_child)) { + int tmp_result = 0; + + crm_debug_3("Updating child <%s id=%s>", crm_element_name(a_child), ID(a_child)); + + tmp_result = update_cib_object(target, a_child); + + /* only the first error is likely to be interesting */ + if (tmp_result != cib_ok) { + crm_err("Error updating child <%s id=%s>", crm_element_name(a_child), ID(a_child)); + + if (result == cib_ok) { + result = tmp_result; + } + } + } + + crm_debug_3("Finished with <%s id=%s>", crm_str(object_name), crm_str(object_id)); return result; } static int -add_cib_object(xmlNode *parent, xmlNode *new_obj) +add_cib_object(xmlNode * parent, xmlNode * new_obj) { enum cib_errors result = cib_ok; const char *object_name = NULL; const char *object_id = NULL; xmlNode *equiv_node = NULL; - - if(new_obj != NULL) { - object_name = crm_element_name(new_obj); + + if (new_obj != NULL) { + object_name = crm_element_name(new_obj); } object_id = crm_element_value(new_obj, XML_ATTR_ID); - crm_debug_3("Processing: <%s id=%s>", - crm_str(object_name), crm_str(object_id)); - - if(new_obj == NULL || object_name == NULL) { - result = cib_NOOBJECT; + crm_debug_3("Processing: <%s id=%s>", crm_str(object_name), crm_str(object_id)); - } else if(parent == NULL) { - result = cib_NOPARENT; + if (new_obj == NULL || object_name == NULL) { + result = cib_NOOBJECT; + + } else if (parent == NULL) { + result = cib_NOPARENT; + + } else if (object_id == NULL) { + /* placeholder object */ + equiv_node = find_xml_node(parent, object_name, FALSE); - } else 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) { - ; /* do nothing */ - - } else if(equiv_node != NULL) { - result = cib_EXISTS; + if (result != cib_ok) { + ; /* do nothing */ + + } else if (equiv_node != NULL) { + result = cib_EXISTS; } else { - result = update_cib_object(parent, new_obj); + result = update_cib_object(parent, new_obj); } return result; } - - -enum cib_errors -cib_process_create( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_create(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *failed = NULL; enum cib_errors result = cib_ok; xmlNode *update_section = NULL; - + crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); - if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { - section = NULL; + 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_CREATE, 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; } - - if(section == NULL) { - return cib_process_modify(op, options, section, req, input, existing_cib, result_cib, answer); + + if (section == NULL) { + return cib_process_modify(op, options, section, req, input, existing_cib, result_cib, + answer); } failed = create_xml_node(NULL, XML_TAG_FAILED); update_section = get_object_root(section, *result_cib); - if(safe_str_eq(crm_element_name(input), section)) { - xmlNode *a_child = NULL; - for(a_child = __xml_first_child(input); a_child != NULL; a_child = __xml_next(a_child)) { - result = add_cib_object(update_section, a_child); - if(update_results(failed, a_child, op, result)) { - break; - } - } + if (safe_str_eq(crm_element_name(input), section)) { + xmlNode *a_child = NULL; + + for (a_child = __xml_first_child(input); a_child != NULL; a_child = __xml_next(a_child)) { + result = add_cib_object(update_section, a_child); + if (update_results(failed, a_child, op, result)) { + break; + } + } } else { - result = add_cib_object(update_section, input); - update_results(failed, input, op, result); + result = add_cib_object(update_section, input); + update_results(failed, input, op, result); } - - if(xml_has_children(failed)) { - CRM_CHECK(result != cib_ok, result = cib_unknown); + + if (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; } -enum cib_errors -cib_process_diff( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_diff(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { unsigned int log_level = LOG_DEBUG; const char *reason = NULL; gboolean apply_diff = TRUE; enum cib_errors result = cib_ok; int this_updates = 0; - int this_epoch = 0; + int this_epoch = 0; int this_admin_epoch = 0; int diff_add_updates = 0; - int diff_add_epoch = 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_epoch = 0; int diff_del_admin_epoch = 0; crm_debug_2("Processing \"%s\" event", op); - cib_diff_version_details( - input, - &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, - &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); + cib_diff_version_details(input, + &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, + &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); crm_element_value_int(existing_cib, XML_ATTR_GENERATION, &this_epoch); crm_element_value_int(existing_cib, XML_ATTR_NUMUPDATES, &this_updates); crm_element_value_int(existing_cib, XML_ATTR_GENERATION_ADMIN, &this_admin_epoch); - if(this_epoch < 0) { this_epoch = 0; } - if(this_updates < 0) { this_updates = 0; } - if(this_admin_epoch < 0) { this_admin_epoch = 0; } - - if(diff_del_admin_epoch == diff_add_admin_epoch - && diff_del_epoch == diff_add_epoch - && diff_del_updates == diff_add_updates) { - if(options & cib_force_diff) { - apply_diff = FALSE; - log_level = LOG_ERR; - reason = "+ and - versions in the diff did not change in global update"; - crm_log_xml_warn(input, "Bad global update"); - - } else if(diff_add_admin_epoch == -1 && diff_add_epoch == -1 && diff_add_updates == -1) { - diff_add_epoch = this_epoch; - diff_add_updates = this_updates + 1; - diff_add_admin_epoch = this_admin_epoch; - diff_del_epoch = this_epoch; - diff_del_updates = this_updates; - diff_del_admin_epoch = this_admin_epoch; - - } else { - apply_diff = FALSE; - log_level = LOG_ERR; - reason = "+ and - versions in the diff did not change"; - log_cib_diff(LOG_ERR, input, __FUNCTION__); - } - } - - if(apply_diff && diff_del_admin_epoch > this_admin_epoch) { - result = cib_diff_resync; - apply_diff = FALSE; - log_level = LOG_INFO; - reason = "current \""XML_ATTR_GENERATION_ADMIN"\" is less than required"; - - } else if(apply_diff && diff_del_admin_epoch < this_admin_epoch) { - apply_diff = FALSE; - log_level = LOG_WARNING; - reason = "current \""XML_ATTR_GENERATION_ADMIN"\" is greater than required"; - - } else if(apply_diff && diff_del_epoch > this_epoch) { - result = cib_diff_resync; - apply_diff = FALSE; - log_level = LOG_INFO; - reason = "current \""XML_ATTR_GENERATION"\" is less than required"; - - } else if(apply_diff && diff_del_epoch < this_epoch) { - apply_diff = FALSE; - log_level = LOG_WARNING; - reason = "current \""XML_ATTR_GENERATION"\" is greater than required"; - - } else if(apply_diff && diff_del_updates > this_updates) { - result = cib_diff_resync; - apply_diff = FALSE; - log_level = LOG_INFO; - reason = "current \""XML_ATTR_NUMUPDATES"\" is less than required"; - - } else if(apply_diff && diff_del_updates < this_updates) { - apply_diff = FALSE; - log_level = LOG_WARNING; - reason = "current \""XML_ATTR_NUMUPDATES"\" is greater than required"; - } - - if(apply_diff) { - free_xml(*result_cib); - *result_cib = NULL; - if(apply_xml_diff(existing_cib, input, result_cib) == FALSE) { - log_level = LOG_NOTICE; - reason = "Failed application of an update diff"; - - if(options & cib_force_diff) { - result = cib_diff_resync; - } - } - } - - if(reason != NULL) { - do_crm_log( - log_level, - "Diff %d.%d.%d -> %d.%d.%d not applied to %d.%d.%d: %s", - diff_del_admin_epoch,diff_del_epoch,diff_del_updates, - diff_add_admin_epoch,diff_add_epoch,diff_add_updates, - this_admin_epoch,this_epoch,this_updates, reason); - - crm_log_xml_trace(input, "Discarded diff"); - if(result == cib_ok) { - result = cib_diff_failed; - } - - } else if(apply_diff) { - crm_debug_2("Diff %d.%d.%d -> %d.%d.%d was applied to %d.%d.%d", - diff_del_admin_epoch,diff_del_epoch,diff_del_updates, - diff_add_admin_epoch,diff_add_epoch,diff_add_updates, - this_admin_epoch,this_epoch,this_updates); - + if (this_epoch < 0) { + this_epoch = 0; + } + if (this_updates < 0) { + this_updates = 0; + } + if (this_admin_epoch < 0) { + this_admin_epoch = 0; + } + + if (diff_del_admin_epoch == diff_add_admin_epoch + && diff_del_epoch == diff_add_epoch && diff_del_updates == diff_add_updates) { + if (options & cib_force_diff) { + apply_diff = FALSE; + log_level = LOG_ERR; + reason = "+ and - versions in the diff did not change in global update"; + crm_log_xml_warn(input, "Bad global update"); + + } else if (diff_add_admin_epoch == -1 && diff_add_epoch == -1 && diff_add_updates == -1) { + diff_add_epoch = this_epoch; + diff_add_updates = this_updates + 1; + diff_add_admin_epoch = this_admin_epoch; + diff_del_epoch = this_epoch; + diff_del_updates = this_updates; + diff_del_admin_epoch = this_admin_epoch; + + } else { + apply_diff = FALSE; + log_level = LOG_ERR; + reason = "+ and - versions in the diff did not change"; + log_cib_diff(LOG_ERR, input, __FUNCTION__); + } + } + + if (apply_diff && diff_del_admin_epoch > this_admin_epoch) { + result = cib_diff_resync; + apply_diff = FALSE; + log_level = LOG_INFO; + reason = "current \"" XML_ATTR_GENERATION_ADMIN "\" is less than required"; + + } else if (apply_diff && diff_del_admin_epoch < this_admin_epoch) { + apply_diff = FALSE; + log_level = LOG_WARNING; + reason = "current \"" XML_ATTR_GENERATION_ADMIN "\" is greater than required"; + + } else if (apply_diff && diff_del_epoch > this_epoch) { + result = cib_diff_resync; + apply_diff = FALSE; + log_level = LOG_INFO; + reason = "current \"" XML_ATTR_GENERATION "\" is less than required"; + + } else if (apply_diff && diff_del_epoch < this_epoch) { + apply_diff = FALSE; + log_level = LOG_WARNING; + reason = "current \"" XML_ATTR_GENERATION "\" is greater than required"; + + } else if (apply_diff && diff_del_updates > this_updates) { + result = cib_diff_resync; + apply_diff = FALSE; + log_level = LOG_INFO; + reason = "current \"" XML_ATTR_NUMUPDATES "\" is less than required"; + + } else if (apply_diff && diff_del_updates < this_updates) { + apply_diff = FALSE; + log_level = LOG_WARNING; + reason = "current \"" XML_ATTR_NUMUPDATES "\" is greater than required"; + } + + if (apply_diff) { + free_xml(*result_cib); + *result_cib = NULL; + if (apply_xml_diff(existing_cib, input, result_cib) == FALSE) { + log_level = LOG_NOTICE; + reason = "Failed application of an update diff"; + + if (options & cib_force_diff) { + result = cib_diff_resync; + } + } + } + + if (reason != NULL) { + do_crm_log(log_level, + "Diff %d.%d.%d -> %d.%d.%d not applied to %d.%d.%d: %s", + diff_del_admin_epoch, diff_del_epoch, diff_del_updates, + diff_add_admin_epoch, diff_add_epoch, diff_add_updates, + this_admin_epoch, this_epoch, this_updates, reason); + + crm_log_xml_trace(input, "Discarded diff"); + if (result == cib_ok) { + result = cib_diff_failed; + } + + } else if (apply_diff) { + crm_debug_2("Diff %d.%d.%d -> %d.%d.%d was applied to %d.%d.%d", + diff_del_admin_epoch, diff_del_epoch, diff_del_updates, + diff_add_admin_epoch, diff_add_epoch, diff_add_updates, + this_admin_epoch, this_epoch, this_updates); + } return result; } gboolean -apply_cib_diff(xmlNode *old, xmlNode *diff, xmlNode **new) +apply_cib_diff(xmlNode * old, xmlNode * diff, xmlNode ** new) { gboolean result = TRUE; const char *value = NULL; int this_updates = 0; - int this_epoch = 0; + int this_epoch = 0; int this_admin_epoch = 0; int diff_add_updates = 0; - int diff_add_epoch = 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_epoch = 0; int diff_del_admin_epoch = 0; CRM_CHECK(diff != NULL, return FALSE); CRM_CHECK(old != NULL, return FALSE); - + value = crm_element_value(old, XML_ATTR_GENERATION_ADMIN); this_admin_epoch = crm_parse_int(value, "0"); - crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION_ADMIN, - this_admin_epoch, value); - + crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION_ADMIN, this_admin_epoch, value); + value = crm_element_value(old, XML_ATTR_GENERATION); this_epoch = crm_parse_int(value, "0"); crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION, this_epoch, value); - + value = crm_element_value(old, XML_ATTR_NUMUPDATES); this_updates = crm_parse_int(value, "0"); crm_debug_3("%s=%d (%s)", XML_ATTR_NUMUPDATES, this_updates, value); - - cib_diff_version_details( - diff, - &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, - &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); + + cib_diff_version_details(diff, + &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, + &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); value = NULL; - if(result && diff_del_admin_epoch != this_admin_epoch) { - value = XML_ATTR_GENERATION_ADMIN; - result = FALSE; - crm_debug_3("%s=%d", value, diff_del_admin_epoch); - - } else if(result && diff_del_epoch != this_epoch) { - value = XML_ATTR_GENERATION; - result = FALSE; - crm_debug_3("%s=%d", value, diff_del_epoch); - - } else if(result && diff_del_updates != this_updates) { - value = XML_ATTR_NUMUPDATES; - result = FALSE; - crm_debug_3("%s=%d", value, diff_del_updates); - } - - if(result) { - xmlNode *tmp = NULL; - xmlNode *diff_copy = copy_xml(diff); - - tmp = find_xml_node(diff_copy, "diff-removed", TRUE); - if(tmp != NULL) { - xml_remove_prop(tmp, XML_ATTR_GENERATION_ADMIN); - xml_remove_prop(tmp, XML_ATTR_GENERATION); - xml_remove_prop(tmp, XML_ATTR_NUMUPDATES); - } - - tmp = find_xml_node(diff_copy, "diff-added", TRUE); - if(tmp != NULL) { - xml_remove_prop(tmp, XML_ATTR_GENERATION_ADMIN); - xml_remove_prop(tmp, XML_ATTR_GENERATION); - xml_remove_prop(tmp, XML_ATTR_NUMUPDATES); - } - - result = apply_xml_diff(old, diff_copy, new); - free_xml(diff_copy); - + if (result && diff_del_admin_epoch != this_admin_epoch) { + value = XML_ATTR_GENERATION_ADMIN; + result = FALSE; + crm_debug_3("%s=%d", value, diff_del_admin_epoch); + + } else if (result && diff_del_epoch != this_epoch) { + value = XML_ATTR_GENERATION; + result = FALSE; + crm_debug_3("%s=%d", value, diff_del_epoch); + + } else if (result && diff_del_updates != this_updates) { + value = XML_ATTR_NUMUPDATES; + result = FALSE; + crm_debug_3("%s=%d", value, diff_del_updates); + } + + if (result) { + xmlNode *tmp = NULL; + xmlNode *diff_copy = copy_xml(diff); + + tmp = find_xml_node(diff_copy, "diff-removed", TRUE); + if (tmp != NULL) { + xml_remove_prop(tmp, XML_ATTR_GENERATION_ADMIN); + xml_remove_prop(tmp, XML_ATTR_GENERATION); + xml_remove_prop(tmp, XML_ATTR_NUMUPDATES); + } + + tmp = find_xml_node(diff_copy, "diff-added", TRUE); + if (tmp != NULL) { + xml_remove_prop(tmp, XML_ATTR_GENERATION_ADMIN); + xml_remove_prop(tmp, XML_ATTR_GENERATION); + xml_remove_prop(tmp, XML_ATTR_NUMUPDATES); + } + + result = apply_xml_diff(old, diff_copy, new); + free_xml(diff_copy); + } else { - crm_err("target and diff %s values didnt match", value); + crm_err("target and diff %s values didnt match", value); } - - + return result; } gboolean -cib_config_changed(xmlNode *last, xmlNode *next, xmlNode **diff) +cib_config_changed(xmlNode * last, xmlNode * next, xmlNode ** diff) { gboolean config_changes = FALSE; xmlXPathObject *xpathObj = NULL; CRM_ASSERT(diff != NULL); - if(last != NULL && next != NULL) { - *diff = diff_xml_object(last, next, FALSE); - } - if(*diff == NULL) { - goto done; - } - - xpathObj = xpath_search(*diff, "//"XML_CIB_TAG_CONFIGURATION); - if(xpathObj && xpathObj->nodesetval->nodeNr > 0) { - config_changes = TRUE; - goto done; - - } else if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - - xpathObj = xpath_search(*diff, "//"XML_TAG_DIFF_REMOVED"//"XML_TAG_CIB); - if(xpathObj) { - int lpc = 0, max = xpathObj->nodesetval->nodeNr; - for(lpc = 0; lpc < max; lpc++) { - xmlNode *top = getXpathResult(xpathObj, lpc); - if(crm_element_value(top, XML_ATTR_GENERATION) != NULL) { - config_changes = TRUE; - goto done; - } - if(crm_element_value(top, XML_ATTR_GENERATION_ADMIN) != NULL) { - config_changes = TRUE; - goto done; - } - - if(crm_element_value(top, XML_ATTR_VALIDATION) != NULL) { - config_changes = TRUE; - goto done; - } - if(crm_element_value(top, XML_ATTR_CRM_VERSION) != NULL) { - config_changes = TRUE; - goto done; - } - } + if (last != NULL && next != NULL) { + *diff = diff_xml_object(last, next, FALSE); + } + if (*diff == NULL) { + goto done; + } + + xpathObj = xpath_search(*diff, "//" XML_CIB_TAG_CONFIGURATION); + if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { + config_changes = TRUE; + goto done; + + } else if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + + xpathObj = xpath_search(*diff, "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_CIB); + if (xpathObj) { + int lpc = 0, max = xpathObj->nodesetval->nodeNr; + + for (lpc = 0; lpc < max; lpc++) { + xmlNode *top = getXpathResult(xpathObj, lpc); + + if (crm_element_value(top, XML_ATTR_GENERATION) != NULL) { + config_changes = TRUE; + goto done; + } + if (crm_element_value(top, XML_ATTR_GENERATION_ADMIN) != NULL) { + config_changes = TRUE; + goto done; + } + + if (crm_element_value(top, XML_ATTR_VALIDATION) != NULL) { + config_changes = TRUE; + goto done; + } + if (crm_element_value(top, XML_ATTR_CRM_VERSION) != NULL) { + config_changes = TRUE; + goto done; + } + } } done: - if(xpathObj) { - xmlXPathFreeObject(xpathObj); + if (xpathObj) { + xmlXPathFreeObject(xpathObj); } return config_changes; } xmlNode * -diff_cib_object(xmlNode *old_cib, xmlNode *new_cib, gboolean suppress) +diff_cib_object(xmlNode * old_cib, xmlNode * new_cib, gboolean suppress) { xmlNode *dest = NULL; xmlNode *src = NULL; const char *name = NULL; const char *value = NULL; xmlNode *diff = diff_xml_object(old_cib, new_cib, suppress); - + /* add complete version information */ src = old_cib; dest = find_xml_node(diff, "diff-removed", FALSE); - if(src != NULL && dest != NULL) { - name = XML_ATTR_GENERATION_ADMIN; - value = crm_element_value(src, name); - if(value == NULL) { - value = "0"; - } - crm_xml_add(dest, name, value); - - name = XML_ATTR_GENERATION; - value = crm_element_value(src, name); - if(value == NULL) { - value = "0"; - } - crm_xml_add(dest, name, value); - - name = XML_ATTR_NUMUPDATES; - value = crm_element_value(src, name); - if(value == NULL) { - value = "0"; - } - crm_xml_add(dest, name, value); - } - + if (src != NULL && dest != NULL) { + name = XML_ATTR_GENERATION_ADMIN; + value = crm_element_value(src, name); + if (value == NULL) { + value = "0"; + } + crm_xml_add(dest, name, value); + + name = XML_ATTR_GENERATION; + value = crm_element_value(src, name); + if (value == NULL) { + value = "0"; + } + crm_xml_add(dest, name, value); + + name = XML_ATTR_NUMUPDATES; + value = crm_element_value(src, name); + if (value == NULL) { + value = "0"; + } + crm_xml_add(dest, name, value); + } + src = new_cib; dest = find_xml_node(diff, "diff-added", FALSE); - if(src != NULL && dest != NULL) { - name = XML_ATTR_GENERATION_ADMIN; - value = crm_element_value(src, name); - if(value == NULL) { - value = "0"; - } - crm_xml_add(dest, name, value); - - name = XML_ATTR_GENERATION; - value = crm_element_value(src, name); - if(value == NULL) { - value = "0"; - } - crm_xml_add(dest, name, value); - - name = XML_ATTR_NUMUPDATES; - value = crm_element_value(src, name); - if(value == NULL) { - value = "0"; - } - crm_xml_add(dest, name, value); + if (src != NULL && dest != NULL) { + name = XML_ATTR_GENERATION_ADMIN; + value = crm_element_value(src, name); + if (value == NULL) { + value = "0"; + } + crm_xml_add(dest, name, value); + + name = XML_ATTR_GENERATION; + value = crm_element_value(src, name); + if (value == NULL) { + value = "0"; + } + crm_xml_add(dest, name, value); + + name = XML_ATTR_NUMUPDATES; + value = crm_element_value(src, name); + if (value == NULL) { + value = "0"; + } + crm_xml_add(dest, name, value); } return diff; } -enum cib_errors -cib_process_xpath( - const char *op, int options, const char *section, xmlNode *req, xmlNode *input, - xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer) +enum cib_errors +cib_process_xpath(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, + xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { int lpc = 0; int max = 0; int rc = cib_ok; gboolean is_query = safe_str_eq(op, CIB_OP_QUERY); - + xmlXPathObjectPtr xpathObj = NULL; + crm_debug_2("Processing \"%s\" event", op); - if(is_query) { - xpathObj = xpath_search(existing_cib, section); + if (is_query) { + xpathObj = xpath_search(existing_cib, section); } else { - xpathObj = xpath_search(*result_cib, section); - } - - if(xpathObj != NULL && xpathObj->nodesetval != NULL) { - max = xpathObj->nodesetval->nodeNr; - } - - if(max < 1 && safe_str_eq(op, CIB_OP_DELETE)) { - crm_debug("%s was already removed", section); - - } else if(max < 1) { - crm_debug("%s: %s does not exist", op, section); - rc = cib_NOTEXISTS; - - } else if(is_query) { - if(max > 1) { - *answer = create_xml_node(NULL, "xpath-query"); - } - } - - for(lpc = 0; lpc < max; lpc++) { - xmlChar *path = NULL; - xmlNode *match = getXpathResult(xpathObj, lpc); - if(match == NULL) { - continue; - } - - path = xmlGetNodePath(match); - crm_debug("Processing %s op for %s (%s)", op, section, path); - free(path); - - if(safe_str_eq(op, CIB_OP_DELETE)) { - free_xml_from_parent(NULL, match); - if((options & cib_multiple) == 0) { - break; - } - - } else if(safe_str_eq(op, CIB_OP_MODIFY)) { - if(update_xml_child(match, input) == FALSE) { - rc = cib_NOTEXISTS; - } else if((options & cib_multiple) == 0) { - break; - } - - } else if(safe_str_eq(op, CIB_OP_CREATE)) { - add_node_copy(match, input); - break; - - } else if(safe_str_eq(op, CIB_OP_QUERY)) { - - if(options & cib_no_children) { - const char *tag = TYPE(match); - xmlNode *shallow = create_xml_node(*answer, tag); - copy_in_properties(shallow, match); - - if(*answer == NULL) { - *answer = shallow; - } - - } else if(*answer) { - add_node_copy(*answer, match); - - } else { - *answer = match; - } - - } else if(safe_str_eq(op, CIB_OP_REPLACE)) { - xmlNode *parent = match->parent; - free_xml_from_parent(NULL, match); - if(input != NULL) { - add_node_copy(parent, input); - } - - if((options & cib_multiple) == 0) { - break; - } - } - } - - if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - + xpathObj = xpath_search(*result_cib, section); + } + + if (xpathObj != NULL && xpathObj->nodesetval != NULL) { + max = xpathObj->nodesetval->nodeNr; + } + + if (max < 1 && safe_str_eq(op, CIB_OP_DELETE)) { + crm_debug("%s was already removed", section); + + } else if (max < 1) { + crm_debug("%s: %s does not exist", op, section); + rc = cib_NOTEXISTS; + + } else if (is_query) { + if (max > 1) { + *answer = create_xml_node(NULL, "xpath-query"); + } + } + + for (lpc = 0; lpc < max; lpc++) { + xmlChar *path = NULL; + xmlNode *match = getXpathResult(xpathObj, lpc); + + if (match == NULL) { + continue; + } + + path = xmlGetNodePath(match); + crm_debug("Processing %s op for %s (%s)", op, section, path); + free(path); + + if (safe_str_eq(op, CIB_OP_DELETE)) { + free_xml_from_parent(NULL, match); + if ((options & cib_multiple) == 0) { + break; + } + + } else if (safe_str_eq(op, CIB_OP_MODIFY)) { + if (update_xml_child(match, input) == FALSE) { + rc = cib_NOTEXISTS; + } else if ((options & cib_multiple) == 0) { + break; + } + + } else if (safe_str_eq(op, CIB_OP_CREATE)) { + add_node_copy(match, input); + break; + + } else if (safe_str_eq(op, CIB_OP_QUERY)) { + + if (options & cib_no_children) { + const char *tag = TYPE(match); + xmlNode *shallow = create_xml_node(*answer, tag); + + copy_in_properties(shallow, match); + + if (*answer == NULL) { + *answer = shallow; + } + + } else if (*answer) { + add_node_copy(*answer, match); + + } else { + *answer = match; + } + + } else if (safe_str_eq(op, CIB_OP_REPLACE)) { + xmlNode *parent = match->parent; + + free_xml_from_parent(NULL, match); + if (input != NULL) { + add_node_copy(parent, input); + } + + if ((options & cib_multiple) == 0) { + break; + } + } + } + + if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + return rc; } /* remove this function */ gboolean -update_results( - xmlNode *failed, xmlNode *target, const char* operation, int return_code) +update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code) { xmlNode *xml_node = NULL; gboolean was_error = FALSE; const char *error_msg = NULL; - - + if (return_code != cib_ok) { - error_msg = cib_error2string(return_code); - - was_error = TRUE; - xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB); - add_node_copy(xml_node, target); - - crm_xml_add(xml_node, XML_FAILCIB_ATTR_ID, ID(target)); - crm_xml_add(xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target)); - crm_xml_add(xml_node, XML_FAILCIB_ATTR_OP, operation); - crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg); - - crm_warn("Action %s failed: %s (cde=%d)", - operation, error_msg, return_code); + error_msg = cib_error2string(return_code); + + was_error = TRUE; + xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB); + add_node_copy(xml_node, target); + + crm_xml_add(xml_node, XML_FAILCIB_ATTR_ID, ID(target)); + crm_xml_add(xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target)); + crm_xml_add(xml_node, XML_FAILCIB_ATTR_OP, operation); + crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg); + + crm_warn("Action %s failed: %s (cde=%d)", operation, error_msg, return_code); } return was_error; } diff --git a/lib/cib/cib_remote.c b/lib/cib/cib_remote.c index a0bd40c00d..3468ba8a16 100644 --- a/lib/cib/cib_remote.c +++ b/lib/cib/cib_remote.c @@ -1,648 +1,643 @@ /* * Copyright (c) 2008 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 - #ifdef HAVE_GNUTLS_GNUTLS_H # undef KEYFILE # include extern gnutls_anon_client_credentials anon_cred_c; extern gnutls_session *create_tls_session(int csock, int type); -const int kx_prio[] = -{ - GNUTLS_KX_ANON_DH, - 0 +const int kx_prio[] = { + GNUTLS_KX_ANON_DH, + 0 }; #else typedef void gnutls_session; #endif #include #include #define DH_BITS 1024 -struct remote_connection_s -{ - int socket; - gboolean encrypted; - gnutls_session *session; - GFDSource *source; - char *token; +struct remote_connection_s { + int socket; + gboolean encrypted; + gnutls_session *session; + GFDSource *source; + char *token; }; -typedef struct cib_remote_opaque_s -{ - int flags; - int socket; - int port; - char *server; - char *user; - char *passwd; - struct remote_connection_s command; - struct remote_connection_s callback; - +typedef struct cib_remote_opaque_s { + int flags; + int socket; + int port; + char *server; + char *user; + char *passwd; + struct remote_connection_s command; + struct remote_connection_s callback; + } cib_remote_opaque_t; void cib_remote_connection_destroy(gpointer user_data); gboolean cib_remote_dispatch(int fd, gpointer user_data); -int cib_remote_signon(cib_t* cib, const char *name, enum cib_conn_type type); -int cib_remote_signoff(cib_t* cib); -int cib_remote_free(cib_t* cib); - -int cib_remote_perform_op( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options); +int cib_remote_signon(cib_t * cib, const char *name, enum cib_conn_type type); +int cib_remote_signoff(cib_t * cib); +int cib_remote_free(cib_t * cib); +int cib_remote_perform_op(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options); -static int cib_remote_inputfd(cib_t* cib) { +static int +cib_remote_inputfd(cib_t * cib) +{ cib_remote_opaque_t *private = cib->variant_opaque; + return private->callback.socket; } -static int cib_remote_set_connection_dnotify( - cib_t *cib, void (*dnotify)(gpointer user_data)) +static int +cib_remote_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data)) { return cib_NOTSUPPORTED; } static int -cib_remote_register_notification(cib_t* cib, const char *callback, int enabled) +cib_remote_register_notification(cib_t * cib, const char *callback, int enabled) { xmlNode *notify_msg = create_xml_node(NULL, "cib_command"); cib_remote_opaque_t *private = cib->variant_opaque; - + crm_xml_add(notify_msg, F_CIB_OPERATION, T_CIB_NOTIFY); crm_xml_add(notify_msg, F_CIB_NOTIFY_TYPE, callback); crm_xml_add_int(notify_msg, F_CIB_NOTIFY_ACTIVATE, enabled); cib_send_remote_msg(private->callback.session, notify_msg, private->callback.encrypted); free_xml(notify_msg); return cib_ok; } -cib_t* -cib_remote_new (const char *server, const char *user, const char *passwd, int port, gboolean encrypted) +cib_t * +cib_remote_new(const char *server, const char *user, const char *passwd, int port, + gboolean encrypted) { cib_remote_opaque_t *private = NULL; cib_t *cib = cib_new_variant(); crm_malloc0(private, sizeof(cib_remote_opaque_t)); cib->variant = cib_remote; cib->variant_opaque = private; - if(server) { - private->server = crm_strdup(server); + if (server) { + private->server = crm_strdup(server); } - if(user) { - private->user = crm_strdup(user); + if (user) { + private->user = crm_strdup(user); } - if(passwd) { - private->passwd = crm_strdup(passwd); + if (passwd) { + private->passwd = crm_strdup(passwd); } private->port = port; private->command.encrypted = encrypted; private->callback.encrypted = encrypted; - /* assign variant specific ops*/ + /* assign variant specific ops */ cib->cmds->variant_op = cib_remote_perform_op; - cib->cmds->signon = cib_remote_signon; - cib->cmds->signoff = cib_remote_signoff; - cib->cmds->free = cib_remote_free; - cib->cmds->inputfd = cib_remote_inputfd; + cib->cmds->signon = cib_remote_signon; + cib->cmds->signoff = cib_remote_signoff; + cib->cmds->free = cib_remote_free; + cib->cmds->inputfd = cib_remote_inputfd; cib->cmds->register_notification = cib_remote_register_notification; cib->cmds->set_connection_dnotify = cib_remote_set_connection_dnotify; return cib; -} +} static int -cib_tls_close(cib_t *cib) +cib_tls_close(cib_t * cib) { cib_remote_opaque_t *private = cib->variant_opaque; - shutdown (private->command.socket, SHUT_RDWR); /* no more receptions */ - shutdown (private->callback.socket, SHUT_RDWR); /* no more receptions */ + + shutdown(private->command.socket, SHUT_RDWR); /* no more receptions */ + shutdown(private->callback.socket, SHUT_RDWR); /* no more receptions */ close(private->command.socket); close(private->callback.socket); #ifdef HAVE_GNUTLS_GNUTLS_H - if(private->command.encrypted) { - gnutls_bye(*(private->command.session), GNUTLS_SHUT_RDWR); - gnutls_deinit(*(private->command.session)); - gnutls_free(private->command.session); + if (private->command.encrypted) { + gnutls_bye(*(private->command.session), GNUTLS_SHUT_RDWR); + gnutls_deinit(*(private->command.session)); + gnutls_free(private->command.session); - gnutls_bye(*(private->callback.session), GNUTLS_SHUT_RDWR); - gnutls_deinit(*(private->callback.session)); - gnutls_free(private->callback.session); + gnutls_bye(*(private->callback.session), GNUTLS_SHUT_RDWR); + gnutls_deinit(*(private->callback.session)); + gnutls_free(private->callback.session); - gnutls_anon_free_client_credentials (anon_cred_c); - gnutls_global_deinit(); + gnutls_anon_free_client_credentials(anon_cred_c); + gnutls_global_deinit(); } #endif return 0; } static int -cib_tls_signon(cib_t *cib, struct remote_connection_s *connection) +cib_tls_signon(cib_t * cib, struct remote_connection_s *connection) { int sock; cib_remote_opaque_t *private = cib->variant_opaque; struct sockaddr_in addr; int rc = 0; char *server = private->server; int ret_ga; struct addrinfo *res; struct addrinfo hints; xmlNode *answer = NULL; xmlNode *login = NULL; - connection->socket = 0; + connection->socket = 0; connection->session = NULL; - + /* create socket */ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == -1 ) { - crm_perror(LOG_ERR,"Socket creation failed"); - return -1; + if (sock == -1) { + crm_perror(LOG_ERR, "Socket creation failed"); + return -1; } - + /* getaddrinfo */ bzero(&hints, sizeof(struct addrinfo)); hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_RAW; - if(hints.ai_family == AF_INET6) { - hints.ai_protocol = IPPROTO_ICMPV6; + if (hints.ai_family == AF_INET6) { + hints.ai_protocol = IPPROTO_ICMPV6; } else { - hints.ai_protocol = IPPROTO_ICMP; + hints.ai_protocol = IPPROTO_ICMP; } crm_debug("Looking up %s", server); ret_ga = getaddrinfo(server, NULL, &hints, &res); if (ret_ga) { - crm_err("getaddrinfo: %s", gai_strerror(ret_ga)); - return -1; + crm_err("getaddrinfo: %s", gai_strerror(ret_ga)); + return -1; } - + if (res->ai_canonname) { - server = res->ai_canonname; + server = res->ai_canonname; } crm_debug("Got address %s for %s", server, private->server); - + if (!res->ai_addr) { - fprintf(stderr, "getaddrinfo failed"); - exit(1); + fprintf(stderr, "getaddrinfo failed"); + exit(1); } - #if 1 memcpy(&addr, res->ai_addr, res->ai_addrlen); #else - /* connect to server*/ + /* connect to server */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(server); #endif addr.sin_port = htons(private->port); - - if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) { - crm_perror(LOG_ERR,"Connection to %s:%d failed", server, private->port); - close(sock); - return -1; + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + crm_perror(LOG_ERR, "Connection to %s:%d failed", server, private->port); + close(sock); + return -1; } - if(connection->encrypted) { - /* initialize GnuTls lib*/ + if (connection->encrypted) { + /* initialize GnuTls lib */ #ifdef HAVE_GNUTLS_GNUTLS_H - gnutls_global_init(); - gnutls_anon_allocate_client_credentials(&anon_cred_c); - - /* bind the socket to GnuTls lib */ - connection->session = create_tls_session(sock, GNUTLS_CLIENT); - if (connection->session == NULL) { - crm_perror(LOG_ERR,"Session creation for %s:%d failed", server, private->port); - close(sock); - cib_tls_close(cib); - return -1; - } + gnutls_global_init(); + gnutls_anon_allocate_client_credentials(&anon_cred_c); + + /* bind the socket to GnuTls lib */ + connection->session = create_tls_session(sock, GNUTLS_CLIENT); + if (connection->session == NULL) { + crm_perror(LOG_ERR, "Session creation for %s:%d failed", server, private->port); + close(sock); + cib_tls_close(cib); + return -1; + } #else - return cib_NOTSUPPORTED; + return cib_NOTSUPPORTED; #endif } else { - connection->session = GUINT_TO_POINTER(sock); + connection->session = GUINT_TO_POINTER(sock); } - + /* login to server */ login = create_xml_node(NULL, "cib_command"); crm_xml_add(login, "op", "authenticate"); crm_xml_add(login, "user", private->user); crm_xml_add(login, "password", private->passwd); crm_xml_add(login, "hidden", "password"); - + cib_send_remote_msg(connection->session, login, connection->encrypted); free_xml(login); answer = cib_recv_remote_msg(connection->session, connection->encrypted); crm_log_xml_debug_3(answer, "Reply"); - if(answer == NULL) { - rc = cib_authentication; + if (answer == NULL) { + rc = cib_authentication; } else { - /* grab the token */ - const char *msg_type = crm_element_value(answer, F_CIB_OPERATION); - const char *tmp_ticket = crm_element_value(answer, F_CIB_CLIENTID); - - if(safe_str_neq(msg_type, CRM_OP_REGISTER) ) { - crm_err("Invalid registration message: %s", msg_type); - rc = cib_registration_msg; - - } else if(tmp_ticket == NULL) { - rc = cib_callback_token; - - } else { - connection->token = crm_strdup(tmp_ticket); - } - } - + /* grab the token */ + const char *msg_type = crm_element_value(answer, F_CIB_OPERATION); + const char *tmp_ticket = crm_element_value(answer, F_CIB_CLIENTID); + + if (safe_str_neq(msg_type, CRM_OP_REGISTER)) { + crm_err("Invalid registration message: %s", msg_type); + rc = cib_registration_msg; + + } else if (tmp_ticket == NULL) { + rc = cib_callback_token; + + } else { + connection->token = crm_strdup(tmp_ticket); + } + } + if (rc != 0) { - cib_tls_close(cib); + cib_tls_close(cib); } - + connection->socket = sock; - connection->source = G_main_add_fd( - G_PRIORITY_HIGH, connection->socket, FALSE, - cib_remote_dispatch, cib, cib_remote_connection_destroy); + connection->source = G_main_add_fd(G_PRIORITY_HIGH, connection->socket, FALSE, + cib_remote_dispatch, cib, cib_remote_connection_destroy); return rc; } void cib_remote_connection_destroy(gpointer user_data) { crm_err("Connection destroyed"); #ifdef HAVE_GNUTLS_GNUTLS_H cib_tls_close(user_data); #endif return; } -gboolean cib_remote_dispatch(int fd, gpointer user_data) +gboolean +cib_remote_dispatch(int fd, gpointer user_data) { cib_t *cib = user_data; cib_remote_opaque_t *private = cib->variant_opaque; - if(fd == private->callback.socket) { - xmlNode *msg = NULL; - const char *type = NULL; - - crm_info("Message on callback channel"); - msg = cib_recv_remote_msg(private->callback.session, private->callback.encrypted); - - type = crm_element_value(msg, F_TYPE); - crm_debug_4("Activating %s callbacks...", type); - - if(safe_str_eq(type, T_CIB)) { - cib_native_callback(cib, msg, 0, 0); - - } else if(safe_str_eq(type, T_CIB_NOTIFY)) { - g_list_foreach(cib->notify_list, cib_native_notify, msg); - - } else { - crm_err("Unknown message type: %s", type); - } - - if(msg != NULL) { - free_xml(msg); - return TRUE; - } - - } else if(fd == private->command.socket) { - crm_err("Message on command channel"); + + if (fd == private->callback.socket) { + xmlNode *msg = NULL; + const char *type = NULL; + + crm_info("Message on callback channel"); + msg = cib_recv_remote_msg(private->callback.session, private->callback.encrypted); + + type = crm_element_value(msg, F_TYPE); + crm_debug_4("Activating %s callbacks...", type); + + if (safe_str_eq(type, T_CIB)) { + cib_native_callback(cib, msg, 0, 0); + + } else if (safe_str_eq(type, T_CIB_NOTIFY)) { + g_list_foreach(cib->notify_list, cib_native_notify, msg); + + } else { + crm_err("Unknown message type: %s", type); + } + + if (msg != NULL) { + free_xml(msg); + return TRUE; + } + + } else if (fd == private->command.socket) { + crm_err("Message on command channel"); } else { - crm_err("Unknown fd"); + crm_err("Unknown fd"); } - + return FALSE; } int -cib_remote_signon(cib_t* cib, const char *name, enum cib_conn_type type) +cib_remote_signon(cib_t * cib, const char *name, enum cib_conn_type type) { int rc = cib_ok; cib_remote_opaque_t *private = cib->variant_opaque; - if(private->passwd == NULL) { - struct termios settings; - int rc; - - rc = tcgetattr (0, &settings); - settings.c_lflag &= ~ECHO; - rc = tcsetattr (0, TCSANOW, &settings); - - fprintf(stderr, "Password: "); - crm_malloc0(private->passwd, 1024); - scanf("%s", private->passwd); - fprintf(stdout, "\n"); - /* fprintf(stderr, "entered: '%s'\n", buffer); */ - - settings.c_lflag |= ECHO; - rc = tcsetattr (0, TCSANOW, &settings); - } - - if(private->server == NULL || private->user == NULL) { - rc = cib_missing; - } - - if(rc == cib_ok) { - rc = cib_tls_signon(cib, &(private->command)); - } - - if(rc == cib_ok) { - rc = cib_tls_signon(cib, &(private->callback)); - } - - if(rc == cib_ok) { - xmlNode *hello = cib_create_op(0, private->callback.token, CRM_OP_REGISTER, NULL, NULL, NULL, 0, NULL); - crm_xml_add(hello, F_CIB_CLIENTNAME, name); - cib_send_remote_msg(private->command.session, hello, private->command.encrypted); - free_xml(hello); - } - - if(rc == cib_ok) { - fprintf(stderr, "%s: Opened connection to %s:%d\n", name, private->server, private->port); - cib->state = cib_connected_command; - cib->type = cib_command; + if (private->passwd == NULL) { + struct termios settings; + int rc; + + rc = tcgetattr(0, &settings); + settings.c_lflag &= ~ECHO; + rc = tcsetattr(0, TCSANOW, &settings); + + fprintf(stderr, "Password: "); + crm_malloc0(private->passwd, 1024); + scanf("%s", private->passwd); + fprintf(stdout, "\n"); + /* fprintf(stderr, "entered: '%s'\n", buffer); */ + + settings.c_lflag |= ECHO; + rc = tcsetattr(0, TCSANOW, &settings); + } + + if (private->server == NULL || private->user == NULL) { + rc = cib_missing; + } + + if (rc == cib_ok) { + rc = cib_tls_signon(cib, &(private->command)); + } + + if (rc == cib_ok) { + rc = cib_tls_signon(cib, &(private->callback)); + } + + if (rc == cib_ok) { + xmlNode *hello = + cib_create_op(0, private->callback.token, CRM_OP_REGISTER, NULL, NULL, NULL, 0, NULL); + crm_xml_add(hello, F_CIB_CLIENTNAME, name); + cib_send_remote_msg(private->command.session, hello, private->command.encrypted); + free_xml(hello); + } + + if (rc == cib_ok) { + fprintf(stderr, "%s: Opened connection to %s:%d\n", name, private->server, private->port); + cib->state = cib_connected_command; + cib->type = cib_command; } else { - fprintf(stderr, "%s: Connection to %s:%d failed: %s\n", - name, private->server, private->port, cib_error2string(rc)); + fprintf(stderr, "%s: Connection to %s:%d failed: %s\n", + name, private->server, private->port, cib_error2string(rc)); } - + return rc; } - + int -cib_remote_signoff(cib_t* cib) +cib_remote_signoff(cib_t * cib) { int rc = cib_ok; + /* cib_remote_opaque_t *private = cib->variant_opaque; */ crm_debug("Signing out of the CIB Service"); #ifdef HAVE_GNUTLS_GNUTLS_H cib_tls_close(cib); #endif - + cib->state = cib_disconnected; - cib->type = cib_none; - + cib->type = cib_none; + return rc; } int -cib_remote_free (cib_t* cib) +cib_remote_free(cib_t * cib) { int rc = cib_ok; crm_warn("Freeing CIB"); - if(cib->state != cib_disconnected) { - rc = cib_remote_signoff(cib); - if(rc == cib_ok) { - cib_remote_opaque_t *private = cib->variant_opaque; - crm_free(private->server); - crm_free(private->user); - crm_free(private->passwd); - crm_free(cib->cmds); - crm_free(private); - crm_free(cib); - } - } - + if (cib->state != cib_disconnected) { + rc = cib_remote_signoff(cib); + if (rc == cib_ok) { + cib_remote_opaque_t *private = cib->variant_opaque; + + crm_free(private->server); + crm_free(private->user); + crm_free(private->passwd); + crm_free(cib->cmds); + crm_free(private); + crm_free(cib); + } + } + return rc; } static gboolean timer_expired = FALSE; static struct timer_rec_s *sync_timer = NULL; -static gboolean cib_timeout_handler(gpointer data) +static gboolean +cib_timeout_handler(gpointer data) { struct timer_rec_s *timer = data; + timer_expired = TRUE; crm_err("Call %d timed out after %ds", timer->call_id, timer->timeout); /* Always return TRUE, never remove the handler * We do that after the while-loop in cib_native_perform_op() */ return TRUE; } int -cib_remote_perform_op( - cib_t *cib, const char *op, const char *host, const char *section, - xmlNode *data, xmlNode **output_data, int call_options) +cib_remote_perform_op(cib_t * cib, const char *op, const char *host, const char *section, + xmlNode * data, xmlNode ** output_data, int call_options) { - int rc = HA_OK; - - xmlNode *op_msg = NULL; - xmlNode *op_reply = NULL; - - cib_remote_opaque_t *private = cib->variant_opaque; - if(sync_timer == NULL) { - crm_malloc0(sync_timer, sizeof(struct timer_rec_s)); - } - - if(cib->state == cib_disconnected) { - return cib_not_connected; - } - - if(output_data != NULL) { - *output_data = NULL; - } - - if(op == NULL) { - crm_err("No operation specified"); - return cib_operation; - } - - cib->call_id++; - /* prevent call_id from being negative (or zero) and conflicting - * with the cib_errors enum - * use 2 because we use it as (cib->call_id - 1) below - */ - if(cib->call_id < 1) { - cib->call_id = 1; - } - - op_msg = cib_create_op( - cib->call_id, private->callback.token, op, host, section, data, call_options, NULL); - if(op_msg == NULL) { - return cib_create_msg; - } - - crm_debug_3("Sending %s message to CIB service", op); - cib_send_remote_msg(private->command.session, op_msg, private->command.encrypted); - free_xml(op_msg); - - if((call_options & cib_discard_reply)) { - crm_debug_3("Discarding reply"); - return cib_ok; - - } else if(!(call_options & cib_sync_call)) { - return cib->call_id; - } - - rc = IPC_OK; - crm_debug_3("Waiting for a syncronous reply"); - - if(cib->call_timeout > 0) { - /* We need this, even with msgfromIPC_timeout(), because we might - * get other/older replies that don't match the active request - */ - timer_expired = FALSE; - sync_timer->call_id = cib->call_id; - sync_timer->timeout = cib->call_timeout*1000; - sync_timer->ref = g_timeout_add( - sync_timer->timeout, cib_timeout_handler, sync_timer); - } - - while(timer_expired == FALSE) { - int reply_id = -1; - int msg_id = cib->call_id; - - op_reply = cib_recv_remote_msg(private->command.session, private->command.encrypted); - if(op_reply == NULL) { - break; - } - - crm_element_value_int(op_reply, F_CIB_CALLID, &reply_id); - CRM_CHECK(reply_id > 0, - free_xml(op_reply); - if(sync_timer->ref > 0) { - g_source_remove(sync_timer->ref); - sync_timer->ref = 0; - } - return cib_reply_failed); - - if(reply_id == msg_id) { - break; - - } else if(reply_id < msg_id) { - crm_debug("Received old reply: %d (wanted %d)", - reply_id, msg_id); - crm_log_xml( - LOG_MSG, "Old reply", op_reply); - - } else if((reply_id - 10000) > msg_id) { - /* wrap-around case */ - crm_debug("Received old reply: %d (wanted %d)", - reply_id, msg_id); - crm_log_xml( - LOG_MSG, "Old reply", op_reply); - } else { - crm_err("Received a __future__ reply:" - " %d (wanted %d)", reply_id, msg_id); - } - - free_xml(op_reply); - op_reply = NULL; - } - - if(sync_timer->ref > 0) { - g_source_remove(sync_timer->ref); - sync_timer->ref = 0; - } - - if(timer_expired) { - return cib_remote_timeout; - } - - /* if(IPC_ISRCONN(native->command_channel) == FALSE) { */ - /* crm_err("CIB disconnected: %d", */ - /* native->command_channel->ch_status); */ - /* cib->state = cib_disconnected; */ - /* } */ - - if(op_reply == NULL) { - crm_err("No reply message - empty - %d", rc); - return cib_reply_failed; - } - - crm_debug_3("Syncronous reply received"); - rc = cib_ok; - - /* Start processing the reply... */ - if(crm_element_value_int(op_reply, F_CIB_RC, &rc) != 0) { - rc = cib_return_code; - } - - if(rc == cib_diff_resync) { - /* This is an internal value that clients do not and should not care about */ - rc = cib_ok; - } - - if(rc == cib_ok || rc == cib_not_master || rc == cib_master_timeout) { - crm_log_xml(LOG_DEBUG, "passed", op_reply); - - } else { + int rc = HA_OK; + + xmlNode *op_msg = NULL; + xmlNode *op_reply = NULL; + + cib_remote_opaque_t *private = cib->variant_opaque; + + if (sync_timer == NULL) { + crm_malloc0(sync_timer, sizeof(struct timer_rec_s)); + } + + if (cib->state == cib_disconnected) { + return cib_not_connected; + } + + if (output_data != NULL) { + *output_data = NULL; + } + + if (op == NULL) { + crm_err("No operation specified"); + return cib_operation; + } + + cib->call_id++; + /* prevent call_id from being negative (or zero) and conflicting + * with the cib_errors enum + * use 2 because we use it as (cib->call_id - 1) below + */ + if (cib->call_id < 1) { + cib->call_id = 1; + } + + op_msg = + cib_create_op(cib->call_id, private->callback.token, op, host, section, data, call_options, + NULL); + if (op_msg == NULL) { + return cib_create_msg; + } + + crm_debug_3("Sending %s message to CIB service", op); + cib_send_remote_msg(private->command.session, op_msg, private->command.encrypted); + free_xml(op_msg); + + if ((call_options & cib_discard_reply)) { + crm_debug_3("Discarding reply"); + return cib_ok; + + } else if (!(call_options & cib_sync_call)) { + return cib->call_id; + } + + rc = IPC_OK; + crm_debug_3("Waiting for a syncronous reply"); + + if (cib->call_timeout > 0) { + /* We need this, even with msgfromIPC_timeout(), because we might + * get other/older replies that don't match the active request + */ + timer_expired = FALSE; + sync_timer->call_id = cib->call_id; + sync_timer->timeout = cib->call_timeout * 1000; + sync_timer->ref = g_timeout_add(sync_timer->timeout, cib_timeout_handler, sync_timer); + } + + while (timer_expired == FALSE) { + int reply_id = -1; + int msg_id = cib->call_id; + + op_reply = cib_recv_remote_msg(private->command.session, private->command.encrypted); + if (op_reply == NULL) { + break; + } + + crm_element_value_int(op_reply, F_CIB_CALLID, &reply_id); + CRM_CHECK(reply_id > 0, free_xml(op_reply); if (sync_timer->ref > 0) { + g_source_remove(sync_timer->ref); sync_timer->ref = 0;} + return cib_reply_failed) ; + + if (reply_id == msg_id) { + break; + + } else if (reply_id < msg_id) { + crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id); + crm_log_xml(LOG_MSG, "Old reply", op_reply); + + } else if ((reply_id - 10000) > msg_id) { + /* wrap-around case */ + crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id); + crm_log_xml(LOG_MSG, "Old reply", op_reply); + } else { + crm_err("Received a __future__ reply:" " %d (wanted %d)", reply_id, msg_id); + } + + free_xml(op_reply); + op_reply = NULL; + } + + if (sync_timer->ref > 0) { + g_source_remove(sync_timer->ref); + sync_timer->ref = 0; + } + + if (timer_expired) { + return cib_remote_timeout; + } + + /* if(IPC_ISRCONN(native->command_channel) == FALSE) { */ + /* crm_err("CIB disconnected: %d", */ + /* native->command_channel->ch_status); */ + /* cib->state = cib_disconnected; */ + /* } */ + + if (op_reply == NULL) { + crm_err("No reply message - empty - %d", rc); + return cib_reply_failed; + } + + crm_debug_3("Syncronous reply received"); + rc = cib_ok; + + /* Start processing the reply... */ + if (crm_element_value_int(op_reply, F_CIB_RC, &rc) != 0) { + rc = cib_return_code; + } + + if (rc == cib_diff_resync) { + /* This is an internal value that clients do not and should not care about */ + rc = cib_ok; + } + + if (rc == cib_ok || rc == cib_not_master || rc == cib_master_timeout) { + crm_log_xml(LOG_DEBUG, "passed", op_reply); + + } else { /* } else if(rc == cib_remote_timeout) { */ - crm_err("Call failed: %s", cib_error2string(rc)); - crm_log_xml(LOG_WARNING, "failed", op_reply); - } - - if(output_data == NULL) { - /* do nothing more */ - - } else if(!(call_options & cib_discard_reply)) { - xmlNode *tmp = get_message_xml(op_reply, F_CIB_CALLDATA); - if(tmp == NULL) { - crm_debug_3("No output in reply to \"%s\" command %d", - op, cib->call_id - 1); - } else { - *output_data = copy_xml(tmp); - } - } - - free_xml(op_reply); - - return rc; + crm_err("Call failed: %s", cib_error2string(rc)); + crm_log_xml(LOG_WARNING, "failed", op_reply); + } + + if (output_data == NULL) { + /* do nothing more */ + + } else if (!(call_options & cib_discard_reply)) { + xmlNode *tmp = get_message_xml(op_reply, F_CIB_CALLDATA); + + if (tmp == NULL) { + crm_debug_3("No output in reply to \"%s\" command %d", op, cib->call_id - 1); + } else { + *output_data = copy_xml(tmp); + } + } + + free_xml(op_reply); + + return rc; } diff --git a/lib/cib/cib_utils.c b/lib/cib/cib_utils.c index 06dcb6ca68..87a07fd908 100644 --- a/lib/cib/cib_utils.c +++ b/lib/cib/cib_utils.c @@ -1,1026 +1,1028 @@ /* * Copyright (c) 2004 International Business Machines * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 -struct config_root_s -{ - const char *name; - const char *parent; - const char *path; +struct config_root_s { + const char *name; + const char *parent; + const char *path; }; /* * "//crm_config" will also work in place of "/cib/configuration/crm_config" * The / prefix means find starting from the root, whereas the // prefix means * find anywhere and risks multiple matches */ /* *INDENT-OFF* */ struct config_root_s known_paths[] = { { NULL, NULL, "//cib" }, { XML_TAG_CIB, NULL, "//cib" }, { XML_CIB_TAG_STATUS, "/cib", "//cib/status" }, { XML_CIB_TAG_CONFIGURATION,"/cib", "//cib/configuration" }, { XML_CIB_TAG_CRMCONFIG, "/cib/configuration", "//cib/configuration/crm_config" }, { XML_CIB_TAG_NODES, "/cib/configuration", "//cib/configuration/nodes" }, { XML_CIB_TAG_DOMAINS, "/cib/configuration", "//cib/configuration/domains" }, { XML_CIB_TAG_RESOURCES, "/cib/configuration", "//cib/configuration/resources" }, { XML_CIB_TAG_CONSTRAINTS, "/cib/configuration", "//cib/configuration/constraints" }, { XML_CIB_TAG_OPCONFIG, "/cib/configuration", "//cib/configuration/op_defaults" }, { XML_CIB_TAG_RSCCONFIG, "/cib/configuration", "//cib/configuration/rsc_defaults" }, { XML_CIB_TAG_ACLS, "/cib/configuration", "//cib/configuration/acls" }, { XML_CIB_TAG_SECTION_ALL, NULL, "//cib" }, }; /* *INDENT-ON* */ const char * cib_error2string(enum cib_errors return_code) { - const char *error_msg = NULL; - switch(return_code) { - case cib_bad_permissions: - error_msg = "bad permissions for the on-disk configuration. shutdown heartbeat and repair."; - break; - case cib_bad_digest: - error_msg = "the on-disk configuration was manually altered. shutdown heartbeat and repair."; - break; - case cib_bad_config: - error_msg = "the on-disk configuration is not valid"; - break; - case cib_msg_field_add: - error_msg = "failed adding field to cib message"; - break; - case cib_id_check: - error_msg = "missing id or id-collision detected"; - break; - case cib_operation: - error_msg = "invalid operation"; - break; - case cib_create_msg: - error_msg = "couldnt create cib message"; - break; - case cib_client_gone: - error_msg = "client left before we could send reply"; - break; - case cib_not_connected: - error_msg = "not connected"; - break; - case cib_not_authorized: - error_msg = "not authorized"; - break; - case cib_send_failed: - error_msg = "send failed"; - break; - case cib_reply_failed: - error_msg = "reply failed"; - break; - case cib_return_code: - error_msg = "no return code"; - break; - case cib_output_ptr: - error_msg = "nowhere to store output"; - break; - case cib_output_data: - error_msg = "corrupt output data"; - break; - case cib_connection: - error_msg = "connection failed"; - break; - case cib_callback_register: - error_msg = "couldnt register callback channel"; - break; - case cib_authentication: - error_msg = ""; - break; - case cib_registration_msg: - error_msg = "invalid registration msg"; - break; - case cib_callback_token: - error_msg = "callback token not found"; - break; - case cib_missing: - error_msg = "cib object missing"; - break; - case cib_variant: - error_msg = "unknown/corrupt cib variant"; - break; - case CIBRES_MISSING_ID: - error_msg = "The id field is missing"; - break; - case CIBRES_MISSING_TYPE: - error_msg = "The type field is missing"; - break; - case CIBRES_MISSING_FIELD: - error_msg = "A required field is missing"; - break; - case CIBRES_OBJTYPE_MISMATCH: - error_msg = "CIBRES_OBJTYPE_MISMATCH"; - break; - case cib_EXISTS: - error_msg = "The object already exists"; - break; - case cib_NOTEXISTS: - error_msg = "The object/attribute does not exist"; - break; - case CIBRES_CORRUPT: - error_msg = "The CIB is corrupt"; - break; - case cib_NOOBJECT: - error_msg = "The update was empty"; - break; - case cib_NOPARENT: - error_msg = "The parent object does not exist"; - break; - case cib_NODECOPY: - error_msg = "Failed while copying update"; - break; - case CIBRES_OTHER: - error_msg = "CIBRES_OTHER"; - break; - case cib_ok: - error_msg = "ok"; - break; - case cib_unknown: - error_msg = "Unknown error"; - break; - case cib_STALE: - error_msg = "Discarded old update"; - break; - case cib_ACTIVATION: - error_msg = "Activation Failed"; - break; - case cib_NOSECTION: - error_msg = "Required section was missing"; - break; - case cib_NOTSUPPORTED: - error_msg = "The action/feature is not supported"; - break; - case cib_not_master: - error_msg = "Local service is not the master instance"; - break; - case cib_client_corrupt: - error_msg = "Service client not valid"; - break; - case cib_remote_timeout: - error_msg = "Remote node did not respond"; - break; - case cib_master_timeout: - error_msg = "No master service is currently active"; - break; - case cib_revision_unsupported: - error_msg = "The required CIB revision number is not supported"; - break; - case cib_revision_unknown: - error_msg = "The CIB revision number could not be determined"; - break; - case cib_missing_data: - error_msg = "Required data for this CIB API call not found"; - break; - case cib_no_quorum: - error_msg = "Write requires quorum"; - break; - case cib_diff_failed: - error_msg = "Application of an update diff failed"; - break; - case cib_diff_resync: - error_msg = "Application of an update diff failed, requesting a full refresh"; - break; - case cib_bad_section: - error_msg = "Invalid CIB section specified"; - break; - case cib_old_data: - error_msg = "Update was older than existing configuration"; - break; - case cib_dtd_validation: - error_msg = "Update does not conform to the configured schema/DTD"; - break; - case cib_invalid_argument: - error_msg = "Invalid argument"; - break; - case cib_transform_failed: - error_msg = "Schema transform failed"; - break; - case cib_permission_denied: - error_msg = "Permission Denied"; - break; - } - - if(error_msg == NULL) { - crm_err("Unknown CIB Error Code: %d", return_code); - error_msg = ""; - } - - return error_msg; + const char *error_msg = NULL; + + switch (return_code) { + case cib_bad_permissions: + error_msg = + "bad permissions for the on-disk configuration. shutdown heartbeat and repair."; + break; + case cib_bad_digest: + error_msg = + "the on-disk configuration was manually altered. shutdown heartbeat and repair."; + break; + case cib_bad_config: + error_msg = "the on-disk configuration is not valid"; + break; + case cib_msg_field_add: + error_msg = "failed adding field to cib message"; + break; + case cib_id_check: + error_msg = "missing id or id-collision detected"; + break; + case cib_operation: + error_msg = "invalid operation"; + break; + case cib_create_msg: + error_msg = "couldnt create cib message"; + break; + case cib_client_gone: + error_msg = "client left before we could send reply"; + break; + case cib_not_connected: + error_msg = "not connected"; + break; + case cib_not_authorized: + error_msg = "not authorized"; + break; + case cib_send_failed: + error_msg = "send failed"; + break; + case cib_reply_failed: + error_msg = "reply failed"; + break; + case cib_return_code: + error_msg = "no return code"; + break; + case cib_output_ptr: + error_msg = "nowhere to store output"; + break; + case cib_output_data: + error_msg = "corrupt output data"; + break; + case cib_connection: + error_msg = "connection failed"; + break; + case cib_callback_register: + error_msg = "couldnt register callback channel"; + break; + case cib_authentication: + error_msg = ""; + break; + case cib_registration_msg: + error_msg = "invalid registration msg"; + break; + case cib_callback_token: + error_msg = "callback token not found"; + break; + case cib_missing: + error_msg = "cib object missing"; + break; + case cib_variant: + error_msg = "unknown/corrupt cib variant"; + break; + case CIBRES_MISSING_ID: + error_msg = "The id field is missing"; + break; + case CIBRES_MISSING_TYPE: + error_msg = "The type field is missing"; + break; + case CIBRES_MISSING_FIELD: + error_msg = "A required field is missing"; + break; + case CIBRES_OBJTYPE_MISMATCH: + error_msg = "CIBRES_OBJTYPE_MISMATCH"; + break; + case cib_EXISTS: + error_msg = "The object already exists"; + break; + case cib_NOTEXISTS: + error_msg = "The object/attribute does not exist"; + break; + case CIBRES_CORRUPT: + error_msg = "The CIB is corrupt"; + break; + case cib_NOOBJECT: + error_msg = "The update was empty"; + break; + case cib_NOPARENT: + error_msg = "The parent object does not exist"; + break; + case cib_NODECOPY: + error_msg = "Failed while copying update"; + break; + case CIBRES_OTHER: + error_msg = "CIBRES_OTHER"; + break; + case cib_ok: + error_msg = "ok"; + break; + case cib_unknown: + error_msg = "Unknown error"; + break; + case cib_STALE: + error_msg = "Discarded old update"; + break; + case cib_ACTIVATION: + error_msg = "Activation Failed"; + break; + case cib_NOSECTION: + error_msg = "Required section was missing"; + break; + case cib_NOTSUPPORTED: + error_msg = "The action/feature is not supported"; + break; + case cib_not_master: + error_msg = "Local service is not the master instance"; + break; + case cib_client_corrupt: + error_msg = "Service client not valid"; + break; + case cib_remote_timeout: + error_msg = "Remote node did not respond"; + break; + case cib_master_timeout: + error_msg = "No master service is currently active"; + break; + case cib_revision_unsupported: + error_msg = "The required CIB revision number is not supported"; + break; + case cib_revision_unknown: + error_msg = "The CIB revision number could not be determined"; + break; + case cib_missing_data: + error_msg = "Required data for this CIB API call not found"; + break; + case cib_no_quorum: + error_msg = "Write requires quorum"; + break; + case cib_diff_failed: + error_msg = "Application of an update diff failed"; + break; + case cib_diff_resync: + error_msg = "Application of an update diff failed, requesting a full refresh"; + break; + case cib_bad_section: + error_msg = "Invalid CIB section specified"; + break; + case cib_old_data: + error_msg = "Update was older than existing configuration"; + break; + case cib_dtd_validation: + error_msg = "Update does not conform to the configured schema/DTD"; + break; + case cib_invalid_argument: + error_msg = "Invalid argument"; + break; + case cib_transform_failed: + error_msg = "Schema transform failed"; + break; + case cib_permission_denied: + error_msg = "Permission Denied"; + break; + } + + if (error_msg == NULL) { + crm_err("Unknown CIB Error Code: %d", return_code); + error_msg = ""; + } + + return error_msg; } int -cib_section2enum(const char *a_section) +cib_section2enum(const char *a_section) { - if(a_section == NULL || strcasecmp(a_section, "all") == 0) { - return cib_section_all; + if (a_section == NULL || strcasecmp(a_section, "all") == 0) { + return cib_section_all; - } else if(strcasecmp(a_section, XML_CIB_TAG_NODES) == 0) { - return cib_section_nodes; + } else if (strcasecmp(a_section, XML_CIB_TAG_NODES) == 0) { + return cib_section_nodes; - } else if(strcasecmp(a_section, XML_CIB_TAG_STATUS) == 0) { - return cib_section_status; + } else if (strcasecmp(a_section, XML_CIB_TAG_STATUS) == 0) { + return cib_section_status; - } else if(strcasecmp(a_section, XML_CIB_TAG_CONSTRAINTS) == 0) { - return cib_section_constraints; - - } else if(strcasecmp(a_section, XML_CIB_TAG_RESOURCES) == 0) { - return cib_section_resources; + } else if (strcasecmp(a_section, XML_CIB_TAG_CONSTRAINTS) == 0) { + return cib_section_constraints; - } else if(strcasecmp(a_section, XML_CIB_TAG_CRMCONFIG) == 0) { - return cib_section_crmconfig; + } else if (strcasecmp(a_section, XML_CIB_TAG_RESOURCES) == 0) { + return cib_section_resources; - } - crm_err("Unknown CIB section: %s", a_section); - return cib_section_none; -} + } else if (strcasecmp(a_section, XML_CIB_TAG_CRMCONFIG) == 0) { + return cib_section_crmconfig; + } + crm_err("Unknown CIB section: %s", a_section); + return cib_section_none; +} int -cib_compare_generation(xmlNode *left, xmlNode *right) +cib_compare_generation(xmlNode * left, xmlNode * right) { - int lpc = 0; - const char *attributes[] = { - XML_ATTR_GENERATION_ADMIN, - XML_ATTR_GENERATION, - XML_ATTR_NUMUPDATES, - }; - - crm_log_xml_debug_3(left, "left"); - crm_log_xml_debug_3(right, "right"); - - for(lpc = 0; lpc < DIMOF(attributes); lpc++) { - int int_elem_l = -1; - int int_elem_r = -1; - const char *elem_r = NULL; - const char *elem_l = crm_element_value(left, attributes[lpc]); - - if(right != NULL) { - elem_r = crm_element_value(right, attributes[lpc]); - } - - if(elem_l != NULL) { int_elem_l = crm_parse_int(elem_l, NULL); } - if(elem_r != NULL) { int_elem_r = crm_parse_int(elem_r, NULL); } - - if(int_elem_l < int_elem_r) { - crm_debug_2("%s (%s < %s)", attributes[lpc], - crm_str(elem_l), crm_str(elem_r)); - return -1; - - } else if(int_elem_l > int_elem_r) { - crm_debug_2("%s (%s > %s)", attributes[lpc], - crm_str(elem_l), crm_str(elem_r)); - return 1; - } - } - - return 0; + int lpc = 0; + + const char *attributes[] = { + XML_ATTR_GENERATION_ADMIN, + XML_ATTR_GENERATION, + XML_ATTR_NUMUPDATES, + }; + + crm_log_xml_debug_3(left, "left"); + crm_log_xml_debug_3(right, "right"); + + for (lpc = 0; lpc < DIMOF(attributes); lpc++) { + int int_elem_l = -1; + int int_elem_r = -1; + const char *elem_r = NULL; + const char *elem_l = crm_element_value(left, attributes[lpc]); + + if (right != NULL) { + elem_r = crm_element_value(right, attributes[lpc]); + } + + if (elem_l != NULL) { + int_elem_l = crm_parse_int(elem_l, NULL); + } + if (elem_r != NULL) { + int_elem_r = crm_parse_int(elem_r, NULL); + } + + if (int_elem_l < int_elem_r) { + crm_debug_2("%s (%s < %s)", attributes[lpc], crm_str(elem_l), crm_str(elem_r)); + return -1; + + } else if (int_elem_l > int_elem_r) { + crm_debug_2("%s (%s > %s)", attributes[lpc], crm_str(elem_l), crm_str(elem_r)); + return 1; + } + } + + return 0; } -xmlNode* -get_cib_copy(cib_t *cib) +xmlNode * +get_cib_copy(cib_t * cib) { - xmlNode *xml_cib; - int options = cib_scope_local|cib_sync_call; - if(cib->cmds->query(cib, NULL, &xml_cib, options) != cib_ok) { - crm_err("Couldnt retrieve the CIB"); - return NULL; - } else if(xml_cib == NULL) { - crm_err("The CIB result was empty"); - return NULL; - } - - if(safe_str_eq(crm_element_name(xml_cib), XML_TAG_CIB)) { - return xml_cib; - } - free_xml(xml_cib); - return NULL; + xmlNode *xml_cib; + int options = cib_scope_local | cib_sync_call; + + if (cib->cmds->query(cib, NULL, &xml_cib, options) != cib_ok) { + crm_err("Couldnt retrieve the CIB"); + return NULL; + } else if (xml_cib == NULL) { + crm_err("The CIB result was empty"); + return NULL; + } + + if (safe_str_eq(crm_element_name(xml_cib), XML_TAG_CIB)) { + return xml_cib; + } + free_xml(xml_cib); + return NULL; } -xmlNode* -cib_get_generation(cib_t *cib) +xmlNode * +cib_get_generation(cib_t * cib) { - xmlNode *the_cib = get_cib_copy(cib); - xmlNode *generation = create_xml_node( - NULL, XML_CIB_TAG_GENERATION_TUPPLE); - - if(the_cib != NULL) { - copy_in_properties(generation, the_cib); - free_xml(the_cib); - } - - return generation; -} + xmlNode *the_cib = get_cib_copy(cib); + xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE); + + if (the_cib != NULL) { + copy_in_properties(generation, the_cib); + free_xml(the_cib); + } + return generation; +} void -log_cib_diff(int log_level, xmlNode *diff, const char *function) +log_cib_diff(int log_level, xmlNode * diff, const char *function) { - 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) { - do_crm_log(log_level, "%s: Diff: --- %d.%d.%d", function, - del_admin_epoch, del_epoch, del_updates); - do_crm_log(log_level, "%s: Diff: +++ %d.%d.%d", function, - add_admin_epoch, add_epoch, add_updates); - } else if(diff != NULL) { - do_crm_log(log_level, - "%s: Local-only Change: %d.%d.%d", function, - add_admin_epoch, add_epoch, add_updates); - } - - log_xml_diff(log_level, diff, function); + 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) { + do_crm_log(log_level, "%s: Diff: --- %d.%d.%d", function, + del_admin_epoch, del_epoch, del_updates); + do_crm_log(log_level, "%s: Diff: +++ %d.%d.%d", function, + add_admin_epoch, add_epoch, add_updates); + } else if (diff != NULL) { + do_crm_log(log_level, + "%s: Local-only Change: %d.%d.%d", function, + add_admin_epoch, add_epoch, add_updates); + } + + log_xml_diff(log_level, diff, function); } gboolean -cib_version_details( - xmlNode *cib, int *admin_epoch, int *epoch, int *updates) +cib_version_details(xmlNode * cib, int *admin_epoch, int *epoch, int *updates) { - *epoch = -1; - *updates = -1; - *admin_epoch = -1; - - if(cib == NULL) { - return FALSE; - - } else { - crm_element_value_int(cib, XML_ATTR_GENERATION, epoch); - crm_element_value_int(cib, XML_ATTR_NUMUPDATES, updates); - crm_element_value_int(cib, XML_ATTR_GENERATION_ADMIN, admin_epoch); - } - return TRUE; + *epoch = -1; + *updates = -1; + *admin_epoch = -1; + + if (cib == NULL) { + return FALSE; + + } else { + crm_element_value_int(cib, XML_ATTR_GENERATION, epoch); + crm_element_value_int(cib, XML_ATTR_NUMUPDATES, updates); + crm_element_value_int(cib, XML_ATTR_GENERATION_ADMIN, admin_epoch); + } + return TRUE; } gboolean -cib_diff_version_details( - xmlNode *diff, int *admin_epoch, int *epoch, int *updates, - int *_admin_epoch, int *_epoch, int *_updates) +cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates, + int *_admin_epoch, int *_epoch, int *_updates) { - xmlNode *tmp = NULL; + xmlNode *tmp = NULL; - tmp = find_xml_node(diff, "diff-added", FALSE); - tmp = find_xml_node(tmp, XML_TAG_CIB, FALSE); - cib_version_details(tmp, admin_epoch, epoch, updates); + tmp = find_xml_node(diff, "diff-added", FALSE); + tmp = find_xml_node(tmp, XML_TAG_CIB, FALSE); + cib_version_details(tmp, admin_epoch, epoch, updates); - tmp = find_xml_node(diff, "diff-removed", FALSE); - cib_version_details(tmp, _admin_epoch, _epoch, _updates); - return TRUE; + tmp = find_xml_node(diff, "diff-removed", FALSE); + cib_version_details(tmp, _admin_epoch, _epoch, _updates); + return TRUE; } /* * The caller should never free the return value */ -const char *get_object_path(const char *object_type) +const char * +get_object_path(const char *object_type) { int lpc = 0; int max = DIMOF(known_paths); - for(; lpc < max; lpc++) { - if((object_type == NULL && known_paths[lpc].name == NULL) - || safe_str_eq(object_type, known_paths[lpc].name)) { - return known_paths[lpc].path; - } + + for (; lpc < max; lpc++) { + if ((object_type == NULL && known_paths[lpc].name == NULL) + || safe_str_eq(object_type, known_paths[lpc].name)) { + return known_paths[lpc].path; + } } return NULL; } -const char *get_object_parent(const char *object_type) +const char * +get_object_parent(const char *object_type) { int lpc = 0; int max = DIMOF(known_paths); - for(; lpc < max; lpc++) { - if(safe_str_eq(object_type, known_paths[lpc].name)) { - return known_paths[lpc].parent; - } + + for (; lpc < max; lpc++) { + if (safe_str_eq(object_type, known_paths[lpc].name)) { + return known_paths[lpc].parent; + } } return NULL; } -xmlNode* -get_object_root(const char *object_type, xmlNode *the_root) +xmlNode * +get_object_root(const char *object_type, xmlNode * the_root) { const char *xpath = get_object_path(object_type); - if(xpath == NULL) { - return the_root; /* or return NULL? */ + if (xpath == NULL) { + return the_root; /* or return NULL? */ } return get_xpath_object(xpath, the_root, LOG_DEBUG_4); } -xmlNode* -create_cib_fragment_adv( - xmlNode *update, const char *update_section, const char *source) +xmlNode * +create_cib_fragment_adv(xmlNode * update, const char *update_section, const char *source) { - xmlNode *cib = NULL; - gboolean whole_cib = FALSE; - xmlNode *object_root = NULL; - char *local_section = NULL; + xmlNode *cib = NULL; + gboolean whole_cib = FALSE; + xmlNode *object_root = NULL; + char *local_section = NULL; /* crm_debug("Creating a blank fragment: %s", update_section); */ - - if(update == NULL && update_section == NULL) { - crm_debug_3("Creating a blank fragment"); - update = createEmptyCib(); - crm_xml_add(cib, XML_ATTR_ORIGIN, source); - return update; - - } else if(update == NULL) { - crm_err("No update to create a fragment for"); - return NULL; - - } - - CRM_CHECK(update_section != NULL, return NULL); - if(safe_str_eq(crm_element_name(update), XML_TAG_CIB)) { - whole_cib = TRUE; - } - - if(whole_cib == FALSE) { - cib = createEmptyCib(); - crm_xml_add(cib, XML_ATTR_ORIGIN, source); - object_root = get_object_root(update_section, cib); - add_node_copy(object_root, update); - - } else { - cib = copy_xml(update); - crm_xml_add(cib, XML_ATTR_ORIGIN, source); - } - - crm_free(local_section); - crm_debug_3("Verifying created fragment"); - return cib; + + if (update == NULL && update_section == NULL) { + crm_debug_3("Creating a blank fragment"); + update = createEmptyCib(); + crm_xml_add(cib, XML_ATTR_ORIGIN, source); + return update; + + } else if (update == NULL) { + crm_err("No update to create a fragment for"); + return NULL; + + } + + CRM_CHECK(update_section != NULL, return NULL); + if (safe_str_eq(crm_element_name(update), XML_TAG_CIB)) { + whole_cib = TRUE; + } + + if (whole_cib == FALSE) { + cib = createEmptyCib(); + crm_xml_add(cib, XML_ATTR_ORIGIN, source); + object_root = get_object_root(update_section, cib); + add_node_copy(object_root, update); + + } else { + cib = copy_xml(update); + crm_xml_add(cib, XML_ATTR_ORIGIN, source); + } + + crm_free(local_section); + crm_debug_3("Verifying created fragment"); + return cib; } /* * It is the callers responsibility to free both the new CIB (output) * and the new CIB (input) */ -xmlNode* +xmlNode * createEmptyCib(void) { - xmlNode *cib_root = NULL, *config = NULL; - - cib_root = create_xml_node(NULL, XML_TAG_CIB); + xmlNode *cib_root = NULL, *config = NULL; + + cib_root = create_xml_node(NULL, XML_TAG_CIB); - config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION); - create_xml_node(cib_root, XML_CIB_TAG_STATUS); + config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION); + create_xml_node(cib_root, XML_CIB_TAG_STATUS); /* crm_xml_add(cib_root, "version", "1"); */ - create_xml_node(config, XML_CIB_TAG_CRMCONFIG); - create_xml_node(config, XML_CIB_TAG_NODES); - create_xml_node(config, XML_CIB_TAG_RESOURCES); - create_xml_node(config, XML_CIB_TAG_CONSTRAINTS); - - return cib_root; + create_xml_node(config, XML_CIB_TAG_CRMCONFIG); + create_xml_node(config, XML_CIB_TAG_NODES); + create_xml_node(config, XML_CIB_TAG_RESOURCES); + create_xml_node(config, XML_CIB_TAG_CONSTRAINTS); + + return cib_root; } static unsigned int dtd_throttle = 0; enum cib_errors -cib_perform_op(const char *op, int call_options, cib_op_t *fn, gboolean is_query, - const char *section, xmlNode *req, xmlNode *input, - gboolean manage_counters, gboolean *config_changed, - xmlNode *current_cib, xmlNode **result_cib, xmlNode **diff, xmlNode **output) +cib_perform_op(const char *op, int call_options, cib_op_t * fn, gboolean is_query, + const char *section, xmlNode * req, xmlNode * input, + gboolean manage_counters, gboolean * config_changed, + xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff, xmlNode ** output) { - int rc = cib_ok; + int rc = cib_ok; gboolean check_dtd = TRUE; xmlNode *scratch = NULL; xmlNode *local_diff = NULL; const char *current_dtd = "unknown"; - + CRM_CHECK(output != NULL, return cib_output_data); CRM_CHECK(result_cib != NULL, return cib_output_data); CRM_CHECK(config_changed != NULL, return cib_output_data); - + *output = NULL; *result_cib = NULL; *config_changed = FALSE; - if(fn == NULL) { - return cib_operation; + if (fn == NULL) { + return cib_operation; } - - if(is_query) { - rc = (*fn)(op, call_options, section, req, input, current_cib, result_cib, output); - return rc; + + if (is_query) { + rc = (*fn) (op, call_options, section, req, input, current_cib, result_cib, output); + return rc; } - + scratch = copy_xml(current_cib); - rc = (*fn)(op, call_options, section, req, input, current_cib, &scratch, output); + rc = (*fn) (op, call_options, section, req, input, current_cib, &scratch, output); CRM_CHECK(current_cib != scratch, return cib_unknown); - if(rc == cib_ok && scratch == NULL) { - rc = cib_unknown; + if (rc == cib_ok && scratch == NULL) { + rc = cib_unknown; } - if(rc == cib_ok && scratch) { - const char *new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION); - if(new_version && compare_version(new_version, CRM_FEATURE_SET) > 0) { - crm_err("Discarding update with feature set '%s' greater than our own '%s'", - new_version, CRM_FEATURE_SET); - rc = cib_NOTSUPPORTED; - } + if (rc == cib_ok && scratch) { + const char *new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION); + + if (new_version && compare_version(new_version, CRM_FEATURE_SET) > 0) { + crm_err("Discarding update with feature set '%s' greater than our own '%s'", + new_version, CRM_FEATURE_SET); + rc = cib_NOTSUPPORTED; + } } - - if(rc == cib_ok && current_cib) { - int old = 0; - int new = 0; - crm_element_value_int(scratch, XML_ATTR_GENERATION_ADMIN, &new); - crm_element_value_int(current_cib, XML_ATTR_GENERATION_ADMIN, &old); - - if(old > new) { - crm_err("%s went backwards: %d -> %d (Opts: 0x%x)", - XML_ATTR_GENERATION_ADMIN, old, new, call_options); - crm_log_xml_warn(req, "Bad Op"); - crm_log_xml_warn(input, "Bad Data"); - rc = cib_old_data; - - } else if(old == new) { - crm_element_value_int(scratch, XML_ATTR_GENERATION, &new); - crm_element_value_int(current_cib, XML_ATTR_GENERATION, &old); - if(old > new) { - crm_err("%s went backwards: %d -> %d (Opts: 0x%x)", - XML_ATTR_GENERATION, old, new, call_options); - crm_log_xml_warn(req, "Bad Op"); - crm_log_xml_warn(input, "Bad Data"); - rc = cib_old_data; - } - } + + if (rc == cib_ok && current_cib) { + int old = 0; + int new = 0; + + crm_element_value_int(scratch, XML_ATTR_GENERATION_ADMIN, &new); + crm_element_value_int(current_cib, XML_ATTR_GENERATION_ADMIN, &old); + + if (old > new) { + crm_err("%s went backwards: %d -> %d (Opts: 0x%x)", + XML_ATTR_GENERATION_ADMIN, old, new, call_options); + crm_log_xml_warn(req, "Bad Op"); + crm_log_xml_warn(input, "Bad Data"); + rc = cib_old_data; + + } else if (old == new) { + crm_element_value_int(scratch, XML_ATTR_GENERATION, &new); + crm_element_value_int(current_cib, XML_ATTR_GENERATION, &old); + if (old > new) { + crm_err("%s went backwards: %d -> %d (Opts: 0x%x)", + XML_ATTR_GENERATION, old, new, call_options); + crm_log_xml_warn(req, "Bad Op"); + crm_log_xml_warn(input, "Bad Data"); + rc = cib_old_data; + } + } } - - if(rc == cib_ok) { - fix_plus_plus_recursive(scratch); - current_dtd = crm_element_value(scratch, XML_ATTR_VALIDATION); - - if(manage_counters) { - if(is_set(call_options, cib_inhibit_bcast) && safe_str_eq(section, XML_CIB_TAG_STATUS)) { - /* Fast-track changes connections which wont be broadcasting anywhere */ - cib_update_counter(scratch, XML_ATTR_NUMUPDATES, FALSE); - goto done; - } - - /* The diff calculation in cib_config_changed() accounts for 25% of the - * CIB's total CPU usage on the DC - * - * RNG validation on the otherhand, accounts for only 9%... - */ - *config_changed = cib_config_changed(current_cib, scratch, &local_diff); - - if(*config_changed) { - cib_update_counter(scratch, XML_ATTR_NUMUPDATES, TRUE); - cib_update_counter(scratch, XML_ATTR_GENERATION, FALSE); - - } else { - /* Previously we only did this if the diff detected a change - * - * But we replies are still sent, even if nothing changes so we - * don't save any network traffic and means we need to jump - * through expensive hoops to detect ordering changes - see below - */ - cib_update_counter(scratch, XML_ATTR_NUMUPDATES, FALSE); - - if(local_diff == NULL) { - /* Nothing to check */ - check_dtd = FALSE; - - /* Create a fake diff so that notifications, which include a _digest_, - * will be sent to our peers - * - * This is the cheapest way to detect changes to group/set ordering - * - * Previously we compared the old and new digest in cib_config_changed(), - * but that accounted for 15% of the CIB's total CPU usage on the DC - */ - local_diff = create_xml_node(NULL, "diff"); - crm_xml_add(local_diff, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); - create_xml_node(local_diff, "diff-removed"); - create_xml_node(local_diff, "diff-added"); - - /* Usually these are attrd re-updates */ - crm_log_xml_trace(req, "Non-change"); - - } else if(dtd_throttle++ % 20) { - /* Throttle the amount of costly validation we perform due to status updates - * a) we don't really care whats in the status section - * b) we don't validate any of it's contents at the moment anyway - */ - check_dtd = FALSE; - } - } - } + + if (rc == cib_ok) { + fix_plus_plus_recursive(scratch); + current_dtd = crm_element_value(scratch, XML_ATTR_VALIDATION); + + if (manage_counters) { + if (is_set(call_options, cib_inhibit_bcast) && safe_str_eq(section, XML_CIB_TAG_STATUS)) { + /* Fast-track changes connections which wont be broadcasting anywhere */ + cib_update_counter(scratch, XML_ATTR_NUMUPDATES, FALSE); + goto done; + } + + /* The diff calculation in cib_config_changed() accounts for 25% of the + * CIB's total CPU usage on the DC + * + * RNG validation on the otherhand, accounts for only 9%... + */ + *config_changed = cib_config_changed(current_cib, scratch, &local_diff); + + if (*config_changed) { + cib_update_counter(scratch, XML_ATTR_NUMUPDATES, TRUE); + cib_update_counter(scratch, XML_ATTR_GENERATION, FALSE); + + } else { + /* Previously we only did this if the diff detected a change + * + * But we replies are still sent, even if nothing changes so we + * don't save any network traffic and means we need to jump + * through expensive hoops to detect ordering changes - see below + */ + cib_update_counter(scratch, XML_ATTR_NUMUPDATES, FALSE); + + if (local_diff == NULL) { + /* Nothing to check */ + check_dtd = FALSE; + + /* Create a fake diff so that notifications, which include a _digest_, + * will be sent to our peers + * + * This is the cheapest way to detect changes to group/set ordering + * + * Previously we compared the old and new digest in cib_config_changed(), + * but that accounted for 15% of the CIB's total CPU usage on the DC + */ + local_diff = create_xml_node(NULL, "diff"); + crm_xml_add(local_diff, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); + create_xml_node(local_diff, "diff-removed"); + create_xml_node(local_diff, "diff-added"); + + /* Usually these are attrd re-updates */ + crm_log_xml_trace(req, "Non-change"); + + } else if (dtd_throttle++ % 20) { + /* Throttle the amount of costly validation we perform due to status updates + * a) we don't really care whats in the status section + * b) we don't validate any of it's contents at the moment anyway + */ + check_dtd = FALSE; + } + } + } } - if(diff != NULL && local_diff != NULL) { - /* Only fix the diff if we'll return it... */ - - xmlNode *cib = NULL; - xmlNode *diff_child = NULL; - const char *tag = NULL; - const char *value = NULL; - - tag = "diff-removed"; - diff_child = find_xml_node(local_diff, tag, FALSE); - if(diff_child == NULL) { - diff_child = create_xml_node(local_diff, tag); - } - - tag = XML_TAG_CIB; - cib = find_xml_node(diff_child, tag, FALSE); - if(cib == NULL) { - cib = create_xml_node(diff_child, tag); - } - - tag = XML_ATTR_GENERATION_ADMIN; - value = crm_element_value(current_cib, tag); - crm_xml_add(diff_child, tag, value); - if(*config_changed) { - crm_xml_add(cib, tag, value); - } - - tag = XML_ATTR_GENERATION; - value = crm_element_value(current_cib, tag); - crm_xml_add(diff_child, tag, value); - if(*config_changed) { - crm_xml_add(cib, tag, value); - } - - tag = XML_ATTR_NUMUPDATES; - value = crm_element_value(current_cib, tag); - crm_xml_add(cib, tag, value); - crm_xml_add(diff_child, tag, value); - - tag = "diff-added"; - diff_child = find_xml_node(local_diff, tag, FALSE); - if(diff_child == NULL) { - diff_child = create_xml_node(local_diff, tag); - } - - tag = XML_TAG_CIB; - cib = find_xml_node(diff_child, tag, FALSE); - if(cib == NULL) { - cib = create_xml_node(diff_child, tag); - } - - if(scratch) { + if (diff != NULL && local_diff != NULL) { + /* Only fix the diff if we'll return it... */ + + xmlNode *cib = NULL; + xmlNode *diff_child = NULL; + const char *tag = NULL; + const char *value = NULL; + + tag = "diff-removed"; + diff_child = find_xml_node(local_diff, tag, FALSE); + if (diff_child == NULL) { + diff_child = create_xml_node(local_diff, tag); + } + + tag = XML_TAG_CIB; + cib = find_xml_node(diff_child, tag, FALSE); + if (cib == NULL) { + cib = create_xml_node(diff_child, tag); + } + + tag = XML_ATTR_GENERATION_ADMIN; + value = crm_element_value(current_cib, tag); + crm_xml_add(diff_child, tag, value); + if (*config_changed) { + crm_xml_add(cib, tag, value); + } + + tag = XML_ATTR_GENERATION; + value = crm_element_value(current_cib, tag); + crm_xml_add(diff_child, tag, value); + if (*config_changed) { + crm_xml_add(cib, tag, value); + } + + tag = XML_ATTR_NUMUPDATES; + value = crm_element_value(current_cib, tag); + crm_xml_add(cib, tag, value); + crm_xml_add(diff_child, tag, value); + + tag = "diff-added"; + diff_child = find_xml_node(local_diff, tag, FALSE); + if (diff_child == NULL) { + diff_child = create_xml_node(local_diff, tag); + } + + tag = XML_TAG_CIB; + cib = find_xml_node(diff_child, tag, FALSE); + if (cib == NULL) { + cib = create_xml_node(diff_child, tag); + } + + if (scratch) { xmlAttrPtr xIter = NULL; - for(xIter = scratch->properties; xIter; xIter = xIter->next) { + + for (xIter = scratch->properties; xIter; xIter = xIter->next) { const char *p_name = (const char *)xIter->name; const char *p_value = crm_element_value(scratch, p_name); - xmlSetProp(cib, (const xmlChar*)p_name, (const xmlChar*)p_value); + + xmlSetProp(cib, (const xmlChar *)p_name, (const xmlChar *)p_value); } } - crm_log_xml_trace(local_diff, "Repaired-diff"); - *diff = local_diff; - local_diff = NULL; + crm_log_xml_trace(local_diff, "Repaired-diff"); + *diff = local_diff; + local_diff = NULL; } done: - if(rc == cib_ok - && check_dtd - && validate_xml(scratch, NULL, TRUE) == FALSE) { - crm_warn("Updated CIB does not validate against %s schema/dtd", crm_str(current_dtd)); - rc = cib_dtd_validation; + if (rc == cib_ok && check_dtd && validate_xml(scratch, NULL, TRUE) == FALSE) { + crm_warn("Updated CIB does not validate against %s schema/dtd", crm_str(current_dtd)); + rc = cib_dtd_validation; } *result_cib = scratch; free_xml(local_diff); return rc; } -int get_channel_token(IPC_Channel *ch, char **token) +int +get_channel_token(IPC_Channel * ch, char **token) { int rc = cib_ok; xmlNode *reg_msg = NULL; const char *msg_type = NULL; const char *tmp_ticket = NULL; - + CRM_CHECK(ch != NULL, return cib_missing); CRM_CHECK(token != NULL, return cib_output_ptr); - + crm_debug_4("Waiting for msg on command channel"); - + reg_msg = xmlfromIPC(ch, MAX_IPC_DELAY); - - if(ch->ops->get_chan_status(ch) != IPC_CONNECT) { - crm_err("No reply message - disconnected"); - free_xml(reg_msg); - return cib_not_connected; - - } else if(reg_msg == NULL) { - crm_err("No reply message - empty"); - return cib_reply_failed; + + if (ch->ops->get_chan_status(ch) != IPC_CONNECT) { + crm_err("No reply message - disconnected"); + free_xml(reg_msg); + return cib_not_connected; + + } else if (reg_msg == NULL) { + crm_err("No reply message - empty"); + return cib_reply_failed; } - + msg_type = crm_element_value(reg_msg, F_CIB_OPERATION); tmp_ticket = crm_element_value(reg_msg, F_CIB_CLIENTID); - - if(safe_str_neq(msg_type, CRM_OP_REGISTER) ) { - crm_err("Invalid registration message: %s", msg_type); - rc = cib_registration_msg; - - } else if(tmp_ticket == NULL) { - rc = cib_callback_token; + + if (safe_str_neq(msg_type, CRM_OP_REGISTER)) { + crm_err("Invalid registration message: %s", msg_type); + rc = cib_registration_msg; + + } else if (tmp_ticket == NULL) { + rc = cib_callback_token; } else { - *token = crm_strdup(tmp_ticket); + *token = crm_strdup(tmp_ticket); } free_xml(reg_msg); return rc; } - xmlNode * -cib_create_op( - int call_id, const char *token, const char *op, const char *host, const char *section, - xmlNode *data, int call_options, const char *user_name) +cib_create_op(int call_id, const char *token, const char *op, const char *host, const char *section, + xmlNode * data, int call_options, const char *user_name) { - int rc = HA_OK; - xmlNode *op_msg = create_xml_node(NULL, "cib_command"); - CRM_CHECK(op_msg != NULL, return NULL); - CRM_CHECK(token != NULL, return NULL); - - crm_xml_add(op_msg, F_XML_TAGNAME, "cib_command"); - - crm_xml_add(op_msg, F_TYPE, T_CIB); - crm_xml_add(op_msg, F_CIB_CALLBACK_TOKEN, token); - crm_xml_add(op_msg, F_CIB_OPERATION, op); - crm_xml_add(op_msg, F_CIB_HOST, host); - crm_xml_add(op_msg, F_CIB_SECTION, section); - crm_xml_add_int(op_msg, F_CIB_CALLID, call_id); + int rc = HA_OK; + xmlNode *op_msg = create_xml_node(NULL, "cib_command"); + + CRM_CHECK(op_msg != NULL, return NULL); + CRM_CHECK(token != NULL, return NULL); + + crm_xml_add(op_msg, F_XML_TAGNAME, "cib_command"); + + crm_xml_add(op_msg, F_TYPE, T_CIB); + crm_xml_add(op_msg, F_CIB_CALLBACK_TOKEN, token); + crm_xml_add(op_msg, F_CIB_OPERATION, op); + crm_xml_add(op_msg, F_CIB_HOST, host); + crm_xml_add(op_msg, F_CIB_SECTION, section); + crm_xml_add_int(op_msg, F_CIB_CALLID, call_id); #if ENABLE_ACL - if(user_name) { - crm_xml_add(op_msg, F_CIB_USER, user_name); - } + if (user_name) { + crm_xml_add(op_msg, F_CIB_USER, user_name); + } #endif - crm_debug_4("Sending call options: %.8lx, %d", - (long)call_options, call_options); - crm_xml_add_int(op_msg, F_CIB_CALLOPTS, call_options); - - if(data != NULL) { - add_message_xml(op_msg, F_CIB_CALLDATA, data); - } - - if (rc != HA_OK) { - crm_err("Failed to create CIB operation message"); - crm_log_xml(LOG_ERR, "op", op_msg); - free_xml(op_msg); - return NULL; - } - - if(call_options & cib_inhibit_bcast) { - CRM_CHECK((call_options & cib_scope_local), return NULL); - } - return op_msg; + crm_debug_4("Sending call options: %.8lx, %d", (long)call_options, call_options); + crm_xml_add_int(op_msg, F_CIB_CALLOPTS, call_options); + + if (data != NULL) { + add_message_xml(op_msg, F_CIB_CALLDATA, data); + } + + if (rc != HA_OK) { + crm_err("Failed to create CIB operation message"); + crm_log_xml(LOG_ERR, "op", op_msg); + free_xml(op_msg); + return NULL; + } + + if (call_options & cib_inhibit_bcast) { + CRM_CHECK((call_options & cib_scope_local), return NULL); + } + return op_msg; } void -cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc) +cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc) { - xmlNode *output = NULL; - cib_callback_client_t *blob = NULL; - cib_callback_client_t local_blob; - - local_blob.id = NULL; - local_blob.callback = NULL; - local_blob.user_data = NULL; - local_blob.only_success = FALSE; - - if(msg != NULL) { - crm_element_value_int(msg, F_CIB_RC, &rc); - crm_element_value_int(msg, F_CIB_CALLID, &call_id); - output = get_message_xml(msg, F_CIB_CALLDATA); - } - - blob = g_hash_table_lookup( - cib_op_callback_table, GINT_TO_POINTER(call_id)); - - if(blob != NULL) { - local_blob = *blob; - blob = NULL; - - remove_cib_op_callback(call_id, FALSE); - - } else { - crm_debug_2("No callback found for call %d", call_id); - local_blob.callback = NULL; - } - - if(cib == NULL) { - crm_debug("No cib object supplied"); - } - - if(rc == cib_diff_resync) { - /* This is an internal value that clients do not and should not care about */ - rc = cib_ok; - } - - if(local_blob.callback != NULL - && (rc == cib_ok || local_blob.only_success == FALSE)) { - crm_debug_2("Invoking callback %s for call %d", crm_str(local_blob.id), call_id); - local_blob.callback(msg, call_id, rc, output, local_blob.user_data); - - } else if(cib && cib->op_callback == NULL && rc != cib_ok) { - crm_warn("CIB command failed: %s", cib_error2string(rc)); - crm_log_xml(LOG_DEBUG, "Failed CIB Update", msg); - } - - if(cib && cib->op_callback != NULL) { - crm_debug_2("Invoking global callback for call %d", call_id); - cib->op_callback(msg, call_id, rc, output); - } - crm_debug_4("OP callback activated."); -} + xmlNode *output = NULL; + cib_callback_client_t *blob = NULL; + cib_callback_client_t local_blob; + + local_blob.id = NULL; + local_blob.callback = NULL; + local_blob.user_data = NULL; + local_blob.only_success = FALSE; + + if (msg != NULL) { + crm_element_value_int(msg, F_CIB_RC, &rc); + crm_element_value_int(msg, F_CIB_CALLID, &call_id); + output = get_message_xml(msg, F_CIB_CALLDATA); + } + + blob = g_hash_table_lookup(cib_op_callback_table, GINT_TO_POINTER(call_id)); + + if (blob != NULL) { + local_blob = *blob; + blob = NULL; + + remove_cib_op_callback(call_id, FALSE); + + } else { + crm_debug_2("No callback found for call %d", call_id); + local_blob.callback = NULL; + } + + if (cib == NULL) { + crm_debug("No cib object supplied"); + } + + if (rc == cib_diff_resync) { + /* This is an internal value that clients do not and should not care about */ + rc = cib_ok; + } + + if (local_blob.callback != NULL && (rc == cib_ok || local_blob.only_success == FALSE)) { + crm_debug_2("Invoking callback %s for call %d", crm_str(local_blob.id), call_id); + local_blob.callback(msg, call_id, rc, output, local_blob.user_data); + } else if (cib && cib->op_callback == NULL && rc != cib_ok) { + crm_warn("CIB command failed: %s", cib_error2string(rc)); + crm_log_xml(LOG_DEBUG, "Failed CIB Update", msg); + } + + if (cib && cib->op_callback != NULL) { + crm_debug_2("Invoking global callback for call %d", call_id); + cib->op_callback(msg, call_id, rc, output); + } + crm_debug_4("OP callback activated."); +} void cib_native_notify(gpointer data, gpointer user_data) { - xmlNode *msg = user_data; - cib_notify_client_t *entry = data; - const char *event = NULL; - - if(msg == NULL) { - crm_warn("Skipping callback - NULL message"); - return; - } - - event = crm_element_value(msg, F_SUBTYPE); - - if(entry == NULL) { - crm_warn("Skipping callback - NULL callback client"); - return; - - } else if(entry->callback == NULL) { - crm_warn("Skipping callback - NULL callback"); - return; - - } else if(safe_str_neq(entry->event, event)) { - crm_debug_4("Skipping callback - event mismatch %p/%s vs. %s", - entry, entry->event, event); - return; - } - - crm_debug_4("Invoking callback for %p/%s event...", entry, event); - entry->callback(event, msg); - crm_debug_4("Callback invoked..."); + xmlNode *msg = user_data; + cib_notify_client_t *entry = data; + const char *event = NULL; + + if (msg == NULL) { + crm_warn("Skipping callback - NULL message"); + return; + } + + event = crm_element_value(msg, F_SUBTYPE); + + if (entry == NULL) { + crm_warn("Skipping callback - NULL callback client"); + return; + + } else if (entry->callback == NULL) { + crm_warn("Skipping callback - NULL callback"); + return; + + } else if (safe_str_neq(entry->event, event)) { + crm_debug_4("Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event); + return; + } + + crm_debug_4("Invoking callback for %p/%s event...", entry, event); + entry->callback(event, msg); + crm_debug_4("Callback invoked..."); } -gboolean determine_host(cib_t *cib_conn, char **node_uname, char **node_uuid) +gboolean +determine_host(cib_t * cib_conn, char **node_uname, char **node_uuid) { CRM_CHECK(node_uname != NULL, return FALSE); - - if(*node_uname == NULL) { - struct utsname name; - if(uname(&name) < 0) { - crm_perror(LOG_ERR,"uname(2) call failed"); - return FALSE; - } - *node_uname = crm_strdup(name.nodename); - crm_info("Detected uname: %s", *node_uname); + + if (*node_uname == NULL) { + struct utsname name; + + if (uname(&name) < 0) { + crm_perror(LOG_ERR, "uname(2) call failed"); + return FALSE; + } + *node_uname = crm_strdup(name.nodename); + crm_info("Detected uname: %s", *node_uname); } - - if(cib_conn && *node_uname != NULL - && node_uuid != NULL && *node_uuid == NULL) { - int rc = query_node_uuid(cib_conn, *node_uname, node_uuid); - if(rc != cib_ok) { - fprintf(stderr,"Could not map uname=%s to a UUID: %s\n", - *node_uname, cib_error2string(rc)); - return FALSE; - } - crm_info("Mapped %s to %s", *node_uname, crm_str(*node_uuid)); + + if (cib_conn && *node_uname != NULL && node_uuid != NULL && *node_uuid == NULL) { + int rc = query_node_uuid(cib_conn, *node_uname, node_uuid); + + if (rc != cib_ok) { + fprintf(stderr, "Could not map uname=%s to a UUID: %s\n", + *node_uname, cib_error2string(rc)); + return FALSE; + } + crm_info("Mapped %s to %s", *node_uname, crm_str(*node_uuid)); } return TRUE; } - pe_cluster_option cib_opts[] = { - /* name, old-name, validate, default, description */ - { "enable-acl", NULL, "boolean", NULL, "false", &check_boolean, - "Enable CIB ACL", NULL }, + /* name, old-name, validate, default, description */ + {"enable-acl", NULL, "boolean", NULL, "false", &check_boolean, + "Enable CIB ACL", NULL} + , }; void cib_metadata(void) { - config_metadata("Cluster Information Base", "1.0", - "Cluster Information Base Options", - "This is a fake resource that details the options that can be configured for the Cluster Information Base.", - cib_opts, DIMOF(cib_opts)); + config_metadata("Cluster Information Base", "1.0", + "Cluster Information Base Options", + "This is a fake resource that details the options that can be configured for the Cluster Information Base.", + cib_opts, DIMOF(cib_opts)); } void -verify_cib_options(GHashTable *options) +verify_cib_options(GHashTable * options) { - verify_all_options(options, cib_opts, DIMOF(cib_opts)); + verify_all_options(options, cib_opts, DIMOF(cib_opts)); } const char * -cib_pref(GHashTable *options, const char *name) +cib_pref(GHashTable * options, const char *name) { - return get_cluster_pref(options, cib_opts, DIMOF(cib_opts), name); + return get_cluster_pref(options, cib_opts, DIMOF(cib_opts), name); } gboolean -cib_read_config(GHashTable *options, xmlNode *current_cib) +cib_read_config(GHashTable * options, xmlNode * current_cib) { - xmlNode *config = NULL; - ha_time_t *now = NULL; + xmlNode *config = NULL; + ha_time_t *now = NULL; - if (options == NULL || current_cib == NULL) { - return FALSE; - } + if (options == NULL || current_cib == NULL) { + return FALSE; + } - now = new_ha_date(TRUE); + now = new_ha_date(TRUE); - g_hash_table_remove_all(options); + g_hash_table_remove_all(options); + + config = get_object_root(XML_CIB_TAG_CRMCONFIG, current_cib); + if (config) { + unpack_instance_attributes(current_cib, config, XML_CIB_TAG_PROPSET, NULL, options, + CIB_OPTIONS_FIRST, FALSE, now); + } - config = get_object_root(XML_CIB_TAG_CRMCONFIG, current_cib); - if (config) { - unpack_instance_attributes( - current_cib, config, XML_CIB_TAG_PROPSET, NULL, options, - CIB_OPTIONS_FIRST, FALSE, now); - } - - verify_cib_options(options); + verify_cib_options(options); - free_ha_date(now); + free_ha_date(now); - return TRUE; + return TRUE; } gboolean -cib_internal_config_changed(xmlNode *diff) +cib_internal_config_changed(xmlNode * diff) { - gboolean changed = FALSE; - const char *config_xpath = "//"XML_TAG_CIB"/"XML_CIB_TAG_CONFIGURATION"/"XML_CIB_TAG_CRMCONFIG; - xmlXPathObject *xpathObj = NULL; + gboolean changed = FALSE; + const char *config_xpath = + "//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_CRMCONFIG; + xmlXPathObject *xpathObj = NULL; - if (diff == NULL) { - return FALSE; - } + if (diff == NULL) { + return FALSE; + } - xpathObj = xpath_search(diff, config_xpath); - if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { - changed = TRUE; - } + xpathObj = xpath_search(diff, config_xpath); + if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { + changed = TRUE; + } - if (xpathObj) { - xmlXPathFreeObject(xpathObj); - } + if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } - return changed; + return changed; } diff --git a/lib/cib/cib_version.c b/lib/cib/cib_version.c index 30ddafb4dd..5128ef2902 100644 --- a/lib/cib/cib_version.c +++ b/lib/cib/cib_version.c @@ -1,168 +1,163 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 - - - -const char * feature_sets[] = { +const char *feature_sets[] = { "1.1", "1.2", "1.3", "2.0", }; - -typedef struct tag_set_s -{ - int length; - const char **tags; +typedef struct tag_set_s { + int length; + const char **tags; } tag_set_t; - const char *feature_tags_12[] = { "master_slave", }; + const char *feature_tags_20[] = { "cluster_property_set", "meta_attributes", "transient_attributes", }; tag_set_t feature_tags[] = { - { 0, NULL }, - { 1, feature_tags_12 }, - { 0, NULL }, - { 3, feature_tags_20 }, + {0, NULL}, + {1, feature_tags_12}, + {0, NULL}, + {3, feature_tags_20}, }; const char *feature_attrs_12[] = { "master_node_max", }; + const char *feature_attrs_20[] = { "start_delay", "disabled", "on_fail", "prereq", "collocated", "globally_unique", "from_role", "to_role", "node_attribute", "score_attribute", "hours", "transition_key", "op_digest", "op_restart_digest", "op_force_restart", }; tag_set_t feature_attrs[] = { - { 0, NULL }, - { 1, feature_attrs_12 }, - { 0, NULL }, - { 15, feature_attrs_20 }, + {0, NULL}, + {1, feature_attrs_12}, + {0, NULL}, + {15, feature_attrs_20}, }; static int -internal_update_feature_set(xmlNode *xml_obj, int current) +internal_update_feature_set(xmlNode * xml_obj, int current) { int lpc = current; int lpc_nested = 0; const char *value = NULL; xmlNode *xml_child = NULL; int num_sets = DIMOF(feature_sets); - CRM_CHECK(compare_version( - CIB_FEATURE_SET, feature_sets[num_sets-1]) == 0, - return num_sets-1); - - for(;lpc < num_sets; lpc++) { - const char *tag = crm_element_name(xml_obj); - crm_debug_3("Checking set %d with %d tags", lpc, - feature_tags[lpc].length); - - lpc_nested = 0; - for(; lpc_nested < feature_tags[lpc].length; lpc_nested++) { - const char *name = feature_tags[lpc].tags[lpc_nested]; - crm_debug_4("Checking %s vs. %s", tag, name); - if(safe_str_eq(tag, name)) { - crm_debug_2("Found feature %s from set %s", - tag, feature_sets[lpc]); - current = lpc; - break; - } - } - if(current == lpc) { - continue; - } - - for(lpc_nested = 0; lpc_nested < feature_attrs[lpc].length; lpc_nested++) { - const char *name = feature_attrs[lpc].tags[lpc_nested]; - crm_debug_4("Checking for %s", name); - value = crm_element_value(xml_obj, name); - if(value != NULL) { - crm_info("Found feature '%s' from set %s", - name, feature_sets[lpc]); - current = lpc; - break; - } - } + CRM_CHECK(compare_version(CIB_FEATURE_SET, feature_sets[num_sets - 1]) == 0, + return num_sets - 1); + + for (; lpc < num_sets; lpc++) { + const char *tag = crm_element_name(xml_obj); + + crm_debug_3("Checking set %d with %d tags", lpc, feature_tags[lpc].length); + + lpc_nested = 0; + for (; lpc_nested < feature_tags[lpc].length; lpc_nested++) { + const char *name = feature_tags[lpc].tags[lpc_nested]; + + crm_debug_4("Checking %s vs. %s", tag, name); + if (safe_str_eq(tag, name)) { + crm_debug_2("Found feature %s from set %s", tag, feature_sets[lpc]); + current = lpc; + break; + } + } + if (current == lpc) { + continue; + } + + for (lpc_nested = 0; lpc_nested < feature_attrs[lpc].length; lpc_nested++) { + const char *name = feature_attrs[lpc].tags[lpc_nested]; + + crm_debug_4("Checking for %s", name); + value = crm_element_value(xml_obj, name); + if (value != NULL) { + crm_info("Found feature '%s' from set %s", name, feature_sets[lpc]); + current = lpc; + break; + } + } } - if(current == (num_sets -1)) { - return current; + if (current == (num_sets - 1)) { + return current; } - - for(xml_child = __xml_first_child(xml_obj); xml_child != NULL; xml_child = __xml_next(xml_child)) { - current = internal_update_feature_set(xml_child,current); - if(current == (num_sets -1)) { - return current; - } + + for (xml_child = __xml_first_child(xml_obj); xml_child != NULL; + xml_child = __xml_next(xml_child)) { + current = internal_update_feature_set(xml_child, current); + if (current == (num_sets - 1)) { + return current; + } } - return current; + return current; } const char * -feature_set(xmlNode *xml_obj) +feature_set(xmlNode * xml_obj) { int set = internal_update_feature_set(xml_obj, 0); - if(set >= 0 && set < DIMOF(feature_sets)) { - return feature_sets[set]; + if (set >= 0 && set < DIMOF(feature_sets)) { + return feature_sets[set]; } crm_err("Unknown feature set: %d", set); CRM_ASSERT(set >= 0 && set < DIMOF(feature_sets)); return "0.0"; } - diff --git a/lib/common/ais.c b/lib/common/ais.c index 7c63605385..50054c9f64 100644 --- a/lib/common/ais.c +++ b/lib/common/ais.c @@ -1,1363 +1,1393 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "stack.h" #ifdef SUPPORT_COROSYNC # include # include #endif #ifdef SUPPORT_CMAN # include cman_handle_t pcmk_cman_handle = NULL; #endif #ifdef SUPPORT_CS_QUORUM # include # include # include # include # include quorum_handle_t pcmk_quorum_handle = 0; cpg_handle_t pcmk_cpg_handle = 0; + struct cpg_name pcmk_cpg_group = { .length = 0, .value[0] = 0, }; #endif static char *pcmk_uname = NULL; static int pcmk_uname_len = 0; static uint32_t pcmk_nodeid = 0; #define cs_repeat(counter, max, code) do { \ code; \ if(rc == CS_ERR_TRY_AGAIN) { \ counter++; \ crm_debug("Retrying operation after %ds", counter); \ sleep(counter); \ } \ } while(rc == CS_ERR_TRY_AGAIN && counter < max) -enum crm_ais_msg_types text2msg_type(const char *text) +enum crm_ais_msg_types +text2msg_type(const char *text) { - int type = crm_msg_none; - - CRM_CHECK(text != NULL, return type); - if(safe_str_eq(text, "ais")) { - type = crm_msg_ais; - } else if(safe_str_eq(text, "crm_plugin")) { - type = crm_msg_ais; - } else if(safe_str_eq(text, CRM_SYSTEM_CIB)) { - type = crm_msg_cib; - } else if(safe_str_eq(text, CRM_SYSTEM_CRMD)) { - type = crm_msg_crmd; - } else if(safe_str_eq(text, CRM_SYSTEM_DC)) { - type = crm_msg_crmd; - } else if(safe_str_eq(text, CRM_SYSTEM_TENGINE)) { - type = crm_msg_te; - } else if(safe_str_eq(text, CRM_SYSTEM_PENGINE)) { - type = crm_msg_pe; - } else if(safe_str_eq(text, CRM_SYSTEM_LRMD)) { - type = crm_msg_lrmd; - } else if(safe_str_eq(text, CRM_SYSTEM_STONITHD)) { - type = crm_msg_stonithd; - } else if(safe_str_eq(text, "stonith-ng")) { - type = crm_msg_stonith_ng; - } else if(safe_str_eq(text, "attrd")) { - type = crm_msg_attrd; - - } else { - /* This will normally be a transient client rather than - * a cluster daemon. Set the type to the pid of the client - */ - int scan_rc = sscanf(text, "%d", &type); - if(scan_rc != 1) { - /* Ensure its sane */ - type = crm_msg_none; - } - } - return type; + int type = crm_msg_none; + + CRM_CHECK(text != NULL, return type); + if (safe_str_eq(text, "ais")) { + type = crm_msg_ais; + } else if (safe_str_eq(text, "crm_plugin")) { + type = crm_msg_ais; + } else if (safe_str_eq(text, CRM_SYSTEM_CIB)) { + type = crm_msg_cib; + } else if (safe_str_eq(text, CRM_SYSTEM_CRMD)) { + type = crm_msg_crmd; + } else if (safe_str_eq(text, CRM_SYSTEM_DC)) { + type = crm_msg_crmd; + } else if (safe_str_eq(text, CRM_SYSTEM_TENGINE)) { + type = crm_msg_te; + } else if (safe_str_eq(text, CRM_SYSTEM_PENGINE)) { + type = crm_msg_pe; + } else if (safe_str_eq(text, CRM_SYSTEM_LRMD)) { + type = crm_msg_lrmd; + } else if (safe_str_eq(text, CRM_SYSTEM_STONITHD)) { + type = crm_msg_stonithd; + } else if (safe_str_eq(text, "stonith-ng")) { + type = crm_msg_stonith_ng; + } else if (safe_str_eq(text, "attrd")) { + type = crm_msg_attrd; + + } else { + /* This will normally be a transient client rather than + * a cluster daemon. Set the type to the pid of the client + */ + int scan_rc = sscanf(text, "%d", &type); + + if (scan_rc != 1) { + /* Ensure its sane */ + type = crm_msg_none; + } + } + return type; } -char *get_ais_data(const AIS_Message *msg) +char * +get_ais_data(const AIS_Message * msg) { int rc = BZ_OK; char *uncompressed = NULL; unsigned int new_size = msg->size + 1; - - if(msg->is_compressed == FALSE) { - crm_debug_2("Returning uncompressed message data"); - uncompressed = strdup(msg->data); + + if (msg->is_compressed == FALSE) { + crm_debug_2("Returning uncompressed message data"); + uncompressed = strdup(msg->data); } else { - crm_debug_2("Decompressing message data"); - crm_malloc0(uncompressed, new_size); - - rc = BZ2_bzBuffToBuffDecompress( - uncompressed, &new_size, (char*)msg->data, msg->compressed_size, 1, 0); - - CRM_ASSERT(rc == BZ_OK); - CRM_ASSERT(new_size == msg->size); - } - + crm_debug_2("Decompressing message data"); + crm_malloc0(uncompressed, new_size); + + rc = BZ2_bzBuffToBuffDecompress(uncompressed, &new_size, (char *)msg->data, + msg->compressed_size, 1, 0); + + CRM_ASSERT(rc == BZ_OK); + CRM_ASSERT(new_size == msg->size); + } + return uncompressed; } - #if SUPPORT_COROSYNC int ais_fd_sync = -1; -int ais_fd_async = -1; /* never send messages via this channel */ +int ais_fd_async = -1; /* never send messages via this channel */ void *ais_ipc_ctx = NULL; hdb_handle_t ais_ipc_handle = 0; GFDSource *ais_source = NULL; GFDSource *ais_source_sync = NULL; GFDSource *cman_source = NULL; GFDSource *cpg_source = NULL; GFDSource *quorumd_source = NULL; static char *ais_cluster_name = NULL; -gboolean get_ais_nodeid(uint32_t *id, char **uname) +gboolean +get_ais_nodeid(uint32_t * id, char **uname) { struct iovec iov; int retries = 0; int rc = CS_OK; coroipc_response_header_t header; struct crm_ais_nodeid_resp_s answer; header.error = CS_OK; header.id = crm_class_nodeid; header.size = sizeof(coroipc_response_header_t); CRM_CHECK(id != NULL, return FALSE); CRM_CHECK(uname != NULL, return FALSE); iov.iov_base = &header; iov.iov_len = header.size; - + retry: errno = 0; - rc = coroipcc_msg_send_reply_receive( - ais_ipc_handle, &iov, 1, &answer, sizeof (answer)); - if(rc == CS_OK) { - CRM_CHECK(answer.header.size == sizeof (struct crm_ais_nodeid_resp_s), - crm_err("Odd message: id=%d, size=%d, error=%d", - answer.header.id, answer.header.size, answer.header.error)); - CRM_CHECK(answer.header.id == crm_class_nodeid, crm_err("Bad response id: %d", answer.header.id)); - } - - if(rc == CS_ERR_TRY_AGAIN && retries < 20) { - retries++; - crm_info("Peer overloaded: Re-sending message (Attempt %d of 20)", retries); - sleep(retries); /* Proportional back off */ - goto retry; - } - - if(rc != CS_OK) { - crm_err("Sending nodeid request: FAILED (rc=%d): %s", rc, ais_error2text(rc)); - return FALSE; - - } else if(answer.header.error != CS_OK) { - crm_err("Bad response from peer: (rc=%d): %s", rc, ais_error2text(rc)); - return FALSE; - } - - crm_info("Server details: id=%u uname=%s cname=%s", - answer.id, answer.uname, answer.cname); - + rc = coroipcc_msg_send_reply_receive(ais_ipc_handle, &iov, 1, &answer, sizeof(answer)); + if (rc == CS_OK) { + CRM_CHECK(answer.header.size == sizeof(struct crm_ais_nodeid_resp_s), + crm_err("Odd message: id=%d, size=%d, error=%d", + answer.header.id, answer.header.size, answer.header.error)); + CRM_CHECK(answer.header.id == crm_class_nodeid, + crm_err("Bad response id: %d", answer.header.id)); + } + + if (rc == CS_ERR_TRY_AGAIN && retries < 20) { + retries++; + crm_info("Peer overloaded: Re-sending message (Attempt %d of 20)", retries); + sleep(retries); /* Proportional back off */ + goto retry; + } + + if (rc != CS_OK) { + crm_err("Sending nodeid request: FAILED (rc=%d): %s", rc, ais_error2text(rc)); + return FALSE; + + } else if (answer.header.error != CS_OK) { + crm_err("Bad response from peer: (rc=%d): %s", rc, ais_error2text(rc)); + return FALSE; + } + + crm_info("Server details: id=%u uname=%s cname=%s", answer.id, answer.uname, answer.cname); + *id = answer.id; *uname = crm_strdup(answer.uname); ais_cluster_name = crm_strdup(answer.cname); return TRUE; } -gboolean crm_get_cluster_name(char **cname) +gboolean +crm_get_cluster_name(char **cname) { CRM_CHECK(cname != NULL, return FALSE); - if(ais_cluster_name) { - *cname = crm_strdup(ais_cluster_name); - return TRUE; + if (ais_cluster_name) { + *cname = crm_strdup(ais_cluster_name); + return TRUE; } return FALSE; } gboolean send_ais_text(int class, const char *data, - gboolean local, const char *node, enum crm_ais_msg_types dest) + gboolean local, const char *node, enum crm_ais_msg_types dest) { static int msg_id = 0; static int local_pid = 0; enum cluster_type_e cluster_type = get_cluster_type(); int retries = 0; int rc = CS_OK; int buf_len = sizeof(coroipc_response_header_t); char *buf = NULL; struct iovec iov; const char *transport = "pcmk"; coroipc_response_header_t *header = NULL; AIS_Message *ais_msg = NULL; enum crm_ais_msg_types sender = text2msg_type(crm_system_name); /* There are only 6 handlers registered to crm_lib_service in plugin.c */ - CRM_CHECK(class < 6, crm_err("Invalid message class: %d", class); return FALSE); + CRM_CHECK(class < 6, crm_err("Invalid message class: %d", class); + return FALSE); - if(data == NULL) { - data = ""; + if (data == NULL) { + data = ""; } - - if(local_pid == 0) { - local_pid = getpid(); + + if (local_pid == 0) { + local_pid = getpid(); } - if(sender == crm_msg_none) { - sender = local_pid; + if (sender == crm_msg_none) { + sender = local_pid; } - + crm_malloc0(ais_msg, sizeof(AIS_Message)); - + ais_msg->id = msg_id++; ais_msg->header.id = class; ais_msg->header.error = CS_OK; - + ais_msg->host.type = dest; ais_msg->host.local = local; - if(node) { - ais_msg->host.size = strlen(node); - memset(ais_msg->host.uname, 0, MAX_NAME); - memcpy(ais_msg->host.uname, node, ais_msg->host.size); - ais_msg->host.id = 0; - + if (node) { + ais_msg->host.size = strlen(node); + memset(ais_msg->host.uname, 0, MAX_NAME); + memcpy(ais_msg->host.uname, node, ais_msg->host.size); + ais_msg->host.id = 0; + } else { - ais_msg->host.size = 0; - memset(ais_msg->host.uname, 0, MAX_NAME); - ais_msg->host.id = 0; + ais_msg->host.size = 0; + memset(ais_msg->host.uname, 0, MAX_NAME); + ais_msg->host.id = 0; } ais_msg->sender.id = 0; ais_msg->sender.type = sender; ais_msg->sender.pid = local_pid; ais_msg->sender.size = pcmk_uname_len; memset(ais_msg->sender.uname, 0, MAX_NAME); memcpy(ais_msg->sender.uname, pcmk_uname, ais_msg->sender.size); ais_msg->size = 1 + strlen(data); - if(ais_msg->size < CRM_BZ2_THRESHOLD) { + if (ais_msg->size < CRM_BZ2_THRESHOLD) { failback: - crm_realloc(ais_msg, sizeof(AIS_Message) + ais_msg->size); - memcpy(ais_msg->data, data, ais_msg->size); - + crm_realloc(ais_msg, sizeof(AIS_Message) + ais_msg->size); + memcpy(ais_msg->data, data, ais_msg->size); + } else { - char *compressed = NULL; - char *uncompressed = crm_strdup(data); - unsigned int len = (ais_msg->size * 1.1) + 600; /* recomended size */ - - crm_debug_5("Compressing message payload"); - crm_malloc(compressed, len); - - rc = BZ2_bzBuffToBuffCompress( - compressed, &len, uncompressed, ais_msg->size, CRM_BZ2_BLOCKS, 0, CRM_BZ2_WORK); - - crm_free(uncompressed); - - if(rc != BZ_OK) { - crm_err("Compression failed: %d", rc); - crm_free(compressed); - goto failback; - } - - crm_realloc(ais_msg, sizeof(AIS_Message) + len + 1); - memcpy(ais_msg->data, compressed, len); - ais_msg->data[len] = 0; - crm_free(compressed); - - ais_msg->is_compressed = TRUE; - ais_msg->compressed_size = len; - - crm_debug_2("Compression details: %d -> %d", - ais_msg->size, ais_data_len(ais_msg)); - } + char *compressed = NULL; + char *uncompressed = crm_strdup(data); + unsigned int len = (ais_msg->size * 1.1) + 600; /* recomended size */ + + crm_debug_5("Compressing message payload"); + crm_malloc(compressed, len); + + rc = BZ2_bzBuffToBuffCompress(compressed, &len, uncompressed, ais_msg->size, CRM_BZ2_BLOCKS, + 0, CRM_BZ2_WORK); + + crm_free(uncompressed); + + if (rc != BZ_OK) { + crm_err("Compression failed: %d", rc); + crm_free(compressed); + goto failback; + } + + crm_realloc(ais_msg, sizeof(AIS_Message) + len + 1); + memcpy(ais_msg->data, compressed, len); + ais_msg->data[len] = 0; + crm_free(compressed); + + ais_msg->is_compressed = TRUE; + ais_msg->compressed_size = len; + + crm_debug_2("Compression details: %d -> %d", ais_msg->size, ais_data_len(ais_msg)); + } ais_msg->header.size = sizeof(AIS_Message) + ais_data_len(ais_msg); crm_debug_3("Sending%s message %d to %s.%s (data=%d, total=%d)", - ais_msg->is_compressed?" compressed":"", - ais_msg->id, ais_dest(&(ais_msg->host)), msg_type2text(dest), - ais_data_len(ais_msg), ais_msg->header.size); + ais_msg->is_compressed ? " compressed" : "", + ais_msg->id, ais_dest(&(ais_msg->host)), msg_type2text(dest), + ais_data_len(ais_msg), ais_msg->header.size); iov.iov_base = ais_msg; iov.iov_len = ais_msg->header.size; crm_realloc(buf, buf_len); do { - if(rc == CS_ERR_TRY_AGAIN) { - retries++; - crm_info("Peer overloaded or membership in flux:" - " Re-sending message (Attempt %d of 20)", retries); - sleep(retries); /* Proportional back off */ - } - - errno = 0; - switch(cluster_type) { - case pcmk_cluster_classic_ais: - rc = coroipcc_msg_send_reply_receive(ais_ipc_handle, &iov, 1, buf, buf_len); - header = (coroipc_response_header_t *)buf; - if(rc == CS_OK) { - CRM_CHECK(header->size == sizeof (coroipc_response_header_t), - crm_err("Odd message: id=%d, size=%d, class=%d, error=%d", - header->id, header->size, class, header->error)); - - CRM_ASSERT(buf_len >= header->size); - CRM_CHECK(header->id == CRM_MESSAGE_IPC_ACK, - crm_err("Bad response id (%d) for request (%d)", header->id, ais_msg->header.id)); - CRM_CHECK(header->error == CS_OK, rc = header->error); - } - break; - - case pcmk_cluster_corosync: - case pcmk_cluster_cman: - transport = "cpg"; - CRM_CHECK(dest != crm_msg_ais, rc = CS_ERR_MESSAGE_ERROR; goto bail); - rc = cpg_mcast_joined(pcmk_cpg_handle, CPG_TYPE_AGREED, &iov, 1); - if(rc == CS_ERR_TRY_AGAIN) { - cpg_flow_control_state_t fc_state = CPG_FLOW_CONTROL_DISABLED; - int rc2 = cpg_flow_control_state_get (pcmk_cpg_handle, &fc_state); - if (rc2 == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) { - crm_warn("Connection overloaded, cannot send messages"); - goto bail; - - } else if (rc2 != CS_OK) { - crm_warn("Could not determin the connection state: %s (%d)", ais_error2text(rc2), rc2); - goto bail; - } - } - break; - - case pcmk_cluster_unknown: - case pcmk_cluster_invalid: - case pcmk_cluster_heartbeat: - CRM_ASSERT(is_openais_cluster()); - break; - } - + if (rc == CS_ERR_TRY_AGAIN) { + retries++; + crm_info("Peer overloaded or membership in flux:" + " Re-sending message (Attempt %d of 20)", retries); + sleep(retries); /* Proportional back off */ + } + + errno = 0; + switch (cluster_type) { + case pcmk_cluster_classic_ais: + rc = coroipcc_msg_send_reply_receive(ais_ipc_handle, &iov, 1, buf, buf_len); + header = (coroipc_response_header_t *) buf; + if (rc == CS_OK) { + CRM_CHECK(header->size == sizeof(coroipc_response_header_t), + crm_err("Odd message: id=%d, size=%d, class=%d, error=%d", + header->id, header->size, class, header->error)); + + CRM_ASSERT(buf_len >= header->size); + CRM_CHECK(header->id == CRM_MESSAGE_IPC_ACK, + crm_err("Bad response id (%d) for request (%d)", header->id, + ais_msg->header.id)); + CRM_CHECK(header->error == CS_OK, rc = header->error); + } + break; + + case pcmk_cluster_corosync: + case pcmk_cluster_cman: + transport = "cpg"; + CRM_CHECK(dest != crm_msg_ais, rc = CS_ERR_MESSAGE_ERROR; + goto bail); + rc = cpg_mcast_joined(pcmk_cpg_handle, CPG_TYPE_AGREED, &iov, 1); + if (rc == CS_ERR_TRY_AGAIN) { + cpg_flow_control_state_t fc_state = CPG_FLOW_CONTROL_DISABLED; + int rc2 = cpg_flow_control_state_get(pcmk_cpg_handle, &fc_state); + + if (rc2 == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) { + crm_warn("Connection overloaded, cannot send messages"); + goto bail; + + } else if (rc2 != CS_OK) { + crm_warn("Could not determin the connection state: %s (%d)", + ais_error2text(rc2), rc2); + goto bail; + } + } + break; + + case pcmk_cluster_unknown: + case pcmk_cluster_invalid: + case pcmk_cluster_heartbeat: + CRM_ASSERT(is_openais_cluster()); + break; + } + } while (rc == CS_ERR_TRY_AGAIN && retries < 20); bail: - if(rc != CS_OK) { - crm_perror(LOG_ERR,"Sending message %d via %s: FAILED (rc=%d): %s", - ais_msg->id, transport, rc, ais_error2text(rc)); + if (rc != CS_OK) { + crm_perror(LOG_ERR, "Sending message %d via %s: FAILED (rc=%d): %s", + ais_msg->id, transport, rc, ais_error2text(rc)); } else { - crm_debug_4("Message %d: sent", ais_msg->id); + crm_debug_4("Message %d: sent", ais_msg->id); } crm_free(buf); crm_free(ais_msg); return (rc == CS_OK); } gboolean -send_ais_message(xmlNode *msg, - gboolean local, const char *node, enum crm_ais_msg_types dest) +send_ais_message(xmlNode * msg, gboolean local, const char *node, enum crm_ais_msg_types dest) { gboolean rc = TRUE; char *data = NULL; - if(is_classic_ais_cluster()) { - if(ais_fd_async < 0 || ais_source == NULL) { - crm_err("Not connected to AIS: %d %p", ais_fd_async, ais_source); - return FALSE; - } + if (is_classic_ais_cluster()) { + if (ais_fd_async < 0 || ais_source == NULL) { + crm_err("Not connected to AIS: %d %p", ais_fd_async, ais_source); + return FALSE; + } } data = dump_xml_unformatted(msg); rc = send_ais_text(0, data, local, node, dest); crm_free(data); return rc; } -void terminate_ais_connection(void) +void +terminate_ais_connection(void) { crm_notice("Disconnecting from AIS"); - + /* G_main_del_fd(ais_source); */ /* G_main_del_fd(ais_source_sync); */ - if(is_classic_ais_cluster() == FALSE) { - coroipcc_service_disconnect(ais_ipc_handle); + if (is_classic_ais_cluster() == FALSE) { + coroipcc_service_disconnect(ais_ipc_handle); } else { - cpg_leave(pcmk_cpg_handle, &pcmk_cpg_group); + cpg_leave(pcmk_cpg_handle, &pcmk_cpg_group); } - if(is_corosync_cluster()) { - quorum_finalize(pcmk_quorum_handle); + if (is_corosync_cluster()) { + quorum_finalize(pcmk_quorum_handle); } - -#ifdef SUPPORT_CMAN - if(is_cman_cluster()) { - cman_stop_notification(pcmk_cman_handle); - cman_finish(pcmk_cman_handle); +# ifdef SUPPORT_CMAN + if (is_cman_cluster()) { + cman_stop_notification(pcmk_cman_handle); + cman_finish(pcmk_cman_handle); } -#endif +# endif } int ais_membership_timer = 0; gboolean ais_membership_force = FALSE; -static gboolean ais_dispatch_message( - AIS_Message *msg, gboolean (*dispatch)(AIS_Message*,char*,int)) +static gboolean +ais_dispatch_message(AIS_Message * msg, gboolean(*dispatch) (AIS_Message *, char *, int)) { char *data = NULL; char *uncompressed = NULL; - + xmlNode *xml = NULL; + CRM_ASSERT(msg != NULL); - + crm_debug_3("Got new%s message (size=%d, %d, %d)", - msg->is_compressed?" compressed":"", - ais_data_len(msg), msg->size, msg->compressed_size); - + msg->is_compressed ? " compressed" : "", + ais_data_len(msg), msg->size, msg->compressed_size); + data = msg->data; - if(msg->is_compressed && msg->size > 0) { - int rc = BZ_OK; - unsigned int new_size = msg->size + 1; - - if(check_message_sanity(msg, NULL) == FALSE) { - goto badmsg; - } - - crm_debug_5("Decompressing message data"); - crm_malloc0(uncompressed, new_size); - rc = BZ2_bzBuffToBuffDecompress( - uncompressed, &new_size, data, msg->compressed_size, 1, 0); - - if(rc != BZ_OK) { - crm_err("Decompression failed: %d", rc); - goto badmsg; - } - - CRM_ASSERT(rc == BZ_OK); - CRM_ASSERT(new_size == msg->size); - - data = uncompressed; - - } else if(check_message_sanity(msg, data) == FALSE) { - goto badmsg; - - } else if(safe_str_eq("identify", data)) { - int pid = getpid(); - char *pid_s = crm_itoa(pid); - send_ais_text(0, pid_s, TRUE, NULL, crm_msg_ais); - crm_free(pid_s); - goto done; - } - - if(msg->header.id != crm_class_members) { - crm_update_peer(msg->sender.id, 0,0,0,0, msg->sender.uname, msg->sender.uname, NULL, NULL); - } - - if(msg->header.id == crm_class_rmpeer) { - uint32_t id = crm_int_helper(data, NULL); - crm_info("Removing peer %s/%u", data, id); - reap_crm_member(id); - goto done; - - } else if(msg->header.id == crm_class_members - || msg->header.id == crm_class_quorum) { - - xml = string2xml(data); - if(xml == NULL) { - crm_err("Invalid membership update: %s", data); - goto badmsg; - } - - if(is_classic_ais_cluster() == FALSE) { - xmlNode *node = NULL; - for(node = __xml_first_child(xml); node != NULL; node = __xml_next(node)) { - crm_update_cman_node(node, crm_peer_seq); - } - - } else { - xmlNode *node = NULL; - const char *value = NULL; - gboolean quorate = FALSE; - - value = crm_element_value(xml, "quorate"); - CRM_CHECK(value != NULL, crm_log_xml_err(xml, "No quorum value:"); goto badmsg); - if(crm_is_true(value)) { - quorate = TRUE; - } - - value = crm_element_value(xml, "id"); - CRM_CHECK(value != NULL, crm_log_xml_err(xml, "No membership id"); goto badmsg); - crm_peer_seq = crm_int_helper(value, NULL); - - if(quorate != crm_have_quorum) { - crm_notice("Membership %s: quorum %s", value, quorate?"acquired":"lost"); - crm_have_quorum = quorate; - - } else { - crm_info("Membership %s: quorum %s", value, quorate?"retained":"still lost"); - } - - for(node = __xml_first_child(xml); node != NULL; node = __xml_next(node)) { - crm_update_ais_node(node, crm_peer_seq); - } - } - } - - if(dispatch != NULL) { - dispatch(msg, data, 0); - } - + if (msg->is_compressed && msg->size > 0) { + int rc = BZ_OK; + unsigned int new_size = msg->size + 1; + + if (check_message_sanity(msg, NULL) == FALSE) { + goto badmsg; + } + + crm_debug_5("Decompressing message data"); + crm_malloc0(uncompressed, new_size); + rc = BZ2_bzBuffToBuffDecompress(uncompressed, &new_size, data, msg->compressed_size, 1, 0); + + if (rc != BZ_OK) { + crm_err("Decompression failed: %d", rc); + goto badmsg; + } + + CRM_ASSERT(rc == BZ_OK); + CRM_ASSERT(new_size == msg->size); + + data = uncompressed; + + } else if (check_message_sanity(msg, data) == FALSE) { + goto badmsg; + + } else if (safe_str_eq("identify", data)) { + int pid = getpid(); + char *pid_s = crm_itoa(pid); + + send_ais_text(0, pid_s, TRUE, NULL, crm_msg_ais); + crm_free(pid_s); + goto done; + } + + if (msg->header.id != crm_class_members) { + crm_update_peer(msg->sender.id, 0, 0, 0, 0, msg->sender.uname, msg->sender.uname, NULL, + NULL); + } + + if (msg->header.id == crm_class_rmpeer) { + uint32_t id = crm_int_helper(data, NULL); + + crm_info("Removing peer %s/%u", data, id); + reap_crm_member(id); + goto done; + + } else if (msg->header.id == crm_class_members || msg->header.id == crm_class_quorum) { + + xml = string2xml(data); + if (xml == NULL) { + crm_err("Invalid membership update: %s", data); + goto badmsg; + } + + if (is_classic_ais_cluster() == FALSE) { + xmlNode *node = NULL; + + for (node = __xml_first_child(xml); node != NULL; node = __xml_next(node)) { + crm_update_cman_node(node, crm_peer_seq); + } + + } else { + xmlNode *node = NULL; + const char *value = NULL; + gboolean quorate = FALSE; + + value = crm_element_value(xml, "quorate"); + CRM_CHECK(value != NULL, crm_log_xml_err(xml, "No quorum value:"); + goto badmsg); + if (crm_is_true(value)) { + quorate = TRUE; + } + + value = crm_element_value(xml, "id"); + CRM_CHECK(value != NULL, crm_log_xml_err(xml, "No membership id"); + goto badmsg); + crm_peer_seq = crm_int_helper(value, NULL); + + if (quorate != crm_have_quorum) { + crm_notice("Membership %s: quorum %s", value, quorate ? "acquired" : "lost"); + crm_have_quorum = quorate; + + } else { + crm_info("Membership %s: quorum %s", value, quorate ? "retained" : "still lost"); + } + + for (node = __xml_first_child(xml); node != NULL; node = __xml_next(node)) { + crm_update_ais_node(node, crm_peer_seq); + } + } + } + + if (dispatch != NULL) { + dispatch(msg, data, 0); + } + done: crm_free(uncompressed); free_xml(xml); return TRUE; badmsg: crm_err("Invalid message (id=%d, dest=%s:%s, from=%s:%s.%d):" - " min=%d, total=%d, size=%d, bz2_size=%d", - msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, (int)sizeof(AIS_Message), - msg->header.size, msg->size, msg->compressed_size); + " min=%d, total=%d, size=%d, bz2_size=%d", + msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), + ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), + msg->sender.pid, (int)sizeof(AIS_Message), + msg->header.size, msg->size, msg->compressed_size); goto done; } -gboolean ais_dispatch(int sender, gpointer user_data) +gboolean +ais_dispatch(int sender, gpointer user_data) { int rc = CS_OK; char *buffer = NULL; gboolean good = TRUE; - gboolean (*dispatch)(AIS_Message*,char*,int) = user_data; + + gboolean(*dispatch) (AIS_Message *, char *, int) = user_data; do { - rc = coroipcc_dispatch_get (ais_ipc_handle, (void**)&buffer, 0); - - if (rc == CS_ERR_TRY_AGAIN) { - return TRUE; - } - if (rc != CS_OK) { - crm_perror(LOG_ERR,"Receiving message body failed: (%d) %s", rc, ais_error2text(rc)); - goto bail; - } - if (buffer == NULL) { - /* NULL is a legal "no message afterall" value */ - return TRUE; - } - - good = ais_dispatch_message((AIS_Message*)buffer, dispatch); - coroipcc_dispatch_put (ais_ipc_handle); - - } while(good); - + rc = coroipcc_dispatch_get(ais_ipc_handle, (void **)&buffer, 0); + + if (rc == CS_ERR_TRY_AGAIN) { + return TRUE; + } + if (rc != CS_OK) { + crm_perror(LOG_ERR, "Receiving message body failed: (%d) %s", rc, ais_error2text(rc)); + goto bail; + } + if (buffer == NULL) { + /* NULL is a legal "no message afterall" value */ + return TRUE; + } + + good = ais_dispatch_message((AIS_Message *) buffer, dispatch); + coroipcc_dispatch_put(ais_ipc_handle); + + } while (good); + return good; bail: crm_err("AIS connection failed"); return FALSE; } static void ais_destroy(gpointer user_data) { crm_err("AIS connection terminated"); ais_fd_sync = -1; exit(1); } -static gboolean pcmk_proc_dispatch(IPC_Channel *ch, gpointer user_data) +static gboolean +pcmk_proc_dispatch(IPC_Channel * ch, gpointer user_data) { xmlNode *msg = NULL; gboolean stay_connected = TRUE; - - while(IPC_ISRCONN(ch)) { - if(ch->ops->is_message_pending(ch) == 0) { - break; - } - - msg = xmlfromIPC(ch, MAX_IPC_DELAY); - - if(msg) { - xmlNode *node = NULL; - for(node = __xml_first_child(msg); node != NULL; node = __xml_next(node)) { - int id = 0; - int children = 0; - const char *uname = crm_element_value(node, "uname"); - crm_element_value_int(node, "processes", &children); - - crm_update_peer(id, 0, 0, 0, children, NULL, uname, NULL, NULL); - } - free_xml(msg); - } - - if(ch->ch_status != IPC_CONNECT) { - break; - } - } - + + while (IPC_ISRCONN(ch)) { + if (ch->ops->is_message_pending(ch) == 0) { + break; + } + + msg = xmlfromIPC(ch, MAX_IPC_DELAY); + + if (msg) { + xmlNode *node = NULL; + + for (node = __xml_first_child(msg); node != NULL; node = __xml_next(node)) { + int id = 0; + int children = 0; + const char *uname = crm_element_value(node, "uname"); + + crm_element_value_int(node, "processes", &children); + + crm_update_peer(id, 0, 0, 0, children, NULL, uname, NULL, NULL); + } + free_xml(msg); + } + + if (ch->ch_status != IPC_CONNECT) { + break; + } + } + if (ch->ch_status != IPC_CONNECT) { - stay_connected = FALSE; + stay_connected = FALSE; } return stay_connected; } -#ifdef SUPPORT_CMAN +# ifdef SUPPORT_CMAN -static gboolean pcmk_cman_dispatch(int sender, gpointer user_data) +static gboolean +pcmk_cman_dispatch(int sender, gpointer user_data) { int rc = cman_dispatch(pcmk_cman_handle, CMAN_DISPATCH_ALL); - if(rc < 0) { - crm_err("Connection to cman failed: %d", rc); - return FALSE; + + if (rc < 0) { + crm_err("Connection to cman failed: %d", rc); + return FALSE; } return TRUE; } -#define MAX_NODES 256 +# define MAX_NODES 256 -static void cman_event_callback(cman_handle_t handle, void *privdata, int reason, int arg) +static void +cman_event_callback(cman_handle_t handle, void *privdata, int reason, int arg) { int rc = 0, lpc = 0, node_count = 0; cman_cluster_t cluster; static cman_node_t cman_nodes[MAX_NODES]; - gboolean (*dispatch)(unsigned long long, gboolean) = privdata; - + + gboolean(*dispatch) (unsigned long long, gboolean) = privdata; + switch (reason) { - case CMAN_REASON_STATECHANGE: - - memset(&cluster, 0, sizeof(cluster)); - rc = cman_get_cluster(pcmk_cman_handle, &cluster); - if (rc < 0) { - crm_err("Couldn't query cman cluster details: %d %d", rc, errno); - return; - } - - crm_peer_seq = cluster.ci_generation; - if(arg != crm_have_quorum) { - crm_notice("Membership %llu: quorum %s", crm_peer_seq, arg?"acquired":"lost"); - crm_have_quorum = arg; - - } else { - crm_info("Membership %llu: quorum %s", crm_peer_seq, arg?"retained":"still lost"); - } - - rc = cman_get_nodes(pcmk_cman_handle, MAX_NODES, &node_count, cman_nodes); - if (rc < 0) { - crm_err("Couldn't query cman node list: %d %d", rc, errno); - return; - } - - for (lpc = 0; lpc < node_count; lpc++) { - if (cman_nodes[lpc].cn_nodeid == 0) { - /* Never allow node ID 0 to be considered a member #315711 */ - cman_nodes[lpc].cn_member = 0; - } - crm_update_peer(cman_nodes[lpc].cn_nodeid, cman_nodes[lpc].cn_incarnation, - cman_nodes[lpc].cn_member?crm_peer_seq:0, 0, 0, - cman_nodes[lpc].cn_name, cman_nodes[lpc].cn_name, NULL, - cman_nodes[lpc].cn_member?CRM_NODE_MEMBER:CRM_NODE_LOST); - } - - if(dispatch) { - dispatch(crm_peer_seq, crm_have_quorum); - } - break; - - case CMAN_REASON_TRY_SHUTDOWN: - /* Always reply with a negative - pacemaker needs to be stopped first */ - crm_info("CMAN wants to shut down: %s", arg?"forced":"optional"); - cman_replyto_shutdown(pcmk_cman_handle, 0); - break; - - case CMAN_REASON_CONFIG_UPDATE: - /* Ignore */ - break; + case CMAN_REASON_STATECHANGE: + + memset(&cluster, 0, sizeof(cluster)); + rc = cman_get_cluster(pcmk_cman_handle, &cluster); + if (rc < 0) { + crm_err("Couldn't query cman cluster details: %d %d", rc, errno); + return; + } + + crm_peer_seq = cluster.ci_generation; + if (arg != crm_have_quorum) { + crm_notice("Membership %llu: quorum %s", crm_peer_seq, arg ? "acquired" : "lost"); + crm_have_quorum = arg; + + } else { + crm_info("Membership %llu: quorum %s", crm_peer_seq, + arg ? "retained" : "still lost"); + } + + rc = cman_get_nodes(pcmk_cman_handle, MAX_NODES, &node_count, cman_nodes); + if (rc < 0) { + crm_err("Couldn't query cman node list: %d %d", rc, errno); + return; + } + + for (lpc = 0; lpc < node_count; lpc++) { + if (cman_nodes[lpc].cn_nodeid == 0) { + /* Never allow node ID 0 to be considered a member #315711 */ + cman_nodes[lpc].cn_member = 0; + } + crm_update_peer(cman_nodes[lpc].cn_nodeid, cman_nodes[lpc].cn_incarnation, + cman_nodes[lpc].cn_member ? crm_peer_seq : 0, 0, 0, + cman_nodes[lpc].cn_name, cman_nodes[lpc].cn_name, NULL, + cman_nodes[lpc].cn_member ? CRM_NODE_MEMBER : CRM_NODE_LOST); + } + + if (dispatch) { + dispatch(crm_peer_seq, crm_have_quorum); + } + break; + + case CMAN_REASON_TRY_SHUTDOWN: + /* Always reply with a negative - pacemaker needs to be stopped first */ + crm_info("CMAN wants to shut down: %s", arg ? "forced" : "optional"); + cman_replyto_shutdown(pcmk_cman_handle, 0); + break; + + case CMAN_REASON_CONFIG_UPDATE: + /* Ignore */ + break; } } -#endif +# endif -gboolean init_cman_connection( - gboolean (*dispatch)(unsigned long long, gboolean), void (*destroy)(gpointer)) +gboolean +init_cman_connection(gboolean(*dispatch) (unsigned long long, gboolean), void (*destroy) (gpointer)) { -#ifdef SUPPORT_CMAN +# ifdef SUPPORT_CMAN int rc = -1, fd = -1; cman_cluster_t cluster; - + crm_info("Configuring Pacemaker to obtain quorum from cman"); memset(&cluster, 0, sizeof(cluster)); pcmk_cman_handle = cman_init(dispatch); - if(pcmk_cman_handle == NULL || cman_is_active(pcmk_cman_handle) == FALSE) { - crm_err("Couldn't connect to cman"); - goto cman_bail; + if (pcmk_cman_handle == NULL || cman_is_active(pcmk_cman_handle) == FALSE) { + crm_err("Couldn't connect to cman"); + goto cman_bail; } rc = cman_get_cluster(pcmk_cman_handle, &cluster); if (rc < 0) { - crm_err("Couldn't query cman cluster details: %d %d", rc, errno); - goto cman_bail; + crm_err("Couldn't query cman cluster details: %d %d", rc, errno); + goto cman_bail; } ais_cluster_name = crm_strdup(cluster.ci_name); - + rc = cman_start_notification(pcmk_cman_handle, cman_event_callback); if (rc < 0) { - crm_err("Couldn't register for cman notifications: %d %d", rc, errno); - goto cman_bail; + crm_err("Couldn't register for cman notifications: %d %d", rc, errno); + goto cman_bail; } /* Get the current membership state */ cman_event_callback(pcmk_cman_handle, dispatch, CMAN_REASON_STATECHANGE, - cman_is_quorate(pcmk_cman_handle)); + cman_is_quorate(pcmk_cman_handle)); fd = cman_get_fd(pcmk_cman_handle); crm_debug("Adding fd=%d to mainloop", fd); - cman_source = G_main_add_fd( - G_PRIORITY_HIGH, fd, FALSE, pcmk_cman_dispatch, dispatch, destroy); + cman_source = G_main_add_fd(G_PRIORITY_HIGH, fd, FALSE, pcmk_cman_dispatch, dispatch, destroy); cman_bail: if (rc < 0) { - cman_finish(pcmk_cman_handle); - return FALSE; + cman_finish(pcmk_cman_handle); + return FALSE; } -#else +# else crm_err("cman qorum is not supported in this build"); exit(100); -#endif +# endif return TRUE; } -#ifdef SUPPORT_CS_QUORUM -gboolean (*pcmk_cpg_dispatch_fn)(AIS_Message*,char*,int) = NULL; +# ifdef SUPPORT_CS_QUORUM +gboolean(*pcmk_cpg_dispatch_fn) (AIS_Message *, char *, int) = NULL; -static gboolean pcmk_cpg_dispatch(int sender, gpointer user_data) +static gboolean +pcmk_cpg_dispatch(int sender, gpointer user_data) { int rc = 0; + pcmk_cpg_dispatch_fn = user_data; rc = cpg_dispatch(pcmk_cpg_handle, CS_DISPATCH_ALL); - if(rc != CS_OK) { - crm_err("Connection to the CPG API failed: %d", rc); - return FALSE; + if (rc != CS_OK) { + crm_err("Connection to the CPG API failed: %d", rc); + return FALSE; } return TRUE; } -static void pcmk_cpg_deliver ( - cpg_handle_t handle, - const struct cpg_name *groupName, - uint32_t nodeid, - uint32_t pid, - void *msg, - size_t msg_len) +static void +pcmk_cpg_deliver(cpg_handle_t handle, + const struct cpg_name *groupName, + uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len) { - AIS_Message *ais_msg = (AIS_Message*)msg; - if(ais_msg->sender.id > 0 && ais_msg->sender.id != nodeid) { - crm_err("Nodeid mismatch from %d.%d: claimed nodeid=%u", - nodeid, pid, ais_msg->sender.id); - return; + AIS_Message *ais_msg = (AIS_Message *) msg; - } else if(ais_msg->host.size != 0 - && safe_str_neq(ais_msg->host.uname, pcmk_uname)) { - /* Not for us */ - return; + if (ais_msg->sender.id > 0 && ais_msg->sender.id != nodeid) { + crm_err("Nodeid mismatch from %d.%d: claimed nodeid=%u", nodeid, pid, ais_msg->sender.id); + return; + + } else if (ais_msg->host.size != 0 && safe_str_neq(ais_msg->host.uname, pcmk_uname)) { + /* Not for us */ + return; } ais_msg->sender.id = nodeid; - if(ais_msg->sender.size == 0) { - crm_node_t *peer = crm_get_peer(nodeid, NULL); - if(peer == NULL) { - crm_err("Peer with nodeid=%u is unknown", nodeid); + if (ais_msg->sender.size == 0) { + crm_node_t *peer = crm_get_peer(nodeid, NULL); + + if (peer == NULL) { + crm_err("Peer with nodeid=%u is unknown", nodeid); - } else if(peer->uname == NULL) { - crm_err("No uname for peer with nodeid=%u", nodeid); + } else if (peer->uname == NULL) { + crm_err("No uname for peer with nodeid=%u", nodeid); - } else { - crm_notice("Fixing uname for peer with nodeid=%u", nodeid); - ais_msg->sender.size = strlen(peer->uname); - memset(ais_msg->sender.uname, 0, MAX_NAME); - memcpy(ais_msg->sender.uname, peer->uname, ais_msg->sender.size); - } + } else { + crm_notice("Fixing uname for peer with nodeid=%u", nodeid); + ais_msg->sender.size = strlen(peer->uname); + memset(ais_msg->sender.uname, 0, MAX_NAME); + memcpy(ais_msg->sender.uname, peer->uname, ais_msg->sender.size); + } } ais_dispatch_message(ais_msg, pcmk_cpg_dispatch_fn); } -static void pcmk_cpg_membership( - cpg_handle_t handle, - const struct cpg_name *groupName, - const struct cpg_address *member_list, size_t member_list_entries, - const struct cpg_address *left_list, size_t left_list_entries, - const struct cpg_address *joined_list, size_t joined_list_entries) +static void +pcmk_cpg_membership(cpg_handle_t handle, + const struct cpg_name *groupName, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) { /* Don't care about CPG membership */ } -static gboolean pcmk_quorum_dispatch(int sender, gpointer user_data) +static gboolean +pcmk_quorum_dispatch(int sender, gpointer user_data) { int rc = 0; + rc = quorum_dispatch(pcmk_quorum_handle, CS_DISPATCH_ALL); - if(rc < 0) { - crm_err("Connection to the Quorum API failed: %d", rc); - return FALSE; + if (rc < 0) { + crm_err("Connection to the Quorum API failed: %d", rc); + return FALSE; } return TRUE; } -static void pcmk_quorum_notification( - quorum_handle_t handle, - uint32_t quorate, - uint64_t ring_id, - uint32_t view_list_entries, - uint32_t *view_list) +static void +pcmk_quorum_notification(quorum_handle_t handle, + uint32_t quorate, + uint64_t ring_id, uint32_t view_list_entries, uint32_t * view_list) { - int i; - - if(quorate != crm_have_quorum) { - crm_notice("Membership "U64T": quorum %s (%lu)", ring_id, - quorate?"acquired":"lost", (long unsigned int)view_list_entries); - crm_have_quorum = quorate; - - } else { - crm_info("Membership "U64T": quorum %s (%lu)", ring_id, - quorate?"retained":"still lost", (long unsigned int)view_list_entries); - } - for (i=0; ihost.type; int tmp_size = msg->header.size - sizeof(AIS_Message); - if(sane && msg->header.size == 0) { - crm_warn("Message with no size"); - sane = FALSE; - } - - if(sane && msg->header.error != CS_OK) { - crm_warn("Message header contains an error: %d", msg->header.error); - sane = FALSE; - } - - if(sane && ais_data_len(msg) != tmp_size) { - crm_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg), tmp_size); - sane = TRUE; - } - - if(sane && ais_data_len(msg) == 0) { - crm_warn("Message with no payload"); - sane = FALSE; - } - - if(sane && data && msg->is_compressed == FALSE) { - int str_size = strlen(data) + 1; - if(ais_data_len(msg) != str_size) { - int lpc = 0; - crm_warn("Message payload is corrupted: expected %d bytes, got %d", - ais_data_len(msg), str_size); - sane = FALSE; - for(lpc = (str_size - 10); lpc < msg->size; lpc++) { - if(lpc < 0) { - lpc = 0; - } - crm_debug("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]); - } - } - } - - if(sane == FALSE) { - crm_err("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", - msg->id, ais_dest(&(msg->host)), msg_type2text(dest), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, msg->is_compressed, ais_data_len(msg), - msg->header.size); - - } else if(repaired) { - crm_err("Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", - msg->id, ais_dest(&(msg->host)), msg_type2text(dest), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, msg->is_compressed, ais_data_len(msg), - msg->header.size); + if (sane && msg->header.size == 0) { + crm_warn("Message with no size"); + sane = FALSE; + } + + if (sane && msg->header.error != CS_OK) { + crm_warn("Message header contains an error: %d", msg->header.error); + sane = FALSE; + } + + if (sane && ais_data_len(msg) != tmp_size) { + crm_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg), + tmp_size); + sane = TRUE; + } + + if (sane && ais_data_len(msg) == 0) { + crm_warn("Message with no payload"); + sane = FALSE; + } + + if (sane && data && msg->is_compressed == FALSE) { + int str_size = strlen(data) + 1; + + if (ais_data_len(msg) != str_size) { + int lpc = 0; + + crm_warn("Message payload is corrupted: expected %d bytes, got %d", + ais_data_len(msg), str_size); + sane = FALSE; + for (lpc = (str_size - 10); lpc < msg->size; lpc++) { + if (lpc < 0) { + lpc = 0; + } + crm_debug("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]); + } + } + } + + if (sane == FALSE) { + crm_err("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", + msg->id, ais_dest(&(msg->host)), msg_type2text(dest), + ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), + msg->sender.pid, msg->is_compressed, ais_data_len(msg), msg->header.size); + + } else if (repaired) { + crm_err + ("Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", + msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)), + msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed, + ais_data_len(msg), msg->header.size); } else { - crm_debug_3("Verfied message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", - msg->id, ais_dest(&(msg->host)), msg_type2text(dest), - ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), - msg->sender.pid, msg->is_compressed, ais_data_len(msg), - msg->header.size); + crm_debug_3 + ("Verfied message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)", + msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)), + msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed, + ais_data_len(msg), msg->header.size); } - + return sane; } #endif -static int get_config_opt( - confdb_handle_t config, - hdb_handle_t object_handle, - const char *key, char **value, const char *fallback) +static int +get_config_opt(confdb_handle_t config, + hdb_handle_t object_handle, const char *key, char **value, const char *fallback) { size_t len = 0; char *env_key = NULL; const char *env_value = NULL; char buffer[256]; - if(*value) { - crm_free(*value); - *value = NULL; + if (*value) { + crm_free(*value); + *value = NULL; } - if(object_handle > 0) { - if(CS_OK == confdb_key_get(config, object_handle, key, strlen(key), &buffer, &len)) { - *value = crm_strdup(buffer); - } + if (object_handle > 0) { + if (CS_OK == confdb_key_get(config, object_handle, key, strlen(key), &buffer, &len)) { + *value = crm_strdup(buffer); + } } - + if (*value) { - crm_info("Found '%s' for option: %s", *value, key); - return 0; + crm_info("Found '%s' for option: %s", *value, key); + return 0; } env_key = crm_concat("HA", key, '_'); env_value = getenv(env_key); crm_free(env_key); if (*value) { - crm_info("Found '%s' in ENV for option: %s", *value, key); - *value = crm_strdup(env_value); - return 0; + crm_info("Found '%s' in ENV for option: %s", *value, key); + *value = crm_strdup(env_value); + return 0; } - if(fallback) { - crm_info("Defaulting to '%s' for option: %s", fallback, key); - *value = crm_strdup(fallback); + if (fallback) { + crm_info("Defaulting to '%s' for option: %s", fallback, key); + *value = crm_strdup(fallback); } else { - crm_info("No default for option: %s", key); + crm_info("No default for option: %s", key); } - + return -1; } -static confdb_handle_t config_find_init(confdb_handle_t config) +static confdb_handle_t +config_find_init(confdb_handle_t config) { - cs_error_t rc = CS_OK; + cs_error_t rc = CS_OK; confdb_handle_t local_handle = OBJECT_PARENT_HANDLE; rc = confdb_object_find_start(config, local_handle); - if(rc == CS_OK) { - return local_handle; + if (rc == CS_OK) { + return local_handle; } else { - crm_err("Couldn't create search context: %d", rc); + crm_err("Couldn't create search context: %d", rc); } return 0; } -static hdb_handle_t config_find_next( - confdb_handle_t config, const char *name, confdb_handle_t top_handle) +static hdb_handle_t +config_find_next(confdb_handle_t config, const char *name, confdb_handle_t top_handle) { cs_error_t rc = CS_OK; hdb_handle_t local_handle = 0; - if(top_handle == 0) { - crm_err("Couldn't search for %s: no valid context", name); - return 0; + if (top_handle == 0) { + crm_err("Couldn't search for %s: no valid context", name); + return 0; } - - crm_debug_2("Searching for %s in "HDB_X_FORMAT, name, top_handle); + + crm_debug_2("Searching for %s in " HDB_X_FORMAT, name, top_handle); rc = confdb_object_find(config, top_handle, name, strlen(name), &local_handle); - if(rc != CS_OK) { - crm_info("No additional configuration supplied for: %s", name); - local_handle = 0; + if (rc != CS_OK) { + crm_info("No additional configuration supplied for: %s", name); + local_handle = 0; } else { - crm_info("Processing additional %s options...", name); + crm_info("Processing additional %s options...", name); } return local_handle; } -enum cluster_type_e -find_corosync_variant(void) +enum cluster_type_e +find_corosync_variant(void) { confdb_handle_t config; enum cluster_type_e found = pcmk_cluster_unknown; int rc; char *value = NULL; confdb_handle_t top_handle = 0; hdb_handle_t local_handle = 0; - static confdb_callbacks_t callbacks = {}; + static confdb_callbacks_t callbacks = { }; - rc = confdb_initialize (&config, &callbacks); + rc = confdb_initialize(&config, &callbacks); if (rc != CS_OK) { - crm_debug("Could not initialize Cluster Configuration Database API instance error %d", rc); - return found; + crm_debug("Could not initialize Cluster Configuration Database API instance error %d", rc); + return found; } top_handle = config_find_init(config); local_handle = config_find_next(config, "service", top_handle); - while(local_handle) { - crm_free(value); - get_config_opt(config, local_handle, "name", &value, NULL); - if(safe_str_eq("pacemaker", value)) { - found = pcmk_cluster_classic_ais; - - crm_free(value); - get_config_opt(config, local_handle, "ver", &value, "0"); - crm_trace("Found Pacemaker plugin version: %s", value); - break; - } - - local_handle = config_find_next(config, "service", top_handle); + while (local_handle) { + crm_free(value); + get_config_opt(config, local_handle, "name", &value, NULL); + if (safe_str_eq("pacemaker", value)) { + found = pcmk_cluster_classic_ais; + + crm_free(value); + get_config_opt(config, local_handle, "ver", &value, "0"); + crm_trace("Found Pacemaker plugin version: %s", value); + break; + } + + local_handle = config_find_next(config, "service", top_handle); } crm_free(value); - if(found == pcmk_cluster_unknown) { - top_handle = config_find_init(config); - local_handle = config_find_next(config, "quorum", top_handle); - get_config_opt(config, local_handle, "provider", &value, NULL); + if (found == pcmk_cluster_unknown) { + top_handle = config_find_init(config); + local_handle = config_find_next(config, "quorum", top_handle); + get_config_opt(config, local_handle, "provider", &value, NULL); - if(safe_str_eq("quorum_cman", value)) { - crm_trace("Found CMAN quorum provider"); - found = pcmk_cluster_cman; - } + if (safe_str_eq("quorum_cman", value)) { + crm_trace("Found CMAN quorum provider"); + found = pcmk_cluster_cman; + } } crm_free(value); - if(found == pcmk_cluster_unknown) { - crm_trace("Defaulting to a 'bare' corosync cluster"); - found = pcmk_cluster_corosync; + if (found == pcmk_cluster_unknown) { + crm_trace("Defaulting to a 'bare' corosync cluster"); + found = pcmk_cluster_corosync; } - - confdb_finalize (config); + + confdb_finalize(config); return found; } diff --git a/lib/common/cluster.c b/lib/common/cluster.c index 6fd2542447..e8b2ab27b3 100644 --- a/lib/common/cluster.c +++ b/lib/common/cluster.c @@ -1,425 +1,433 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "stack.h" CRM_TRACE_INIT_DATA(cluster); #if SUPPORT_HEARTBEAT void *hb_library = NULL; #endif -xmlNode *create_common_message( - xmlNode *original_request, xmlNode *xml_response_data); +xmlNode *create_common_message(xmlNode * original_request, xmlNode * xml_response_data); -gboolean crm_cluster_connect( - char **our_uname, char **our_uuid, void *dispatch, void *destroy, +gboolean +crm_cluster_connect(char **our_uname, char **our_uuid, void *dispatch, void *destroy, #if SUPPORT_HEARTBEAT - ll_cluster_t **hb_conn + ll_cluster_t ** hb_conn #else - void **hb_conn + void **hb_conn #endif - ) { + ) +{ enum cluster_type_e type = get_cluster_type(); + crm_notice("Connecting to cluster infrastructure: %s", name_for_cluster_type(type)); - if(hb_conn != NULL) { - *hb_conn = NULL; + if (hb_conn != NULL) { + *hb_conn = NULL; } - #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - crm_peer_init(); - return init_ais_connection(dispatch, destroy, our_uuid, our_uname, NULL); + if (is_openais_cluster()) { + crm_peer_init(); + return init_ais_connection(dispatch, destroy, our_uuid, our_uname, NULL); } #endif - + #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - int rv; - CRM_ASSERT(hb_conn != NULL); - - if(*hb_conn == NULL) { - /* No object passed in, create a new one. */ - ll_cluster_t* (*new_cluster)(const char * llctype) = find_library_function( - &hb_library, HEARTBEAT_LIBRARY, "ll_cluster_new"); - - *hb_conn = (*new_cluster)("heartbeat"); - /* dlclose(handle); */ - - } else { - /* Object passed in. Disconnect first, then reconnect below. */ - ll_cluster_t *conn = *hb_conn; - conn->llc_ops->signoff(conn, FALSE); - } - - /* make sure we are disconnected first with the old object, if any. */ - if (heartbeat_cluster && heartbeat_cluster != *hb_conn) { - heartbeat_cluster->llc_ops->signoff(heartbeat_cluster, FALSE); - } - - CRM_ASSERT(*hb_conn != NULL); - heartbeat_cluster = *hb_conn; - - rv = register_heartbeat_conn( - heartbeat_cluster, our_uuid, our_uname, dispatch, destroy); - - if (rv) { - /* we'll benefit from a bigger queue length on heartbeat side. - * Otherwise, if peers send messages faster than we can consume - * them right now, heartbeat messaging layer will kick us out once - * it's (small) default queue fills up :( - * If we fail to adjust the sendq length, that's not yet fatal, though. - */ - if (HA_OK != (*hb_conn)->llc_ops->set_sendq_len(*hb_conn, 1024)) { - crm_warn("Cannot set sendq length: %s", - (*hb_conn)->llc_ops->errmsg(*hb_conn)); - } - } - return rv; + if (is_heartbeat_cluster()) { + int rv; + + CRM_ASSERT(hb_conn != NULL); + + if (*hb_conn == NULL) { + /* No object passed in, create a new one. */ + ll_cluster_t *(*new_cluster) (const char *llctype) = + find_library_function(&hb_library, HEARTBEAT_LIBRARY, "ll_cluster_new"); + + *hb_conn = (*new_cluster) ("heartbeat"); + /* dlclose(handle); */ + + } else { + /* Object passed in. Disconnect first, then reconnect below. */ + ll_cluster_t *conn = *hb_conn; + + conn->llc_ops->signoff(conn, FALSE); + } + + /* make sure we are disconnected first with the old object, if any. */ + if (heartbeat_cluster && heartbeat_cluster != *hb_conn) { + heartbeat_cluster->llc_ops->signoff(heartbeat_cluster, FALSE); + } + + CRM_ASSERT(*hb_conn != NULL); + heartbeat_cluster = *hb_conn; + + rv = register_heartbeat_conn(heartbeat_cluster, our_uuid, our_uname, dispatch, destroy); + + if (rv) { + /* we'll benefit from a bigger queue length on heartbeat side. + * Otherwise, if peers send messages faster than we can consume + * them right now, heartbeat messaging layer will kick us out once + * it's (small) default queue fills up :( + * If we fail to adjust the sendq length, that's not yet fatal, though. + */ + if (HA_OK != (*hb_conn)->llc_ops->set_sendq_len(*hb_conn, 1024)) { + crm_warn("Cannot set sendq length: %s", (*hb_conn)->llc_ops->errmsg(*hb_conn)); + } + } + return rv; } #endif crm_info("Unsupported cluster stack: %s", getenv("HA_cluster_type")); return FALSE; } -gboolean send_cluster_message( - const char *node, enum crm_ais_msg_types service, xmlNode *data, gboolean ordered) { +gboolean +send_cluster_message(const char *node, enum crm_ais_msg_types service, xmlNode * data, + gboolean ordered) +{ #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - return send_ais_message(data, FALSE, node, service); + if (is_openais_cluster()) { + return send_ais_message(data, FALSE, node, service); } #endif #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - return send_ha_message(heartbeat_cluster, data, node, ordered); + if (is_heartbeat_cluster()) { + return send_ha_message(heartbeat_cluster, data, node, ordered); } #endif return FALSE; } static GHashTable *crm_uuid_cache = NULL; static GHashTable *crm_uname_cache = NULL; void empty_uuid_cache(void) { - if(crm_uuid_cache != NULL) { - g_hash_table_destroy(crm_uuid_cache); - crm_uuid_cache = NULL; - } + if (crm_uuid_cache != NULL) { + g_hash_table_destroy(crm_uuid_cache); + crm_uuid_cache = NULL; + } } void unget_uuid(const char *uname) { - if(crm_uuid_cache == NULL) { - return; - } - g_hash_table_remove(crm_uuid_cache, uname); + if (crm_uuid_cache == NULL) { + return; + } + g_hash_table_remove(crm_uuid_cache, uname); } const char * -get_uuid(const char *uname) +get_uuid(const char *uname) { char *uuid_calc = NULL; + CRM_CHECK(uname != NULL, return NULL); - if(crm_uuid_cache == NULL) { - crm_uuid_cache = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); + if (crm_uuid_cache == NULL) { + crm_uuid_cache = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); } - + CRM_CHECK(uname != NULL, return NULL); - + /* avoid blocking calls where possible */ uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname); - if(uuid_calc != NULL) { - return uuid_calc; + if (uuid_calc != NULL) { + return uuid_calc; } - #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - uuid_calc = crm_strdup(uname); - goto fallback; + if (is_openais_cluster()) { + uuid_calc = crm_strdup(uname); + goto fallback; } #endif #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - cl_uuid_t uuid_raw; - const char *unknown = "00000000-0000-0000-0000-000000000000"; - - if(heartbeat_cluster == NULL) { - crm_warn("No connection to heartbeat, using uuid=uname"); - uuid_calc = crm_strdup(uname); - goto fallback; - } - - if(heartbeat_cluster->llc_ops->get_uuid_by_name( - heartbeat_cluster, uname, &uuid_raw) == HA_FAIL) { - crm_err("get_uuid_by_name() call failed for host %s", uname); - crm_free(uuid_calc); - return NULL; - } - - crm_malloc0(uuid_calc, 50); - cl_uuid_unparse(&uuid_raw, uuid_calc); - - if(safe_str_eq(uuid_calc, unknown)) { - crm_warn("Could not calculate UUID for %s", uname); - crm_free(uuid_calc); - return NULL; - } + if (is_heartbeat_cluster()) { + cl_uuid_t uuid_raw; + const char *unknown = "00000000-0000-0000-0000-000000000000"; + + if (heartbeat_cluster == NULL) { + crm_warn("No connection to heartbeat, using uuid=uname"); + uuid_calc = crm_strdup(uname); + goto fallback; + } + + if (heartbeat_cluster->llc_ops->get_uuid_by_name(heartbeat_cluster, uname, &uuid_raw) == + HA_FAIL) { + crm_err("get_uuid_by_name() call failed for host %s", uname); + crm_free(uuid_calc); + return NULL; + } + + crm_malloc0(uuid_calc, 50); + cl_uuid_unparse(&uuid_raw, uuid_calc); + + if (safe_str_eq(uuid_calc, unknown)) { + crm_warn("Could not calculate UUID for %s", uname); + crm_free(uuid_calc); + return NULL; + } } #endif goto fallback; - + fallback: - g_hash_table_insert(crm_uuid_cache, crm_strdup(uname), uuid_calc); - uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname); + g_hash_table_insert(crm_uuid_cache, crm_strdup(uname), uuid_calc); + uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname); - return uuid_calc; + return uuid_calc; } const char * -get_uname(const char *uuid) +get_uname(const char *uuid) { char *uname = NULL; - - if(crm_uname_cache == NULL) { - crm_uname_cache = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); + + if (crm_uname_cache == NULL) { + crm_uname_cache = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); } - + CRM_CHECK(uuid != NULL, return NULL); - + /* avoid blocking calls where possible */ uname = g_hash_table_lookup(crm_uname_cache, uuid); - if(uname != NULL) { - return uname; + if (uname != NULL) { + return uname; } - #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - g_hash_table_insert(crm_uname_cache, crm_strdup(uuid), crm_strdup(uuid)); + if (is_openais_cluster()) { + g_hash_table_insert(crm_uname_cache, crm_strdup(uuid), crm_strdup(uuid)); } #endif - + #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - if(heartbeat_cluster != NULL && uuid != NULL) { - cl_uuid_t uuid_raw; - char *uuid_copy = crm_strdup(uuid); - cl_uuid_parse(uuid_copy, &uuid_raw); - crm_malloc(uname, MAX_NAME); - - if(heartbeat_cluster->llc_ops->get_name_by_uuid( - heartbeat_cluster, &uuid_raw, uname, MAX_NAME) == HA_FAIL) { - crm_err("Could not calculate uname for %s", uuid); - crm_free(uuid_copy); - crm_free(uname); - - } else { - g_hash_table_insert(crm_uname_cache, uuid_copy, uname); - } - } + if (is_heartbeat_cluster()) { + if (heartbeat_cluster != NULL && uuid != NULL) { + cl_uuid_t uuid_raw; + char *uuid_copy = crm_strdup(uuid); + + cl_uuid_parse(uuid_copy, &uuid_raw); + crm_malloc(uname, MAX_NAME); + + if (heartbeat_cluster->llc_ops->get_name_by_uuid(heartbeat_cluster, &uuid_raw, uname, + MAX_NAME) == HA_FAIL) { + crm_err("Could not calculate uname for %s", uuid); + crm_free(uuid_copy); + crm_free(uname); + + } else { + g_hash_table_insert(crm_uname_cache, uuid_copy, uname); + } + } } #endif return g_hash_table_lookup(crm_uname_cache, uuid); } void -set_uuid(xmlNode *node,const char *attr,const char *uname) +set_uuid(xmlNode * node, const char *attr, const char *uname) { - const char *uuid_calc = get_uuid(uname); - crm_xml_add(node, attr, uuid_calc); - return; + const char *uuid_calc = get_uuid(uname); + + crm_xml_add(node, attr, uuid_calc); + return; } -xmlNode* +xmlNode * createPingAnswerFragment(const char *from, const char *status) { - xmlNode *ping = NULL; - - - ping = create_xml_node(NULL, XML_CRM_TAG_PING); - - crm_xml_add(ping, XML_PING_ATTR_STATUS, status); - crm_xml_add(ping, XML_PING_ATTR_SYSFROM, from); - - return ping; + xmlNode *ping = NULL; + + ping = create_xml_node(NULL, XML_CRM_TAG_PING); + + crm_xml_add(ping, XML_PING_ATTR_STATUS, status); + crm_xml_add(ping, XML_PING_ATTR_SYSFROM, from); + + return ping; } const char * name_for_cluster_type(enum cluster_type_e type) { - switch(type) { - case pcmk_cluster_classic_ais: - return "classic openais (with plugin)"; - case pcmk_cluster_cman: - return "cman"; - case pcmk_cluster_corosync: - return "corosync"; - case pcmk_cluster_heartbeat: - return "heartbeat"; - case pcmk_cluster_unknown: - return "unknown"; - case pcmk_cluster_invalid: - return "invalid"; + switch (type) { + case pcmk_cluster_classic_ais: + return "classic openais (with plugin)"; + case pcmk_cluster_cman: + return "cman"; + case pcmk_cluster_corosync: + return "corosync"; + case pcmk_cluster_heartbeat: + return "heartbeat"; + case pcmk_cluster_unknown: + return "unknown"; + case pcmk_cluster_invalid: + return "invalid"; } crm_err("Invalid cluster type: %d", type); return "invalid"; } /* Do not expose these two */ int set_cluster_type(enum cluster_type_e type); static enum cluster_type_e cluster_type = pcmk_cluster_unknown; -int set_cluster_type(enum cluster_type_e type) +int +set_cluster_type(enum cluster_type_e type) { - if(cluster_type == pcmk_cluster_unknown) { - crm_info("Cluster type set to: %s", name_for_cluster_type(type)); - cluster_type = type; - return 0; + if (cluster_type == pcmk_cluster_unknown) { + crm_info("Cluster type set to: %s", name_for_cluster_type(type)); + cluster_type = type; + return 0; - } else if(cluster_type == type) { - return 0; + } else if (cluster_type == type) { + return 0; - } else if(pcmk_cluster_unknown == type) { - cluster_type = type; - return 0; + } else if (pcmk_cluster_unknown == type) { + cluster_type = type; + return 0; } crm_err("Cluster type already set to %s, ignoring %s", - name_for_cluster_type(cluster_type), - name_for_cluster_type(type)); + name_for_cluster_type(cluster_type), name_for_cluster_type(type)); return -1; } enum cluster_type_e -get_cluster_type(void) +get_cluster_type(void) { - if(cluster_type == pcmk_cluster_unknown) { - const char *cluster = getenv("HA_cluster_type"); - cluster_type = pcmk_cluster_invalid; - if(cluster) { - crm_info("Cluster type is: '%s'", cluster); + if (cluster_type == pcmk_cluster_unknown) { + const char *cluster = getenv("HA_cluster_type"); + + cluster_type = pcmk_cluster_invalid; + if (cluster) { + crm_info("Cluster type is: '%s'", cluster); - } else { + } else { #if SUPPORT_COROSYNC - cluster_type = find_corosync_variant(); - if(cluster_type == pcmk_cluster_unknown) { - cluster = "heartbeat"; - crm_info("Assuming a 'heartbeat' based cluster"); - } else { - cluster = name_for_cluster_type(cluster_type); - crm_info("Detected an active '%s' cluster", cluster); - } + cluster_type = find_corosync_variant(); + if (cluster_type == pcmk_cluster_unknown) { + cluster = "heartbeat"; + crm_info("Assuming a 'heartbeat' based cluster"); + } else { + cluster = name_for_cluster_type(cluster_type); + crm_info("Detected an active '%s' cluster", cluster); + } #else - cluster = "heartbeat"; + cluster = "heartbeat"; #endif - } - - if(safe_str_eq(cluster, "heartbeat")) { + } + + if (safe_str_eq(cluster, "heartbeat")) { #if SUPPORT_HEARTBEAT - cluster_type = pcmk_cluster_heartbeat; + cluster_type = pcmk_cluster_heartbeat; #else - cluster_type = pcmk_cluster_invalid; + cluster_type = pcmk_cluster_invalid; #endif - } else if(safe_str_eq(cluster, "openais") - || safe_str_eq(cluster, "classic openais (with plugin)")) { + } else if (safe_str_eq(cluster, "openais") + || safe_str_eq(cluster, "classic openais (with plugin)")) { #if SUPPORT_COROSYNC - cluster_type = pcmk_cluster_classic_ais; + cluster_type = pcmk_cluster_classic_ais; #else - cluster_type = pcmk_cluster_invalid; + cluster_type = pcmk_cluster_invalid; #endif - } else if(safe_str_eq(cluster, "corosync")) { + } else if (safe_str_eq(cluster, "corosync")) { #if SUPPORT_COROSYNC - cluster_type = pcmk_cluster_corosync; + cluster_type = pcmk_cluster_corosync; #else - cluster_type = pcmk_cluster_invalid; + cluster_type = pcmk_cluster_invalid; #endif - } else if(safe_str_eq(cluster, "cman")) { + } else if (safe_str_eq(cluster, "cman")) { #if SUPPORT_CMAN - cluster_type = pcmk_cluster_cman; + cluster_type = pcmk_cluster_cman; #else - cluster_type = pcmk_cluster_invalid; + cluster_type = pcmk_cluster_invalid; #endif - } else { - cluster_type = pcmk_cluster_invalid; - } - - if(cluster_type == pcmk_cluster_invalid) { - crm_crit("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.", cluster); - exit(100); - } + } else { + cluster_type = pcmk_cluster_invalid; + } + + if (cluster_type == pcmk_cluster_invalid) { + crm_crit + ("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.", + cluster); + exit(100); + } } return cluster_type; } -gboolean is_cman_cluster(void) +gboolean +is_cman_cluster(void) { return get_cluster_type() == pcmk_cluster_cman; } -gboolean is_corosync_cluster(void) +gboolean +is_corosync_cluster(void) { return get_cluster_type() == pcmk_cluster_corosync; } -gboolean is_classic_ais_cluster(void) +gboolean +is_classic_ais_cluster(void) { return get_cluster_type() == pcmk_cluster_classic_ais; } -gboolean is_openais_cluster(void) +gboolean +is_openais_cluster(void) { enum cluster_type_e type = get_cluster_type(); - if(type == pcmk_cluster_classic_ais) { - return TRUE; - } else if(type == pcmk_cluster_corosync) { - return TRUE; - } else if(type == pcmk_cluster_cman) { - return TRUE; + + if (type == pcmk_cluster_classic_ais) { + return TRUE; + } else if (type == pcmk_cluster_corosync) { + return TRUE; + } else if (type == pcmk_cluster_cman) { + return TRUE; } return FALSE; } -gboolean is_heartbeat_cluster(void) +gboolean +is_heartbeat_cluster(void) { return get_cluster_type() == pcmk_cluster_heartbeat; } - diff --git a/lib/common/heartbeat.c b/lib/common/heartbeat.c index f5e377d473..13c71ba350 100644 --- a/lib/common/heartbeat.c +++ b/lib/common/heartbeat.c @@ -1,222 +1,218 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "stack.h" - -xmlNode *create_common_message( - xmlNode *original_request, xmlNode *xml_response_data); - +xmlNode *create_common_message(xmlNode * original_request, xmlNode * xml_response_data); #if SUPPORT_HEARTBEAT ll_cluster_t *heartbeat_cluster = NULL; -gboolean -send_ha_message(ll_cluster_t *hb_conn, xmlNode *xml, const char *node, gboolean force_ordered) +gboolean +send_ha_message(ll_cluster_t * hb_conn, xmlNode * xml, const char *node, gboolean force_ordered) { gboolean all_is_good = TRUE; HA_Message *msg = convert_xml_message(xml); - - if (msg == NULL) { - crm_err("cant send NULL message"); - all_is_good = FALSE; - - } else if(hb_conn == NULL) { - crm_err("No heartbeat connection specified"); - all_is_good = FALSE; - - } else if(hb_conn->llc_ops->chan_is_connected(hb_conn) == FALSE) { - crm_err("Not connected to Heartbeat"); - all_is_good = FALSE; - - } else if(node != NULL) { - if(hb_conn->llc_ops->send_ordered_nodemsg( - hb_conn, msg, node) != HA_OK) { - all_is_good = FALSE; - crm_err("Send failed"); - } - - } else if(force_ordered) { - if(hb_conn->llc_ops->send_ordered_clustermsg(hb_conn, msg) != HA_OK) { - all_is_good = FALSE; - crm_err("Broadcast Send failed"); - } - - } else { - if(hb_conn->llc_ops->sendclustermsg(hb_conn, msg) != HA_OK) { - all_is_good = FALSE; - crm_err("Broadcast Send failed"); - } - } - - if(all_is_good == FALSE && hb_conn != NULL) { - IPC_Channel *ipc = NULL; - IPC_Queue *send_q = NULL; - - if(hb_conn->llc_ops->chan_is_connected(hb_conn) != HA_OK) { - ipc = hb_conn->llc_ops->ipcchan(hb_conn); - } - if(ipc != NULL) { + + if (msg == NULL) { + crm_err("cant send NULL message"); + all_is_good = FALSE; + + } else if (hb_conn == NULL) { + crm_err("No heartbeat connection specified"); + all_is_good = FALSE; + + } else if (hb_conn->llc_ops->chan_is_connected(hb_conn) == FALSE) { + crm_err("Not connected to Heartbeat"); + all_is_good = FALSE; + + } else if (node != NULL) { + if (hb_conn->llc_ops->send_ordered_nodemsg(hb_conn, msg, node) != HA_OK) { + all_is_good = FALSE; + crm_err("Send failed"); + } + + } else if (force_ordered) { + if (hb_conn->llc_ops->send_ordered_clustermsg(hb_conn, msg) != HA_OK) { + all_is_good = FALSE; + crm_err("Broadcast Send failed"); + } + + } else { + if (hb_conn->llc_ops->sendclustermsg(hb_conn, msg) != HA_OK) { + all_is_good = FALSE; + crm_err("Broadcast Send failed"); + } + } + + if (all_is_good == FALSE && hb_conn != NULL) { + IPC_Channel *ipc = NULL; + IPC_Queue *send_q = NULL; + + if (hb_conn->llc_ops->chan_is_connected(hb_conn) != HA_OK) { + ipc = hb_conn->llc_ops->ipcchan(hb_conn); + } + if (ipc != NULL) { /* ipc->ops->resume_io(ipc); */ - send_q = ipc->send_queue; - } - if(send_q != NULL) { - CRM_CHECK(send_q->current_qlen < send_q->max_qlen, ;); - } - } - - crm_log_xml(all_is_good?LOG_MSG:LOG_WARNING, "HA[outbound]", xml); - crm_msg_del(msg); - return all_is_good; + send_q = ipc->send_queue; + } + if (send_q != NULL) { + CRM_CHECK(send_q->current_qlen < send_q->max_qlen,; + ); + } + } + + crm_log_xml(all_is_good ? LOG_MSG : LOG_WARNING, "HA[outbound]", xml); + crm_msg_del(msg); + return all_is_good; } gboolean -ha_msg_dispatch(ll_cluster_t *cluster_conn, gpointer user_data) +ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data) { IPC_Channel *channel = NULL; + crm_debug_3("Invoked"); - - if(cluster_conn != NULL) { - channel = cluster_conn->llc_ops->ipcchan(cluster_conn); + + if (cluster_conn != NULL) { + channel = cluster_conn->llc_ops->ipcchan(cluster_conn); } - + CRM_CHECK(cluster_conn != NULL, return FALSE); CRM_CHECK(channel != NULL, return FALSE); - - if(channel != NULL && IPC_ISRCONN(channel)) { - if(cluster_conn->llc_ops->msgready(cluster_conn) == 0) { - crm_debug_2("no message ready yet"); - } - /* invoke the callbacks but dont block */ - cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); + + if (channel != NULL && IPC_ISRCONN(channel)) { + if (cluster_conn->llc_ops->msgready(cluster_conn) == 0) { + crm_debug_2("no message ready yet"); + } + /* invoke the callbacks but dont block */ + cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); } - + if (channel == NULL || channel->ch_status != IPC_CONNECT) { - crm_info("Lost connection to heartbeat service."); - return FALSE; + crm_info("Lost connection to heartbeat service."); + return FALSE; } - + return TRUE; } gboolean -register_heartbeat_conn( - ll_cluster_t *hb_cluster, char **uuid, char **uname, - void (*hb_message)(HA_Message *msg, void* private_data), - void (*hb_destroy)(gpointer user_data)) +register_heartbeat_conn(ll_cluster_t * hb_cluster, char **uuid, char **uname, + void (*hb_message) (HA_Message * msg, void *private_data), + void (*hb_destroy) (gpointer user_data)) { const char *const_uuid = NULL; const char *const_uname = NULL; - + crm_debug("Signing in with Heartbeat"); if (hb_cluster->llc_ops->signon(hb_cluster, crm_system_name) != HA_OK) { - crm_err("Cannot sign on with heartbeat: %s", - hb_cluster->llc_ops->errmsg(hb_cluster)); - return FALSE; + crm_err("Cannot sign on with heartbeat: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); + return FALSE; } - - if (HA_OK != hb_cluster->llc_ops->set_msg_callback( - hb_cluster, crm_system_name, hb_message, hb_cluster)){ - - crm_err("Cannot set msg callback: %s", - hb_cluster->llc_ops->errmsg(hb_cluster)); - return FALSE; + + if (HA_OK != + hb_cluster->llc_ops->set_msg_callback(hb_cluster, crm_system_name, hb_message, + hb_cluster)) { + + crm_err("Cannot set msg callback: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); + return FALSE; } { void *handle = NULL; - GLLclusterSource* (*g_main_add_cluster)( - int priority, ll_cluster_t* api, gboolean can_recurse, - gboolean (*dispatch)(ll_cluster_t* source_data,gpointer user_data), - gpointer userdata, GDestroyNotify notify) = find_library_function( - &handle, HEARTBEAT_LIBRARY, "G_main_add_ll_cluster"); - - (*g_main_add_cluster)(G_PRIORITY_HIGH, hb_cluster, - FALSE, ha_msg_dispatch, hb_cluster, hb_destroy); + GLLclusterSource *(*g_main_add_cluster) (int priority, ll_cluster_t * api, + gboolean can_recurse, + gboolean(*dispatch) (ll_cluster_t * source_data, + gpointer user_data), + gpointer userdata, GDestroyNotify notify) = + find_library_function(&handle, HEARTBEAT_LIBRARY, "G_main_add_ll_cluster"); + + (*g_main_add_cluster) (G_PRIORITY_HIGH, hb_cluster, + FALSE, ha_msg_dispatch, hb_cluster, hb_destroy); dlclose(handle); } - + const_uname = hb_cluster->llc_ops->get_mynodeid(hb_cluster); CRM_CHECK(const_uname != NULL, return FALSE); - + const_uuid = get_uuid(const_uname); CRM_CHECK(const_uuid != NULL, return FALSE); crm_info("Hostname: %s", const_uname); crm_info("UUID: %s", const_uuid); - if(uname) { - *uname = crm_strdup(const_uname); + if (uname) { + *uname = crm_strdup(const_uname); } - if(uuid) { - *uuid = crm_strdup(const_uuid); + if (uuid) { + *uuid = crm_strdup(const_uuid); } - + return TRUE; } gboolean ccm_have_quorum(oc_ed_t event) { - if(event==OC_EV_MS_NEW_MEMBERSHIP - || event==OC_EV_MS_PRIMARY_RESTORED) { - return TRUE; - } - return FALSE; + if (event == OC_EV_MS_NEW_MEMBERSHIP || event == OC_EV_MS_PRIMARY_RESTORED) { + return TRUE; + } + return FALSE; } const char * ccm_event_name(oc_ed_t event) { - if(event==OC_EV_MS_NEW_MEMBERSHIP) { - return "NEW MEMBERSHIP"; + if (event == OC_EV_MS_NEW_MEMBERSHIP) { + return "NEW MEMBERSHIP"; - } else if(event==OC_EV_MS_NOT_PRIMARY) { - return "NOT PRIMARY"; + } else if (event == OC_EV_MS_NOT_PRIMARY) { + return "NOT PRIMARY"; - } else if(event==OC_EV_MS_PRIMARY_RESTORED) { - return "PRIMARY RESTORED"; - - } else if(event==OC_EV_MS_EVICTED) { - return "EVICTED"; + } else if (event == OC_EV_MS_PRIMARY_RESTORED) { + return "PRIMARY RESTORED"; + + } else if (event == OC_EV_MS_EVICTED) { + return "EVICTED"; + + } else if (event == OC_EV_MS_INVALID) { + return "INVALID"; + } - } else if(event==OC_EV_MS_INVALID) { - return "INVALID"; - } + return "NO QUORUM MEMBERSHIP"; - return "NO QUORUM MEMBERSHIP"; - } #endif diff --git a/lib/common/ipc.c b/lib/common/ipc.c index 4bfefe06f8..f7016199d3 100644 --- a/lib/common/ipc.c +++ b/lib/common/ipc.c @@ -1,670 +1,642 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 -xmlNode *xmlfromIPC(IPC_Channel *ch, int timeout) +xmlNode * +xmlfromIPC(IPC_Channel * ch, int timeout) { xmlNode *xml = NULL; HA_Message *msg = NULL; - + #if HAVE_MSGFROMIPC_TIMEOUT int ipc_rc = IPC_OK; msg = msgfromIPC_timeout(ch, MSG_ALLOWINTR, timeout, &ipc_rc); - - if(ipc_rc == IPC_TIMEOUT) { - crm_warn("No message received in the required interval (%ds)", timeout); - return NULL; - - } else if(ipc_rc == IPC_BROKEN) { - crm_debug("Peer disconnected"); - return NULL; - - } else if(ipc_rc != IPC_OK) { - crm_err("msgfromIPC_timeout failed: rc=%d", ipc_rc); - return NULL; - - } else if(msg == NULL) { - crm_err("Empty reply from msgfromIPC_timeout"); - return NULL; + + if (ipc_rc == IPC_TIMEOUT) { + crm_warn("No message received in the required interval (%ds)", timeout); + return NULL; + + } else if (ipc_rc == IPC_BROKEN) { + crm_debug("Peer disconnected"); + return NULL; + + } else if (ipc_rc != IPC_OK) { + crm_err("msgfromIPC_timeout failed: rc=%d", ipc_rc); + return NULL; + + } else if (msg == NULL) { + crm_err("Empty reply from msgfromIPC_timeout"); + return NULL; } #else static gboolean do_show_error = TRUE; - if(timeout && do_show_error) { - crm_err("Timeouts are not supported by the current heartbeat libraries"); - do_show_error = FALSE; + if (timeout && do_show_error) { + crm_err("Timeouts are not supported by the current heartbeat libraries"); + do_show_error = FALSE; } msg = msgfromIPC_noauth(ch); - if(msg == NULL) { - crm_debug("Empty reply from msgfromIPC_noauth"); - return NULL; + if (msg == NULL) { + crm_debug("Empty reply from msgfromIPC_noauth"); + return NULL; } #endif xml = convert_ha_message(NULL, msg, __FUNCTION__); CRM_CHECK(xml != NULL, crm_err("Invalid ipc message")); crm_msg_del(msg); return xml; } -static int xml2ipcchan(xmlNode *m, IPC_Channel *ch) +static int +xml2ipcchan(xmlNode * m, IPC_Channel * ch) { - HA_Message *msg = NULL; - IPC_Message *imsg = NULL; - - if (m == NULL || ch == NULL) { - cl_log(LOG_ERR, "Invalid msg2ipcchan argument"); - errno = EINVAL; - return HA_FAIL; - } - - msg = convert_xml_message(m); - if ((imsg = hamsg2ipcmsg(msg, ch)) == NULL) { - cl_log(LOG_ERR, "hamsg2ipcmsg() failure"); - crm_msg_del(msg); - return HA_FAIL; - } - crm_msg_del(msg); - - if (ch->ops->send(ch, imsg) != IPC_OK) { - if (ch->ch_status == IPC_CONNECT) { - snprintf(ch->failreason,MAXFAILREASON, - "send failed,farside_pid=%d, sendq length=%ld(max is %ld)", - ch->farside_pid, (long)ch->send_queue->current_qlen, - (long)ch->send_queue->max_qlen); - } - imsg->msg_done(imsg); - return HA_FAIL; - } - return HA_OK; + HA_Message *msg = NULL; + IPC_Message *imsg = NULL; + + if (m == NULL || ch == NULL) { + cl_log(LOG_ERR, "Invalid msg2ipcchan argument"); + errno = EINVAL; + return HA_FAIL; + } + + msg = convert_xml_message(m); + if ((imsg = hamsg2ipcmsg(msg, ch)) == NULL) { + cl_log(LOG_ERR, "hamsg2ipcmsg() failure"); + crm_msg_del(msg); + return HA_FAIL; + } + crm_msg_del(msg); + + if (ch->ops->send(ch, imsg) != IPC_OK) { + if (ch->ch_status == IPC_CONNECT) { + snprintf(ch->failreason, MAXFAILREASON, + "send failed,farside_pid=%d, sendq length=%ld(max is %ld)", + ch->farside_pid, (long)ch->send_queue->current_qlen, + (long)ch->send_queue->max_qlen); + } + imsg->msg_done(imsg); + return HA_FAIL; + } + return HA_OK; } /* frees msg */ -gboolean -send_ipc_message(IPC_Channel *ipc_client, xmlNode *msg) +gboolean +send_ipc_message(IPC_Channel * ipc_client, xmlNode * msg) { - gboolean all_is_good = TRUE; - int fail_level = LOG_WARNING; - - if(ipc_client != NULL && ipc_client->conntype == IPC_CLIENT) { - fail_level = LOG_ERR; - } - - if (msg == NULL) { - crm_err("cant send NULL message"); - all_is_good = FALSE; - - } else if (ipc_client == NULL) { - crm_err("cant send message without an IPC Channel"); - all_is_good = FALSE; - - } else if(ipc_client->ops->get_chan_status(ipc_client) != IPC_CONNECT) { - do_crm_log(fail_level, "IPC Channel to %d is not connected", - (int)ipc_client->farside_pid); - all_is_good = FALSE; - } - - if(all_is_good && xml2ipcchan(msg, ipc_client) != HA_OK) { - do_crm_log(fail_level, "Could not send IPC message to %d", - (int)ipc_client->farside_pid); - all_is_good = FALSE; - - if(ipc_client->ops->get_chan_status(ipc_client) != IPC_CONNECT) { - do_crm_log(fail_level, - "IPC Channel to %d is no longer connected", - (int)ipc_client->farside_pid); - - } else if(ipc_client->conntype == IPC_CLIENT) { - if(ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) { - crm_err("Send queue to %d (size=%d) full.", - ipc_client->farside_pid, - (int)ipc_client->send_queue->max_qlen); - } - } - } - /* crm_log_xml(all_is_good?LOG_MSG:LOG_WARNING,"IPC[outbound]",msg); */ - - return all_is_good; + gboolean all_is_good = TRUE; + int fail_level = LOG_WARNING; + + if (ipc_client != NULL && ipc_client->conntype == IPC_CLIENT) { + fail_level = LOG_ERR; + } + + if (msg == NULL) { + crm_err("cant send NULL message"); + all_is_good = FALSE; + + } else if (ipc_client == NULL) { + crm_err("cant send message without an IPC Channel"); + all_is_good = FALSE; + + } else if (ipc_client->ops->get_chan_status(ipc_client) != IPC_CONNECT) { + do_crm_log(fail_level, "IPC Channel to %d is not connected", (int)ipc_client->farside_pid); + all_is_good = FALSE; + } + + if (all_is_good && xml2ipcchan(msg, ipc_client) != HA_OK) { + do_crm_log(fail_level, "Could not send IPC message to %d", (int)ipc_client->farside_pid); + all_is_good = FALSE; + + if (ipc_client->ops->get_chan_status(ipc_client) != IPC_CONNECT) { + do_crm_log(fail_level, + "IPC Channel to %d is no longer connected", (int)ipc_client->farside_pid); + + } else if (ipc_client->conntype == IPC_CLIENT) { + if (ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) { + crm_err("Send queue to %d (size=%d) full.", + ipc_client->farside_pid, (int)ipc_client->send_queue->max_qlen); + } + } + } + /* crm_log_xml(all_is_good?LOG_MSG:LOG_WARNING,"IPC[outbound]",msg); */ + + return all_is_good; } void default_ipc_connection_destroy(gpointer user_data) { - return; + return; } int -init_server_ipc_comms( - char *channel_name, - gboolean (*channel_client_connect)(IPC_Channel *newclient,gpointer user_data), - void (*channel_connection_destroy)(gpointer user_data)) +init_server_ipc_comms(char *channel_name, + gboolean(*channel_client_connect) (IPC_Channel * newclient, + gpointer user_data), + void (*channel_connection_destroy) (gpointer user_data)) { - /* the clients wait channel is the other source of events. - * This source delivers the clients connection events. - * listen to this source at a relatively lower priority. - */ - - char commpath[SOCKET_LEN]; - IPC_WaitConnection *wait_ch; - - sprintf(commpath, CRM_STATE_DIR "/%s", channel_name); - - wait_ch = wait_channel_init(commpath); - - if (wait_ch == NULL) { - return 1; - } - - G_main_add_IPC_WaitConnection( - G_PRIORITY_LOW, wait_ch, NULL, FALSE, - channel_client_connect, channel_name, - channel_connection_destroy); - - crm_debug_3("Listening on: %s", commpath); - - return 0; + /* the clients wait channel is the other source of events. + * This source delivers the clients connection events. + * listen to this source at a relatively lower priority. + */ + + char commpath[SOCKET_LEN]; + IPC_WaitConnection *wait_ch; + + sprintf(commpath, CRM_STATE_DIR "/%s", channel_name); + + wait_ch = wait_channel_init(commpath); + + if (wait_ch == NULL) { + return 1; + } + + G_main_add_IPC_WaitConnection(G_PRIORITY_LOW, wait_ch, NULL, FALSE, + channel_client_connect, channel_name, channel_connection_destroy); + + crm_debug_3("Listening on: %s", commpath); + + return 0; } -GCHSource* +GCHSource * init_client_ipc_comms(const char *channel_name, - gboolean (*dispatch)( - IPC_Channel* source_data, gpointer user_data), - void *client_data, IPC_Channel **ch) + gboolean(*dispatch) (IPC_Channel * source_data, gpointer user_data), + void *client_data, IPC_Channel ** ch) { - IPC_Channel *a_ch = NULL; - GCHSource *the_source = NULL; - void *callback_data = client_data; - - a_ch = init_client_ipc_comms_nodispatch(channel_name); - if(ch != NULL) { - *ch = a_ch; - if(callback_data == NULL) { - callback_data = a_ch; - } - } - - if(a_ch == NULL) { - crm_warn("Setup of client connection failed," - " not adding channel to mainloop"); - - return NULL; - } - - if(dispatch == NULL) { - crm_warn("No dispatch method specified..." - "maybe you meant init_client_ipc_comms_nodispatch()?"); - } else { - crm_debug_3("Adding dispatch method to channel"); - - the_source = G_main_add_IPC_Channel( - G_PRIORITY_HIGH, a_ch, FALSE, dispatch, callback_data, - default_ipc_connection_destroy); - } - - return the_source; + IPC_Channel *a_ch = NULL; + GCHSource *the_source = NULL; + void *callback_data = client_data; + + a_ch = init_client_ipc_comms_nodispatch(channel_name); + if (ch != NULL) { + *ch = a_ch; + if (callback_data == NULL) { + callback_data = a_ch; + } + } + + if (a_ch == NULL) { + crm_warn("Setup of client connection failed," " not adding channel to mainloop"); + + return NULL; + } + + if (dispatch == NULL) { + crm_warn("No dispatch method specified..." + "maybe you meant init_client_ipc_comms_nodispatch()?"); + } else { + crm_debug_3("Adding dispatch method to channel"); + + the_source = G_main_add_IPC_Channel(G_PRIORITY_HIGH, a_ch, FALSE, dispatch, callback_data, + default_ipc_connection_destroy); + } + + return the_source; } IPC_Channel * init_client_ipc_comms_nodispatch(const char *channel_name) { - IPC_Channel *ch; - GHashTable *attrs; - static char path[] = IPC_PATH_ATTR; - - char *commpath = NULL; - int local_socket_len = 2; /* 2 = '/' + '\0' */ - - local_socket_len += strlen(channel_name); - local_socket_len += strlen(CRM_STATE_DIR); - - crm_malloc0(commpath, local_socket_len); - - sprintf(commpath, CRM_STATE_DIR "/%s", channel_name); - commpath[local_socket_len - 1] = '\0'; - crm_debug("Attempting to talk on: %s", commpath); - - attrs = g_hash_table_new(crm_str_hash,g_str_equal); - g_hash_table_insert(attrs, path, commpath); - - ch = ipc_channel_constructor(IPC_ANYTYPE, attrs); - g_hash_table_destroy(attrs); - - if (ch == NULL) { - crm_err("Could not access channel on: %s", commpath); - crm_free(commpath); - return NULL; - - } else if (ch->ops->initiate_connection(ch) != IPC_OK) { - crm_debug("Could not init comms on: %s", commpath); - ch->ops->destroy(ch); - crm_free(commpath); - return NULL; - } - - ch->ops->set_recv_qlen(ch, 512); - ch->ops->set_send_qlen(ch, 512); - ch->should_send_block = TRUE; - - crm_debug_3("Processing of %s complete", commpath); - - crm_free(commpath); - return ch; + IPC_Channel *ch; + GHashTable *attrs; + static char path[] = IPC_PATH_ATTR; + + char *commpath = NULL; + int local_socket_len = 2; /* 2 = '/' + '\0' */ + + local_socket_len += strlen(channel_name); + local_socket_len += strlen(CRM_STATE_DIR); + + crm_malloc0(commpath, local_socket_len); + + sprintf(commpath, CRM_STATE_DIR "/%s", channel_name); + commpath[local_socket_len - 1] = '\0'; + crm_debug("Attempting to talk on: %s", commpath); + + attrs = g_hash_table_new(crm_str_hash, g_str_equal); + g_hash_table_insert(attrs, path, commpath); + + ch = ipc_channel_constructor(IPC_ANYTYPE, attrs); + g_hash_table_destroy(attrs); + + if (ch == NULL) { + crm_err("Could not access channel on: %s", commpath); + crm_free(commpath); + return NULL; + + } else if (ch->ops->initiate_connection(ch) != IPC_OK) { + crm_debug("Could not init comms on: %s", commpath); + ch->ops->destroy(ch); + crm_free(commpath); + return NULL; + } + + ch->ops->set_recv_qlen(ch, 512); + ch->ops->set_send_qlen(ch, 512); + ch->should_send_block = TRUE; + + crm_debug_3("Processing of %s complete", commpath); + + crm_free(commpath); + return ch; } IPC_WaitConnection * wait_channel_init(char daemonsocket[]) { - IPC_WaitConnection *wait_ch; - mode_t mask; - char path[] = IPC_PATH_ATTR; - GHashTable * attrs; - - - attrs = g_hash_table_new(crm_str_hash,g_str_equal); - g_hash_table_insert(attrs, path, daemonsocket); - - mask = umask(0); - wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs); - if (wait_ch == NULL) { - crm_perror(LOG_ERR,"Can't create wait channel of type %s", - IPC_ANYTYPE); - exit(1); - } - mask = umask(mask); - - g_hash_table_destroy(attrs); - - return wait_ch; + IPC_WaitConnection *wait_ch; + mode_t mask; + char path[] = IPC_PATH_ATTR; + GHashTable *attrs; + + attrs = g_hash_table_new(crm_str_hash, g_str_equal); + g_hash_table_insert(attrs, path, daemonsocket); + + mask = umask(0); + wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs); + if (wait_ch == NULL) { + crm_perror(LOG_ERR, "Can't create wait channel of type %s", IPC_ANYTYPE); + exit(1); + } + mask = umask(mask); + + g_hash_table_destroy(attrs); + + return wait_ch; } gboolean -subsystem_msg_dispatch(IPC_Channel *sender, void *user_data) +subsystem_msg_dispatch(IPC_Channel * sender, void *user_data) { - int lpc = 0; - xmlNode *msg = NULL; - xmlNode *data = NULL; - gboolean all_is_well = TRUE; - const char *sys_to; - const char *task; - gboolean (*process_function) - (xmlNode *msg, xmlNode *data, IPC_Channel *sender) = NULL; - - while(IPC_ISRCONN(sender)) { - gboolean process = FALSE; - if(sender->ops->is_message_pending(sender) == 0) { - break; - } - - msg = xmlfromIPC(sender, MAX_IPC_DELAY); - if (msg == NULL) { - break; - } - - lpc++; - crm_log_xml(LOG_MSG, __FUNCTION__, msg); - - sys_to = crm_element_value(msg, F_CRM_SYS_TO); - task = crm_element_value(msg, F_CRM_TASK); - - if(safe_str_eq(task, CRM_OP_HELLO)) { - process = TRUE; - - } else if(sys_to == NULL) { - crm_err("Value of %s was NULL!!", F_CRM_SYS_TO); - - } else if(task == NULL) { - crm_err("Value of %s was NULL!!", F_CRM_TASK); - - } else { - process = TRUE; - } - - if(process == FALSE) { - free_xml(msg); msg = NULL; - continue; - } - - data = get_message_xml(msg, F_CRM_DATA); - process_function = user_data; - if(FALSE == process_function(msg, data, sender)) { - crm_warn("Received a message destined for %s" - " by mistake", sys_to); - } - - free_xml(msg); msg = NULL; - - if(sender->ch_status == IPC_CONNECT) { - break; - } - } - - crm_debug_2("Processed %d messages", lpc); - if (sender->ch_status != IPC_CONNECT) { - crm_err("The server %d has left us: Shutting down...NOW", - sender->farside_pid); - - exit(1); /* shutdown properly later */ - - return !all_is_well; - } - return all_is_well; + int lpc = 0; + xmlNode *msg = NULL; + xmlNode *data = NULL; + gboolean all_is_well = TRUE; + const char *sys_to; + const char *task; + + gboolean(*process_function) + (xmlNode * msg, xmlNode * data, IPC_Channel * sender) = NULL; + + while (IPC_ISRCONN(sender)) { + gboolean process = FALSE; + + if (sender->ops->is_message_pending(sender) == 0) { + break; + } + + msg = xmlfromIPC(sender, MAX_IPC_DELAY); + if (msg == NULL) { + break; + } + + lpc++; + crm_log_xml(LOG_MSG, __FUNCTION__, msg); + + sys_to = crm_element_value(msg, F_CRM_SYS_TO); + task = crm_element_value(msg, F_CRM_TASK); + + if (safe_str_eq(task, CRM_OP_HELLO)) { + process = TRUE; + + } else if (sys_to == NULL) { + crm_err("Value of %s was NULL!!", F_CRM_SYS_TO); + + } else if (task == NULL) { + crm_err("Value of %s was NULL!!", F_CRM_TASK); + + } else { + process = TRUE; + } + + if (process == FALSE) { + free_xml(msg); + msg = NULL; + continue; + } + + data = get_message_xml(msg, F_CRM_DATA); + process_function = user_data; + if (FALSE == process_function(msg, data, sender)) { + crm_warn("Received a message destined for %s" " by mistake", sys_to); + } + + free_xml(msg); + msg = NULL; + + if (sender->ch_status == IPC_CONNECT) { + break; + } + } + + crm_debug_2("Processed %d messages", lpc); + if (sender->ch_status != IPC_CONNECT) { + crm_err("The server %d has left us: Shutting down...NOW", sender->farside_pid); + + exit(1); /* shutdown properly later */ + + return !all_is_well; + } + return all_is_well; } gboolean -is_ipc_empty(IPC_Channel *ch) +is_ipc_empty(IPC_Channel * ch) { - if(ch == NULL) { - return TRUE; - - } else if(ch->send_queue->current_qlen == 0 - && ch->recv_queue->current_qlen == 0) { - return TRUE; - } - return FALSE; + if (ch == NULL) { + return TRUE; + + } else if (ch->send_queue->current_qlen == 0 && ch->recv_queue->current_qlen == 0) { + return TRUE; + } + return FALSE; } void -send_hello_message(IPC_Channel *ipc_client, - const char *uuid, - const char *client_name, - const char *major_version, - const char *minor_version) +send_hello_message(IPC_Channel * ipc_client, + const char *uuid, + const char *client_name, const char *major_version, const char *minor_version) { - xmlNode *hello_node = NULL; - xmlNode *hello = NULL; - if (uuid == NULL || strlen(uuid) == 0 - || client_name == NULL || strlen(client_name) == 0 - || major_version == NULL || strlen(major_version) == 0 - || minor_version == NULL || strlen(minor_version) == 0) { - crm_err("Missing fields, Hello message will not be valid."); - return; - } - - hello_node = create_xml_node(NULL, XML_TAG_OPTIONS); - crm_xml_add(hello_node, "major_version", major_version); - crm_xml_add(hello_node, "minor_version", minor_version); - crm_xml_add(hello_node, "client_name", client_name); - crm_xml_add(hello_node, "client_uuid", uuid); - - crm_debug_4("creating hello message"); - hello = create_request( - CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid); - - send_ipc_message(ipc_client, hello); - crm_debug_4("hello message sent"); - - free_xml(hello_node); - free_xml(hello); -} + xmlNode *hello_node = NULL; + xmlNode *hello = NULL; + + if (uuid == NULL || strlen(uuid) == 0 + || client_name == NULL || strlen(client_name) == 0 + || major_version == NULL || strlen(major_version) == 0 + || minor_version == NULL || strlen(minor_version) == 0) { + crm_err("Missing fields, Hello message will not be valid."); + return; + } + + hello_node = create_xml_node(NULL, XML_TAG_OPTIONS); + crm_xml_add(hello_node, "major_version", major_version); + crm_xml_add(hello_node, "minor_version", minor_version); + crm_xml_add(hello_node, "client_name", client_name); + crm_xml_add(hello_node, "client_uuid", uuid); + crm_debug_4("creating hello message"); + hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid); + + send_ipc_message(ipc_client, hello); + crm_debug_4("hello message sent"); + + free_xml(hello_node); + free_xml(hello); +} gboolean -process_hello_message(xmlNode *hello, - char **uuid, - char **client_name, - char **major_version, - char **minor_version) +process_hello_message(xmlNode * hello, + char **uuid, char **client_name, char **major_version, char **minor_version) { - const char *local_uuid; - const char *local_client_name; - const char *local_major_version; - const char *local_minor_version; - - *uuid = NULL; - *client_name = NULL; - *major_version = NULL; - *minor_version = NULL; - - if(hello == NULL) { - return FALSE; - } - - local_uuid = crm_element_value(hello, "client_uuid"); - local_client_name = crm_element_value(hello, "client_name"); - local_major_version = crm_element_value(hello, "major_version"); - local_minor_version = crm_element_value(hello, "minor_version"); - - if (local_uuid == NULL || strlen(local_uuid) == 0) { - crm_err("Hello message was not valid (field %s not found)", - "uuid"); - return FALSE; - - } else if (local_client_name==NULL || strlen(local_client_name)==0){ - crm_err("Hello message was not valid (field %s not found)", - "client name"); - return FALSE; - - } else if(local_major_version == NULL - || strlen(local_major_version) == 0){ - crm_err("Hello message was not valid (field %s not found)", - "major version"); - return FALSE; - - } else if (local_minor_version == NULL - || strlen(local_minor_version) == 0){ - crm_err("Hello message was not valid (field %s not found)", - "minor version"); - return FALSE; - } - - *uuid = crm_strdup(local_uuid); - *client_name = crm_strdup(local_client_name); - *major_version = crm_strdup(local_major_version); - *minor_version = crm_strdup(local_minor_version); - - crm_debug_3("Hello message ok"); - return TRUE; + const char *local_uuid; + const char *local_client_name; + const char *local_major_version; + const char *local_minor_version; + + *uuid = NULL; + *client_name = NULL; + *major_version = NULL; + *minor_version = NULL; + + if (hello == NULL) { + return FALSE; + } + + local_uuid = crm_element_value(hello, "client_uuid"); + local_client_name = crm_element_value(hello, "client_name"); + local_major_version = crm_element_value(hello, "major_version"); + local_minor_version = crm_element_value(hello, "minor_version"); + + if (local_uuid == NULL || strlen(local_uuid) == 0) { + crm_err("Hello message was not valid (field %s not found)", "uuid"); + return FALSE; + + } else if (local_client_name == NULL || strlen(local_client_name) == 0) { + crm_err("Hello message was not valid (field %s not found)", "client name"); + return FALSE; + + } else if (local_major_version == NULL || strlen(local_major_version) == 0) { + crm_err("Hello message was not valid (field %s not found)", "major version"); + return FALSE; + + } else if (local_minor_version == NULL || strlen(local_minor_version) == 0) { + crm_err("Hello message was not valid (field %s not found)", "minor version"); + return FALSE; + } + + *uuid = crm_strdup(local_uuid); + *client_name = crm_strdup(local_client_name); + *major_version = crm_strdup(local_major_version); + *minor_version = crm_strdup(local_minor_version); + + crm_debug_3("Hello message ok"); + return TRUE; } xmlNode * -create_request_adv(const char *task, xmlNode *msg_data, - const char *host_to, const char *sys_to, - const char *sys_from, const char *uuid_from, - const char *origin) +create_request_adv(const char *task, xmlNode * msg_data, + const char *host_to, const char *sys_to, + const char *sys_from, const char *uuid_from, const char *origin) { - char *true_from = NULL; - xmlNode *request = NULL; - char *reference = generateReference(task, sys_from); - - if (uuid_from != NULL) { - true_from = generate_hash_key(sys_from, uuid_from); - } else if(sys_from != NULL) { - true_from = crm_strdup(sys_from); - } else { - crm_err("No sys from specified"); - } - - /* host_from will get set for us if necessary by CRMd when routed */ - request = create_xml_node(NULL, __FUNCTION__); - crm_xml_add(request, F_CRM_ORIGIN, origin); - crm_xml_add(request, F_TYPE, T_CRM); - crm_xml_add(request, F_CRM_VERSION, CRM_FEATURE_SET); - crm_xml_add(request, F_CRM_MSG_TYPE, XML_ATTR_REQUEST); - crm_xml_add(request, XML_ATTR_REFERENCE, reference); - crm_xml_add(request, F_CRM_TASK, task); - crm_xml_add(request, F_CRM_SYS_TO, sys_to); - crm_xml_add(request, F_CRM_SYS_FROM, true_from); - - /* HOSTTO will be ignored if it is to the DC anyway. */ - if(host_to != NULL && strlen(host_to) > 0) { - crm_xml_add(request, F_CRM_HOST_TO, host_to); - } - - if (msg_data != NULL) { - add_message_xml(request, F_CRM_DATA, msg_data); - } - crm_free(reference); - crm_free(true_from); - - return request; + char *true_from = NULL; + xmlNode *request = NULL; + char *reference = generateReference(task, sys_from); + + if (uuid_from != NULL) { + true_from = generate_hash_key(sys_from, uuid_from); + } else if (sys_from != NULL) { + true_from = crm_strdup(sys_from); + } else { + crm_err("No sys from specified"); + } + + /* host_from will get set for us if necessary by CRMd when routed */ + request = create_xml_node(NULL, __FUNCTION__); + crm_xml_add(request, F_CRM_ORIGIN, origin); + crm_xml_add(request, F_TYPE, T_CRM); + crm_xml_add(request, F_CRM_VERSION, CRM_FEATURE_SET); + crm_xml_add(request, F_CRM_MSG_TYPE, XML_ATTR_REQUEST); + crm_xml_add(request, XML_ATTR_REFERENCE, reference); + crm_xml_add(request, F_CRM_TASK, task); + crm_xml_add(request, F_CRM_SYS_TO, sys_to); + crm_xml_add(request, F_CRM_SYS_FROM, true_from); + + /* HOSTTO will be ignored if it is to the DC anyway. */ + if (host_to != NULL && strlen(host_to) > 0) { + crm_xml_add(request, F_CRM_HOST_TO, host_to); + } + + if (msg_data != NULL) { + add_message_xml(request, F_CRM_DATA, msg_data); + } + crm_free(reference); + crm_free(true_from); + + return request; } ha_msg_input_t * -new_ha_msg_input(xmlNode *orig) +new_ha_msg_input(xmlNode * orig) { - ha_msg_input_t *input_copy = NULL; - crm_malloc0(input_copy, sizeof(ha_msg_input_t)); - input_copy->msg = orig; - input_copy->xml = get_message_xml(input_copy->msg, F_CRM_DATA); - return input_copy; + ha_msg_input_t *input_copy = NULL; + + crm_malloc0(input_copy, sizeof(ha_msg_input_t)); + input_copy->msg = orig; + input_copy->xml = get_message_xml(input_copy->msg, F_CRM_DATA); + return input_copy; } void -delete_ha_msg_input(ha_msg_input_t *orig) +delete_ha_msg_input(ha_msg_input_t * orig) { - if(orig == NULL) { - return; - } - free_xml(orig->msg); - crm_free(orig); + if (orig == NULL) { + return; + } + free_xml(orig->msg); + crm_free(orig); } xmlNode * -validate_crm_message( - xmlNode *msg, const char *sys, const char *uuid, const char *msg_type) +validate_crm_message(xmlNode * msg, const char *sys, const char *uuid, const char *msg_type) { - const char *to = NULL; - const char *type = NULL; - const char *crm_msg_reference = NULL; - xmlNode *action = NULL; - const char *true_sys; - char *local_sys = NULL; - - - if (msg == NULL) { - return NULL; - } - - to = crm_element_value(msg, F_CRM_SYS_TO); - type = crm_element_value(msg, F_CRM_MSG_TYPE); - - crm_msg_reference = crm_element_value(msg, XML_ATTR_REFERENCE); - action = msg; - true_sys = sys; - - if (uuid != NULL) { - local_sys = generate_hash_key(sys, uuid); - true_sys = local_sys; - } - - if (to == NULL) { - crm_info("No sub-system defined."); - action = NULL; - } else if (true_sys != NULL && strcasecmp(to, true_sys) != 0) { - crm_debug_3("The message is not for this sub-system (%s != %s).", - to, true_sys); - action = NULL; - } - - crm_free(local_sys); - - if (type == NULL) { - crm_info("No message type defined."); - return NULL; - - } else if (msg_type != NULL && strcasecmp(msg_type, type) != 0) { - crm_info("Expecting a (%s) message but received a (%s).", - msg_type, type); - action = NULL; - } - - if (crm_msg_reference == NULL) { - crm_info("No message crm_msg_reference defined."); - action = NULL; - } + const char *to = NULL; + const char *type = NULL; + const char *crm_msg_reference = NULL; + xmlNode *action = NULL; + const char *true_sys; + char *local_sys = NULL; + + if (msg == NULL) { + return NULL; + } + + to = crm_element_value(msg, F_CRM_SYS_TO); + type = crm_element_value(msg, F_CRM_MSG_TYPE); + + crm_msg_reference = crm_element_value(msg, XML_ATTR_REFERENCE); + action = msg; + true_sys = sys; + + if (uuid != NULL) { + local_sys = generate_hash_key(sys, uuid); + true_sys = local_sys; + } + + if (to == NULL) { + crm_info("No sub-system defined."); + action = NULL; + } else if (true_sys != NULL && strcasecmp(to, true_sys) != 0) { + crm_debug_3("The message is not for this sub-system (%s != %s).", to, true_sys); + action = NULL; + } + + crm_free(local_sys); + + if (type == NULL) { + crm_info("No message type defined."); + return NULL; + + } else if (msg_type != NULL && strcasecmp(msg_type, type) != 0) { + crm_info("Expecting a (%s) message but received a (%s).", msg_type, type); + action = NULL; + } + + if (crm_msg_reference == NULL) { + crm_info("No message crm_msg_reference defined."); + action = NULL; + } /* if(action != NULL) crm_debug_3( "XML is valid and node with message type (%s) found.", type); crm_debug_3("Returning node (%s)", crm_element_name(action)); */ - - return action; + + return action; } /* * This method adds a copy of xml_response_data */ xmlNode * -create_reply_adv(xmlNode *original_request, - xmlNode *xml_response_data, const char *origin) +create_reply_adv(xmlNode * original_request, xmlNode * xml_response_data, const char *origin) { - xmlNode *reply = NULL; - - const char *host_from= crm_element_value(original_request, F_CRM_HOST_FROM); - const char *sys_from = crm_element_value(original_request, F_CRM_SYS_FROM); - const char *sys_to = crm_element_value(original_request, F_CRM_SYS_TO); - const char *type = crm_element_value(original_request, F_CRM_MSG_TYPE); - const char *operation= crm_element_value(original_request, F_CRM_TASK); - const char *crm_msg_reference = crm_element_value( - original_request, XML_ATTR_REFERENCE); - - if (type == NULL) { - crm_err("Cannot create new_message," - " no message type in original message"); - CRM_ASSERT(type != NULL); - return NULL; + xmlNode *reply = NULL; + + const char *host_from = crm_element_value(original_request, F_CRM_HOST_FROM); + const char *sys_from = crm_element_value(original_request, F_CRM_SYS_FROM); + const char *sys_to = crm_element_value(original_request, F_CRM_SYS_TO); + const char *type = crm_element_value(original_request, F_CRM_MSG_TYPE); + const char *operation = crm_element_value(original_request, F_CRM_TASK); + const char *crm_msg_reference = crm_element_value(original_request, XML_ATTR_REFERENCE); + + if (type == NULL) { + crm_err("Cannot create new_message," " no message type in original message"); + CRM_ASSERT(type != NULL); + return NULL; #if 0 - } else if (strcasecmp(XML_ATTR_REQUEST, type) != 0) { - crm_err("Cannot create new_message," - " original message was not a request"); - return NULL; + } else if (strcasecmp(XML_ATTR_REQUEST, type) != 0) { + crm_err("Cannot create new_message," " original message was not a request"); + return NULL; #endif - } - reply = create_xml_node(NULL, __FUNCTION__); - crm_xml_add(reply, F_CRM_ORIGIN, origin); - crm_xml_add(reply, F_TYPE, T_CRM); - crm_xml_add(reply, F_CRM_VERSION, CRM_FEATURE_SET); - crm_xml_add(reply, F_CRM_MSG_TYPE, XML_ATTR_RESPONSE); - crm_xml_add(reply, XML_ATTR_REFERENCE, crm_msg_reference); - crm_xml_add(reply, F_CRM_TASK, operation); - - /* since this is a reply, we reverse the from and to */ - crm_xml_add(reply, F_CRM_SYS_TO, sys_from); - crm_xml_add(reply, F_CRM_SYS_FROM, sys_to); - - /* HOSTTO will be ignored if it is to the DC anyway. */ - if(host_from != NULL && strlen(host_from) > 0) { - crm_xml_add(reply, F_CRM_HOST_TO, host_from); - } - - if (xml_response_data != NULL) { - add_message_xml(reply, F_CRM_DATA, xml_response_data); - } - - return reply; + } + reply = create_xml_node(NULL, __FUNCTION__); + crm_xml_add(reply, F_CRM_ORIGIN, origin); + crm_xml_add(reply, F_TYPE, T_CRM); + crm_xml_add(reply, F_CRM_VERSION, CRM_FEATURE_SET); + crm_xml_add(reply, F_CRM_MSG_TYPE, XML_ATTR_RESPONSE); + crm_xml_add(reply, XML_ATTR_REFERENCE, crm_msg_reference); + crm_xml_add(reply, F_CRM_TASK, operation); + + /* since this is a reply, we reverse the from and to */ + crm_xml_add(reply, F_CRM_SYS_TO, sys_from); + crm_xml_add(reply, F_CRM_SYS_FROM, sys_to); + + /* HOSTTO will be ignored if it is to the DC anyway. */ + if (host_from != NULL && strlen(host_from) > 0) { + crm_xml_add(reply, F_CRM_HOST_TO, host_from); + } + + if (xml_response_data != NULL) { + add_message_xml(reply, F_CRM_DATA, xml_response_data); + } + + return reply; } diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index f5fcbfcab0..b7554c23a3 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1,1389 +1,1383 @@ /* * Copyright (C) 2005 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 */ /* * Primary reference: * http://en.wikipedia.org/wiki/ISO_8601 (as at 2005-08-01) * * Secondary references: * http://hydracen.com/dx/iso8601.htm * http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt * http://www.personal.ecu.edu/mccartyr/isowdcal.html * http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm * */ #include #include #include #include #include -gboolean gregorian_to_ordinal(ha_time_t *a_date); -gboolean ordinal_to_gregorian(ha_time_t *a_date); -gboolean ordinal_to_weekdays(ha_time_t *a_date); -void normalize_time(ha_time_t *a_time); +gboolean gregorian_to_ordinal(ha_time_t * a_date); +gboolean ordinal_to_gregorian(ha_time_t * a_date); +gboolean ordinal_to_weekdays(ha_time_t * a_date); +void normalize_time(ha_time_t * a_time); /* * Andrew's code was originally written for OSes whose "struct tm" contains: * long tm_gmtoff; :: Seconds east of UTC * const char *tm_zone; :: Timezone abbreviation * Some OSes lack these, instead having: * time_t (or long) timezone; :: "difference between UTC and local standard time" * char *tzname[2] = { "...", "..." }; * I (David Lee) confess to not understanding the details. So my attempted * generalisations for where their use is necessary may be flawed. * * 1. Does "difference between ..." subtract the same or opposite way? * 2. Should it use "altzone" instead of "timezone"? * 3. Should it use tzname[0] or tzname[1]? Interaction with timezone/altzone? */ #if defined(HAVE_STRUCT_TM_TM_GMTOFF) -#define GMTOFF(tm) ((tm)->tm_gmtoff) +# define GMTOFF(tm) ((tm)->tm_gmtoff) #else /* Note: extern variable; macro argument not actually used. */ -#define GMTOFF(tm) (timezone) +# define GMTOFF(tm) (timezone) #endif char * -date_to_string(ha_time_t *date_time, int flags) +date_to_string(ha_time_t * date_time, int flags) { - char *date_s = NULL; - char *time_s = NULL; - char *offset_s = NULL; - char *result_s = NULL; - ha_time_t *dt = NULL; - - if(flags & ha_log_local) { - crm_debug_6("Local version"); - dt = date_time; - } else { - dt = date_time->normalized; - } + char *date_s = NULL; + char *time_s = NULL; + char *offset_s = NULL; + char *result_s = NULL; + ha_time_t *dt = NULL; + + if (flags & ha_log_local) { + crm_debug_6("Local version"); + dt = date_time; + } else { + dt = date_time->normalized; + } - CRM_CHECK(dt != NULL, return NULL); - - if(flags & ha_log_date) { - crm_malloc0(date_s, 32); - if(date_s == NULL) { - return NULL; - - } else if(flags & ha_date_weeks) { - snprintf(date_s, 31, "%d-W%.2d-%d", - dt->weekyears, dt->weeks, dt->weekdays); - - } else if(flags & ha_date_ordinal) { - snprintf(date_s, 31, "%d-%.3d",dt->years, dt->yeardays); - - } else { - snprintf(date_s, 31, "%.4d-%.2d-%.2d", - dt->years, dt->months, dt->days); - } - } - if(flags & ha_log_time) { - int offset = 0; - crm_malloc0(time_s, 32); - if(time_s == NULL) { - goto cleanup; - } - - snprintf(time_s, 31, "%.2d:%.2d:%.2d", - dt->hours, dt->minutes, dt->seconds); - - if(dt->offset != NULL) { - offset =(dt->offset->hours * 100) + dt->offset->minutes; - } - - crm_malloc0(offset_s, 32); - if((flags & ha_log_local) == 0 || offset == 0) { - snprintf(offset_s, 31, "Z"); - - } else { - int hr = dt->offset->hours; - int mins = dt->offset->minutes; - if(hr < 0) { - hr = 0 - hr; - } - if(mins < 0) { - mins = 0 - mins; - } - snprintf(offset_s, 31, " %s%.2d:%.2d", - offset>0?"+":"-", hr, mins); - } - } + CRM_CHECK(dt != NULL, return NULL); + + if (flags & ha_log_date) { + crm_malloc0(date_s, 32); + if (date_s == NULL) { + return NULL; + + } else if (flags & ha_date_weeks) { + snprintf(date_s, 31, "%d-W%.2d-%d", dt->weekyears, dt->weeks, dt->weekdays); + + } else if (flags & ha_date_ordinal) { + snprintf(date_s, 31, "%d-%.3d", dt->years, dt->yeardays); + + } else { + snprintf(date_s, 31, "%.4d-%.2d-%.2d", dt->years, dt->months, dt->days); + } + } + if (flags & ha_log_time) { + int offset = 0; + + crm_malloc0(time_s, 32); + if (time_s == NULL) { + goto cleanup; + } + + snprintf(time_s, 31, "%.2d:%.2d:%.2d", dt->hours, dt->minutes, dt->seconds); + + if (dt->offset != NULL) { + offset = (dt->offset->hours * 100) + dt->offset->minutes; + } + + crm_malloc0(offset_s, 32); + if ((flags & ha_log_local) == 0 || offset == 0) { + snprintf(offset_s, 31, "Z"); + + } else { + int hr = dt->offset->hours; + int mins = dt->offset->minutes; + + if (hr < 0) { + hr = 0 - hr; + } + if (mins < 0) { + mins = 0 - mins; + } + snprintf(offset_s, 31, " %s%.2d:%.2d", offset > 0 ? "+" : "-", hr, mins); + } + } - crm_malloc0(result_s, 100); + crm_malloc0(result_s, 100); - snprintf(result_s, 100, "%s%s%s%s", - date_s?date_s:"", (date_s!=NULL&&time_s!=NULL)?" ":"", - time_s?time_s:"", offset_s?offset_s:""); + snprintf(result_s, 100, "%s%s%s%s", + date_s ? date_s : "", (date_s != NULL && time_s != NULL) ? " " : "", + time_s ? time_s : "", offset_s ? offset_s : ""); cleanup: - crm_free(date_s); - crm_free(time_s); - crm_free(offset_s); + crm_free(date_s); + crm_free(time_s); + crm_free(offset_s); - return result_s; + return result_s; } void -log_date(int log_level, const char *prefix, ha_time_t *date_time, int flags) +log_date(int log_level, const char *prefix, ha_time_t * date_time, int flags) { - char *date_s = date_to_string(date_time, flags); - do_crm_log(log_level, "%s%s%s", - prefix?prefix:"", prefix?": ":"", - date_s?date_s:"__invalid_date__"); + char *date_s = date_to_string(date_time, flags); - crm_free(date_s); + do_crm_log(log_level, "%s%s%s", + prefix ? prefix : "", prefix ? ": " : "", date_s ? date_s : "__invalid_date__"); + + crm_free(date_s); } void -log_time_period(int log_level, ha_time_period_t *dtp, int flags) +log_time_period(int log_level, ha_time_period_t * dtp, int flags) { - log_date(log_level, "Period start:", dtp->start, flags); - log_date(log_level, "Period end:", dtp->end, flags); + log_date(log_level, "Period start:", dtp->start, flags); + log_date(log_level, "Period end:", dtp->end, flags); } -ha_time_t* +ha_time_t * parse_time_offset(char **offset_str) { - ha_time_t *new_time = NULL; - crm_malloc0(new_time, sizeof(ha_time_t)); - crm_malloc0(new_time->has, sizeof(ha_has_time_t)); - - if((*offset_str)[0] == 'Z') { - - } else if((*offset_str)[0] == '+' - || (*offset_str)[0] == '-' - || isdigit((int) (*offset_str)[0])) { - gboolean negate = FALSE; - if((*offset_str)[0] == '-') { - negate = TRUE; - (*offset_str)++; - } - parse_time(offset_str, new_time, FALSE); - if(negate) { - new_time->hours = 0 - new_time->hours; - new_time->minutes = 0 - new_time->minutes; - new_time->seconds = 0 - new_time->seconds; - } - - } else { + ha_time_t *new_time = NULL; + + crm_malloc0(new_time, sizeof(ha_time_t)); + crm_malloc0(new_time->has, sizeof(ha_has_time_t)); + + if ((*offset_str)[0] == 'Z') { + + } else if ((*offset_str)[0] == '+' || (*offset_str)[0] == '-' || isdigit((int)(*offset_str)[0])) { + gboolean negate = FALSE; + + if ((*offset_str)[0] == '-') { + negate = TRUE; + (*offset_str)++; + } + parse_time(offset_str, new_time, FALSE); + if (negate) { + new_time->hours = 0 - new_time->hours; + new_time->minutes = 0 - new_time->minutes; + new_time->seconds = 0 - new_time->seconds; + } + + } else { #if defined(HAVE_STRUCT_TM_TM_GMTOFF) - time_t now = time(NULL); - struct tm *now_tm = localtime(&now); + time_t now = time(NULL); + struct tm *now_tm = localtime(&now); #endif - int h_offset = GMTOFF(now_tm) / (3600); - int m_offset = (GMTOFF(now_tm) - (3600 * h_offset)) / (60); - if(h_offset < 0 && m_offset < 0) { - m_offset = 0 - m_offset; - } - new_time->hours = h_offset; - new_time->minutes = m_offset; - new_time->has->hours = TRUE; - new_time->has->minutes = TRUE; - } - return new_time; + int h_offset = GMTOFF(now_tm) / (3600); + int m_offset = (GMTOFF(now_tm) - (3600 * h_offset)) / (60); + + if (h_offset < 0 && m_offset < 0) { + m_offset = 0 - m_offset; + } + new_time->hours = h_offset; + new_time->minutes = m_offset; + new_time->has->hours = TRUE; + new_time->has->minutes = TRUE; + } + return new_time; } -ha_time_t* -parse_time(char **time_str, ha_time_t *a_time, gboolean with_offset) +ha_time_t * +parse_time(char **time_str, ha_time_t * a_time, gboolean with_offset) { - ha_time_t *new_time = a_time; - tzset(); - if(a_time == NULL) { - new_time = new_ha_date(FALSE); - } + ha_time_t *new_time = a_time; - CRM_CHECK(new_time != NULL, return NULL); - CRM_CHECK(new_time->has != NULL, free_ha_date(new_time); return NULL); - - /* reset the time fields */ - new_time->hours = 0; - new_time->minutes = 0; - new_time->seconds = 0; - - crm_debug_4("Get hours..."); - new_time->has->hours = FALSE; - if(parse_int(time_str, 2, 24, &new_time->hours)) { - new_time->has->hours = TRUE; - } + tzset(); + if (a_time == NULL) { + new_time = new_ha_date(FALSE); + } - crm_debug_4("Get minutes..."); - new_time->has->minutes = FALSE; - if(parse_int(time_str, 2, 60, &new_time->minutes)) { - new_time->has->minutes = TRUE; - } + CRM_CHECK(new_time != NULL, return NULL); + CRM_CHECK(new_time->has != NULL, free_ha_date(new_time); + return NULL); - crm_debug_4("Get seconds..."); - new_time->has->seconds = FALSE; - if(parse_int(time_str, 2, 60, &new_time->seconds)){ - new_time->has->seconds = TRUE; - } - - if(with_offset) { - crm_debug_4("Get offset..."); - while(isspace((int) (*time_str)[0])) { - (*time_str)++; - } - - new_time->offset = parse_time_offset(time_str); - normalize_time(new_time); - } - return new_time; + /* reset the time fields */ + new_time->hours = 0; + new_time->minutes = 0; + new_time->seconds = 0; + + crm_debug_4("Get hours..."); + new_time->has->hours = FALSE; + if (parse_int(time_str, 2, 24, &new_time->hours)) { + new_time->has->hours = TRUE; + } + + crm_debug_4("Get minutes..."); + new_time->has->minutes = FALSE; + if (parse_int(time_str, 2, 60, &new_time->minutes)) { + new_time->has->minutes = TRUE; + } + + crm_debug_4("Get seconds..."); + new_time->has->seconds = FALSE; + if (parse_int(time_str, 2, 60, &new_time->seconds)) { + new_time->has->seconds = TRUE; + } + + if (with_offset) { + crm_debug_4("Get offset..."); + while (isspace((int)(*time_str)[0])) { + (*time_str)++; + } + + new_time->offset = parse_time_offset(time_str); + normalize_time(new_time); + } + return new_time; } void -normalize_time(ha_time_t *a_time) +normalize_time(ha_time_t * a_time) { - CRM_CHECK(a_time != NULL, return); - CRM_CHECK(a_time->has != NULL, return); + CRM_CHECK(a_time != NULL, return); + CRM_CHECK(a_time->has != NULL, return); - if(a_time->normalized == NULL) { - crm_malloc0(a_time->normalized, sizeof(ha_time_t)); - } - if(a_time->normalized->has == NULL) { - crm_malloc0(a_time->normalized->has, sizeof(ha_has_time_t)); - } + if (a_time->normalized == NULL) { + crm_malloc0(a_time->normalized, sizeof(ha_time_t)); + } + if (a_time->normalized->has == NULL) { + crm_malloc0(a_time->normalized->has, sizeof(ha_has_time_t)); + } - ha_set_time(a_time->normalized, a_time, FALSE); - if(a_time->offset != NULL) { - if(a_time->offset->has->hours) { - sub_hours(a_time->normalized, a_time->offset->hours); - } - if(a_time->offset->has->minutes) { - sub_minutes(a_time->normalized,a_time->offset->minutes); - } - if(a_time->offset->has->seconds) { - sub_seconds(a_time->normalized,a_time->offset->seconds); - } - } - CRM_CHECK(is_date_sane(a_time), return); + ha_set_time(a_time->normalized, a_time, FALSE); + if (a_time->offset != NULL) { + if (a_time->offset->has->hours) { + sub_hours(a_time->normalized, a_time->offset->hours); + } + if (a_time->offset->has->minutes) { + sub_minutes(a_time->normalized, a_time->offset->minutes); + } + if (a_time->offset->has->seconds) { + sub_seconds(a_time->normalized, a_time->offset->seconds); + } + } + CRM_CHECK(is_date_sane(a_time), return); } - - ha_time_t * parse_date(char **date_str) { - gboolean is_done = FALSE; - gboolean converted = FALSE; - ha_time_t *new_time = NULL; - - CRM_CHECK(date_str != NULL, return NULL); - CRM_CHECK(strlen(*date_str) > 0, return NULL); - - if((*date_str)[0] == 'T' || (*date_str)[2] == ':') { - /* Just a time supplied - Infer current date */ - new_time = new_ha_date(TRUE); - - parse_time(date_str, new_time, TRUE); - normalize_time(new_time); - is_done = TRUE; - - } else { - crm_malloc0(new_time, sizeof(ha_time_t)); - crm_malloc0(new_time->has, sizeof(ha_has_time_t)); - } + gboolean is_done = FALSE; + gboolean converted = FALSE; + ha_time_t *new_time = NULL; - while(is_done == FALSE) { - char ch = (*date_str)[0]; - crm_debug_5("Switching on ch=%c (len=%d)", - ch, (int)strlen(*date_str)); - - if(ch == 0) { - /* all done */ - is_done = TRUE; - break; - - } else if(ch == '/') { - /* all done - interval marker */ - is_done = TRUE; - break; - - } else if(ch == 'W') { - CRM_CHECK(new_time->has->weeks == FALSE, ;); - (*date_str)++; - if(parse_int(date_str, 2, 53, &new_time->weeks)){ - new_time->has->weeks = TRUE; - new_time->weekyears = new_time->years; - new_time->has->weekyears = new_time->has->years; - } - if((*date_str)[0] == '-') { - (*date_str)++; - if(parse_int(date_str, 1, 7, &new_time->weekdays)) { - new_time->has->weekdays = TRUE; - } - } - - if(new_time->weekdays == 0 - || new_time->has->weekdays == FALSE) { - new_time->weekdays = 1; - new_time->has->weekdays = TRUE; - } - - } else if(ch == '-') { - (*date_str)++; - if(check_for_ordinal(*date_str)) { - if(parse_int(date_str, 3, 366, &new_time->yeardays)) { - new_time->has->yeardays = TRUE; - } - } - - } else if(ch == 'O') { - /* ordinal date */ - (*date_str)++; - if(parse_int(date_str, 3, 366, &new_time->yeardays)){ - new_time->has->yeardays = TRUE; - } - - } else if(ch == 'T' || ch == ' ') { - if(new_time->has->yeardays) { - converted = convert_from_ordinal(new_time); - - } else if(new_time->has->weekdays) { - converted = convert_from_weekdays(new_time); - - } else { - converted = convert_from_gregorian(new_time); - } - (*date_str)++; - parse_time(date_str, new_time, TRUE); - is_done = TRUE; - - } else if(isdigit((int) ch)) { - if(new_time->has->years == FALSE - && parse_int(date_str, 4, 9999, &new_time->years)) { - new_time->has->years = TRUE; - - } else if(check_for_ordinal(*date_str) && parse_int( - date_str, 3, - is_leap_year(new_time->years)?366:365, - &new_time->yeardays)) { - new_time->has->yeardays = TRUE; - - } else if(new_time->has->months == FALSE - && parse_int(date_str, 2, 12, &new_time->months)) { - new_time->has->months = TRUE; - - } else if(new_time->has->days == FALSE) { - if(parse_int(date_str, 2, - days_per_month(new_time->months, new_time->years), - &new_time->days)) { - new_time->has->days = TRUE; - } - } - - } else { - crm_err("Unexpected characters at: %s", *date_str); - is_done = TRUE; - break; - } - } + CRM_CHECK(date_str != NULL, return NULL); + CRM_CHECK(strlen(*date_str) > 0, return NULL); - if(converted) { - - } else if(new_time->has->yeardays) { - convert_from_ordinal(new_time); + if ((*date_str)[0] == 'T' || (*date_str)[2] == ':') { + /* Just a time supplied - Infer current date */ + new_time = new_ha_date(TRUE); - } else if(new_time->has->weekdays) { - convert_from_weekdays(new_time); + parse_time(date_str, new_time, TRUE); + normalize_time(new_time); + is_done = TRUE; - } else { - convert_from_gregorian(new_time); - } + } else { + crm_malloc0(new_time, sizeof(ha_time_t)); + crm_malloc0(new_time->has, sizeof(ha_has_time_t)); + } - normalize_time(new_time); - - log_date(LOG_DEBUG_3, "Unpacked", new_time, ha_log_date|ha_log_time); + while (is_done == FALSE) { + char ch = (*date_str)[0]; + + crm_debug_5("Switching on ch=%c (len=%d)", ch, (int)strlen(*date_str)); + + if (ch == 0) { + /* all done */ + is_done = TRUE; + break; + + } else if (ch == '/') { + /* all done - interval marker */ + is_done = TRUE; + break; + + } else if (ch == 'W') { + CRM_CHECK(new_time->has->weeks == FALSE,; + ); + (*date_str)++; + if (parse_int(date_str, 2, 53, &new_time->weeks)) { + new_time->has->weeks = TRUE; + new_time->weekyears = new_time->years; + new_time->has->weekyears = new_time->has->years; + } + if ((*date_str)[0] == '-') { + (*date_str)++; + if (parse_int(date_str, 1, 7, &new_time->weekdays)) { + new_time->has->weekdays = TRUE; + } + } + + if (new_time->weekdays == 0 || new_time->has->weekdays == FALSE) { + new_time->weekdays = 1; + new_time->has->weekdays = TRUE; + } + + } else if (ch == '-') { + (*date_str)++; + if (check_for_ordinal(*date_str)) { + if (parse_int(date_str, 3, 366, &new_time->yeardays)) { + new_time->has->yeardays = TRUE; + } + } + + } else if (ch == 'O') { + /* ordinal date */ + (*date_str)++; + if (parse_int(date_str, 3, 366, &new_time->yeardays)) { + new_time->has->yeardays = TRUE; + } + + } else if (ch == 'T' || ch == ' ') { + if (new_time->has->yeardays) { + converted = convert_from_ordinal(new_time); + + } else if (new_time->has->weekdays) { + converted = convert_from_weekdays(new_time); + + } else { + converted = convert_from_gregorian(new_time); + } + (*date_str)++; + parse_time(date_str, new_time, TRUE); + is_done = TRUE; + + } else if (isdigit((int)ch)) { + if (new_time->has->years == FALSE && parse_int(date_str, 4, 9999, &new_time->years)) { + new_time->has->years = TRUE; + + } else if (check_for_ordinal(*date_str) && parse_int(date_str, 3, + is_leap_year(new_time->years) ? 366 + : 365, &new_time->yeardays)) { + new_time->has->yeardays = TRUE; + + } else if (new_time->has->months == FALSE + && parse_int(date_str, 2, 12, &new_time->months)) { + new_time->has->months = TRUE; + + } else if (new_time->has->days == FALSE) { + if (parse_int(date_str, 2, + days_per_month(new_time->months, new_time->years), &new_time->days)) { + new_time->has->days = TRUE; + } + } + + } else { + crm_err("Unexpected characters at: %s", *date_str); + is_done = TRUE; + break; + } + } + + if (converted) { + + } else if (new_time->has->yeardays) { + convert_from_ordinal(new_time); + + } else if (new_time->has->weekdays) { + convert_from_weekdays(new_time); + + } else { + convert_from_gregorian(new_time); + } + + normalize_time(new_time); + + log_date(LOG_DEBUG_3, "Unpacked", new_time, ha_log_date | ha_log_time); - CRM_CHECK(is_date_sane(new_time), return NULL); - - return new_time; + CRM_CHECK(is_date_sane(new_time), return NULL); + + return new_time; } -ha_time_t* +ha_time_t * parse_time_duration(char **interval_str) { - gboolean is_time = FALSE; - ha_time_t *diff = NULL; - - CRM_CHECK(interval_str != NULL, goto bail); - CRM_CHECK(strlen(*interval_str) > 0, goto bail); - CRM_CHECK((*interval_str)[0] == 'P', goto bail); - (*interval_str)++; - - crm_malloc0(diff, sizeof(ha_time_t)); - crm_malloc0(diff->has, sizeof(ha_has_time_t)); - - while(isspace((int) (*interval_str)[0]) == FALSE) { - int an_int = 0; - char ch = 0; - - if((*interval_str)[0] == 'T') { - is_time = TRUE; - (*interval_str)++; - } - - if(parse_int(interval_str, 10, 0, &an_int) == FALSE) { - break; - } - ch = (*interval_str)[0]; - (*interval_str)++; - - crm_debug_4("%c=%d", ch, an_int); - - switch(ch) { - case 0: - return diff; - break; - case 'Y': - diff->years = an_int; - diff->has->years = TRUE; - break; - case 'M': - if(is_time) { - diff->minutes = an_int; - diff->has->minutes = TRUE; - } else { - diff->months = an_int; - diff->has->months = TRUE; - } - break; - case 'W': - diff->weeks = an_int; - diff->has->weeks = TRUE; - break; - case 'D': - diff->days = an_int; - diff->has->days = TRUE; - diff->yeardays = an_int; - diff->has->yeardays = TRUE; - break; - case 'H': - diff->hours = an_int; - diff->has->hours = TRUE; - break; - case 'S': - diff->seconds = an_int; - diff->has->seconds = TRUE; - break; - default: - goto bail; - break; - } - } - return diff; + gboolean is_time = FALSE; + ha_time_t *diff = NULL; + + CRM_CHECK(interval_str != NULL, goto bail); + CRM_CHECK(strlen(*interval_str) > 0, goto bail); + CRM_CHECK((*interval_str)[0] == 'P', goto bail); + (*interval_str)++; + + crm_malloc0(diff, sizeof(ha_time_t)); + crm_malloc0(diff->has, sizeof(ha_has_time_t)); + + while (isspace((int)(*interval_str)[0]) == FALSE) { + int an_int = 0; + char ch = 0; + + if ((*interval_str)[0] == 'T') { + is_time = TRUE; + (*interval_str)++; + } + + if (parse_int(interval_str, 10, 0, &an_int) == FALSE) { + break; + } + ch = (*interval_str)[0]; + (*interval_str)++; + + crm_debug_4("%c=%d", ch, an_int); + + switch (ch) { + case 0: + return diff; + break; + case 'Y': + diff->years = an_int; + diff->has->years = TRUE; + break; + case 'M': + if (is_time) { + diff->minutes = an_int; + diff->has->minutes = TRUE; + } else { + diff->months = an_int; + diff->has->months = TRUE; + } + break; + case 'W': + diff->weeks = an_int; + diff->has->weeks = TRUE; + break; + case 'D': + diff->days = an_int; + diff->has->days = TRUE; + diff->yeardays = an_int; + diff->has->yeardays = TRUE; + break; + case 'H': + diff->hours = an_int; + diff->has->hours = TRUE; + break; + case 'S': + diff->seconds = an_int; + diff->has->seconds = TRUE; + break; + default: + goto bail; + break; + } + } + return diff; bail: - if(diff) { - crm_free(diff->has); - } - crm_free(diff); - return NULL; + if (diff) { + crm_free(diff->has); + } + crm_free(diff); + return NULL; } -ha_time_period_t* +ha_time_period_t * parse_time_period(char **period_str) { - gboolean invalid = FALSE; - const char *original = *period_str; - ha_time_period_t *period = NULL; - - CRM_CHECK(period_str != NULL, return NULL); - CRM_CHECK(strlen(*period_str) > 0, return NULL); - - tzset(); - crm_malloc0(period, sizeof(ha_time_period_t)); - - if((*period_str)[0] == 'P') { - period->diff = parse_time_duration(period_str); - } else { - period->start = parse_date(period_str); - } + gboolean invalid = FALSE; + const char *original = *period_str; + ha_time_period_t *period = NULL; - if((*period_str)[0] != 0) { - CRM_CHECK((*period_str)[0] == '/', invalid = TRUE; goto bail); - (*period_str)++; - - if((*period_str)[0] == 'P') { - period->diff = parse_time_duration(period_str); - } else { - period->end = parse_date(period_str); - } - - } else if(period->diff != NULL) { - /* just aduration starting from now */ - time_t now = time(NULL); - crm_malloc0(period->start, sizeof(ha_time_t)); - crm_malloc0(period->start->has, sizeof(ha_has_time_t)); - crm_malloc0(period->start->offset, sizeof(ha_time_t)); - crm_malloc0(period->start->offset->has, sizeof(ha_has_time_t)); - - ha_set_timet_time(period->start, &now); - normalize_time(period->start); - - } else { - invalid = TRUE; - CRM_CHECK((*period_str)[0] == '/', goto bail); - goto bail; - } - - - /* sanity checks */ - if(period->start == NULL && period->end == NULL) { - crm_err("Invalid time period: %s", original); - invalid = TRUE; - - } else if(period->start == NULL && period->diff == NULL) { - crm_err("Invalid time period: %s", original); - invalid = TRUE; - - } else if(period->end == NULL && period->diff == NULL) { - crm_err("Invalid time period: %s", original); - invalid = TRUE; - } + CRM_CHECK(period_str != NULL, return NULL); + CRM_CHECK(strlen(*period_str) > 0, return NULL); + + tzset(); + crm_malloc0(period, sizeof(ha_time_period_t)); + + if ((*period_str)[0] == 'P') { + period->diff = parse_time_duration(period_str); + } else { + period->start = parse_date(period_str); + } + + if ((*period_str)[0] != 0) { + CRM_CHECK((*period_str)[0] == '/', invalid = TRUE; + goto bail); + (*period_str)++; + + if ((*period_str)[0] == 'P') { + period->diff = parse_time_duration(period_str); + } else { + period->end = parse_date(period_str); + } + + } else if (period->diff != NULL) { + /* just aduration starting from now */ + time_t now = time(NULL); + + crm_malloc0(period->start, sizeof(ha_time_t)); + crm_malloc0(period->start->has, sizeof(ha_has_time_t)); + crm_malloc0(period->start->offset, sizeof(ha_time_t)); + crm_malloc0(period->start->offset->has, sizeof(ha_has_time_t)); + + ha_set_timet_time(period->start, &now); + normalize_time(period->start); + + } else { + invalid = TRUE; + CRM_CHECK((*period_str)[0] == '/', goto bail); + goto bail; + } + + /* sanity checks */ + if (period->start == NULL && period->end == NULL) { + crm_err("Invalid time period: %s", original); + invalid = TRUE; + + } else if (period->start == NULL && period->diff == NULL) { + crm_err("Invalid time period: %s", original); + invalid = TRUE; + + } else if (period->end == NULL && period->diff == NULL) { + crm_err("Invalid time period: %s", original); + invalid = TRUE; + } bail: - if(invalid) { - crm_free(period->start); - crm_free(period->end); - crm_free(period->diff); - crm_free(period); - return NULL; - } - if(period->end == NULL && period->diff == NULL) { - } - - if(period->start == NULL) { - period->start = subtract_duration(period->end, period->diff); - normalize_time(period->start); - - } else if(period->end == NULL) { - period->end = add_time(period->start, period->diff); - normalize_time(period->end); - } + if (invalid) { + crm_free(period->start); + crm_free(period->end); + crm_free(period->diff); + crm_free(period); + return NULL; + } + if (period->end == NULL && period->diff == NULL) { + } - is_date_sane(period->start); - is_date_sane(period->end); - - return period; + if (period->start == NULL) { + period->start = subtract_duration(period->end, period->diff); + normalize_time(period->start); + + } else if (period->end == NULL) { + period->end = add_time(period->start, period->diff); + normalize_time(period->end); + } + + is_date_sane(period->start); + is_date_sane(period->end); + + return period; } int month2days[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; /* http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt */ int -january1(int year) +january1(int year) { - int YY = (year - 1) % 100; - int C = (year - 1) - YY; - int G = YY + YY/4; - int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7); - crm_debug_6("YY=%d, C=%d, G=%d", YY, C, G); - crm_debug_5("January 1 %.4d: %d", year, jan1); - return jan1; + int YY = (year - 1) % 100; + int C = (year - 1) - YY; + int G = YY + YY / 4; + int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7); + + crm_debug_6("YY=%d, C=%d, G=%d", YY, C, G); + crm_debug_5("January 1 %.4d: %d", year, jan1); + return jan1; } int -weeks_in_year(int year) +weeks_in_year(int year) { - int weeks = 52; - int jan1 = january1(year); - /* if jan1 == thursday */ - if(jan1 == 4) { - weeks++; - } else { - jan1 = january1(year+1); - /* if dec31 == thursday aka. jan1 of next year is a friday */ - if(jan1 == 5) { - weeks++; - } - - } - return weeks; + int weeks = 52; + int jan1 = january1(year); + + /* if jan1 == thursday */ + if (jan1 == 4) { + weeks++; + } else { + jan1 = january1(year + 1); + /* if dec31 == thursday aka. jan1 of next year is a friday */ + if (jan1 == 5) { + weeks++; + } + + } + return weeks; } gboolean -convert_from_gregorian(ha_time_t *a_date) +convert_from_gregorian(ha_time_t * a_date) { - CRM_CHECK(gregorian_to_ordinal(a_date), return FALSE); - CRM_CHECK(ordinal_to_weekdays(a_date), return FALSE); - return TRUE; + CRM_CHECK(gregorian_to_ordinal(a_date), return FALSE); + CRM_CHECK(ordinal_to_weekdays(a_date), return FALSE); + return TRUE; } gboolean -gregorian_to_ordinal(ha_time_t *a_date) +gregorian_to_ordinal(ha_time_t * a_date) { - CRM_CHECK(a_date->has->years, return FALSE); - CRM_CHECK(a_date->has->months, return FALSE); - CRM_CHECK(a_date->has->days, return FALSE); - - CRM_CHECK(a_date->months > 0, return FALSE); - CRM_CHECK(a_date->days > 0, return FALSE); - - a_date->yeardays = month2days[a_date->months-1]; - a_date->yeardays += a_date->days; - a_date->has->yeardays = TRUE; - - if(is_leap_year(a_date->years) && a_date->months > 2) { - (a_date->yeardays)++; - } - crm_debug_4("Converted %.4d-%.2d-%.2d to %.4d-%.3d", - a_date->years, a_date->months, a_date->days, - a_date->years, a_date->yeardays); - - return TRUE; + CRM_CHECK(a_date->has->years, return FALSE); + CRM_CHECK(a_date->has->months, return FALSE); + CRM_CHECK(a_date->has->days, return FALSE); + + CRM_CHECK(a_date->months > 0, return FALSE); + CRM_CHECK(a_date->days > 0, return FALSE); + + a_date->yeardays = month2days[a_date->months - 1]; + a_date->yeardays += a_date->days; + a_date->has->yeardays = TRUE; + + if (is_leap_year(a_date->years) && a_date->months > 2) { + (a_date->yeardays)++; + } + crm_debug_4("Converted %.4d-%.2d-%.2d to %.4d-%.3d", + a_date->years, a_date->months, a_date->days, a_date->years, a_date->yeardays); + + return TRUE; } gboolean -convert_from_ordinal(ha_time_t *a_date) +convert_from_ordinal(ha_time_t * a_date) { - CRM_CHECK(ordinal_to_gregorian(a_date), return FALSE); - CRM_CHECK(ordinal_to_weekdays(a_date), return FALSE); - return TRUE; + CRM_CHECK(ordinal_to_gregorian(a_date), return FALSE); + CRM_CHECK(ordinal_to_weekdays(a_date), return FALSE); + return TRUE; } - -gboolean ordinal_to_gregorian(ha_time_t *a_date) +gboolean +ordinal_to_gregorian(ha_time_t * a_date) { - /* Day of the year this month ends on */ - int m_end = 0; - - CRM_CHECK(a_date->has->years, return FALSE); - CRM_CHECK(a_date->has->yeardays, return FALSE); - - CRM_CHECK(a_date->yeardays > 0, return FALSE); - - if(is_leap_year(a_date->years) && a_date->yeardays > 366) { - crm_err("Year %.4d only has 366 days (supplied %.3d)", - a_date->years, a_date->yeardays); - a_date->yeardays = 366; - - } else if(!is_leap_year(a_date->years) && a_date->yeardays > 365) { - crm_err("Year %.4d only has 365 days (supplied %.3d)", - a_date->years, a_date->yeardays); - a_date->yeardays = 365; - } - - a_date->days = a_date->yeardays; - a_date->months = 0; - do { - a_date->months++; - m_end += days_per_month(a_date->months, a_date->years); - a_date->days -= days_per_month(a_date->months-1, a_date->years); - - crm_debug_6("month %d: %d vs. %d - current day: %d", - a_date->months, a_date->yeardays, - m_end, a_date->days); - } while (a_date->months < 12 && m_end < a_date->yeardays); - - CRM_CHECK(a_date->months > 0, return FALSE); - CRM_CHECK(a_date->days <= days_per_month(a_date->months, a_date->years), - return FALSE); - - a_date->has->days = TRUE; - a_date->has->months = TRUE; - a_date->has->years = TRUE; - - crm_debug_4("Converted %.4d-%.3d to %.4d-%.2d-%.2d", - a_date->years, a_date->yeardays, - a_date->years, a_date->months, a_date->days); - - return TRUE; -} + /* Day of the year this month ends on */ + int m_end = 0; + + CRM_CHECK(a_date->has->years, return FALSE); + CRM_CHECK(a_date->has->yeardays, return FALSE); + + CRM_CHECK(a_date->yeardays > 0, return FALSE); + + if (is_leap_year(a_date->years) && a_date->yeardays > 366) { + crm_err("Year %.4d only has 366 days (supplied %.3d)", a_date->years, a_date->yeardays); + a_date->yeardays = 366; + + } else if (!is_leap_year(a_date->years) && a_date->yeardays > 365) { + crm_err("Year %.4d only has 365 days (supplied %.3d)", a_date->years, a_date->yeardays); + a_date->yeardays = 365; + } + + a_date->days = a_date->yeardays; + a_date->months = 0; + do { + a_date->months++; + m_end += days_per_month(a_date->months, a_date->years); + a_date->days -= days_per_month(a_date->months - 1, a_date->years); + crm_debug_6("month %d: %d vs. %d - current day: %d", + a_date->months, a_date->yeardays, m_end, a_date->days); + } while (a_date->months < 12 && m_end < a_date->yeardays); + + CRM_CHECK(a_date->months > 0, return FALSE); + CRM_CHECK(a_date->days <= days_per_month(a_date->months, a_date->years), return FALSE); + + a_date->has->days = TRUE; + a_date->has->months = TRUE; + a_date->has->years = TRUE; + + crm_debug_4("Converted %.4d-%.3d to %.4d-%.2d-%.2d", + a_date->years, a_date->yeardays, a_date->years, a_date->months, a_date->days); + + return TRUE; +} gboolean -ordinal_to_weekdays(ha_time_t *a_date) +ordinal_to_weekdays(ha_time_t * a_date) { - int year_num = 0; - int jan1 = january1(a_date->years); - int h = -1; - - CRM_CHECK(a_date->has->years, return FALSE); - CRM_CHECK(a_date->has->yeardays, return FALSE); - CRM_CHECK(a_date->yeardays > 0, return FALSE); - - h = a_date->yeardays + jan1 - 1; - a_date->weekdays = 1 + ((h-1) % 7); - a_date->has->weekdays = TRUE; - - if(a_date->yeardays <= (8-jan1) && jan1 > 4) { - year_num = a_date->years - 1; - a_date->weeks = weeks_in_year(year_num); - a_date->has->weeks = TRUE; - - } else { - year_num = a_date->years; - } + int year_num = 0; + int jan1 = january1(a_date->years); + int h = -1; - if(year_num == a_date->years) { - int i = 365; - if(is_leap_year(year_num)) { - i = 366; - } - if( (i - a_date->yeardays) < (4 - a_date->weekdays) ) { - year_num = a_date->years + 1; - a_date->weeks = 1; - a_date->has->weeks = TRUE; - } - } + CRM_CHECK(a_date->has->years, return FALSE); + CRM_CHECK(a_date->has->yeardays, return FALSE); + CRM_CHECK(a_date->yeardays > 0, return FALSE); - if(year_num == a_date->years) { - int j = a_date->yeardays + (7-a_date->weekdays) + (jan1 - 1); - a_date->weeks = j / 7; - a_date->has->weeks = TRUE; - if(jan1 > 4) { - a_date->weeks -= 1; - } - } + h = a_date->yeardays + jan1 - 1; + a_date->weekdays = 1 + ((h - 1) % 7); + a_date->has->weekdays = TRUE; - a_date->weekyears = year_num; - a_date->has->weekyears = TRUE; - crm_debug_4("Converted %.4d-%.3d to %.4dW%.2d-%d", - a_date->years, a_date->yeardays, - a_date->weekyears, a_date->weeks, a_date->weekdays); - return TRUE; + if (a_date->yeardays <= (8 - jan1) && jan1 > 4) { + year_num = a_date->years - 1; + a_date->weeks = weeks_in_year(year_num); + a_date->has->weeks = TRUE; + + } else { + year_num = a_date->years; + } + + if (year_num == a_date->years) { + int i = 365; + + if (is_leap_year(year_num)) { + i = 366; + } + if ((i - a_date->yeardays) < (4 - a_date->weekdays)) { + year_num = a_date->years + 1; + a_date->weeks = 1; + a_date->has->weeks = TRUE; + } + } + + if (year_num == a_date->years) { + int j = a_date->yeardays + (7 - a_date->weekdays) + (jan1 - 1); + + a_date->weeks = j / 7; + a_date->has->weeks = TRUE; + if (jan1 > 4) { + a_date->weeks -= 1; + } + } + + a_date->weekyears = year_num; + a_date->has->weekyears = TRUE; + crm_debug_4("Converted %.4d-%.3d to %.4dW%.2d-%d", + a_date->years, a_date->yeardays, + a_date->weekyears, a_date->weeks, a_date->weekdays); + return TRUE; } gboolean -convert_from_weekdays(ha_time_t *a_date) +convert_from_weekdays(ha_time_t * a_date) { - gboolean conversion = FALSE; - int jan1 = january1(a_date->weekyears); - - CRM_CHECK(a_date->has->weekyears, return FALSE); - CRM_CHECK(a_date->has->weeks, return FALSE); - CRM_CHECK(a_date->has->weekdays, return FALSE); - - CRM_CHECK(a_date->weeks > 0, return FALSE); - CRM_CHECK(a_date->weekdays > 0, return FALSE); - CRM_CHECK(a_date->weekdays < 8, return FALSE); - - a_date->has->years = TRUE; - a_date->years = a_date->weekyears; - - a_date->has->yeardays = TRUE; - a_date->yeardays = (7 * (a_date->weeks-1)); - - /* break up the addition to make sure overflows are correctly handled */ - if(a_date->yeardays == 0) { - a_date->yeardays = a_date->weekdays; - } else { - add_yeardays(a_date, a_date->weekdays); - } - - crm_debug_5("Pre-conversion: %dW%d-%d to %.4d-%.3d", - a_date->weekyears, a_date->weeks, a_date->weekdays, - a_date->years, a_date->yeardays); - - conversion = ordinal_to_gregorian(a_date); - - if(conversion) { - if(jan1 < 4) { - sub_days(a_date, jan1-1); - } else if(jan1 > 4) { - add_days(a_date, jan1-4); - } - } - return conversion; + gboolean conversion = FALSE; + int jan1 = january1(a_date->weekyears); + + CRM_CHECK(a_date->has->weekyears, return FALSE); + CRM_CHECK(a_date->has->weeks, return FALSE); + CRM_CHECK(a_date->has->weekdays, return FALSE); + + CRM_CHECK(a_date->weeks > 0, return FALSE); + CRM_CHECK(a_date->weekdays > 0, return FALSE); + CRM_CHECK(a_date->weekdays < 8, return FALSE); + + a_date->has->years = TRUE; + a_date->years = a_date->weekyears; + + a_date->has->yeardays = TRUE; + a_date->yeardays = (7 * (a_date->weeks - 1)); + + /* break up the addition to make sure overflows are correctly handled */ + if (a_date->yeardays == 0) { + a_date->yeardays = a_date->weekdays; + } else { + add_yeardays(a_date, a_date->weekdays); + } + + crm_debug_5("Pre-conversion: %dW%d-%d to %.4d-%.3d", + a_date->weekyears, a_date->weeks, a_date->weekdays, + a_date->years, a_date->yeardays); + + conversion = ordinal_to_gregorian(a_date); + + if (conversion) { + if (jan1 < 4) { + sub_days(a_date, jan1 - 1); + } else if (jan1 > 4) { + add_days(a_date, jan1 - 4); + } + } + return conversion; } void -ha_set_time(ha_time_t *lhs, ha_time_t *rhs, gboolean offset) +ha_set_time(ha_time_t * lhs, ha_time_t * rhs, gboolean offset) { - crm_debug_6("lhs=%p, rhs=%p, offset=%d", lhs, rhs, offset); + crm_debug_6("lhs=%p, rhs=%p, offset=%d", lhs, rhs, offset); - CRM_CHECK(lhs != NULL && rhs != NULL, return); - CRM_CHECK(lhs->has != NULL && rhs->has != NULL, return); - - lhs->years = rhs->years; - lhs->has->years = rhs->has->years; + CRM_CHECK(lhs != NULL && rhs != NULL, return); + CRM_CHECK(lhs->has != NULL && rhs->has != NULL, return); - lhs->weekyears = rhs->weekyears; - lhs->has->weekyears = rhs->has->weekyears; - - lhs->months = rhs->months; - lhs->has->months = rhs->has->months; + lhs->years = rhs->years; + lhs->has->years = rhs->has->years; - lhs->weeks = rhs->weeks; - lhs->has->weeks = rhs->has->weeks; + lhs->weekyears = rhs->weekyears; + lhs->has->weekyears = rhs->has->weekyears; - lhs->days = rhs->days; - lhs->has->days = rhs->has->days; + lhs->months = rhs->months; + lhs->has->months = rhs->has->months; - lhs->weekdays = rhs->weekdays; - lhs->has->weekdays = rhs->has->weekdays; - - lhs->yeardays = rhs->yeardays; - lhs->has->yeardays = rhs->has->yeardays; + lhs->weeks = rhs->weeks; + lhs->has->weeks = rhs->has->weeks; - lhs->hours = rhs->hours; - lhs->has->hours = rhs->has->hours; + lhs->days = rhs->days; + lhs->has->days = rhs->has->days; - lhs->minutes = rhs->minutes; - lhs->has->minutes = rhs->has->minutes; + lhs->weekdays = rhs->weekdays; + lhs->has->weekdays = rhs->has->weekdays; - lhs->seconds = rhs->seconds; - lhs->has->seconds = rhs->has->seconds; + lhs->yeardays = rhs->yeardays; + lhs->has->yeardays = rhs->has->yeardays; - if(lhs->offset) { - reset_time(lhs->offset); - } - if(offset && rhs->offset) { - ha_set_time(lhs->offset, rhs->offset, FALSE); - } - -} + lhs->hours = rhs->hours; + lhs->has->hours = rhs->has->hours; + lhs->minutes = rhs->minutes; + lhs->has->minutes = rhs->has->minutes; + lhs->seconds = rhs->seconds; + lhs->has->seconds = rhs->has->seconds; + + if (lhs->offset) { + reset_time(lhs->offset); + } + if (offset && rhs->offset) { + ha_set_time(lhs->offset, rhs->offset, FALSE); + } + +} void -ha_set_tm_time(ha_time_t *lhs, struct tm *rhs) +ha_set_tm_time(ha_time_t * lhs, struct tm *rhs) { - int wday = rhs->tm_wday; - int h_offset = 0; - int m_offset = 0; - - if(rhs->tm_year > 0) { - /* years since 1900 */ - lhs->years = 1900 + rhs->tm_year; - lhs->has->years = TRUE; - } + int wday = rhs->tm_wday; + int h_offset = 0; + int m_offset = 0; + + if (rhs->tm_year > 0) { + /* years since 1900 */ + lhs->years = 1900 + rhs->tm_year; + lhs->has->years = TRUE; + } - if(rhs->tm_yday >= 0) { - /* days since January 1 [0-365] */ - lhs->yeardays = 1 + rhs->tm_yday; - lhs->has->yeardays =TRUE; - } + if (rhs->tm_yday >= 0) { + /* days since January 1 [0-365] */ + lhs->yeardays = 1 + rhs->tm_yday; + lhs->has->yeardays = TRUE; + } - if(rhs->tm_hour >= 0) { - lhs->hours = rhs->tm_hour; - lhs->has->hours =TRUE; - } - if(rhs->tm_min >= 0) { - lhs->minutes = rhs->tm_min; - lhs->has->minutes =TRUE; - } - if(rhs->tm_sec >= 0) { - lhs->seconds = rhs->tm_sec; - lhs->has->seconds =TRUE; - } + if (rhs->tm_hour >= 0) { + lhs->hours = rhs->tm_hour; + lhs->has->hours = TRUE; + } + if (rhs->tm_min >= 0) { + lhs->minutes = rhs->tm_min; + lhs->has->minutes = TRUE; + } + if (rhs->tm_sec >= 0) { + lhs->seconds = rhs->tm_sec; + lhs->has->seconds = TRUE; + } - convert_from_ordinal(lhs); + convert_from_ordinal(lhs); - /* months since January [0-11] */ - CRM_CHECK(rhs->tm_mon < 0 || lhs->months == (1 + rhs->tm_mon), return); + /* months since January [0-11] */ + CRM_CHECK(rhs->tm_mon < 0 || lhs->months == (1 + rhs->tm_mon), return); - /* day of the month [1-31] */ - CRM_CHECK(rhs->tm_mday < 0 || lhs->days == rhs->tm_mday, return); + /* day of the month [1-31] */ + CRM_CHECK(rhs->tm_mday < 0 || lhs->days == rhs->tm_mday, return); - /* days since Sunday [0-6] */ - if(wday == 0) { - wday= 7; - } - - CRM_CHECK(rhs->tm_wday < 0 || lhs->weekdays == wday, return); - CRM_CHECK(lhs->offset != NULL, return); - CRM_CHECK(lhs->offset->has != NULL, return); - - /* tm_gmtoff == offset from UTC in seconds */ - h_offset = GMTOFF(rhs) / (3600); - m_offset = (GMTOFF(rhs) - (3600 * h_offset)) / (60); - crm_debug_6("Offset (s): %ld, offset (hh:mm): %.2d:%.2d", - GMTOFF(rhs), h_offset, m_offset); - - lhs->offset->hours = h_offset; - lhs->offset->has->hours = TRUE; - - lhs->offset->minutes = m_offset; - lhs->offset->has->minutes = TRUE; - - normalize_time(lhs); -} + /* days since Sunday [0-6] */ + if (wday == 0) { + wday = 7; + } + + CRM_CHECK(rhs->tm_wday < 0 || lhs->weekdays == wday, return); + CRM_CHECK(lhs->offset != NULL, return); + CRM_CHECK(lhs->offset->has != NULL, return); + + /* tm_gmtoff == offset from UTC in seconds */ + h_offset = GMTOFF(rhs) / (3600); + m_offset = (GMTOFF(rhs) - (3600 * h_offset)) / (60); + crm_debug_6("Offset (s): %ld, offset (hh:mm): %.2d:%.2d", GMTOFF(rhs), h_offset, m_offset); + lhs->offset->hours = h_offset; + lhs->offset->has->hours = TRUE; + + lhs->offset->minutes = m_offset; + lhs->offset->has->minutes = TRUE; + + normalize_time(lhs); +} void -ha_set_timet_time(ha_time_t *lhs, time_t *rhs) +ha_set_timet_time(ha_time_t * lhs, time_t * rhs) { - ha_set_tm_time(lhs, localtime(rhs)); + ha_set_tm_time(lhs, localtime(rhs)); } ha_time_t * -add_time(ha_time_t *lhs, ha_time_t *rhs) +add_time(ha_time_t * lhs, ha_time_t * rhs) { - ha_time_t *answer = NULL; - CRM_CHECK(lhs != NULL && rhs != NULL, return NULL); - - answer = new_ha_date(FALSE); - ha_set_time(answer, lhs, TRUE); + ha_time_t *answer = NULL; - normalize_time(lhs); - normalize_time(answer); + CRM_CHECK(lhs != NULL && rhs != NULL, return NULL); - if(rhs->has->years) { - add_years(answer, rhs->years); - } - if(rhs->has->months) { - add_months(answer, rhs->months); - } - if(rhs->has->weeks) { - add_weeks(answer, rhs->weeks); - } - if(rhs->has->days) { - add_days(answer, rhs->days); - } + answer = new_ha_date(FALSE); + ha_set_time(answer, lhs, TRUE); + + normalize_time(lhs); + normalize_time(answer); + + if (rhs->has->years) { + add_years(answer, rhs->years); + } + if (rhs->has->months) { + add_months(answer, rhs->months); + } + if (rhs->has->weeks) { + add_weeks(answer, rhs->weeks); + } + if (rhs->has->days) { + add_days(answer, rhs->days); + } - add_hours(answer, rhs->hours); - add_minutes(answer, rhs->minutes); - add_seconds(answer, rhs->seconds); + add_hours(answer, rhs->hours); + add_minutes(answer, rhs->minutes); + add_seconds(answer, rhs->seconds); - normalize_time(answer); - - return answer; + normalize_time(answer); + + return answer; } ha_time_t * -subtract_time(ha_time_t *lhs, ha_time_t *rhs) +subtract_time(ha_time_t * lhs, ha_time_t * rhs) { - ha_time_t *answer = NULL; - CRM_CHECK(lhs != NULL && rhs != NULL, return NULL); + ha_time_t *answer = NULL; - answer = new_ha_date(FALSE); - ha_set_time(answer, lhs, TRUE); + CRM_CHECK(lhs != NULL && rhs != NULL, return NULL); - normalize_time(lhs); - normalize_time(rhs); - normalize_time(answer); + answer = new_ha_date(FALSE); + ha_set_time(answer, lhs, TRUE); - sub_seconds(answer, rhs->seconds); - sub_minutes(answer, rhs->minutes); - sub_hours(answer, rhs->hours); + normalize_time(lhs); + normalize_time(rhs); + normalize_time(answer); - answer->yeardays -= rhs->yeardays; - while(answer->yeardays < 0) { - answer->yeardays += is_leap_year(answer->years)?356:355; - answer->years--; - } - - answer->days -= rhs->days; - while(answer->days < 0) { - answer->days += days_per_month(answer->months, answer->years); - answer->months--; - } - - answer->months -= rhs->months; - while(answer->months < 0) { - answer->months += 12; - /* answer->years--; : done in the yeardays section */ - } - - answer->years -= rhs->years; + sub_seconds(answer, rhs->seconds); + sub_minutes(answer, rhs->minutes); + sub_hours(answer, rhs->hours); + + answer->yeardays -= rhs->yeardays; + while (answer->yeardays < 0) { + answer->yeardays += is_leap_year(answer->years) ? 356 : 355; + answer->years--; + } - return answer; + answer->days -= rhs->days; + while (answer->days < 0) { + answer->days += days_per_month(answer->months, answer->years); + answer->months--; + } + + answer->months -= rhs->months; + while (answer->months < 0) { + answer->months += 12; + /* answer->years--; : done in the yeardays section */ + } + + answer->years -= rhs->years; + + return answer; } ha_time_t * -subtract_duration(ha_time_t *lhs, ha_time_t *rhs) +subtract_duration(ha_time_t * lhs, ha_time_t * rhs) { - ha_time_t *answer = NULL; - CRM_CHECK(lhs != NULL && rhs != NULL, return NULL); - - answer = new_ha_date(FALSE); - ha_set_time(answer, lhs, TRUE); - - normalize_time(lhs); - normalize_time(rhs); - normalize_time(answer); - - sub_seconds(answer, rhs->seconds); - sub_minutes(answer, rhs->minutes); - sub_hours(answer, rhs->hours); - - sub_days(answer, rhs->days); - sub_weeks(answer, rhs->weeks); - sub_months(answer, rhs->months); - sub_years(answer, rhs->years); - - normalize_time(answer); - - return answer; + ha_time_t *answer = NULL; + + CRM_CHECK(lhs != NULL && rhs != NULL, return NULL); + + answer = new_ha_date(FALSE); + ha_set_time(answer, lhs, TRUE); + + normalize_time(lhs); + normalize_time(rhs); + normalize_time(answer); + + sub_seconds(answer, rhs->seconds); + sub_minutes(answer, rhs->minutes); + sub_hours(answer, rhs->hours); + + sub_days(answer, rhs->days); + sub_weeks(answer, rhs->weeks); + sub_months(answer, rhs->months); + sub_years(answer, rhs->years); + + normalize_time(answer); + + return answer; } /* ha_time_interval_t* */ /* parse_time_interval(char **interval_str) */ /* { */ /* return NULL; */ /* } */ int month_days[14] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 29 }; + int days_per_month(int month, int year) { - if(month == 2 && is_leap_year(year)) { - month = 13; - } - return month_days[month]; + if (month == 2 && is_leap_year(year)) { + month = 13; + } + return month_days[month]; } gboolean -is_leap_year(int year) +is_leap_year(int year) { - gboolean is_leap = FALSE; - if(year % 4 == 0) { - is_leap = TRUE; - } - if(year % 100 == 0 && year % 400 != 0 ) { - is_leap = FALSE; - } - return is_leap; -} + gboolean is_leap = FALSE; + if (year % 4 == 0) { + is_leap = TRUE; + } + if (year % 100 == 0 && year % 400 != 0) { + is_leap = FALSE; + } + return is_leap; +} gboolean parse_int(char **str, int field_width, int uppper_bound, int *result) { - int lpc = 0; - int intermediate = 0; - gboolean fraction = FALSE; - gboolean negate = FALSE; + int lpc = 0; + int intermediate = 0; + gboolean fraction = FALSE; + gboolean negate = FALSE; - CRM_CHECK(str != NULL, return FALSE); - CRM_CHECK(*str != NULL, return FALSE); - CRM_CHECK(result != NULL, return FALSE); + CRM_CHECK(str != NULL, return FALSE); + CRM_CHECK(*str != NULL, return FALSE); + CRM_CHECK(result != NULL, return FALSE); - *result = 0; + *result = 0; - if(strlen(*str) <= 0) { - return FALSE; - } - - if((*str)[0] == 'T') { - (*str)++; - } + if (strlen(*str) <= 0) { + return FALSE; + } - if((*str)[0] == '.' || (*str)[0] == ',') { - fraction = TRUE; - field_width = -1; - (*str)++; - } else if((*str)[0] == '-') { - negate = TRUE; - (*str)++; - } else if((*str)[0] == '+' - || (*str)[0] == ':') { - (*str)++; - } + if ((*str)[0] == 'T') { + (*str)++; + } - for(; (fraction || lpc < field_width) && isdigit((int) (*str)[0]); lpc++) { - if(fraction) { - intermediate = ((*str)[0] - '0')/(10^lpc); - } else { - *result *= 10; - intermediate = (*str)[0] - '0'; - } - *result += intermediate; - (*str)++; - } - if(fraction) { - *result = (int)(*result * uppper_bound); - - } else if(uppper_bound > 0 && *result > uppper_bound) { - *result = uppper_bound; - } - if(negate) { - *result = 0 - *result; - } - if(lpc > 0) { - crm_debug_5("Found int: %d. Stopped at str[%d]='%c'", *result, lpc, (*str)[lpc]); - return TRUE; - } - return FALSE; + if ((*str)[0] == '.' || (*str)[0] == ',') { + fraction = TRUE; + field_width = -1; + (*str)++; + } else if ((*str)[0] == '-') { + negate = TRUE; + (*str)++; + } else if ((*str)[0] == '+' || (*str)[0] == ':') { + (*str)++; + } + + for (; (fraction || lpc < field_width) && isdigit((int)(*str)[0]); lpc++) { + if (fraction) { + intermediate = ((*str)[0] - '0') / (10 ^ lpc); + } else { + *result *= 10; + intermediate = (*str)[0] - '0'; + } + *result += intermediate; + (*str)++; + } + if (fraction) { + *result = (int)(*result * uppper_bound); + + } else if (uppper_bound > 0 && *result > uppper_bound) { + *result = uppper_bound; + } + if (negate) { + *result = 0 - *result; + } + if (lpc > 0) { + crm_debug_5("Found int: %d. Stopped at str[%d]='%c'", *result, lpc, (*str)[lpc]); + return TRUE; + } + return FALSE; } gboolean check_for_ordinal(const char *str) { - if(isdigit((int) str[2]) == FALSE) { - crm_debug_6("char 3 == %c", str[2]); - return FALSE; - } - if(isspace((int) str[3])) { - return TRUE; - } else if(str[3] == 0) { - return TRUE; - } else if(str[3] == 'T') { - return TRUE; - } else if(str[3] == '/') { - return TRUE; - } - crm_debug_6("char 4 == %c", str[3]); - return FALSE; + if (isdigit((int)str[2]) == FALSE) { + crm_debug_6("char 3 == %c", str[2]); + return FALSE; + } + if (isspace((int)str[3])) { + return TRUE; + } else if (str[3] == 0) { + return TRUE; + } else if (str[3] == 'T') { + return TRUE; + } else if (str[3] == '/') { + return TRUE; + } + crm_debug_6("char 4 == %c", str[3]); + return FALSE; } -int str_lookup(const char *str, enum date_fields field) +int +str_lookup(const char *str, enum date_fields field) { - return 0; + return 0; } void -reset_time(ha_time_t *a_time) +reset_time(ha_time_t * a_time) { - a_time->years = 0; - a_time->has->years = FALSE; - - a_time->weekyears = 0; - a_time->has->weekyears = FALSE; - - a_time->months = 0; - a_time->has->months = FALSE; - - a_time->weeks = 0; - a_time->has->weeks = FALSE; - - a_time->days = 0; - a_time->has->days = FALSE; - - a_time->weekdays = 0; - a_time->has->weekdays = FALSE; - - a_time->yeardays = 0; - a_time->has->yeardays = FALSE; - - a_time->hours = 0; - a_time->has->hours = FALSE; - - a_time->minutes = 0; - a_time->has->minutes = FALSE; - - a_time->seconds = 0; - a_time->has->seconds = FALSE; -} + a_time->years = 0; + a_time->has->years = FALSE; + + a_time->weekyears = 0; + a_time->has->weekyears = FALSE; + + a_time->months = 0; + a_time->has->months = FALSE; + + a_time->weeks = 0; + a_time->has->weeks = FALSE; + a_time->days = 0; + a_time->has->days = FALSE; + + a_time->weekdays = 0; + a_time->has->weekdays = FALSE; + + a_time->yeardays = 0; + a_time->has->yeardays = FALSE; + + a_time->hours = 0; + a_time->has->hours = FALSE; + + a_time->minutes = 0; + a_time->has->minutes = FALSE; + + a_time->seconds = 0; + a_time->has->seconds = FALSE; +} void -reset_tm(struct tm *some_tm) +reset_tm(struct tm *some_tm) { - some_tm->tm_sec = -1; /* seconds after the minute [0-60] */ - some_tm->tm_min = -1; /* minutes after the hour [0-59] */ - some_tm->tm_hour = -1; /* hours since midnight [0-23] */ - some_tm->tm_mday = -1; /* day of the month [1-31] */ - some_tm->tm_mon = -1; /* months since January [0-11] */ - some_tm->tm_year = -1; /* years since 1900 */ - some_tm->tm_wday = -1; /* days since Sunday [0-6] */ - some_tm->tm_yday = -1; /* days since January 1 [0-365] */ - some_tm->tm_isdst = -1; /* Daylight Savings Time flag */ + some_tm->tm_sec = -1; /* seconds after the minute [0-60] */ + some_tm->tm_min = -1; /* minutes after the hour [0-59] */ + some_tm->tm_hour = -1; /* hours since midnight [0-23] */ + some_tm->tm_mday = -1; /* day of the month [1-31] */ + some_tm->tm_mon = -1; /* months since January [0-11] */ + some_tm->tm_year = -1; /* years since 1900 */ + some_tm->tm_wday = -1; /* days since Sunday [0-6] */ + some_tm->tm_yday = -1; /* days since January 1 [0-365] */ + some_tm->tm_isdst = -1; /* Daylight Savings Time flag */ #if defined(HAVE_STRUCT_TM_TM_GMTOFF) - some_tm->tm_gmtoff = -1; /* offset from CUT in seconds */ + some_tm->tm_gmtoff = -1; /* offset from CUT in seconds */ #endif #if defined(HAVE_TM_ZONE) - some_tm->tm_zone = NULL;/* timezone abbreviation */ + some_tm->tm_zone = NULL; /* timezone abbreviation */ #endif } gboolean -is_date_sane(ha_time_t *a_date) +is_date_sane(ha_time_t * a_date) { - int ydays = 0; - int mdays = 0; - int weeks = 0; - - CRM_CHECK(a_date != NULL, return FALSE); - - ydays = is_leap_year(a_date->years)?366:365; - mdays = days_per_month(a_date->months, a_date->years); - weeks = weeks_in_year(a_date->weekyears); - crm_debug_5("max ydays: %d, max mdays: %d, max weeks: %d", - ydays, mdays, weeks); - - CRM_CHECK(a_date->has->years, return FALSE); - CRM_CHECK(a_date->has->weekyears, return FALSE); - - CRM_CHECK(a_date->has->months, return FALSE); - CRM_CHECK(a_date->months > 0, return FALSE); - CRM_CHECK(a_date->months <= 12, return FALSE); - - CRM_CHECK(a_date->has->weeks, return FALSE); - CRM_CHECK(a_date->weeks > 0, return FALSE); - CRM_CHECK(a_date->weeks <= weeks, return FALSE); - - CRM_CHECK(a_date->has->days, return FALSE); - CRM_CHECK(a_date->days > 0, return FALSE); - CRM_CHECK(a_date->days <= mdays, return FALSE); - - CRM_CHECK(a_date->has->weekdays, return FALSE); - CRM_CHECK(a_date->weekdays > 0, return FALSE); - CRM_CHECK(a_date->weekdays <= 7, return FALSE); - - CRM_CHECK(a_date->has->yeardays, return FALSE); - CRM_CHECK(a_date->yeardays > 0, return FALSE); - CRM_CHECK(a_date->yeardays <= ydays, return FALSE); - - CRM_CHECK(a_date->hours >= 0, return FALSE); - CRM_CHECK(a_date->hours < 24, return FALSE); - - CRM_CHECK(a_date->minutes >= 0, return FALSE); - CRM_CHECK(a_date->minutes < 60, return FALSE); - - CRM_CHECK(a_date->seconds >= 0, return FALSE); - CRM_CHECK(a_date->seconds <= 60, return FALSE); - - return TRUE; + int ydays = 0; + int mdays = 0; + int weeks = 0; + + CRM_CHECK(a_date != NULL, return FALSE); + + ydays = is_leap_year(a_date->years) ? 366 : 365; + mdays = days_per_month(a_date->months, a_date->years); + weeks = weeks_in_year(a_date->weekyears); + crm_debug_5("max ydays: %d, max mdays: %d, max weeks: %d", ydays, mdays, weeks); + + CRM_CHECK(a_date->has->years, return FALSE); + CRM_CHECK(a_date->has->weekyears, return FALSE); + + CRM_CHECK(a_date->has->months, return FALSE); + CRM_CHECK(a_date->months > 0, return FALSE); + CRM_CHECK(a_date->months <= 12, return FALSE); + + CRM_CHECK(a_date->has->weeks, return FALSE); + CRM_CHECK(a_date->weeks > 0, return FALSE); + CRM_CHECK(a_date->weeks <= weeks, return FALSE); + + CRM_CHECK(a_date->has->days, return FALSE); + CRM_CHECK(a_date->days > 0, return FALSE); + CRM_CHECK(a_date->days <= mdays, return FALSE); + + CRM_CHECK(a_date->has->weekdays, return FALSE); + CRM_CHECK(a_date->weekdays > 0, return FALSE); + CRM_CHECK(a_date->weekdays <= 7, return FALSE); + + CRM_CHECK(a_date->has->yeardays, return FALSE); + CRM_CHECK(a_date->yeardays > 0, return FALSE); + CRM_CHECK(a_date->yeardays <= ydays, return FALSE); + + CRM_CHECK(a_date->hours >= 0, return FALSE); + CRM_CHECK(a_date->hours < 24, return FALSE); + + CRM_CHECK(a_date->minutes >= 0, return FALSE); + CRM_CHECK(a_date->minutes < 60, return FALSE); + + CRM_CHECK(a_date->seconds >= 0, return FALSE); + CRM_CHECK(a_date->seconds <= 60, return FALSE); + + return TRUE; } #define do_cmp_field(lhs, rhs, field) \ { \ if(lhs->field > rhs->field) { \ crm_debug_2("%s: %d > %d", \ #field, lhs->field, rhs->field); \ return 1; \ } else if(lhs->field < rhs->field) { \ crm_debug_2("%s: %d < %d", \ #field, lhs->field, rhs->field); \ return -1; \ } \ } int -compare_date(ha_time_t *lhs, ha_time_t *rhs) +compare_date(ha_time_t * lhs, ha_time_t * rhs) { - if(lhs == NULL && rhs == NULL) { - return 0; - } else if(lhs == NULL) { - return -1; - } else if(rhs == NULL) { - return 1; - } - - normalize_time(lhs); - normalize_time(rhs); + if (lhs == NULL && rhs == NULL) { + return 0; + } else if (lhs == NULL) { + return -1; + } else if (rhs == NULL) { + return 1; + } + + normalize_time(lhs); + normalize_time(rhs); - do_cmp_field(lhs->normalized, rhs->normalized, years); - do_cmp_field(lhs->normalized, rhs->normalized, yeardays); - do_cmp_field(lhs->normalized, rhs->normalized, hours); - do_cmp_field(lhs->normalized, rhs->normalized, minutes); - do_cmp_field(lhs->normalized, rhs->normalized, seconds); + do_cmp_field(lhs->normalized, rhs->normalized, years); + do_cmp_field(lhs->normalized, rhs->normalized, yeardays); + do_cmp_field(lhs->normalized, rhs->normalized, hours); + do_cmp_field(lhs->normalized, rhs->normalized, minutes); + do_cmp_field(lhs->normalized, rhs->normalized, seconds); - return 0; + return 0; } ha_time_t * -new_ha_date(gboolean set_to_now) +new_ha_date(gboolean set_to_now) { - time_t tm_now; - ha_time_t *now = NULL; - - tzset(); - crm_malloc0(now, sizeof(ha_time_t)); - crm_malloc0(now->has, sizeof(ha_has_time_t)); - crm_malloc0(now->offset, sizeof(ha_time_t)); - crm_malloc0(now->offset->has, sizeof(ha_has_time_t)); - if(set_to_now) { - tm_now = time(NULL); - now->tm_now = tm_now; - ha_set_timet_time(now, &tm_now); - } - return now; + time_t tm_now; + ha_time_t *now = NULL; + + tzset(); + crm_malloc0(now, sizeof(ha_time_t)); + crm_malloc0(now->has, sizeof(ha_has_time_t)); + crm_malloc0(now->offset, sizeof(ha_time_t)); + crm_malloc0(now->offset->has, sizeof(ha_has_time_t)); + if (set_to_now) { + tm_now = time(NULL); + now->tm_now = tm_now; + ha_set_timet_time(now, &tm_now); + } + return now; } void -free_ha_date(ha_time_t *a_date) +free_ha_date(ha_time_t * a_date) { - if(a_date == NULL) { - return; - } - free_ha_date(a_date->normalized); - free_ha_date(a_date->offset); - crm_free(a_date->has); - crm_free(a_date); + if (a_date == NULL) { + return; + } + free_ha_date(a_date->normalized); + free_ha_date(a_date->offset); + crm_free(a_date->has); + crm_free(a_date); } void -log_tm_date(int log_level, struct tm *some_tm) +log_tm_date(int log_level, struct tm *some_tm) { - const char *tzn; + const char *tzn; #if defined(HAVE_TM_ZONE) - tzn = some_tm->tm_zone; + tzn = some_tm->tm_zone; #elif defined(HAVE_TZNAME) - tzn = tzname[0]; + tzn = tzname[0]; #else - tzn = NULL; + tzn = NULL; #endif - do_crm_log(log_level, - "%.2d/%.2d/%.4d %.2d:%.2d:%.2d %s" - " (wday=%d, yday=%d, dst=%d, offset=%ld)", - some_tm->tm_mday, - some_tm->tm_mon, - 1900+some_tm->tm_year, - some_tm->tm_hour, - some_tm->tm_min, - some_tm->tm_sec, - tzn, - some_tm->tm_wday==0?7:some_tm->tm_wday, - 1+some_tm->tm_yday, - some_tm->tm_isdst, - GMTOFF(some_tm)); + do_crm_log(log_level, + "%.2d/%.2d/%.4d %.2d:%.2d:%.2d %s" + " (wday=%d, yday=%d, dst=%d, offset=%ld)", + some_tm->tm_mday, + some_tm->tm_mon, + 1900 + some_tm->tm_year, + some_tm->tm_hour, + some_tm->tm_min, + some_tm->tm_sec, + tzn, + some_tm->tm_wday == 0 ? 7 : some_tm->tm_wday, + 1 + some_tm->tm_yday, some_tm->tm_isdst, GMTOFF(some_tm)); } ha_time_t *the_epoch = NULL; #define update_seconds(date, field, multiplier) do { \ before = in_seconds; \ in_seconds += a_date->field; \ in_seconds *= multiplier; \ if(before > in_seconds) { \ crm_crit("Date wrap detected: %s", #field); \ return 0; \ } \ } while(0) - -unsigned long long date_in_seconds(ha_time_t *a_date) + +unsigned long long +date_in_seconds(ha_time_t * a_date) { unsigned long long before = 0; unsigned long long in_seconds = 0; - /* normalize_time(a_date); */ - update_seconds(a_date, years, 365); + + /* normalize_time(a_date); */ + update_seconds(a_date, years, 365); update_seconds(a_date, yeardays, 24); - update_seconds(a_date, hours, 60); - update_seconds(a_date, minutes, 60); - update_seconds(a_date, seconds, 1); + update_seconds(a_date, hours, 60); + update_seconds(a_date, minutes, 60); + update_seconds(a_date, seconds, 1); return in_seconds; } -unsigned long long date_in_seconds_since_epoch(ha_time_t *a_date) +unsigned long long +date_in_seconds_since_epoch(ha_time_t * a_date) { ha_time_t *since_epoch = NULL; unsigned long long in_seconds = 0; + normalize_time(a_date); - if(the_epoch == NULL) { - char *EPOCH = crm_strdup("1970-01-01"); - the_epoch = parse_date(&EPOCH); - normalize_time(the_epoch); - crm_free(EPOCH); + if (the_epoch == NULL) { + char *EPOCH = crm_strdup("1970-01-01"); + + the_epoch = parse_date(&EPOCH); + normalize_time(the_epoch); + crm_free(EPOCH); } since_epoch = subtract_time(a_date, the_epoch); in_seconds = date_in_seconds(since_epoch); free_ha_date(since_epoch); return in_seconds; } - diff --git a/lib/common/iso8601_fields.c b/lib/common/iso8601_fields.c index fe054fbe7f..53949e715d 100644 --- a/lib/common/iso8601_fields.c +++ b/lib/common/iso8601_fields.c @@ -1,404 +1,394 @@ /* * Copyright (C) 2005 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 */ /* * http://en.wikipedia.org/wiki/ISO_8601 as at 2005-08-01 * */ #include #include #include #include #include - #define do_add_field(atime, field, extra, limit, overflow) \ { \ crm_debug_6("Adding %d to %d (limit=%d)", \ extra, atime->field, limit); \ atime->field += extra; \ if(limit > 0) { \ while(limit < atime->field) { \ crm_debug_6("Overflowing: %d", atime->field); \ atime->field -= limit; \ overflow(atime, 1); \ } \ } \ atime->field = atime->field; \ crm_debug_6("Result: %d", atime->field); \ } #define do_add_time_field(atime, field, extra, limit, overflow) \ { \ crm_debug_6("Adding %d to %d (limit=%d)", \ extra, atime->field, limit); \ atime->field += extra; \ if(limit > 0) { \ while(limit <= atime->field) { \ crm_debug_6("Overflowing: %d", atime->field); \ atime->field -= limit; \ overflow(atime, 1); \ } \ } \ atime->field = atime->field; \ crm_debug_6("Result: %d", atime->field); \ } #define do_sub_field(atime, field, extra, limit, overflow) \ { \ crm_debug_6("Subtracting %d from %d (limit=%d)", \ extra, atime->field, limit); \ atime->field -= extra; \ while(atime->field <= 1) { \ crm_debug_6("Underflowing: %d", atime->field); \ atime->field += limit; \ overflow(atime, 1); \ } \ crm_debug_6("Result: %d", atime->field); \ } #define do_sub_time_field(atime, field, extra, limit, overflow) \ { \ crm_debug_6("Subtracting %d from %d (limit=%d)", \ extra, atime->field, limit); \ atime->field -= extra; \ while(atime->field < 0) { \ crm_debug_6("Underflowing: %d", atime->field); \ atime->field += limit; \ overflow(atime, 1); \ } \ crm_debug_6("Result: %d", atime->field); \ } void -add_seconds(ha_time_t *a_time, int extra) +add_seconds(ha_time_t * a_time, int extra) { - if(extra < 0) { - sub_seconds(a_time, -extra); - } else { - do_add_time_field(a_time, seconds, extra, 60, add_minutes); - } + if (extra < 0) { + sub_seconds(a_time, -extra); + } else { + do_add_time_field(a_time, seconds, extra, 60, add_minutes); + } } - void -add_minutes(ha_time_t *a_time, int extra) +add_minutes(ha_time_t * a_time, int extra) { - if(extra < 0) { - sub_minutes(a_time, -extra); - } else { - do_add_time_field(a_time, minutes, extra, 60, add_hours); - } + if (extra < 0) { + sub_minutes(a_time, -extra); + } else { + do_add_time_field(a_time, minutes, extra, 60, add_hours); + } } - void -add_hours(ha_time_t *a_time, int extra) +add_hours(ha_time_t * a_time, int extra) { - if(extra < 0) { - sub_hours(a_time, -extra); - } else { - do_add_time_field(a_time, hours, extra, 24, add_days); - } + if (extra < 0) { + sub_hours(a_time, -extra); + } else { + do_add_time_field(a_time, hours, extra, 24, add_days); + } } void -add_days(ha_time_t *a_time, int extra) +add_days(ha_time_t * a_time, int extra) { - if(a_time->has->days == FALSE) { - crm_debug_4("has->days == FALSE"); - return; - } - if(extra < 0) { - sub_days(a_time, -extra); - } else { - do_add_field(a_time, days, extra, - days_per_month(a_time->months, a_time->years), - add_months); - } - - convert_from_gregorian(a_time); + if (a_time->has->days == FALSE) { + crm_debug_4("has->days == FALSE"); + return; + } + if (extra < 0) { + sub_days(a_time, -extra); + } else { + do_add_field(a_time, days, extra, + days_per_month(a_time->months, a_time->years), add_months); + } + + convert_from_gregorian(a_time); } void -add_weekdays(ha_time_t *a_time, int extra) +add_weekdays(ha_time_t * a_time, int extra) { - if(a_time->has->weekdays == FALSE) { - crm_debug_4("has->weekdays == FALSE"); - return; - } - if(extra < 0) { - sub_weekdays(a_time, -extra); - } else { - do_add_field(a_time, weekdays, extra, 7, add_weeks); - } - - convert_from_weekdays(a_time); + if (a_time->has->weekdays == FALSE) { + crm_debug_4("has->weekdays == FALSE"); + return; + } + if (extra < 0) { + sub_weekdays(a_time, -extra); + } else { + do_add_field(a_time, weekdays, extra, 7, add_weeks); + } + + convert_from_weekdays(a_time); } void -add_yeardays(ha_time_t *a_time, int extra) +add_yeardays(ha_time_t * a_time, int extra) { - if(a_time->has->yeardays == FALSE) { - crm_debug_4("has->yeardays == FALSE"); - return; - } - if(extra < 0) { - sub_yeardays(a_time, -extra); - } else { - do_add_field(a_time, yeardays, extra, - (is_leap_year(a_time->years)?366:365), - add_ordinalyears); - } - - convert_from_ordinal(a_time); + if (a_time->has->yeardays == FALSE) { + crm_debug_4("has->yeardays == FALSE"); + return; + } + if (extra < 0) { + sub_yeardays(a_time, -extra); + } else { + do_add_field(a_time, yeardays, extra, + (is_leap_year(a_time->years) ? 366 : 365), add_ordinalyears); + } + + convert_from_ordinal(a_time); } void -add_weeks(ha_time_t *a_time, int extra) +add_weeks(ha_time_t * a_time, int extra) { - if(a_time->has->weeks== FALSE) { - crm_debug_4("has->weeks == FALSE"); - return; - } - if(extra < 0) { - sub_weeks(a_time, -extra); - } else { - do_add_field(a_time, weeks, extra, - weeks_in_year(a_time->years), add_weekyears); - } - - convert_from_weekdays(a_time); + if (a_time->has->weeks == FALSE) { + crm_debug_4("has->weeks == FALSE"); + return; + } + if (extra < 0) { + sub_weeks(a_time, -extra); + } else { + do_add_field(a_time, weeks, extra, weeks_in_year(a_time->years), add_weekyears); + } + + convert_from_weekdays(a_time); } void -add_months(ha_time_t *a_time, int extra) +add_months(ha_time_t * a_time, int extra) { - int max = 0; - if(a_time->has->months == FALSE) { - crm_debug_4("has->months == FALSE"); - return; - } - if(extra < 0) { - sub_months(a_time, -extra); - } else { - do_add_field(a_time, months, extra, 12, add_years); - } - - - max = days_per_month(a_time->months, a_time->years); - if(a_time->days > max) { - a_time->days = max; - } - convert_from_gregorian(a_time); + int max = 0; + + if (a_time->has->months == FALSE) { + crm_debug_4("has->months == FALSE"); + return; + } + if (extra < 0) { + sub_months(a_time, -extra); + } else { + do_add_field(a_time, months, extra, 12, add_years); + } + + max = days_per_month(a_time->months, a_time->years); + if (a_time->days > max) { + a_time->days = max; + } + convert_from_gregorian(a_time); } void -add_years(ha_time_t *a_time, int extra) +add_years(ha_time_t * a_time, int extra) { - if(a_time->has->years == FALSE) { - crm_debug_4("has->years == FALSE"); - return; - } - a_time->years += extra; - convert_from_gregorian(a_time); + if (a_time->has->years == FALSE) { + crm_debug_4("has->years == FALSE"); + return; + } + a_time->years += extra; + convert_from_gregorian(a_time); } void -add_ordinalyears(ha_time_t *a_time, int extra) +add_ordinalyears(ha_time_t * a_time, int extra) { - if(a_time->has->years == FALSE) { - crm_debug_4("has->years == FALSE"); - return; - } - a_time->years += extra; - convert_from_ordinal(a_time); + if (a_time->has->years == FALSE) { + crm_debug_4("has->years == FALSE"); + return; + } + a_time->years += extra; + convert_from_ordinal(a_time); } void -add_weekyears(ha_time_t *a_time, int extra) +add_weekyears(ha_time_t * a_time, int extra) { - if(a_time->has->weekyears == FALSE) { - crm_debug_4("has->weekyears == FALSE"); - return; - } - a_time->weekyears += extra; - convert_from_weekdays(a_time); + if (a_time->has->weekyears == FALSE) { + crm_debug_4("has->weekyears == FALSE"); + return; + } + a_time->weekyears += extra; + convert_from_weekdays(a_time); } void -sub_seconds(ha_time_t *a_time, int extra) +sub_seconds(ha_time_t * a_time, int extra) { - if(extra < 0) { - add_seconds(a_time, -extra); - } else { - do_sub_time_field(a_time, seconds, extra, 60, sub_minutes); - } + if (extra < 0) { + add_seconds(a_time, -extra); + } else { + do_sub_time_field(a_time, seconds, extra, 60, sub_minutes); + } } void -sub_minutes(ha_time_t *a_time, int extra) +sub_minutes(ha_time_t * a_time, int extra) { - if(extra < 0) { - add_minutes(a_time, -extra); - } else { - do_sub_time_field(a_time, minutes, extra, 60, sub_hours); - } + if (extra < 0) { + add_minutes(a_time, -extra); + } else { + do_sub_time_field(a_time, minutes, extra, 60, sub_hours); + } } void -sub_hours(ha_time_t *a_time, int extra) +sub_hours(ha_time_t * a_time, int extra) { - if(extra < 0) { - add_hours(a_time, -extra); - } else { - do_sub_time_field(a_time, hours, extra, 24, sub_days); - } + if (extra < 0) { + add_hours(a_time, -extra); + } else { + do_sub_time_field(a_time, hours, extra, 24, sub_days); + } } void -sub_days(ha_time_t *a_time, int extra) +sub_days(ha_time_t * a_time, int extra) { - if(a_time->has->days == FALSE) { - crm_debug_4("has->days == FALSE"); - return; - } - - crm_debug_5("Subtracting %d days from %.4d-%.2d-%.2d", - extra, a_time->years, a_time->months, a_time->days); - - if(extra < 0) { - add_days(a_time, -extra); - } else { - do_sub_field(a_time, days, extra, - days_per_month(a_time->months, a_time->years), - sub_months); - } - - convert_from_gregorian(a_time); + if (a_time->has->days == FALSE) { + crm_debug_4("has->days == FALSE"); + return; + } + + crm_debug_5("Subtracting %d days from %.4d-%.2d-%.2d", + extra, a_time->years, a_time->months, a_time->days); + + if (extra < 0) { + add_days(a_time, -extra); + } else { + do_sub_field(a_time, days, extra, + days_per_month(a_time->months, a_time->years), sub_months); + } + + convert_from_gregorian(a_time); } void -sub_weekdays(ha_time_t *a_time, int extra) +sub_weekdays(ha_time_t * a_time, int extra) { - if(a_time->has->weekdays == FALSE) { - crm_debug_4("has->weekdays == FALSE"); - return; - } + if (a_time->has->weekdays == FALSE) { + crm_debug_4("has->weekdays == FALSE"); + return; + } - crm_debug_5("Subtracting %d days from %.4d-%.2d-%.2d", - extra, a_time->years, a_time->months, a_time->days); - - if(extra < 0) { - add_weekdays(a_time, -extra); - } else { - do_sub_field(a_time, weekdays, extra, 7, sub_weeks); - } + crm_debug_5("Subtracting %d days from %.4d-%.2d-%.2d", + extra, a_time->years, a_time->months, a_time->days); + + if (extra < 0) { + add_weekdays(a_time, -extra); + } else { + do_sub_field(a_time, weekdays, extra, 7, sub_weeks); + } - convert_from_weekdays(a_time); + convert_from_weekdays(a_time); } void -sub_yeardays(ha_time_t *a_time, int extra) +sub_yeardays(ha_time_t * a_time, int extra) { - if(a_time->has->yeardays == FALSE) { - crm_debug_4("has->yeardays == FALSE"); - return; - } + if (a_time->has->yeardays == FALSE) { + crm_debug_4("has->yeardays == FALSE"); + return; + } - crm_debug_5("Subtracting %d days from %.4d-%.3d", - extra, a_time->years, a_time->yeardays); - - if(extra < 0) { - add_yeardays(a_time, -extra); - } else { - do_sub_field(a_time, yeardays, extra, - is_leap_year(a_time->years)?366:365, sub_ordinalyears); - } + crm_debug_5("Subtracting %d days from %.4d-%.3d", extra, a_time->years, a_time->yeardays); - convert_from_ordinal(a_time); -} + if (extra < 0) { + add_yeardays(a_time, -extra); + } else { + do_sub_field(a_time, yeardays, extra, + is_leap_year(a_time->years) ? 366 : 365, sub_ordinalyears); + } + convert_from_ordinal(a_time); +} void -sub_weeks(ha_time_t *a_time, int extra) +sub_weeks(ha_time_t * a_time, int extra) { - if(a_time->has->weeks == FALSE) { - crm_debug_4("has->weeks == FALSE"); - return; - } - if(extra < 0) { - add_weeks(a_time, -extra); - } else { - do_sub_field(a_time, weeks, extra, - weeks_in_year(a_time->years), sub_weekyears); - } - - convert_from_weekdays(a_time); + if (a_time->has->weeks == FALSE) { + crm_debug_4("has->weeks == FALSE"); + return; + } + if (extra < 0) { + add_weeks(a_time, -extra); + } else { + do_sub_field(a_time, weeks, extra, weeks_in_year(a_time->years), sub_weekyears); + } + + convert_from_weekdays(a_time); } void -sub_months(ha_time_t *a_time, int extra) +sub_months(ha_time_t * a_time, int extra) { - if(a_time->has->months == FALSE) { - crm_debug_4("has->months == FALSE"); - return; - } - if(extra < 0) { - add_months(a_time, -extra); - } else { - do_sub_field(a_time, months, extra, 12, sub_years); - } - convert_from_gregorian(a_time); + if (a_time->has->months == FALSE) { + crm_debug_4("has->months == FALSE"); + return; + } + if (extra < 0) { + add_months(a_time, -extra); + } else { + do_sub_field(a_time, months, extra, 12, sub_years); + } + convert_from_gregorian(a_time); } void -sub_years(ha_time_t *a_time, int extra) +sub_years(ha_time_t * a_time, int extra) { - if(a_time->has->years == FALSE) { - crm_debug_4("has->years == FALSE"); - return; - } - a_time->years -= extra; - convert_from_gregorian(a_time); + if (a_time->has->years == FALSE) { + crm_debug_4("has->years == FALSE"); + return; + } + a_time->years -= extra; + convert_from_gregorian(a_time); } void -sub_weekyears(ha_time_t *a_time, int extra) +sub_weekyears(ha_time_t * a_time, int extra) { - if(a_time->has->weekyears == FALSE) { - crm_debug_4("has->weekyears == FALSE"); - return; - } - a_time->weekyears -= extra; + if (a_time->has->weekyears == FALSE) { + crm_debug_4("has->weekyears == FALSE"); + return; + } + a_time->weekyears -= extra; - convert_from_weekdays(a_time); + convert_from_weekdays(a_time); } void -sub_ordinalyears(ha_time_t *a_time, int extra) +sub_ordinalyears(ha_time_t * a_time, int extra) { - if(a_time->has->years == FALSE) { - crm_debug_4("has->years == FALSE"); - return; - } - a_time->years -= extra; + if (a_time->has->years == FALSE) { + crm_debug_4("has->years == FALSE"); + return; + } + a_time->years -= extra; - convert_from_ordinal(a_time); + convert_from_ordinal(a_time); } diff --git a/lib/common/mainloop.c b/lib/common/mainloop.c index 877f57714e..2e8b1d0c70 100644 --- a/lib/common/mainloop.c +++ b/lib/common/mainloop.c @@ -1,241 +1,247 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include static gboolean -crm_trigger_prepare(GSource* source, gint *timeout) +crm_trigger_prepare(GSource * source, gint * timeout) { - crm_trigger_t *trig = (crm_trigger_t*)source; + crm_trigger_t *trig = (crm_trigger_t *) source; + return trig->trigger; } static gboolean -crm_trigger_check(GSource* source) +crm_trigger_check(GSource * source) { - crm_trigger_t *trig = (crm_trigger_t*)source; + crm_trigger_t *trig = (crm_trigger_t *) source; + return trig->trigger; } static gboolean -crm_trigger_dispatch(GSource *source, GSourceFunc callback, gpointer userdata) +crm_trigger_dispatch(GSource * source, GSourceFunc callback, gpointer userdata) { - crm_trigger_t *trig = (crm_trigger_t*)source; + crm_trigger_t *trig = (crm_trigger_t *) source; + trig->trigger = FALSE; - if(callback) { - return callback(trig->user_data); + if (callback) { + return callback(trig->user_data); } return TRUE; } static GSourceFuncs crm_trigger_funcs = { crm_trigger_prepare, crm_trigger_check, crm_trigger_dispatch, NULL }; static crm_trigger_t * -mainloop_setup_trigger( - GSource *source, int priority, gboolean (*dispatch)(gpointer user_data), gpointer userdata) +mainloop_setup_trigger(GSource * source, int priority, gboolean(*dispatch) (gpointer user_data), + gpointer userdata) { crm_trigger_t *trigger = NULL; - trigger = (crm_trigger_t*) source; + + trigger = (crm_trigger_t *) source; trigger->id = 0; trigger->trigger = FALSE; trigger->user_data = userdata; - if(dispatch) { - g_source_set_callback(source, dispatch, trigger, NULL); + if (dispatch) { + g_source_set_callback(source, dispatch, trigger, NULL); } - + g_source_set_priority(source, priority); g_source_set_can_recurse(source, FALSE); trigger->id = g_source_attach(source, NULL); return trigger; } crm_trigger_t * -mainloop_add_trigger( - int priority, gboolean (*dispatch)(gpointer user_data), gpointer userdata) +mainloop_add_trigger(int priority, gboolean(*dispatch) (gpointer user_data), gpointer userdata) { GSource *source = NULL; CRM_ASSERT(sizeof(crm_trigger_t) > sizeof(GSource)); source = g_source_new(&crm_trigger_funcs, sizeof(crm_trigger_t)); CRM_ASSERT(source != NULL); return mainloop_setup_trigger(source, priority, dispatch, userdata); } -void -mainloop_set_trigger(crm_trigger_t* source) +void +mainloop_set_trigger(crm_trigger_t * source) { source->trigger = TRUE; } -gboolean -mainloop_destroy_trigger(crm_trigger_t* source) +gboolean +mainloop_destroy_trigger(crm_trigger_t * source) { source->trigger = FALSE; if (source->id > 0) { - g_source_remove(source->id); + g_source_remove(source->id); } return TRUE; } -typedef struct signal_s -{ - crm_trigger_t trigger; /* must be first */ - void (*handler)(int sig); - int signal; +typedef struct signal_s { + crm_trigger_t trigger; /* must be first */ + void (*handler) (int sig); + int signal; } crm_signal_t; static crm_signal_t *crm_signals[NSIG]; static gboolean -crm_signal_dispatch(GSource *source, GSourceFunc callback, gpointer userdata) +crm_signal_dispatch(GSource * source, GSourceFunc callback, gpointer userdata) { - crm_signal_t *sig = (crm_signal_t*)source; - crm_info("Invoking handler for signal %d: %s", - sig->signal, strsignal(sig->signal)); + crm_signal_t *sig = (crm_signal_t *) source; + + crm_info("Invoking handler for signal %d: %s", sig->signal, strsignal(sig->signal)); sig->trigger.trigger = FALSE; - if(sig->handler) { - sig->handler(sig->signal); + if (sig->handler) { + sig->handler(sig->signal); } return TRUE; } -static void mainloop_signal_handler(int sig) +static void +mainloop_signal_handler(int sig) { - if(sig > 0 && sig < NSIG && crm_signals[sig] != NULL) { - mainloop_set_trigger((crm_trigger_t*)crm_signals[sig]); + if (sig > 0 && sig < NSIG && crm_signals[sig] != NULL) { + mainloop_set_trigger((crm_trigger_t *) crm_signals[sig]); } } static GSourceFuncs crm_signal_funcs = { crm_trigger_prepare, crm_trigger_check, crm_signal_dispatch, NULL }; -gboolean crm_signal(int sig, void (*dispatch)(int sig)) +gboolean +crm_signal(int sig, void (*dispatch) (int sig)) { sigset_t mask; struct sigaction sa; - struct sigaction old; + struct sigaction old; - if(sigemptyset(&mask) < 0) { - crm_perror(LOG_ERR, "Call to sigemptyset failed"); - return FALSE; + if (sigemptyset(&mask) < 0) { + crm_perror(LOG_ERR, "Call to sigemptyset failed"); + return FALSE; } memset(&sa, 0, sizeof(struct sigaction)); sa.sa_handler = dispatch; sa.sa_flags = SA_RESTART; sa.sa_mask = mask; - - if(sigaction(sig, &sa, &old) < 0) { - crm_perror(LOG_ERR, "Could not install signal handler for signal %d", sig); - return FALSE; + + if (sigaction(sig, &sa, &old) < 0) { + crm_perror(LOG_ERR, "Could not install signal handler for signal %d", sig); + return FALSE; } - + return TRUE; } gboolean -mainloop_add_signal(int sig, void (*dispatch)(int sig)) +mainloop_add_signal(int sig, void (*dispatch) (int sig)) { GSource *source = NULL; int priority = G_PRIORITY_HIGH - 1; - if(sig == SIGTERM) { - /* TERM is higher priority than other signals, - * signals are higher priority than other ipc. - * Yes, minus: smaller is "higher" - */ - priority--; + + if (sig == SIGTERM) { + /* TERM is higher priority than other signals, + * signals are higher priority than other ipc. + * Yes, minus: smaller is "higher" + */ + priority--; } - - if(sig >= NSIG || sig < 0) { - crm_err("Signal %d is out of range", sig); - return FALSE; - - } else if(crm_signals[sig] != NULL) { - crm_err("Signal handler for %d is already installed", sig); - return FALSE; + + if (sig >= NSIG || sig < 0) { + crm_err("Signal %d is out of range", sig); + return FALSE; + + } else if (crm_signals[sig] != NULL) { + crm_err("Signal handler for %d is already installed", sig); + return FALSE; } - + CRM_ASSERT(sizeof(crm_signal_t) > sizeof(GSource)); source = g_source_new(&crm_signal_funcs, sizeof(crm_signal_t)); - crm_signals[sig] = (crm_signal_t*)mainloop_setup_trigger(source, priority, NULL, NULL); + crm_signals[sig] = (crm_signal_t *) mainloop_setup_trigger(source, priority, NULL, NULL); CRM_ASSERT(crm_signals[sig] != NULL); crm_signals[sig]->handler = dispatch; crm_signals[sig]->signal = sig; - if(crm_signal(sig, mainloop_signal_handler) == FALSE) { - crm_signal_t *tmp = crm_signals[sig]; - crm_signals[sig] = NULL; + if (crm_signal(sig, mainloop_signal_handler) == FALSE) { + crm_signal_t *tmp = crm_signals[sig]; - mainloop_destroy_trigger((crm_trigger_t*)tmp); - return FALSE; + crm_signals[sig] = NULL; + + mainloop_destroy_trigger((crm_trigger_t *) tmp); + return FALSE; } - + return TRUE; } -gboolean +gboolean mainloop_destroy_signal(int sig) { crm_signal_t *tmp = NULL; - - if(sig >= NSIG || sig < 0) { - crm_err("Signal %d is out of range", sig); - return FALSE; - } else if(crm_signal(sig, NULL) == FALSE) { - crm_perror(LOG_ERR, "Could not uninstall signal handler for signal %d", sig); - return FALSE; + if (sig >= NSIG || sig < 0) { + crm_err("Signal %d is out of range", sig); + return FALSE; + + } else if (crm_signal(sig, NULL) == FALSE) { + crm_perror(LOG_ERR, "Could not uninstall signal handler for signal %d", sig); + return FALSE; - } else if(crm_signals[sig] == NULL) { - return TRUE; + } else if (crm_signals[sig] == NULL) { + return TRUE; } tmp = crm_signals[sig]; crm_signals[sig] = NULL; - mainloop_destroy_trigger((crm_trigger_t*)tmp); + mainloop_destroy_trigger((crm_trigger_t *) tmp); return TRUE; } diff --git a/lib/common/membership.c b/lib/common/membership.c index b97e6346eb..1b97366936 100644 --- a/lib/common/membership.c +++ b/lib/common/membership.c @@ -1,510 +1,532 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include -#include +#include #include #include -#include +#include #include GHashTable *crm_peer_id_cache = NULL; GHashTable *crm_peer_cache = NULL; unsigned long long crm_peer_seq = 0; gboolean crm_have_quorum = FALSE; -gboolean crm_is_member_active(const crm_node_t *node) +gboolean +crm_is_member_active(const crm_node_t * node) { - if(node && safe_str_eq(node->state, CRM_NODE_MEMBER)) { - return TRUE; + if (node && safe_str_eq(node->state, CRM_NODE_MEMBER)) { + return TRUE; } return FALSE; } -gboolean crm_is_full_member(const crm_node_t *node) +gboolean +crm_is_full_member(const crm_node_t * node) { - if(crm_is_member_active(node) && (node->processes & crm_proc_crmd)) { - return TRUE; + if (crm_is_member_active(node) && (node->processes & crm_proc_crmd)) { + return TRUE; } return FALSE; } -static gboolean crm_reap_dead_member( - gpointer key, gpointer value, gpointer user_data) +static gboolean +crm_reap_dead_member(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; crm_node_t *search = user_data; - if(search != NULL && node->id != search->id) { - return FALSE; + if (search != NULL && node->id != search->id) { + return FALSE; - } else if(crm_is_member_active(value) == FALSE) { - crm_notice("Removing %s/%u from the membership list", node->uname, node->id); - return TRUE; + } else if (crm_is_member_active(value) == FALSE) { + crm_notice("Removing %s/%u from the membership list", node->uname, node->id); + return TRUE; } return FALSE; } -guint reap_crm_member(uint32_t id) +guint +reap_crm_member(uint32_t id) { int matches = 0; crm_node_t *node = g_hash_table_lookup(crm_peer_id_cache, GUINT_TO_POINTER(id)); - if(node == NULL) { - crm_info("Peer %u is unknown", id); + if (node == NULL) { + crm_info("Peer %u is unknown", id); - } else if(crm_is_member_active(node)) { - crm_warn("Peer %u/%s is still active", id, node->uname); + } else if (crm_is_member_active(node)) { + crm_warn("Peer %u/%s is still active", id, node->uname); } else { - if(g_hash_table_remove(crm_peer_id_cache, GUINT_TO_POINTER(id))) { - crm_notice("Removed dead peer %u from the uuid cache", id); - - } else { - crm_warn("Peer %u/%s was not removed", id, node->uname); - } + if (g_hash_table_remove(crm_peer_id_cache, GUINT_TO_POINTER(id))) { + crm_notice("Removed dead peer %u from the uuid cache", id); - matches = g_hash_table_foreach_remove( - crm_peer_cache, crm_reap_dead_member, node); + } else { + crm_warn("Peer %u/%s was not removed", id, node->uname); + } - crm_notice("Removed %d dead peers with id=%u from the membership list", matches, id); + matches = g_hash_table_foreach_remove(crm_peer_cache, crm_reap_dead_member, node); + + crm_notice("Removed %d dead peers with id=%u from the membership list", matches, id); } - + return matches; } -static void crm_count_member( - gpointer key, gpointer value, gpointer user_data) +static void +crm_count_member(gpointer key, gpointer value, gpointer user_data) { guint *count = user_data; - if(crm_is_full_member(value)) { - *count = *count + 1; + + if (crm_is_full_member(value)) { + *count = *count + 1; } } -guint crm_active_members(void) +guint +crm_active_members(void) { guint count = 0; + g_hash_table_foreach(crm_peer_cache, crm_count_member, &count); return count; } -struct peer_count_s -{ - uint32_t peer; - guint count; +struct peer_count_s { + uint32_t peer; + guint count; }; -static void crm_count_peer( - gpointer key, gpointer value, gpointer user_data) +static void +crm_count_peer(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; struct peer_count_s *search = user_data; - if(crm_is_member_active(node) && (node->processes & search->peer)) { - search->count = search->count + 1; + + if (crm_is_member_active(node) && (node->processes & search->peer)) { + search->count = search->count + 1; } } -guint crm_active_peers(uint32_t peer) +guint +crm_active_peers(uint32_t peer) { struct peer_count_s search; + search.count = 0; search.peer = peer; g_hash_table_foreach(crm_peer_cache, crm_count_peer, &search); return search.count; } -void destroy_crm_node(gpointer data) +void +destroy_crm_node(gpointer data) { crm_node_t *node = data; + crm_debug_2("Destroying entry for node %u", node->id); crm_free(node->addr); crm_free(node->uname); crm_free(node->state); crm_free(node->uuid); crm_free(node); } -void crm_peer_init(void) +void +crm_peer_init(void) { static gboolean initialized = FALSE; - if(initialized) { - return; + + if (initialized) { + return; } initialized = TRUE; crm_peer_destroy(); - if(crm_peer_cache == NULL) { - crm_peer_cache = g_hash_table_new_full( - crm_str_hash, g_str_equal, NULL, destroy_crm_node); + if (crm_peer_cache == NULL) { + crm_peer_cache = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, destroy_crm_node); } - if(crm_peer_id_cache == NULL) { - crm_peer_id_cache = g_hash_table_new_full( - g_direct_hash, g_direct_equal, NULL, NULL); + if (crm_peer_id_cache == NULL) { + crm_peer_id_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); } } -void crm_peer_destroy(void) +void +crm_peer_destroy(void) { - if(crm_peer_cache != NULL) { - g_hash_table_destroy(crm_peer_cache); - crm_peer_cache = NULL; + if (crm_peer_cache != NULL) { + g_hash_table_destroy(crm_peer_cache); + crm_peer_cache = NULL; } - - if(crm_peer_id_cache != NULL) { - g_hash_table_destroy(crm_peer_id_cache); - crm_peer_id_cache = NULL; + + if (crm_peer_id_cache != NULL) { + g_hash_table_destroy(crm_peer_id_cache); + crm_peer_id_cache = NULL; } } -void (*crm_status_callback)(enum crm_status_type, crm_node_t*, const void*) = NULL; - -void crm_set_status_callback( - void (*dispatch)(enum crm_status_type,crm_node_t*, const void*)) +void (*crm_status_callback) (enum crm_status_type, crm_node_t *, const void *) = NULL; + +void +crm_set_status_callback(void (*dispatch) (enum crm_status_type, crm_node_t *, const void *)) { crm_status_callback = dispatch; } -static crm_node_t *crm_new_peer(unsigned int id, const char *uname) +static crm_node_t * +crm_new_peer(unsigned int id, const char *uname) { crm_node_t *node = NULL; + CRM_CHECK(uname != NULL || id > 0, return NULL); crm_debug("Creating entry for node %s/%u", uname, id); - + crm_malloc0(node, sizeof(crm_node_t)); node->state = crm_strdup("unknown"); - if(id > 0) { - node->id = id; - crm_info("Node %s now has id: %u", crm_str(uname), id); - g_hash_table_replace(crm_peer_id_cache, GUINT_TO_POINTER(node->id), node); + if (id > 0) { + node->id = id; + crm_info("Node %s now has id: %u", crm_str(uname), id); + g_hash_table_replace(crm_peer_id_cache, GUINT_TO_POINTER(node->id), node); } - - if(uname) { - node->uname = crm_strdup(uname); - CRM_ASSERT(node->uname != NULL); - crm_info("Node %u is now known as %s", id, node->uname); - g_hash_table_replace(crm_peer_cache, node->uname, node); - if(is_openais_cluster()) { - node->uuid = crm_strdup(node->uname); - } + if (uname) { + node->uname = crm_strdup(uname); + CRM_ASSERT(node->uname != NULL); + crm_info("Node %u is now known as %s", id, node->uname); + g_hash_table_replace(crm_peer_cache, node->uname, node); + + if (is_openais_cluster()) { + node->uuid = crm_strdup(node->uname); + } - if(crm_status_callback) { - crm_status_callback(crm_status_uname, node, NULL); - } + if (crm_status_callback) { + crm_status_callback(crm_status_uname, node, NULL); + } } - + return node; } -crm_node_t *crm_get_peer(unsigned int id, const char *uname) +crm_node_t * +crm_get_peer(unsigned int id, const char *uname) { crm_node_t *node = NULL; - if(uname != NULL) { - node = g_hash_table_lookup(crm_peer_cache, uname); - } - - if(node == NULL && id > 0) { - node = g_hash_table_lookup(crm_peer_id_cache, GUINT_TO_POINTER(id)); - if(node && node->uname && uname) { - crm_crit("Node %s and %s share the same cluster node id '%u'!", - node->uname, uname, id); - - /* NOTE: Calling crm_new_peer() means the entry in - * crm_peer_id_cache will point to the new entity - */ - - /* TODO: Replace the old uname instead? */ - node = crm_new_peer(id, uname); - CRM_ASSERT(node->uname != NULL); - } - } - - if(node && uname && node->uname == NULL) { - node->uname = crm_strdup(uname); - crm_info("Node %u is now known as %s", id, uname); - g_hash_table_insert(crm_peer_cache, node->uname, node); - if(crm_status_callback) { - crm_status_callback(crm_status_uname, node, NULL); - } - - } - - if(node && id > 0 && id != node->id) { - g_hash_table_remove(crm_peer_id_cache, GUINT_TO_POINTER(node->id)); - g_hash_table_insert(crm_peer_id_cache, GUINT_TO_POINTER(id), node); - node->id = id; - crm_info("Node %s now has id: %u", crm_str(uname), id); - } - + + if (uname != NULL) { + node = g_hash_table_lookup(crm_peer_cache, uname); + } + + if (node == NULL && id > 0) { + node = g_hash_table_lookup(crm_peer_id_cache, GUINT_TO_POINTER(id)); + if (node && node->uname && uname) { + crm_crit("Node %s and %s share the same cluster node id '%u'!", node->uname, uname, id); + + /* NOTE: Calling crm_new_peer() means the entry in + * crm_peer_id_cache will point to the new entity + */ + + /* TODO: Replace the old uname instead? */ + node = crm_new_peer(id, uname); + CRM_ASSERT(node->uname != NULL); + } + } + + if (node && uname && node->uname == NULL) { + node->uname = crm_strdup(uname); + crm_info("Node %u is now known as %s", id, uname); + g_hash_table_insert(crm_peer_cache, node->uname, node); + if (crm_status_callback) { + crm_status_callback(crm_status_uname, node, NULL); + } + + } + + if (node && id > 0 && id != node->id) { + g_hash_table_remove(crm_peer_id_cache, GUINT_TO_POINTER(node->id)); + g_hash_table_insert(crm_peer_id_cache, GUINT_TO_POINTER(id), node); + node->id = id; + crm_info("Node %s now has id: %u", crm_str(uname), id); + } + return node; } -crm_node_t *crm_update_peer( - unsigned int id, uint64_t born, uint64_t seen, int32_t votes, uint32_t children, - const char *uuid, const char *uname, const char *addr, const char *state) +crm_node_t * +crm_update_peer(unsigned int id, uint64_t born, uint64_t seen, int32_t votes, uint32_t children, + const char *uuid, const char *uname, const char *addr, const char *state) { gboolean state_changed = FALSE; gboolean addr_changed = FALSE; gboolean procs_changed = FALSE; gboolean votes_changed = FALSE; - + crm_node_t *node = NULL; + CRM_CHECK(uname != NULL || id > 0, return NULL); CRM_ASSERT(crm_peer_cache != NULL); CRM_ASSERT(crm_peer_id_cache != NULL); node = crm_get_peer(id, uname); - if(node == NULL) { - node = crm_new_peer(id, uname); + if (node == NULL) { + node = crm_new_peer(id, uname); - /* do it now so we don't get '(new)' everywhere */ - node->votes = votes; - node->processes = children; - if(addr) { - node->addr = crm_strdup(addr); - } + /* do it now so we don't get '(new)' everywhere */ + node->votes = votes; + node->processes = children; + if (addr) { + node->addr = crm_strdup(addr); + } } - if(votes > 0 && node->votes != votes) { - votes_changed = TRUE; - node->votes = votes; + if (votes > 0 && node->votes != votes) { + votes_changed = TRUE; + node->votes = votes; } - - if(node->uuid == NULL) { - if(uuid != NULL) { - node->uuid = crm_strdup(uuid); - - } else if(node->uname != NULL && is_openais_cluster()) { - node->uuid = crm_strdup(node->uname); - } + + if (node->uuid == NULL) { + if (uuid != NULL) { + node->uuid = crm_strdup(uuid); + + } else if (node->uname != NULL && is_openais_cluster()) { + node->uuid = crm_strdup(node->uname); + } } - if(children > 0 && children != node->processes) { - uint32_t last = node->processes; - node->processes = children; - procs_changed = TRUE; + if (children > 0 && children != node->processes) { + uint32_t last = node->processes; - if(crm_status_callback) { - crm_status_callback(crm_status_processes, node, &last); - } + node->processes = children; + procs_changed = TRUE; + + if (crm_status_callback) { + crm_status_callback(crm_status_processes, node, &last); + } } - if(born != 0) { - node->born = born; + if (born != 0) { + node->born = born; } - if(state != NULL && safe_str_neq(node->state, state)) { - char *last = node->state; - node->state = crm_strdup(state); - state_changed = TRUE; + if (state != NULL && safe_str_neq(node->state, state)) { + char *last = node->state; + + node->state = crm_strdup(state); + state_changed = TRUE; - if(crm_status_callback) { - crm_status_callback(crm_status_nstate, node, last); - } - crm_free(last); + if (crm_status_callback) { + crm_status_callback(crm_status_nstate, node, last); + } + crm_free(last); } - if(seen != 0 && crm_is_member_active(node)) { - node->last_seen = seen; + if (seen != 0 && crm_is_member_active(node)) { + node->last_seen = seen; } - - if(addr != NULL) { - if(node->addr == NULL || crm_str_eq(node->addr, addr, FALSE) == FALSE) { - addr_changed = TRUE; - crm_free(node->addr); - node->addr = crm_strdup(addr); - } + + if (addr != NULL) { + if (node->addr == NULL || crm_str_eq(node->addr, addr, FALSE) == FALSE) { + addr_changed = TRUE; + crm_free(node->addr); + node->addr = crm_strdup(addr); + } } - if(state_changed || addr_changed || votes_changed || procs_changed) { - crm_info("Node %s: id=%u state=%s%s addr=%s%s votes=%d%s born="U64T" seen="U64T" proc=%.32x%s", - node->uname, node->id, - node->state, state_changed?" (new)":"", - node->addr, addr_changed?" (new)":"", - node->votes, votes_changed?" (new)":"", - node->born, node->last_seen, - node->processes, procs_changed?" (new)":"" - ); + if (state_changed || addr_changed || votes_changed || procs_changed) { + crm_info("Node %s: id=%u state=%s%s addr=%s%s votes=%d%s born=" U64T " seen=" U64T + " proc=%.32x%s", node->uname, node->id, node->state, state_changed ? " (new)" : "", + node->addr, addr_changed ? " (new)" : "", node->votes, + votes_changed ? " (new)" : "", node->born, node->last_seen, node->processes, + procs_changed ? " (new)" : ""); } - + return node; } -crm_node_t *crm_update_ais_node(xmlNode *member, long long seq) +crm_node_t * +crm_update_ais_node(xmlNode * member, long long seq) { const char *id_s = crm_element_value(member, "id"); const char *addr = crm_element_value(member, "addr"); const char *uname = crm_element_value(member, "uname"); const char *state = crm_element_value(member, "state"); const char *born_s = crm_element_value(member, "born"); const char *seen_s = crm_element_value(member, "seen"); const char *votes_s = crm_element_value(member, "votes"); const char *procs_s = crm_element_value(member, "processes"); int votes = crm_int_helper(votes_s, NULL); unsigned int id = crm_int_helper(id_s, NULL); unsigned int procs = crm_int_helper(procs_s, NULL); /* TODO: These values will contain garbage if version < 0.7.1 */ uint64_t born = crm_int_helper(born_s, NULL); uint64_t seen = crm_int_helper(seen_s, NULL); return crm_update_peer(id, born, seen, votes, procs, uname, uname, addr, state); } -crm_node_t *crm_update_cman_node(xmlNode *member, long long seq) +crm_node_t * +crm_update_cman_node(xmlNode * member, long long seq) { const char *id_s = crm_element_value(member, "id"); const char *uname = crm_element_value(member, "uname"); const char *procs_s = crm_element_value(member, "processes"); unsigned int id = crm_int_helper(id_s, NULL); unsigned int procs = crm_int_helper(procs_s, NULL); crm_info("Updating peer processes for %s", crm_str(uname)); return crm_update_peer(id, 0, 0, 0, procs, uname, uname, NULL, NULL); } #if SUPPORT_HEARTBEAT -crm_node_t *crm_update_ccm_node( - const oc_ev_membership_t *oc, int offset, const char *state, uint64_t seq) +crm_node_t * +crm_update_ccm_node(const oc_ev_membership_t * oc, int offset, const char *state, uint64_t seq) { crm_node_t *node = NULL; const char *uuid = NULL; + CRM_CHECK(oc->m_array[offset].node_uname != NULL, return NULL); uuid = get_uuid(oc->m_array[offset].node_uname); node = crm_update_peer(oc->m_array[offset].node_id, - oc->m_array[offset].node_born_on, seq, -1, 0, - uuid, oc->m_array[offset].node_uname, NULL, state); + oc->m_array[offset].node_born_on, seq, -1, 0, + uuid, oc->m_array[offset].node_uname, NULL, state); - if(safe_str_eq(CRM_NODE_ACTIVE, state)) { - /* Heartbeat doesn't send status notifications for nodes that were already part of the cluster */ - crm_update_peer_proc( - oc->m_array[offset].node_uname, crm_proc_ais, ONLINESTATUS); + if (safe_str_eq(CRM_NODE_ACTIVE, state)) { + /* Heartbeat doesn't send status notifications for nodes that were already part of the cluster */ + crm_update_peer_proc(oc->m_array[offset].node_uname, crm_proc_ais, ONLINESTATUS); - /* Nor does it send status notifications for processes that were already active */ - crm_update_peer_proc( - oc->m_array[offset].node_uname, crm_proc_crmd, ONLINESTATUS); + /* Nor does it send status notifications for processes that were already active */ + crm_update_peer_proc(oc->m_array[offset].node_uname, crm_proc_crmd, ONLINESTATUS); } return node; } #endif -void crm_update_peer_proc(const char *uname, uint32_t flag, const char *status) +void +crm_update_peer_proc(const char *uname, uint32_t flag, const char *status) { uint32_t last = 0; crm_node_t *node = NULL; gboolean changed = FALSE; + CRM_ASSERT(crm_peer_cache != NULL); CRM_CHECK(uname != NULL, return); - node = g_hash_table_lookup(crm_peer_cache, uname); - CRM_CHECK(node != NULL, - crm_err("Could not set %s.%s to %s", uname, peer2text(flag), status); - return); + node = g_hash_table_lookup(crm_peer_cache, uname); + CRM_CHECK(node != NULL, crm_err("Could not set %s.%s to %s", uname, peer2text(flag), status); + return); last = node->processes; - if(safe_str_eq(status, ONLINESTATUS)) { - if((node->processes & flag) == 0) { - set_bit_inplace(node->processes, flag); - changed = TRUE; - } - - } else if(node->processes & flag) { - clear_bit_inplace(node->processes, flag); - changed = TRUE; - } - - if(changed) { - crm_info("%s.%s is now %s", uname, peer2text(flag), status); - if(crm_status_callback) { - crm_status_callback(crm_status_processes, node, &last); - } + if (safe_str_eq(status, ONLINESTATUS)) { + if ((node->processes & flag) == 0) { + set_bit_inplace(node->processes, flag); + changed = TRUE; + } + + } else if (node->processes & flag) { + clear_bit_inplace(node->processes, flag); + changed = TRUE; + } + + if (changed) { + crm_info("%s.%s is now %s", uname, peer2text(flag), status); + if (crm_status_callback) { + crm_status_callback(crm_status_processes, node, &last); + } } } -static int crm_terminate_member_common(int nodeid, const char *uname, IPC_Channel *cluster, int *connection) +static int +crm_terminate_member_common(int nodeid, const char *uname, IPC_Channel * cluster, int *connection) { crm_node_t *node = NULL; gboolean success = FALSE; const char *reason = "Cluster connection failed"; node = crm_get_peer(nodeid, uname); - if(cluster == NULL) { - reason = "No connection to the cluster"; + if (cluster == NULL) { + reason = "No connection to the cluster"; + + } else if (node == NULL) { + if (uname) { + crm_err("Nothing known about node uname=%s", uname); - } else if(node == NULL) { - if(uname) { - crm_err("Nothing known about node uname=%s", uname); - - } else if(nodeid > 0) { - crm_err("Nothing known about node id=%d", nodeid); + } else if (nodeid > 0) { + crm_err("Nothing known about node id=%d", nodeid); - } else { - crm_err("A node id or uname is required, got %d/%p", nodeid, uname); - } - return -1; + } else { + crm_err("A node id or uname is required, got %d/%p", nodeid, uname); + } + return -1; } else { - time_t now = time(NULL); - char *now_s = crm_itoa(now); - if(cluster) { - success = attrd_update(cluster, 'U', node->uname, "terminate", now_s, XML_CIB_TAG_STATUS, NULL, NULL); - } else { - success = attrd_update_no_mainloop(connection, 'U', node->uname, "terminate", now_s, XML_CIB_TAG_STATUS, NULL, NULL); - } - crm_free(now_s); + time_t now = time(NULL); + char *now_s = crm_itoa(now); + + if (cluster) { + success = + attrd_update(cluster, 'U', node->uname, "terminate", now_s, XML_CIB_TAG_STATUS, + NULL, NULL); + } else { + success = + attrd_update_no_mainloop(connection, 'U', node->uname, "terminate", now_s, + XML_CIB_TAG_STATUS, NULL, NULL); + } + crm_free(now_s); } - - if(success) { - crm_info("Requested that node %d/%s be terminated", nodeid, node->uname); - return 1; + + if (success) { + crm_info("Requested that node %d/%s be terminated", nodeid, node->uname); + return 1; } crm_err("Could not terminate node %d/%s: %s", nodeid, node->uname, reason); return 0; } -int crm_terminate_member(int nodeid, const char *uname, IPC_Channel *cluster) +int +crm_terminate_member(int nodeid, const char *uname, IPC_Channel * cluster) { - if(cluster != NULL) { - return crm_terminate_member_common(nodeid, uname, cluster, NULL); + if (cluster != NULL) { + return crm_terminate_member_common(nodeid, uname, cluster, NULL); } crm_err("Could not terminate node %d/%s: No cluster connection", nodeid, uname); return 0; } -int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection) +int +crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection) { return crm_terminate_member_common(nodeid, uname, NULL, connection); } - diff --git a/lib/common/remote.c b/lib/common/remote.c index 8a073c2f56..5faf5889bc 100644 --- a/lib/common/remote.c +++ b/lib/common/remote.c @@ -1,336 +1,340 @@ /* * Copyright (c) 2008 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #ifdef HAVE_GNUTLS_GNUTLS_H # undef KEYFILE # include #endif #ifdef HAVE_GNUTLS_GNUTLS_H const int tls_kx_order[] = { - GNUTLS_KX_ANON_DH, - GNUTLS_KX_DHE_RSA, - GNUTLS_KX_DHE_DSS, - GNUTLS_KX_RSA, - 0 + GNUTLS_KX_ANON_DH, + GNUTLS_KX_DHE_RSA, + GNUTLS_KX_DHE_DSS, + GNUTLS_KX_RSA, + 0 }; + gnutls_anon_client_credentials anon_cred_c; gnutls_anon_server_credentials anon_cred_s; -static char *cib_send_tls(gnutls_session *session, xmlNode *msg); -static char *cib_recv_tls(gnutls_session *session); +static char *cib_send_tls(gnutls_session * session, xmlNode * msg); +static char *cib_recv_tls(gnutls_session * session); #endif char *cib_recv_plaintext(int sock); -char *cib_send_plaintext(int sock, xmlNode *msg); +char *cib_send_plaintext(int sock, xmlNode * msg); #ifdef HAVE_GNUTLS_GNUTLS_H gnutls_session *create_tls_session(int csock, int type); gnutls_session * -create_tls_session(int csock, int type /* GNUTLS_SERVER, GNUTLS_CLIENT */) +create_tls_session(int csock, int type /* GNUTLS_SERVER, GNUTLS_CLIENT */ ) { - int rc = 0; - gnutls_session *session = gnutls_malloc(sizeof(gnutls_session)); + int rc = 0; + gnutls_session *session = gnutls_malloc(sizeof(gnutls_session)); - gnutls_init(session, type); -#ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT + gnutls_init(session, type); +# ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT /* http://www.manpagez.com/info/gnutls/gnutls-2.10.4/gnutls_81.php#Echo-Server-with-anonymous-authentication */ - gnutls_priority_set_direct (*session, "NORMAL:+ANON-DH", NULL); + gnutls_priority_set_direct(*session, "NORMAL:+ANON-DH", NULL); /* gnutls_priority_set_direct (*session, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); */ -#else - gnutls_set_default_priority(*session); - gnutls_kx_set_priority (*session, tls_kx_order); -#endif - gnutls_transport_set_ptr(*session, - (gnutls_transport_ptr) GINT_TO_POINTER(csock)); - switch(type) { - case GNUTLS_SERVER: - gnutls_credentials_set(*session, GNUTLS_CRD_ANON, anon_cred_s); - break; - case GNUTLS_CLIENT: - gnutls_credentials_set(*session, GNUTLS_CRD_ANON, anon_cred_c); - break; - } - - do { - rc = gnutls_handshake (*session); - } while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN); - - if (rc < 0) { - crm_err("Handshake failed: %s", gnutls_strerror(rc)); - gnutls_deinit(*session); - gnutls_free(session); - return NULL; - } - return session; +# else + gnutls_set_default_priority(*session); + gnutls_kx_set_priority(*session, tls_kx_order); +# endif + gnutls_transport_set_ptr(*session, (gnutls_transport_ptr) GINT_TO_POINTER(csock)); + switch (type) { + case GNUTLS_SERVER: + gnutls_credentials_set(*session, GNUTLS_CRD_ANON, anon_cred_s); + break; + case GNUTLS_CLIENT: + gnutls_credentials_set(*session, GNUTLS_CRD_ANON, anon_cred_c); + break; + } + + do { + rc = gnutls_handshake(*session); + } while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN); + + if (rc < 0) { + crm_err("Handshake failed: %s", gnutls_strerror(rc)); + gnutls_deinit(*session); + gnutls_free(session); + return NULL; + } + return session; } -static char* -cib_send_tls(gnutls_session *session, xmlNode *msg) +static char * +cib_send_tls(gnutls_session * session, xmlNode * msg) { - char *xml_text = NULL; -#if 0 - const char *name = crm_element_name(msg); - if(safe_str_neq(name, "cib_command")) { - xmlNodeSetName(msg, "cib_result"); - } -#endif - xml_text = dump_xml_unformatted(msg); - if(xml_text != NULL) { - char *unsent = xml_text; - int len = strlen(xml_text); - int rc = 0; - - len++; /* null char */ - crm_debug_3("Message size: %d", len); - - while(TRUE) { - rc = gnutls_record_send (*session, unsent, len); - crm_debug("Sent %d bytes", rc); - - if(rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN) { - crm_debug("Retry"); - - } else if(rc < 0) { - crm_debug("Connection terminated"); - break; - - } else if(rc < len) { - crm_debug("Only sent %d of %d bytes", rc, len); - len -= rc; - unsent += rc; - } else { - break; - } - } - - } - crm_free(xml_text); - return NULL; - + char *xml_text = NULL; + +# if 0 + const char *name = crm_element_name(msg); + + if (safe_str_neq(name, "cib_command")) { + xmlNodeSetName(msg, "cib_result"); + } +# endif + xml_text = dump_xml_unformatted(msg); + if (xml_text != NULL) { + char *unsent = xml_text; + int len = strlen(xml_text); + int rc = 0; + + len++; /* null char */ + crm_debug_3("Message size: %d", len); + + while (TRUE) { + rc = gnutls_record_send(*session, unsent, len); + crm_debug("Sent %d bytes", rc); + + if (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN) { + crm_debug("Retry"); + + } else if (rc < 0) { + crm_debug("Connection terminated"); + break; + + } else if (rc < len) { + crm_debug("Only sent %d of %d bytes", rc, len); + len -= rc; + unsent += rc; + } else { + break; + } + } + + } + crm_free(xml_text); + return NULL; + } -static char* -cib_recv_tls(gnutls_session *session) +static char * +cib_recv_tls(gnutls_session * session) { - char* buf = NULL; - - int rc = 0; - int len = 0; - int chunk_size = 1024; - - if (session == NULL) { - return NULL; - } - - crm_malloc0(buf, chunk_size); - - while(TRUE) { - errno = 0; - rc = gnutls_record_recv(*session, buf+len, chunk_size); - crm_debug_2("Got %d more bytes. errno=%d", rc, errno); - - if(rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN) { - crm_debug_2("Retry"); - - } else if(rc == GNUTLS_E_UNEXPECTED_PACKET_LENGTH) { - crm_trace("Session disconnected"); - goto bail; - - } else if(rc < 0) { - crm_err("Error receiving message: %s (%d)", gnutls_strerror(rc), rc); - goto bail; - - } else if(rc == chunk_size) { - len += rc; - chunk_size *= 2; - crm_realloc(buf, len + chunk_size); - crm_debug_2("Retry with %d more bytes", (int)chunk_size); - CRM_ASSERT(buf != NULL); - - } else if(buf[len+rc-1] != 0) { - crm_debug_2("Last char is %d '%c'", buf[len+rc-1], buf[len+rc-1]); - crm_debug_2("Retry with %d more bytes", (int)chunk_size); - len += rc; - crm_realloc(buf, len + chunk_size); - CRM_ASSERT(buf != NULL); - - } else { - crm_debug_2("Got %d more bytes", (int)rc); - return buf; - } - } + char *buf = NULL; + + int rc = 0; + int len = 0; + int chunk_size = 1024; + + if (session == NULL) { + return NULL; + } + + crm_malloc0(buf, chunk_size); + + while (TRUE) { + errno = 0; + rc = gnutls_record_recv(*session, buf + len, chunk_size); + crm_debug_2("Got %d more bytes. errno=%d", rc, errno); + + if (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN) { + crm_debug_2("Retry"); + + } else if (rc == GNUTLS_E_UNEXPECTED_PACKET_LENGTH) { + crm_trace("Session disconnected"); + goto bail; + + } else if (rc < 0) { + crm_err("Error receiving message: %s (%d)", gnutls_strerror(rc), rc); + goto bail; + + } else if (rc == chunk_size) { + len += rc; + chunk_size *= 2; + crm_realloc(buf, len + chunk_size); + crm_debug_2("Retry with %d more bytes", (int)chunk_size); + CRM_ASSERT(buf != NULL); + + } else if (buf[len + rc - 1] != 0) { + crm_debug_2("Last char is %d '%c'", buf[len + rc - 1], buf[len + rc - 1]); + crm_debug_2("Retry with %d more bytes", (int)chunk_size); + len += rc; + crm_realloc(buf, len + chunk_size); + CRM_ASSERT(buf != NULL); + + } else { + crm_debug_2("Got %d more bytes", (int)rc); + return buf; + } + } bail: - crm_free(buf); - return NULL; - + crm_free(buf); + return NULL; + } #endif -char* -cib_send_plaintext(int sock, xmlNode *msg) +char * +cib_send_plaintext(int sock, xmlNode * msg) { - char *xml_text = dump_xml_unformatted(msg); - if(xml_text != NULL) { - int rc = 0; - char *unsent = xml_text; - int len = strlen(xml_text); - len++; /* null char */ - crm_debug_3("Message on socket %d: size=%d", sock, len); - retry: - rc = write (sock, unsent, len); - if(rc < 0) { - switch(errno) { - case EINTR: - case EAGAIN: - crm_debug_2("Retry"); - goto retry; - default: - crm_perror(LOG_ERR, "Could only write %d of the remaining %d bytes", rc, len); - break; - } - - } else if(rc < len) { - crm_debug_2("Only sent %d of %d remaining bytes", rc, len); - len -= rc; - unsent += rc; - goto retry; - - } else { - crm_debug_2("Sent %d bytes: %.100s", rc, xml_text); - } - } - crm_free(xml_text); - return NULL; - + char *xml_text = dump_xml_unformatted(msg); + + if (xml_text != NULL) { + int rc = 0; + char *unsent = xml_text; + int len = strlen(xml_text); + + len++; /* null char */ + crm_debug_3("Message on socket %d: size=%d", sock, len); + retry: + rc = write(sock, unsent, len); + if (rc < 0) { + switch (errno) { + case EINTR: + case EAGAIN: + crm_debug_2("Retry"); + goto retry; + default: + crm_perror(LOG_ERR, "Could only write %d of the remaining %d bytes", rc, len); + break; + } + + } else if (rc < len) { + crm_debug_2("Only sent %d of %d remaining bytes", rc, len); + len -= rc; + unsent += rc; + goto retry; + + } else { + crm_debug_2("Sent %d bytes: %.100s", rc, xml_text); + } + } + crm_free(xml_text); + return NULL; + } -char* +char * cib_recv_plaintext(int sock) { - char* buf = NULL; - - ssize_t rc = 0; - ssize_t len = 0; - ssize_t chunk_size = 512; - - crm_malloc0(buf, chunk_size); - - while(1) { - errno = 0; - rc = read(sock, buf+len, chunk_size); - crm_debug_2("Got %d more bytes. errno=%d", (int)rc, errno); - - if(errno == EINTR || errno == EAGAIN) { - crm_debug_2("Retry: %d", (int)rc); - if(rc > 0) { - len += rc; - crm_realloc(buf, len + chunk_size); - CRM_ASSERT(buf != NULL); - } - - } else if(rc < 0) { - crm_perror(LOG_ERR,"Error receiving message: %d", (int)rc); - goto bail; - - } else if(rc == chunk_size) { - len += rc; - chunk_size *= 2; - crm_realloc(buf, len + chunk_size); - crm_debug_2("Retry with %d more bytes", (int)chunk_size); - CRM_ASSERT(buf != NULL); - - } else if(buf[len+rc-1] != 0) { - crm_debug_2("Last char is %d '%c'", buf[len+rc-1], buf[len+rc-1]); - crm_debug_2("Retry with %d more bytes", (int)chunk_size); - len += rc; - crm_realloc(buf, len + chunk_size); - CRM_ASSERT(buf != NULL); - - } else { - return buf; - } - } + char *buf = NULL; + + ssize_t rc = 0; + ssize_t len = 0; + ssize_t chunk_size = 512; + + crm_malloc0(buf, chunk_size); + + while (1) { + errno = 0; + rc = read(sock, buf + len, chunk_size); + crm_debug_2("Got %d more bytes. errno=%d", (int)rc, errno); + + if (errno == EINTR || errno == EAGAIN) { + crm_debug_2("Retry: %d", (int)rc); + if (rc > 0) { + len += rc; + crm_realloc(buf, len + chunk_size); + CRM_ASSERT(buf != NULL); + } + + } else if (rc < 0) { + crm_perror(LOG_ERR, "Error receiving message: %d", (int)rc); + goto bail; + + } else if (rc == chunk_size) { + len += rc; + chunk_size *= 2; + crm_realloc(buf, len + chunk_size); + crm_debug_2("Retry with %d more bytes", (int)chunk_size); + CRM_ASSERT(buf != NULL); + + } else if (buf[len + rc - 1] != 0) { + crm_debug_2("Last char is %d '%c'", buf[len + rc - 1], buf[len + rc - 1]); + crm_debug_2("Retry with %d more bytes", (int)chunk_size); + len += rc; + crm_realloc(buf, len + chunk_size); + CRM_ASSERT(buf != NULL); + + } else { + return buf; + } + } bail: - crm_free(buf); - return NULL; - + crm_free(buf); + return NULL; + } void -cib_send_remote_msg(void *session, xmlNode *msg, gboolean encrypted) +cib_send_remote_msg(void *session, xmlNode * msg, gboolean encrypted) { - if(encrypted) { + if (encrypted) { #ifdef HAVE_GNUTLS_GNUTLS_H - cib_send_tls(session, msg); + cib_send_tls(session, msg); #else - CRM_ASSERT(encrypted == FALSE); + CRM_ASSERT(encrypted == FALSE); #endif } else { - cib_send_plaintext(GPOINTER_TO_INT(session), msg); + cib_send_plaintext(GPOINTER_TO_INT(session), msg); } } -xmlNode* +xmlNode * cib_recv_remote_msg(void *session, gboolean encrypted) { char *reply = NULL; xmlNode *xml = NULL; - if(encrypted) { + + if (encrypted) { #ifdef HAVE_GNUTLS_GNUTLS_H - reply = cib_recv_tls(session); + reply = cib_recv_tls(session); #else - CRM_ASSERT(encrypted == FALSE); + CRM_ASSERT(encrypted == FALSE); #endif } else { - reply = cib_recv_plaintext(GPOINTER_TO_INT(session)); + reply = cib_recv_plaintext(GPOINTER_TO_INT(session)); } - if(reply == NULL || strlen(reply) == 0) { - crm_trace("Empty reply"); + if (reply == NULL || strlen(reply) == 0) { + crm_trace("Empty reply"); } else { - xml = string2xml(reply); - if(xml == NULL) { - crm_err("Couldn't parse: '%.120s'", reply); - } + xml = string2xml(reply); + if (xml == NULL) { + crm_err("Couldn't parse: '%.120s'", reply); + } } - + crm_free(reply); return xml; } - diff --git a/lib/common/utils.c b/lib/common/utils.c index 740563b521..196f1272ca 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -1,2675 +1,2710 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_HB_CONFIG_H -#include /* for HB_COREDIR */ +# include /* for HB_COREDIR */ #endif #if HAVE_GLUE_CONFIG_H -#include /* for HB_COREDIR */ +# include /* for HB_COREDIR */ #endif #ifndef MAXLINE -# define MAXLINE 512 +# define MAXLINE 512 #endif #ifdef HAVE_GETOPT_H # include #endif CRM_TRACE_INIT_DATA(common); static uint ref_counter = 0; unsigned int crm_log_level = LOG_INFO; gboolean crm_config_error = FALSE; gboolean crm_config_warning = FALSE; const char *crm_system_name = "unknown"; int node_score_red = 0; int node_score_green = 0; int node_score_yellow = 0; int node_score_infinity = INFINITY; void crm_set_env_options(void); gboolean -check_time(const char *value) +check_time(const char *value) { - if(crm_get_msec(value) < 5000) { - return FALSE; + if (crm_get_msec(value) < 5000) { + return FALSE; } return TRUE; } gboolean -check_timer(const char *value) +check_timer(const char *value) { - if(crm_get_msec(value) < 0) { - return FALSE; + if (crm_get_msec(value) < 0) { + return FALSE; } return TRUE; } gboolean -check_boolean(const char *value) +check_boolean(const char *value) { int tmp = FALSE; - if(crm_str_to_boolean(value, &tmp) != 1) { - return FALSE; + + if (crm_str_to_boolean(value, &tmp) != 1) { + return FALSE; } return TRUE; } gboolean -check_number(const char *value) +check_number(const char *value) { errno = 0; - if(value == NULL) { - return FALSE; - - } else if(safe_str_eq(value, MINUS_INFINITY_S)) { - - } else if(safe_str_eq(value, INFINITY_S)) { + if (value == NULL) { + return FALSE; + + } else if (safe_str_eq(value, MINUS_INFINITY_S)) { + + } else if (safe_str_eq(value, INFINITY_S)) { } else { - crm_int_helper(value, NULL); + crm_int_helper(value, NULL); } - if(errno != 0) { - return FALSE; + if (errno != 0) { + return FALSE; } return TRUE; } int -char2score(const char *score) +char2score(const char *score) { int score_f = 0; - - if(score == NULL) { - - } else if(safe_str_eq(score, MINUS_INFINITY_S)) { - score_f = -node_score_infinity; - - } else if(safe_str_eq(score, INFINITY_S)) { - score_f = node_score_infinity; - - } else if(safe_str_eq(score, "+"INFINITY_S)) { - score_f = node_score_infinity; - - } else if(safe_str_eq(score, "red")) { - score_f = node_score_red; - - } else if(safe_str_eq(score, "yellow")) { - score_f = node_score_yellow; - - } else if(safe_str_eq(score, "green")) { - score_f = node_score_green; + + if (score == NULL) { + + } else if (safe_str_eq(score, MINUS_INFINITY_S)) { + score_f = -node_score_infinity; + + } else if (safe_str_eq(score, INFINITY_S)) { + score_f = node_score_infinity; + + } else if (safe_str_eq(score, "+" INFINITY_S)) { + score_f = node_score_infinity; + + } else if (safe_str_eq(score, "red")) { + score_f = node_score_red; + + } else if (safe_str_eq(score, "yellow")) { + score_f = node_score_yellow; + + } else if (safe_str_eq(score, "green")) { + score_f = node_score_green; } else { - score_f = crm_parse_int(score, NULL); - if(score_f > 0 && score_f > node_score_infinity) { - score_f = node_score_infinity; - - } else if(score_f < 0 && score_f < -node_score_infinity) { - score_f = -node_score_infinity; - } - } - + score_f = crm_parse_int(score, NULL); + if (score_f > 0 && score_f > node_score_infinity) { + score_f = node_score_infinity; + + } else if (score_f < 0 && score_f < -node_score_infinity) { + score_f = -node_score_infinity; + } + } + return score_f; } char * -score2char(int score) +score2char(int score) { - if(score >= node_score_infinity) { - return crm_strdup(INFINITY_S); + if (score >= node_score_infinity) { + return crm_strdup(INFINITY_S); - } else if(score <= -node_score_infinity) { - return crm_strdup("-"INFINITY_S); - } + } else if (score <= -node_score_infinity) { + return crm_strdup("-" INFINITY_S); + } return crm_itoa(score); } - const char * -cluster_option(GHashTable* options, gboolean(*validate)(const char*), - const char *name, const char *old_name, const char *def_value) +cluster_option(GHashTable * options, gboolean(*validate) (const char *), + const char *name, const char *old_name, const char *def_value) { const char *value = NULL; + CRM_ASSERT(name != NULL); - if(options != NULL) { - value = g_hash_table_lookup(options, name); - } - - if(value == NULL && old_name && options != NULL) { - value = g_hash_table_lookup(options, old_name); - if(value != NULL) { - crm_config_warn("Using deprecated name '%s' for" - " cluster option '%s'", old_name, name); - g_hash_table_insert( - options, crm_strdup(name), crm_strdup(value)); - value = g_hash_table_lookup(options, old_name); - } - } - - if(value == NULL) { - crm_debug_2("Using default value '%s' for cluster option '%s'", - def_value, name); - - if(options == NULL) { - return def_value; - } - - g_hash_table_insert( - options, crm_strdup(name), crm_strdup(def_value)); - value = g_hash_table_lookup(options, name); - } - - if(validate && validate(value) == FALSE) { - crm_config_err("Value '%s' for cluster option '%s' is invalid." - " Defaulting to %s", value, name, def_value); - g_hash_table_replace(options, crm_strdup(name), - crm_strdup(def_value)); - value = g_hash_table_lookup(options, name); - } - + if (options != NULL) { + value = g_hash_table_lookup(options, name); + } + + if (value == NULL && old_name && options != NULL) { + value = g_hash_table_lookup(options, old_name); + if (value != NULL) { + crm_config_warn("Using deprecated name '%s' for" + " cluster option '%s'", old_name, name); + g_hash_table_insert(options, crm_strdup(name), crm_strdup(value)); + value = g_hash_table_lookup(options, old_name); + } + } + + if (value == NULL) { + crm_debug_2("Using default value '%s' for cluster option '%s'", def_value, name); + + if (options == NULL) { + return def_value; + } + + g_hash_table_insert(options, crm_strdup(name), crm_strdup(def_value)); + value = g_hash_table_lookup(options, name); + } + + if (validate && validate(value) == FALSE) { + crm_config_err("Value '%s' for cluster option '%s' is invalid." + " Defaulting to %s", value, name, def_value); + g_hash_table_replace(options, crm_strdup(name), crm_strdup(def_value)); + value = g_hash_table_lookup(options, name); + } + return value; } - const char * -get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name) +get_cluster_pref(GHashTable * options, pe_cluster_option * option_list, int len, const char *name) { int lpc = 0; const char *value = NULL; gboolean found = FALSE; - for(lpc = 0; lpc < len; lpc++) { - if(safe_str_eq(name, option_list[lpc].name)) { - found = TRUE; - value = cluster_option(options, - option_list[lpc].is_valid, - option_list[lpc].name, - option_list[lpc].alt_name, - option_list[lpc].default_value); - } + + for (lpc = 0; lpc < len; lpc++) { + if (safe_str_eq(name, option_list[lpc].name)) { + found = TRUE; + value = cluster_option(options, + option_list[lpc].is_valid, + option_list[lpc].name, + option_list[lpc].alt_name, option_list[lpc].default_value); + } } CRM_CHECK(found, crm_err("No option named: %s", name)); CRM_ASSERT(value != NULL); return value; } void -config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, - pe_cluster_option *option_list, int len) +config_metadata(const char *name, const char *version, const char *desc_short, + const char *desc_long, pe_cluster_option * option_list, int len) { int lpc = 0; fprintf(stdout, "" - "\n" - "\n" - " %s\n" - " %s\n" - " %s\n" - " \n", name, version, desc_long, desc_short); - - for(lpc = 0; lpc < len; lpc++) { - if(option_list[lpc].description_long == NULL - && option_list[lpc].description_short == NULL) { - continue; - } - fprintf(stdout, " \n" - " %s\n" - " \n" - " %s%s%s\n" - " \n", - option_list[lpc].name, - option_list[lpc].description_short, - option_list[lpc].type, - option_list[lpc].default_value, - option_list[lpc].description_long?option_list[lpc].description_long:option_list[lpc].description_short, - option_list[lpc].values?" Allowed values: ":"", - option_list[lpc].values?option_list[lpc].values:""); + "\n" + "\n" + " %s\n" + " %s\n" + " %s\n" + " \n", name, version, desc_long, desc_short); + + for (lpc = 0; lpc < len; lpc++) { + if (option_list[lpc].description_long == NULL && option_list[lpc].description_short == NULL) { + continue; + } + fprintf(stdout, " \n" + " %s\n" + " \n" + " %s%s%s\n" + " \n", + option_list[lpc].name, + option_list[lpc].description_short, + option_list[lpc].type, + option_list[lpc].default_value, + option_list[lpc].description_long ? option_list[lpc]. + description_long : option_list[lpc].description_short, + option_list[lpc].values ? " Allowed values: " : "", + option_list[lpc].values ? option_list[lpc].values : ""); } fprintf(stdout, " \n\n"); } void -verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len) +verify_all_options(GHashTable * options, pe_cluster_option * option_list, int len) { int lpc = 0; - for(lpc = 0; lpc < len; lpc++) { - cluster_option(options, - option_list[lpc].is_valid, - option_list[lpc].name, - option_list[lpc].alt_name, - option_list[lpc].default_value); + + for (lpc = 0; lpc < len; lpc++) { + cluster_option(options, + option_list[lpc].is_valid, + option_list[lpc].name, + option_list[lpc].alt_name, option_list[lpc].default_value); } } char * generateReference(const char *custom1, const char *custom2) { const char *local_cust1 = custom1; const char *local_cust2 = custom2; int reference_len = 4; char *since_epoch = NULL; - reference_len += 20; /* too big */ - reference_len += 40; /* too big */ - - if(local_cust1 == NULL) { local_cust1 = "_empty_"; } + reference_len += 20; /* too big */ + reference_len += 40; /* too big */ + + if (local_cust1 == NULL) { + local_cust1 = "_empty_"; + } reference_len += strlen(local_cust1); - - if(local_cust2 == NULL) { local_cust2 = "_empty_"; } + + if (local_cust2 == NULL) { + local_cust2 = "_empty_"; + } reference_len += strlen(local_cust2); - + crm_malloc0(since_epoch, reference_len); - if(since_epoch != NULL) { - sprintf(since_epoch, "%s-%s-%ld-%u", - local_cust1, local_cust2, - (unsigned long)time(NULL), ref_counter++); + if (since_epoch != NULL) { + sprintf(since_epoch, "%s-%s-%ld-%u", + local_cust1, local_cust2, (unsigned long)time(NULL), ref_counter++); } return since_epoch; } gboolean decodeNVpair(const char *srcstring, char separator, char **name, char **value) { int lpc = 0; int len = 0; const char *temp = NULL; CRM_ASSERT(name != NULL && value != NULL); *name = NULL; *value = NULL; crm_debug_4("Attempting to decode: [%s]", srcstring); if (srcstring != NULL) { - len = strlen(srcstring); - while(lpc <= len) { - if (srcstring[lpc] == separator) { - crm_malloc0(*name, lpc+1); - if(*name == NULL) { - break; /* and return FALSE */ - } - strncpy(*name, srcstring, lpc); - (*name)[lpc] = '\0'; + len = strlen(srcstring); + while (lpc <= len) { + if (srcstring[lpc] == separator) { + crm_malloc0(*name, lpc + 1); + if (*name == NULL) { + break; /* and return FALSE */ + } + strncpy(*name, srcstring, lpc); + (*name)[lpc] = '\0'; /* this sucks but as the strtok manpage says.. * it *is* a bug */ - len = len-lpc; len--; - if(len <= 0) { - *value = NULL; - } else { - - crm_malloc0(*value, len+1); - if(*value == NULL) { - crm_free(*name); - break; /* and return FALSE */ - } - temp = srcstring+lpc+1; - strncpy(*value, temp, len); - (*value)[len] = '\0'; - } - return TRUE; - } - lpc++; - } - } - - if(*name != NULL) { - crm_free(*name); + len = len - lpc; + len--; + if (len <= 0) { + *value = NULL; + } else { + + crm_malloc0(*value, len + 1); + if (*value == NULL) { + crm_free(*name); + break; /* and return FALSE */ + } + temp = srcstring + lpc + 1; + strncpy(*value, temp, len); + (*value)[len] = '\0'; + } + return TRUE; + } + lpc++; + } + } + + if (*name != NULL) { + crm_free(*name); } *name = NULL; *value = NULL; - + return FALSE; } char * -crm_concat(const char *prefix, const char *suffix, char join) +crm_concat(const char *prefix, const char *suffix, char join) { int len = 0; char *new_str = NULL; + CRM_ASSERT(prefix != NULL); CRM_ASSERT(suffix != NULL); len = strlen(prefix) + strlen(suffix) + 2; crm_malloc0(new_str, (len)); sprintf(new_str, "%s%c%s", prefix, join, suffix); - new_str[len-1] = 0; + new_str[len - 1] = 0; return new_str; } - char * generate_hash_key(const char *crm_msg_reference, const char *sys) { - char *hash_key = crm_concat(sys?sys:"none", crm_msg_reference, '_'); + char *hash_key = crm_concat(sys ? sys : "none", crm_msg_reference, '_'); + crm_debug_3("created hash key: (%s)", hash_key); return hash_key; } char * generate_hash_value(const char *src_node, const char *src_subsys) { char *hash_value = NULL; - + if (src_node == NULL || src_subsys == NULL) { - return NULL; + return NULL; } - + if (strcasecmp(CRM_SYSTEM_DC, src_subsys) == 0) { - hash_value = crm_strdup(src_subsys); - CRM_ASSERT(hash_value); - return hash_value; + hash_value = crm_strdup(src_subsys); + CRM_ASSERT(hash_value); + return hash_value; } hash_value = crm_concat(src_node, src_subsys, '_'); crm_info("created hash value: (%s)", hash_value); return hash_value; } char * crm_itoa(int an_int) { int len = 32; char *buffer = NULL; - - crm_malloc0(buffer, (len+1)); - if(buffer != NULL) { - snprintf(buffer, len, "%d", an_int); + + crm_malloc0(buffer, (len + 1)); + if (buffer != NULL) { + snprintf(buffer, len, "%d", an_int); } - + return buffer; } -extern int LogToLoggingDaemon(int priority, const char * buf, int bstrlen, gboolean use_pri_str); +extern int LogToLoggingDaemon(int priority, const char *buf, int bstrlen, gboolean use_pri_str); #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER GLogFunc glib_log_default; static void -crm_glib_handler(const gchar *log_domain, GLogLevelFlags flags, const gchar *message, gpointer user_data) +crm_glib_handler(const gchar * log_domain, GLogLevelFlags flags, const gchar * message, + gpointer user_data) { int log_level = LOG_WARNING; GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK); - switch(msg_level) { - case G_LOG_LEVEL_CRITICAL: - /* log and record how we got here */ - crm_abort(__FILE__,__PRETTY_FUNCTION__,__LINE__, message, TRUE, TRUE); - return; - - case G_LOG_LEVEL_ERROR: log_level = LOG_ERR; break; - case G_LOG_LEVEL_MESSAGE: log_level = LOG_NOTICE; break; - case G_LOG_LEVEL_INFO: log_level = LOG_INFO; break; - case G_LOG_LEVEL_DEBUG: log_level = LOG_DEBUG; break; - - case G_LOG_LEVEL_WARNING: - case G_LOG_FLAG_RECURSION: - case G_LOG_FLAG_FATAL: - case G_LOG_LEVEL_MASK: - log_level = LOG_WARNING; - break; + switch (msg_level) { + case G_LOG_LEVEL_CRITICAL: + /* log and record how we got here */ + crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, message, TRUE, TRUE); + return; + + case G_LOG_LEVEL_ERROR: + log_level = LOG_ERR; + break; + case G_LOG_LEVEL_MESSAGE: + log_level = LOG_NOTICE; + break; + case G_LOG_LEVEL_INFO: + log_level = LOG_INFO; + break; + case G_LOG_LEVEL_DEBUG: + log_level = LOG_DEBUG; + break; + + case G_LOG_LEVEL_WARNING: + case G_LOG_FLAG_RECURSION: + case G_LOG_FLAG_FATAL: + case G_LOG_LEVEL_MASK: + log_level = LOG_WARNING; + break; } do_crm_log(log_level, "%s: %s", log_domain, message); } #endif -void crm_log_deinit(void) { +void +crm_log_deinit(void) +{ #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER g_log_set_default_handler(glib_log_default, NULL); #endif } -gboolean crm_log_init( - const char *entity, int level, gboolean coredir, gboolean to_stderr, - int argc, char **argv) +gboolean +crm_log_init(const char *entity, int level, gboolean coredir, gboolean to_stderr, + int argc, char **argv) { return crm_log_init_worker(entity, level, coredir, to_stderr, argc, argv, FALSE); } -gboolean crm_log_init_quiet( - const char *entity, int level, gboolean coredir, gboolean to_stderr, - int argc, char **argv) +gboolean +crm_log_init_quiet(const char *entity, int level, gboolean coredir, gboolean to_stderr, + int argc, char **argv) { return crm_log_init_worker(entity, level, coredir, to_stderr, argc, argv, TRUE); } #if SUPPORT_TRACING static int -update_trace_data(struct _pcmk_ddebug_query *query, struct _pcmk_ddebug *start, struct _pcmk_ddebug *stop) +update_trace_data(struct _pcmk_ddebug_query *query, struct _pcmk_ddebug *start, + struct _pcmk_ddebug *stop) { int lpc = 0; unsigned nfound = 0; struct _pcmk_ddebug *dp; const char *match = "unknown"; CRM_ASSERT(stop != NULL); CRM_ASSERT(start != NULL); - + for (dp = start; dp != stop; dp++) { - gboolean bump = FALSE; - lpc++; - /* fprintf(stderr, "checking: %-12s %20s:%u fmt:%s\n", */ - /* dp->function, dp->filename, dp->lineno, dp->format); */ - - if (query->functions && strstr(query->functions, dp->function) != NULL) { - match = "function"; - bump = TRUE; - } - - if(query->files) { - char token[500]; - const char *offset = NULL; - const char *next = query->files; - - do { - offset = next; - next = strchrnul(offset, ','); - snprintf(token, 499, "%.*s", (int)(next-offset), offset); - - if (query->files && strstr(dp->filename, token) != NULL) { - match = "file"; - bump = TRUE; - - } else if(next[0] != 0) { - next++; - } - - } while(bump == FALSE && next != NULL && next[0] != 0); - } - - if (query->formats && strstr(query->formats, dp->format) != NULL) { - match = "format"; - bump = TRUE; - } - - if(bump) { - nfound++; - dp->bump = LOG_NOTICE; - do_crm_log_always(LOG_INFO, "Detected '%s' match: %-12s %20s:%u fmt:%s", - match, dp->function, dp->filename, dp->lineno, dp->format); - } + gboolean bump = FALSE; + + lpc++; + /* fprintf(stderr, "checking: %-12s %20s:%u fmt:%s\n", */ + /* dp->function, dp->filename, dp->lineno, dp->format); */ + + if (query->functions && strstr(query->functions, dp->function) != NULL) { + match = "function"; + bump = TRUE; + } + + if (query->files) { + char token[500]; + const char *offset = NULL; + const char *next = query->files; + + do { + offset = next; + next = strchrnul(offset, ','); + snprintf(token, 499, "%.*s", (int)(next - offset), offset); + + if (query->files && strstr(dp->filename, token) != NULL) { + match = "file"; + bump = TRUE; + + } else if (next[0] != 0) { + next++; + } + + } while (bump == FALSE && next != NULL && next[0] != 0); + } + + if (query->formats && strstr(query->formats, dp->format) != NULL) { + match = "format"; + bump = TRUE; + } + + if (bump) { + nfound++; + dp->bump = LOG_NOTICE; + do_crm_log_always(LOG_INFO, "Detected '%s' match: %-12s %20s:%u fmt:%s", + match, dp->function, dp->filename, dp->lineno, dp->format); + } } query->total += lpc; query->matches += nfound; return nfound; } -#define _GNU_SOURCE -#include -#include -#include +# define _GNU_SOURCE +# include +# include +# include static int ddebug_callback(struct dl_phdr_info *info, size_t size, void *data) { - if(strlen(info->dlpi_name) > 0) { - struct _pcmk_ddebug_query *query = data; - - void *handle; - void *start; - void *stop; - char *error; - - handle = dlopen (info->dlpi_name, RTLD_LAZY); - error = dlerror(); - if (!handle || error) { - crm_err("%s", error); - if(handle) { - dlclose(handle); - } - return 0; - } - - start = dlsym(handle, "__start___verbose"); - error = dlerror(); - if (error) { - goto done; - } - - stop = dlsym(handle, "__stop___verbose"); - error = dlerror(); - if (error) { - goto done; - - } else { - unsigned long int len = (unsigned long int)stop - (unsigned long int)start; - crm_info("Checking for query matches in %lu trace symbols from: %s (offset: %p)", - len/sizeof(struct _pcmk_ddebug), info->dlpi_name, start); - - update_trace_data(query, start, stop); - } - done: - dlclose(handle); - } - + if (strlen(info->dlpi_name) > 0) { + struct _pcmk_ddebug_query *query = data; + + void *handle; + void *start; + void *stop; + char *error; + + handle = dlopen(info->dlpi_name, RTLD_LAZY); + error = dlerror(); + if (!handle || error) { + crm_err("%s", error); + if (handle) { + dlclose(handle); + } + return 0; + } + + start = dlsym(handle, "__start___verbose"); + error = dlerror(); + if (error) { + goto done; + } + + stop = dlsym(handle, "__stop___verbose"); + error = dlerror(); + if (error) { + goto done; + + } else { + unsigned long int len = (unsigned long int)stop - (unsigned long int)start; + + crm_info("Checking for query matches in %lu trace symbols from: %s (offset: %p)", + len / sizeof(struct _pcmk_ddebug), info->dlpi_name, start); + + update_trace_data(query, start, stop); + } + done: + dlclose(handle); + } + return 0; } #endif - -void update_all_trace_data(void) +void +update_all_trace_data(void) { #if SUPPORT_TRACING gboolean search = FALSE; const char *env_value = NULL; struct _pcmk_ddebug_query query; memset(&query, 0, sizeof(struct _pcmk_ddebug_query)); env_value = getenv("PCMK_trace_files"); - if(env_value) { - search = TRUE; - query.files = env_value; + if (env_value) { + search = TRUE; + query.files = env_value; } env_value = getenv("PCMK_trace_formats"); - if(env_value) { - search = TRUE; - query.formats = env_value; + if (env_value) { + search = TRUE; + query.formats = env_value; } env_value = getenv("PCMK_trace_functions"); - if(env_value) { - search = TRUE; - query.functions = env_value; - } - - if(search) { - update_trace_data(&query, __start___verbose, __stop___verbose); - dl_iterate_phdr(ddebug_callback, &query); - if(query.matches == 0) { - do_crm_log_always(LOG_DEBUG, - "no matches for query: {fn='%s', file='%s', fmt='%s'} in %llu entries", - crm_str(query.functions), crm_str(query.files), crm_str(query.formats), query.total); - } else { - do_crm_log_always(LOG_INFO, - "%llu matches for query: {fn='%s', file='%s', fmt='%s'} in %llu entries", - query.matches, crm_str(query.functions), crm_str(query.files), crm_str(query.formats), - query.total); - } + if (env_value) { + search = TRUE; + query.functions = env_value; + } + + if (search) { + update_trace_data(&query, __start___verbose, __stop___verbose); + dl_iterate_phdr(ddebug_callback, &query); + if (query.matches == 0) { + do_crm_log_always(LOG_DEBUG, + "no matches for query: {fn='%s', file='%s', fmt='%s'} in %llu entries", + crm_str(query.functions), crm_str(query.files), + crm_str(query.formats), query.total); + } else { + do_crm_log_always(LOG_INFO, + "%llu matches for query: {fn='%s', file='%s', fmt='%s'} in %llu entries", + query.matches, crm_str(query.functions), crm_str(query.files), + crm_str(query.formats), query.total); + } } /* return query.matches; */ #endif } gboolean -crm_log_init_worker( - const char *entity, int level, gboolean coredir, gboolean to_stderr, - int argc, char **argv, gboolean quiet) +crm_log_init_worker(const char *entity, int level, gboolean coredir, gboolean to_stderr, + int argc, char **argv, gboolean quiet) { /* Redirect messages from glib functions to our handler */ /* cl_malloc_forced_for_glib(); */ #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL); #endif - + /* and for good measure... - this enum is a bit field (!) */ - g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/ + g_log_set_always_fatal((GLogLevelFlags) 0); /*value out of range */ - if(entity) { - crm_system_name = entity; + if (entity) { + crm_system_name = entity; - } else if(argc > 0 && argv != NULL) { - crm_system_name = basename(argv[0]); - if(strstr(crm_system_name, "lt-") == crm_system_name) { - crm_system_name += 3; - } - - } else if(crm_system_name == NULL) { - crm_system_name = "Unknown"; + } else if (argc > 0 && argv != NULL) { + crm_system_name = basename(argv[0]); + if (strstr(crm_system_name, "lt-") == crm_system_name) { + crm_system_name += 3; + } + + } else if (crm_system_name == NULL) { + crm_system_name = "Unknown"; } - + setenv("PCMK_service", crm_system_name, 1); cl_log_set_entity(crm_system_name); set_crm_log_level(level); crm_set_env_options(); - if(quiet) { - /* Nuke any syslog activity */ - unsetenv("HA_logfacility"); + if (quiet) { + /* Nuke any syslog activity */ + unsetenv("HA_logfacility"); } else { - cl_log_args(argc, argv); - if(getenv("HA_logfacility") == NULL) { - /* Set a default */ - cl_log_set_facility(HA_LOG_FACILITY); - } /* else: picked up by crm_set_env_options() */ + cl_log_args(argc, argv); + if (getenv("HA_logfacility") == NULL) { + /* Set a default */ + cl_log_set_facility(HA_LOG_FACILITY); + } /* else: picked up by crm_set_env_options() */ } - + cl_log_enable_stderr(to_stderr); - - if(coredir) { - const char *user = getenv("USER"); - if(user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) { - crm_info("Not switching to corefile directory for %s", user); - coredir = FALSE; - } - } - - if(coredir) { - int user = getuid(); - const char *base = HA_COREDIR; - struct passwd *pwent = getpwuid(user); - - if (pwent == NULL) { - crm_perror(LOG_ERR, "Cannot get name for uid: %d", user); - - } else if(safe_str_neq(pwent->pw_name, "root") - && safe_str_neq(pwent->pw_name, "nobody") - && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) { - crm_debug("Don't change active directory for regular user: %s", pwent->pw_name); - - } else if (chdir(base) < 0) { - crm_perror(LOG_ERR, "Cannot change active directory to %s", base); - - } else if (chdir(pwent->pw_name) < 0) { - crm_perror(LOG_ERR, "Cannot change active directory to %s/%s", base, pwent->pw_name); - } else { - crm_info("Changed active directory to %s/%s", base, pwent->pw_name); + + if (coredir) { + const char *user = getenv("USER"); + + if (user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) { + crm_info("Not switching to corefile directory for %s", user); + coredir = FALSE; + } + } + + if (coredir) { + int user = getuid(); + const char *base = HA_COREDIR; + struct passwd *pwent = getpwuid(user); + + if (pwent == NULL) { + crm_perror(LOG_ERR, "Cannot get name for uid: %d", user); + + } else if (safe_str_neq(pwent->pw_name, "root") + && safe_str_neq(pwent->pw_name, "nobody") + && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) { + crm_debug("Don't change active directory for regular user: %s", pwent->pw_name); + + } else if (chdir(base) < 0) { + crm_perror(LOG_ERR, "Cannot change active directory to %s", base); + + } else if (chdir(pwent->pw_name) < 0) { + crm_perror(LOG_ERR, "Cannot change active directory to %s/%s", base, pwent->pw_name); + } else { + crm_info("Changed active directory to %s/%s", base, pwent->pw_name); #if 0 - { - char path[512]; - snprintf(path, 512, "%s-%d", crm_system_name, getpid()); - mkdir(path, 0750); - chdir(path); - crm_info("Changed active directory to %s/%s/%s", - base, pwent->pw_name, path); - } + { + char path[512]; + + snprintf(path, 512, "%s-%d", crm_system_name, getpid()); + mkdir(path, 0750); + chdir(path); + crm_info("Changed active directory to %s/%s/%s", base, pwent->pw_name, path); + } #endif - } + } } update_all_trace_data(); crm_signal(DEBUG_INC, alter_debug); crm_signal(DEBUG_DEC, alter_debug); return TRUE; } /* returns the old value */ unsigned int set_crm_log_level(unsigned int level) { unsigned int old = crm_log_level; - crm_log_level = level; + + crm_log_level = level; return old; } unsigned int get_crm_log_level(void) { return crm_log_level; } static int crm_version_helper(const char *text, char **end_text) { int atoi_result = -1; + CRM_ASSERT(end_text != NULL); errno = 0; - - if(text != NULL && text[0] != 0) { - atoi_result = (int)strtol(text, end_text, 10); - - if(errno == EINVAL) { - crm_err("Conversion of '%s' %c failed", text, text[0]); - atoi_result = -1; - } + + if (text != NULL && text[0] != 0) { + atoi_result = (int)strtol(text, end_text, 10); + + if (errno == EINVAL) { + crm_err("Conversion of '%s' %c failed", text, text[0]); + atoi_result = -1; + } } return atoi_result; } - /* * version1 < version2 : -1 * version1 = version2 : 0 * version1 > version2 : 1 */ int compare_version(const char *version1, const char *version2) { int rc = 0; int lpc = 0; char *ver1_copy = NULL, *ver2_copy = NULL; char *rest1 = NULL, *rest2 = NULL; - if(version1 == NULL && version2 == NULL) { - return 0; - } else if(version1 == NULL) { - return -1; - } else if(version2 == NULL) { - return 1; + if (version1 == NULL && version2 == NULL) { + return 0; + } else if (version1 == NULL) { + return -1; + } else if (version2 == NULL) { + return 1; } - + ver1_copy = crm_strdup(version1); ver2_copy = crm_strdup(version2); rest1 = ver1_copy; rest2 = ver2_copy; - while(1) { - int digit1 = 0; - int digit2 = 0; - - lpc++; - - if(rest1 == rest2) { - break; - } - - if(rest1 != NULL) { - digit1 = crm_version_helper(rest1, &rest1); - } - - if(rest2 != NULL) { - digit2 = crm_version_helper(rest2, &rest2); - } - - if(digit1 < digit2){ - rc = -1; - crm_debug_5("%d < %d", digit1, digit2); - break; - - } else if (digit1 > digit2){ - rc = 1; - crm_debug_5("%d > %d", digit1, digit2); - break; - } - - if(rest1 != NULL && rest1[0] == '.') { - rest1++; - } - if(rest1 != NULL && rest1[0] == 0) { - rest1 = NULL; - } - - if(rest2 != NULL && rest2[0] == '.') { - rest2++; - } - if(rest2 != NULL && rest2[0] == 0) { - rest2 = NULL; - } - } - + while (1) { + int digit1 = 0; + int digit2 = 0; + + lpc++; + + if (rest1 == rest2) { + break; + } + + if (rest1 != NULL) { + digit1 = crm_version_helper(rest1, &rest1); + } + + if (rest2 != NULL) { + digit2 = crm_version_helper(rest2, &rest2); + } + + if (digit1 < digit2) { + rc = -1; + crm_debug_5("%d < %d", digit1, digit2); + break; + + } else if (digit1 > digit2) { + rc = 1; + crm_debug_5("%d > %d", digit1, digit2); + break; + } + + if (rest1 != NULL && rest1[0] == '.') { + rest1++; + } + if (rest1 != NULL && rest1[0] == 0) { + rest1 = NULL; + } + + if (rest2 != NULL && rest2[0] == '.') { + rest2++; + } + if (rest2 != NULL && rest2[0] == 0) { + rest2 = NULL; + } + } + crm_free(ver1_copy); crm_free(ver2_copy); - if(rc == 0) { - crm_debug_3("%s == %s (%d)", version1, version2, lpc); - } else if(rc < 0) { - crm_debug_3("%s < %s (%d)", version1, version2, lpc); - } else if(rc > 0) { - crm_debug_3("%s > %s (%d)", version1, version2, lpc); + if (rc == 0) { + crm_debug_3("%s == %s (%d)", version1, version2, lpc); + } else if (rc < 0) { + crm_debug_3("%s < %s (%d)", version1, version2, lpc); + } else if (rc > 0) { + crm_debug_3("%s > %s (%d)", version1, version2, lpc); } return rc; } gboolean do_stderr = FALSE; void -alter_debug(int nsig) +alter_debug(int nsig) { crm_signal(DEBUG_INC, alter_debug); crm_signal(DEBUG_DEC, alter_debug); - - switch(nsig) { - case DEBUG_INC: - if (crm_log_level < 100) { - crm_log_level++; - } - break; - case DEBUG_DEC: - if (crm_log_level > 0) { - crm_log_level--; - } - break; + switch (nsig) { + case DEBUG_INC: + if (crm_log_level < 100) { + crm_log_level++; + } + break; - default: - fprintf(stderr, "Unknown signal %d\n", nsig); - cl_log(LOG_ERR, "Unknown signal %d", nsig); - break; + case DEBUG_DEC: + if (crm_log_level > 0) { + crm_log_level--; + } + break; + + default: + fprintf(stderr, "Unknown signal %d\n", nsig); + cl_log(LOG_ERR, "Unknown signal %d", nsig); + break; } } - -void g_hash_destroy_str(gpointer data) +void +g_hash_destroy_str(gpointer data) { crm_free(data); } #include /* #include */ /* #include */ long long crm_int_helper(const char *text, char **end_text) { long long result = -1; char *local_end_text = NULL; int saved_errno = 0; - + errno = 0; - - if(text != NULL) { + + if (text != NULL) { #ifdef ANSI_ONLY - if(end_text != NULL) { - result = strtol(text, end_text, 10); - } else { - result = strtol(text, &local_end_text, 10); - } + if (end_text != NULL) { + result = strtol(text, end_text, 10); + } else { + result = strtol(text, &local_end_text, 10); + } #else - if(end_text != NULL) { - result = strtoll(text, end_text, 10); - } else { - result = strtoll(text, &local_end_text, 10); - } + if (end_text != NULL) { + result = strtoll(text, end_text, 10); + } else { + result = strtoll(text, &local_end_text, 10); + } #endif - saved_errno = errno; + saved_errno = errno; /* CRM_CHECK(errno != EINVAL); */ - if(errno == EINVAL) { - crm_err("Conversion of %s failed", text); - result = -1; - - } else if(errno == ERANGE) { - crm_err("Conversion of %s was clipped: %lld", text, result); - - } else if(errno != 0) { - crm_perror(LOG_ERR,"Conversion of %s failed:", text); - } - - if(local_end_text != NULL && local_end_text[0] != '\0') { - crm_err("Characters left over after parsing '%s': '%s'", text, local_end_text); - } - - errno = saved_errno; + if (errno == EINVAL) { + crm_err("Conversion of %s failed", text); + result = -1; + + } else if (errno == ERANGE) { + crm_err("Conversion of %s was clipped: %lld", text, result); + + } else if (errno != 0) { + crm_perror(LOG_ERR, "Conversion of %s failed:", text); + } + + if (local_end_text != NULL && local_end_text[0] != '\0') { + crm_err("Characters left over after parsing '%s': '%s'", text, local_end_text); + } + + errno = saved_errno; } return result; } int crm_parse_int(const char *text, const char *default_text) { int atoi_result = -1; - if(text != NULL) { - atoi_result = crm_int_helper(text, NULL); - if(errno == 0) { - return atoi_result; - } - } - - if(default_text != NULL) { - atoi_result = crm_int_helper(default_text, NULL); - if(errno == 0) { - return atoi_result; - } + + if (text != NULL) { + atoi_result = crm_int_helper(text, NULL); + if (errno == 0) { + return atoi_result; + } + } + + if (default_text != NULL) { + atoi_result = crm_int_helper(default_text, NULL); + if (errno == 0) { + return atoi_result; + } } else { - crm_err("No default conversion value supplied"); + crm_err("No default conversion value supplied"); } return -1; } gboolean safe_str_neq(const char *a, const char *b) { - if(a == b) { - return FALSE; + if (a == b) { + return FALSE; - } else if(a==NULL || b==NULL) { - return TRUE; + } else if (a == NULL || b == NULL) { + return TRUE; - } else if(strcasecmp(a, b) == 0) { - return FALSE; + } else if (strcasecmp(a, b) == 0) { + return FALSE; } return TRUE; } char * crm_strdup_fn(const char *src, const char *file, const char *fn, int line) { char *dup = NULL; - CRM_CHECK(src != NULL, - crm_err("Could not perform copy at %s:%d (%s)", file, line, fn); - return NULL); + + CRM_CHECK(src != NULL, crm_err("Could not perform copy at %s:%d (%s)", file, line, fn); + return NULL); crm_malloc0(dup, strlen(src) + 1); return strcpy(dup, src); } - - #define ENV_PREFIX "HA_" void -crm_set_env_options(void) +crm_set_env_options(void) { cl_inherit_logging_environment(500); cl_log_set_logd_channel_source(NULL, NULL); - if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) { - set_crm_log_level(LOG_INFO + debug_level); + if (debug_level > 0 && (debug_level + LOG_INFO) > (int)crm_log_level) { + set_crm_log_level(LOG_INFO + debug_level); } } gboolean -crm_is_true(const char * s) +crm_is_true(const char *s) { gboolean ret = FALSE; - if(s != NULL) { - crm_str_to_boolean(s, &ret); + + if (s != NULL) { + crm_str_to_boolean(s, &ret); } return ret; } int -crm_str_to_boolean(const char * s, int * ret) +crm_str_to_boolean(const char *s, int *ret) { - if(s == NULL) { - return -1; + if (s == NULL) { + return -1; } else if (strcasecmp(s, "true") == 0 - || strcasecmp(s, "on") == 0 - || strcasecmp(s, "yes") == 0 - || strcasecmp(s, "y") == 0 - || strcasecmp(s, "1") == 0){ - *ret = TRUE; - return 1; + || strcasecmp(s, "on") == 0 + || strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0) { + *ret = TRUE; + return 1; } else if (strcasecmp(s, "false") == 0 - || strcasecmp(s, "off") == 0 - || strcasecmp(s, "no") == 0 - || strcasecmp(s, "n") == 0 - || strcasecmp(s, "0") == 0){ - *ret = FALSE; - return 1; + || strcasecmp(s, "off") == 0 + || strcasecmp(s, "no") == 0 || strcasecmp(s, "n") == 0 || strcasecmp(s, "0") == 0) { + *ret = FALSE; + return 1; } return -1; } #ifndef NUMCHARS -# define NUMCHARS "0123456789." +# define NUMCHARS "0123456789." #endif #ifndef WHITESPACE -# define WHITESPACE " \t\n\r\f" +# define WHITESPACE " \t\n\r\f" #endif unsigned long long -crm_get_interval(const char * input) +crm_get_interval(const char *input) { ha_time_t *interval = NULL; char *input_copy = crm_strdup(input); char *input_copy_mutable = input_copy; unsigned long long msec = 0; - - if(input == NULL) { - return 0; - } else if(input[0] != 'P') { - crm_free(input_copy); - return crm_get_msec(input); + if (input == NULL) { + return 0; + + } else if (input[0] != 'P') { + crm_free(input_copy); + return crm_get_msec(input); } - + interval = parse_time_duration(&input_copy_mutable); msec = date_in_seconds(interval); free_ha_date(interval); crm_free(input_copy); return msec * 1000; } long long -crm_get_msec(const char * input) +crm_get_msec(const char *input) { const char *cp = input; const char *units; long long multiplier = 1000; long long divisor = 1; long long msec = -1; char *end_text = NULL; + /* double dret; */ - if(input == NULL) { - return msec; + if (input == NULL) { + return msec; } - + cp += strspn(cp, WHITESPACE); units = cp + strspn(cp, NUMCHARS); units += strspn(units, WHITESPACE); if (strchr(NUMCHARS, *cp) == NULL) { - return msec; - } - - if (strncasecmp(units, "ms", 2) == 0 - || strncasecmp(units, "msec", 4) == 0) { - multiplier = 1; - divisor = 1; - } else if (strncasecmp(units, "us", 2) == 0 - || strncasecmp(units, "usec", 4) == 0) { - multiplier = 1; - divisor = 1000; - } else if (strncasecmp(units, "s", 1) == 0 - || strncasecmp(units, "sec", 3) == 0) { - multiplier = 1000; - divisor = 1; - } else if (strncasecmp(units, "m", 1) == 0 - || strncasecmp(units, "min", 3) == 0) { - multiplier = 60*1000; - divisor = 1; - } else if (strncasecmp(units, "h", 1) == 0 - || strncasecmp(units, "hr", 2) == 0) { - multiplier = 60*60*1000; - divisor = 1; + return msec; + } + + if (strncasecmp(units, "ms", 2) == 0 || strncasecmp(units, "msec", 4) == 0) { + multiplier = 1; + divisor = 1; + } else if (strncasecmp(units, "us", 2) == 0 || strncasecmp(units, "usec", 4) == 0) { + multiplier = 1; + divisor = 1000; + } else if (strncasecmp(units, "s", 1) == 0 || strncasecmp(units, "sec", 3) == 0) { + multiplier = 1000; + divisor = 1; + } else if (strncasecmp(units, "m", 1) == 0 || strncasecmp(units, "min", 3) == 0) { + multiplier = 60 * 1000; + divisor = 1; + } else if (strncasecmp(units, "h", 1) == 0 || strncasecmp(units, "hr", 2) == 0) { + multiplier = 60 * 60 * 1000; + divisor = 1; } else if (*units != EOS && *units != '\n' && *units != '\r') { - return msec; + return msec; } - + msec = crm_int_helper(cp, &end_text); msec *= multiplier; msec /= divisor; /* dret += 0.5; */ /* msec = (long long)dret; */ return msec; } const char * op_status2text(op_status_t status) { - switch(status) { - case LRM_OP_PENDING: - return "pending"; - break; - case LRM_OP_DONE: - return "complete"; - break; - case LRM_OP_ERROR: - return "Error"; - break; - case LRM_OP_TIMEOUT: - return "Timed Out"; - break; - case LRM_OP_NOTSUPPORTED: - return "NOT SUPPORTED"; - break; - case LRM_OP_CANCELLED: - return "Cancelled"; - break; + switch (status) { + case LRM_OP_PENDING: + return "pending"; + break; + case LRM_OP_DONE: + return "complete"; + break; + case LRM_OP_ERROR: + return "Error"; + break; + case LRM_OP_TIMEOUT: + return "Timed Out"; + break; + case LRM_OP_NOTSUPPORTED: + return "NOT SUPPORTED"; + break; + case LRM_OP_CANCELLED: + return "Cancelled"; + break; } crm_err("Unknown status: %d", status); return "UNKNOWN!"; } char * generate_op_key(const char *rsc_id, const char *op_type, int interval) { int len = 35; char *op_id = NULL; - CRM_CHECK(rsc_id != NULL, return NULL); + CRM_CHECK(rsc_id != NULL, return NULL); CRM_CHECK(op_type != NULL, return NULL); - + len += strlen(op_type); len += strlen(rsc_id); crm_malloc0(op_id, len); CRM_CHECK(op_id != NULL, return NULL); sprintf(op_id, "%s_%s_%d", rsc_id, op_type, interval); return op_id; } gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, int *interval) { char *notify = NULL; char *mutable_key = NULL; char *mutable_key_ptr = NULL; int len = 0, offset = 0, ch = 0; CRM_CHECK(key != NULL, return FALSE); - + *interval = 0; len = strlen(key); - offset = len-1; + offset = len - 1; crm_debug_3("Source: %s", key); - - while(offset > 0 && isdigit(key[offset])) { - int digits = len-offset; - ch = key[offset] - '0'; - CRM_CHECK(ch < 10, return FALSE); - CRM_CHECK(ch >= 0, return FALSE); - while(digits > 1) { - digits--; - ch = ch * 10; - } - *interval += ch; - offset--; + + while (offset > 0 && isdigit(key[offset])) { + int digits = len - offset; + + ch = key[offset] - '0'; + CRM_CHECK(ch < 10, return FALSE); + CRM_CHECK(ch >= 0, return FALSE); + while (digits > 1) { + digits--; + ch = ch * 10; + } + *interval += ch; + offset--; } crm_debug_3(" Interval: %d", *interval); CRM_CHECK(key[offset] == '_', return FALSE); mutable_key = crm_strdup(key); mutable_key_ptr = mutable_key_ptr; mutable_key[offset] = 0; offset--; - while(offset > 0 && key[offset] != '_') { - offset--; + while (offset > 0 && key[offset] != '_') { + offset--; } - CRM_CHECK(key[offset] == '_', - crm_free(mutable_key); return FALSE); + CRM_CHECK(key[offset] == '_', crm_free(mutable_key); + return FALSE); - mutable_key_ptr = mutable_key+offset+1; + mutable_key_ptr = mutable_key + offset + 1; crm_debug_3(" Action: %s", mutable_key_ptr); - + *op_type = crm_strdup(mutable_key_ptr); mutable_key[offset] = 0; offset--; - CRM_CHECK(mutable_key != mutable_key_ptr, - crm_free(mutable_key); return FALSE); + CRM_CHECK(mutable_key != mutable_key_ptr, crm_free(mutable_key); + return FALSE); notify = strstr(mutable_key, "_post_notify"); - if(safe_str_eq(notify, "_post_notify")) { - notify[0] = 0; + if (safe_str_eq(notify, "_post_notify")) { + notify[0] = 0; } notify = strstr(mutable_key, "_pre_notify"); - if(safe_str_eq(notify, "_pre_notify")) { - notify[0] = 0; + if (safe_str_eq(notify, "_pre_notify")) { + notify[0] = 0; } - + crm_debug_3(" Resource: %s", mutable_key); *rsc_id = mutable_key; return TRUE; } char * generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type) { int len = 12; char *op_id = NULL; - CRM_CHECK(rsc_id != NULL, return NULL); + CRM_CHECK(rsc_id != NULL, return NULL); CRM_CHECK(op_type != NULL, return NULL); CRM_CHECK(notify_type != NULL, return NULL); - + len += strlen(op_type); len += strlen(rsc_id); len += strlen(notify_type); crm_malloc0(op_id, len); - if(op_id != NULL) { - sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type); + if (op_id != NULL) { + sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type); } return op_id; } char * generate_transition_magic_v202(const char *transition_key, int op_status) { int len = 80; char *fail_state = NULL; CRM_CHECK(transition_key != NULL, return NULL); - + len += strlen(transition_key); - + crm_malloc0(fail_state, len); - if(fail_state != NULL) { - snprintf(fail_state, len, "%d:%s", op_status,transition_key); + if (fail_state != NULL) { + snprintf(fail_state, len, "%d:%s", op_status, transition_key); } return fail_state; } char * generate_transition_magic(const char *transition_key, int op_status, int op_rc) { int len = 80; char *fail_state = NULL; CRM_CHECK(transition_key != NULL, return NULL); - + len += strlen(transition_key); - + crm_malloc0(fail_state, len); - if(fail_state != NULL) { - snprintf(fail_state, len, "%d:%d;%s", - op_status, op_rc, transition_key); + if (fail_state != NULL) { + snprintf(fail_state, len, "%d:%d;%s", op_status, op_rc, transition_key); } return fail_state; } gboolean -decode_transition_magic( - const char *magic, char **uuid, int *transition_id, int *action_id, - int *op_status, int *op_rc, int *target_rc) +decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, + int *op_status, int *op_rc, int *target_rc) { int res = 0; char *key = NULL; gboolean result = TRUE; CRM_CHECK(magic != NULL, return FALSE); CRM_CHECK(op_rc != NULL, return FALSE); CRM_CHECK(op_status != NULL, return FALSE); - - crm_malloc0(key, strlen(magic)+1); + + crm_malloc0(key, strlen(magic) + 1); res = sscanf(magic, "%d:%d;%s", op_status, op_rc, key); - if(res != 3) { - crm_crit("Only found %d items in: %s", res, magic); - result = FALSE; - goto bail; - } - - CRM_CHECK(decode_transition_key(key, uuid, transition_id, action_id, target_rc), - result = FALSE; - goto bail; - ); - + if (res != 3) { + crm_crit("Only found %d items in: %s", res, magic); + result = FALSE; + goto bail; + } + + CRM_CHECK(decode_transition_key(key, uuid, transition_id, action_id, target_rc), result = FALSE; + goto bail;); + bail: crm_free(key); return result; } char * generate_transition_key(int transition_id, int action_id, int target_rc, const char *node) { int len = 40; char *fail_state = NULL; CRM_CHECK(node != NULL, return NULL); - + len += strlen(node); - + crm_malloc0(fail_state, len); - if(fail_state != NULL) { - snprintf(fail_state, len, "%d:%d:%d:%s", - action_id, transition_id, target_rc, node); + if (fail_state != NULL) { + snprintf(fail_state, len, "%d:%d:%d:%s", action_id, transition_id, target_rc, node); } return fail_state; } - gboolean -decode_transition_key( - const char *key, char **uuid, int *transition_id, int *action_id, int *target_rc) +decode_transition_key(const char *key, char **uuid, int *transition_id, int *action_id, + int *target_rc) { int res = 0; gboolean done = FALSE; CRM_CHECK(uuid != NULL, return FALSE); CRM_CHECK(target_rc != NULL, return FALSE); CRM_CHECK(action_id != NULL, return FALSE); CRM_CHECK(transition_id != NULL, return FALSE); - - crm_malloc0(*uuid, strlen(key)+1); + + crm_malloc0(*uuid, strlen(key) + 1); res = sscanf(key, "%d:%d:%d:%s", action_id, transition_id, target_rc, *uuid); - switch(res) { - case 4: - /* Post Pacemaker 0.6 */ - done = TRUE; - break; - case 3: - case 2: - /* this can be tricky - the UUID might start with an integer */ - - /* Until Pacemaker 0.6 */ - done = TRUE; - *target_rc = -1; - res = sscanf(key, "%d:%d:%s", action_id, transition_id, *uuid); - if(res == 2) { - *action_id = -1; - res = sscanf(key, "%d:%s", transition_id, *uuid); - CRM_CHECK(res == 2, done = FALSE); - - } else if(res != 3) { - CRM_CHECK(res == 3, done = FALSE); - } - break; - - case 1: - /* Prior to Heartbeat 2.0.8 */ - done = TRUE; - *action_id = -1; - *target_rc = -1; - res = sscanf(key, "%d:%s", transition_id, *uuid); - CRM_CHECK(res == 2, done = FALSE); - break; - default: - crm_crit("Unhandled sscanf result (%d) for %s", res, key); - - } - - if(strlen(*uuid) != 36) { - crm_warn("Bad UUID (%s) in sscanf result (%d) for %s", *uuid, res, key); - } - - if(done == FALSE) { - crm_err("Cannot decode '%s' rc=%d", key, res); - - crm_free(*uuid); - *uuid = NULL; - *target_rc = -1; - *action_id = -1; - *transition_id = -1; - } - + switch (res) { + case 4: + /* Post Pacemaker 0.6 */ + done = TRUE; + break; + case 3: + case 2: + /* this can be tricky - the UUID might start with an integer */ + + /* Until Pacemaker 0.6 */ + done = TRUE; + *target_rc = -1; + res = sscanf(key, "%d:%d:%s", action_id, transition_id, *uuid); + if (res == 2) { + *action_id = -1; + res = sscanf(key, "%d:%s", transition_id, *uuid); + CRM_CHECK(res == 2, done = FALSE); + + } else if (res != 3) { + CRM_CHECK(res == 3, done = FALSE); + } + break; + + case 1: + /* Prior to Heartbeat 2.0.8 */ + done = TRUE; + *action_id = -1; + *target_rc = -1; + res = sscanf(key, "%d:%s", transition_id, *uuid); + CRM_CHECK(res == 2, done = FALSE); + break; + default: + crm_crit("Unhandled sscanf result (%d) for %s", res, key); + + } + + if (strlen(*uuid) != 36) { + crm_warn("Bad UUID (%s) in sscanf result (%d) for %s", *uuid, res, key); + } + + if (done == FALSE) { + crm_err("Cannot decode '%s' rc=%d", key, res); + + crm_free(*uuid); + *uuid = NULL; + *target_rc = -1; + *action_id = -1; + *transition_id = -1; + } + return done; } void -filter_action_parameters(xmlNode *param_set, const char *version) +filter_action_parameters(xmlNode * param_set, const char *version) { char *key = NULL; char *timeout = NULL; char *interval = NULL; - + const char *attr_filter[] = { - XML_ATTR_ID, - XML_ATTR_CRM_VERSION, - XML_LRM_ATTR_OP_DIGEST, + XML_ATTR_ID, + XML_ATTR_CRM_VERSION, + XML_LRM_ATTR_OP_DIGEST, }; gboolean do_delete = FALSE; int lpc = 0; static int meta_len = 0; - if(meta_len == 0) { - meta_len = strlen(CRM_META); - } - - if(param_set == NULL) { - return; + + if (meta_len == 0) { + meta_len = strlen(CRM_META); + } + + if (param_set == NULL) { + return; } - for(lpc = 0; lpc < DIMOF(attr_filter); lpc++) { - xml_remove_prop(param_set, attr_filter[lpc]); + for (lpc = 0; lpc < DIMOF(attr_filter); lpc++) { + xml_remove_prop(param_set, attr_filter[lpc]); } key = crm_meta_name(XML_LRM_ATTR_INTERVAL); interval = crm_element_value_copy(param_set, key); crm_free(key); key = crm_meta_name(XML_ATTR_TIMEOUT); timeout = crm_element_value_copy(param_set, key); - if(param_set) { + if (param_set) { xmlAttrPtr xIter = param_set->properties; - while(xIter) { + + while (xIter) { const char *prop_name = (const char *)xIter->name; - xIter = xIter->next; - do_delete = FALSE; - if(strncasecmp(prop_name, CRM_META, meta_len) == 0) { - do_delete = TRUE; - } - if(do_delete) { - xml_remove_prop(param_set, prop_name); - } + xIter = xIter->next; + do_delete = FALSE; + if (strncasecmp(prop_name, CRM_META, meta_len) == 0) { + do_delete = TRUE; + } + + if (do_delete) { + xml_remove_prop(param_set, prop_name); + } } } - if(crm_get_msec(interval) > 0 && compare_version(version, "1.0.8") > 0) { - /* Re-instate the operation's timeout value */ - if(timeout != NULL) { - crm_xml_add(param_set, key, timeout); - } + if (crm_get_msec(interval) > 0 && compare_version(version, "1.0.8") > 0) { + /* Re-instate the operation's timeout value */ + if (timeout != NULL) { + crm_xml_add(param_set, key, timeout); + } } crm_free(interval); crm_free(timeout); crm_free(key); } void -filter_reload_parameters(xmlNode *param_set, const char *restart_string) +filter_reload_parameters(xmlNode * param_set, const char *restart_string) { int len = 0; char *name = NULL; char *match = NULL; - - if(param_set == NULL) { - return; + + if (param_set == NULL) { + return; } - if(param_set) { + if (param_set) { xmlAttrPtr xIter = param_set->properties; - while(xIter) { + + while (xIter) { const char *prop_name = (const char *)xIter->name; - xIter = xIter->next; - name = NULL; - len = strlen(prop_name) + 3; - crm_malloc0(name, len); - sprintf(name, " %s ", prop_name); - name[len-1] = 0; - - match = strstr(restart_string, name); - if(match == NULL) { - crm_debug_3("%s not found in %s", - prop_name, restart_string); - xml_remove_prop(param_set, prop_name); - } - crm_free(name); + xIter = xIter->next; + name = NULL; + len = strlen(prop_name) + 3; + + crm_malloc0(name, len); + sprintf(name, " %s ", prop_name); + name[len - 1] = 0; + + match = strstr(restart_string, name); + if (match == NULL) { + crm_debug_3("%s not found in %s", prop_name, restart_string); + xml_remove_prop(param_set, prop_name); + } + crm_free(name); } } } void crm_abort(const char *file, const char *function, int line, - const char *assert_condition, gboolean do_core, gboolean do_fork) + const char *assert_condition, gboolean do_core, gboolean do_fork) { int rc = 0; int pid = 0; int status = 0; - if(do_core == FALSE) { - do_crm_log(LOG_ERR, "%s: Triggered assert at %s:%d : %s", - function, file, line, assert_condition); - return; + if (do_core == FALSE) { + do_crm_log(LOG_ERR, "%s: Triggered assert at %s:%d : %s", + function, file, line, assert_condition); + return; - } else if(do_fork) { - pid=fork(); + } else if (do_fork) { + pid = fork(); } else { - do_crm_log(LOG_ERR, "%s: Triggered fatal assert at %s:%d : %s", - function, file, line, assert_condition); - } - - switch(pid) { - case -1: - do_crm_log(LOG_CRIT, "%s: Cannot create core for non-fatal assert at %s:%d : %s", - function, file, line, assert_condition); - return; - - case 0: /* Child */ - abort(); - break; - - default: /* Parent */ - do_crm_log(LOG_ERR, - "%s: Forked child %d to record non-fatal assert at %s:%d : %s", - function, pid, file, line, assert_condition); - do { - rc = waitpid(pid, &status, 0); - if(rc < 0 && errno != EINTR) { - crm_perror(LOG_ERR,"%s: Cannot wait on forked child %d", function, pid); - } - - } while(rc < 0 && errno == EINTR); - - return; + do_crm_log(LOG_ERR, "%s: Triggered fatal assert at %s:%d : %s", + function, file, line, assert_condition); + } + + switch (pid) { + case -1: + do_crm_log(LOG_CRIT, "%s: Cannot create core for non-fatal assert at %s:%d : %s", + function, file, line, assert_condition); + return; + + case 0: /* Child */ + abort(); + break; + + default: /* Parent */ + do_crm_log(LOG_ERR, + "%s: Forked child %d to record non-fatal assert at %s:%d : %s", + function, pid, file, line, assert_condition); + do { + rc = waitpid(pid, &status, 0); + if (rc < 0 && errno != EINTR) { + crm_perror(LOG_ERR, "%s: Cannot wait on forked child %d", function, pid); + } + + } while (rc < 0 && errno == EINTR); + + return; } } char * -generate_series_filename( - const char *directory, const char *series, int sequence, gboolean bzip) +generate_series_filename(const char *directory, const char *series, int sequence, gboolean bzip) { int len = 40; char *filename = NULL; const char *ext = "raw"; - CRM_CHECK(directory != NULL, return NULL); + CRM_CHECK(directory != NULL, return NULL); CRM_CHECK(series != NULL, return NULL); - + len += strlen(directory); len += strlen(series); crm_malloc0(filename, len); CRM_CHECK(filename != NULL, return NULL); - if(bzip) { - ext = "bz2"; + if (bzip) { + ext = "bz2"; } sprintf(filename, "%s/%s-%d.%s", directory, series, sequence, ext); - + return filename; } int get_last_sequence(const char *directory, const char *series) { FILE *file_strm = NULL; int start = 0, length = 0, read_len = 0; char *series_file = NULL; char *buffer = NULL; int seq = 0; int len = 36; - CRM_CHECK(directory != NULL, return 0); + CRM_CHECK(directory != NULL, return 0); CRM_CHECK(series != NULL, return 0); - + len += strlen(directory); len += strlen(series); crm_malloc0(series_file, len); CRM_CHECK(series_file != NULL, return 0); sprintf(series_file, "%s/%s.last", directory, series); - + file_strm = fopen(series_file, "r"); - if(file_strm == NULL) { - crm_debug("Series file %s does not exist", series_file); - crm_free(series_file); - return 0; + if (file_strm == NULL) { + crm_debug("Series file %s does not exist", series_file); + crm_free(series_file); + return 0; } - + /* see how big the file is */ - start = ftell(file_strm); + start = ftell(file_strm); fseek(file_strm, 0L, SEEK_END); length = ftell(file_strm); fseek(file_strm, 0L, start); - + CRM_ASSERT(length >= 0); CRM_ASSERT(start == ftell(file_strm)); - if(length <= 0) { - crm_info("%s was not valid", series_file); - crm_free(buffer); - buffer = NULL; + if (length <= 0) { + crm_info("%s was not valid", series_file); + crm_free(buffer); + buffer = NULL; } else { - crm_debug_3("Reading %d bytes from file", length); - crm_malloc0(buffer, (length+1)); - read_len = fread(buffer, 1, length, file_strm); - if(read_len != length) { - crm_err("Calculated and read bytes differ: %d vs. %d", - length, read_len); - crm_free(buffer); - buffer = NULL; - } - } - + crm_debug_3("Reading %d bytes from file", length); + crm_malloc0(buffer, (length + 1)); + read_len = fread(buffer, 1, length, file_strm); + if (read_len != length) { + crm_err("Calculated and read bytes differ: %d vs. %d", length, read_len); + crm_free(buffer); + buffer = NULL; + } + } + crm_free(series_file); seq = crm_parse_int(buffer, "0"); crm_free(buffer); fclose(file_strm); return seq; } void -write_last_sequence( - const char *directory, const char *series, int sequence, int max) +write_last_sequence(const char *directory, const char *series, int sequence, int max) { int rc = 0; int len = 36; FILE *file_strm = NULL; char *series_file = NULL; - CRM_CHECK(directory != NULL, return); + CRM_CHECK(directory != NULL, return); CRM_CHECK(series != NULL, return); - if(max == 0) { - return; + if (max == 0) { + return; } - while(max > 0 && sequence > max) { - sequence -= max; + while (max > 0 && sequence > max) { + sequence -= max; } - + len += strlen(directory); len += strlen(series); crm_malloc0(series_file, len); sprintf(series_file, "%s/%s.last", directory, series); - + file_strm = fopen(series_file, "w"); - if(file_strm == NULL) { - crm_err("Cannout open series file %s for writing", series_file); - goto bail; + if (file_strm == NULL) { + crm_err("Cannout open series file %s for writing", series_file); + goto bail; } rc = fprintf(file_strm, "%d", sequence); - if(rc < 0) { - crm_perror(LOG_ERR,"Cannot write to series file %s", series_file); + if (rc < 0) { + crm_perror(LOG_ERR, "Cannot write to series file %s", series_file); } bail: - if(file_strm != NULL) { - fflush(file_strm); - fclose(file_strm); + if (file_strm != NULL) { + fflush(file_strm); + fclose(file_strm); } - + crm_free(series_file); } #define LOCKSTRLEN 11 -int crm_pid_active(long pid) +int +crm_pid_active(long pid) { - if(pid <= 0) { - return -1; + if (pid <= 0) { + return -1; } else if (kill(pid, 0) < 0 && errno == ESRCH) { - return 0; + return 0; } - #ifndef HAVE_PROC_PID return 1; #else { - int rc = 0; - int running = 0; - char proc_path[PATH_MAX], exe_path[PATH_MAX], myexe_path[PATH_MAX]; - - /* check to make sure pid hasn't been reused by another process */ - snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", pid); - - rc = readlink(proc_path, exe_path, PATH_MAX-1); - if(rc < 0) { - crm_perror(LOG_ERR, "Could not read from %s", proc_path); - goto bail; - } - - exe_path[rc] = 0; - snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", (long unsigned int)getpid()); - rc = readlink(proc_path, myexe_path, PATH_MAX-1); - if(rc < 0) { - crm_perror(LOG_ERR, "Could not read from %s", proc_path); - goto bail; - } - - myexe_path[rc] = 0; - if(strcmp(exe_path, myexe_path) == 0) { - running = 1; - } - } - + int rc = 0; + int running = 0; + char proc_path[PATH_MAX], exe_path[PATH_MAX], myexe_path[PATH_MAX]; + + /* check to make sure pid hasn't been reused by another process */ + snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", pid); + + rc = readlink(proc_path, exe_path, PATH_MAX - 1); + if (rc < 0) { + crm_perror(LOG_ERR, "Could not read from %s", proc_path); + goto bail; + } + + exe_path[rc] = 0; + snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", (long unsigned int)getpid()); + rc = readlink(proc_path, myexe_path, PATH_MAX - 1); + if (rc < 0) { + crm_perror(LOG_ERR, "Could not read from %s", proc_path); + goto bail; + } + + myexe_path[rc] = 0; + if (strcmp(exe_path, myexe_path) == 0) { + running = 1; + } + } + bail: return running; #endif } - int crm_read_pidfile(const char *filename) { int fd; long pid = -1; - char buf[LOCKSTRLEN+1]; + char buf[LOCKSTRLEN + 1]; + if ((fd = open(filename, O_RDONLY)) < 0) { - goto bail; + goto bail; } - + if (read(fd, buf, sizeof(buf)) < 1) { - goto bail; - } - + goto bail; + } + if (sscanf(buf, "%lu", &pid) > 0) { - if (pid <= 0){ - pid = -LSB_STATUS_STOPPED; - } + if (pid <= 0) { + pid = -LSB_STATUS_STOPPED; + } } - + bail: - if(fd >= 0) { close(fd); } + if (fd >= 0) { + close(fd); + } return pid; } int crm_lock_pidfile(const char *filename) { struct stat sbuf; int fd = 0, rc = 0; long pid = 0, mypid = 0; - char lf_name[256], tf_name[256], buf[LOCKSTRLEN+1]; + char lf_name[256], tf_name[256], buf[LOCKSTRLEN + 1]; - mypid = (unsigned long) getpid(); - snprintf(lf_name, sizeof(lf_name), "%s",filename); + mypid = (unsigned long)getpid(); + snprintf(lf_name, sizeof(lf_name), "%s", filename); snprintf(tf_name, sizeof(tf_name), "%s.%lu", filename, mypid); - + if ((fd = open(lf_name, O_RDONLY)) >= 0) { - if (fstat(fd, &sbuf) >= 0 && sbuf.st_size < LOCKSTRLEN) { - sleep(1); /* if someone was about to create one, - * give'm a sec to do so - * Though if they follow our protocol, - * this won't happen. They should really - * put the pid in, then link, not the - * other way around. - */ - } - if (read(fd, buf, sizeof(buf)) > 0) { - if (sscanf(buf, "%lu", &pid) > 0) { - if (pid > 1 && pid != getpid() && crm_pid_active(pid)) { - /* locked by existing process - give up */ - close(fd); - return -1; - } - } - } - unlink(lf_name); - close(fd); - } - + if (fstat(fd, &sbuf) >= 0 && sbuf.st_size < LOCKSTRLEN) { + sleep(1); /* if someone was about to create one, + * give'm a sec to do so + * Though if they follow our protocol, + * this won't happen. They should really + * put the pid in, then link, not the + * other way around. + */ + } + if (read(fd, buf, sizeof(buf)) > 0) { + if (sscanf(buf, "%lu", &pid) > 0) { + if (pid > 1 && pid != getpid() && crm_pid_active(pid)) { + /* locked by existing process - give up */ + close(fd); + return -1; + } + } + } + unlink(lf_name); + close(fd); + } + if ((fd = open(tf_name, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) { - /* Hmmh, why did we fail? Anyway, nothing we can do about it */ - return -3; + /* Hmmh, why did we fail? Anyway, nothing we can do about it */ + return -3; } /* Slight overkill with the %*d format ;-) */ - snprintf(buf, sizeof(buf), "%*lu\n", LOCKSTRLEN-1, mypid); + snprintf(buf, sizeof(buf), "%*lu\n", LOCKSTRLEN - 1, mypid); if (write(fd, buf, LOCKSTRLEN) != LOCKSTRLEN) { - /* Again, nothing we can do about this */ - rc = -3; - close(fd); - goto out; + /* Again, nothing we can do about this */ + rc = -3; + close(fd); + goto out; } close(fd); switch (link(tf_name, lf_name)) { - case 0: - if (stat(tf_name, &sbuf) < 0) { - /* something weird happened */ - rc = -3; + case 0: + if (stat(tf_name, &sbuf) < 0) { + /* something weird happened */ + rc = -3; - } else if (sbuf.st_nlink < 2) { - /* somehow, it didn't get through - NFS trouble? */ - rc = -2; + } else if (sbuf.st_nlink < 2) { + /* somehow, it didn't get through - NFS trouble? */ + rc = -2; - } else { - rc = 0; - } - break; + } else { + rc = 0; + } + break; - case EEXIST: - rc = -1; - break; + case EEXIST: + rc = -1; + break; - default: - rc = -3; + default: + rc = -3; } out: unlink(tf_name); return rc; } void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile) { long pid; const char *devnull = "/dev/null"; - if(daemonize == FALSE) { - return; + if (daemonize == FALSE) { + return; } - + pid = fork(); if (pid < 0) { - fprintf(stderr, "%s: could not start daemon\n", name); - crm_perror(LOG_ERR,"fork"); - exit(LSB_EXIT_GENERIC); + fprintf(stderr, "%s: could not start daemon\n", name); + crm_perror(LOG_ERR, "fork"); + exit(LSB_EXIT_GENERIC); } else if (pid > 0) { - exit(LSB_EXIT_OK); + exit(LSB_EXIT_OK); } - if (crm_lock_pidfile(pidfile) < 0 ) { - pid = crm_read_pidfile(pidfile); - if(crm_pid_active(pid) > 0) { - crm_warn("%s: already running [pid %ld] (%s).\n", name, pid, pidfile); - exit(LSB_EXIT_OK); - } + if (crm_lock_pidfile(pidfile) < 0) { + pid = crm_read_pidfile(pidfile); + if (crm_pid_active(pid) > 0) { + crm_warn("%s: already running [pid %ld] (%s).\n", name, pid, pidfile); + exit(LSB_EXIT_OK); + } } - + umask(022); close(STDIN_FILENO); - (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ + (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ close(STDOUT_FILENO); - (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ + (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ close(STDERR_FILENO); - (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ + (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ } gboolean crm_is_writable(const char *dir, const char *file, - const char *user, const char *group, gboolean need_both) + const char *user, const char *group, gboolean need_both) { int s_res = -1; struct stat buf; char *full_file = NULL; const char *target = NULL; - + gboolean pass = TRUE; gboolean readwritable = FALSE; CRM_ASSERT(dir != NULL); - if(file != NULL) { - full_file = crm_concat(dir, file, '/'); - target = full_file; - s_res = stat(full_file, &buf); - if( s_res == 0 && S_ISREG(buf.st_mode) == FALSE ) { - crm_err("%s must be a regular file", target); - pass = FALSE; - goto out; - } - } - + if (file != NULL) { + full_file = crm_concat(dir, file, '/'); + target = full_file; + s_res = stat(full_file, &buf); + if (s_res == 0 && S_ISREG(buf.st_mode) == FALSE) { + crm_err("%s must be a regular file", target); + pass = FALSE; + goto out; + } + } + if (s_res != 0) { - target = dir; - s_res = stat(dir, &buf); - if(s_res != 0) { - crm_err("%s must exist and be a directory", dir); - pass = FALSE; - goto out; - - } else if( S_ISDIR(buf.st_mode) == FALSE ) { - crm_err("%s must be a directory", dir); - pass = FALSE; - } - } - - if(user) { - struct passwd *sys_user = NULL; - sys_user = getpwnam(user); - readwritable = (sys_user != NULL - && buf.st_uid == sys_user->pw_uid - && (buf.st_mode & (S_IRUSR|S_IWUSR))); - if(readwritable == FALSE) { - crm_err("%s must be owned and r/w by user %s", - target, user); - if(need_both) { - pass = FALSE; - } - } - } - - if(group) { - struct group *sys_grp = getgrnam(group); - readwritable = ( - sys_grp != NULL - && buf.st_gid == sys_grp->gr_gid - && (buf.st_mode & (S_IRGRP|S_IWGRP))); - if(readwritable == FALSE) { - if(need_both || user == NULL) { - pass = FALSE; - crm_err("%s must be owned and r/w by group %s", - target, group); - } else { - crm_warn("%s should be owned and r/w by group %s", - target, group); - } - } + target = dir; + s_res = stat(dir, &buf); + if (s_res != 0) { + crm_err("%s must exist and be a directory", dir); + pass = FALSE; + goto out; + + } else if (S_ISDIR(buf.st_mode) == FALSE) { + crm_err("%s must be a directory", dir); + pass = FALSE; + } + } + + if (user) { + struct passwd *sys_user = NULL; + + sys_user = getpwnam(user); + readwritable = (sys_user != NULL + && buf.st_uid == sys_user->pw_uid && (buf.st_mode & (S_IRUSR | S_IWUSR))); + if (readwritable == FALSE) { + crm_err("%s must be owned and r/w by user %s", target, user); + if (need_both) { + pass = FALSE; + } + } + } + + if (group) { + struct group *sys_grp = getgrnam(group); + + readwritable = (sys_grp != NULL + && buf.st_gid == sys_grp->gr_gid && (buf.st_mode & (S_IRGRP | S_IWGRP))); + if (readwritable == FALSE) { + if (need_both || user == NULL) { + pass = FALSE; + crm_err("%s must be owned and r/w by group %s", target, group); + } else { + crm_warn("%s should be owned and r/w by group %s", target, group); + } + } } out: crm_free(full_file); return pass; } -static unsigned long long crm_bit_filter = 0; /* 0x00000002ULL; */ +static unsigned long long crm_bit_filter = 0; /* 0x00000002ULL; */ static unsigned int bit_log_level = LOG_DEBUG_5; long long crm_clear_bit(const char *function, long long word, long long bit) { unsigned int level = bit_log_level; - if(bit & crm_bit_filter) { - level = LOG_ERR; + + if (bit & crm_bit_filter) { + level = LOG_ERR; } do_crm_log_unlikely(level, "Bit 0x%.16llx cleared by %s", bit, function); word &= ~bit; return word; } long long crm_set_bit(const char *function, long long word, long long bit) { unsigned int level = bit_log_level; - if(bit & crm_bit_filter) { - level = LOG_ERR; + + if (bit & crm_bit_filter) { + level = LOG_ERR; } do_crm_log_unlikely(level, "Bit 0x%.16llx set by %s", bit, function); word |= bit; return word; } -gboolean crm_str_eq(const char *a, const char *b, gboolean use_case) +gboolean +crm_str_eq(const char *a, const char *b, gboolean use_case) { - if(a == b) { - return TRUE; - - } else if(a == NULL || b == NULL) { - /* shouldn't be comparing NULLs */ - return FALSE; - - } else if(use_case && a[0] != b[0]) { - return FALSE; - - } else if(strcasecmp(a, b) == 0) { - return TRUE; + if (a == b) { + return TRUE; + + } else if (a == NULL || b == NULL) { + /* shouldn't be comparing NULLs */ + return FALSE; + + } else if (use_case && a[0] != b[0]) { + return FALSE; + + } else if (strcasecmp(a, b) == 0) { + return TRUE; } return FALSE; } -char *crm_meta_name(const char *field) +char * +crm_meta_name(const char *field) { int lpc = 0; int max = 0; char *crm_name = NULL; CRM_CHECK(field != NULL, return NULL); crm_name = crm_concat(CRM_META, field, '_'); - /* Massage the names so they can be used as shell variables */ + /* Massage the names so they can be used as shell variables */ max = strlen(crm_name); - for(; lpc < max; lpc++) { - switch(crm_name[lpc]) { - case '-': - crm_name[lpc] = '_'; - break; - } + for (; lpc < max; lpc++) { + switch (crm_name[lpc]) { + case '-': + crm_name[lpc] = '_'; + break; + } } return crm_name; } -const char *crm_meta_value(GHashTable *hash, const char *field) +const char * +crm_meta_value(GHashTable * hash, const char *field) { char *key = NULL; const char *value = NULL; key = crm_meta_name(field); - if(key) { - value = g_hash_table_lookup(hash, key); - crm_free(key); + if (key) { + value = g_hash_table_lookup(hash, key); + crm_free(key); } - + return value; } static struct crm_option *crm_long_options = NULL; static const char *crm_app_description = NULL; static const char *crm_short_options = NULL; static const char *crm_app_usage = NULL; -static struct option *crm_create_long_opts(struct crm_option *long_options) +static struct option * +crm_create_long_opts(struct crm_option *long_options) { struct option *long_opts = NULL; #ifdef HAVE_GETOPT_H int index = 0, lpc = 0; /* * A previous, possibly poor, choice of '?' as the short form of --help * means that getopt_long() returns '?' for both --help and for "unknown option" * * This dummy entry allows us to differentiate between the two in crm_get_option() * and exit with the correct error code */ - crm_realloc(long_opts, (index+1) * sizeof(struct option)); + crm_realloc(long_opts, (index + 1) * sizeof(struct option)); long_opts[index].name = "__dummmy__"; long_opts[index].has_arg = 0; long_opts[index].flag = 0; long_opts[index].val = '_'; index++; - - for(lpc = 0; long_options[lpc].name != NULL; lpc++) { - if(long_options[lpc].name[0] == '-') { - continue; - } - - crm_realloc(long_opts, (index+1) * sizeof(struct option)); - /*fprintf(stderr, "Creating %d %s = %c\n", index, - * long_options[lpc].name, long_options[lpc].val); */ - long_opts[index].name = long_options[lpc].name; - long_opts[index].has_arg = long_options[lpc].has_arg; - long_opts[index].flag = long_options[lpc].flag; - long_opts[index].val = long_options[lpc].val; - index++; + + for (lpc = 0; long_options[lpc].name != NULL; lpc++) { + if (long_options[lpc].name[0] == '-') { + continue; + } + + crm_realloc(long_opts, (index + 1) * sizeof(struct option)); + /*fprintf(stderr, "Creating %d %s = %c\n", index, + * long_options[lpc].name, long_options[lpc].val); */ + long_opts[index].name = long_options[lpc].name; + long_opts[index].has_arg = long_options[lpc].has_arg; + long_opts[index].flag = long_options[lpc].flag; + long_opts[index].val = long_options[lpc].val; + index++; } /* Now create the list terminator */ - crm_realloc(long_opts, (index+1) * sizeof(struct option)); + crm_realloc(long_opts, (index + 1) * sizeof(struct option)); long_opts[index].name = NULL; long_opts[index].has_arg = 0; long_opts[index].flag = 0; long_opts[index].val = 0; #endif - + return long_opts; } -void crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options, const char *app_desc) -{ - if(short_options) { - crm_short_options = short_options; - - } else if(long_options) { - int lpc = 0; - int opt_string_len = 0; - char *local_short_options = NULL; - - for(lpc = 0; long_options[lpc].name != NULL; lpc++) { - if(long_options[lpc].val) { - crm_realloc(local_short_options, opt_string_len + 3); - local_short_options[opt_string_len++] = long_options[lpc].val; - if(long_options[lpc].has_arg == required_argument) { - local_short_options[opt_string_len++] = ':'; - } - local_short_options[opt_string_len] = 0; - } - } - crm_short_options = local_short_options; - crm_trace("Generated short option string: '%s'", local_short_options); +void +crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options, + const char *app_desc) +{ + if (short_options) { + crm_short_options = short_options; + + } else if (long_options) { + int lpc = 0; + int opt_string_len = 0; + char *local_short_options = NULL; + + for (lpc = 0; long_options[lpc].name != NULL; lpc++) { + if (long_options[lpc].val) { + crm_realloc(local_short_options, opt_string_len + 3); + local_short_options[opt_string_len++] = long_options[lpc].val; + if (long_options[lpc].has_arg == required_argument) { + local_short_options[opt_string_len++] = ':'; + } + local_short_options[opt_string_len] = 0; + } + } + crm_short_options = local_short_options; + crm_trace("Generated short option string: '%s'", local_short_options); } - - if(long_options) { - crm_long_options = long_options; + + if (long_options) { + crm_long_options = long_options; } - if(app_desc) { - crm_app_description = app_desc; + if (app_desc) { + crm_app_description = app_desc; } - if(app_usage) { - crm_app_usage = app_usage; + if (app_usage) { + crm_app_usage = app_usage; } } -int crm_get_option(int argc, char **argv, int *index) +int +crm_get_option(int argc, char **argv, int *index) { #ifdef HAVE_GETOPT_H static struct option *long_opts = NULL; - if(long_opts == NULL && crm_long_options) { - long_opts = crm_create_long_opts(crm_long_options); - } - - if(long_opts) { - int flag = getopt_long(argc, argv, crm_short_options, long_opts, index); - switch(flag) { - case 0: return long_opts[*index].val; - case -1: /* End of option processing */ break; - case ':': crm_debug_2("Missing argument"); crm_help('?', 1); break; - case '?': crm_help('?', *index?0:1); break; - } - return flag; + + if (long_opts == NULL && crm_long_options) { + long_opts = crm_create_long_opts(crm_long_options); + } + + if (long_opts) { + int flag = getopt_long(argc, argv, crm_short_options, long_opts, index); + + switch (flag) { + case 0: + return long_opts[*index].val; + case -1: /* End of option processing */ + break; + case ':': + crm_debug_2("Missing argument"); + crm_help('?', 1); + break; + case '?': + crm_help('?', *index ? 0 : 1); + break; + } + return flag; } #endif - if(crm_short_options) { - return getopt(argc, argv, crm_short_options); + if (crm_short_options) { + return getopt(argc, argv, crm_short_options); } - + return -1; } -void crm_help(char cmd, int exit_code) +void +crm_help(char cmd, int exit_code) { int i = 0; FILE *stream = (exit_code ? stderr : stdout); - if(cmd == 'v' || cmd == '$') { - fprintf(stream, "Pacemaker %s\n", VERSION); - fprintf(stream, "Written by Andrew Beekhof\n"); - goto out; + if (cmd == 'v' || cmd == '$') { + fprintf(stream, "Pacemaker %s\n", VERSION); + fprintf(stream, "Written by Andrew Beekhof\n"); + goto out; } - if(cmd == '!') { - fprintf(stream, "Pacemaker %s (Build: %s): %s\n", VERSION, BUILD_VERSION, CRM_FEATURES); - goto out; + if (cmd == '!') { + fprintf(stream, "Pacemaker %s (Build: %s): %s\n", VERSION, BUILD_VERSION, CRM_FEATURES); + goto out; } - + fprintf(stream, "%s - %s\n", crm_system_name, crm_app_description); - if(crm_app_usage) { - fprintf(stream, "Usage: %s %s\n", crm_system_name, crm_app_usage); + if (crm_app_usage) { + fprintf(stream, "Usage: %s %s\n", crm_system_name, crm_app_usage); } - - if(crm_long_options) { - fprintf(stream, "Options:\n"); - for(i = 0; crm_long_options[i].name != NULL; i++) { - if(crm_long_options[i].flags & pcmk_option_hidden) { - } else if(crm_long_options[i].flags & pcmk_option_paragraph) { - fprintf(stream, "%s\n\n", crm_long_options[i].desc); + if (crm_long_options) { + fprintf(stream, "Options:\n"); + for (i = 0; crm_long_options[i].name != NULL; i++) { + if (crm_long_options[i].flags & pcmk_option_hidden) { - } else if(crm_long_options[i].flags & pcmk_option_example) { - fprintf(stream, "\t#%s\n\n", crm_long_options[i].desc); + } else if (crm_long_options[i].flags & pcmk_option_paragraph) { + fprintf(stream, "%s\n\n", crm_long_options[i].desc); - } else if(crm_long_options[i].val == '-' && crm_long_options[i].desc) { - fprintf(stream, "%s\n", crm_long_options[i].desc); - - } else { + } else if (crm_long_options[i].flags & pcmk_option_example) { + fprintf(stream, "\t#%s\n\n", crm_long_options[i].desc); + + } else if (crm_long_options[i].val == '-' && crm_long_options[i].desc) { + fprintf(stream, "%s\n", crm_long_options[i].desc); + + } else { /* is val printable as char ? */ - if(crm_long_options[i].val <= UCHAR_MAX) { + if (crm_long_options[i].val <= UCHAR_MAX) { fprintf(stream, " -%c,", crm_long_options[i].val); } else { fputs(" ", stream); } - fprintf(stream, " --%s%c%s\t%s\n", crm_long_options[i].name, - crm_long_options[i].has_arg?'=':' ',crm_long_options[i].has_arg?"value":"", - crm_long_options[i].desc?crm_long_options[i].desc:""); - } - } - - } else if(crm_short_options) { - fprintf(stream, "Usage: %s - %s\n", crm_system_name, crm_app_description); - for(i = 0; crm_short_options[i] != 0; i++) { - int has_arg = FALSE; - - if(crm_short_options[i+1] == ':') { - has_arg = TRUE; - } - - fprintf(stream, " -%c %s\n", crm_short_options[i], has_arg?"{value}":""); - if(has_arg) { - i++; - } - } + fprintf(stream, " --%s%c%s\t%s\n", crm_long_options[i].name, + crm_long_options[i].has_arg ? '=' : ' ', + crm_long_options[i].has_arg ? "value" : "", + crm_long_options[i].desc ? crm_long_options[i].desc : ""); + } + } + + } else if (crm_short_options) { + fprintf(stream, "Usage: %s - %s\n", crm_system_name, crm_app_description); + for (i = 0; crm_short_options[i] != 0; i++) { + int has_arg = FALSE; + + if (crm_short_options[i + 1] == ':') { + has_arg = TRUE; + } + + fprintf(stream, " -%c %s\n", crm_short_options[i], has_arg ? "{value}" : ""); + if (has_arg) { + i++; + } + } } fprintf(stream, "\nReport bugs to %s\n", PACKAGE_BUGREPORT); out: - if(exit_code >= 0) { - exit(exit_code); + if (exit_code >= 0) { + exit(exit_code); } } #include <../../tools/attrd.h> -gboolean attrd_update_delegate(IPC_Channel *cluster, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen, const char *user_name) +gboolean +attrd_update_delegate(IPC_Channel * cluster, char command, const char *host, const char *name, + const char *value, const char *section, const char *set, const char *dampen, + const char *user_name) { gboolean success = FALSE; const char *reason = "Cluster connection failed"; /* remap common aliases */ - if(safe_str_eq(section, "reboot")) { - section = XML_CIB_TAG_STATUS; - - } else if(safe_str_eq(section, "forever")) { - section = XML_CIB_TAG_NODES; + if (safe_str_eq(section, "reboot")) { + section = XML_CIB_TAG_STATUS; + + } else if (safe_str_eq(section, "forever")) { + section = XML_CIB_TAG_NODES; } - - if(cluster == NULL) { - reason = "No connection to the cluster"; + + if (cluster == NULL) { + reason = "No connection to the cluster"; } else { - xmlNode *update = create_xml_node(NULL, __FUNCTION__); - crm_xml_add(update, F_TYPE, T_ATTRD); - crm_xml_add(update, F_ORIG, crm_system_name); - - if(name == NULL && command == 'U') { - command = 'R'; - } - - switch(command) { - case 'D': - case 'U': - case 'v': - crm_xml_add(update, F_ATTRD_TASK, "update"); - crm_xml_add(update, F_ATTRD_ATTRIBUTE, name); - break; - case 'R': - crm_xml_add(update, F_ATTRD_TASK, "refresh"); - break; - case 'q': - crm_xml_add(update, F_ATTRD_TASK, "query"); - break; - } - - crm_xml_add(update, F_ATTRD_VALUE, value); - crm_xml_add(update, F_ATTRD_DAMPEN, dampen); - crm_xml_add(update, F_ATTRD_SECTION, section); - crm_xml_add(update, F_ATTRD_HOST, host); - crm_xml_add(update, F_ATTRD_SET, set); + xmlNode *update = create_xml_node(NULL, __FUNCTION__); + + crm_xml_add(update, F_TYPE, T_ATTRD); + crm_xml_add(update, F_ORIG, crm_system_name); + + if (name == NULL && command == 'U') { + command = 'R'; + } + + switch (command) { + case 'D': + case 'U': + case 'v': + crm_xml_add(update, F_ATTRD_TASK, "update"); + crm_xml_add(update, F_ATTRD_ATTRIBUTE, name); + break; + case 'R': + crm_xml_add(update, F_ATTRD_TASK, "refresh"); + break; + case 'q': + crm_xml_add(update, F_ATTRD_TASK, "query"); + break; + } + + crm_xml_add(update, F_ATTRD_VALUE, value); + crm_xml_add(update, F_ATTRD_DAMPEN, dampen); + crm_xml_add(update, F_ATTRD_SECTION, section); + crm_xml_add(update, F_ATTRD_HOST, host); + crm_xml_add(update, F_ATTRD_SET, set); #if ENABLE_ACL - if (user_name) { - crm_xml_add(update, F_ATTRD_USER, user_name); - } + if (user_name) { + crm_xml_add(update, F_ATTRD_USER, user_name); + } #endif - success = send_ipc_message(cluster, update); - free_xml(update); + success = send_ipc_message(cluster, update); + free_xml(update); } - - if(success) { - crm_debug("Sent update: %s=%s for %s", name, value, host?host:"localhost"); - return TRUE; + + if (success) { + crm_debug("Sent update: %s=%s for %s", name, value, host ? host : "localhost"); + return TRUE; } - crm_info("Could not send update: %s=%s for %s", name, value, host?host:"localhost"); + crm_info("Could not send update: %s=%s for %s", name, value, host ? host : "localhost"); return FALSE; } -gboolean attrd_lazy_update(char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen) +gboolean +attrd_lazy_update(char command, const char *host, const char *name, const char *value, + const char *section, const char *set, const char *dampen) { int max = 5; gboolean updated = FALSE; static IPC_Channel *cluster = NULL; - while(updated == 0 && max > 0) { - if(cluster == NULL) { - crm_info("Connecting to cluster... %d retries remaining", max); - cluster = init_client_ipc_comms_nodispatch(T_ATTRD); - } - - if(cluster != NULL) { - updated = attrd_update(cluster, command, host, name, value, section, set, dampen); - } - - if(updated == 0) { - cluster = NULL; - sleep(2); - max--; - } else { - crm_info("Updated %s=%s for %s", name, value, host); - } + while (updated == 0 && max > 0) { + if (cluster == NULL) { + crm_info("Connecting to cluster... %d retries remaining", max); + cluster = init_client_ipc_comms_nodispatch(T_ATTRD); + } + + if (cluster != NULL) { + updated = attrd_update(cluster, command, host, name, value, section, set, dampen); + } + + if (updated == 0) { + cluster = NULL; + sleep(2); + max--; + } else { + crm_info("Updated %s=%s for %s", name, value, host); + } } return updated; } -gboolean attrd_update_no_mainloop(int *connection, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen) +gboolean +attrd_update_no_mainloop(int *connection, char command, const char *host, const char *name, + const char *value, const char *section, const char *set, + const char *dampen) { int max = 5; gboolean updated = FALSE; static IPC_Channel *cluster = NULL; - if(connection && *connection == 0 && cluster) { - crm_info("Forcing a new connection to the cluster"); - cluster = NULL; - } - - while(updated == 0 && max > 0) { - if(cluster == NULL) { - crm_info("Connecting to cluster... %d retries remaining", max); - cluster = init_client_ipc_comms_nodispatch(T_ATTRD); - } - - if(connection) { - if(cluster != NULL) { - *connection = cluster->ops->get_recv_select_fd(cluster); - } else { - *connection = 0; - } - } - - if(cluster != NULL) { - updated = attrd_update(cluster, command, host, name, value, section, set, dampen); - } - - if(updated == 0) { - cluster = NULL; - sleep(2); - max--; - } else { - crm_info("Updated %s=%s for %s", name, value, host); - } + if (connection && *connection == 0 && cluster) { + crm_info("Forcing a new connection to the cluster"); + cluster = NULL; + } + + while (updated == 0 && max > 0) { + if (cluster == NULL) { + crm_info("Connecting to cluster... %d retries remaining", max); + cluster = init_client_ipc_comms_nodispatch(T_ATTRD); + } + + if (connection) { + if (cluster != NULL) { + *connection = cluster->ops->get_recv_select_fd(cluster); + } else { + *connection = 0; + } + } + + if (cluster != NULL) { + updated = attrd_update(cluster, command, host, name, value, section, set, dampen); + } + + if (updated == 0) { + cluster = NULL; + sleep(2); + max--; + } else { + crm_info("Updated %s=%s for %s", name, value, host); + } } return updated; } #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" static void -append_digest(lrm_op_t *op, xmlNode *update, const char *version, const char *magic, int level) +append_digest(lrm_op_t * op, xmlNode * update, const char *version, const char *magic, int level) { /* this will enable us to later determine that the * resource's parameters have changed and we should force * a restart */ char *digest = NULL; xmlNode *args_xml = NULL; - if(op->params == NULL) { - return; + if (op->params == NULL) { + return; } - + args_xml = create_xml_node(NULL, XML_TAG_PARAMS); g_hash_table_foreach(op->params, hash2field, args_xml); filter_action_parameters(args_xml, version); digest = calculate_operation_digest(args_xml, version); #if 0 - if(level < crm_log_level - && op->interval == 0 - && crm_str_eq(op->op_type, CRMD_ACTION_START, TRUE)) { - char *digest_source = dump_xml_unformatted(args_xml); - do_crm_log(level, "Calculated digest %s for %s (%s). Source: %s\n", - digest, ID(update), magic, digest_source); - crm_free(digest_source); + if (level < crm_log_level + && op->interval == 0 && crm_str_eq(op->op_type, CRMD_ACTION_START, TRUE)) { + char *digest_source = dump_xml_unformatted(args_xml); + + do_crm_log(level, "Calculated digest %s for %s (%s). Source: %s\n", + digest, ID(update), magic, digest_source); + crm_free(digest_source); } #endif crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest); free_xml(args_xml); crm_free(digest); } int -rsc_op_expected_rc(lrm_op_t *op) +rsc_op_expected_rc(lrm_op_t * op) { int rc = 0; - if(op && op->user_data) { - int dummy = 0; - char *uuid = NULL; - decode_transition_key(op->user_data, &uuid, &dummy, &dummy, &rc); - crm_free(uuid); + + if (op && op->user_data) { + int dummy = 0; + char *uuid = NULL; + + decode_transition_key(op->user_data, &uuid, &dummy, &dummy, &rc); + crm_free(uuid); } return rc; } - gboolean -did_rsc_op_fail(lrm_op_t *op, int target_rc) +did_rsc_op_fail(lrm_op_t * op, int target_rc) { - switch(op->op_status) { - case LRM_OP_CANCELLED: - case LRM_OP_PENDING: - return FALSE; - break; + switch (op->op_status) { + case LRM_OP_CANCELLED: + case LRM_OP_PENDING: + return FALSE; + break; - case LRM_OP_NOTSUPPORTED: - case LRM_OP_TIMEOUT: - case LRM_OP_ERROR: - return TRUE; - break; + case LRM_OP_NOTSUPPORTED: + case LRM_OP_TIMEOUT: + case LRM_OP_ERROR: + return TRUE; + break; - default: - if(target_rc != op->rc) { - return TRUE; - } + default: + if (target_rc != op->rc) { + return TRUE; + } } return FALSE; } xmlNode * -create_operation_update( - xmlNode *parent, lrm_op_t *op, const char *caller_version, int target_rc, const char *origin, int level) +create_operation_update(xmlNode * parent, lrm_op_t * op, const char *caller_version, int target_rc, + const char *origin, int level) { char *key = NULL; char *magic = NULL; char *op_id = NULL; char *local_user_data = NULL; xmlNode *xml_op = NULL; const char *task = NULL; gboolean dc_munges_migrate_ops = (compare_version(caller_version, "3.0.3") < 0); CRM_CHECK(op != NULL, return NULL); do_crm_log(level, "%s: Updating resouce %s after %s %s op (interval=%d)", - origin, op->rsc_id, op_status2text(op->op_status), op->op_type, op->interval); + origin, op->rsc_id, op_status2text(op->op_status), op->op_type, op->interval); - if(op->op_status == LRM_OP_CANCELLED) { - crm_debug_3("Ignoring cancelled op"); - return NULL; + if (op->op_status == LRM_OP_CANCELLED) { + crm_debug_3("Ignoring cancelled op"); + return NULL; } crm_debug_3("DC version: %s", caller_version); task = op->op_type; /* remap the task name under various scenarios * this makes life easier for the PE when its trying determin the current state */ - if(crm_str_eq(task, "reload", TRUE)) { - if(op->op_status == LRM_OP_DONE) { - task = CRMD_ACTION_START; - } else { - task = CRMD_ACTION_STATUS; - } - - } else if(dc_munges_migrate_ops - && crm_str_eq(task, CRMD_ACTION_MIGRATE, TRUE)) { - /* if the migrate_from fails it will have enough info to do the right thing */ - if(op->op_status == LRM_OP_DONE) { - task = CRMD_ACTION_STOP; - } else { - task = CRMD_ACTION_STATUS; - } - - } else if(dc_munges_migrate_ops - && op->op_status == LRM_OP_DONE - && crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) { - task = CRMD_ACTION_START; + if (crm_str_eq(task, "reload", TRUE)) { + if (op->op_status == LRM_OP_DONE) { + task = CRMD_ACTION_START; + } else { + task = CRMD_ACTION_STATUS; + } + + } else if (dc_munges_migrate_ops && crm_str_eq(task, CRMD_ACTION_MIGRATE, TRUE)) { + /* if the migrate_from fails it will have enough info to do the right thing */ + if (op->op_status == LRM_OP_DONE) { + task = CRMD_ACTION_STOP; + } else { + task = CRMD_ACTION_STATUS; + } + + } else if (dc_munges_migrate_ops + && op->op_status == LRM_OP_DONE && crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) { + task = CRMD_ACTION_START; } key = generate_op_key(op->rsc_id, task, op->interval); - if(op->interval > 0) { - op_id = crm_strdup(key); - - } else if(crm_str_eq(task, CRMD_ACTION_NOTIFY, TRUE)) { - const char *n_type = crm_meta_value(op->params, "notify_type"); - const char *n_task = crm_meta_value(op->params, "notify_operation"); - CRM_LOG_ASSERT(n_type != NULL); - CRM_LOG_ASSERT(n_task != NULL); - op_id = generate_notify_key(op->rsc_id, n_type, n_task); - - /* these are not yet allowed to fail */ - op->op_status = LRM_OP_DONE; - op->rc = 0; + if (op->interval > 0) { + op_id = crm_strdup(key); + + } else if (crm_str_eq(task, CRMD_ACTION_NOTIFY, TRUE)) { + const char *n_type = crm_meta_value(op->params, "notify_type"); + const char *n_task = crm_meta_value(op->params, "notify_operation"); + + CRM_LOG_ASSERT(n_type != NULL); + CRM_LOG_ASSERT(n_task != NULL); + op_id = generate_notify_key(op->rsc_id, n_type, n_task); + + /* these are not yet allowed to fail */ + op->op_status = LRM_OP_DONE; + op->rc = 0; } else if (did_rsc_op_fail(op, target_rc)) { - op_id = generate_op_key(op->rsc_id, "last_failure", 0); + op_id = generate_op_key(op->rsc_id, "last_failure", 0); } else { - op_id = generate_op_key(op->rsc_id, "last", 0); + op_id = generate_op_key(op->rsc_id, "last", 0); } xml_op = find_entity(parent, XML_LRM_TAG_RSC_OP, op_id); - if(xml_op == NULL) { - xml_op = create_xml_node(parent, XML_LRM_TAG_RSC_OP); - } - - if(op->user_data == NULL) { - crm_debug("Generating fake transition key for:" - " %s_%s_%d %d from %s", - op->rsc_id, op->op_type, op->interval, op->call_id, - op->app_name); - local_user_data = generate_transition_key(-1, op->call_id, target_rc, FAKE_TE_ID); - op->user_data = local_user_data; - } - + if (xml_op == NULL) { + xml_op = create_xml_node(parent, XML_LRM_TAG_RSC_OP); + } + + if (op->user_data == NULL) { + crm_debug("Generating fake transition key for:" + " %s_%s_%d %d from %s", + op->rsc_id, op->op_type, op->interval, op->call_id, op->app_name); + local_user_data = generate_transition_key(-1, op->call_id, target_rc, FAKE_TE_ID); + op->user_data = local_user_data; + } + magic = generate_transition_magic(op->user_data, op->op_status, op->rc); - crm_xml_add(xml_op, XML_ATTR_ID, op_id); - crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key); - crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task); - crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin); - crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version); - crm_xml_add(xml_op, XML_ATTR_TRANSITION_KEY, op->user_data); - crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic); - - crm_xml_add_int(xml_op, XML_LRM_ATTR_CALLID, op->call_id); - crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc); - crm_xml_add_int(xml_op, XML_LRM_ATTR_OPSTATUS, op->op_status); - crm_xml_add_int(xml_op, XML_LRM_ATTR_INTERVAL, op->interval); - - if(compare_version("2.1", caller_version) <= 0) { - if(op->t_run || op->t_rcchange || op->exec_time || op->queue_time) { - crm_debug_2("Timing data (%s_%s_%d): last=%lu change=%lu exec=%lu queue=%lu", - op->rsc_id, op->op_type, op->interval, - op->t_run, op->t_rcchange, op->exec_time, op->queue_time); - - if(op->interval == 0) { - crm_xml_add_int(xml_op, "last-run", op->t_run); - } - crm_xml_add_int(xml_op, "last-rc-change", op->t_rcchange); - crm_xml_add_int(xml_op, "exec-time", op->exec_time); - crm_xml_add_int(xml_op, "queue-time", op->queue_time); - } - } - - if(crm_str_eq(op->op_type, CRMD_ACTION_MIGRATE, TRUE) - || crm_str_eq(op->op_type, CRMD_ACTION_MIGRATED, TRUE)) { - /* - * Record migrate_source and migrate_target always for migrate ops. - */ - const char *name = XML_LRM_ATTR_MIGRATE_SOURCE; - crm_xml_add(xml_op, name, crm_meta_value(op->params, name)); - - name = XML_LRM_ATTR_MIGRATE_TARGET; - crm_xml_add(xml_op, name, crm_meta_value(op->params, name)); + crm_xml_add(xml_op, XML_ATTR_ID, op_id); + crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key); + crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task); + crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin); + crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version); + crm_xml_add(xml_op, XML_ATTR_TRANSITION_KEY, op->user_data); + crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic); + + crm_xml_add_int(xml_op, XML_LRM_ATTR_CALLID, op->call_id); + crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc); + crm_xml_add_int(xml_op, XML_LRM_ATTR_OPSTATUS, op->op_status); + crm_xml_add_int(xml_op, XML_LRM_ATTR_INTERVAL, op->interval); + + if (compare_version("2.1", caller_version) <= 0) { + if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) { + crm_debug_2("Timing data (%s_%s_%d): last=%lu change=%lu exec=%lu queue=%lu", + op->rsc_id, op->op_type, op->interval, + op->t_run, op->t_rcchange, op->exec_time, op->queue_time); + + if (op->interval == 0) { + crm_xml_add_int(xml_op, "last-run", op->t_run); + } + crm_xml_add_int(xml_op, "last-rc-change", op->t_rcchange); + crm_xml_add_int(xml_op, "exec-time", op->exec_time); + crm_xml_add_int(xml_op, "queue-time", op->queue_time); + } + } + + if (crm_str_eq(op->op_type, CRMD_ACTION_MIGRATE, TRUE) + || crm_str_eq(op->op_type, CRMD_ACTION_MIGRATED, TRUE)) { + /* + * Record migrate_source and migrate_target always for migrate ops. + */ + const char *name = XML_LRM_ATTR_MIGRATE_SOURCE; + + crm_xml_add(xml_op, name, crm_meta_value(op->params, name)); + + name = XML_LRM_ATTR_MIGRATE_TARGET; + crm_xml_add(xml_op, name, crm_meta_value(op->params, name)); } append_digest(op, xml_op, caller_version, magic, LOG_DEBUG); - - if(local_user_data) { - crm_free(local_user_data); - op->user_data = NULL; + + if (local_user_data) { + crm_free(local_user_data); + op->user_data = NULL; } - crm_free(magic); + crm_free(magic); crm_free(op_id); crm_free(key); return xml_op; } void -free_lrm_op(lrm_op_t *op) +free_lrm_op(lrm_op_t * op) { - if(op == NULL) { - return; + if (op == NULL) { + return; } g_hash_table_destroy(op->params); crm_free(op->user_data); crm_free(op->output); crm_free(op->rsc_id); crm_free(op->op_type); crm_free(op->app_name); - crm_free(op); + crm_free(op); } #if ENABLE_ACL void -determine_request_user(char **user, IPC_Channel *channel, xmlNode *request, const char *field) +determine_request_user(char **user, IPC_Channel * channel, xmlNode * request, const char *field) { /* Get our internal validation out of the way first */ CRM_CHECK(user != NULL && channel != NULL && field != NULL, return); - if(*user == NULL) { - /* Figure out who our peer is and cache it... */ - struct passwd *pwent = getpwuid(channel->farside_uid); - if(pwent == NULL) { - crm_perror(LOG_ERR, "Cannot get password entry of uid: %d", channel->farside_uid); - } else { - *user = crm_strdup(pwent->pw_name); - } + if (*user == NULL) { + /* Figure out who our peer is and cache it... */ + struct passwd *pwent = getpwuid(channel->farside_uid); + + if (pwent == NULL) { + crm_perror(LOG_ERR, "Cannot get password entry of uid: %d", channel->farside_uid); + } else { + *user = crm_strdup(pwent->pw_name); + } } /* If our peer is a privileged user, we might be doing something on behalf of someone else */ - if(is_privileged(*user) == FALSE) { - /* We're not a privileged user, set or overwrite any existing value for $field */ - crm_xml_replace(request, field, *user); + if (is_privileged(*user) == FALSE) { + /* We're not a privileged user, set or overwrite any existing value for $field */ + crm_xml_replace(request, field, *user); - } else if(crm_element_value(request, field) == NULL) { - /* Even if we're privileged, make sure there is always a value set */ - crm_xml_replace(request, field, *user); + } else if (crm_element_value(request, field) == NULL) { + /* Even if we're privileged, make sure there is always a value set */ + crm_xml_replace(request, field, *user); /* } else { Legal delegation */ } - + crm_debug_2("Processing msg for user '%s'", crm_element_value(request, field)); } #endif /* * This re-implements g_str_hash as it was prior to glib2-2.28: * * http://git.gnome.org/browse/glib/commit/?id=354d655ba8a54b754cb5a3efb42767327775696c * * Note that the new g_str_hash is presumably a *better* hash (it's actually * a correct implementation of DJB's hash), but we need to preserve existing * behaviour, because the hash key ultimately determines the "sort" order * when iterating through GHashTables, which affects allocation of scores to * clone instances when iterating through rsc->allowed_nodes. It (somehow) * also appears to have some minor impact on the ordering of a few * pseudo_event IDs in the transition graph. */ guint g_str_hash_traditional(gconstpointer v) { const signed char *p; guint32 h = 0; for (p = v; *p != '\0'; p++) - h = (h << 5) - h + *p; + h = (h << 5) - h + *p; return h; } -void *find_library_function(void **handle, const char *lib, const char *fn) +void * +find_library_function(void **handle, const char *lib, const char *fn) { char *error; void *a_function; - - if(*handle == NULL) { - *handle = dlopen (lib, RTLD_LAZY); + + if (*handle == NULL) { + *handle = dlopen(lib, RTLD_LAZY); } - + if (!(*handle)) { - crm_err("Could not open %s: %s", lib, dlerror()); - exit(100); + crm_err("Could not open %s: %s", lib, dlerror()); + exit(100); } - + a_function = dlsym(*handle, fn); - if ((error = dlerror()) != NULL) { - crm_err("Could not find %s in %s: %s", fn, lib, error); - exit(100); + if ((error = dlerror()) != NULL) { + crm_err("Could not find %s in %s: %s", fn, lib, error); + exit(100); } - + return a_function; } -void *convert_const_pointer(const void *ptr) +void * +convert_const_pointer(const void *ptr) { /* Worst function ever */ - return (void*)ptr; + return (void *)ptr; } diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 597039890a..3733e39bb0 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1,1831 +1,1861 @@ /* * Copyright (c) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 /* Add it for compiling on OSX */ +#include /* Add it for compiling on OSX */ #include #include #include #include #include #include CRM_TRACE_INIT_DATA(stonith); -typedef struct stonith_private_s -{ - char *token; - IPC_Channel *command_channel; - IPC_Channel *callback_channel; - GCHSource *callback_source; - GHashTable *stonith_op_callback_table; - GList *notify_list; - - void (*op_callback)( - stonith_t *st, const xmlNode *msg, int call, int rc, xmlNode *output, void *userdata); - +typedef struct stonith_private_s { + char *token; + IPC_Channel *command_channel; + IPC_Channel *callback_channel; + GCHSource *callback_source; + GHashTable *stonith_op_callback_table; + GList *notify_list; + + void (*op_callback) (stonith_t * st, const xmlNode * msg, int call, int rc, xmlNode * output, + void *userdata); + } stonith_private_t; -typedef struct stonith_notify_client_s -{ - const char *event; - const char *obj_id; /* implement one day */ - const char *obj_type; /* implement one day */ - void (*notify)(stonith_t *st, const char *event, xmlNode *msg); - +typedef struct stonith_notify_client_s { + const char *event; + const char *obj_id; /* implement one day */ + const char *obj_type; /* implement one day */ + void (*notify) (stonith_t * st, const char *event, xmlNode * msg); + } stonith_notify_client_t; -typedef struct stonith_callback_client_s -{ - void (*callback)( - stonith_t *st, const xmlNode *msg, int call, int rc, xmlNode *output, void *userdata); - const char *id; - void *user_data; - gboolean only_success; - struct timer_rec_s *timer; - +typedef struct stonith_callback_client_s { + void (*callback) (stonith_t * st, const xmlNode * msg, int call, int rc, xmlNode * output, + void *userdata); + const char *id; + void *user_data; + gboolean only_success; + struct timer_rec_s *timer; + } stonith_callback_client_t; -struct notify_blob_s -{ - stonith_t *stonith; - xmlNode *xml; +struct notify_blob_s { + stonith_t *stonith; + xmlNode *xml; }; -struct timer_rec_s -{ - int call_id; - int timeout; - guint ref; - stonith_t *stonith; +struct timer_rec_s { + int call_id; + int timeout; + guint ref; + stonith_t *stonith; }; -typedef enum stonith_errors (*stonith_op_t)( - const char *, int, const char *, xmlNode *, - xmlNode*, xmlNode*, xmlNode**, xmlNode**); +typedef enum stonith_errors (*stonith_op_t) (const char *, int, const char *, xmlNode *, + xmlNode *, xmlNode *, xmlNode **, xmlNode **); static const char META_TEMPLATE[] = -"\n" -"\n" -"\n" -" 1.0\n" -" \n" -"%s\n" -" \n" -" %s\n" -"%s\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" 2.0\n" -" \n" -"\n"; - -bool stonith_dispatch(stonith_t *st); -gboolean stonith_dispatch_internal(IPC_Channel *channel, gpointer user_data); -void stonith_perform_callback(stonith_t *stonith, xmlNode *msg, int call_id, int rc); -xmlNode *stonith_create_op( - int call_id, const char *token, const char *op, xmlNode *data, int call_options); -int stonith_send_command( - stonith_t *stonith, const char *op, xmlNode *data, - xmlNode **output_data, int call_options, int timeout); + "\n" + "\n" + "\n" + " 1.0\n" + " \n" + "%s\n" + " \n" + " %s\n" + "%s\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " 2.0\n" " \n" "\n"; + +bool stonith_dispatch(stonith_t * st); +gboolean stonith_dispatch_internal(IPC_Channel * channel, gpointer user_data); +void stonith_perform_callback(stonith_t * stonith, xmlNode * msg, int call_id, int rc); +xmlNode *stonith_create_op(int call_id, const char *token, const char *op, xmlNode * data, + int call_options); +int stonith_send_command(stonith_t * stonith, const char *op, xmlNode * data, + xmlNode ** output_data, int call_options, int timeout); static void stonith_connection_destroy(gpointer user_data); static void stonith_send_notification(gpointer data, gpointer user_data); -static void stonith_connection_destroy(gpointer user_data) +static void +stonith_connection_destroy(gpointer user_data) { stonith_t *stonith = user_data; stonith_private_t *native = NULL; struct notify_blob_s blob; blob.stonith = stonith; blob.xml = create_xml_node(NULL, "notify"); native = stonith->private; native->callback_source = NULL; stonith->state = stonith_disconnected; crm_xml_add(blob.xml, F_TYPE, T_STONITH_NOTIFY); crm_xml_add(blob.xml, F_SUBTYPE, T_STONITH_NOTIFY_DISCONNECT); g_list_foreach(native->notify_list, stonith_send_notification, &blob); free_xml(blob.xml); } -static int stonith_api_register_device( - stonith_t *stonith, int call_options, - const char *id, const char *namespace, const char *agent, - stonith_key_value_t *params) +static int +stonith_api_register_device(stonith_t * stonith, int call_options, + const char *id, const char *namespace, const char *agent, + stonith_key_value_t * params) { int rc = 0; xmlNode *data = create_xml_node(NULL, F_STONITH_DEVICE); xmlNode *args = create_xml_node(data, XML_TAG_ATTRS); crm_xml_add(data, XML_ATTR_ID, id); crm_xml_add(data, "origin", __FUNCTION__); crm_xml_add(data, "agent", agent); crm_xml_add(data, "namespace", namespace); - for( ; params; params = params->next ) { - hash2field( (gpointer)params->key, (gpointer)params->value, args ); - } + for (; params; params = params->next) { + hash2field((gpointer) params->key, (gpointer) params->value, args); + } rc = stonith_send_command(stonith, STONITH_OP_DEVICE_ADD, data, NULL, call_options, 0); free_xml(data); - + return rc; } -static int stonith_api_remove_device( - stonith_t *stonith, int call_options, const char *name) +static int +stonith_api_remove_device(stonith_t * stonith, int call_options, const char *name) { int rc = 0; xmlNode *data = NULL; data = create_xml_node(NULL, F_STONITH_DEVICE); crm_xml_add(data, "origin", __FUNCTION__); crm_xml_add(data, XML_ATTR_ID, name); rc = stonith_send_command(stonith, STONITH_OP_DEVICE_DEL, data, NULL, call_options, 0); free_xml(data); - + return rc; } -static void append_arg( - gpointer key, gpointer value, gpointer user_data) +static void +append_arg(gpointer key, gpointer value, gpointer user_data) { - int len = 3; /* =, \n, \0 */ + int len = 3; /* =, \n, \0 */ int last = 0; char **args = user_data; CRM_CHECK(key != NULL, return); CRM_CHECK(value != NULL, return); - if(strstr(key, "pcmk_")) { - return; - } else if(strstr(key, CRM_META)) { - return; - } else if(safe_str_eq(key, "crm_feature_set")) { - return; + if (strstr(key, "pcmk_")) { + return; + } else if (strstr(key, CRM_META)) { + return; + } else if (safe_str_eq(key, "crm_feature_set")) { + return; } - + len += strlen(key); len += strlen(value); - if(*args != NULL) { - last = strlen(*args); + if (*args != NULL) { + last = strlen(*args); } - - crm_realloc(*args, last+len); + + crm_realloc(*args, last + len); crm_debug_2("Appending: %s=%s", (char *)key, (char *)value); - sprintf((*args)+last, "%s=%s\n", (char *)key, (char *)value); + sprintf((*args) + last, "%s=%s\n", (char *)key, (char *)value); } -static void append_const_arg(const char *key, const char *value, char **arg_list) +static void +append_const_arg(const char *key, const char *value, char **arg_list) { char *glib_sucks_key = crm_strdup(key); char *glib_sucks_value = crm_strdup(value); - + append_arg(glib_sucks_key, glib_sucks_value, arg_list); crm_free(glib_sucks_value); crm_free(glib_sucks_key); } -static void append_host_specific_args(const char *victim, const char *map, GHashTable *params, char **arg_list) +static void +append_host_specific_args(const char *victim, const char *map, GHashTable * params, char **arg_list) { char *name = NULL; int last = 0, lpc = 0, max = 0; - if(map == NULL) { - /* The best default there is for now... */ - crm_debug("Using default arg map: port=uname"); - append_const_arg("port", victim, arg_list); - return; + if (map == NULL) { + /* The best default there is for now... */ + crm_debug("Using default arg map: port=uname"); + append_const_arg("port", victim, arg_list); + return; } - + max = strlen(map); crm_debug("Processing arg map: %s", map); - for(; lpc < max + 1; lpc++) { - if(isalpha(map[lpc])) { - /* keep going */ - - } else if(map[lpc] == '=' || map[lpc] == ':') { - crm_free(name); - crm_malloc0(name, 1 + lpc - last); - strncpy(name, map + last, lpc - last); - crm_debug("Got name: %s", name); - last = lpc + 1; - - } else if(map[lpc] == 0 || map[lpc] == ',' || isspace(map[lpc])) { - char *param = NULL; - const char *value = NULL; - - crm_malloc0(param, 1 + lpc - last); - strncpy(param, map + last, lpc - last); - last = lpc + 1; - - crm_debug("Got key: %s", param); - if(name == NULL) { - crm_err("Misparsed '%s', found '%s' without a name", map, param); - crm_free(param); - continue; - } - - if(safe_str_eq(param, "uname")) { - value = victim; - } else { - char *key = crm_meta_name(param); - value = g_hash_table_lookup(params, key); - crm_free(key); - } - - if(value) { - crm_debug("Setting '%s'='%s' (%s) for %s", name, value, param, victim); - append_const_arg(name, value, arg_list); - - } else { - crm_err("No node attribute '%s' for '%s'", name, victim); - } - - crm_free(name); name=NULL; - crm_free(param); - if(map[lpc] == 0) { - break; - } - - } else if(isspace(map[lpc])) { - last = lpc; - } - } - crm_free(name); + for (; lpc < max + 1; lpc++) { + if (isalpha(map[lpc])) { + /* keep going */ + + } else if (map[lpc] == '=' || map[lpc] == ':') { + crm_free(name); + crm_malloc0(name, 1 + lpc - last); + strncpy(name, map + last, lpc - last); + crm_debug("Got name: %s", name); + last = lpc + 1; + + } else if (map[lpc] == 0 || map[lpc] == ',' || isspace(map[lpc])) { + char *param = NULL; + const char *value = NULL; + + crm_malloc0(param, 1 + lpc - last); + strncpy(param, map + last, lpc - last); + last = lpc + 1; + + crm_debug("Got key: %s", param); + if (name == NULL) { + crm_err("Misparsed '%s', found '%s' without a name", map, param); + crm_free(param); + continue; + } + + if (safe_str_eq(param, "uname")) { + value = victim; + } else { + char *key = crm_meta_name(param); + + value = g_hash_table_lookup(params, key); + crm_free(key); + } + + if (value) { + crm_debug("Setting '%s'='%s' (%s) for %s", name, value, param, victim); + append_const_arg(name, value, arg_list); + + } else { + crm_err("No node attribute '%s' for '%s'", name, victim); + } + + crm_free(name); + name = NULL; + crm_free(param); + if (map[lpc] == 0) { + break; + } + + } else if (isspace(map[lpc])) { + last = lpc; + } + } + crm_free(name); } - -static char *make_args(const char *action, const char *victim, GHashTable *device_args, GHashTable *port_map) +static char * +make_args(const char *action, const char *victim, GHashTable * device_args, GHashTable * port_map) { char buffer[512]; char *arg_list = NULL; const char *value = NULL; + CRM_CHECK(action != NULL, return NULL); - if(device_args) { - g_hash_table_foreach(device_args, append_arg, &arg_list); + if (device_args) { + g_hash_table_foreach(device_args, append_arg, &arg_list); } buffer[511] = 0; snprintf(buffer, 511, "pcmk_%s_action", action); - if(device_args) { - value = g_hash_table_lookup(device_args, buffer); + if (device_args) { + value = g_hash_table_lookup(device_args, buffer); } - - if(value == NULL && device_args) { - /* Legacy support for early 1.1 releases - Remove for 1.2 */ - snprintf(buffer, 511, "pcmk_%s_cmd", action); - value = g_hash_table_lookup(device_args, buffer); + + if (value == NULL && device_args) { + /* Legacy support for early 1.1 releases - Remove for 1.2 */ + snprintf(buffer, 511, "pcmk_%s_cmd", action); + value = g_hash_table_lookup(device_args, buffer); } - if(value) { - crm_info("Substituting action '%s' for requested operation '%s'", value, action); - action = value; + if (value) { + crm_info("Substituting action '%s' for requested operation '%s'", value, action); + action = value; } - + append_const_arg(STONITH_ATTR_ACTION_OP, action, &arg_list); - if(victim && device_args) { - const char *alias = victim; - const char *param = g_hash_table_lookup(device_args, STONITH_ATTR_HOSTARG); - - if(port_map && g_hash_table_lookup(port_map, victim)) { - alias = g_hash_table_lookup(port_map, victim); - } - - /* Always supply the node's name too: - * https://fedorahosted.org/cluster/wiki/FenceAgentAPI - */ - append_const_arg("nodename", victim, &arg_list); - - /* Check if we need to supply the victim in any other form */ - if(param == NULL) { - const char *map = g_hash_table_lookup(device_args, STONITH_ATTR_ARGMAP); - if(map == NULL) { - param = "port"; - value = g_hash_table_lookup(device_args, param); - - } else { - /* Legacy handling */ - append_host_specific_args(alias, map, device_args, &arg_list); - value = map; /* Nothing more to do */ - } - - } else if(safe_str_eq(param, "none")) { - value = param; /* Nothing more to do */ - - } else { - value = g_hash_table_lookup(device_args, param); - } - - /* Don't overwrite explictly set values for $param */ - if(value == NULL || safe_str_eq(value, "dynamic")) { - crm_info("%s-ing node '%s' as '%s=%s'", action, victim, param, alias); - append_const_arg(param, alias, &arg_list); - } + if (victim && device_args) { + const char *alias = victim; + const char *param = g_hash_table_lookup(device_args, STONITH_ATTR_HOSTARG); + + if (port_map && g_hash_table_lookup(port_map, victim)) { + alias = g_hash_table_lookup(port_map, victim); + } + + /* Always supply the node's name too: + * https://fedorahosted.org/cluster/wiki/FenceAgentAPI + */ + append_const_arg("nodename", victim, &arg_list); + + /* Check if we need to supply the victim in any other form */ + if (param == NULL) { + const char *map = g_hash_table_lookup(device_args, STONITH_ATTR_ARGMAP); + + if (map == NULL) { + param = "port"; + value = g_hash_table_lookup(device_args, param); + + } else { + /* Legacy handling */ + append_host_specific_args(alias, map, device_args, &arg_list); + value = map; /* Nothing more to do */ + } + + } else if (safe_str_eq(param, "none")) { + value = param; /* Nothing more to do */ + + } else { + value = g_hash_table_lookup(device_args, param); + } + + /* Don't overwrite explictly set values for $param */ + if (value == NULL || safe_str_eq(value, "dynamic")) { + crm_info("%s-ing node '%s' as '%s=%s'", action, victim, param, alias); + append_const_arg(param, alias, &arg_list); + } } - + crm_debug_3("Calculated: %s", arg_list); return arg_list; } /* Borrowed from libfence and extended */ -int run_stonith_agent( - const char *agent, const char *action, const char *victim, GHashTable *device_args, GHashTable *port_map, - int *agent_result, char **output, async_command_t *track) +int +run_stonith_agent(const char *agent, const char *action, const char *victim, + GHashTable * device_args, GHashTable * port_map, int *agent_result, char **output, + async_command_t * track) { char *args = make_args(action, victim, device_args, port_map); int pid, status, len, rc = st_err_internal; int p_read_fd, p_write_fd; /* parent read/write file descriptors */ int c_read_fd, c_write_fd; /* child read/write file descriptors */ int fd1[2]; int fd2[2]; c_read_fd = c_write_fd = p_read_fd = p_write_fd = -1; if (args == NULL || agent == NULL) - goto fail; + goto fail; len = strlen(args); if (pipe(fd1)) - goto fail; + goto fail; p_read_fd = fd1[0]; c_write_fd = fd1[1]; if (pipe(fd2)) - goto fail; + goto fail; c_read_fd = fd2[0]; p_write_fd = fd2[1]; crm_debug("forking"); pid = fork(); if (pid < 0) { - rc = st_err_agent_fork; - goto fail; + rc = st_err_agent_fork; + goto fail; } if (pid) { - /* parent */ - int ret; - int total = 0; - - fcntl(p_read_fd, F_SETFL, fcntl(p_read_fd, F_GETFL, 0) | O_NONBLOCK); - - do { - crm_debug("sending args"); - ret = write(p_write_fd, args+total, len-total); - if(ret > 0) { - total += ret; - } - - } while (errno == EINTR && total < len); - - if (total != len) { - crm_perror(LOG_ERR, "Sent %d not %d bytes", total, len); - if(ret >= 0) { - rc = st_err_agent_args; - } - goto fail; - } - - close(p_write_fd); - - if(track) { - track->stdout = p_read_fd; - NewTrackedProc(pid, 0, PT_LOGNORMAL, track, track->pt_ops); - crm_trace("Op: %s on %s, timeout: %d", action, agent, track->timeout); - - if(track->timeout) { - track->killseq[0].mstimeout = track->timeout; /* after timeout send TERM */ - track->killseq[0].signalno = SIGTERM; - track->killseq[1].mstimeout = 5000; /* after another 5s remove it */ - track->killseq[1].signalno = SIGKILL; - track->killseq[2].mstimeout = 5000; /* if it's still there after another 5s, complain */ - track->killseq[2].signalno = 0; - - SetTrackedProcTimeouts(pid, track->killseq); - - } else { - crm_err("No timeout set for stonith operation %s with device %s", action, agent); - } - - close(c_write_fd); - close(c_read_fd); - crm_free(args); - return pid; - - } else { - waitpid(pid, &status, 0); - - if(output != NULL) { - len = 0; - do { - char buf[500]; - ret = read(p_read_fd, buf, 500); - if(ret > 0) { - buf[ret] = 0; - crm_realloc(*output, len + ret + 1); - sprintf((*output)+len, "%s", buf); - crm_debug("%d: %s", ret, (*output)+len); - len += ret; - } - - } while (ret == 500 || (ret < 0 && errno == EINTR)); - } - - rc = st_err_agent; - *agent_result = st_err_agent; - if (WIFEXITED(status)) { - crm_debug("result = %d", WEXITSTATUS(status)); - *agent_result = -WEXITSTATUS(status); - rc = 0; - } - } + /* parent */ + int ret; + int total = 0; + + fcntl(p_read_fd, F_SETFL, fcntl(p_read_fd, F_GETFL, 0) | O_NONBLOCK); + + do { + crm_debug("sending args"); + ret = write(p_write_fd, args + total, len - total); + if (ret > 0) { + total += ret; + } + + } while (errno == EINTR && total < len); + + if (total != len) { + crm_perror(LOG_ERR, "Sent %d not %d bytes", total, len); + if (ret >= 0) { + rc = st_err_agent_args; + } + goto fail; + } + + close(p_write_fd); + + if (track) { + track->stdout = p_read_fd; + NewTrackedProc(pid, 0, PT_LOGNORMAL, track, track->pt_ops); + crm_trace("Op: %s on %s, timeout: %d", action, agent, track->timeout); + + if (track->timeout) { + track->killseq[0].mstimeout = track->timeout; /* after timeout send TERM */ + track->killseq[0].signalno = SIGTERM; + track->killseq[1].mstimeout = 5000; /* after another 5s remove it */ + track->killseq[1].signalno = SIGKILL; + track->killseq[2].mstimeout = 5000; /* if it's still there after another 5s, complain */ + track->killseq[2].signalno = 0; + + SetTrackedProcTimeouts(pid, track->killseq); + + } else { + crm_err("No timeout set for stonith operation %s with device %s", action, agent); + } + + close(c_write_fd); + close(c_read_fd); + crm_free(args); + return pid; + + } else { + waitpid(pid, &status, 0); + + if (output != NULL) { + len = 0; + do { + char buf[500]; + + ret = read(p_read_fd, buf, 500); + if (ret > 0) { + buf[ret] = 0; + crm_realloc(*output, len + ret + 1); + sprintf((*output) + len, "%s", buf); + crm_debug("%d: %s", ret, (*output) + len); + len += ret; + } + + } while (ret == 500 || (ret < 0 && errno == EINTR)); + } + + rc = st_err_agent; + *agent_result = st_err_agent; + if (WIFEXITED(status)) { + crm_debug("result = %d", WEXITSTATUS(status)); + *agent_result = -WEXITSTATUS(status); + rc = 0; + } + } } else { - /* child */ + /* child */ - close(1); - if (dup(c_write_fd) < 0) - goto fail; - close(2); - if (dup(c_write_fd) < 0) - goto fail; - close(0); - if (dup(c_read_fd) < 0) - goto fail; + close(1); + if (dup(c_write_fd) < 0) + goto fail; + close(2); + if (dup(c_write_fd) < 0) + goto fail; + close(0); + if (dup(c_read_fd) < 0) + goto fail; - /* keep c_write_fd open so parent can report all errors. */ - close(c_read_fd); - close(p_read_fd); - close(p_write_fd); + /* keep c_write_fd open so parent can report all errors. */ + close(c_read_fd); + close(p_read_fd); + close(p_write_fd); - execlp(agent, agent, NULL); - exit(EXIT_FAILURE); + execlp(agent, agent, NULL); + exit(EXIT_FAILURE); } fail: crm_free(args); - if(p_read_fd >= 0) { close(p_read_fd); } - if(p_write_fd >= 0) { close(p_write_fd); } + if (p_read_fd >= 0) { + close(p_read_fd); + } + if (p_write_fd >= 0) { + close(p_write_fd); + } - if(c_read_fd >= 0) { close(c_read_fd); } - if(c_write_fd >= 0) { close(c_write_fd); } + if (c_read_fd >= 0) { + close(c_read_fd); + } + if (c_write_fd >= 0) { + close(c_write_fd); + } return rc; } -static int stonith_api_device_list( - stonith_t *stonith, int call_options, const char *namespace, - stonith_key_value_t **devices, int timeout) +static int +stonith_api_device_list(stonith_t * stonith, int call_options, const char *namespace, + stonith_key_value_t ** devices, int timeout) { int count = 0; - if ( devices == NULL ) { - crm_err("Parameter error: stonith_api_device_list"); - return -2; + + if (devices == NULL) { + crm_err("Parameter error: stonith_api_device_list"); + return -2; } - + /* Include Heartbeat agents */ - if(namespace == NULL || safe_str_eq("heartbeat", namespace)) { - char **entry = NULL; - char **type_list = stonith_types(); - for(entry = type_list; entry != NULL && *entry; ++entry) { - crm_trace("Added: %s", *entry); - *devices = stonith_key_value_add(*devices, NULL, *entry); - count++; - } - if(type_list) { - stonith_free_hostlist(type_list); - } + if (namespace == NULL || safe_str_eq("heartbeat", namespace)) { + char **entry = NULL; + char **type_list = stonith_types(); + + for (entry = type_list; entry != NULL && *entry; ++entry) { + crm_trace("Added: %s", *entry); + *devices = stonith_key_value_add(*devices, NULL, *entry); + count++; + } + if (type_list) { + stonith_free_hostlist(type_list); + } } /* Include Red Hat agents, basically: ls -1 @sbin_dir@/fence_* */ - if(namespace == NULL || safe_str_eq("redhat", namespace)) { - struct dirent **namelist; - int file_num = scandir(RH_STONITH_DIR, &namelist, 0, alphasort); - if (file_num > 0) { - struct stat prop; - char buffer[FILENAME_MAX+1]; - - while (file_num--) { - if ('.' == namelist[file_num]->d_name[0]) { - free(namelist[file_num]); - continue; - - } else if(0 != strncmp(RH_STONITH_PREFIX, - namelist[file_num]->d_name, - strlen(RH_STONITH_PREFIX))) { - free(namelist[file_num]); - continue; - } - - snprintf(buffer,FILENAME_MAX,"%s/%s", RH_STONITH_DIR, namelist[file_num]->d_name); - if(stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) { - *devices = stonith_key_value_add(*devices, NULL, namelist[file_num]->d_name); - count++; - } - - free(namelist[file_num]); - } - free(namelist); - } + if (namespace == NULL || safe_str_eq("redhat", namespace)) { + struct dirent **namelist; + int file_num = scandir(RH_STONITH_DIR, &namelist, 0, alphasort); + + if (file_num > 0) { + struct stat prop; + char buffer[FILENAME_MAX + 1]; + + while (file_num--) { + if ('.' == namelist[file_num]->d_name[0]) { + free(namelist[file_num]); + continue; + + } else if (0 != strncmp(RH_STONITH_PREFIX, + namelist[file_num]->d_name, strlen(RH_STONITH_PREFIX))) { + free(namelist[file_num]); + continue; + } + + snprintf(buffer, FILENAME_MAX, "%s/%s", RH_STONITH_DIR, namelist[file_num]->d_name); + if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) { + *devices = stonith_key_value_add(*devices, NULL, namelist[file_num]->d_name); + count++; + } + + free(namelist[file_num]); + } + free(namelist); + } } return count; } -static int stonith_api_device_metadata( - stonith_t *stonith, int call_options, const char *agent, const char *namespace, - char **output, int timeout) +static int +stonith_api_device_metadata(stonith_t * stonith, int call_options, const char *agent, + const char *namespace, char **output, int timeout) { int rc = 0; int bufferlen = 0; char *buffer = NULL; char *xml_meta_longdesc = NULL; char *xml_meta_shortdesc = NULL; char *meta_param = NULL; char *meta_longdesc = NULL; char *meta_shortdesc = NULL; const char *provider = get_stonith_provider(agent, namespace); - Stonith *stonith_obj = NULL; + Stonith *stonith_obj = NULL; static const char *no_parameter_info = ""; crm_info("looking up %s/%s metadata", agent, provider); - + /* By having this in a library, we can access it from stonith_admin * when neither lrmd or stonith-ng are running * Important for the crm shell's validations... */ - - if(safe_str_eq(provider, "redhat")) { - - int exec_rc = run_stonith_agent( - agent, "metadata", NULL, NULL, NULL, &rc, &buffer, NULL); - - if(exec_rc < 0 || rc != 0 || buffer == NULL) { - /* failed */ - crm_debug("Query failed: %d %d: %s", exec_rc, rc, crm_str(buffer)); - - /* provide a fake metadata entry */ - meta_longdesc = crm_strdup(no_parameter_info); - meta_shortdesc = crm_strdup(no_parameter_info); - meta_param = crm_strdup( -" \n" -" \n" -" \n" -" \n" -" Fencing action (null, off, on, [reboot], status, hostlist, devstatus)\n" -" \n" -" "); - - goto build; - } - + + if (safe_str_eq(provider, "redhat")) { + + int exec_rc = run_stonith_agent(agent, "metadata", NULL, NULL, NULL, &rc, &buffer, NULL); + + if (exec_rc < 0 || rc != 0 || buffer == NULL) { + /* failed */ + crm_debug("Query failed: %d %d: %s", exec_rc, rc, crm_str(buffer)); + + /* provide a fake metadata entry */ + meta_longdesc = crm_strdup(no_parameter_info); + meta_shortdesc = crm_strdup(no_parameter_info); + meta_param = crm_strdup(" \n" + " \n" + " \n" + " \n" + " Fencing action (null, off, on, [reboot], status, hostlist, devstatus)\n" + " \n" " "); + + goto build; + } + } else { - stonith_obj = stonith_new(agent); - - meta_longdesc = crm_strdup(stonith_get_info(stonith_obj, ST_DEVICEDESCR)); - if (meta_longdesc == NULL) { - crm_warn("no long description in %s's metadata.", agent); - meta_longdesc = crm_strdup(no_parameter_info); - } - - meta_shortdesc = crm_strdup(stonith_get_info(stonith_obj, ST_DEVICEID)); - if (meta_shortdesc == NULL) { - crm_warn("no short description in %s's metadata.", agent); - meta_shortdesc = crm_strdup(no_parameter_info); - } - - meta_param = crm_strdup(stonith_get_info(stonith_obj, ST_CONF_XML)); - if (meta_param == NULL) { - crm_warn("no list of parameters in %s's metadata.", agent); - meta_param = crm_strdup(no_parameter_info); - } - - build: - xml_meta_longdesc = (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_longdesc); - xml_meta_shortdesc = (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_shortdesc); - - bufferlen = strlen(META_TEMPLATE) + strlen(agent) - + strlen(xml_meta_longdesc) + strlen(xml_meta_shortdesc) - + strlen(meta_param) + 1; - - crm_malloc0(buffer, bufferlen); - snprintf(buffer, bufferlen-1, META_TEMPLATE, - agent, xml_meta_longdesc, xml_meta_shortdesc, meta_param); - - xmlFree(xml_meta_longdesc); - xmlFree(xml_meta_shortdesc); - - if(stonith_obj) { - stonith_delete(stonith_obj); - } - - crm_free(meta_shortdesc); - crm_free(meta_longdesc); - crm_free(meta_param); - } - - if(output) { - *output = buffer; + stonith_obj = stonith_new(agent); + + meta_longdesc = crm_strdup(stonith_get_info(stonith_obj, ST_DEVICEDESCR)); + if (meta_longdesc == NULL) { + crm_warn("no long description in %s's metadata.", agent); + meta_longdesc = crm_strdup(no_parameter_info); + } + + meta_shortdesc = crm_strdup(stonith_get_info(stonith_obj, ST_DEVICEID)); + if (meta_shortdesc == NULL) { + crm_warn("no short description in %s's metadata.", agent); + meta_shortdesc = crm_strdup(no_parameter_info); + } + + meta_param = crm_strdup(stonith_get_info(stonith_obj, ST_CONF_XML)); + if (meta_param == NULL) { + crm_warn("no list of parameters in %s's metadata.", agent); + meta_param = crm_strdup(no_parameter_info); + } + + build: + xml_meta_longdesc = + (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_longdesc); + xml_meta_shortdesc = + (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_shortdesc); + + bufferlen = strlen(META_TEMPLATE) + strlen(agent) + + strlen(xml_meta_longdesc) + strlen(xml_meta_shortdesc) + + strlen(meta_param) + 1; + + crm_malloc0(buffer, bufferlen); + snprintf(buffer, bufferlen - 1, META_TEMPLATE, + agent, xml_meta_longdesc, xml_meta_shortdesc, meta_param); + + xmlFree(xml_meta_longdesc); + xmlFree(xml_meta_shortdesc); + + if (stonith_obj) { + stonith_delete(stonith_obj); + } + + crm_free(meta_shortdesc); + crm_free(meta_longdesc); + crm_free(meta_param); + } + + if (output) { + *output = buffer; } else { - crm_free(buffer); + crm_free(buffer); } - + return rc; } -static int stonith_api_confirm( - stonith_t *stonith, int call_options, const char *target) +static int +stonith_api_confirm(stonith_t * stonith, int call_options, const char *target) { - int rc = 0; + int rc = 0; xmlNode *data = NULL; data = create_xml_node(NULL, __FUNCTION__); crm_xml_add(data, F_STONITH_TARGET, target); rc = stonith_send_command(stonith, STONITH_OP_FENCE, data, NULL, call_options, 0); free_xml(data); - + return rc; } -static int stonith_api_query( - stonith_t *stonith, int call_options, const char *target, - stonith_key_value_t **devices, int timeout) +static int +stonith_api_query(stonith_t * stonith, int call_options, const char *target, + stonith_key_value_t ** devices, int timeout) { int rc = 0, lpc = 0, max = 0; xmlNode *data = NULL; xmlNode *output = NULL; xmlXPathObjectPtr xpathObj = NULL; CRM_CHECK(devices != NULL, return st_err_missing); data = create_xml_node(NULL, F_STONITH_DEVICE); crm_xml_add(data, "origin", __FUNCTION__); crm_xml_add(data, F_STONITH_TARGET, target); rc = stonith_send_command(stonith, STONITH_OP_QUERY, data, &output, call_options, timeout); - if(rc < 0) { - return rc; + if (rc < 0) { + return rc; } - + xpathObj = xpath_search(output, "//@agent"); - if(xpathObj) { - max = xpathObj->nodesetval->nodeNr; + if (xpathObj) { + max = xpathObj->nodesetval->nodeNr; + + for (lpc = 0; lpc < max; lpc++) { + xmlNode *match = getXpathResult(xpathObj, lpc); - for(lpc = 0; lpc < max; lpc++) { - xmlNode *match = getXpathResult(xpathObj, lpc); - CRM_CHECK(match != NULL, continue); - - crm_info("%s[%d] = %s", "//@agent", lpc, xmlGetNodePath(match)); - *devices = stonith_key_value_add(*devices, NULL, crm_element_value(match, XML_ATTR_ID)); - } + CRM_CHECK(match != NULL, continue); + + crm_info("%s[%d] = %s", "//@agent", lpc, xmlGetNodePath(match)); + *devices = stonith_key_value_add(*devices, NULL, crm_element_value(match, XML_ATTR_ID)); + } } - + free_xml(output); free_xml(data); return max; } -static int stonith_api_call( - stonith_t *stonith, int call_options, const char *id, const char *action, const char *victim, int timeout) +static int +stonith_api_call(stonith_t * stonith, int call_options, const char *id, const char *action, + const char *victim, int timeout) { int rc = 0; xmlNode *data = NULL; data = create_xml_node(NULL, F_STONITH_DEVICE); crm_xml_add(data, "origin", __FUNCTION__); crm_xml_add(data, F_STONITH_DEVICE, id); crm_xml_add(data, F_STONITH_ACTION, action); crm_xml_add(data, F_STONITH_TARGET, victim); rc = stonith_send_command(stonith, STONITH_OP_EXEC, data, NULL, call_options, timeout); free_xml(data); - + return rc; } -static int stonith_api_fence( - stonith_t *stonith, int call_options, const char *node, const char *action, int timeout) +static int +stonith_api_fence(stonith_t * stonith, int call_options, const char *node, const char *action, + int timeout) { int rc = 0; xmlNode *data = NULL; data = create_xml_node(NULL, __FUNCTION__); crm_xml_add(data, F_STONITH_TARGET, node); crm_xml_add(data, F_STONITH_ACTION, action); crm_xml_add_int(data, F_STONITH_TIMEOUT, timeout); rc = stonith_send_command(stonith, STONITH_OP_FENCE, data, NULL, call_options, timeout); free_xml(data); - + return rc; } -static int stonith_api_history( - stonith_t *stonith, int call_options, const char *node, - stonith_history_t **history, int timeout) +static int +stonith_api_history(stonith_t * stonith, int call_options, const char *node, + stonith_history_t ** history, int timeout) { int rc = 0; xmlNode *data = NULL; xmlNode *output = NULL; stonith_history_t *last = NULL; *history = NULL; - if(node) { - data = create_xml_node(NULL, __FUNCTION__); - crm_xml_add(data, F_STONITH_TARGET, node); + if (node) { + data = create_xml_node(NULL, __FUNCTION__); + crm_xml_add(data, F_STONITH_TARGET, node); } - + rc = stonith_send_command(stonith, STONITH_OP_FENCE_HISTORY, data, &output, - call_options | st_opt_sync_call, timeout); + call_options | st_opt_sync_call, timeout); free_xml(data); - + if (rc == 0) { - xmlNode *op = NULL; - xmlNode *reply = get_xpath_object("//"F_STONITH_HISTORY_LIST, output, LOG_ERR); - - for(op = __xml_first_child(reply); op != NULL; op = __xml_next(op)) { - stonith_history_t *kvp; - - crm_malloc0(kvp, sizeof(stonith_history_t)); - kvp->target = crm_element_value_copy(op, F_STONITH_TARGET); - kvp->action = crm_element_value_copy(op, F_STONITH_ACTION); - kvp->origin = crm_element_value_copy(op, F_STONITH_ORIGIN); - kvp->delegate = crm_element_value_copy(op, F_STONITH_DELEGATE); - crm_element_value_int(op, F_STONITH_DATE, &kvp->completed); - crm_element_value_int(op, F_STONITH_STATE, &kvp->state); - - if (last) { - last->next = kvp; - } else { - *history = kvp; - } - last = kvp; + xmlNode *op = NULL; + xmlNode *reply = get_xpath_object("//" F_STONITH_HISTORY_LIST, output, LOG_ERR); + + for (op = __xml_first_child(reply); op != NULL; op = __xml_next(op)) { + stonith_history_t *kvp; + + crm_malloc0(kvp, sizeof(stonith_history_t)); + kvp->target = crm_element_value_copy(op, F_STONITH_TARGET); + kvp->action = crm_element_value_copy(op, F_STONITH_ACTION); + kvp->origin = crm_element_value_copy(op, F_STONITH_ORIGIN); + kvp->delegate = crm_element_value_copy(op, F_STONITH_DELEGATE); + crm_element_value_int(op, F_STONITH_DATE, &kvp->completed); + crm_element_value_int(op, F_STONITH_STATE, &kvp->state); + + if (last) { + last->next = kvp; + } else { + *history = kvp; + } + last = kvp; } } return rc; } const char * stonith_error2string(enum stonith_errors return_code) { const char *error_msg = NULL; - switch(return_code) { - case stonith_ok: - error_msg = "OK"; - break; - case st_err_not_supported: - error_msg = "Not supported"; - break; - case st_err_authentication: - error_msg = "Not authenticated"; - break; - case st_err_generic: - error_msg = "Generic error"; - break; - case st_err_internal: - error_msg = "Internal error"; - break; - case st_err_unknown_device: - error_msg = "Unknown device"; - break; - case st_err_unknown_operation: - error_msg = "Unknown operation"; - break; - case st_err_unknown_port: - error_msg = "Unknown victim"; - break; - case st_err_none_available: - error_msg = "No available fencing devices"; - break; - case st_err_connection: - error_msg = "Not connected"; - break; - case st_err_missing: - error_msg = "Missing input"; - break; - case st_err_exists: - error_msg = "Device exists"; - break; - case st_err_timeout: - error_msg = "Operation timed out"; - break; - case st_err_signal: - error_msg = "Killed by signal"; - break; - case st_err_ipc: - error_msg = "IPC connection failed"; - break; - case st_err_peer: - error_msg = "Error from peer"; - break; - case stonith_pending: - error_msg = "Stonith operation is in progress"; - break; - case st_err_agent_fork: - error_msg = "Call to fork() failed"; - break; - case st_err_agent_args: - error_msg = "Could not send arguments to the stonith device"; - break; - case st_err_agent: - error_msg = "Execution of the stonith agent failed"; - break; - } - - if(error_msg == NULL) { - crm_err("Unknown Stonith error code: %d", return_code); - error_msg = ""; - } - + + switch (return_code) { + case stonith_ok: + error_msg = "OK"; + break; + case st_err_not_supported: + error_msg = "Not supported"; + break; + case st_err_authentication: + error_msg = "Not authenticated"; + break; + case st_err_generic: + error_msg = "Generic error"; + break; + case st_err_internal: + error_msg = "Internal error"; + break; + case st_err_unknown_device: + error_msg = "Unknown device"; + break; + case st_err_unknown_operation: + error_msg = "Unknown operation"; + break; + case st_err_unknown_port: + error_msg = "Unknown victim"; + break; + case st_err_none_available: + error_msg = "No available fencing devices"; + break; + case st_err_connection: + error_msg = "Not connected"; + break; + case st_err_missing: + error_msg = "Missing input"; + break; + case st_err_exists: + error_msg = "Device exists"; + break; + case st_err_timeout: + error_msg = "Operation timed out"; + break; + case st_err_signal: + error_msg = "Killed by signal"; + break; + case st_err_ipc: + error_msg = "IPC connection failed"; + break; + case st_err_peer: + error_msg = "Error from peer"; + break; + case stonith_pending: + error_msg = "Stonith operation is in progress"; + break; + case st_err_agent_fork: + error_msg = "Call to fork() failed"; + break; + case st_err_agent_args: + error_msg = "Could not send arguments to the stonith device"; + break; + case st_err_agent: + error_msg = "Execution of the stonith agent failed"; + break; + } + + if (error_msg == NULL) { + crm_err("Unknown Stonith error code: %d", return_code); + error_msg = ""; + } + return error_msg; } -gboolean is_redhat_agent(const char *agent) +gboolean +is_redhat_agent(const char *agent) { int rc = 0; struct stat prop; - char buffer[FILENAME_MAX+1]; + char buffer[FILENAME_MAX + 1]; - snprintf(buffer,FILENAME_MAX,"%s/%s", RH_STONITH_DIR, agent); + snprintf(buffer, FILENAME_MAX, "%s/%s", RH_STONITH_DIR, agent); rc = stat(buffer, &prop); if (rc >= 0 && S_ISREG(prop.st_mode)) { - return TRUE; + return TRUE; } return FALSE; } -const char *get_stonith_provider(const char *agent, const char *provider) +const char * +get_stonith_provider(const char *agent, const char *provider) { /* This function sucks */ - if(is_redhat_agent(agent)) { - return "redhat"; + if (is_redhat_agent(agent)) { + return "redhat"; } else { - Stonith *stonith_obj = stonith_new(agent); - if(stonith_obj) { - stonith_delete(stonith_obj); - return "heartbeat"; - } + Stonith *stonith_obj = stonith_new(agent); + + if (stonith_obj) { + stonith_delete(stonith_obj); + return "heartbeat"; + } } - + crm_err("No such device: %s", agent); return NULL; } -static gint stonithlib_GCompareFunc(gconstpointer a, gconstpointer b) +static gint +stonithlib_GCompareFunc(gconstpointer a, gconstpointer b) { int rc = 0; const stonith_notify_client_t *a_client = a; const stonith_notify_client_t *b_client = b; - + CRM_CHECK(a_client->event != NULL && b_client->event != NULL, return 0); rc = strcmp(a_client->event, b_client->event); - if(rc == 0) { - if(a_client->notify == NULL || b_client->notify == NULL) { - return 0; - - } else if(a_client->notify == b_client->notify) { - return 0; - - } else if(((long)a_client->notify) < ((long)b_client->notify)) { - crm_err("callbacks for %s are not equal: %p vs. %p", - a_client->event, a_client->notify, b_client->notify); - return -1; - } - crm_err("callbacks for %s are not equal: %p vs. %p", - a_client->event, a_client->notify, b_client->notify); - return 1; + if (rc == 0) { + if (a_client->notify == NULL || b_client->notify == NULL) { + return 0; + + } else if (a_client->notify == b_client->notify) { + return 0; + + } else if (((long)a_client->notify) < ((long)b_client->notify)) { + crm_err("callbacks for %s are not equal: %p vs. %p", + a_client->event, a_client->notify, b_client->notify); + return -1; + } + crm_err("callbacks for %s are not equal: %p vs. %p", + a_client->event, a_client->notify, b_client->notify); + return 1; } return rc; } -static int get_stonith_token(IPC_Channel *ch, char **token) +static int +get_stonith_token(IPC_Channel * ch, char **token) { int rc = stonith_ok; xmlNode *reg_msg = NULL; const char *msg_type = NULL; const char *tmp_ticket = NULL; - + CRM_CHECK(ch != NULL, return st_err_missing); CRM_CHECK(token != NULL, return st_err_missing); - + crm_debug_4("Waiting for msg on command channel"); - + reg_msg = xmlfromIPC(ch, MAX_IPC_DELAY); - - if(ch->ops->get_chan_status(ch) != IPC_CONNECT) { - crm_err("No reply message - disconnected"); - free_xml(reg_msg); - return st_err_connection; - - } else if(reg_msg == NULL) { - crm_err("No reply message - empty"); - return st_err_ipc; + + if (ch->ops->get_chan_status(ch) != IPC_CONNECT) { + crm_err("No reply message - disconnected"); + free_xml(reg_msg); + return st_err_connection; + + } else if (reg_msg == NULL) { + crm_err("No reply message - empty"); + return st_err_ipc; } - + msg_type = crm_element_value(reg_msg, F_STONITH_OPERATION); tmp_ticket = crm_element_value(reg_msg, F_STONITH_CLIENTID); - - if(safe_str_neq(msg_type, CRM_OP_REGISTER) ) { - crm_err("Invalid registration message: %s", msg_type); - rc = st_err_internal; - - } else if(tmp_ticket == NULL) { - crm_err("No registration token provided"); - crm_log_xml_warn(reg_msg, "Bad reply"); - rc = st_err_internal; + + if (safe_str_neq(msg_type, CRM_OP_REGISTER)) { + crm_err("Invalid registration message: %s", msg_type); + rc = st_err_internal; + + } else if (tmp_ticket == NULL) { + crm_err("No registration token provided"); + crm_log_xml_warn(reg_msg, "Bad reply"); + rc = st_err_internal; } else { - crm_debug("Obtained registration token: %s", tmp_ticket); - *token = crm_strdup(tmp_ticket); + crm_debug("Obtained registration token: %s", tmp_ticket); + *token = crm_strdup(tmp_ticket); } free_xml(reg_msg); return rc; } -xmlNode *stonith_create_op( - int call_id, const char *token, const char *op, xmlNode *data, int call_options) +xmlNode * +stonith_create_op(int call_id, const char *token, const char *op, xmlNode * data, int call_options) { - int rc = HA_OK; + int rc = HA_OK; xmlNode *op_msg = create_xml_node(NULL, "stonith_command"); + CRM_CHECK(op_msg != NULL, return NULL); CRM_CHECK(token != NULL, return NULL); crm_xml_add(op_msg, F_XML_TAGNAME, "stonith_command"); - + crm_xml_add(op_msg, F_TYPE, T_STONITH_NG); crm_xml_add(op_msg, F_STONITH_CALLBACK_TOKEN, token); crm_xml_add(op_msg, F_STONITH_OPERATION, op); crm_xml_add_int(op_msg, F_STONITH_CALLID, call_id); - crm_debug_4("Sending call options: %.8lx, %d", - (long)call_options, call_options); + crm_debug_4("Sending call options: %.8lx, %d", (long)call_options, call_options); crm_xml_add_int(op_msg, F_STONITH_CALLOPTS, call_options); - if(data != NULL) { - add_message_xml(op_msg, F_STONITH_CALLDATA, data); + if (data != NULL) { + add_message_xml(op_msg, F_STONITH_CALLDATA, data); } - + if (rc != HA_OK) { - crm_err("Failed to create STONITH operation message"); - crm_log_xml(LOG_ERR, "BadOp", op_msg); - free_xml(op_msg); - return NULL; + crm_err("Failed to create STONITH operation message"); + crm_log_xml(LOG_ERR, "BadOp", op_msg); + free_xml(op_msg); + return NULL; } return op_msg; } -static void stonith_destroy_op_callback(gpointer data) +static void +stonith_destroy_op_callback(gpointer data) { stonith_callback_client_t *blob = data; - if(blob->timer && blob->timer->ref > 0) { - g_source_remove(blob->timer->ref); + + if (blob->timer && blob->timer->ref > 0) { + g_source_remove(blob->timer->ref); } crm_free(blob->timer); crm_free(blob); } -static int stonith_api_signoff(stonith_t* stonith) +static int +stonith_api_signoff(stonith_t * stonith) { stonith_private_t *native = stonith->private; crm_debug("Signing out of the STONITH Service"); - + /* close channels */ if (native->command_channel != NULL) { - native->command_channel->ops->destroy( - native->command_channel); - native->command_channel = NULL; + native->command_channel->ops->destroy(native->command_channel); + native->command_channel = NULL; } if (native->callback_source != NULL) { - G_main_del_IPC_Channel(native->callback_source); - native->callback_source = NULL; + G_main_del_IPC_Channel(native->callback_source); + native->callback_source = NULL; } if (native->callback_channel != NULL) { #ifdef BUG - native->callback_channel->ops->destroy( - native->callback_channel); + native->callback_channel->ops->destroy(native->callback_channel); #endif - native->callback_channel = NULL; + native->callback_channel = NULL; } stonith->state = stonith_disconnected; return stonith_ok; } -static int stonith_api_signon( - stonith_t* stonith, const char *name, int *stonith_fd) +static int +stonith_api_signon(stonith_t * stonith, const char *name, int *stonith_fd) { int rc = stonith_ok; xmlNode *hello = NULL; char *uuid_ticket = NULL; stonith_private_t *native = stonith->private; - + crm_debug_4("Connecting command channel"); stonith->state = stonith_connected_command; native->command_channel = init_client_ipc_comms_nodispatch(stonith_channel); - - if(native->command_channel == NULL) { - crm_debug("Connection to command channel failed"); - rc = st_err_connection; - - } else if(native->command_channel->ch_status != IPC_CONNECT) { - crm_err("Connection may have succeeded," - " but authentication to command channel failed"); - rc = st_err_authentication; - } - - if(rc == stonith_ok) { - rc = get_stonith_token(native->command_channel, &uuid_ticket); - if(rc == stonith_ok) { - native->token = uuid_ticket; - uuid_ticket = NULL; - - } else { - stonith->state = stonith_disconnected; - native->command_channel->ops->disconnect(native->command_channel); - return rc; - } - } - - native->callback_channel = init_client_ipc_comms_nodispatch( - stonith_channel_callback); - - if(native->callback_channel == NULL) { - crm_debug("Connection to callback channel failed"); - rc = st_err_connection; - - } else if(native->callback_channel->ch_status != IPC_CONNECT) { - crm_err("Connection may have succeeded," - " but authentication to command channel failed"); - rc = st_err_authentication; - } - - if(rc == stonith_ok) { - native->callback_channel->send_queue->max_qlen = 500; - rc = get_stonith_token(native->callback_channel, &uuid_ticket); - if(rc == stonith_ok) { - crm_free(native->token); - native->token = uuid_ticket; - } - } - - if(rc == stonith_ok) { - CRM_CHECK(native->token != NULL, ;); - hello = stonith_create_op(0, native->token, CRM_OP_REGISTER, NULL, 0); - crm_xml_add(hello, F_STONITH_CLIENTNAME, name); - - if(send_ipc_message(native->command_channel, hello) == FALSE) { - rc = st_err_internal; - } - - free_xml(hello); - } - - if(rc == stonith_ok) { - if(stonith_fd != NULL) { - *stonith_fd = native->callback_channel->ops->get_recv_select_fd( - native->callback_channel); - - } else { /* do mainloop */ - - crm_debug_4("Connecting callback channel"); - native->callback_source = G_main_add_IPC_Channel( - G_PRIORITY_HIGH, native->callback_channel, FALSE, stonith_dispatch_internal, - stonith, default_ipc_connection_destroy); - - if(native->callback_source == NULL) { - crm_err("Callback source not recorded"); - rc = st_err_connection; - - } else { - set_IPC_Channel_dnotify( - native->callback_source, stonith_connection_destroy); - } - } - } - - if(rc == stonith_ok) { + + if (native->command_channel == NULL) { + crm_debug("Connection to command channel failed"); + rc = st_err_connection; + + } else if (native->command_channel->ch_status != IPC_CONNECT) { + crm_err("Connection may have succeeded," " but authentication to command channel failed"); + rc = st_err_authentication; + } + + if (rc == stonith_ok) { + rc = get_stonith_token(native->command_channel, &uuid_ticket); + if (rc == stonith_ok) { + native->token = uuid_ticket; + uuid_ticket = NULL; + + } else { + stonith->state = stonith_disconnected; + native->command_channel->ops->disconnect(native->command_channel); + return rc; + } + } + + native->callback_channel = init_client_ipc_comms_nodispatch(stonith_channel_callback); + + if (native->callback_channel == NULL) { + crm_debug("Connection to callback channel failed"); + rc = st_err_connection; + + } else if (native->callback_channel->ch_status != IPC_CONNECT) { + crm_err("Connection may have succeeded," " but authentication to command channel failed"); + rc = st_err_authentication; + } + + if (rc == stonith_ok) { + native->callback_channel->send_queue->max_qlen = 500; + rc = get_stonith_token(native->callback_channel, &uuid_ticket); + if (rc == stonith_ok) { + crm_free(native->token); + native->token = uuid_ticket; + } + } + + if (rc == stonith_ok) { + CRM_CHECK(native->token != NULL,; + ); + hello = stonith_create_op(0, native->token, CRM_OP_REGISTER, NULL, 0); + crm_xml_add(hello, F_STONITH_CLIENTNAME, name); + + if (send_ipc_message(native->command_channel, hello) == FALSE) { + rc = st_err_internal; + } + + free_xml(hello); + } + + if (rc == stonith_ok) { + if (stonith_fd != NULL) { + *stonith_fd = + native->callback_channel->ops->get_recv_select_fd(native->callback_channel); + + } else { /* do mainloop */ + + crm_debug_4("Connecting callback channel"); + native->callback_source = + G_main_add_IPC_Channel(G_PRIORITY_HIGH, native->callback_channel, FALSE, + stonith_dispatch_internal, stonith, + default_ipc_connection_destroy); + + if (native->callback_source == NULL) { + crm_err("Callback source not recorded"); + rc = st_err_connection; + + } else { + set_IPC_Channel_dnotify(native->callback_source, stonith_connection_destroy); + } + } + } + + if (rc == stonith_ok) { #if HAVE_MSGFROMIPC_TIMEOUT - stonith->call_timeout = MAX_IPC_DELAY; + stonith->call_timeout = MAX_IPC_DELAY; #endif - crm_debug("Connection to STONITH successful"); - return stonith_ok; + crm_debug("Connection to STONITH successful"); + return stonith_ok; } crm_debug("Connection to STONITH failed: %s", stonith_error2string(rc)); stonith->cmds->disconnect(stonith); return rc; } -static int stonith_set_notification(stonith_t* stonith, const char *callback, int enabled) +static int +stonith_set_notification(stonith_t * stonith, const char *callback, int enabled) { xmlNode *notify_msg = create_xml_node(NULL, __FUNCTION__); stonith_private_t *native = stonith->private; - if(stonith->state != stonith_disconnected) { - crm_xml_add(notify_msg, F_STONITH_OPERATION, T_STONITH_NOTIFY); - if(enabled) { - crm_xml_add(notify_msg, F_STONITH_NOTIFY_ACTIVATE, callback); - } else { - crm_xml_add(notify_msg, F_STONITH_NOTIFY_DEACTIVATE, callback); - } - send_ipc_message(native->callback_channel, notify_msg); + if (stonith->state != stonith_disconnected) { + crm_xml_add(notify_msg, F_STONITH_OPERATION, T_STONITH_NOTIFY); + if (enabled) { + crm_xml_add(notify_msg, F_STONITH_NOTIFY_ACTIVATE, callback); + } else { + crm_xml_add(notify_msg, F_STONITH_NOTIFY_DEACTIVATE, callback); + } + send_ipc_message(native->callback_channel, notify_msg); } free_xml(notify_msg); return stonith_ok; } -static int stonith_api_add_notification( - stonith_t *stonith, const char *event, - void (*callback)(stonith_t *stonith, const char *event, xmlNode *msg)) +static int +stonith_api_add_notification(stonith_t * stonith, const char *event, + void (*callback) (stonith_t * stonith, const char *event, + xmlNode * msg)) { GList *list_item = NULL; stonith_notify_client_t *new_client = NULL; stonith_private_t *private = NULL; private = stonith->private; - crm_debug_2("Adding callback for %s events (%d)", - event, g_list_length(private->notify_list)); + crm_debug_2("Adding callback for %s events (%d)", event, g_list_length(private->notify_list)); crm_malloc0(new_client, sizeof(stonith_notify_client_t)); new_client->event = event; new_client->notify = callback; - list_item = g_list_find_custom( - private->notify_list, new_client, stonithlib_GCompareFunc); - - if(list_item != NULL) { - crm_warn("Callback already present"); - crm_free(new_client); - return st_err_exists; - + list_item = g_list_find_custom(private->notify_list, new_client, stonithlib_GCompareFunc); + + if (list_item != NULL) { + crm_warn("Callback already present"); + crm_free(new_client); + return st_err_exists; + } else { - private->notify_list = g_list_append(private->notify_list, new_client); + private->notify_list = g_list_append(private->notify_list, new_client); + + stonith_set_notification(stonith, event, 1); - stonith_set_notification(stonith, event, 1); - - crm_debug_3("Callback added (%d)", g_list_length(private->notify_list)); + crm_debug_3("Callback added (%d)", g_list_length(private->notify_list)); } return stonith_ok; } - -static int stonith_api_del_notification(stonith_t *stonith, const char *event) +static int +stonith_api_del_notification(stonith_t * stonith, const char *event) { GList *list_item = NULL; stonith_notify_client_t *new_client = NULL; stonith_private_t *private = NULL; crm_debug("Removing callback for %s events", event); private = stonith->private; crm_malloc0(new_client, sizeof(stonith_notify_client_t)); new_client->event = event; new_client->notify = NULL; - list_item = g_list_find_custom( - private->notify_list, new_client, stonithlib_GCompareFunc); - + list_item = g_list_find_custom(private->notify_list, new_client, stonithlib_GCompareFunc); + stonith_set_notification(stonith, event, 0); - if(list_item != NULL) { - stonith_notify_client_t *list_client = list_item->data; - private->notify_list = - g_list_remove(private->notify_list, list_client); - crm_free(list_client); + if (list_item != NULL) { + stonith_notify_client_t *list_client = list_item->data; - crm_debug_3("Removed callback"); + private->notify_list = g_list_remove(private->notify_list, list_client); + crm_free(list_client); + + crm_debug_3("Removed callback"); } else { - crm_debug_3("Callback not present"); + crm_debug_3("Callback not present"); } crm_free(new_client); return stonith_ok; } -static gboolean stonith_async_timeout_handler(gpointer data) +static gboolean +stonith_async_timeout_handler(gpointer data) { struct timer_rec_s *timer = data; + crm_debug("Async call %d timed out after %dms", timer->call_id, timer->timeout); stonith_perform_callback(timer->stonith, NULL, timer->call_id, st_err_timeout); /* Always return TRUE, never remove the handler * We do that in stonith_del_callback() */ return TRUE; } -static int stonith_api_add_callback( - stonith_t *stonith, int call_id, int timeout, bool only_success, - void *user_data, const char *callback_name, - void (*callback)( - stonith_t *st, const xmlNode *msg, int call, int rc, xmlNode *output, void *userdata)) +static int +stonith_api_add_callback(stonith_t * stonith, int call_id, int timeout, bool only_success, + void *user_data, const char *callback_name, + void (*callback) (stonith_t * st, const xmlNode * msg, int call, int rc, + xmlNode * output, void *userdata)) { stonith_callback_client_t *blob = NULL; stonith_private_t *private = NULL; + CRM_CHECK(stonith != NULL, return st_err_missing); CRM_CHECK(stonith->private != NULL, return st_err_missing); private = stonith->private; - if(call_id == 0) { - private->op_callback = callback; + if (call_id == 0) { + private->op_callback = callback; - } else if(call_id < 0) { - if(only_success == FALSE) { - callback(stonith, NULL, call_id, call_id, NULL, user_data); - } else { - crm_warn("STONITH call failed: %s", stonith_error2string(call_id)); - } - return FALSE; + } else if (call_id < 0) { + if (only_success == FALSE) { + callback(stonith, NULL, call_id, call_id, NULL, user_data); + } else { + crm_warn("STONITH call failed: %s", stonith_error2string(call_id)); + } + return FALSE; } - + crm_malloc0(blob, sizeof(stonith_callback_client_t)); blob->id = callback_name; blob->only_success = only_success; blob->user_data = user_data; blob->callback = callback; - if(timeout > 0) { - struct timer_rec_s *async_timer = NULL; - - crm_malloc0(async_timer, sizeof(struct timer_rec_s)); - blob->timer = async_timer; + if (timeout > 0) { + struct timer_rec_s *async_timer = NULL; + + crm_malloc0(async_timer, sizeof(struct timer_rec_s)); + blob->timer = async_timer; - async_timer->stonith = stonith; - async_timer->call_id = call_id; - async_timer->timeout = timeout*1100; - async_timer->ref = g_timeout_add( - async_timer->timeout, stonith_async_timeout_handler, async_timer); + async_timer->stonith = stonith; + async_timer->call_id = call_id; + async_timer->timeout = timeout * 1100; + async_timer->ref = + g_timeout_add(async_timer->timeout, stonith_async_timeout_handler, async_timer); } - + g_hash_table_insert(private->stonith_op_callback_table, GINT_TO_POINTER(call_id), blob); - + return TRUE; } -static int stonith_api_del_callback(stonith_t *stonith, int call_id, bool all_callbacks) +static int +stonith_api_del_callback(stonith_t * stonith, int call_id, bool all_callbacks) { stonith_private_t *private = stonith->private; - - if(all_callbacks) { - private->op_callback = NULL; - g_hash_table_destroy(private->stonith_op_callback_table); - private->stonith_op_callback_table = g_hash_table_new_full( - g_direct_hash, g_direct_equal, - NULL, stonith_destroy_op_callback); - } else if(call_id == 0) { - private->op_callback = NULL; + if (all_callbacks) { + private->op_callback = NULL; + g_hash_table_destroy(private->stonith_op_callback_table); + private->stonith_op_callback_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, + stonith_destroy_op_callback); + + } else if (call_id == 0) { + private->op_callback = NULL; } else { - g_hash_table_remove(private->stonith_op_callback_table, GINT_TO_POINTER(call_id)); + g_hash_table_remove(private->stonith_op_callback_table, GINT_TO_POINTER(call_id)); } return stonith_ok; } -static void stonith_dump_pending_op( - gpointer key, gpointer value, gpointer user_data) +static void +stonith_dump_pending_op(gpointer key, gpointer value, gpointer user_data) { int call = GPOINTER_TO_INT(key); stonith_callback_client_t *blob = value; crm_debug("Call %d (%s): pending", call, crm_str(blob->id)); } -void stonith_dump_pending_callbacks(stonith_t *stonith) +void +stonith_dump_pending_callbacks(stonith_t * stonith) { stonith_private_t *private = stonith->private; - if(private->stonith_op_callback_table == NULL) { - return; + + if (private->stonith_op_callback_table == NULL) { + return; } - return g_hash_table_foreach( - private->stonith_op_callback_table, stonith_dump_pending_op, NULL); + return g_hash_table_foreach(private->stonith_op_callback_table, stonith_dump_pending_op, NULL); } -void stonith_perform_callback(stonith_t *stonith, xmlNode *msg, int call_id, int rc) +void +stonith_perform_callback(stonith_t * stonith, xmlNode * msg, int call_id, int rc) { xmlNode *output = NULL; stonith_private_t *private = NULL; stonith_callback_client_t *blob = NULL; stonith_callback_client_t local_blob; + CRM_CHECK(stonith != NULL, return); CRM_CHECK(stonith->private != NULL, return); private = stonith->private; local_blob.id = NULL; local_blob.callback = NULL; local_blob.user_data = NULL; local_blob.only_success = FALSE; - if(msg != NULL) { - crm_element_value_int(msg, F_STONITH_RC, &rc); - crm_element_value_int(msg, F_STONITH_CALLID, &call_id); - output = get_message_xml(msg, F_STONITH_CALLDATA); + if (msg != NULL) { + crm_element_value_int(msg, F_STONITH_RC, &rc); + crm_element_value_int(msg, F_STONITH_CALLID, &call_id); + output = get_message_xml(msg, F_STONITH_CALLDATA); } - + CRM_CHECK(call_id > 0, crm_warn("Strange or missing call-id")); - blob = g_hash_table_lookup( - private->stonith_op_callback_table, GINT_TO_POINTER(call_id)); - - if(blob != NULL) { - local_blob = *blob; - blob = NULL; - - stonith_api_del_callback(stonith, call_id, FALSE); + blob = g_hash_table_lookup(private->stonith_op_callback_table, GINT_TO_POINTER(call_id)); + + if (blob != NULL) { + local_blob = *blob; + blob = NULL; + + stonith_api_del_callback(stonith, call_id, FALSE); } else { - crm_debug_2("No callback found for call %d", call_id); - local_blob.callback = NULL; + crm_debug_2("No callback found for call %d", call_id); + local_blob.callback = NULL; } - if(stonith == NULL) { - crm_debug("No stonith object supplied"); + if (stonith == NULL) { + crm_debug("No stonith object supplied"); } - - if(local_blob.callback != NULL - && (rc == stonith_ok || local_blob.only_success == FALSE)) { - crm_debug_2("Invoking callback %s for call %d", crm_str(local_blob.id), call_id); - local_blob.callback(stonith, msg, call_id, rc, output, local_blob.user_data); - - } else if(private->op_callback == NULL && rc != stonith_ok) { - crm_warn("STONITH command failed: %s", stonith_error2string(rc)); - crm_log_xml(LOG_DEBUG, "Failed STONITH Update", msg); + + if (local_blob.callback != NULL && (rc == stonith_ok || local_blob.only_success == FALSE)) { + crm_debug_2("Invoking callback %s for call %d", crm_str(local_blob.id), call_id); + local_blob.callback(stonith, msg, call_id, rc, output, local_blob.user_data); + + } else if (private->op_callback == NULL && rc != stonith_ok) { + crm_warn("STONITH command failed: %s", stonith_error2string(rc)); + crm_log_xml(LOG_DEBUG, "Failed STONITH Update", msg); } - - if(private->op_callback != NULL) { - crm_debug_2("Invoking global callback for call %d", call_id); - private->op_callback(stonith, msg, call_id, rc, output, NULL); + + if (private->op_callback != NULL) { + crm_debug_2("Invoking global callback for call %d", call_id); + private->op_callback(stonith, msg, call_id, rc, output, NULL); } crm_debug_4("OP callback activated."); } -static void stonith_send_notification(gpointer data, gpointer user_data) +static void +stonith_send_notification(gpointer data, gpointer user_data) { struct notify_blob_s *blob = user_data; stonith_notify_client_t *entry = data; const char *event = NULL; - - if(blob->xml == NULL) { - crm_warn("Skipping callback - NULL message"); - return; + + if (blob->xml == NULL) { + crm_warn("Skipping callback - NULL message"); + return; } event = crm_element_value(blob->xml, F_SUBTYPE); - - if(entry == NULL) { - crm_warn("Skipping callback - NULL callback client"); - return; - } else if(entry->notify == NULL) { - crm_warn("Skipping callback - NULL callback"); - return; + if (entry == NULL) { + crm_warn("Skipping callback - NULL callback client"); + return; - } else if(safe_str_neq(entry->event, event)) { - crm_debug_4("Skipping callback - event mismatch %p/%s vs. %s", - entry, entry->event, event); - return; + } else if (entry->notify == NULL) { + crm_warn("Skipping callback - NULL callback"); + return; + + } else if (safe_str_neq(entry->event, event)) { + crm_debug_4("Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event); + return; } - + crm_debug_4("Invoking callback for %p/%s event...", entry, event); entry->notify(blob->stonith, event, blob->xml); crm_debug_4("Callback invoked..."); } -int stonith_send_command( - stonith_t *stonith, const char *op, xmlNode *data, xmlNode **output_data, - int call_options, int timeout) +int +stonith_send_command(stonith_t * stonith, const char *op, xmlNode * data, xmlNode ** output_data, + int call_options, int timeout) { - int rc = HA_OK; - - xmlNode *op_msg = NULL; + int rc = HA_OK; + + xmlNode *op_msg = NULL; xmlNode *op_reply = NULL; stonith_private_t *native = stonith->private; - - if(stonith->state == stonith_disconnected) { - return st_err_connection; + + if (stonith->state == stonith_disconnected) { + return st_err_connection; } - if(output_data != NULL) { - *output_data = NULL; + if (output_data != NULL) { + *output_data = NULL; } - - if(op == NULL) { - crm_err("No operation specified"); - return st_err_missing; + + if (op == NULL) { + crm_err("No operation specified"); + return st_err_missing; } stonith->call_id++; /* prevent call_id from being negative (or zero) and conflicting * with the stonith_errors enum * use 2 because we use it as (stonith->call_id - 1) below */ - if(stonith->call_id < 1) { - stonith->call_id = 1; + if (stonith->call_id < 1) { + stonith->call_id = 1; } - - CRM_CHECK(native->token != NULL, ;); + + CRM_CHECK(native->token != NULL,; + ); op_msg = stonith_create_op(stonith->call_id, native->token, op, data, call_options); - if(op_msg == NULL) { - return st_err_missing; + if (op_msg == NULL) { + return st_err_missing; } crm_xml_add_int(op_msg, F_STONITH_TIMEOUT, timeout); crm_debug_3("Sending %s message to STONITH service, Timeout: %d", op, timeout); - if(send_ipc_message(native->command_channel, op_msg) == FALSE) { - crm_err("Sending message to STONITH service FAILED"); - free_xml(op_msg); - return st_err_ipc; + if (send_ipc_message(native->command_channel, op_msg) == FALSE) { + crm_err("Sending message to STONITH service FAILED"); + free_xml(op_msg); + return st_err_ipc; } else { - crm_debug_3("Message sent"); + crm_debug_3("Message sent"); } free_xml(op_msg); - if((call_options & st_opt_discard_reply)) { - crm_debug_3("Discarding reply"); - return stonith_ok; + if ((call_options & st_opt_discard_reply)) { + crm_debug_3("Discarding reply"); + return stonith_ok; - } else if(!(call_options & st_opt_sync_call)) { - crm_debug_3("Async call, returning"); - CRM_CHECK(stonith->call_id != 0, return st_err_ipc); + } else if (!(call_options & st_opt_sync_call)) { + crm_debug_3("Async call, returning"); + CRM_CHECK(stonith->call_id != 0, return st_err_ipc); - return stonith->call_id; + return stonith->call_id; } - + rc = IPC_OK; crm_debug_3("Waiting for a syncronous reply"); rc = stonith_ok; - while(IPC_ISRCONN(native->command_channel)) { - int reply_id = -1; - int msg_id = stonith->call_id; - - op_reply = xmlfromIPC(native->command_channel, timeout); - if(op_reply == NULL) { - rc = st_err_peer; - break; - } - - crm_element_value_int(op_reply, F_STONITH_CALLID, &reply_id); - if(reply_id <= 0) { - rc = st_err_peer; - break; - - } else if(reply_id == msg_id) { - crm_debug_3("Syncronous reply received"); - crm_log_xml(LOG_MSG, "Reply", op_reply); - if(crm_element_value_int(op_reply, F_STONITH_RC, &rc) != 0) { - rc = st_err_peer; - } - - if(output_data != NULL && is_not_set(call_options, st_opt_discard_reply)) { - *output_data = op_reply; - op_reply = NULL; - } - - goto done; - - } else if(reply_id < msg_id) { - crm_debug("Recieved old reply: %d (wanted %d)", reply_id, msg_id); - crm_log_xml(LOG_MSG, "Old reply", op_reply); - - } else if((reply_id - 10000) > msg_id) { - /* wrap-around case */ - crm_debug("Recieved old reply: %d (wanted %d)", reply_id, msg_id); - crm_log_xml(LOG_MSG, "Old reply", op_reply); - - } else { - crm_err("Received a __future__ reply:" - " %d (wanted %d)", reply_id, msg_id); - } - free_xml(op_reply); - op_reply = NULL; - } - - if(op_reply == NULL && stonith->state == stonith_disconnected) { - rc = st_err_connection; - - } else if(rc == stonith_ok && op_reply == NULL) { - rc = st_err_peer; - } - + while (IPC_ISRCONN(native->command_channel)) { + int reply_id = -1; + int msg_id = stonith->call_id; + + op_reply = xmlfromIPC(native->command_channel, timeout); + if (op_reply == NULL) { + rc = st_err_peer; + break; + } + + crm_element_value_int(op_reply, F_STONITH_CALLID, &reply_id); + if (reply_id <= 0) { + rc = st_err_peer; + break; + + } else if (reply_id == msg_id) { + crm_debug_3("Syncronous reply received"); + crm_log_xml(LOG_MSG, "Reply", op_reply); + if (crm_element_value_int(op_reply, F_STONITH_RC, &rc) != 0) { + rc = st_err_peer; + } + + if (output_data != NULL && is_not_set(call_options, st_opt_discard_reply)) { + *output_data = op_reply; + op_reply = NULL; + } + + goto done; + + } else if (reply_id < msg_id) { + crm_debug("Recieved old reply: %d (wanted %d)", reply_id, msg_id); + crm_log_xml(LOG_MSG, "Old reply", op_reply); + + } else if ((reply_id - 10000) > msg_id) { + /* wrap-around case */ + crm_debug("Recieved old reply: %d (wanted %d)", reply_id, msg_id); + crm_log_xml(LOG_MSG, "Old reply", op_reply); + + } else { + crm_err("Received a __future__ reply:" " %d (wanted %d)", reply_id, msg_id); + } + free_xml(op_reply); + op_reply = NULL; + } + + if (op_reply == NULL && stonith->state == stonith_disconnected) { + rc = st_err_connection; + + } else if (rc == stonith_ok && op_reply == NULL) { + rc = st_err_peer; + } + done: - if(IPC_ISRCONN(native->command_channel) == FALSE) { - crm_err("STONITH disconnected: %d", native->command_channel->ch_status); - stonith->state = stonith_disconnected; + if (IPC_ISRCONN(native->command_channel) == FALSE) { + crm_err("STONITH disconnected: %d", native->command_channel->ch_status); + stonith->state = stonith_disconnected; } free_xml(op_reply); return rc; } -static gboolean stonith_msgready(stonith_t* stonith) +static gboolean +stonith_msgready(stonith_t * stonith) { stonith_private_t *private = NULL; - + if (stonith == NULL) { - crm_err("No STONITH!"); - return FALSE; + crm_err("No STONITH!"); + return FALSE; } private = stonith->private; - if(private->command_channel != NULL) { - /* drain the channel */ - IPC_Channel *cmd_ch = private->command_channel; - xmlNode *cmd_msg = NULL; - while(cmd_ch->ch_status != IPC_DISCONNECT - && cmd_ch->ops->is_message_pending(cmd_ch)) { - /* this will happen when the STONITH exited from beneath us */ - cmd_msg = xmlfromIPC(cmd_ch, MAX_IPC_DELAY); - free_xml(cmd_msg); - } + if (private->command_channel != NULL) { + /* drain the channel */ + IPC_Channel *cmd_ch = private->command_channel; + xmlNode *cmd_msg = NULL; + + while (cmd_ch->ch_status != IPC_DISCONNECT && cmd_ch->ops->is_message_pending(cmd_ch)) { + /* this will happen when the STONITH exited from beneath us */ + cmd_msg = xmlfromIPC(cmd_ch, MAX_IPC_DELAY); + free_xml(cmd_msg); + } } else { - crm_err("No command channel"); - } + crm_err("No command channel"); + } - if(private->callback_channel == NULL) { - crm_err("No callback channel"); - return FALSE; + if (private->callback_channel == NULL) { + crm_err("No callback channel"); + return FALSE; - } else if(private->callback_channel->ch_status == IPC_DISCONNECT) { - crm_info("Lost connection to the STONITH service [%d].", - private->callback_channel->farside_pid); - return FALSE; + } else if (private->callback_channel->ch_status == IPC_DISCONNECT) { + crm_info("Lost connection to the STONITH service [%d].", + private->callback_channel->farside_pid); + return FALSE; - } else if(private->callback_channel->ops->is_message_pending( - private->callback_channel)) { - crm_debug_4("Message pending on command channel [%d]", - private->callback_channel->farside_pid); - return TRUE; + } else if (private->callback_channel->ops->is_message_pending(private->callback_channel)) { + crm_debug_4("Message pending on command channel [%d]", + private->callback_channel->farside_pid); + return TRUE; } crm_debug_3("No message pending"); return FALSE; } -static int stonith_rcvmsg(stonith_t* stonith) +static int +stonith_rcvmsg(stonith_t * stonith) { const char *type = NULL; stonith_private_t *private = NULL; struct notify_blob_s blob; - + if (stonith == NULL) { - crm_err("No STONITH!"); - return FALSE; + crm_err("No STONITH!"); + return FALSE; } blob.stonith = stonith; private = stonith->private; - + /* if it is not blocking mode and no message in the channel, return */ if (stonith_msgready(stonith) == FALSE) { - crm_debug_3("No message ready and non-blocking..."); - return 0; + crm_debug_3("No message ready and non-blocking..."); + return 0; } /* IPC_INTR is not a factor here */ blob.xml = xmlfromIPC(private->callback_channel, MAX_IPC_DELAY); if (blob.xml == NULL) { - crm_warn("Received a NULL msg from STONITH service."); - return 0; + crm_warn("Received a NULL msg from STONITH service."); + return 0; } /* do callbacks */ type = crm_element_value(blob.xml, F_TYPE); crm_debug_4("Activating %s callbacks...", type); - if(safe_str_eq(type, T_STONITH_NG)) { - stonith_perform_callback(stonith, blob.xml, 0, 0); - - } else if(safe_str_eq(type, T_STONITH_NOTIFY)) { - g_list_foreach(private->notify_list, stonith_send_notification, &blob); + if (safe_str_eq(type, T_STONITH_NG)) { + stonith_perform_callback(stonith, blob.xml, 0, 0); + + } else if (safe_str_eq(type, T_STONITH_NOTIFY)) { + g_list_foreach(private->notify_list, stonith_send_notification, &blob); } else { - crm_err("Unknown message type: %s", type); - crm_log_xml_warn(blob.xml, "BadReply"); + crm_err("Unknown message type: %s", type); + crm_log_xml_warn(blob.xml, "BadReply"); } - + free_xml(blob.xml); return 1; } -bool stonith_dispatch(stonith_t *st) +bool +stonith_dispatch(stonith_t * st) { stonith_private_t *private = NULL; bool stay_connected = TRUE; - + CRM_CHECK(st != NULL, return FALSE); - + private = st->private; - - stay_connected = stonith_dispatch_internal(private->callback_channel, - (gpointer *)st); + + stay_connected = stonith_dispatch_internal(private->callback_channel, (gpointer *) st); return stay_connected; } -gboolean stonith_dispatch_internal(IPC_Channel *channel, gpointer user_data) +gboolean +stonith_dispatch_internal(IPC_Channel * channel, gpointer user_data) { stonith_t *stonith = user_data; stonith_private_t *private = NULL; gboolean stay_connected = TRUE; - + CRM_CHECK(stonith != NULL, return FALSE); - + private = stonith->private; CRM_CHECK(private->callback_channel == channel, return FALSE); - - while(stonith_msgready(stonith)) { - /* invoke the callbacks but dont block */ - int rc = stonith_rcvmsg(stonith); - if( rc < 0) { - crm_err("Message acquisition failed: %d", rc); - break; - } else if(rc == 0) { - break; - } + while (stonith_msgready(stonith)) { + /* invoke the callbacks but dont block */ + int rc = stonith_rcvmsg(stonith); + + if (rc < 0) { + crm_err("Message acquisition failed: %d", rc); + break; + + } else if (rc == 0) { + break; + } } - - if(private->callback_channel - && private->callback_channel->ch_status != IPC_CONNECT) { - crm_crit("Lost connection to the STONITH service [%d/callback].", - channel->farside_pid); - private->callback_source = NULL; - stay_connected = FALSE; + + if (private->callback_channel && private->callback_channel->ch_status != IPC_CONNECT) { + crm_crit("Lost connection to the STONITH service [%d/callback].", channel->farside_pid); + private->callback_source = NULL; + stay_connected = FALSE; } - - if(private->command_channel - && private->command_channel->ch_status != IPC_CONNECT) { - crm_crit("Lost connection to the STONITH service [%d/command].", - channel->farside_pid); - private->callback_source = NULL; - stay_connected = FALSE; + + if (private->command_channel && private->command_channel->ch_status != IPC_CONNECT) { + crm_crit("Lost connection to the STONITH service [%d/command].", channel->farside_pid); + private->callback_source = NULL; + stay_connected = FALSE; } return stay_connected; } -static int stonith_api_free (stonith_t* stonith) +static int +stonith_api_free(stonith_t * stonith) { int rc = stonith_ok; - if(stonith->state != stonith_disconnected) { - rc = stonith->cmds->disconnect(stonith); + if (stonith->state != stonith_disconnected) { + rc = stonith->cmds->disconnect(stonith); } - if(stonith->state == stonith_disconnected) { - stonith_private_t *private = stonith->private; - g_hash_table_destroy(private->stonith_op_callback_table); - crm_free(private->token); - crm_free(stonith->private); - crm_free(stonith->cmds); - crm_free(stonith); + if (stonith->state == stonith_disconnected) { + stonith_private_t *private = stonith->private; + + g_hash_table_destroy(private->stonith_op_callback_table); + crm_free(private->token); + crm_free(stonith->private); + crm_free(stonith->cmds); + crm_free(stonith); } - + return rc; } -void stonith_api_delete(stonith_t *stonith) +void +stonith_api_delete(stonith_t * stonith) { - stonith_private_t* private = stonith->private; + stonith_private_t *private = stonith->private; GList *list = private->notify_list; - while(list != NULL) { - stonith_notify_client_t *client = g_list_nth_data(list, 0); - list = g_list_remove(list, client); - crm_free(client); + + while (list != NULL) { + stonith_notify_client_t *client = g_list_nth_data(list, 0); + + list = g_list_remove(list, client); + crm_free(client); } - + stonith->cmds->free(stonith); stonith = NULL; } -stonith_t *stonith_api_new(void) +stonith_t * +stonith_api_new(void) { - stonith_t* new_stonith = NULL; - stonith_private_t* private = NULL; + stonith_t *new_stonith = NULL; + stonith_private_t *private = NULL; + crm_malloc0(new_stonith, sizeof(stonith_t)); crm_malloc0(private, sizeof(stonith_private_t)); new_stonith->private = private; - - private->stonith_op_callback_table = g_hash_table_new_full( - g_direct_hash, g_direct_equal, - NULL, stonith_destroy_op_callback); + + private->stonith_op_callback_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, stonith_destroy_op_callback); private->notify_list = NULL; new_stonith->call_id = 1; new_stonith->state = stonith_disconnected; - + crm_malloc0(new_stonith->cmds, sizeof(stonith_api_operations_t)); /* *INDENT-OFF* */ new_stonith->cmds->free = stonith_api_free; new_stonith->cmds->connect = stonith_api_signon; new_stonith->cmds->disconnect = stonith_api_signoff; new_stonith->cmds->call = stonith_api_call; new_stonith->cmds->fence = stonith_api_fence; new_stonith->cmds->confirm = stonith_api_confirm; new_stonith->cmds->history = stonith_api_history; new_stonith->cmds->list = stonith_api_device_list; new_stonith->cmds->metadata = stonith_api_device_metadata; new_stonith->cmds->query = stonith_api_query; new_stonith->cmds->remove_device = stonith_api_remove_device; new_stonith->cmds->register_device = stonith_api_register_device; new_stonith->cmds->remove_callback = stonith_api_del_callback; new_stonith->cmds->register_callback = stonith_api_add_callback; new_stonith->cmds->remove_notification = stonith_api_del_notification; new_stonith->cmds->register_notification = stonith_api_add_notification; /* *INDENT-ON* */ return new_stonith; } -stonith_key_value_t *stonith_key_value_add(stonith_key_value_t *kvp, const char *key, const char *value) { +stonith_key_value_t * +stonith_key_value_add(stonith_key_value_t * kvp, const char *key, const char *value) +{ stonith_key_value_t *p; crm_malloc(p, sizeof(stonith_key_value_t)); p->next = kvp; p->key = crm_strdup(key); p->value = crm_strdup(value); - return( p ); + return (p); } -void stonith_key_value_freeall(stonith_key_value_t *kvp, int keys, int values) { +void +stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values) +{ stonith_key_value_t *p; - while(kvp) { + while (kvp) { p = kvp->next; - if(keys) { - free(kvp->key); - } - if(values) { - free(kvp->value); - } + if (keys) { + free(kvp->key); + } + if (values) { + free(kvp->value); + } free(kvp); kvp = p; } } diff --git a/lib/pengine/clone.c b/lib/pengine/clone.c index 3a08ac97d4..83a1672bc5 100644 --- a/lib/pengine/clone.c +++ b/lib/pengine/clone.c @@ -1,513 +1,521 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #define VARIANT_CLONE 1 #include "./variant.h" -void clone_create_notifications( - resource_t *rsc, action_t *action, action_t *action_complete, - pe_working_set_t *data_set); -void force_non_unique_clone(resource_t *rsc, const char *rid, pe_working_set_t *data_set); -resource_t *create_child_clone(resource_t *rsc, int sub_id, pe_working_set_t *data_set); +void clone_create_notifications(resource_t * rsc, action_t * action, action_t * action_complete, + pe_working_set_t * data_set); +void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set); +resource_t *create_child_clone(resource_t * rsc, int sub_id, pe_working_set_t * data_set); -static void mark_as_orphan(resource_t *rsc) +static void +mark_as_orphan(resource_t * rsc) { GListPtr gIter = rsc->children; + set_bit(rsc->flags, pe_rsc_orphan); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - mark_as_orphan(child); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + mark_as_orphan(child); } } -static void clear_bit_recursive(resource_t *rsc, unsigned long long flag) +static void +clear_bit_recursive(resource_t * rsc, unsigned long long flag) { GListPtr gIter = rsc->children; + clear_bit_inplace(rsc->flags, flag); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - clear_bit_recursive(child_rsc, flag); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + clear_bit_recursive(child_rsc, flag); } } -void force_non_unique_clone(resource_t *rsc, const char *rid, pe_working_set_t *data_set) +void +force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set) { - if(rsc->variant == pe_clone || rsc->variant == pe_master) { - clone_variant_data_t *clone_data = NULL; - get_clone_variant_data(clone_data, rsc); - - crm_config_warn("Clones %s contains non-OCF resource %s and so " - "can only be used as an anonymous clone. " - "Set the "XML_RSC_ATTR_UNIQUE" meta attribute to false", - rsc->id, rid); - - clone_data->clone_node_max = 1; - clone_data->clone_max = g_list_length(data_set->nodes); - clear_bit_recursive(rsc, pe_rsc_unique); + if (rsc->variant == pe_clone || rsc->variant == pe_master) { + clone_variant_data_t *clone_data = NULL; + + get_clone_variant_data(clone_data, rsc); + + crm_config_warn("Clones %s contains non-OCF resource %s and so " + "can only be used as an anonymous clone. " + "Set the " XML_RSC_ATTR_UNIQUE " meta attribute to false", rsc->id, rid); + + clone_data->clone_node_max = 1; + clone_data->clone_max = g_list_length(data_set->nodes); + clear_bit_recursive(rsc, pe_rsc_unique); } } resource_t * -find_clone_instance(resource_t *rsc, const char *sub_id, pe_working_set_t *data_set) +find_clone_instance(resource_t * rsc, const char *sub_id, pe_working_set_t * data_set) { char *child_id = NULL; resource_t *child = NULL; const char *child_base = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); child_base = ID(clone_data->xml_obj_child); child_id = crm_concat(child_base, sub_id, ':'); child = pe_find_resource(rsc->children, child_id); crm_free(child_id); return child; } resource_t * -create_child_clone(resource_t *rsc, int sub_id, pe_working_set_t *data_set) +create_child_clone(resource_t * rsc, int sub_id, pe_working_set_t * data_set) { - gboolean as_orphan = FALSE; - char *inc_num = NULL; - char *inc_max = NULL; - resource_t *child_rsc = NULL; - xmlNode * child_copy = NULL; - clone_variant_data_t *clone_data = NULL; - get_clone_variant_data(clone_data, rsc); - - CRM_CHECK(clone_data->xml_obj_child != NULL, return FALSE); - - if(sub_id < 0) { - as_orphan = TRUE; - sub_id = clone_data->total_clones; - } - inc_num = crm_itoa(sub_id); - inc_max = crm_itoa(clone_data->clone_max); - - child_copy = copy_xml(clone_data->xml_obj_child); - - crm_xml_add(child_copy, XML_RSC_ATTR_INCARNATION, inc_num); - - if(common_unpack(child_copy, &child_rsc, - rsc, data_set) == FALSE) { - pe_err("Failed unpacking resource %s", - crm_element_value(child_copy, XML_ATTR_ID)); - child_rsc = NULL; - goto bail; - } + gboolean as_orphan = FALSE; + char *inc_num = NULL; + char *inc_max = NULL; + resource_t *child_rsc = NULL; + xmlNode *child_copy = NULL; + clone_variant_data_t *clone_data = NULL; + + get_clone_variant_data(clone_data, rsc); + + CRM_CHECK(clone_data->xml_obj_child != NULL, return FALSE); + + if (sub_id < 0) { + as_orphan = TRUE; + sub_id = clone_data->total_clones; + } + inc_num = crm_itoa(sub_id); + inc_max = crm_itoa(clone_data->clone_max); + + child_copy = copy_xml(clone_data->xml_obj_child); + + crm_xml_add(child_copy, XML_RSC_ATTR_INCARNATION, inc_num); + + if (common_unpack(child_copy, &child_rsc, rsc, data_set) == FALSE) { + pe_err("Failed unpacking resource %s", crm_element_value(child_copy, XML_ATTR_ID)); + child_rsc = NULL; + goto bail; + } /* child_rsc->globally_unique = rsc->globally_unique; */ - clone_data->total_clones += 1; - crm_debug_2("Setting clone attributes for: %s", child_rsc->id); - rsc->children = g_list_append(rsc->children, child_rsc); - if(as_orphan) { - mark_as_orphan(child_rsc); - } - - add_hash_param(child_rsc->meta, XML_RSC_ATTR_INCARNATION_MAX, inc_max); - - print_resource(LOG_DEBUG_3, "Added", child_rsc, FALSE); + clone_data->total_clones += 1; + crm_debug_2("Setting clone attributes for: %s", child_rsc->id); + rsc->children = g_list_append(rsc->children, child_rsc); + if (as_orphan) { + mark_as_orphan(child_rsc); + } + + add_hash_param(child_rsc->meta, XML_RSC_ATTR_INCARNATION_MAX, inc_max); + + print_resource(LOG_DEBUG_3, "Added", child_rsc, FALSE); bail: - crm_free(inc_num); - crm_free(inc_max); - - return child_rsc; + crm_free(inc_num); + crm_free(inc_max); + + return child_rsc; } -gboolean master_unpack(resource_t *rsc, pe_working_set_t *data_set) +gboolean +master_unpack(resource_t * rsc, pe_working_set_t * data_set) { - const char *master_max = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_MASTER_MAX); - const char *master_node_max = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_MASTER_NODEMAX); - - g_hash_table_replace(rsc->meta, crm_strdup("stateful"), crm_strdup(XML_BOOLEAN_TRUE)); - if(clone_unpack(rsc, data_set)) { - clone_variant_data_t *clone_data = NULL; - get_clone_variant_data(clone_data, rsc); - clone_data->master_max = crm_parse_int(master_max, "1"); - clone_data->master_node_max = crm_parse_int(master_node_max, "1"); - return TRUE; - } - return FALSE; + const char *master_max = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_MASTER_MAX); + const char *master_node_max = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_MASTER_NODEMAX); + + g_hash_table_replace(rsc->meta, crm_strdup("stateful"), crm_strdup(XML_BOOLEAN_TRUE)); + if (clone_unpack(rsc, data_set)) { + clone_variant_data_t *clone_data = NULL; + + get_clone_variant_data(clone_data, rsc); + clone_data->master_max = crm_parse_int(master_max, "1"); + clone_data->master_node_max = crm_parse_int(master_node_max, "1"); + return TRUE; + } + return FALSE; } -gboolean clone_unpack(resource_t *rsc, pe_working_set_t *data_set) +gboolean +clone_unpack(resource_t * rsc, pe_working_set_t * data_set) { - int lpc = 0; - const char *type = NULL; - resource_t *self = NULL; - int num_xml_children = 0; - xmlNode *a_child = NULL; - xmlNode *xml_tmp = NULL; - xmlNode *xml_self = NULL; - xmlNode *xml_obj = rsc->xml; - clone_variant_data_t *clone_data = NULL; - - const char *ordered = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_ORDERED); - const char *interleave = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_INTERLEAVE); - const char *max_clones = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_INCARNATION_MAX); - const char *max_clones_node = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX); - - crm_debug_3("Processing resource %s...", rsc->id); - - crm_malloc0(clone_data, sizeof(clone_variant_data_t)); - rsc->variant_opaque = clone_data; - clone_data->interleave = FALSE; - clone_data->ordered = FALSE; - - clone_data->active_clones = 0; - clone_data->xml_obj_child = NULL; - clone_data->clone_node_max = crm_parse_int(max_clones_node, "1"); - - if(max_clones) { - clone_data->clone_max = crm_parse_int(max_clones, "1"); - - } else if(g_list_length(data_set->nodes) > 0) { - clone_data->clone_max = g_list_length(data_set->nodes); - - } else { - clone_data->clone_max = 1; /* Handy during crm_verify */ - } - - if(crm_is_true(interleave)) { - clone_data->interleave = TRUE; - } - if(crm_is_true(ordered)) { - clone_data->ordered = TRUE; - } - if((rsc->flags & pe_rsc_unique) == 0 && clone_data->clone_node_max > 1) { - crm_config_err("Anonymous clones (%s) may only support one copy" - " per node", rsc->id); - clone_data->clone_node_max = 1; - } - - crm_debug_2("Options for %s", rsc->id); - crm_debug_2("\tClone max: %d", clone_data->clone_max); - crm_debug_2("\tClone node max: %d", clone_data->clone_node_max); - crm_debug_2("\tClone is unique: %s", is_set(rsc->flags, pe_rsc_unique)?"true":"false"); - - clone_data->xml_obj_child = find_xml_node( - xml_obj, XML_CIB_TAG_GROUP, FALSE); - - if(clone_data->xml_obj_child == NULL) { - clone_data->xml_obj_child = find_xml_node(xml_obj, XML_CIB_TAG_RESOURCE, TRUE); - for(a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { - if(crm_str_eq((const char *)a_child->name, XML_CIB_TAG_RESOURCE, TRUE)) { - num_xml_children++; - } - } - } - - if(clone_data->xml_obj_child == NULL) { - crm_config_err("%s has nothing to clone", rsc->id); - return FALSE; - } - - for(a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { - if(crm_str_eq((const char *)a_child->name, type, TRUE)) { - num_xml_children++; - } - } - - if(num_xml_children > 1) { - crm_config_err("%s has too many children. Only the first (%s) will be cloned.", - rsc->id, ID(clone_data->xml_obj_child)); - } - - xml_self = copy_xml(rsc->xml); - /* this is a bit of a hack - but simplifies everything else */ - xmlNodeSetName(xml_self, ((const xmlChar*)XML_CIB_TAG_RESOURCE)); - xml_tmp = find_xml_node(xml_obj, "operations", FALSE); - if(xml_tmp != NULL) { - add_node_copy(xml_self, xml_tmp); - } - - /* - * Make clones ever so slightly sticky by default - * - * This helps ensure clone instances are not shuffled around the cluster - * for no benefit in situations when pre-allocation is not appropriate - */ - if(g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_STICKINESS) == NULL) { - add_hash_param(rsc->meta, XML_RSC_ATTR_STICKINESS, "1"); - } - - if(common_unpack(xml_self, &self, rsc, data_set)) { - clone_data->self = self; - - } else { - crm_log_xml_err(xml_self, "Couldnt unpack dummy child"); - clone_data->self = self; - return FALSE; - } - - crm_debug_2("\tClone is unique (fixed): %s", is_set(rsc->flags, pe_rsc_unique)?"true":"false"); - clone_data->notify_confirm = is_set(rsc->flags, pe_rsc_notify); - add_hash_param(rsc->meta, XML_RSC_ATTR_UNIQUE, - is_set(rsc->flags, pe_rsc_unique)?XML_BOOLEAN_TRUE:XML_BOOLEAN_FALSE); - - for(lpc = 0; lpc < clone_data->clone_max; lpc++) { - create_child_clone(rsc, lpc, data_set); - } - - if(clone_data->clone_max == 0) { - /* create one so that unpack_find_resource() will hook up - * any orphans up to the parent correctly - */ - create_child_clone(rsc, -1, data_set); - } - - crm_debug_3("Added %d children to resource %s...", - clone_data->clone_max, rsc->id); - return TRUE; + int lpc = 0; + const char *type = NULL; + resource_t *self = NULL; + int num_xml_children = 0; + xmlNode *a_child = NULL; + xmlNode *xml_tmp = NULL; + xmlNode *xml_self = NULL; + xmlNode *xml_obj = rsc->xml; + clone_variant_data_t *clone_data = NULL; + + const char *ordered = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ORDERED); + const char *interleave = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERLEAVE); + const char *max_clones = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_MAX); + const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX); + + crm_debug_3("Processing resource %s...", rsc->id); + + crm_malloc0(clone_data, sizeof(clone_variant_data_t)); + rsc->variant_opaque = clone_data; + clone_data->interleave = FALSE; + clone_data->ordered = FALSE; + + clone_data->active_clones = 0; + clone_data->xml_obj_child = NULL; + clone_data->clone_node_max = crm_parse_int(max_clones_node, "1"); + + if (max_clones) { + clone_data->clone_max = crm_parse_int(max_clones, "1"); + + } else if (g_list_length(data_set->nodes) > 0) { + clone_data->clone_max = g_list_length(data_set->nodes); + + } else { + clone_data->clone_max = 1; /* Handy during crm_verify */ + } + + if (crm_is_true(interleave)) { + clone_data->interleave = TRUE; + } + if (crm_is_true(ordered)) { + clone_data->ordered = TRUE; + } + if ((rsc->flags & pe_rsc_unique) == 0 && clone_data->clone_node_max > 1) { + crm_config_err("Anonymous clones (%s) may only support one copy" " per node", rsc->id); + clone_data->clone_node_max = 1; + } + + crm_debug_2("Options for %s", rsc->id); + crm_debug_2("\tClone max: %d", clone_data->clone_max); + crm_debug_2("\tClone node max: %d", clone_data->clone_node_max); + crm_debug_2("\tClone is unique: %s", is_set(rsc->flags, pe_rsc_unique) ? "true" : "false"); + + clone_data->xml_obj_child = find_xml_node(xml_obj, XML_CIB_TAG_GROUP, FALSE); + + if (clone_data->xml_obj_child == NULL) { + clone_data->xml_obj_child = find_xml_node(xml_obj, XML_CIB_TAG_RESOURCE, TRUE); + for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { + if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_RESOURCE, TRUE)) { + num_xml_children++; + } + } + } + + if (clone_data->xml_obj_child == NULL) { + crm_config_err("%s has nothing to clone", rsc->id); + return FALSE; + } + + for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) { + if (crm_str_eq((const char *)a_child->name, type, TRUE)) { + num_xml_children++; + } + } + + if (num_xml_children > 1) { + crm_config_err("%s has too many children. Only the first (%s) will be cloned.", + rsc->id, ID(clone_data->xml_obj_child)); + } + + xml_self = copy_xml(rsc->xml); + /* this is a bit of a hack - but simplifies everything else */ + xmlNodeSetName(xml_self, ((const xmlChar *)XML_CIB_TAG_RESOURCE)); + xml_tmp = find_xml_node(xml_obj, "operations", FALSE); + if (xml_tmp != NULL) { + add_node_copy(xml_self, xml_tmp); + } + + /* + * Make clones ever so slightly sticky by default + * + * This helps ensure clone instances are not shuffled around the cluster + * for no benefit in situations when pre-allocation is not appropriate + */ + if (g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_STICKINESS) == NULL) { + add_hash_param(rsc->meta, XML_RSC_ATTR_STICKINESS, "1"); + } + + if (common_unpack(xml_self, &self, rsc, data_set)) { + clone_data->self = self; + + } else { + crm_log_xml_err(xml_self, "Couldnt unpack dummy child"); + clone_data->self = self; + return FALSE; + } + + crm_debug_2("\tClone is unique (fixed): %s", + is_set(rsc->flags, pe_rsc_unique) ? "true" : "false"); + clone_data->notify_confirm = is_set(rsc->flags, pe_rsc_notify); + add_hash_param(rsc->meta, XML_RSC_ATTR_UNIQUE, + is_set(rsc->flags, pe_rsc_unique) ? XML_BOOLEAN_TRUE : XML_BOOLEAN_FALSE); + + for (lpc = 0; lpc < clone_data->clone_max; lpc++) { + create_child_clone(rsc, lpc, data_set); + } + + if (clone_data->clone_max == 0) { + /* create one so that unpack_find_resource() will hook up + * any orphans up to the parent correctly + */ + create_child_clone(rsc, -1, data_set); + } + + crm_debug_3("Added %d children to resource %s...", clone_data->clone_max, rsc->id); + return TRUE; } -gboolean clone_active(resource_t *rsc, gboolean all) +gboolean +clone_active(resource_t * rsc, gboolean all) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - gboolean child_active = child_rsc->fns->active(child_rsc, all); - - if(all == FALSE && child_active) { - return TRUE; - } else if(all && child_active == FALSE) { - return FALSE; - } - } - - if(all) { - return TRUE; + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + gboolean child_active = child_rsc->fns->active(child_rsc, all); + + if (all == FALSE && child_active) { + return TRUE; + } else if (all && child_active == FALSE) { + return FALSE; + } + } + + if (all) { + return TRUE; } else { - return FALSE; + return FALSE; } } static char * -add_list_element(char *list, const char *value) +add_list_element(char *list, const char *value) { int len = 0; int last = 0; - if(value == NULL) { - return list; + if (value == NULL) { + return list; } - if(list) { - last = strlen(list); + if (list) { + last = strlen(list); } - len = last + 2; /* +1 space, +1 EOS */ + len = last + 2; /* +1 space, +1 EOS */ len += strlen(value); crm_realloc(list, len); sprintf(list + last, " %s", value); return list; } static void -short_print(char *list, const char *prefix, const char *type, long options, void *print_data) +short_print(char *list, const char *prefix, const char *type, long options, void *print_data) { - if(list) { - if(options & pe_print_html) { - status_print("
  • "); - } - status_print("%s%s: [%s ]", prefix, type, list); + if (list) { + if (options & pe_print_html) { + status_print("
  • "); + } + status_print("%s%s: [%s ]", prefix, type, list); - if(options & pe_print_html) { - status_print("
  • \n"); + if (options & pe_print_html) { + status_print("\n"); - } else if(options & pe_print_suppres_nl) { - /* nothing */ - } else if((options & pe_print_printf) || (options & pe_print_ncurses)) { - status_print("\n"); - } + } else if (options & pe_print_suppres_nl) { + /* nothing */ + } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { + status_print("\n"); + } } } -void clone_print( - resource_t *rsc, const char *pre_text, long options, void *print_data) +void +clone_print(resource_t * rsc, const char *pre_text, long options, void *print_data) { char *child_text = NULL; char *master_list = NULL; char *started_list = NULL; char *stopped_list = NULL; const char *type = "Clone"; GListPtr gIter = rsc->children; - + clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - if(pre_text == NULL) { pre_text = " "; } + if (pre_text == NULL) { + pre_text = " "; + } child_text = crm_concat(pre_text, " ", ' '); - if(rsc->variant == pe_master) { - type = "Master/Slave"; + if (rsc->variant == pe_master) { + type = "Master/Slave"; } status_print("%s%s Set: %s [%s]%s%s", - pre_text?pre_text:"", type, rsc->id, ID(clone_data->xml_obj_child), - is_set(rsc->flags, pe_rsc_unique)?" (unique)":"", - is_set(rsc->flags, pe_rsc_managed)?"":" (unmanaged)"); - - if(options & pe_print_html) { - status_print("\n
      \n"); - - } else if((options & pe_print_log) == 0) { - status_print("\n"); - } - - for(; gIter != NULL; gIter = gIter->next) { - gboolean print_full = FALSE; - resource_t *child_rsc = (resource_t*)gIter->data; - - if(child_rsc->fns->active(child_rsc, FALSE) == FALSE) { - /* Inactive clone */ - if(is_set(child_rsc->flags, pe_rsc_orphan)) { - continue; - - } else if(is_set(rsc->flags, pe_rsc_unique)) { - print_full = TRUE; - } else { - stopped_list = add_list_element(stopped_list, child_rsc->id); - } - - } else if(is_set(child_rsc->flags, pe_rsc_unique) - || is_set(child_rsc->flags, pe_rsc_orphan) - || is_set(child_rsc->flags, pe_rsc_managed) == FALSE - || is_set(child_rsc->flags, pe_rsc_failed)) { - - /* Unique, unmanaged or failed clone */ - print_full = TRUE; - - } else if(child_rsc->fns->active(child_rsc, TRUE)) { - /* Fully active anonymous clone */ - node_t *location = child_rsc->fns->location(child_rsc, NULL, TRUE); - - if(location) { - const char *host = location->details->uname; - enum rsc_role_e a_role = child_rsc->fns->state(child_rsc, TRUE); - - if(a_role > RSC_ROLE_SLAVE) { - /* And active on a single node as master */ - master_list = add_list_element(master_list, host); - - } else { - /* And active on a single node as started/slave */ - started_list = add_list_element(started_list, host); - } - - } else { - /* uncolocated group - bleh */ - print_full = TRUE; - } - - } else { - /* Partially active anonymous clone */ - print_full = TRUE; - } - - if(print_full) { - if(options & pe_print_html) { - status_print("
    • \n"); - } - child_rsc->fns->print( - child_rsc, child_text, options, print_data); - if(options & pe_print_html) { - status_print("
    • \n"); - } - } - } - + pre_text ? pre_text : "", type, rsc->id, ID(clone_data->xml_obj_child), + is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "", + is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)"); + + if (options & pe_print_html) { + status_print("\n
        \n"); + + } else if ((options & pe_print_log) == 0) { + status_print("\n"); + } + + for (; gIter != NULL; gIter = gIter->next) { + gboolean print_full = FALSE; + resource_t *child_rsc = (resource_t *) gIter->data; + + if (child_rsc->fns->active(child_rsc, FALSE) == FALSE) { + /* Inactive clone */ + if (is_set(child_rsc->flags, pe_rsc_orphan)) { + continue; + + } else if (is_set(rsc->flags, pe_rsc_unique)) { + print_full = TRUE; + } else { + stopped_list = add_list_element(stopped_list, child_rsc->id); + } + + } else if (is_set(child_rsc->flags, pe_rsc_unique) + || is_set(child_rsc->flags, pe_rsc_orphan) + || is_set(child_rsc->flags, pe_rsc_managed) == FALSE + || is_set(child_rsc->flags, pe_rsc_failed)) { + + /* Unique, unmanaged or failed clone */ + print_full = TRUE; + + } else if (child_rsc->fns->active(child_rsc, TRUE)) { + /* Fully active anonymous clone */ + node_t *location = child_rsc->fns->location(child_rsc, NULL, TRUE); + + if (location) { + const char *host = location->details->uname; + enum rsc_role_e a_role = child_rsc->fns->state(child_rsc, TRUE); + + if (a_role > RSC_ROLE_SLAVE) { + /* And active on a single node as master */ + master_list = add_list_element(master_list, host); + + } else { + /* And active on a single node as started/slave */ + started_list = add_list_element(started_list, host); + } + + } else { + /* uncolocated group - bleh */ + print_full = TRUE; + } + + } else { + /* Partially active anonymous clone */ + print_full = TRUE; + } + + if (print_full) { + if (options & pe_print_html) { + status_print("
      • \n"); + } + child_rsc->fns->print(child_rsc, child_text, options, print_data); + if (options & pe_print_html) { + status_print("
      • \n"); + } + } + } + short_print(master_list, child_text, "Masters", options, print_data); - short_print(started_list, child_text, rsc->variant==pe_master?"Slaves":"Started", options, print_data); + short_print(started_list, child_text, rsc->variant == pe_master ? "Slaves" : "Started", options, + print_data); short_print(stopped_list, child_text, "Stopped", options, print_data); crm_free(master_list); crm_free(started_list); - crm_free(stopped_list); - - if(options & pe_print_html) { - status_print("
      \n"); + crm_free(stopped_list); + + if (options & pe_print_html) { + status_print("
    \n"); } crm_free(child_text); } -void clone_free(resource_t *rsc) +void +clone_free(resource_t * rsc) { GListPtr gIter = rsc->children; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); crm_debug_3("Freeing %s", rsc->id); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; - crm_debug_3("Freeing child %s", child_rsc->id); - free_xml(child_rsc->xml); - child_rsc->fns->free(child_rsc); + crm_debug_3("Freeing child %s", child_rsc->id); + free_xml(child_rsc->xml); + child_rsc->fns->free(child_rsc); } g_list_free(rsc->children); - if(clone_data->self) { - free_xml(clone_data->self->xml); - clone_data->self->fns->free(clone_data->self); + if (clone_data->self) { + free_xml(clone_data->self->xml); + clone_data->self->fns->free(clone_data->self); } CRM_ASSERT(clone_data->demote_notify == NULL); CRM_ASSERT(clone_data->stop_notify == NULL); CRM_ASSERT(clone_data->start_notify == NULL); CRM_ASSERT(clone_data->promote_notify == NULL); - + common_free(rsc); } enum rsc_role_e -clone_resource_state(const resource_t *rsc, gboolean current) +clone_resource_state(const resource_t * rsc, gboolean current) { enum rsc_role_e clone_role = RSC_ROLE_UNKNOWN; GListPtr gIter = rsc->children; - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - enum rsc_role_e a_role = child_rsc->fns->state(child_rsc, current); - if(a_role > clone_role) { - clone_role = a_role; - } + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + enum rsc_role_e a_role = child_rsc->fns->state(child_rsc, current); + + if (a_role > clone_role) { + clone_role = a_role; + } } - + crm_debug_3("%s role: %s", rsc->id, role2text(clone_role)); return clone_role; } diff --git a/lib/pengine/common.c b/lib/pengine/common.c index 44ed0edb5f..443dbd3837 100644 --- a/lib/pengine/common.c +++ b/lib/pengine/common.c @@ -1,439 +1,434 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 gboolean was_processing_error = FALSE; gboolean was_processing_warning = FALSE; static gboolean -check_quorum(const char *value) +check_quorum(const char *value) { - if(safe_str_eq(value, "stop")) { - return TRUE; + if (safe_str_eq(value, "stop")) { + return TRUE; - } else if(safe_str_eq(value, "freeze")) { - return TRUE; + } else if (safe_str_eq(value, "freeze")) { + return TRUE; - } else if(safe_str_eq(value, "ignore")) { - return TRUE; + } else if (safe_str_eq(value, "ignore")) { + return TRUE; - } else if(safe_str_eq(value, "suicide")) { - return TRUE; - } - return FALSE; + } else if (safe_str_eq(value, "suicide")) { + return TRUE; + } + return FALSE; } static gboolean -check_health(const char *value) +check_health(const char *value) { - if(safe_str_eq(value, "none")) { - return TRUE; + if (safe_str_eq(value, "none")) { + return TRUE; - } else if(safe_str_eq(value, "custom")) { - return TRUE; + } else if (safe_str_eq(value, "custom")) { + return TRUE; - } else if(safe_str_eq(value, "only-green")) { - return TRUE; + } else if (safe_str_eq(value, "only-green")) { + return TRUE; - } else if(safe_str_eq(value, "progressive")) { - return TRUE; + } else if (safe_str_eq(value, "progressive")) { + return TRUE; - } else if(safe_str_eq(value, "migrate-on-red")) { - return TRUE; - } - return FALSE; + } else if (safe_str_eq(value, "migrate-on-red")) { + return TRUE; + } + return FALSE; } static gboolean -check_stonith_action(const char *value) +check_stonith_action(const char *value) { - if(safe_str_eq(value, "reboot")) { - return TRUE; + if (safe_str_eq(value, "reboot")) { + return TRUE; - } else if(safe_str_eq(value, "poweroff")) { - return TRUE; - } - return FALSE; + } else if (safe_str_eq(value, "poweroff")) { + return TRUE; + } + return FALSE; } static gboolean check_placement_strategy(const char *value) { - if(safe_str_eq(value, "default")) { - return TRUE; + if (safe_str_eq(value, "default")) { + return TRUE; - } else if(safe_str_eq(value, "utilization")) { - return TRUE; + } else if (safe_str_eq(value, "utilization")) { + return TRUE; - } else if(safe_str_eq(value, "minimal")) { - return TRUE; + } else if (safe_str_eq(value, "minimal")) { + return TRUE; - } else if(safe_str_eq(value, "balanced")) { - return TRUE; - } - return FALSE; + } else if (safe_str_eq(value, "balanced")) { + return TRUE; + } + return FALSE; } /* *INDENT-OFF* */ pe_cluster_option pe_opts[] = { /* name, old-name, validate, default, description */ { "no-quorum-policy", "no_quorum_policy", "enum", "stop, freeze, ignore, suicide", "stop", &check_quorum, "What to do when the cluster does not have quorum", NULL }, { "symmetric-cluster", "symmetric_cluster", "boolean", NULL, "true", &check_boolean, "All resources can run anywhere by default", NULL }, { "default-resource-stickiness", "default_resource_stickiness", "integer", NULL, "0", &check_number, "", NULL }, { "is-managed-default", "is_managed_default", "boolean", NULL, "true", &check_boolean, "Should the cluster start/stop resources as required", NULL }, { "maintenance-mode", NULL, "boolean", NULL, "false", &check_boolean, "Should the cluster monitor resources and start/stop them as required", NULL }, { "start-failure-is-fatal", NULL, "boolean", NULL, "true", &check_boolean, "Always treat start failures as fatal", "This was the old default. However when set to FALSE, the cluster will instead use the resource's failcount and value for resource-failure-stickiness" }, { "enable-startup-probes", NULL, "boolean", NULL, "true", &check_boolean, "Should the cluster check for active resources during startup", NULL }, /* Stonith Options */ { "stonith-enabled", "stonith_enabled", "boolean", NULL, "true", &check_boolean, "Failed nodes are STONITH'd", NULL }, { "stonith-action", "stonith_action", "enum", "reboot, poweroff", "reboot", &check_stonith_action, "Action to send to STONITH device", NULL }, { "stonith-timeout", NULL, "time", NULL, "60s", &check_timer, "How long to wait for the STONITH action to complete", NULL }, { "startup-fencing", "startup_fencing", "boolean", NULL, "true", &check_boolean, "STONITH unseen nodes", "Advanced Use Only! Not using the default is very unsafe!" }, /* Timeouts etc */ { "cluster-delay", "transition_idle_timeout", "time", NULL, "60s", &check_time, "Round trip delay over the network (excluding action execution)", "The \"correct\" value will depend on the speed and load of your network and cluster nodes." }, { "batch-limit", NULL, "integer", NULL, "30", &check_number, "The number of jobs that the TE is allowed to execute in parallel", "The \"correct\" value will depend on the speed and load of your network and cluster nodes." }, { "default-action-timeout", "default_action_timeout", "time", NULL, "20s", &check_time, "How long to wait for actions to complete", NULL }, /* Orphans and stopping */ { "stop-all-resources", NULL, "boolean", NULL, "false", &check_boolean, "Should the cluster stop all active resources (except those needed for fencing)", NULL }, { "stop-orphan-resources", "stop_orphan_resources", "boolean", NULL, "true", &check_boolean, "Should deleted resources be stopped", NULL }, { "stop-orphan-actions", "stop_orphan_actions", "boolean", NULL, "true", &check_boolean, "Should deleted actions be cancelled", NULL }, { "remove-after-stop", "remove_after_stop", "boolean", NULL, "false", &check_boolean, "Remove resources from the LRM after they are stopped", "Always set this to false. Other values are, at best, poorly tested and potentially dangerous." }, /* { "", "", , "0", "", NULL }, */ /* Storing inputs */ { "pe-error-series-max", NULL, "integer", NULL, "-1", &check_number, "The number of PE inputs resulting in ERRORs to save", "Zero to disable, -1 to store unlimited." }, { "pe-warn-series-max", NULL, "integer", NULL, "5000", &check_number, "The number of PE inputs resulting in WARNINGs to save", "Zero to disable, -1 to store unlimited." }, { "pe-input-series-max", NULL, "integer", NULL, "4000", &check_number, "The number of other PE inputs to save", "Zero to disable, -1 to store unlimited." }, /* Node health */ { "node-health-strategy", NULL, "enum", "none, migrate-on-red, only-green, progressive, custom", "none", &check_health, "The strategy combining node attributes to determine overall node health.", "Requires external entities to create node attributes (named with the prefix '#health') with values: 'red', 'yellow' or 'green'."}, { "node-health-green", NULL, "integer", NULL, "0", &check_number, "The score 'green' translates to in rsc_location constraints", "Only used when node-health-strategy is set to custom or progressive." }, { "node-health-yellow", NULL, "integer", NULL, "0", &check_number, "The score 'yellow' translates to in rsc_location constraints", "Only used when node-health-strategy is set to custom or progressive." }, { "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number, "The score 'red' translates to in rsc_location constraints", "Only used when node-health-strategy is set to custom or progressive." }, /*Placement Strategy*/ { "placement-strategy", NULL, "enum", "default, utilization, minimal, balanced", "default", &check_placement_strategy, "The strategy to determine resource placement", NULL}, }; /* *INDENT-ON* */ void pe_metadata(void) { - config_metadata("Policy Engine", "1.0", - "Policy Engine Options", - "This is a fake resource that details the options that can be configured for the Policy Engine.", - pe_opts, DIMOF(pe_opts)); + config_metadata("Policy Engine", "1.0", + "Policy Engine Options", + "This is a fake resource that details the options that can be configured for the Policy Engine.", + pe_opts, DIMOF(pe_opts)); } void -verify_pe_options(GHashTable *options) +verify_pe_options(GHashTable * options) { - verify_all_options(options, pe_opts, DIMOF(pe_opts)); + verify_all_options(options, pe_opts, DIMOF(pe_opts)); } const char * -pe_pref(GHashTable *options, const char *name) +pe_pref(GHashTable * options, const char *name) { - return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name); + return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name); } const char * fail2text(enum action_fail_response fail) { - const char *result = ""; - switch(fail) - { - case action_fail_ignore: - result = "ignore"; - break; - case action_fail_block: - result = "block"; - break; - case action_fail_recover: - result = "recover"; - break; - case action_fail_migrate: - result = "migrate"; - break; - case action_fail_stop: - result = "stop"; - break; - case action_fail_fence: - result = "fence"; - break; - case action_fail_standby: - result = "standby"; - break; - } - return result; + const char *result = ""; + + switch (fail) { + case action_fail_ignore: + result = "ignore"; + break; + case action_fail_block: + result = "block"; + break; + case action_fail_recover: + result = "recover"; + break; + case action_fail_migrate: + result = "migrate"; + break; + case action_fail_stop: + result = "stop"; + break; + case action_fail_fence: + result = "fence"; + break; + case action_fail_standby: + result = "standby"; + break; + } + return result; } - - enum action_tasks -text2task(const char *task) +text2task(const char *task) { - if(safe_str_eq(task, CRMD_ACTION_STOP)) { - return stop_rsc; - } else if(safe_str_eq(task, CRMD_ACTION_STOPPED)) { - return stopped_rsc; - } else if(safe_str_eq(task, CRMD_ACTION_START)) { - return start_rsc; - } else if(safe_str_eq(task, CRMD_ACTION_STARTED)) { - return started_rsc; - } else if(safe_str_eq(task, CRM_OP_SHUTDOWN)) { - return shutdown_crm; - } else if(safe_str_eq(task, CRM_OP_FENCE)) { - return stonith_node; - } else if(safe_str_eq(task, CRMD_ACTION_STATUS)) { - return monitor_rsc; - } else if(safe_str_eq(task, CRMD_ACTION_NOTIFY)) { - return action_notify; - } else if(safe_str_eq(task, CRMD_ACTION_NOTIFIED)) { - return action_notified; - } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { - return action_promote; - } else if(safe_str_eq(task, CRMD_ACTION_DEMOTE)) { - return action_demote; - } else if(safe_str_eq(task, CRMD_ACTION_PROMOTED)) { - return action_promoted; - } else if(safe_str_eq(task, CRMD_ACTION_DEMOTED)) { - return action_demoted; - } - + if (safe_str_eq(task, CRMD_ACTION_STOP)) { + return stop_rsc; + } else if (safe_str_eq(task, CRMD_ACTION_STOPPED)) { + return stopped_rsc; + } else if (safe_str_eq(task, CRMD_ACTION_START)) { + return start_rsc; + } else if (safe_str_eq(task, CRMD_ACTION_STARTED)) { + return started_rsc; + } else if (safe_str_eq(task, CRM_OP_SHUTDOWN)) { + return shutdown_crm; + } else if (safe_str_eq(task, CRM_OP_FENCE)) { + return stonith_node; + } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) { + return monitor_rsc; + } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) { + return action_notify; + } else if (safe_str_eq(task, CRMD_ACTION_NOTIFIED)) { + return action_notified; + } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) { + return action_promote; + } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) { + return action_demote; + } else if (safe_str_eq(task, CRMD_ACTION_PROMOTED)) { + return action_promoted; + } else if (safe_str_eq(task, CRMD_ACTION_DEMOTED)) { + return action_demoted; + } #if SUPPORT_TRACING - if(safe_str_eq(task, CRMD_ACTION_CANCEL)) { - return no_action; - } else if(safe_str_eq(task, CRMD_ACTION_DELETE)) { - return no_action; - } else if(safe_str_eq(task, CRMD_ACTION_STATUS)) { - return no_action; - } else if(safe_str_eq(task, CRM_OP_PROBED)) { - return no_action; - } else if(safe_str_eq(task, CRM_OP_LRM_REFRESH)) { - return no_action; - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATE)) { - return no_action; - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATED)) { - return no_action; - } else if(safe_str_eq(task, "fail")) { - return no_action; - } else if(safe_str_eq(task, "stonith_up")) { - return no_action; - } else if(safe_str_eq(task, "stonith_complete")) { - return no_action; - } else if(safe_str_eq(task, "all_stopped")) { - return no_action; - } - crm_trace("Unsupported action: %s", task); + if (safe_str_eq(task, CRMD_ACTION_CANCEL)) { + return no_action; + } else if (safe_str_eq(task, CRMD_ACTION_DELETE)) { + return no_action; + } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) { + return no_action; + } else if (safe_str_eq(task, CRM_OP_PROBED)) { + return no_action; + } else if (safe_str_eq(task, CRM_OP_LRM_REFRESH)) { + return no_action; + } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) { + return no_action; + } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) { + return no_action; + } else if (safe_str_eq(task, "fail")) { + return no_action; + } else if (safe_str_eq(task, "stonith_up")) { + return no_action; + } else if (safe_str_eq(task, "stonith_complete")) { + return no_action; + } else if (safe_str_eq(task, "all_stopped")) { + return no_action; + } + crm_trace("Unsupported action: %s", task); #endif - return no_action; + return no_action; } - const char * task2text(enum action_tasks task) { - const char *result = ""; - switch(task) - { - case no_action: - result = "no_action"; - break; - case stop_rsc: - result = CRMD_ACTION_STOP; - break; - case stopped_rsc: - result = CRMD_ACTION_STOPPED; - break; - case start_rsc: - result = CRMD_ACTION_START; - break; - case started_rsc: - result = CRMD_ACTION_STARTED; - break; - case shutdown_crm: - result = CRM_OP_SHUTDOWN; - break; - case stonith_node: - result = CRM_OP_FENCE; - break; - case monitor_rsc: - result = CRMD_ACTION_STATUS; - break; - case action_notify: - result = CRMD_ACTION_NOTIFY; - break; - case action_notified: - result = CRMD_ACTION_NOTIFIED; - break; - case action_promote: - result = CRMD_ACTION_PROMOTE; - break; - case action_promoted: - result = CRMD_ACTION_PROMOTED; - break; - case action_demote: - result = CRMD_ACTION_DEMOTE; - break; - case action_demoted: - result = CRMD_ACTION_DEMOTED; - break; - } - - return result; + const char *result = ""; + + switch (task) { + case no_action: + result = "no_action"; + break; + case stop_rsc: + result = CRMD_ACTION_STOP; + break; + case stopped_rsc: + result = CRMD_ACTION_STOPPED; + break; + case start_rsc: + result = CRMD_ACTION_START; + break; + case started_rsc: + result = CRMD_ACTION_STARTED; + break; + case shutdown_crm: + result = CRM_OP_SHUTDOWN; + break; + case stonith_node: + result = CRM_OP_FENCE; + break; + case monitor_rsc: + result = CRMD_ACTION_STATUS; + break; + case action_notify: + result = CRMD_ACTION_NOTIFY; + break; + case action_notified: + result = CRMD_ACTION_NOTIFIED; + break; + case action_promote: + result = CRMD_ACTION_PROMOTE; + break; + case action_promoted: + result = CRMD_ACTION_PROMOTED; + break; + case action_demote: + result = CRMD_ACTION_DEMOTE; + break; + case action_demoted: + result = CRMD_ACTION_DEMOTED; + break; + } + + return result; } const char * -role2text(enum rsc_role_e role) +role2text(enum rsc_role_e role) { - CRM_CHECK(role >= RSC_ROLE_UNKNOWN, return RSC_ROLE_UNKNOWN_S); - CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S); - switch(role) { - case RSC_ROLE_UNKNOWN: - return RSC_ROLE_UNKNOWN_S; - case RSC_ROLE_STOPPED: - return RSC_ROLE_STOPPED_S; - case RSC_ROLE_STARTED: - return RSC_ROLE_STARTED_S; - case RSC_ROLE_SLAVE: - return RSC_ROLE_SLAVE_S; - case RSC_ROLE_MASTER: - return RSC_ROLE_MASTER_S; - } - return RSC_ROLE_UNKNOWN_S; + CRM_CHECK(role >= RSC_ROLE_UNKNOWN, return RSC_ROLE_UNKNOWN_S); + CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S); + switch (role) { + case RSC_ROLE_UNKNOWN: + return RSC_ROLE_UNKNOWN_S; + case RSC_ROLE_STOPPED: + return RSC_ROLE_STOPPED_S; + case RSC_ROLE_STARTED: + return RSC_ROLE_STARTED_S; + case RSC_ROLE_SLAVE: + return RSC_ROLE_SLAVE_S; + case RSC_ROLE_MASTER: + return RSC_ROLE_MASTER_S; + } + return RSC_ROLE_UNKNOWN_S; } enum rsc_role_e -text2role(const char *role) +text2role(const char *role) { - CRM_ASSERT(role != NULL); - if(safe_str_eq(role, RSC_ROLE_STOPPED_S)) { - return RSC_ROLE_STOPPED; - } else if(safe_str_eq(role, RSC_ROLE_STARTED_S)) { - return RSC_ROLE_STARTED; - } else if(safe_str_eq(role, RSC_ROLE_SLAVE_S)) { - return RSC_ROLE_SLAVE; - } else if(safe_str_eq(role, RSC_ROLE_MASTER_S)) { - return RSC_ROLE_MASTER; - } else if(safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) { - return RSC_ROLE_UNKNOWN; - } - crm_err("Unknown role: %s", role); - return RSC_ROLE_UNKNOWN; + CRM_ASSERT(role != NULL); + if (safe_str_eq(role, RSC_ROLE_STOPPED_S)) { + return RSC_ROLE_STOPPED; + } else if (safe_str_eq(role, RSC_ROLE_STARTED_S)) { + return RSC_ROLE_STARTED; + } else if (safe_str_eq(role, RSC_ROLE_SLAVE_S)) { + return RSC_ROLE_SLAVE; + } else if (safe_str_eq(role, RSC_ROLE_MASTER_S)) { + return RSC_ROLE_MASTER; + } else if (safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) { + return RSC_ROLE_UNKNOWN; + } + crm_err("Unknown role: %s", role); + return RSC_ROLE_UNKNOWN; } int -merge_weights(int w1, int w2) +merge_weights(int w1, int w2) { - int result = w1 + w2; - - if(w1 <= -INFINITY || w2 <= -INFINITY) { - if(w1 >= INFINITY || w2 >= INFINITY) { - crm_debug_2("-INFINITY + INFINITY == -INFINITY"); - } - return -INFINITY; - - } else if(w1 >= INFINITY || w2 >= INFINITY) { - return INFINITY; - } - - /* detect wrap-around */ - if(result > 0) { - if(w1 <= 0 && w2 < 0) { - result = -INFINITY; - } - - } else if(w1 > 0 && w2 > 0) { - result = INFINITY; - } - - /* detect +/- INFINITY */ - if(result >= INFINITY) { - result = INFINITY; - - } else if(result <= -INFINITY) { - result = -INFINITY; - } - - crm_debug_5("%d + %d = %d", w1, w2, result); - return result; + int result = w1 + w2; + + if (w1 <= -INFINITY || w2 <= -INFINITY) { + if (w1 >= INFINITY || w2 >= INFINITY) { + crm_debug_2("-INFINITY + INFINITY == -INFINITY"); + } + return -INFINITY; + + } else if (w1 >= INFINITY || w2 >= INFINITY) { + return INFINITY; + } + + /* detect wrap-around */ + if (result > 0) { + if (w1 <= 0 && w2 < 0) { + result = -INFINITY; + } + + } else if (w1 > 0 && w2 > 0) { + result = INFINITY; + } + + /* detect +/- INFINITY */ + if (result >= INFINITY) { + result = INFINITY; + + } else if (result <= -INFINITY) { + result = -INFINITY; + } + + crm_debug_5("%d + %d = %d", w1, w2, result); + return result; } void -add_hash_param(GHashTable *hash, const char *name, const char *value) +add_hash_param(GHashTable * hash, const char *name, const char *value) { - CRM_CHECK(hash != NULL, return); - - crm_debug_3("adding: name=%s value=%s", crm_str(name), crm_str(value)); - if(name == NULL || value == NULL) { - return; - - } else if(safe_str_eq(value, "#default")) { - return; - - } else if(g_hash_table_lookup(hash, name) == NULL) { - g_hash_table_insert(hash, crm_strdup(name), crm_strdup(value)); - } -} + CRM_CHECK(hash != NULL, return); + + crm_debug_3("adding: name=%s value=%s", crm_str(name), crm_str(value)); + if (name == NULL || value == NULL) { + return; + } else if (safe_str_eq(value, "#default")) { + return; + + } else if (g_hash_table_lookup(hash, name) == NULL) { + g_hash_table_insert(hash, crm_strdup(name), crm_strdup(value)); + } +} diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index 50f583ebb2..67cff441e7 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.c @@ -1,621 +1,629 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 - -extern xmlNode *get_object_root(const char *object_type,xmlNode *the_root); -void populate_hash(xmlNode *nvpair_list, GHashTable *hash, - const char **attrs, int attrs_length); +extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root); +void populate_hash(xmlNode * nvpair_list, GHashTable * hash, const char **attrs, int attrs_length); resource_object_functions_t resource_class_functions[] = { { - native_unpack, - native_find_rsc, - native_parameter, - native_print, - native_active, - native_resource_state, - native_location, - native_free - }, + native_unpack, + native_find_rsc, + native_parameter, + native_print, + native_active, + native_resource_state, + native_location, + native_free}, { - group_unpack, - native_find_rsc, - native_parameter, - group_print, - group_active, - group_resource_state, - native_location, - group_free - }, + group_unpack, + native_find_rsc, + native_parameter, + group_print, + group_active, + group_resource_state, + native_location, + group_free}, { - clone_unpack, - native_find_rsc, - native_parameter, - clone_print, - clone_active, - clone_resource_state, - native_location, - clone_free - }, + clone_unpack, + native_find_rsc, + native_parameter, + clone_print, + clone_active, + clone_resource_state, + native_location, + clone_free}, { - master_unpack, - native_find_rsc, - native_parameter, - clone_print, - clone_active, - clone_resource_state, - native_location, - clone_free - } + master_unpack, + native_find_rsc, + native_parameter, + clone_print, + clone_active, + clone_resource_state, + native_location, + clone_free} }; -enum pe_obj_types get_resource_type(const char *name) +enum pe_obj_types +get_resource_type(const char *name) { - if(safe_str_eq(name, XML_CIB_TAG_RESOURCE)) { - return pe_native; + if (safe_str_eq(name, XML_CIB_TAG_RESOURCE)) { + return pe_native; - } else if(safe_str_eq(name, XML_CIB_TAG_GROUP)) { - return pe_group; + } else if (safe_str_eq(name, XML_CIB_TAG_GROUP)) { + return pe_group; - } else if(safe_str_eq(name, XML_CIB_TAG_INCARNATION)) { - return pe_clone; + } else if (safe_str_eq(name, XML_CIB_TAG_INCARNATION)) { + return pe_clone; - } else if(safe_str_eq(name, XML_CIB_TAG_MASTER)) { - return pe_master; + } else if (safe_str_eq(name, XML_CIB_TAG_MASTER)) { + return pe_master; } - + return pe_unknown; } -const char *get_resource_typename(enum pe_obj_types type) +const char * +get_resource_typename(enum pe_obj_types type) { - switch(type) { - case pe_native: - return XML_CIB_TAG_RESOURCE; - case pe_group: - return XML_CIB_TAG_GROUP; - case pe_clone: - return XML_CIB_TAG_INCARNATION; - case pe_master: - return XML_CIB_TAG_MASTER; - case pe_unknown: - return "unknown"; + switch (type) { + case pe_native: + return XML_CIB_TAG_RESOURCE; + case pe_group: + return XML_CIB_TAG_GROUP; + case pe_clone: + return XML_CIB_TAG_INCARNATION; + case pe_master: + return XML_CIB_TAG_MASTER; + case pe_unknown: + return "unknown"; } return ""; } -static void dup_attr(gpointer key, gpointer value, gpointer user_data) +static void +dup_attr(gpointer key, gpointer value, gpointer user_data) { add_hash_param(user_data, key, value); } void -get_meta_attributes(GHashTable *meta_hash, resource_t *rsc, - node_t *node, pe_working_set_t *data_set) +get_meta_attributes(GHashTable * meta_hash, resource_t * rsc, + node_t * node, pe_working_set_t * data_set) { GHashTable *node_hash = NULL; - if(node) { - node_hash = node->details->attrs; + + if (node) { + node_hash = node->details->attrs; } - if(rsc->xml) { + if (rsc->xml) { xmlAttrPtr xIter = NULL; - for(xIter = rsc->xml->properties; xIter; xIter = xIter->next) { + + for (xIter = rsc->xml->properties; xIter; xIter = xIter->next) { const char *prop_name = (const char *)xIter->name; const char *prop_value = crm_element_value(rsc->xml, prop_name); + add_hash_param(meta_hash, prop_name, prop_value); } } unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_META_SETS, node_hash, - meta_hash, NULL, FALSE, data_set->now); + meta_hash, NULL, FALSE, data_set->now); /* populate from the regular attributes until the GUI can create * meta attributes */ unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash, - meta_hash, NULL, FALSE, data_set->now); + meta_hash, NULL, FALSE, data_set->now); /* set anything else based on the parent */ - if(rsc->parent != NULL) { - g_hash_table_foreach(rsc->parent->meta, dup_attr, meta_hash); - } + if (rsc->parent != NULL) { + g_hash_table_foreach(rsc->parent->meta, dup_attr, meta_hash); + } /* and finally check the defaults */ - unpack_instance_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_META_SETS, node_hash, - meta_hash, NULL, FALSE, data_set->now); + unpack_instance_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_META_SETS, + node_hash, meta_hash, NULL, FALSE, data_set->now); } void -get_rsc_attributes(GHashTable *meta_hash, resource_t *rsc, - node_t *node, pe_working_set_t *data_set) +get_rsc_attributes(GHashTable * meta_hash, resource_t * rsc, + node_t * node, pe_working_set_t * data_set) { GHashTable *node_hash = NULL; - if(node) { - node_hash = node->details->attrs; + + if (node) { + node_hash = node->details->attrs; } - + unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash, - meta_hash, NULL, FALSE, data_set->now); - + meta_hash, NULL, FALSE, data_set->now); + /* set anything else based on the parent */ - if(rsc->parent != NULL) { - get_rsc_attributes(meta_hash, rsc->parent, node, data_set); + if (rsc->parent != NULL) { + get_rsc_attributes(meta_hash, rsc->parent, node, data_set); } else { - /* and finally check the defaults */ - unpack_instance_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_ATTR_SETS, node_hash, - meta_hash, NULL, FALSE, data_set->now); + /* and finally check the defaults */ + unpack_instance_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_ATTR_SETS, + node_hash, meta_hash, NULL, FALSE, data_set->now); } } -static char* -template_op_key(xmlNode *op) +static char * +template_op_key(xmlNode * op) { const char *name = crm_element_value(op, "name"); const char *role = crm_element_value(op, "role"); char *key = NULL; - if(role == NULL - || crm_str_eq(role, RSC_ROLE_STARTED_S, TRUE) - || crm_str_eq(role, RSC_ROLE_SLAVE_S, TRUE)) { - role = RSC_ROLE_UNKNOWN_S; + if (role == NULL || crm_str_eq(role, RSC_ROLE_STARTED_S, TRUE) + || crm_str_eq(role, RSC_ROLE_SLAVE_S, TRUE)) { + role = RSC_ROLE_UNKNOWN_S; } key = crm_concat(name, role, '-'); return key; } static gboolean -unpack_template(xmlNode *xml_obj, xmlNode **expanded_xml, pe_working_set_t *data_set) +unpack_template(xmlNode * xml_obj, xmlNode ** expanded_xml, pe_working_set_t * data_set) { xmlNode *cib_resources = NULL; xmlNode *template = NULL; xmlNode *new_xml = NULL; xmlNode *child_xml = NULL; xmlNode *rsc_ops = NULL; xmlNode *template_ops = NULL; const char *template_ref = NULL; const char *id = NULL; - - if(xml_obj == NULL) { - pe_err("No resource object for template unpacking"); - return FALSE; + + if (xml_obj == NULL) { + pe_err("No resource object for template unpacking"); + return FALSE; } template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE); - if(template_ref == NULL) { - return TRUE; + if (template_ref == NULL) { + return TRUE; } id = ID(xml_obj); - if(id == NULL) { - pe_err("'%s' object must have a id", crm_element_name(xml_obj)); - return FALSE; + if (id == NULL) { + pe_err("'%s' object must have a id", crm_element_name(xml_obj)); + return FALSE; } - if(crm_str_eq(template_ref, id, TRUE)) { - pe_err("The resource object '%s' should not reference itself", id); - return FALSE; + if (crm_str_eq(template_ref, id, TRUE)) { + pe_err("The resource object '%s' should not reference itself", id); + return FALSE; } cib_resources = get_object_root(XML_CIB_TAG_RESOURCES, data_set->input); - if(cib_resources == NULL) { - pe_err("Cannot get the root of object '%s'", XML_CIB_TAG_RESOURCES); - return FALSE; + if (cib_resources == NULL) { + pe_err("Cannot get the root of object '%s'", XML_CIB_TAG_RESOURCES); + return FALSE; } - + template = find_entity(cib_resources, XML_CIB_TAG_RSC_TEMPLATE, template_ref); - if(template == NULL) { - pe_err("No template named '%s'", template_ref); - return FALSE; + if (template == NULL) { + pe_err("No template named '%s'", template_ref); + return FALSE; } new_xml = copy_xml(template); xmlNodeSetName(new_xml, xml_obj->name); crm_xml_replace(new_xml, XML_ATTR_ID, id); template_ops = find_xml_node(new_xml, "operations", FALSE); - for(child_xml = __xml_first_child(xml_obj); child_xml != NULL; child_xml = __xml_next(child_xml)) { - xmlNode *new_child = NULL; + for (child_xml = __xml_first_child(xml_obj); child_xml != NULL; + child_xml = __xml_next(child_xml)) { + xmlNode *new_child = NULL; - new_child = add_node_copy(new_xml, child_xml); + new_child = add_node_copy(new_xml, child_xml); - if(crm_str_eq((const char *)new_child->name, "operations", TRUE)) { - rsc_ops = new_child; - } + if (crm_str_eq((const char *)new_child->name, "operations", TRUE)) { + rsc_ops = new_child; + } } - if(template_ops && rsc_ops) { - xmlNode * op = NULL; - GHashTable *rsc_ops_hash = g_hash_table_new_full( - crm_str_hash, g_str_equal, g_hash_destroy_str, NULL); + if (template_ops && rsc_ops) { + xmlNode *op = NULL; + GHashTable *rsc_ops_hash = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, NULL); - for(op = __xml_first_child(rsc_ops); op != NULL; op = __xml_next(op)) { - char *key = template_op_key(op); + for (op = __xml_first_child(rsc_ops); op != NULL; op = __xml_next(op)) { + char *key = template_op_key(op); - g_hash_table_insert(rsc_ops_hash, key, op); - } + g_hash_table_insert(rsc_ops_hash, key, op); + } - for(op = __xml_first_child(template_ops); op != NULL; op = __xml_next(op)) { - char *key = template_op_key(op); + for (op = __xml_first_child(template_ops); op != NULL; op = __xml_next(op)) { + char *key = template_op_key(op); - if(g_hash_table_lookup(rsc_ops_hash, key) == NULL) { - add_node_copy(rsc_ops, op); - } + if (g_hash_table_lookup(rsc_ops_hash, key) == NULL) { + add_node_copy(rsc_ops, op); + } - crm_free(key); - } + crm_free(key); + } - if(rsc_ops_hash) { - g_hash_table_destroy(rsc_ops_hash); - } + if (rsc_ops_hash) { + g_hash_table_destroy(rsc_ops_hash); + } - free_xml_from_parent(NULL, template_ops); + free_xml_from_parent(NULL, template_ops); } - - /*free_xml(*expanded_xml);*/ + + /*free_xml(*expanded_xml); */ *expanded_xml = new_xml; /* Disable multi-level templates for now */ /*if(unpack_template(new_xml, expanded_xml, data_set) == FALSE) { - free_xml(*expanded_xml); - *expanded_xml = NULL; + free_xml(*expanded_xml); + *expanded_xml = NULL; - return FALSE; - }*/ + return FALSE; + } */ return TRUE; } -gboolean -common_unpack(xmlNode * xml_obj, resource_t **rsc, - resource_t *parent, pe_working_set_t *data_set) +gboolean +common_unpack(xmlNode * xml_obj, resource_t ** rsc, + resource_t * parent, pe_working_set_t * data_set) { xmlNode *expanded_xml = NULL; xmlNode *ops = NULL; resource_t *top = NULL; const char *value = NULL; - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *class = crm_element_value(xml_obj, XML_AGENT_ATTR_CLASS); crm_log_xml_debug_3(xml_obj, "Processing resource input..."); - - if(id == NULL) { - pe_err("Must specify id tag in "); - return FALSE; - - } else if(rsc == NULL) { - pe_err("Nowhere to unpack resource into"); - return FALSE; - + + if (id == NULL) { + pe_err("Must specify id tag in "); + return FALSE; + + } else if (rsc == NULL) { + pe_err("Nowhere to unpack resource into"); + return FALSE; + } - - if(unpack_template(xml_obj, &expanded_xml, data_set) == FALSE) { - return FALSE; + + if (unpack_template(xml_obj, &expanded_xml, data_set) == FALSE) { + return FALSE; } crm_malloc0(*rsc, sizeof(resource_t)); - if(expanded_xml) { - crm_log_xml_debug_3(expanded_xml, "Expanded resource..."); - (*rsc)->xml = expanded_xml; - (*rsc)->orig_xml = xml_obj; + if (expanded_xml) { + crm_log_xml_debug_3(expanded_xml, "Expanded resource..."); + (*rsc)->xml = expanded_xml; + (*rsc)->orig_xml = xml_obj; } else { - (*rsc)->xml = xml_obj; - (*rsc)->orig_xml = NULL; + (*rsc)->xml = xml_obj; + (*rsc)->orig_xml = NULL; } - (*rsc)->parent = parent; + (*rsc)->parent = parent; ops = find_xml_node((*rsc)->xml, "operations", FALSE); (*rsc)->ops_xml = expand_idref(ops, data_set->input); (*rsc)->variant = get_resource_type(crm_element_name(xml_obj)); - if((*rsc)->variant == pe_unknown) { - pe_err("Unknown resource type: %s", crm_element_name(xml_obj)); - crm_free(*rsc); - return FALSE; - } - - (*rsc)->parameters = g_hash_table_new_full( - crm_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str); - - (*rsc)->meta = g_hash_table_new_full( - crm_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str); - - (*rsc)->allowed_nodes = g_hash_table_new_full( - crm_str_hash,g_str_equal, NULL, g_hash_destroy_str); - - (*rsc)->known_on = g_hash_table_new_full( - crm_str_hash,g_str_equal, NULL, g_hash_destroy_str); - + if ((*rsc)->variant == pe_unknown) { + pe_err("Unknown resource type: %s", crm_element_name(xml_obj)); + crm_free(*rsc); + return FALSE; + } + + (*rsc)->parameters = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + + (*rsc)->meta = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + + (*rsc)->allowed_nodes = + g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); + + (*rsc)->known_on = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); + value = crm_element_value(xml_obj, XML_RSC_ATTR_INCARNATION); - if(value) { - (*rsc)->id = crm_concat(id, value, ':'); - add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value); - + if (value) { + (*rsc)->id = crm_concat(id, value, ':'); + add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value); + } else { - (*rsc)->id = crm_strdup(id); + (*rsc)->id = crm_strdup(id); } - if(parent) { - (*rsc)->long_name = crm_concat(parent->long_name, (*rsc)->id, ':'); + if (parent) { + (*rsc)->long_name = crm_concat(parent->long_name, (*rsc)->id, ':'); } else { - (*rsc)->long_name = crm_strdup((*rsc)->id); + (*rsc)->long_name = crm_strdup((*rsc)->id); } - + (*rsc)->fns = &resource_class_functions[(*rsc)->variant]; crm_debug_3("Unpacking resource..."); get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set); - + (*rsc)->flags = 0; - set_bit((*rsc)->flags, pe_rsc_runnable); - set_bit((*rsc)->flags, pe_rsc_provisional); + set_bit((*rsc)->flags, pe_rsc_runnable); + set_bit((*rsc)->flags, pe_rsc_provisional); - if(is_set(data_set->flags, pe_flag_is_managed_default)) { - set_bit((*rsc)->flags, pe_rsc_managed); + if (is_set(data_set->flags, pe_flag_is_managed_default)) { + set_bit((*rsc)->flags, pe_rsc_managed); } - (*rsc)->rsc_cons = NULL; - (*rsc)->rsc_tickets = NULL; - (*rsc)->actions = NULL; - (*rsc)->role = RSC_ROLE_STOPPED; - (*rsc)->next_role = RSC_ROLE_UNKNOWN; + (*rsc)->rsc_cons = NULL; + (*rsc)->rsc_tickets = NULL; + (*rsc)->actions = NULL; + (*rsc)->role = RSC_ROLE_STOPPED; + (*rsc)->next_role = RSC_ROLE_UNKNOWN; - (*rsc)->recovery_type = recovery_stop_start; - (*rsc)->stickiness = data_set->default_resource_stickiness; - (*rsc)->migration_threshold= INFINITY; - (*rsc)->failure_timeout = 0; + (*rsc)->recovery_type = recovery_stop_start; + (*rsc)->stickiness = data_set->default_resource_stickiness; + (*rsc)->migration_threshold = INFINITY; + (*rsc)->failure_timeout = 0; value = g_hash_table_lookup((*rsc)->meta, XML_CIB_ATTR_PRIORITY); - (*rsc)->priority = crm_parse_int(value, "0"); + (*rsc)->priority = crm_parse_int(value, "0"); (*rsc)->effective_priority = (*rsc)->priority; value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_NOTIFY); - if(crm_is_true(value)) { - set_bit((*rsc)->flags, pe_rsc_notify); + if (crm_is_true(value)) { + set_bit((*rsc)->flags, pe_rsc_notify); } - + value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MANAGED); - if(value != NULL && safe_str_neq("default", value)) { - gboolean bool_value = TRUE; - crm_str_to_boolean(value, &bool_value); - if(bool_value == FALSE) { - clear_bit((*rsc)->flags, pe_rsc_managed); - } else { - set_bit((*rsc)->flags, pe_rsc_managed); - } + if (value != NULL && safe_str_neq("default", value)) { + gboolean bool_value = TRUE; + + crm_str_to_boolean(value, &bool_value); + if (bool_value == FALSE) { + clear_bit((*rsc)->flags, pe_rsc_managed); + } else { + set_bit((*rsc)->flags, pe_rsc_managed); + } } - if(is_set(data_set->flags, pe_flag_maintenance_mode)) { - clear_bit((*rsc)->flags, pe_rsc_managed); + if (is_set(data_set->flags, pe_flag_maintenance_mode)) { + clear_bit((*rsc)->flags, pe_rsc_managed); } - + crm_debug_2("Options for %s", (*rsc)->id); value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE); top = uber_parent(*rsc); - if(crm_is_true(value) || top->variant < pe_clone) { - set_bit((*rsc)->flags, pe_rsc_unique); + if (crm_is_true(value) || top->variant < pe_clone) { + set_bit((*rsc)->flags, pe_rsc_unique); } - + value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_RESTART); - if(safe_str_eq(value, "restart")) { - (*rsc)->restart_type = pe_restart_restart; - crm_debug_2("\tDependency restart handling: restart"); + if (safe_str_eq(value, "restart")) { + (*rsc)->restart_type = pe_restart_restart; + crm_debug_2("\tDependency restart handling: restart"); } else { - (*rsc)->restart_type = pe_restart_ignore; - crm_debug_2("\tDependency restart handling: ignore"); + (*rsc)->restart_type = pe_restart_ignore; + crm_debug_2("\tDependency restart handling: ignore"); } value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MULTIPLE); - if(safe_str_eq(value, "stop_only")) { - (*rsc)->recovery_type = recovery_stop_only; - crm_debug_2("\tMultiple running resource recovery: stop only"); + if (safe_str_eq(value, "stop_only")) { + (*rsc)->recovery_type = recovery_stop_only; + crm_debug_2("\tMultiple running resource recovery: stop only"); - } else if(safe_str_eq(value, "block")) { - (*rsc)->recovery_type = recovery_block; - crm_debug_2("\tMultiple running resource recovery: block"); + } else if (safe_str_eq(value, "block")) { + (*rsc)->recovery_type = recovery_block; + crm_debug_2("\tMultiple running resource recovery: block"); - } else { - (*rsc)->recovery_type = recovery_stop_start; - crm_debug_2("\tMultiple running resource recovery: stop/start"); + } else { + (*rsc)->recovery_type = recovery_stop_start; + crm_debug_2("\tMultiple running resource recovery: stop/start"); } value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_STICKINESS); - if(value != NULL && safe_str_neq("default", value)) { - (*rsc)->stickiness = char2score(value); + if (value != NULL && safe_str_neq("default", value)) { + (*rsc)->stickiness = char2score(value); } value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_STICKINESS); - if(value != NULL && safe_str_neq("default", value)) { - (*rsc)->migration_threshold = char2score(value); - - } else if(value == NULL) { - /* Make a best-effort guess at a migration threshold for people with 0.6 configs - * try with underscores and hyphens, from both the resource and global defaults section - */ - - value = g_hash_table_lookup((*rsc)->meta, "resource-failure-stickiness"); - if(value == NULL) { - value = g_hash_table_lookup((*rsc)->meta, "resource_failure_stickiness"); - } - if(value == NULL) { - value = g_hash_table_lookup(data_set->config_hash, "default-resource-failure-stickiness"); - } - if(value == NULL) { - value = g_hash_table_lookup(data_set->config_hash, "default_resource_failure_stickiness"); - } - - if(value) { - int fail_sticky = char2score(value); - if(fail_sticky == -INFINITY) { - (*rsc)->migration_threshold = 1; - crm_info("Set a migration threshold of %d for %s based on a failure-stickiness of %s", - (*rsc)->migration_threshold, (*rsc)->id, value); - - } else if((*rsc)->stickiness != 0 && fail_sticky != 0) { - (*rsc)->migration_threshold = (*rsc)->stickiness / fail_sticky; - if((*rsc)->migration_threshold < 0) { - /* Make sure it's positive */ - (*rsc)->migration_threshold = 0 - (*rsc)->migration_threshold; - } - (*rsc)->migration_threshold += 1; - crm_info("Calculated a migration threshold for %s of %d based on a stickiness of %d/%s", - (*rsc)->id, (*rsc)->migration_threshold, (*rsc)->stickiness, value); - } - } - } - - - + if (value != NULL && safe_str_neq("default", value)) { + (*rsc)->migration_threshold = char2score(value); + + } else if (value == NULL) { + /* Make a best-effort guess at a migration threshold for people with 0.6 configs + * try with underscores and hyphens, from both the resource and global defaults section + */ + + value = g_hash_table_lookup((*rsc)->meta, "resource-failure-stickiness"); + if (value == NULL) { + value = g_hash_table_lookup((*rsc)->meta, "resource_failure_stickiness"); + } + if (value == NULL) { + value = + g_hash_table_lookup(data_set->config_hash, "default-resource-failure-stickiness"); + } + if (value == NULL) { + value = + g_hash_table_lookup(data_set->config_hash, "default_resource_failure_stickiness"); + } + + if (value) { + int fail_sticky = char2score(value); + + if (fail_sticky == -INFINITY) { + (*rsc)->migration_threshold = 1; + crm_info + ("Set a migration threshold of %d for %s based on a failure-stickiness of %s", + (*rsc)->migration_threshold, (*rsc)->id, value); + + } else if ((*rsc)->stickiness != 0 && fail_sticky != 0) { + (*rsc)->migration_threshold = (*rsc)->stickiness / fail_sticky; + if ((*rsc)->migration_threshold < 0) { + /* Make sure it's positive */ + (*rsc)->migration_threshold = 0 - (*rsc)->migration_threshold; + } + (*rsc)->migration_threshold += 1; + crm_info + ("Calculated a migration threshold for %s of %d based on a stickiness of %d/%s", + (*rsc)->id, (*rsc)->migration_threshold, (*rsc)->stickiness, value); + } + } + } + value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT); - if(value != NULL) { - /* call crm_get_msec() and convert back to seconds */ - (*rsc)->failure_timeout = (crm_get_msec(value) / 1000); + if (value != NULL) { + /* call crm_get_msec() and convert back to seconds */ + (*rsc)->failure_timeout = (crm_get_msec(value) / 1000); } - + get_target_role(*rsc, &((*rsc)->next_role)); crm_debug_2("\tDesired next state: %s", - (*rsc)->next_role!=RSC_ROLE_UNKNOWN?role2text((*rsc)->next_role):"default"); + (*rsc)->next_role != RSC_ROLE_UNKNOWN ? role2text((*rsc)->next_role) : "default"); - if((*rsc)->fns->unpack(*rsc, data_set) == FALSE) { - return FALSE; + if ((*rsc)->fns->unpack(*rsc, data_set) == FALSE) { + return FALSE; } - - if(is_set(data_set->flags, pe_flag_symmetric_cluster)) { - resource_location(*rsc, NULL, 0, "symmetric_default", data_set); + + if (is_set(data_set->flags, pe_flag_symmetric_cluster)) { + resource_location(*rsc, NULL, 0, "symmetric_default", data_set); } - + crm_debug_2("\tAction notification: %s", - is_set((*rsc)->flags, pe_rsc_notify)?"required":"not required"); + is_set((*rsc)->flags, pe_rsc_notify) ? "required" : "not required"); - if(safe_str_eq(class, "stonith")) { - set_bit_inplace(data_set->flags, pe_flag_have_stonith_resource); + if (safe_str_eq(class, "stonith")) { + set_bit_inplace(data_set->flags, pe_flag_have_stonith_resource); } - (*rsc)->utilization = g_hash_table_new_full( - crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + (*rsc)->utilization = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); unpack_instance_attributes(data_set->input, (*rsc)->xml, XML_TAG_UTILIZATION, NULL, - (*rsc)->utilization, NULL, FALSE, data_set->now); - + (*rsc)->utilization, NULL, FALSE, data_set->now); + /* data_set->resources = g_list_append(data_set->resources, (*rsc)); */ return TRUE; } - -void common_update_score(resource_t *rsc, const char *id, int score) +void +common_update_score(resource_t * rsc, const char *id, int score) { node_t *node = NULL; + node = pe_hash_table_lookup(rsc->allowed_nodes, id); - if(node != NULL) { - crm_debug_2("Updating score for %s on %s: %d + %d", - rsc->id, id, node->weight, score); - node->weight = merge_weights(node->weight, score); + if (node != NULL) { + crm_debug_2("Updating score for %s on %s: %d + %d", rsc->id, id, node->weight, score); + node->weight = merge_weights(node->weight, score); } - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - common_update_score(child_rsc, id, score); - } + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + common_update_score(child_rsc, id, score); + } } } -resource_t *uber_parent(resource_t *rsc) +resource_t * +uber_parent(resource_t * rsc) { resource_t *parent = rsc; - if(parent == NULL) { - return NULL; + + if (parent == NULL) { + return NULL; } - while(parent->parent != NULL) { - parent = parent->parent; + while (parent->parent != NULL) { + parent = parent->parent; } return parent; } -void common_free(resource_t *rsc) +void +common_free(resource_t * rsc) { - if(rsc == NULL) { - return; + if (rsc == NULL) { + return; } - + crm_debug_5("Freeing %s %d", rsc->id, rsc->variant); g_list_free(rsc->rsc_cons); g_list_free(rsc->rsc_cons_lhs); g_list_free(rsc->rsc_tickets); g_list_free(rsc->dangling_migrations); - if(rsc->parameters != NULL) { - g_hash_table_destroy(rsc->parameters); + if (rsc->parameters != NULL) { + g_hash_table_destroy(rsc->parameters); } - if(rsc->meta != NULL) { - g_hash_table_destroy(rsc->meta); + if (rsc->meta != NULL) { + g_hash_table_destroy(rsc->meta); } - if(rsc->utilization != NULL) { - g_hash_table_destroy(rsc->utilization); + if (rsc->utilization != NULL) { + g_hash_table_destroy(rsc->utilization); } - if(rsc->orig_xml) { - free_xml(rsc->xml); + if (rsc->orig_xml) { + free_xml(rsc->xml); } - if(rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) { - if(rsc->orig_xml) { - free_xml(rsc->orig_xml); - } else { - free_xml(rsc->xml); - } + if (rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) { + if (rsc->orig_xml) { + free_xml(rsc->orig_xml); + } else { + free_xml(rsc->xml); + } } - if(rsc->running_on) { - g_list_free(rsc->running_on); - rsc->running_on = NULL; + if (rsc->running_on) { + g_list_free(rsc->running_on); + rsc->running_on = NULL; } - if(rsc->known_on) { - g_hash_table_destroy(rsc->known_on); - rsc->known_on = NULL; + if (rsc->known_on) { + g_hash_table_destroy(rsc->known_on); + rsc->known_on = NULL; } - if(rsc->actions) { - g_list_free(rsc->actions); - rsc->actions = NULL; + if (rsc->actions) { + g_list_free(rsc->actions); + rsc->actions = NULL; } - if(rsc->allowed_nodes) { - g_hash_table_destroy(rsc->allowed_nodes); - rsc->allowed_nodes = NULL; + if (rsc->allowed_nodes) { + g_hash_table_destroy(rsc->allowed_nodes); + rsc->allowed_nodes = NULL; } g_list_free(rsc->rsc_location); crm_free(rsc->id); - crm_free(rsc->long_name); + crm_free(rsc->long_name); crm_free(rsc->clone_name); crm_free(rsc->allocated_to); crm_free(rsc->variant_opaque); crm_free(rsc); crm_debug_5("Resource freed"); } - diff --git a/lib/pengine/group.c b/lib/pengine/group.c index bd91c091c4..4d48375515 100644 --- a/lib/pengine/group.c +++ b/lib/pengine/group.c @@ -1,225 +1,223 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 - #define VARIANT_GROUP 1 #include "./variant.h" -gboolean group_unpack(resource_t *rsc, pe_working_set_t *data_set) +gboolean +group_unpack(resource_t * rsc, pe_working_set_t * data_set) { resource_t *self = NULL; xmlNode *xml_obj = rsc->xml; xmlNode *xml_self = copy_xml(rsc->xml); xmlNode *xml_native_rsc = NULL; group_variant_data_t *group_data = NULL; - const char *group_ordered = g_hash_table_lookup( - rsc->meta, XML_RSC_ATTR_ORDERED); - const char *group_colocated = g_hash_table_lookup( - rsc->meta, "collocated"); + const char *group_ordered = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ORDERED); + const char *group_colocated = g_hash_table_lookup(rsc->meta, "collocated"); const char *clone_id = NULL; - + crm_debug_3("Processing resource %s...", rsc->id); crm_malloc0(group_data, sizeof(group_variant_data_t)); group_data->num_children = 0; - group_data->self = NULL; - group_data->first_child = NULL; - group_data->last_child = NULL; + group_data->self = NULL; + group_data->first_child = NULL; + group_data->last_child = NULL; rsc->variant_opaque = group_data; - group_data->ordered = TRUE; + group_data->ordered = TRUE; group_data->colocated = TRUE; - if(group_ordered != NULL) { - crm_str_to_boolean(group_ordered, &(group_data->ordered)); + if (group_ordered != NULL) { + crm_str_to_boolean(group_ordered, &(group_data->ordered)); } - if(group_colocated != NULL) { - crm_str_to_boolean(group_colocated, &(group_data->colocated)); + if (group_colocated != NULL) { + crm_str_to_boolean(group_colocated, &(group_data->colocated)); } - + /* this is a bit of a hack - but simplifies everything else */ - xmlNodeSetName(xml_self, ((const xmlChar*)XML_CIB_TAG_RESOURCE)); - if(common_unpack(xml_self, &self, NULL, data_set)) { - group_data->self = self; - self->restart_type = pe_restart_restart; + xmlNodeSetName(xml_self, ((const xmlChar *)XML_CIB_TAG_RESOURCE)); + if (common_unpack(xml_self, &self, NULL, data_set)) { + group_data->self = self; + self->restart_type = pe_restart_restart; } else { - crm_log_xml_err(xml_self, "Couldnt unpack dummy child"); - return FALSE; + crm_log_xml_err(xml_self, "Couldnt unpack dummy child"); + return FALSE; } clone_id = crm_element_value(rsc->xml, XML_RSC_ATTR_INCARNATION); - - for(xml_native_rsc = __xml_first_child(xml_obj); xml_native_rsc != NULL; xml_native_rsc = __xml_next(xml_native_rsc)) { - if(crm_str_eq((const char *)xml_native_rsc->name, XML_CIB_TAG_RESOURCE, TRUE)) { - resource_t *new_rsc = NULL; - crm_xml_add(xml_native_rsc, XML_RSC_ATTR_INCARNATION, clone_id); - if(common_unpack(xml_native_rsc, &new_rsc, - rsc, data_set) == FALSE) { - pe_err("Failed unpacking resource %s", - crm_element_value(xml_obj, XML_ATTR_ID)); - if(new_rsc != NULL && new_rsc->fns != NULL) { - new_rsc->fns->free(new_rsc); - } - } - - group_data->num_children++; - rsc->children = g_list_append(rsc->children, new_rsc); - - if(group_data->first_child == NULL) { - group_data->first_child = new_rsc; - } - group_data->last_child = new_rsc; - print_resource(LOG_DEBUG_3, "Added", new_rsc, FALSE); - } + + for (xml_native_rsc = __xml_first_child(xml_obj); xml_native_rsc != NULL; + xml_native_rsc = __xml_next(xml_native_rsc)) { + if (crm_str_eq((const char *)xml_native_rsc->name, XML_CIB_TAG_RESOURCE, TRUE)) { + resource_t *new_rsc = NULL; + + crm_xml_add(xml_native_rsc, XML_RSC_ATTR_INCARNATION, clone_id); + if (common_unpack(xml_native_rsc, &new_rsc, rsc, data_set) == FALSE) { + pe_err("Failed unpacking resource %s", crm_element_value(xml_obj, XML_ATTR_ID)); + if (new_rsc != NULL && new_rsc->fns != NULL) { + new_rsc->fns->free(new_rsc); + } + } + + group_data->num_children++; + rsc->children = g_list_append(rsc->children, new_rsc); + + if (group_data->first_child == NULL) { + group_data->first_child = new_rsc; + } + group_data->last_child = new_rsc; + print_resource(LOG_DEBUG_3, "Added", new_rsc, FALSE); + } } - - if(group_data->num_children == 0) { + if (group_data->num_children == 0) { #if 0 - /* Bug #1287 */ - crm_config_err("Group %s did not have any children", rsc->id); - return FALSE; + /* Bug #1287 */ + crm_config_err("Group %s did not have any children", rsc->id); + return FALSE; #else - crm_config_warn("Group %s did not have any children", rsc->id); - return TRUE; + crm_config_warn("Group %s did not have any children", rsc->id); + return TRUE; #endif } - - crm_debug_3("Added %d children to resource %s...", - group_data->num_children, rsc->id); - + + crm_debug_3("Added %d children to resource %s...", group_data->num_children, rsc->id); + return TRUE; } - -gboolean group_active(resource_t *rsc, gboolean all) +gboolean +group_active(resource_t * rsc, gboolean all) { gboolean c_all = TRUE; gboolean c_any = FALSE; GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; - if(child_rsc->fns->active(child_rsc, all)) { - c_any = TRUE; - } else { - c_all = FALSE; - } + if (child_rsc->fns->active(child_rsc, all)) { + c_any = TRUE; + } else { + c_all = FALSE; + } } - - if(c_any == FALSE) { - return FALSE; - } else if(all && c_all == FALSE) { - return FALSE; + + if (c_any == FALSE) { + return FALSE; + } else if (all && c_all == FALSE) { + return FALSE; } return TRUE; } -void group_print( - resource_t *rsc, const char *pre_text, long options, void *print_data) +void +group_print(resource_t * rsc, const char *pre_text, long options, void *print_data) { char *child_text = NULL; GListPtr gIter = rsc->children; - if(pre_text == NULL) { pre_text = " "; } + if (pre_text == NULL) { + pre_text = " "; + } child_text = crm_concat(pre_text, " ", ' '); - - status_print("%sResource Group: %s", - pre_text?pre_text:"", rsc->id); - if(options & pe_print_html) { - status_print("\n
      \n"); + status_print("%sResource Group: %s", pre_text ? pre_text : "", rsc->id); + + if (options & pe_print_html) { + status_print("\n
        \n"); - } else if((options & pe_print_log) == 0) { - status_print("\n"); + } else if ((options & pe_print_log) == 0) { + status_print("\n"); } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - if(options & pe_print_html) { - status_print("
      • \n"); - } - child_rsc->fns->print( - child_rsc, child_text, options, print_data); - if(options & pe_print_html) { - status_print("
      • \n"); - } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + if (options & pe_print_html) { + status_print("
      • \n"); + } + child_rsc->fns->print(child_rsc, child_text, options, print_data); + if (options & pe_print_html) { + status_print("
      • \n"); + } } - if(options & pe_print_html) { - status_print("
      \n"); + if (options & pe_print_html) { + status_print("
    \n"); } crm_free(child_text); } -void group_free(resource_t *rsc) +void +group_free(resource_t * rsc) { GListPtr gIter = rsc->children; group_variant_data_t *group_data = NULL; + CRM_CHECK(rsc != NULL, return); get_group_variant_data(group_data, rsc); crm_debug_3("Freeing %s", rsc->id); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; - crm_debug_3("Freeing child %s", child_rsc->id); - child_rsc->fns->free(child_rsc); + crm_debug_3("Freeing child %s", child_rsc->id); + child_rsc->fns->free(child_rsc); } crm_debug_3("Freeing child list"); g_list_free(rsc->children); - if(group_data->self != NULL) { - free_xml(group_data->self->xml); - group_data->self->fns->free(group_data->self); + if (group_data->self != NULL) { + free_xml(group_data->self->xml); + group_data->self->fns->free(group_data->self); } common_free(rsc); } enum rsc_role_e -group_resource_state(const resource_t *rsc, gboolean current) +group_resource_state(const resource_t * rsc, gboolean current) { enum rsc_role_e group_role = RSC_ROLE_UNKNOWN; GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - enum rsc_role_e role = child_rsc->fns->state(child_rsc, current); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + enum rsc_role_e role = child_rsc->fns->state(child_rsc, current); - if(role > group_role) { - group_role = role; - } + if (role > group_role) { + group_role = role; + } } crm_debug_3("%s role: %s", rsc->id, role2text(group_role)); return group_role; } diff --git a/lib/pengine/native.c b/lib/pengine/native.c index 8a8711736e..1812861495 100644 --- a/lib/pengine/native.c +++ b/lib/pengine/native.c @@ -1,502 +1,511 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #define VARIANT_NATIVE 1 #include "./variant.h" void -native_add_running(resource_t *rsc, node_t *node, pe_working_set_t *data_set) +native_add_running(resource_t * rsc, node_t * node, pe_working_set_t * data_set) { GListPtr gIter = rsc->running_on; + CRM_CHECK(node != NULL, return); - for(; gIter != NULL; gIter = gIter->next) { - node_t *a_node = (node_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + node_t *a_node = (node_t *) gIter->data; - CRM_CHECK(a_node != NULL, return); - if(safe_str_eq(a_node->details->id, node->details->id)) { - return; - } + CRM_CHECK(a_node != NULL, return); + if (safe_str_eq(a_node->details->id, node->details->id)) { + return; + } } - + crm_debug_3("Adding %s to %s", rsc->id, node->details->uname); - + rsc->running_on = g_list_append(rsc->running_on, node); - if(rsc->variant == pe_native) { - node->details->running_rsc = g_list_append( - node->details->running_rsc, rsc); + if (rsc->variant == pe_native) { + node->details->running_rsc = g_list_append(node->details->running_rsc, rsc); } - if(is_not_set(rsc->flags, pe_rsc_managed)) { - crm_info("resource %s isnt managed", rsc->id); - resource_location(rsc, node, INFINITY, - "not_managed_default", data_set); - return; + if (is_not_set(rsc->flags, pe_rsc_managed)) { + crm_info("resource %s isnt managed", rsc->id); + resource_location(rsc, node, INFINITY, "not_managed_default", data_set); + return; } - - if(rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) { - switch(rsc->recovery_type) { - case recovery_stop_only: - { - GHashTableIter gIter; - node_t *local_node = NULL; - - /* make sure it doesnt come up again */ - g_hash_table_destroy(rsc->allowed_nodes); - rsc->allowed_nodes = node_hash_from_list(data_set->nodes); - g_hash_table_iter_init (&gIter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&gIter, NULL, (void**)&local_node)) { - local_node->weight = -INFINITY; - } - } - break; - case recovery_stop_start: - break; - case recovery_block: - clear_bit(rsc->flags, pe_rsc_managed); - break; - } - crm_debug("%s is active on %d nodes including %s: %s", - rsc->id, g_list_length(rsc->running_on), node->details->uname, recovery2text(rsc->recovery_type)); - + + if (rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) { + switch (rsc->recovery_type) { + case recovery_stop_only: + { + GHashTableIter gIter; + node_t *local_node = NULL; + + /* make sure it doesnt come up again */ + g_hash_table_destroy(rsc->allowed_nodes); + rsc->allowed_nodes = node_hash_from_list(data_set->nodes); + g_hash_table_iter_init(&gIter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) { + local_node->weight = -INFINITY; + } + } + break; + case recovery_stop_start: + break; + case recovery_block: + clear_bit(rsc->flags, pe_rsc_managed); + break; + } + crm_debug("%s is active on %d nodes including %s: %s", + rsc->id, g_list_length(rsc->running_on), node->details->uname, + recovery2text(rsc->recovery_type)); + } else { - crm_trace("Resource %s is active on: %s", rsc->id, node->details->uname); + crm_trace("Resource %s is active on: %s", rsc->id, node->details->uname); } - - if(rsc->parent != NULL) { - native_add_running(rsc->parent, node, data_set); + + if (rsc->parent != NULL) { + native_add_running(rsc->parent, node, data_set); } } +extern void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set); -extern void force_non_unique_clone(resource_t *rsc, const char *rid, pe_working_set_t *data_set); -gboolean native_unpack(resource_t *rsc, pe_working_set_t *data_set) +gboolean +native_unpack(resource_t * rsc, pe_working_set_t * data_set) { - native_variant_data_t *native_data = NULL; - - crm_debug_3("Processing resource %s...", rsc->id); - - crm_malloc0(native_data, sizeof(native_variant_data_t)); - - if(is_set(rsc->flags, pe_rsc_unique) && rsc->parent) { - const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if(safe_str_eq(class, "lsb")) { - resource_t *top = uber_parent(rsc); - force_non_unique_clone(top, rsc->id, data_set); - } - } - - rsc->variant_opaque = native_data; - return TRUE; + native_variant_data_t *native_data = NULL; + + crm_debug_3("Processing resource %s...", rsc->id); + + crm_malloc0(native_data, sizeof(native_variant_data_t)); + + if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) { + const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); + + if (safe_str_eq(class, "lsb")) { + resource_t *top = uber_parent(rsc); + + force_non_unique_clone(top, rsc->id, data_set); + } + } + + rsc->variant_opaque = native_data; + return TRUE; } resource_t * -native_find_rsc( - resource_t *rsc, const char *id, node_t *on_node, int flags) +native_find_rsc(resource_t * rsc, const char *id, node_t * on_node, int flags) { gboolean match = FALSE; resource_t *result = NULL; GListPtr gIter = rsc->children; - - if(is_not_set(flags, pe_find_clone) && id == NULL) { - return NULL; + + if (is_not_set(flags, pe_find_clone) && id == NULL) { + return NULL; } - if(flags & pe_find_partial) { - if(strstr(rsc->id, id) == rsc->id) { - match = TRUE; - - } else if(rsc->long_name && strstr(rsc->long_name, id) == rsc->long_name) { - match = TRUE; - - } else if(is_set(flags, pe_find_renamed) && rsc->clone_name && strstr(rsc->clone_name, id) == rsc->clone_name) { - match = TRUE; - } - - } else if(flags & pe_find_clone) { - if(rsc->children != NULL) { - match = FALSE; - - } else if(id == NULL) { - match = TRUE; - - } else if(strstr(rsc->id, id)) { - match = TRUE; - - } else if(is_set(flags, pe_find_renamed) && rsc->clone_name && strstr(rsc->clone_name, id) == rsc->clone_name) { - match = TRUE; - } - + if (flags & pe_find_partial) { + if (strstr(rsc->id, id) == rsc->id) { + match = TRUE; + + } else if (rsc->long_name && strstr(rsc->long_name, id) == rsc->long_name) { + match = TRUE; + + } else if (is_set(flags, pe_find_renamed) && rsc->clone_name + && strstr(rsc->clone_name, id) == rsc->clone_name) { + match = TRUE; + } + + } else if (flags & pe_find_clone) { + if (rsc->children != NULL) { + match = FALSE; + + } else if (id == NULL) { + match = TRUE; + + } else if (strstr(rsc->id, id)) { + match = TRUE; + + } else if (is_set(flags, pe_find_renamed) && rsc->clone_name + && strstr(rsc->clone_name, id) == rsc->clone_name) { + match = TRUE; + } + } else { - if(strcmp(rsc->id, id) == 0){ - match = TRUE; - - } else if(rsc->long_name && strcmp(rsc->long_name, id) == 0) { - match = TRUE; - - } else if(is_set(flags, pe_find_renamed) && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) { - match = TRUE; - } + if (strcmp(rsc->id, id) == 0) { + match = TRUE; + + } else if (rsc->long_name && strcmp(rsc->long_name, id) == 0) { + match = TRUE; + + } else if (is_set(flags, pe_find_renamed) && rsc->clone_name + && strcmp(rsc->clone_name, id) == 0) { + match = TRUE; + } } - if(match && on_node) { - if(is_set(flags, pe_find_current) && rsc->running_on) { - - GListPtr gIter = rsc->running_on; - for(; gIter != NULL; gIter = gIter->next) { - node_t *loc = (node_t*)gIter->data; - - if(loc->details == on_node->details) { - return rsc; - } - } - - } else if(is_set(flags, pe_find_inactive) && rsc->running_on == NULL) { - return rsc; - - } else if(is_not_set(flags, pe_find_current) && rsc->allocated_to && rsc->allocated_to->details == on_node->details) { - return rsc; - } - - } else if(match) { - return rsc; + if (match && on_node) { + if (is_set(flags, pe_find_current) && rsc->running_on) { + + GListPtr gIter = rsc->running_on; + + for (; gIter != NULL; gIter = gIter->next) { + node_t *loc = (node_t *) gIter->data; + + if (loc->details == on_node->details) { + return rsc; + } + } + + } else if (is_set(flags, pe_find_inactive) && rsc->running_on == NULL) { + return rsc; + + } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to + && rsc->allocated_to->details == on_node->details) { + return rsc; + } + + } else if (match) { + return rsc; } - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; - result = rsc->fns->find_rsc(child, id, on_node, flags); - if(result) { - return result; - } + result = rsc->fns->find_rsc(child, id, on_node, flags); + if (result) { + return result; + } } return NULL; } char * -native_parameter( - resource_t *rsc, node_t *node, gboolean create, const char *name, - pe_working_set_t *data_set) +native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name, + pe_working_set_t * data_set) { - char *value_copy = NULL; - const char *value = NULL; - GHashTable *hash = rsc->parameters; - GHashTable *local_hash = NULL; - - CRM_CHECK(rsc != NULL, return NULL); - CRM_CHECK(name != NULL && strlen(name) != 0, return NULL); - - crm_debug_2("Looking up %s in %s", name, rsc->id); - - if(create || g_hash_table_size(rsc->parameters) == 0) { - if(node != NULL) { - crm_debug_2("Creating hash with node %s", - node->details->uname); - } else { - crm_debug_2("Creating default hash"); - } - - local_hash = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - - get_rsc_attributes(local_hash, rsc, node, data_set); - - hash = local_hash; - } - - value = g_hash_table_lookup(hash, name); - if(value == NULL) { - /* try meta attributes instead */ - value = g_hash_table_lookup(rsc->meta, name); - } - - if(value != NULL) { - value_copy = crm_strdup(value); - } - if(local_hash != NULL) { - g_hash_table_destroy(local_hash); - } - return value_copy; + char *value_copy = NULL; + const char *value = NULL; + GHashTable *hash = rsc->parameters; + GHashTable *local_hash = NULL; + + CRM_CHECK(rsc != NULL, return NULL); + CRM_CHECK(name != NULL && strlen(name) != 0, return NULL); + + crm_debug_2("Looking up %s in %s", name, rsc->id); + + if (create || g_hash_table_size(rsc->parameters) == 0) { + if (node != NULL) { + crm_debug_2("Creating hash with node %s", node->details->uname); + } else { + crm_debug_2("Creating default hash"); + } + + local_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); + + get_rsc_attributes(local_hash, rsc, node, data_set); + + hash = local_hash; + } + + value = g_hash_table_lookup(hash, name); + if (value == NULL) { + /* try meta attributes instead */ + value = g_hash_table_lookup(rsc->meta, name); + } + + if (value != NULL) { + value_copy = crm_strdup(value); + } + if (local_hash != NULL) { + g_hash_table_destroy(local_hash); + } + return value_copy; } -gboolean native_active(resource_t *rsc, gboolean all) -{ +gboolean +native_active(resource_t * rsc, gboolean all) +{ GListPtr gIter = rsc->running_on; - for(; gIter != NULL; gIter = gIter->next) { - node_t *a_node = (node_t*)gIter->data; - - - if(a_node->details->online == FALSE) { - crm_debug("Resource %s: node %s is offline", - rsc->id, a_node->details->uname); - } else if(a_node->details->unclean) { - crm_debug("Resource %s: node %s is unclean", - rsc->id, a_node->details->uname); - } else { - crm_debug("Resource %s active on %s", - rsc->id, a_node->details->uname); - return TRUE; - } + + for (; gIter != NULL; gIter = gIter->next) { + node_t *a_node = (node_t *) gIter->data; + + if (a_node->details->online == FALSE) { + crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname); + } else if (a_node->details->unclean) { + crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname); + } else { + crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname); + return TRUE; + } } - + return FALSE; } -struct print_data_s -{ - long options; - void *print_data; +struct print_data_s { + long options; + void *print_data; }; -static void native_print_attr(gpointer key, gpointer value, gpointer user_data) +static void +native_print_attr(gpointer key, gpointer value, gpointer user_data) { - long options = ((struct print_data_s*)user_data)->options; - void *print_data = ((struct print_data_s*)user_data)->print_data; - status_print("Option: %s = %s\n", (char*)key, (char*)value); + long options = ((struct print_data_s *)user_data)->options; + void *print_data = ((struct print_data_s *)user_data)->print_data; + + status_print("Option: %s = %s\n", (char *)key, (char *)value); } void -native_print( - resource_t *rsc, const char *pre_text, long options, void *print_data) +native_print(resource_t * rsc, const char *pre_text, long options, void *print_data) { - node_t *node = NULL; - const char *prov = NULL; - const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if(pre_text == NULL && (options & pe_print_printf)) { pre_text = " "; } - - if(safe_str_eq(class, "ocf")) { - prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); - } - - if(rsc->running_on != NULL) { - node = rsc->running_on->data; - } - - if(options & pe_print_html) { - if(is_not_set(rsc->flags, pe_rsc_managed)) { - status_print(""); - - } else if(is_set(rsc->flags, pe_rsc_failed)) { - status_print(""); - - } else if(rsc->variant == pe_native - && g_list_length(rsc->running_on) == 0) { - status_print(""); - - } else if(g_list_length(rsc->running_on) > 1) { - status_print(""); - - } else if(is_set(rsc->flags, pe_rsc_failure_ignored)) { - status_print(""); - - } else { - status_print(""); - } - } - - if((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { - const char *desc = NULL; - desc = crm_element_value(rsc->xml, XML_ATTR_DESC); - status_print("%s%s\t(%s%s%s:%s%s) %s %s%s%s%s%s", - pre_text?pre_text:"", rsc->id, - class, prov?"::":"", prov?prov:"", - crm_element_value(rsc->xml, XML_ATTR_TYPE), - is_set(rsc->flags, pe_rsc_orphan)?" ORPHANED":"", - (rsc->variant!=pe_native)?"":role2text(rsc->role), - is_set(rsc->flags, pe_rsc_managed)?"":" (unmanaged)", - is_set(rsc->flags, pe_rsc_failed)?" FAILED":"", - is_set(rsc->flags, pe_rsc_failure_ignored)?" (failure ignored)":"", - desc?": ":"", desc?desc:""); - - } else { - status_print("%s%s\t(%s%s%s:%s):\t%s%s %s%s%s%s", - pre_text?pre_text:"", rsc->id, - class, prov?"::":"", prov?prov:"", - crm_element_value(rsc->xml, XML_ATTR_TYPE), - is_set(rsc->flags, pe_rsc_orphan)?" ORPHANED ":"", - (rsc->variant!=pe_native)?"":role2text(rsc->role), - (rsc->variant!=pe_native)?"":node!=NULL?node->details->uname:"", - is_set(rsc->flags, pe_rsc_managed)?"":" (unmanaged)", - is_set(rsc->flags, pe_rsc_failed)?" FAILED":"", - is_set(rsc->flags, pe_rsc_failure_ignored)?" (failure ignored)":""); - + node_t *node = NULL; + const char *prov = NULL; + const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); + + if (pre_text == NULL && (options & pe_print_printf)) { + pre_text = " "; + } + + if (safe_str_eq(class, "ocf")) { + prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); + } + + if (rsc->running_on != NULL) { + node = rsc->running_on->data; + } + + if (options & pe_print_html) { + if (is_not_set(rsc->flags, pe_rsc_managed)) { + status_print(""); + + } else if (is_set(rsc->flags, pe_rsc_failed)) { + status_print(""); + + } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) { + status_print(""); + + } else if (g_list_length(rsc->running_on) > 1) { + status_print(""); + + } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) { + status_print(""); + + } else { + status_print(""); + } + } + + if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { + const char *desc = NULL; + + desc = crm_element_value(rsc->xml, XML_ATTR_DESC); + status_print("%s%s\t(%s%s%s:%s%s) %s %s%s%s%s%s", + pre_text ? pre_text : "", rsc->id, + class, prov ? "::" : "", prov ? prov : "", + crm_element_value(rsc->xml, XML_ATTR_TYPE), + is_set(rsc->flags, pe_rsc_orphan) ? " ORPHANED" : "", + (rsc->variant != pe_native) ? "" : role2text(rsc->role), + is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)", + is_set(rsc->flags, pe_rsc_failed) ? " FAILED" : "", + is_set(rsc->flags, pe_rsc_failure_ignored) ? " (failure ignored)" : "", + desc ? ": " : "", desc ? desc : ""); + + } else { + status_print("%s%s\t(%s%s%s:%s):\t%s%s %s%s%s%s", + pre_text ? pre_text : "", rsc->id, + class, prov ? "::" : "", prov ? prov : "", + crm_element_value(rsc->xml, XML_ATTR_TYPE), + is_set(rsc->flags, pe_rsc_orphan) ? " ORPHANED " : "", + (rsc->variant != pe_native) ? "" : role2text(rsc->role), + (rsc->variant != pe_native) ? "" : node != NULL ? node->details->uname : "", + is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)", + is_set(rsc->flags, pe_rsc_failed) ? " FAILED" : "", + is_set(rsc->flags, pe_rsc_failure_ignored) ? " (failure ignored)" : ""); + #if CURSES_ENABLED - if(options & pe_print_ncurses) { - move(-1, 0); /* Coverity: False positive */ - } + if (options & pe_print_ncurses) { + move(-1, 0); /* Coverity: False positive */ + } #endif - } - - if(options & pe_print_html) { - status_print(" "); - } - - if((options & pe_print_rsconly)) { - - } else if(g_list_length(rsc->running_on) > 1) { - GListPtr gIter = rsc->running_on; - int counter = 0; - - if(options & pe_print_html) { - status_print("
      \n"); - } else if((options & pe_print_printf) - || (options & pe_print_ncurses)) { - status_print("["); - } - - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - counter++; - - if(options & pe_print_html) { - status_print("
    • \n%s", - node->details->uname); - - } else if((options & pe_print_printf) - || (options & pe_print_ncurses)) { - status_print("\t%s", node->details->uname); - - } else if((options & pe_print_log)) { - status_print("\t%d : %s", counter, node->details->uname); - - } else { - status_print("%s", node->details->uname); - } - if(options & pe_print_html) { - status_print("
    • \n"); - - } - } - - if(options & pe_print_html) { - status_print("
    \n"); - } else if((options & pe_print_printf) - || (options & pe_print_ncurses)) { - status_print(" ]"); - } - } - - if(options & pe_print_html) { - status_print("
    \n"); - } else if(options & pe_print_suppres_nl) { - /* nothing */ - } else if((options & pe_print_printf) || (options & pe_print_ncurses)) { - status_print("\n"); - } - - if(options & pe_print_details) { - struct print_data_s pdata; - pdata.options = options; - pdata.print_data = print_data; - g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata); - } - - if(options & pe_print_dev) { - GHashTableIter iter; - node_t *node = NULL; - status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text, - is_set(rsc->flags, pe_rsc_provisional)?"provisional, ":"", - is_set(rsc->flags, pe_rsc_runnable)?"":"non-startable, ", - crm_element_name(rsc->xml), - (double)rsc->priority); - status_print("%s\tAllowed Nodes", pre_text); - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - status_print("%s\t * %s %d", - pre_text, - node->details->uname, - node->weight); - } - } - - if(options & pe_print_max_details) { - GHashTableIter iter; - node_t *node = NULL; - status_print("%s\t=== Allowed Nodes\n", pre_text); - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - print_node("\t", node, FALSE); - } - } + } + + if (options & pe_print_html) { + status_print("
    "); + } + + if ((options & pe_print_rsconly)) { + + } else if (g_list_length(rsc->running_on) > 1) { + GListPtr gIter = rsc->running_on; + int counter = 0; + + if (options & pe_print_html) { + status_print("
      \n"); + } else if ((options & pe_print_printf) + || (options & pe_print_ncurses)) { + status_print("["); + } + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + counter++; + + if (options & pe_print_html) { + status_print("
    • \n%s", node->details->uname); + + } else if ((options & pe_print_printf) + || (options & pe_print_ncurses)) { + status_print("\t%s", node->details->uname); + + } else if ((options & pe_print_log)) { + status_print("\t%d : %s", counter, node->details->uname); + + } else { + status_print("%s", node->details->uname); + } + if (options & pe_print_html) { + status_print("
    • \n"); + + } + } + + if (options & pe_print_html) { + status_print("
    \n"); + } else if ((options & pe_print_printf) + || (options & pe_print_ncurses)) { + status_print(" ]"); + } + } + + if (options & pe_print_html) { + status_print("
    \n"); + } else if (options & pe_print_suppres_nl) { + /* nothing */ + } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { + status_print("\n"); + } + + if (options & pe_print_details) { + struct print_data_s pdata; + + pdata.options = options; + pdata.print_data = print_data; + g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata); + } + + if (options & pe_print_dev) { + GHashTableIter iter; + node_t *node = NULL; + + status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text, + is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "", + is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ", + crm_element_name(rsc->xml), (double)rsc->priority); + status_print("%s\tAllowed Nodes", pre_text); + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + status_print("%s\t * %s %d", pre_text, node->details->uname, node->weight); + } + } + + if (options & pe_print_max_details) { + GHashTableIter iter; + node_t *node = NULL; + + status_print("%s\t=== Allowed Nodes\n", pre_text); + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + print_node("\t", node, FALSE); + } + } } -void native_free(resource_t *rsc) +void +native_free(resource_t * rsc) { - crm_debug_4("Freeing resource action list (not the data)"); - common_free(rsc); + crm_debug_4("Freeing resource action list (not the data)"); + common_free(rsc); } - enum rsc_role_e -native_resource_state(const resource_t *rsc, gboolean current) +native_resource_state(const resource_t * rsc, gboolean current) { - enum rsc_role_e role = rsc->next_role; - if(current) { - role = rsc->role; - } - crm_debug_4("%s state: %s", rsc->id, role2text(role)); - return role; + enum rsc_role_e role = rsc->next_role; + + if (current) { + role = rsc->role; + } + crm_debug_4("%s state: %s", rsc->id, role2text(role)); + return role; } -node_t *native_location(resource_t *rsc, GListPtr *list, gboolean current) +node_t * +native_location(resource_t * rsc, GListPtr * list, gboolean current) { node_t *one = NULL; GListPtr result = NULL; - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - child->fns->location(child, &result, current); - } - - - } else if(current && rsc->running_on) { - result = g_list_copy(rsc->running_on); - - } else if(current == FALSE && rsc->allocated_to) { - result = g_list_append(NULL, rsc->allocated_to); + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + child->fns->location(child, &result, current); + } + + } else if (current && rsc->running_on) { + result = g_list_copy(rsc->running_on); + + } else if (current == FALSE && rsc->allocated_to) { + result = g_list_append(NULL, rsc->allocated_to); } - if(result && g_list_length(result) == 1) { - one = g_list_nth_data(result, 0); + if (result && g_list_length(result) == 1) { + one = g_list_nth_data(result, 0); } - - if(list) { - GListPtr gIter = result; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - if(*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) { - *list = g_list_append(*list, node); - } - } + + if (list) { + GListPtr gIter = result; + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) { + *list = g_list_append(*list, node); + } + } } - g_list_free(result); + g_list_free(result); return one; } diff --git a/lib/pengine/rules.c b/lib/pengine/rules.c index 32ad038783..e47296c60c 100644 --- a/lib/pengine/rules.c +++ b/lib/pengine/rules.c @@ -1,662 +1,660 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 CRM_TRACE_INIT_DATA(pe_rules); -ha_time_t *parse_xml_duration(ha_time_t *start, xmlNode *duration_spec); +ha_time_t *parse_xml_duration(ha_time_t * start, xmlNode * duration_spec); -gboolean test_date_expression(xmlNode *time_expr, ha_time_t *now); -gboolean cron_range_satisfied(ha_time_t *now, xmlNode *cron_spec); -gboolean test_attr_expression( - xmlNode *expr, GHashTable *hash, ha_time_t *now); -gboolean test_role_expression( - xmlNode *expr, enum rsc_role_e role, ha_time_t *now); +gboolean test_date_expression(xmlNode * time_expr, ha_time_t * now); +gboolean cron_range_satisfied(ha_time_t * now, xmlNode * cron_spec); +gboolean test_attr_expression(xmlNode * expr, GHashTable * hash, ha_time_t * now); +gboolean test_role_expression(xmlNode * expr, enum rsc_role_e role, ha_time_t * now); gboolean -test_ruleset(xmlNode *ruleset, GHashTable *node_hash, ha_time_t *now) +test_ruleset(xmlNode * ruleset, GHashTable * node_hash, ha_time_t * now) { gboolean ruleset_default = TRUE; xmlNode *rule = NULL; - for(rule = __xml_first_child(ruleset); rule != NULL; rule = __xml_next(rule)) { - if(crm_str_eq((const char *)rule->name, XML_TAG_RULE, TRUE)) { - ruleset_default = FALSE; - if(test_rule(rule, node_hash, RSC_ROLE_UNKNOWN, now)) { - return TRUE; - } - } + + for (rule = __xml_first_child(ruleset); rule != NULL; rule = __xml_next(rule)) { + if (crm_str_eq((const char *)rule->name, XML_TAG_RULE, TRUE)) { + ruleset_default = FALSE; + if (test_rule(rule, node_hash, RSC_ROLE_UNKNOWN, now)) { + return TRUE; + } + } } - + return ruleset_default; } gboolean -test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, - ha_time_t *now) +test_rule(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, ha_time_t * now) { xmlNode *expr = NULL; gboolean test = TRUE; gboolean empty = TRUE; gboolean passed = TRUE; gboolean do_and = TRUE; const char *value = NULL; rule = expand_idref(rule, NULL); value = crm_element_value(rule, XML_RULE_ATTR_BOOLEAN_OP); - if(safe_str_eq(value, "or")) { - do_and = FALSE; - passed = FALSE; + if (safe_str_eq(value, "or")) { + do_and = FALSE; + passed = FALSE; } crm_debug_2("Testing rule %s", ID(rule)); - for(expr = __xml_first_child(rule); expr != NULL; expr = __xml_next(expr)) { - test = test_expression(expr, node_hash, role, now); - empty = FALSE; - - if(test && do_and == FALSE) { - crm_debug_3("Expression %s/%s passed", - ID(rule), ID(expr)); - return TRUE; - - } else if(test == FALSE && do_and) { - crm_debug_3("Expression %s/%s failed", - ID(rule), ID(expr)); - return FALSE; - } + for (expr = __xml_first_child(rule); expr != NULL; expr = __xml_next(expr)) { + test = test_expression(expr, node_hash, role, now); + empty = FALSE; + + if (test && do_and == FALSE) { + crm_debug_3("Expression %s/%s passed", ID(rule), ID(expr)); + return TRUE; + + } else if (test == FALSE && do_and) { + crm_debug_3("Expression %s/%s failed", ID(rule), ID(expr)); + return FALSE; + } } - if(empty) { - crm_err("Invalid Rule %s: rules must contain at least one expression", ID(rule)); + if (empty) { + crm_err("Invalid Rule %s: rules must contain at least one expression", ID(rule)); } - - crm_debug_2("Rule %s %s", ID(rule), passed?"passed":"failed"); + + crm_debug_2("Rule %s %s", ID(rule), passed ? "passed" : "failed"); return passed; } gboolean -test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, - ha_time_t *now) +test_expression(xmlNode * expr, GHashTable * node_hash, enum rsc_role_e role, ha_time_t * now) { gboolean accept = FALSE; const char *uname = NULL; - - switch(find_expression_type(expr)) { - case nested_rule: - accept = test_rule(expr, node_hash, role, now); - break; - case attr_expr: - case loc_expr: - /* these expressions can never succeed if there is - * no node to compare with - */ - if(node_hash != NULL) { - accept = test_attr_expression(expr, node_hash, now); - } - break; - - case time_expr: - accept = test_date_expression(expr, now); - break; - - case role_expr: - accept = test_role_expression(expr, role, now); - break; - - default: - CRM_CHECK(FALSE /* bad type */, return FALSE); - accept = FALSE; + + switch (find_expression_type(expr)) { + case nested_rule: + accept = test_rule(expr, node_hash, role, now); + break; + case attr_expr: + case loc_expr: + /* these expressions can never succeed if there is + * no node to compare with + */ + if (node_hash != NULL) { + accept = test_attr_expression(expr, node_hash, now); + } + break; + + case time_expr: + accept = test_date_expression(expr, now); + break; + + case role_expr: + accept = test_role_expression(expr, role, now); + break; + + default: + CRM_CHECK(FALSE /* bad type */ , return FALSE); + accept = FALSE; } - if(node_hash) { - uname = g_hash_table_lookup(node_hash, "#uname"); + if (node_hash) { + uname = g_hash_table_lookup(node_hash, "#uname"); } - + crm_debug_2("Expression %s %s on %s", - ID(expr), accept?"passed":"failed", - uname?uname:"all ndoes"); + ID(expr), accept ? "passed" : "failed", uname ? uname : "all ndoes"); return accept; } enum expression_type -find_expression_type(xmlNode *expr) +find_expression_type(xmlNode * expr) { const char *tag = NULL; - const char *attr = NULL; + const char *attr = NULL; + attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE); tag = crm_element_name(expr); - if(safe_str_eq(tag, "date_expression")) { - return time_expr; - - } else if(safe_str_eq(tag, XML_TAG_RULE)) { - return nested_rule; - - } else if(safe_str_neq(tag, "expression")) { - return not_expr; - - } else if(safe_str_eq(attr, "#uname") || safe_str_eq(attr, "#id")) { - return loc_expr; - - } else if(safe_str_eq(attr, "#role")) { - return role_expr; - } + if (safe_str_eq(tag, "date_expression")) { + return time_expr; + + } else if (safe_str_eq(tag, XML_TAG_RULE)) { + return nested_rule; + + } else if (safe_str_neq(tag, "expression")) { + return not_expr; + + } else if (safe_str_eq(attr, "#uname") || safe_str_eq(attr, "#id")) { + return loc_expr; + + } else if (safe_str_eq(attr, "#role")) { + return role_expr; + } return attr_expr; } gboolean -test_role_expression( - xmlNode *expr, enum rsc_role_e role, ha_time_t *now) +test_role_expression(xmlNode * expr, enum rsc_role_e role, ha_time_t * now) { gboolean accept = FALSE; - const char *op = NULL; - const char *value = NULL; + const char *op = NULL; + const char *value = NULL; - if(role == RSC_ROLE_UNKNOWN) { - return accept; + if (role == RSC_ROLE_UNKNOWN) { + return accept; } - + value = crm_element_value(expr, XML_EXPR_ATTR_VALUE); - op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION); - - if(safe_str_eq(op, "defined")) { - if(role > RSC_ROLE_STARTED) { - accept = TRUE; - } - - } else if(safe_str_eq(op, "not_defined")) { - if(role < RSC_ROLE_SLAVE && role > RSC_ROLE_UNKNOWN) { - accept = TRUE; - } - - } else if(safe_str_eq(op, "eq")) { - if(text2role(value) == role) { - accept = TRUE; - } - - } else if(safe_str_eq(op, "ne")) { - /* we will only test "ne" wtih master/slave roles style */ - if(role < RSC_ROLE_SLAVE && role > RSC_ROLE_UNKNOWN) { - accept = FALSE; - - } else if(text2role(value) != role) { - accept = TRUE; - } - } + op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION); + + if (safe_str_eq(op, "defined")) { + if (role > RSC_ROLE_STARTED) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "not_defined")) { + if (role < RSC_ROLE_SLAVE && role > RSC_ROLE_UNKNOWN) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "eq")) { + if (text2role(value) == role) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "ne")) { + /* we will only test "ne" wtih master/slave roles style */ + if (role < RSC_ROLE_SLAVE && role > RSC_ROLE_UNKNOWN) { + accept = FALSE; + + } else if (text2role(value) != role) { + accept = TRUE; + } + } return accept; } gboolean -test_attr_expression(xmlNode *expr, GHashTable *hash, ha_time_t *now) +test_attr_expression(xmlNode * expr, GHashTable * hash, ha_time_t * now) { gboolean accept = FALSE; int cmp = 0; const char *h_val = NULL; - const char *op = NULL; - const char *type = NULL; - const char *attr = NULL; - const char *value = NULL; - - attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE); - op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION); + const char *op = NULL; + const char *type = NULL; + const char *attr = NULL; + const char *value = NULL; + + attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE); + op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION); value = crm_element_value(expr, XML_EXPR_ATTR_VALUE); - type = crm_element_value(expr, XML_EXPR_ATTR_TYPE); - - if(attr == NULL || op == NULL) { - pe_err("Invlaid attribute or operation in expression" - " (\'%s\' \'%s\' \'%s\')", - crm_str(attr), crm_str(op), crm_str(value)); - return FALSE; + type = crm_element_value(expr, XML_EXPR_ATTR_TYPE); + + if (attr == NULL || op == NULL) { + pe_err("Invlaid attribute or operation in expression" + " (\'%s\' \'%s\' \'%s\')", crm_str(attr), crm_str(op), crm_str(value)); + return FALSE; } - if(hash != NULL) { - h_val = (const char*)g_hash_table_lookup(hash, attr); + if (hash != NULL) { + h_val = (const char *)g_hash_table_lookup(hash, attr); } - - if(value != NULL && h_val != NULL) { - if(type == NULL) { - if(safe_str_eq(op, "lt") - || safe_str_eq(op, "lte") - || safe_str_eq(op, "gt") - || safe_str_eq(op, "gte")) { - type = "number"; - - } else { - type = "string"; - } - crm_debug_2("Defaulting to %s based comparison for '%s' op", type, op); - } - - if(safe_str_eq(type, "string")) { - cmp = strcasecmp(h_val, value); - - } else if(safe_str_eq(type, "number")) { - int h_val_f = crm_parse_int(h_val, NULL); - int value_f = crm_parse_int(value, NULL); - - if(h_val_f < value_f) { - cmp = -1; - } else if(h_val_f > value_f) { - cmp = 1; - } else { - cmp = 0; - } - - } else if(safe_str_eq(type, "version")) { - cmp = compare_version(h_val, value); - - } - - } else if(value == NULL && h_val == NULL) { - cmp = 0; - } else if(value == NULL) { - cmp = 1; + + if (value != NULL && h_val != NULL) { + if (type == NULL) { + if (safe_str_eq(op, "lt") + || safe_str_eq(op, "lte") + || safe_str_eq(op, "gt") + || safe_str_eq(op, "gte")) { + type = "number"; + + } else { + type = "string"; + } + crm_debug_2("Defaulting to %s based comparison for '%s' op", type, op); + } + + if (safe_str_eq(type, "string")) { + cmp = strcasecmp(h_val, value); + + } else if (safe_str_eq(type, "number")) { + int h_val_f = crm_parse_int(h_val, NULL); + int value_f = crm_parse_int(value, NULL); + + if (h_val_f < value_f) { + cmp = -1; + } else if (h_val_f > value_f) { + cmp = 1; + } else { + cmp = 0; + } + + } else if (safe_str_eq(type, "version")) { + cmp = compare_version(h_val, value); + + } + + } else if (value == NULL && h_val == NULL) { + cmp = 0; + } else if (value == NULL) { + cmp = 1; } else { - cmp = -1; + cmp = -1; } - - if(safe_str_eq(op, "defined")) { - if(h_val != NULL) { accept = TRUE; } - - } else if(safe_str_eq(op, "not_defined")) { - if(h_val == NULL) { accept = TRUE; } - - } else if(safe_str_eq(op, "eq")) { - if((h_val == value) || cmp == 0) { - accept = TRUE; - } - - } else if(safe_str_eq(op, "ne")) { - if((h_val == NULL && value != NULL) - || (h_val != NULL && value == NULL) - || cmp != 0) { - accept = TRUE; - } - - } else if(value == NULL || h_val == NULL) { - /* the comparision is meaningless from this point on */ - accept = FALSE; - - } else if(safe_str_eq(op, "lt")) { - if(cmp < 0) { accept = TRUE; } - - } else if(safe_str_eq(op, "lte")) { - if(cmp <= 0) { accept = TRUE; } - - } else if(safe_str_eq(op, "gt")) { - if(cmp > 0) { accept = TRUE; } - - } else if(safe_str_eq(op, "gte")) { - if(cmp >= 0) { accept = TRUE; } + + if (safe_str_eq(op, "defined")) { + if (h_val != NULL) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "not_defined")) { + if (h_val == NULL) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "eq")) { + if ((h_val == value) || cmp == 0) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "ne")) { + if ((h_val == NULL && value != NULL) + || (h_val != NULL && value == NULL) + || cmp != 0) { + accept = TRUE; + } + + } else if (value == NULL || h_val == NULL) { + /* the comparision is meaningless from this point on */ + accept = FALSE; + + } else if (safe_str_eq(op, "lt")) { + if (cmp < 0) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "lte")) { + if (cmp <= 0) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "gt")) { + if (cmp > 0) { + accept = TRUE; + } + + } else if (safe_str_eq(op, "gte")) { + if (cmp >= 0) { + accept = TRUE; + } } - + return accept; } /* As per the nethack rules: * * moon period = 29.53058 days ~= 30, year = 365.2422 days * days moon phase advances on first day of year compared to preceding year * = 365.2422 - 12*29.53058 ~= 11 * years in Metonic cycle (time until same phases fall on the same days of * the month) = 18.6 ~= 19 * moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30 * (29 as initial condition) * current phase in days = first day phase + days elapsed in year * 6 moons ~= 177 days * 177 ~= 8 reported phases * 22 * + 11/22 for rounding * * 0-7, with 0: new, 4: full */ static int -phase_of_the_moon(ha_time_t *now) +phase_of_the_moon(ha_time_t * now) { int epact, diy, goldn; diy = now->yeardays; goldn = (now->years % 19) + 1; epact = (11 * goldn + 18) % 30; if ((epact == 25 && goldn > 11) || epact == 24) - epact++; + epact++; - return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 ); + return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7); } #define cron_check(xml_field, time_field) \ value = crm_element_value(cron_spec, xml_field); \ if(value != NULL) { \ gboolean pass = TRUE; \ decodeNVpair(value, '-', &value_low, &value_high); \ if(value_low == NULL) { \ value_low = crm_strdup(value); \ } \ value_low_i = crm_parse_int(value_low, "0"); \ value_high_i = crm_parse_int(value_high, "-1"); \ if(value_high_i < 0) { \ if(value_low_i != time_field) { \ pass = FALSE; \ } \ } else if(value_low_i > time_field) { \ pass = FALSE; \ } else if(value_high_i < time_field) { \ pass = FALSE; \ } \ crm_free(value_low); \ crm_free(value_high); \ if(pass == FALSE) { \ crm_debug("Condition '%s' in %s: failed", value, xml_field); \ return pass; \ } \ crm_debug("Condition '%s' in %s: passed", value, xml_field); \ } gboolean -cron_range_satisfied(ha_time_t *now, xmlNode *cron_spec) +cron_range_satisfied(ha_time_t * now, xmlNode * cron_spec) { const char *value = NULL; char *value_low = NULL; char *value_high = NULL; int value_low_i = 0; int value_high_i = 0; CRM_CHECK(now != NULL, return FALSE); - - cron_check("seconds", now->seconds); - cron_check("minutes", now->minutes); - cron_check("hours", now->hours); - cron_check("monthdays", now->days); - cron_check("weekdays", now->weekdays); - cron_check("yeardays", now->yeardays); - cron_check("weeks", now->weeks); - cron_check("months", now->months); - cron_check("years", now->years); - cron_check("weekyears", now->weekyears); - cron_check("moon", phase_of_the_moon(now)); - + + cron_check("seconds", now->seconds); + cron_check("minutes", now->minutes); + cron_check("hours", now->hours); + cron_check("monthdays", now->days); + cron_check("weekdays", now->weekdays); + cron_check("yeardays", now->yeardays); + cron_check("weeks", now->weeks); + cron_check("months", now->months); + cron_check("years", now->years); + cron_check("weekyears", now->weekyears); + cron_check("moon", phase_of_the_moon(now)); + return TRUE; } #define update_field(xml_field, time_fn) \ value = crm_element_value(duration_spec, xml_field); \ if(value != NULL) { \ int value_i = crm_parse_int(value, "0"); \ time_fn(end, value_i); \ } ha_time_t * -parse_xml_duration(ha_time_t *start, xmlNode *duration_spec) +parse_xml_duration(ha_time_t * start, xmlNode * duration_spec) { ha_time_t *end = NULL; const char *value = NULL; end = new_ha_date(FALSE); ha_set_time(end, start, TRUE); - update_field("years", add_years); - update_field("months", add_months); - update_field("weeks", add_weeks); - update_field("days", add_days); - update_field("hours", add_hours); + update_field("years", add_years); + update_field("months", add_months); + update_field("weeks", add_weeks); + update_field("days", add_days); + update_field("hours", add_hours); update_field("minutes", add_minutes); update_field("seconds", add_seconds); - + return end; } - gboolean -test_date_expression(xmlNode *time_expr, ha_time_t *now) +test_date_expression(xmlNode * time_expr, ha_time_t * now) { ha_time_t *start = NULL; ha_time_t *end = NULL; const char *value = NULL; char *value_copy = NULL; char *value_copy_start = NULL; const char *op = crm_element_value(time_expr, "operation"); xmlNode *duration_spec = NULL; xmlNode *date_spec = NULL; gboolean passed = FALSE; crm_debug_2("Testing expression: %s", ID(time_expr)); - + duration_spec = first_named_child(time_expr, "duration"); date_spec = first_named_child(time_expr, "date_spec"); - + value = crm_element_value(time_expr, "start"); - if(value != NULL) { - value_copy = crm_strdup(value); - value_copy_start = value_copy; - start = parse_date(&value_copy); - crm_free(value_copy_start); + if (value != NULL) { + value_copy = crm_strdup(value); + value_copy_start = value_copy; + start = parse_date(&value_copy); + crm_free(value_copy_start); } value = crm_element_value(time_expr, "end"); - if(value != NULL) { - value_copy = crm_strdup(value); - value_copy_start = value_copy; - end = parse_date(&value_copy); - crm_free(value_copy_start); + if (value != NULL) { + value_copy = crm_strdup(value); + value_copy_start = value_copy; + end = parse_date(&value_copy); + crm_free(value_copy_start); } - if(start != NULL && end == NULL && duration_spec != NULL) { - end = parse_xml_duration(start, duration_spec); + if (start != NULL && end == NULL && duration_spec != NULL) { + end = parse_xml_duration(start, duration_spec); } - if(op == NULL) { - op = "in_range"; + if (op == NULL) { + op = "in_range"; } - - if(safe_str_eq(op, "date_spec") || safe_str_eq(op, "in_range")) { - if(start != NULL && compare_date(start, now) > 0) { - passed = FALSE; - } else if(end != NULL && compare_date(end, now) < 0) { - passed = FALSE; - } else if(safe_str_eq(op, "in_range")) { - passed = TRUE; - } else { - passed = cron_range_satisfied(now, date_spec); - } - - } else if(safe_str_eq(op, "gt") && compare_date(start, now) < 0) { - passed = TRUE; - - - } else if(safe_str_eq(op, "lt") && compare_date(end, now) > 0) { - passed = TRUE; - - } else if(safe_str_eq(op, "eq") && compare_date(start, now) == 0) { - passed = TRUE; - - } else if(safe_str_eq(op, "neq") && compare_date(start, now) != 0) { - passed = TRUE; + + if (safe_str_eq(op, "date_spec") || safe_str_eq(op, "in_range")) { + if (start != NULL && compare_date(start, now) > 0) { + passed = FALSE; + } else if (end != NULL && compare_date(end, now) < 0) { + passed = FALSE; + } else if (safe_str_eq(op, "in_range")) { + passed = TRUE; + } else { + passed = cron_range_satisfied(now, date_spec); + } + + } else if (safe_str_eq(op, "gt") && compare_date(start, now) < 0) { + passed = TRUE; + + } else if (safe_str_eq(op, "lt") && compare_date(end, now) > 0) { + passed = TRUE; + + } else if (safe_str_eq(op, "eq") && compare_date(start, now) == 0) { + passed = TRUE; + + } else if (safe_str_eq(op, "neq") && compare_date(start, now) != 0) { + passed = TRUE; } free_ha_date(start); free_ha_date(end); return passed; } - -typedef struct sorted_set_s -{ - int score; - const char *name; - const char *special_name; - xmlNode *attr_set; +typedef struct sorted_set_s { + int score; + const char *name; + const char *special_name; + xmlNode *attr_set; } sorted_set_t; static gint sort_pairs(gconstpointer a, gconstpointer b) { const sorted_set_t *pair_a = a; const sorted_set_t *pair_b = b; - - if(a == NULL && b == NULL) { - return 0; - } else if(a == NULL) { - return 1; - } else if(b == NULL) { - return -1; + + if (a == NULL && b == NULL) { + return 0; + } else if (a == NULL) { + return 1; + } else if (b == NULL) { + return -1; } - if(safe_str_eq(pair_a->name, pair_a->special_name)) { - return -1; + if (safe_str_eq(pair_a->name, pair_a->special_name)) { + return -1; - } else if(safe_str_eq(pair_b->name, pair_a->special_name)) { - return 1; + } else if (safe_str_eq(pair_b->name, pair_a->special_name)) { + return 1; } - - if(pair_a->score < pair_b->score) { - return 1; - } else if(pair_a->score > pair_b->score) { - return -1; + + if (pair_a->score < pair_b->score) { + return 1; + } else if (pair_a->score > pair_b->score) { + return -1; } return 0; } - static void -populate_hash(xmlNode *nvpair_list, GHashTable *hash, gboolean overwrite) +populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite) { const char *name = NULL; const char *value = NULL; const char *old_value = NULL; xmlNode *list = nvpair_list; xmlNode *an_attr = NULL; name = crm_element_name(list->children); - if(safe_str_eq(XML_TAG_ATTRS, name)) { - list = list->children; + if (safe_str_eq(XML_TAG_ATTRS, name)) { + list = list->children; } - for(an_attr = __xml_first_child(list); an_attr != NULL; an_attr = __xml_next(an_attr)) { - if(crm_str_eq((const char *)an_attr->name, XML_CIB_TAG_NVPAIR, TRUE)) { - name = crm_element_value(an_attr, XML_NVPAIR_ATTR_NAME); - - crm_debug_4("Setting attribute: %s", name); - value = crm_element_value( - an_attr, XML_NVPAIR_ATTR_VALUE); - - if(name == NULL || value == NULL) { - continue; - - } - - old_value = g_hash_table_lookup(hash, name); - - if(safe_str_eq(value, "#default")) { - if(old_value) { - crm_debug_2("Removing value for %s (%s)", name, value); - g_hash_table_remove(hash, name); - } - continue; - - } else if(old_value == NULL) { - g_hash_table_insert(hash, crm_strdup(name), crm_strdup(value)); - - } else if(overwrite) { - crm_debug("Overwriting value of %s: %s -> %s", name, old_value, value); - g_hash_table_replace(hash, crm_strdup(name), crm_strdup(value)); - } - } + for (an_attr = __xml_first_child(list); an_attr != NULL; an_attr = __xml_next(an_attr)) { + if (crm_str_eq((const char *)an_attr->name, XML_CIB_TAG_NVPAIR, TRUE)) { + name = crm_element_value(an_attr, XML_NVPAIR_ATTR_NAME); + + crm_debug_4("Setting attribute: %s", name); + value = crm_element_value(an_attr, XML_NVPAIR_ATTR_VALUE); + + if (name == NULL || value == NULL) { + continue; + + } + + old_value = g_hash_table_lookup(hash, name); + + if (safe_str_eq(value, "#default")) { + if (old_value) { + crm_debug_2("Removing value for %s (%s)", name, value); + g_hash_table_remove(hash, name); + } + continue; + + } else if (old_value == NULL) { + g_hash_table_insert(hash, crm_strdup(name), crm_strdup(value)); + + } else if (overwrite) { + crm_debug("Overwriting value of %s: %s -> %s", name, old_value, value); + g_hash_table_replace(hash, crm_strdup(name), crm_strdup(value)); + } + } } } struct unpack_data_s { - gboolean overwrite; - GHashTable *node_hash; - GHashTable *hash; - ha_time_t *now; + gboolean overwrite; + GHashTable *node_hash; + GHashTable *hash; + ha_time_t *now; }; static void unpack_attr_set(gpointer data, gpointer user_data) { sorted_set_t *pair = data; struct unpack_data_s *unpack_data = user_data; - - if(test_ruleset(pair->attr_set, - unpack_data->node_hash, unpack_data->now) == FALSE) { - return; + + if (test_ruleset(pair->attr_set, unpack_data->node_hash, unpack_data->now) == FALSE) { + return; } - + crm_debug_3("Adding attributes from %s", pair->name); populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite); } void -unpack_instance_attributes( - xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, - GHashTable *hash, const char *always_first, gboolean overwrite, ha_time_t *now) +unpack_instance_attributes(xmlNode * top, xmlNode * xml_obj, const char *set_name, + GHashTable * node_hash, GHashTable * hash, const char *always_first, + gboolean overwrite, ha_time_t * now) { GListPtr sorted = NULL; GListPtr unsorted = NULL; const char *score = NULL; sorted_set_t *pair = NULL; struct unpack_data_s data; xmlNode *attr_set = NULL; - - if(xml_obj == NULL) { - crm_debug_4("No instance attributes"); - return; + + if (xml_obj == NULL) { + crm_debug_4("No instance attributes"); + return; } crm_debug_4("Checking for attributes"); - for(attr_set = __xml_first_child(xml_obj); attr_set != NULL; attr_set = __xml_next(attr_set)) { - /* Uncertain if set_name == NULL check is strictly necessary here */ - if(set_name == NULL || crm_str_eq((const char *)attr_set->name, set_name, TRUE)) { - pair = NULL; - attr_set = expand_idref(attr_set, top); - if(attr_set == NULL) { - continue; - } - - crm_malloc0(pair, sizeof(sorted_set_t)); - pair->name = ID(attr_set); - pair->special_name = always_first; - pair->attr_set = attr_set; - - score = crm_element_value(attr_set, XML_RULE_ATTR_SCORE); - pair->score = char2score(score); - - unsorted = g_list_prepend(unsorted, pair); - } + for (attr_set = __xml_first_child(xml_obj); attr_set != NULL; attr_set = __xml_next(attr_set)) { + /* Uncertain if set_name == NULL check is strictly necessary here */ + if (set_name == NULL || crm_str_eq((const char *)attr_set->name, set_name, TRUE)) { + pair = NULL; + attr_set = expand_idref(attr_set, top); + if (attr_set == NULL) { + continue; + } + + crm_malloc0(pair, sizeof(sorted_set_t)); + pair->name = ID(attr_set); + pair->special_name = always_first; + pair->attr_set = attr_set; + + score = crm_element_value(attr_set, XML_RULE_ATTR_SCORE); + pair->score = char2score(score); + + unsorted = g_list_prepend(unsorted, pair); + } } - if(pair != NULL) { - data.hash = hash; - data.node_hash = node_hash; - data.now = now; - data.overwrite = overwrite; + if (pair != NULL) { + data.hash = hash; + data.node_hash = node_hash; + data.now = now; + data.overwrite = overwrite; } - + sorted = g_list_sort(unsorted, sort_pairs); g_list_foreach(sorted, unpack_attr_set, &data); slist_basic_destroy(sorted); } diff --git a/lib/pengine/status.c b/lib/pengine/status.c index 3e210af0b4..664a62918a 100644 --- a/lib/pengine/status.c +++ b/lib/pengine/status.c @@ -1,289 +1,286 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 -extern xmlNode*get_object_root( - const char *object_type, xmlNode *the_root); +extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root); #define MEMCHECK_STAGE_0 0 #define check_and_exit(stage) cleanup_calculations(data_set); \ crm_mem_stats(NULL); \ crm_err("Exiting: stage %d", stage); \ exit(1); - /* * Unpack everything * At the end you'll have: * - A list of nodes * - A list of resources (each with any dependencies on other resources) * - A list of constraints between resources and nodes * - A list of constraints between start/stop actions * - A list of nodes that need to be stonith'd * - A list of nodes that need to be shutdown * - A list of the possible stop/start actions (without dependencies) */ gboolean -cluster_status(pe_working_set_t *data_set) +cluster_status(pe_working_set_t * data_set) { - xmlNode * config = get_object_root( - XML_CIB_TAG_CRMCONFIG, data_set->input); - xmlNode * cib_nodes = get_object_root( - XML_CIB_TAG_NODES, data_set->input); - xmlNode * cib_resources = get_object_root( - XML_CIB_TAG_RESOURCES, data_set->input); - xmlNode * cib_status = get_object_root( - XML_CIB_TAG_STATUS, data_set->input); - xmlNode * cib_domains = get_object_root( - XML_CIB_TAG_DOMAINS, data_set->input); - const char *value = crm_element_value( - data_set->input, XML_ATTR_HAVE_QUORUM); - - crm_debug_3("Beginning unpack"); - pe_dataset = data_set; - - /* reset remaining global variables */ - data_set->failed = create_xml_node(NULL, "failed-ops"); - - if(data_set->input == NULL) { - return FALSE; - } - - if(data_set->now == NULL) { - data_set->now = new_ha_date(TRUE); - } - - if(data_set->input != NULL - && crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) { - /* this should always be present */ - data_set->dc_uuid = crm_element_value_copy( - data_set->input, XML_ATTR_DC_UUID); - } - - clear_bit_inplace(data_set->flags, pe_flag_have_quorum); - if(crm_is_true(value)) { - set_bit_inplace(data_set->flags, pe_flag_have_quorum); - } - - data_set->op_defaults = get_object_root(XML_CIB_TAG_OPCONFIG, data_set->input); - data_set->rsc_defaults = get_object_root(XML_CIB_TAG_RSCCONFIG, data_set->input); - - unpack_config(config, data_set); - - if(is_set(data_set->flags, pe_flag_have_quorum) == FALSE - && data_set->no_quorum_policy != no_quorum_ignore) { - crm_warn("We do not have quorum" - " - fencing and resource management disabled"); - } - - unpack_nodes(cib_nodes, data_set); - unpack_domains(cib_domains, data_set); - unpack_resources(cib_resources, data_set); - unpack_status(cib_status, data_set); - - set_bit_inplace(data_set->flags, pe_flag_have_status); - return TRUE; + xmlNode *config = get_object_root(XML_CIB_TAG_CRMCONFIG, data_set->input); + xmlNode *cib_nodes = get_object_root(XML_CIB_TAG_NODES, data_set->input); + xmlNode *cib_resources = get_object_root(XML_CIB_TAG_RESOURCES, data_set->input); + xmlNode *cib_status = get_object_root(XML_CIB_TAG_STATUS, data_set->input); + xmlNode *cib_domains = get_object_root(XML_CIB_TAG_DOMAINS, data_set->input); + const char *value = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM); + + crm_debug_3("Beginning unpack"); + pe_dataset = data_set; + + /* reset remaining global variables */ + data_set->failed = create_xml_node(NULL, "failed-ops"); + + if (data_set->input == NULL) { + return FALSE; + } + + if (data_set->now == NULL) { + data_set->now = new_ha_date(TRUE); + } + + if (data_set->input != NULL && crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) { + /* this should always be present */ + data_set->dc_uuid = crm_element_value_copy(data_set->input, XML_ATTR_DC_UUID); + } + + clear_bit_inplace(data_set->flags, pe_flag_have_quorum); + if (crm_is_true(value)) { + set_bit_inplace(data_set->flags, pe_flag_have_quorum); + } + + data_set->op_defaults = get_object_root(XML_CIB_TAG_OPCONFIG, data_set->input); + data_set->rsc_defaults = get_object_root(XML_CIB_TAG_RSCCONFIG, data_set->input); + + unpack_config(config, data_set); + + if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE + && data_set->no_quorum_policy != no_quorum_ignore) { + crm_warn("We do not have quorum" " - fencing and resource management disabled"); + } + + unpack_nodes(cib_nodes, data_set); + unpack_domains(cib_domains, data_set); + unpack_resources(cib_resources, data_set); + unpack_status(cib_status, data_set); + + set_bit_inplace(data_set->flags, pe_flag_have_status); + return TRUE; } static void pe_free_resources(GListPtr resources) -{ - resource_t *rsc = NULL; - GListPtr iterator = resources; - while(iterator != NULL) { - iterator = iterator; - rsc = (resource_t *)iterator->data; - iterator = iterator->next; - rsc->fns->free(rsc); - } - if(resources != NULL) { - g_list_free(resources); - } +{ + resource_t *rsc = NULL; + GListPtr iterator = resources; + + while (iterator != NULL) { + iterator = iterator; + rsc = (resource_t *) iterator->data; + iterator = iterator->next; + rsc->fns->free(rsc); + } + if (resources != NULL) { + g_list_free(resources); + } } static void -pe_free_actions(GListPtr actions) +pe_free_actions(GListPtr actions) { - GListPtr iterator = actions; - while(iterator != NULL) { - pe_free_action(iterator->data); - iterator = iterator->next; - } - if(actions != NULL) { - g_list_free(actions); - } + GListPtr iterator = actions; + + while (iterator != NULL) { + pe_free_action(iterator->data); + iterator = iterator->next; + } + if (actions != NULL) { + g_list_free(actions); + } } static void pe_free_nodes(GListPtr nodes) { - GListPtr iterator = nodes; - while(iterator != NULL) { - node_t *node = (node_t*)iterator->data; - struct node_shared_s *details = node->details; - iterator = iterator->next; - - crm_debug_5("deleting node"); - crm_debug_5("%s is being deleted", details->uname); - print_node("delete", node, FALSE); - - if(details != NULL) { - if(details->attrs != NULL) { - g_hash_table_destroy(details->attrs); - } - if(details->utilization != NULL) { - g_hash_table_destroy(details->utilization); - } - g_list_free(details->running_rsc); - g_list_free(details->allocated_rsc); - crm_free(details); - } - crm_free(node); - } - if(nodes != NULL) { - g_list_free(nodes); - } + GListPtr iterator = nodes; + + while (iterator != NULL) { + node_t *node = (node_t *) iterator->data; + struct node_shared_s *details = node->details; + + iterator = iterator->next; + + crm_debug_5("deleting node"); + crm_debug_5("%s is being deleted", details->uname); + print_node("delete", node, FALSE); + + if (details != NULL) { + if (details->attrs != NULL) { + g_hash_table_destroy(details->attrs); + } + if (details->utilization != NULL) { + g_hash_table_destroy(details->utilization); + } + g_list_free(details->running_rsc); + g_list_free(details->allocated_rsc); + crm_free(details); + } + crm_free(node); + } + if (nodes != NULL) { + g_list_free(nodes); + } } void -cleanup_calculations(pe_working_set_t *data_set) +cleanup_calculations(pe_working_set_t * data_set) { - pe_dataset = NULL; - if(data_set == NULL) { - return; - } - - clear_bit_inplace(data_set->flags, pe_flag_have_status); - if(data_set->config_hash != NULL) { - g_hash_table_destroy(data_set->config_hash); - } - - if(data_set->tickets) { - g_hash_table_destroy(data_set->tickets); - } - - crm_free(data_set->dc_uuid); - - crm_debug_3("deleting resources"); - pe_free_resources(data_set->resources); - - crm_debug_3("deleting actions"); - pe_free_actions(data_set->actions); - - if(data_set->domains) { - g_hash_table_destroy(data_set->domains); - } - - crm_debug_3("deleting nodes"); - pe_free_nodes(data_set->nodes); - - free_xml(data_set->graph); - free_ha_date(data_set->now); - free_xml(data_set->input); - free_xml(data_set->failed); - - set_working_set_defaults(data_set); - - CRM_CHECK(data_set->ordering_constraints == NULL, ;); - CRM_CHECK(data_set->placement_constraints == NULL, ;); + pe_dataset = NULL; + if (data_set == NULL) { + return; + } + + clear_bit_inplace(data_set->flags, pe_flag_have_status); + if (data_set->config_hash != NULL) { + g_hash_table_destroy(data_set->config_hash); + } + + if (data_set->tickets) { + g_hash_table_destroy(data_set->tickets); + } + + crm_free(data_set->dc_uuid); + + crm_debug_3("deleting resources"); + pe_free_resources(data_set->resources); + + crm_debug_3("deleting actions"); + pe_free_actions(data_set->actions); + + if (data_set->domains) { + g_hash_table_destroy(data_set->domains); + } + + crm_debug_3("deleting nodes"); + pe_free_nodes(data_set->nodes); + + free_xml(data_set->graph); + free_ha_date(data_set->now); + free_xml(data_set->input); + free_xml(data_set->failed); + + set_working_set_defaults(data_set); + + CRM_CHECK(data_set->ordering_constraints == NULL,; + ); + CRM_CHECK(data_set->placement_constraints == NULL,; + ); } void -set_working_set_defaults(pe_working_set_t *data_set) +set_working_set_defaults(pe_working_set_t * data_set) { pe_dataset = data_set; memset(data_set, 0, sizeof(pe_working_set_t)); - data_set->order_id = 1; - data_set->action_id = 1; - data_set->no_quorum_policy = no_quorum_freeze; + data_set->order_id = 1; + data_set->action_id = 1; + data_set->no_quorum_policy = no_quorum_freeze; data_set->flags = 0x0ULL; set_bit_inplace(data_set->flags, pe_flag_stop_rsc_orphans); set_bit_inplace(data_set->flags, pe_flag_symmetric_cluster); set_bit_inplace(data_set->flags, pe_flag_is_managed_default); - set_bit_inplace(data_set->flags, pe_flag_stop_action_orphans); + set_bit_inplace(data_set->flags, pe_flag_stop_action_orphans); } - resource_t * pe_find_resource(GListPtr rsc_list, const char *id) { - unsigned lpc = 0; - resource_t *rsc = NULL; - resource_t *match = NULL; - - if(id == NULL) { - return NULL; - } - - for(lpc = 0; lpc < g_list_length(rsc_list); lpc++) { - rsc = g_list_nth_data(rsc_list, lpc); - - match = rsc->fns->find_rsc(rsc, id, NULL, pe_find_renamed|pe_find_current); - if(match != NULL) { - return match; - } - } - crm_debug_2("No match for %s", id); - return NULL; + unsigned lpc = 0; + resource_t *rsc = NULL; + resource_t *match = NULL; + + if (id == NULL) { + return NULL; + } + + for (lpc = 0; lpc < g_list_length(rsc_list); lpc++) { + rsc = g_list_nth_data(rsc_list, lpc); + + match = rsc->fns->find_rsc(rsc, id, NULL, pe_find_renamed | pe_find_current); + if (match != NULL) { + return match; + } + } + crm_debug_2("No match for %s", id); + return NULL; } node_t * pe_find_node_id(GListPtr nodes, const char *id) { GListPtr gIter = nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - if(node && safe_str_eq(node->details->id, id)) { - return node; - } + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + if (node && safe_str_eq(node->details->id, id)) { + return node; + } } /* error */ return NULL; } node_t * pe_find_node(GListPtr nodes, const char *uname) { GListPtr gIter = nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - if(node && safe_str_eq(node->details->uname, uname)) { - return node; - } + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + if (node && safe_str_eq(node->details->uname, uname)) { + return node; + } } /* error */ return NULL; } diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index 045817ac09..03a9479433 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -1,2248 +1,2260 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 CRM_TRACE_INIT_DATA(pe_status); #define set_config_flag(data_set, option, flag) do { \ const char *tmp = pe_pref(data_set->config_hash, option); \ if(tmp) { \ if(crm_is_true(tmp)) { \ set_bit_inplace(data_set->flags, flag); \ } else { \ clear_bit_inplace(data_set->flags, flag); \ } \ } \ } while(0) -gboolean unpack_rsc_op( - resource_t *rsc, node_t *node, xmlNode *xml_op, GListPtr next, - enum action_fail_response *failed, pe_working_set_t *data_set); +gboolean unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, GListPtr next, + enum action_fail_response *failed, pe_working_set_t * data_set); -static void pe_fence_node(pe_working_set_t *data_set, node_t *node, const char *reason) +static void +pe_fence_node(pe_working_set_t * data_set, node_t * node, const char *reason) { CRM_CHECK(node, return); - if(node->details->unclean == FALSE) { - if(is_set(data_set->flags, pe_flag_stonith_enabled)) { - crm_warn("Node %s will be fenced %s", node->details->uname, reason); - } else { - crm_warn("Node %s is unclean %s", node->details->uname, reason); - } + if (node->details->unclean == FALSE) { + if (is_set(data_set->flags, pe_flag_stonith_enabled)) { + crm_warn("Node %s will be fenced %s", node->details->uname, reason); + } else { + crm_warn("Node %s is unclean %s", node->details->uname, reason); + } } node->details->unclean = TRUE; } - gboolean -unpack_config(xmlNode *config, pe_working_set_t *data_set) +unpack_config(xmlNode * config, pe_working_set_t * data_set) { const char *value = NULL; - GHashTable *config_hash = g_hash_table_new_full( - crm_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str); + GHashTable *config_hash = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); data_set->config_hash = config_hash; - unpack_instance_attributes( - data_set->input, config, XML_CIB_TAG_PROPSET, NULL, config_hash, - CIB_OPTIONS_FIRST, FALSE, data_set->now); + unpack_instance_attributes(data_set->input, config, XML_CIB_TAG_PROPSET, NULL, config_hash, + CIB_OPTIONS_FIRST, FALSE, data_set->now); verify_pe_options(data_set->config_hash); set_config_flag(data_set, "enable-startup-probes", pe_flag_startup_probes); crm_info("Startup probes: %s", - is_set(data_set->flags, pe_flag_startup_probes)?"enabled":"disabled (dangerous)"); - + is_set(data_set->flags, pe_flag_startup_probes) ? "enabled" : "disabled (dangerous)"); + value = pe_pref(data_set->config_hash, "stonith-timeout"); data_set->stonith_timeout = crm_get_msec(value); crm_debug("STONITH timeout: %d", data_set->stonith_timeout); - + set_config_flag(data_set, "stonith-enabled", pe_flag_stonith_enabled); crm_debug("STONITH of failed nodes is %s", - is_set(data_set->flags, pe_flag_stonith_enabled)?"enabled":"disabled"); + is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled"); data_set->stonith_action = pe_pref(data_set->config_hash, "stonith-action"); - crm_debug_2("STONITH will %s nodes", data_set->stonith_action); - + crm_debug_2("STONITH will %s nodes", data_set->stonith_action); + set_config_flag(data_set, "stop-all-resources", pe_flag_stop_everything); crm_debug("Stop all active resources: %s", - is_set(data_set->flags, pe_flag_stop_everything)?"true":"false"); - + is_set(data_set->flags, pe_flag_stop_everything) ? "true" : "false"); + set_config_flag(data_set, "symmetric-cluster", pe_flag_symmetric_cluster); - if(is_set(data_set->flags, pe_flag_symmetric_cluster)) { - crm_debug("Cluster is symmetric" - " - resources can run anywhere by default"); + if (is_set(data_set->flags, pe_flag_symmetric_cluster)) { + crm_debug("Cluster is symmetric" " - resources can run anywhere by default"); } - + value = pe_pref(data_set->config_hash, "default-resource-stickiness"); data_set->default_resource_stickiness = char2score(value); - crm_debug("Default stickiness: %d", - data_set->default_resource_stickiness); + crm_debug("Default stickiness: %d", data_set->default_resource_stickiness); value = pe_pref(data_set->config_hash, "no-quorum-policy"); - if(safe_str_eq(value, "ignore")) { - data_set->no_quorum_policy = no_quorum_ignore; - - } else if(safe_str_eq(value, "freeze")) { - data_set->no_quorum_policy = no_quorum_freeze; + if (safe_str_eq(value, "ignore")) { + data_set->no_quorum_policy = no_quorum_ignore; + + } else if (safe_str_eq(value, "freeze")) { + data_set->no_quorum_policy = no_quorum_freeze; + + } else if (safe_str_eq(value, "suicide")) { + gboolean do_panic = FALSE; - } else if(safe_str_eq(value, "suicide")) { - gboolean do_panic = FALSE; - crm_element_value_int(data_set->input, XML_ATTR_QUORUM_PANIC, &do_panic); + crm_element_value_int(data_set->input, XML_ATTR_QUORUM_PANIC, &do_panic); - if(is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE){ - crm_config_err("Setting no-quorum-policy=suicide makes no sense if stonith-enabled=false"); - } + if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { + crm_config_err + ("Setting no-quorum-policy=suicide makes no sense if stonith-enabled=false"); + } - if(do_panic && is_set(data_set->flags, pe_flag_stonith_enabled)) { - data_set->no_quorum_policy = no_quorum_suicide; + if (do_panic && is_set(data_set->flags, pe_flag_stonith_enabled)) { + data_set->no_quorum_policy = no_quorum_suicide; + + } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE && do_panic == FALSE) { + crm_notice("Resetting no-quorum-policy to 'stop': The cluster has never had quorum"); + data_set->no_quorum_policy = no_quorum_stop; + } - } else if(is_set(data_set->flags, pe_flag_have_quorum) == FALSE && do_panic == FALSE) { - crm_notice("Resetting no-quorum-policy to 'stop': The cluster has never had quorum"); - data_set->no_quorum_policy = no_quorum_stop; - } - } else { - data_set->no_quorum_policy = no_quorum_stop; + data_set->no_quorum_policy = no_quorum_stop; } - + switch (data_set->no_quorum_policy) { - case no_quorum_freeze: - crm_debug("On loss of CCM Quorum: Freeze resources"); - break; - case no_quorum_stop: - crm_debug("On loss of CCM Quorum: Stop ALL resources"); - break; - case no_quorum_suicide: - crm_notice("On loss of CCM Quorum: Fence all remaining nodes"); - break; - case no_quorum_ignore: - crm_notice("On loss of CCM Quorum: Ignore"); - break; + case no_quorum_freeze: + crm_debug("On loss of CCM Quorum: Freeze resources"); + break; + case no_quorum_stop: + crm_debug("On loss of CCM Quorum: Stop ALL resources"); + break; + case no_quorum_suicide: + crm_notice("On loss of CCM Quorum: Fence all remaining nodes"); + break; + case no_quorum_ignore: + crm_notice("On loss of CCM Quorum: Ignore"); + break; } set_config_flag(data_set, "stop-orphan-resources", pe_flag_stop_rsc_orphans); crm_debug_2("Orphan resources are %s", - is_set(data_set->flags, pe_flag_stop_rsc_orphans)?"stopped":"ignored"); - + is_set(data_set->flags, pe_flag_stop_rsc_orphans) ? "stopped" : "ignored"); + set_config_flag(data_set, "stop-orphan-actions", pe_flag_stop_action_orphans); crm_debug_2("Orphan resource actions are %s", - is_set(data_set->flags, pe_flag_stop_action_orphans)?"stopped":"ignored"); + is_set(data_set->flags, pe_flag_stop_action_orphans) ? "stopped" : "ignored"); set_config_flag(data_set, "remove-after-stop", pe_flag_remove_after_stop); crm_debug_2("Stopped resources are removed from the status section: %s", - is_set(data_set->flags, pe_flag_remove_after_stop)?"true":"false"); - + is_set(data_set->flags, pe_flag_remove_after_stop) ? "true" : "false"); + set_config_flag(data_set, "maintenance-mode", pe_flag_maintenance_mode); crm_debug_2("Maintenance mode: %s", - is_set(data_set->flags, pe_flag_maintenance_mode)?"true":"false"); + is_set(data_set->flags, pe_flag_maintenance_mode) ? "true" : "false"); - if(is_set(data_set->flags, pe_flag_maintenance_mode)) { - clear_bit(data_set->flags, pe_flag_is_managed_default); + if (is_set(data_set->flags, pe_flag_maintenance_mode)) { + clear_bit(data_set->flags, pe_flag_is_managed_default); } else { - set_config_flag(data_set, "is-managed-default", pe_flag_is_managed_default); + set_config_flag(data_set, "is-managed-default", pe_flag_is_managed_default); } crm_debug_2("By default resources are %smanaged", - is_set(data_set->flags, pe_flag_is_managed_default)?"":"not "); + is_set(data_set->flags, pe_flag_is_managed_default) ? "" : "not "); set_config_flag(data_set, "start-failure-is-fatal", pe_flag_start_failure_fatal); crm_debug_2("Start failures are %s", - is_set(data_set->flags, pe_flag_start_failure_fatal)?"always fatal":"handled by failcount"); + is_set(data_set->flags, + pe_flag_start_failure_fatal) ? "always fatal" : "handled by failcount"); - node_score_red = char2score(pe_pref(data_set->config_hash, "node-health-red")); - node_score_green = char2score(pe_pref(data_set->config_hash, "node-health-green")); + node_score_red = char2score(pe_pref(data_set->config_hash, "node-health-red")); + node_score_green = char2score(pe_pref(data_set->config_hash, "node-health-green")); node_score_yellow = char2score(pe_pref(data_set->config_hash, "node-health-yellow")); crm_info("Node scores: 'red' = %s, 'yellow' = %s, 'green' = %s", - pe_pref(data_set->config_hash, "node-health-red"), - pe_pref(data_set->config_hash, "node-health-yellow"), - pe_pref(data_set->config_hash, "node-health-green")); + pe_pref(data_set->config_hash, "node-health-red"), + pe_pref(data_set->config_hash, "node-health-yellow"), + pe_pref(data_set->config_hash, "node-health-green")); data_set->placement_strategy = pe_pref(data_set->config_hash, "placement-strategy"); - crm_debug_2("Placement strategy: %s", data_set->placement_strategy); - + crm_debug_2("Placement strategy: %s", data_set->placement_strategy); + return TRUE; } gboolean -unpack_nodes(xmlNode * xml_nodes, pe_working_set_t *data_set) +unpack_nodes(xmlNode * xml_nodes, pe_working_set_t * data_set) { xmlNode *xml_obj = NULL; - node_t *new_node = NULL; - const char *id = NULL; - const char *uname = NULL; - const char *type = NULL; - const char *score = NULL; + node_t *new_node = NULL; + const char *id = NULL; + const char *uname = NULL; + const char *type = NULL; + const char *score = NULL; gboolean unseen_are_unclean = TRUE; - const char *blind_faith = pe_pref( - data_set->config_hash, "startup-fencing"); - - if(crm_is_true(blind_faith) == FALSE) { - unseen_are_unclean = FALSE; - crm_warn("Blind faith: not fencing unseen nodes"); - } - - for(xml_obj = __xml_first_child(xml_nodes); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { - if(crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_NODE, TRUE)) { - new_node = NULL; - - id = crm_element_value(xml_obj, XML_ATTR_ID); - uname = crm_element_value(xml_obj, XML_ATTR_UNAME); - type = crm_element_value(xml_obj, XML_ATTR_TYPE); - score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); - crm_debug_3("Processing node %s/%s", uname, id); - - if(id == NULL) { - crm_config_err("Must specify id tag in "); - continue; - } - if(type == NULL) { - crm_config_err("Must specify type tag in "); - continue; - } - if(pe_find_node(data_set->nodes, uname) != NULL) { - crm_config_warn("Detected multiple node entries with uname=%s" - " - this is rarely intended", uname); - } - - crm_malloc0(new_node, sizeof(node_t)); - if(new_node == NULL) { - return FALSE; - } - - new_node->weight = char2score(score); - new_node->fixed = FALSE; - crm_malloc0(new_node->details, - sizeof(struct node_shared_s)); - - if(new_node->details == NULL) { - crm_free(new_node); - return FALSE; - } - - crm_debug_3("Creaing node for entry %s/%s", uname, id); - new_node->details->id = id; - new_node->details->uname = uname; - new_node->details->type = node_ping; - new_node->details->online = FALSE; - new_node->details->shutdown = FALSE; - new_node->details->running_rsc = NULL; - new_node->details->attrs = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - new_node->details->utilization = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - + const char *blind_faith = pe_pref(data_set->config_hash, "startup-fencing"); + + if (crm_is_true(blind_faith) == FALSE) { + unseen_are_unclean = FALSE; + crm_warn("Blind faith: not fencing unseen nodes"); + } + + for (xml_obj = __xml_first_child(xml_nodes); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { + if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_NODE, TRUE)) { + new_node = NULL; + + id = crm_element_value(xml_obj, XML_ATTR_ID); + uname = crm_element_value(xml_obj, XML_ATTR_UNAME); + type = crm_element_value(xml_obj, XML_ATTR_TYPE); + score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); + crm_debug_3("Processing node %s/%s", uname, id); + + if (id == NULL) { + crm_config_err("Must specify id tag in "); + continue; + } + if (type == NULL) { + crm_config_err("Must specify type tag in "); + continue; + } + if (pe_find_node(data_set->nodes, uname) != NULL) { + crm_config_warn("Detected multiple node entries with uname=%s" + " - this is rarely intended", uname); + } + + crm_malloc0(new_node, sizeof(node_t)); + if (new_node == NULL) { + return FALSE; + } + + new_node->weight = char2score(score); + new_node->fixed = FALSE; + crm_malloc0(new_node->details, sizeof(struct node_shared_s)); + + if (new_node->details == NULL) { + crm_free(new_node); + return FALSE; + } + + crm_debug_3("Creaing node for entry %s/%s", uname, id); + new_node->details->id = id; + new_node->details->uname = uname; + new_node->details->type = node_ping; + new_node->details->online = FALSE; + new_node->details->shutdown = FALSE; + new_node->details->running_rsc = NULL; + new_node->details->attrs = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, + g_hash_destroy_str); + new_node->details->utilization = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, + g_hash_destroy_str); + /* if(data_set->have_quorum == FALSE */ /* && data_set->no_quorum_policy == no_quorum_stop) { */ /* /\* start shutting resources down *\/ */ /* new_node->weight = -INFINITY; */ /* } */ - - if(is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE || unseen_are_unclean == FALSE) { - /* blind faith... */ - new_node->details->unclean = FALSE; - - } else { - /* all nodes are unclean until we've seen their - * status entry - */ - new_node->details->unclean = TRUE; - } - - if(type == NULL - || safe_str_eq(type, "member") - || safe_str_eq(type, NORMALNODE)) { - new_node->details->type = node_member; - } - - add_node_attrs(xml_obj, new_node, FALSE, data_set); - unpack_instance_attributes( - data_set->input, xml_obj, XML_TAG_UTILIZATION, NULL, - new_node->details->utilization, NULL, FALSE, data_set->now); - - data_set->nodes = g_list_append(data_set->nodes, new_node); - crm_debug_3("Done with node %s", - crm_element_value(xml_obj, XML_ATTR_UNAME)); - } - } - + + if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE + || unseen_are_unclean == FALSE) { + /* blind faith... */ + new_node->details->unclean = FALSE; + + } else { + /* all nodes are unclean until we've seen their + * status entry + */ + new_node->details->unclean = TRUE; + } + + if (type == NULL || safe_str_eq(type, "member") + || safe_str_eq(type, NORMALNODE)) { + new_node->details->type = node_member; + } + + add_node_attrs(xml_obj, new_node, FALSE, data_set); + unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_UTILIZATION, NULL, + new_node->details->utilization, NULL, FALSE, data_set->now); + + data_set->nodes = g_list_append(data_set->nodes, new_node); + crm_debug_3("Done with node %s", crm_element_value(xml_obj, XML_ATTR_UNAME)); + } + } + return TRUE; } -static void g_hash_destroy_node_list(gpointer data) +static void +g_hash_destroy_node_list(gpointer data) { GListPtr domain = data; + slist_basic_destroy(domain); } gboolean -unpack_domains(xmlNode *xml_domains, pe_working_set_t *data_set) +unpack_domains(xmlNode * xml_domains, pe_working_set_t * data_set) { const char *id = NULL; GListPtr domain = NULL; xmlNode *xml_node = NULL; xmlNode *xml_domain = NULL; crm_info("Unpacking domains"); - data_set->domains = g_hash_table_new_full( - crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_node_list); - - for(xml_domain = __xml_first_child(xml_domains); xml_domain != NULL; xml_domain = __xml_next(xml_domain)) { - if(crm_str_eq((const char *)xml_domain->name, XML_CIB_TAG_DOMAIN, TRUE)) { - domain = NULL; - id = crm_element_value(xml_domain, XML_ATTR_ID); - - for(xml_node = __xml_first_child(xml_domain); xml_node != NULL; xml_node = __xml_next(xml_node)) { - if(crm_str_eq((const char *)xml_node->name, XML_CIB_TAG_NODE, TRUE)) { - node_t *copy = NULL; - node_t *node = NULL; - const char *uname = crm_element_value(xml_node, "name"); - const char *score = crm_element_value(xml_node, XML_RULE_ATTR_SCORE); - - if(uname == NULL) { - crm_config_err("Invalid domain %s: Must specify id tag in ", id); - continue; - } - - node = pe_find_node(data_set->nodes, uname); - if(node == NULL) { - node = pe_find_node_id(data_set->nodes, uname); - } - if(node == NULL) { - crm_config_warn("Invalid domain %s: Node %s does not exist", id, uname); - continue; - } - - copy = node_copy(node); - copy->weight = char2score(score); - crm_debug("Adding %s to domain %s with score %s", node->details->uname, id, score); - - domain = g_list_prepend(domain, copy); - } - } - - if(domain) { - crm_debug("Created domain %s with %d members", id, g_list_length(domain)); - g_hash_table_replace(data_set->domains, crm_strdup(id), domain); - } - } - } - + data_set->domains = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, + g_hash_destroy_node_list); + + for (xml_domain = __xml_first_child(xml_domains); xml_domain != NULL; + xml_domain = __xml_next(xml_domain)) { + if (crm_str_eq((const char *)xml_domain->name, XML_CIB_TAG_DOMAIN, TRUE)) { + domain = NULL; + id = crm_element_value(xml_domain, XML_ATTR_ID); + + for (xml_node = __xml_first_child(xml_domain); xml_node != NULL; + xml_node = __xml_next(xml_node)) { + if (crm_str_eq((const char *)xml_node->name, XML_CIB_TAG_NODE, TRUE)) { + node_t *copy = NULL; + node_t *node = NULL; + const char *uname = crm_element_value(xml_node, "name"); + const char *score = crm_element_value(xml_node, XML_RULE_ATTR_SCORE); + + if (uname == NULL) { + crm_config_err("Invalid domain %s: Must specify id tag in ", id); + continue; + } + + node = pe_find_node(data_set->nodes, uname); + if (node == NULL) { + node = pe_find_node_id(data_set->nodes, uname); + } + if (node == NULL) { + crm_config_warn("Invalid domain %s: Node %s does not exist", id, uname); + continue; + } + + copy = node_copy(node); + copy->weight = char2score(score); + crm_debug("Adding %s to domain %s with score %s", node->details->uname, id, + score); + + domain = g_list_prepend(domain, copy); + } + } + + if (domain) { + crm_debug("Created domain %s with %d members", id, g_list_length(domain)); + g_hash_table_replace(data_set->domains, crm_strdup(id), domain); + } + } + } + return TRUE; } -gboolean -unpack_resources(xmlNode * xml_resources, pe_working_set_t *data_set) +gboolean +unpack_resources(xmlNode * xml_resources, pe_working_set_t * data_set) { xmlNode *xml_obj = NULL; - for(xml_obj = __xml_first_child(xml_resources); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { - resource_t *new_rsc = NULL; - - if(crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_RSC_TEMPLATE, TRUE)) { - continue; - } - - crm_debug_3("Beginning unpack... <%s id=%s... >", - crm_element_name(xml_obj), ID(xml_obj)); - if(common_unpack(xml_obj, &new_rsc, NULL, data_set)) { - data_set->resources = g_list_append( - data_set->resources, new_rsc); - - print_resource(LOG_DEBUG_3, "Added", new_rsc, FALSE); - - } else { - crm_config_err("Failed unpacking %s %s", - crm_element_name(xml_obj), - crm_element_value(xml_obj, XML_ATTR_ID)); - if(new_rsc != NULL && new_rsc->fns != NULL) { - new_rsc->fns->free(new_rsc); - } - } - } - - data_set->resources = g_list_sort( - data_set->resources, sort_rsc_priority); - - if(is_set(data_set->flags, pe_flag_stonith_enabled) && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) { - crm_config_err("Resource start-up disabled since no STONITH resources have been defined"); - crm_config_err("Either configure some or disable STONITH with the stonith-enabled option"); - crm_config_err("NOTE: Clusters with shared data need STONITH to ensure data integrity"); - } - + + for (xml_obj = __xml_first_child(xml_resources); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { + resource_t *new_rsc = NULL; + + if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_RSC_TEMPLATE, TRUE)) { + continue; + } + + crm_debug_3("Beginning unpack... <%s id=%s... >", crm_element_name(xml_obj), ID(xml_obj)); + if (common_unpack(xml_obj, &new_rsc, NULL, data_set)) { + data_set->resources = g_list_append(data_set->resources, new_rsc); + + print_resource(LOG_DEBUG_3, "Added", new_rsc, FALSE); + + } else { + crm_config_err("Failed unpacking %s %s", + crm_element_name(xml_obj), crm_element_value(xml_obj, XML_ATTR_ID)); + if (new_rsc != NULL && new_rsc->fns != NULL) { + new_rsc->fns->free(new_rsc); + } + } + } + + data_set->resources = g_list_sort(data_set->resources, sort_rsc_priority); + + if (is_set(data_set->flags, pe_flag_stonith_enabled) + && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) { + crm_config_err("Resource start-up disabled since no STONITH resources have been defined"); + crm_config_err("Either configure some or disable STONITH with the stonith-enabled option"); + crm_config_err("NOTE: Clusters with shared data need STONITH to ensure data integrity"); + } + return TRUE; } static void get_ticket_state(gpointer key, gpointer value, gpointer user_data) { const char *attr_key = key; const char *granted_prefix = "granted-ticket-"; const char *last_granted_prefix = "last-granted-ticket-"; static int granted_prefix_strlen = 0; static int last_granted_prefix_strlen = 0; - - const char *ticket_id = NULL; + + const char *ticket_id = NULL; const char *is_granted = NULL; const char *last_granted = NULL; ticket_t *ticket = NULL; GHashTable *tickets = user_data; - if(granted_prefix_strlen == 0) { - granted_prefix_strlen = strlen(granted_prefix); + if (granted_prefix_strlen == 0) { + granted_prefix_strlen = strlen(granted_prefix); } - if(last_granted_prefix_strlen == 0) { - last_granted_prefix_strlen = strlen(last_granted_prefix); + if (last_granted_prefix_strlen == 0) { + last_granted_prefix_strlen = strlen(last_granted_prefix); } if (strstr(attr_key, granted_prefix) == attr_key) { - ticket_id = attr_key + granted_prefix_strlen; - if(strlen(ticket_id)) { - is_granted = value; - } + ticket_id = attr_key + granted_prefix_strlen; + if (strlen(ticket_id)) { + is_granted = value; + } } else if (strstr(attr_key, last_granted_prefix) == attr_key) { - ticket_id = attr_key + last_granted_prefix_strlen; - if(strlen(ticket_id)) { - last_granted = value; - } + ticket_id = attr_key + last_granted_prefix_strlen; + if (strlen(ticket_id)) { + last_granted = value; + } } - if(ticket_id == NULL || strlen(ticket_id) == 0) { - return; + if (ticket_id == NULL || strlen(ticket_id) == 0) { + return; } ticket = g_hash_table_lookup(tickets, ticket_id); - if(ticket == NULL) { - crm_malloc0(ticket, sizeof(ticket_t)); - if(ticket == NULL) { - crm_config_err("Cannot allocate ticket '%s'", ticket_id); - return; - } + if (ticket == NULL) { + crm_malloc0(ticket, sizeof(ticket_t)); + if (ticket == NULL) { + crm_config_err("Cannot allocate ticket '%s'", ticket_id); + return; + } - ticket->id = crm_strdup(ticket_id); - ticket->granted = FALSE; - ticket->last_granted = -1; + ticket->id = crm_strdup(ticket_id); + ticket->granted = FALSE; + ticket->last_granted = -1; - g_hash_table_insert(tickets, crm_strdup(ticket->id), ticket); + g_hash_table_insert(tickets, crm_strdup(ticket->id), ticket); } - if(is_granted) { - if(crm_is_true(is_granted)) { - ticket->granted = TRUE; - crm_info("We have ticket '%s'", ticket->id); - } else { - ticket->granted = FALSE; - crm_info("We do not have ticket '%s'", ticket->id); - } + if (is_granted) { + if (crm_is_true(is_granted)) { + ticket->granted = TRUE; + crm_info("We have ticket '%s'", ticket->id); + } else { + ticket->granted = FALSE; + crm_info("We do not have ticket '%s'", ticket->id); + } - } else if(last_granted) { - ticket->last_granted = crm_parse_int(last_granted, 0); + } else if (last_granted) { + ticket->last_granted = crm_parse_int(last_granted, 0); } } -static void destroy_ticket(gpointer data) +static void +destroy_ticket(gpointer data) { ticket_t *ticket = data; crm_free(ticket->id); crm_free(ticket); } + /* remove nodes that are down, stopping */ /* create +ve rsc_to_node constraints between resources and the nodes they are running on */ /* anything else? */ gboolean -unpack_status(xmlNode * status, pe_working_set_t *data_set) +unpack_status(xmlNode * status, pe_working_set_t * data_set) { - const char *id = NULL; + const char *id = NULL; const char *uname = NULL; - xmlNode * lrm_rsc = NULL; - xmlNode * attrs = NULL; - xmlNode * state = NULL; - xmlNode * node_state = NULL; - node_t *this_node = NULL; - + xmlNode *lrm_rsc = NULL; + xmlNode *attrs = NULL; + xmlNode *state = NULL; + xmlNode *node_state = NULL; + node_t *this_node = NULL; + crm_debug_3("Beginning unpack"); - data_set->tickets = g_hash_table_new_full( - crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket); - - for(state = __xml_first_child(status); state != NULL; state = __xml_next(state)) { - if(crm_str_eq((const char *)state->name, XML_CIB_TAG_TICKETS, TRUE)) { - xmlNode *tickets = state; - GHashTable *attrs_hash = g_hash_table_new_full( - crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); - - unpack_instance_attributes( - data_set->input, tickets, XML_TAG_ATTR_SETS, NULL, - attrs_hash, NULL, TRUE, data_set->now); - - g_hash_table_foreach(attrs_hash, get_ticket_state, data_set->tickets); - - if(attrs_hash) { - g_hash_table_destroy(attrs_hash); - } - } - - if(crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE)) { - node_state = state; - - id = crm_element_value(node_state, XML_ATTR_ID); - uname = crm_element_value(node_state, XML_ATTR_UNAME); - attrs = find_xml_node(node_state, XML_TAG_TRANSIENT_NODEATTRS, FALSE); - - crm_debug_3("Processing node id=%s, uname=%s", id, uname); - this_node = pe_find_node_id(data_set->nodes, id); - - if(uname == NULL) { - /* error */ - continue; - - } else if(this_node == NULL) { - crm_config_warn("Node %s in status section no longer exists", - uname); - continue; - } - - /* Mark the node as provisionally clean - * - at least we have seen it in the current cluster's lifetime - */ - this_node->details->unclean = FALSE; - add_node_attrs(attrs, this_node, TRUE, data_set); - - if(crm_is_true(g_hash_table_lookup(this_node->details->attrs, "standby"))) { - crm_info("Node %s is in standby-mode", - this_node->details->uname); - this_node->details->standby = TRUE; - } - - crm_debug_3("determining node state"); - determine_online_status(node_state, this_node, data_set); - - if(this_node->details->online - && data_set->no_quorum_policy == no_quorum_suicide) { - /* Everything else should flow from this automatically - * At least until the PE becomes able to migrate off healthy resources - */ - pe_fence_node(data_set, this_node, "because the cluster does not have quorum"); - } - } + data_set->tickets = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket); + + for (state = __xml_first_child(status); state != NULL; state = __xml_next(state)) { + if (crm_str_eq((const char *)state->name, XML_CIB_TAG_TICKETS, TRUE)) { + xmlNode *tickets = state; + GHashTable *attrs_hash = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, + g_hash_destroy_str); + + unpack_instance_attributes(data_set->input, tickets, XML_TAG_ATTR_SETS, NULL, + attrs_hash, NULL, TRUE, data_set->now); + + g_hash_table_foreach(attrs_hash, get_ticket_state, data_set->tickets); + + if (attrs_hash) { + g_hash_table_destroy(attrs_hash); + } + } + + if (crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE)) { + node_state = state; + + id = crm_element_value(node_state, XML_ATTR_ID); + uname = crm_element_value(node_state, XML_ATTR_UNAME); + attrs = find_xml_node(node_state, XML_TAG_TRANSIENT_NODEATTRS, FALSE); + + crm_debug_3("Processing node id=%s, uname=%s", id, uname); + this_node = pe_find_node_id(data_set->nodes, id); + + if (uname == NULL) { + /* error */ + continue; + + } else if (this_node == NULL) { + crm_config_warn("Node %s in status section no longer exists", uname); + continue; + } + + /* Mark the node as provisionally clean + * - at least we have seen it in the current cluster's lifetime + */ + this_node->details->unclean = FALSE; + add_node_attrs(attrs, this_node, TRUE, data_set); + + if (crm_is_true(g_hash_table_lookup(this_node->details->attrs, "standby"))) { + crm_info("Node %s is in standby-mode", this_node->details->uname); + this_node->details->standby = TRUE; + } + + crm_debug_3("determining node state"); + determine_online_status(node_state, this_node, data_set); + + if (this_node->details->online && data_set->no_quorum_policy == no_quorum_suicide) { + /* Everything else should flow from this automatically + * At least until the PE becomes able to migrate off healthy resources + */ + pe_fence_node(data_set, this_node, "because the cluster does not have quorum"); + } + } } /* Now that we know all node states, we can safely handle migration ops * But, for now, only process healthy nodes * - this is necessary for the logic in bug lf#2508 to function correctly - */ - for(node_state = __xml_first_child(status); node_state != NULL; node_state = __xml_next(node_state)) { - if(crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE) == FALSE) { - continue; - } - - id = crm_element_value(node_state, XML_ATTR_ID); - this_node = pe_find_node_id(data_set->nodes, id); - - if(this_node == NULL) { - crm_info("Node %s is unknown", id); - continue; - - } else if(this_node->details->online) { - crm_trace("Processing lrm resource entries on healthy node: %s", this_node->details->uname); - lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); - lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE); - unpack_lrm_resources(this_node, lrm_rsc, data_set); - } + */ + for (node_state = __xml_first_child(status); node_state != NULL; + node_state = __xml_next(node_state)) { + if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE) == FALSE) { + continue; + } + + id = crm_element_value(node_state, XML_ATTR_ID); + this_node = pe_find_node_id(data_set->nodes, id); + + if (this_node == NULL) { + crm_info("Node %s is unknown", id); + continue; + + } else if (this_node->details->online) { + crm_trace("Processing lrm resource entries on healthy node: %s", + this_node->details->uname); + lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); + lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE); + unpack_lrm_resources(this_node, lrm_rsc, data_set); + } } /* Now handle failed nodes - but only if stonith is enabled * * By definition, offline nodes run no resources so there is nothing to do. * Only when stonith is enabled do we need to know what is on the node to * ensure rsc start events happen after the stonith */ - for(node_state = __xml_first_child(status); - node_state != NULL && is_set(data_set->flags, pe_flag_stonith_enabled); - node_state = __xml_next(node_state)) { - - if(crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE) == FALSE) { - continue; - } - - id = crm_element_value(node_state, XML_ATTR_ID); - this_node = pe_find_node_id(data_set->nodes, id); - - if(this_node == NULL || this_node->details->online) { - continue; - - } else { - crm_trace("Processing lrm resource entries on unhealthy node: %s", this_node->details->uname); - lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); - lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE); - unpack_lrm_resources(this_node, lrm_rsc, data_set); - } - } - + for (node_state = __xml_first_child(status); + node_state != NULL && is_set(data_set->flags, pe_flag_stonith_enabled); + node_state = __xml_next(node_state)) { + + if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE) == FALSE) { + continue; + } + + id = crm_element_value(node_state, XML_ATTR_ID); + this_node = pe_find_node_id(data_set->nodes, id); + + if (this_node == NULL || this_node->details->online) { + continue; + + } else { + crm_trace("Processing lrm resource entries on unhealthy node: %s", + this_node->details->uname); + lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); + lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE); + unpack_lrm_resources(this_node, lrm_rsc, data_set); + } + } + return TRUE; } static gboolean -determine_online_status_no_fencing(pe_working_set_t *data_set, xmlNode * node_state, node_t *this_node) +determine_online_status_no_fencing(pe_working_set_t * data_set, xmlNode * node_state, + node_t * this_node) { gboolean online = FALSE; const char *join_state = crm_element_value(node_state, XML_CIB_ATTR_JOINSTATE); - const char *crm_state = crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE); - const char *ccm_state = crm_element_value(node_state, XML_CIB_ATTR_INCCM); - const char *ha_state = crm_element_value(node_state, XML_CIB_ATTR_HASTATE); - const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); - - if(ha_state == NULL) { - ha_state = DEADSTATUS; - } - - if(!crm_is_true(ccm_state) || safe_str_eq(ha_state, DEADSTATUS)){ - crm_debug_2("Node is down: ha_state=%s, ccm_state=%s", - crm_str(ha_state), crm_str(ccm_state)); - - } else if(safe_str_eq(crm_state, ONLINESTATUS)) { - if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) { - online = TRUE; - } else { - crm_debug("Node is not ready to run resources: %s", join_state); - } - - } else if(this_node->details->expected_up == FALSE) { - crm_debug_2("CRMd is down: ha_state=%s, ccm_state=%s", - crm_str(ha_state), crm_str(ccm_state)); - crm_debug_2("\tcrm_state=%s, join_state=%s, expected=%s", - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); - + const char *crm_state = crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE); + const char *ccm_state = crm_element_value(node_state, XML_CIB_ATTR_INCCM); + const char *ha_state = crm_element_value(node_state, XML_CIB_ATTR_HASTATE); + const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); + + if (ha_state == NULL) { + ha_state = DEADSTATUS; + } + + if (!crm_is_true(ccm_state) || safe_str_eq(ha_state, DEADSTATUS)) { + crm_debug_2("Node is down: ha_state=%s, ccm_state=%s", + crm_str(ha_state), crm_str(ccm_state)); + + } else if (safe_str_eq(crm_state, ONLINESTATUS)) { + if (safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) { + online = TRUE; + } else { + crm_debug("Node is not ready to run resources: %s", join_state); + } + + } else if (this_node->details->expected_up == FALSE) { + crm_debug_2("CRMd is down: ha_state=%s, ccm_state=%s", + crm_str(ha_state), crm_str(ccm_state)); + crm_debug_2("\tcrm_state=%s, join_state=%s, expected=%s", + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); + } else { - /* mark it unclean */ - pe_fence_node(data_set, this_node, "because it is partially and/or un-expectedly down"); - crm_info("\tha_state=%s, ccm_state=%s," - " crm_state=%s, join_state=%s, expected=%s", - crm_str(ha_state), crm_str(ccm_state), - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); + /* mark it unclean */ + pe_fence_node(data_set, this_node, "because it is partially and/or un-expectedly down"); + crm_info("\tha_state=%s, ccm_state=%s," + " crm_state=%s, join_state=%s, expected=%s", + crm_str(ha_state), crm_str(ccm_state), + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } return online; } static gboolean -determine_online_status_fencing(pe_working_set_t *data_set, xmlNode * node_state, node_t *this_node) +determine_online_status_fencing(pe_working_set_t * data_set, xmlNode * node_state, + node_t * this_node) { gboolean online = FALSE; gboolean do_terminate = FALSE; const char *join_state = crm_element_value(node_state, XML_CIB_ATTR_JOINSTATE); - const char *crm_state = crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE); - const char *ccm_state = crm_element_value(node_state, XML_CIB_ATTR_INCCM); - const char *ha_state = crm_element_value(node_state, XML_CIB_ATTR_HASTATE); - const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); + const char *crm_state = crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE); + const char *ccm_state = crm_element_value(node_state, XML_CIB_ATTR_INCCM); + const char *ha_state = crm_element_value(node_state, XML_CIB_ATTR_HASTATE); + const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); const char *terminate = g_hash_table_lookup(this_node->details->attrs, "terminate"); - if(ha_state == NULL) { - ha_state = DEADSTATUS; - } - - if(crm_is_true(terminate)) { - do_terminate = TRUE; - - } else if(terminate != NULL && strlen(terminate) > 0) { - /* could be a time() value */ - char t = terminate[0]; - if(t != '0' && isdigit(t)) { - do_terminate = TRUE; - } - } - - if(crm_is_true(ccm_state) - && safe_str_eq(ha_state, ACTIVESTATUS) - && safe_str_eq(crm_state, ONLINESTATUS)) { - - if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) { - online = TRUE; - if(do_terminate) { - pe_fence_node(data_set, this_node, "because termination was requested"); - } - - } else if(join_state == exp_state /* == NULL */) { - crm_info("Node %s is coming up", this_node->details->uname); - crm_debug("\tha_state=%s, ccm_state=%s," - " crm_state=%s, join_state=%s, expected=%s", - crm_str(ha_state), crm_str(ccm_state), - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); - - } else if(safe_str_eq(join_state, CRMD_JOINSTATE_PENDING)) { - crm_info("Node %s is not ready to run resources", - this_node->details->uname); - this_node->details->standby = TRUE; - this_node->details->pending = TRUE; - online = TRUE; - - } else if(safe_str_eq(join_state, CRMD_JOINSTATE_NACK)) { - crm_warn("Node %s is not part of the cluster", - this_node->details->uname); - this_node->details->standby = TRUE; - this_node->details->pending = TRUE; - online = TRUE; - - } else if(safe_str_eq(join_state, exp_state)) { - crm_info("Node %s is still coming up: %s", - this_node->details->uname, join_state); - crm_info("\tha_state=%s, ccm_state=%s, crm_state=%s", - crm_str(ha_state), crm_str(ccm_state), crm_str(crm_state)); - this_node->details->standby = TRUE; - this_node->details->pending = TRUE; - online = TRUE; - - } else { - crm_warn("Node %s (%s) is un-expectedly down", - this_node->details->uname, this_node->details->id); - crm_info("\tha_state=%s, ccm_state=%s," - " crm_state=%s, join_state=%s, expected=%s", - crm_str(ha_state), crm_str(ccm_state), - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); - pe_fence_node(data_set, this_node, "because it is un-expectedly down"); - } - - } else if(crm_is_true(ccm_state) == FALSE - && safe_str_eq(ha_state, DEADSTATUS) - && safe_str_eq(crm_state, OFFLINESTATUS) - && this_node->details->expected_up == FALSE) { - crm_debug("Node %s is down: join_state=%s, expected=%s", - this_node->details->uname, - crm_str(join_state), crm_str(exp_state)); + if (ha_state == NULL) { + ha_state = DEADSTATUS; + } + + if (crm_is_true(terminate)) { + do_terminate = TRUE; + + } else if (terminate != NULL && strlen(terminate) > 0) { + /* could be a time() value */ + char t = terminate[0]; + + if (t != '0' && isdigit(t)) { + do_terminate = TRUE; + } + } + + if (crm_is_true(ccm_state) + && safe_str_eq(ha_state, ACTIVESTATUS) + && safe_str_eq(crm_state, ONLINESTATUS)) { + + if (safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) { + online = TRUE; + if (do_terminate) { + pe_fence_node(data_set, this_node, "because termination was requested"); + } + + } else if (join_state == exp_state /* == NULL */ ) { + crm_info("Node %s is coming up", this_node->details->uname); + crm_debug("\tha_state=%s, ccm_state=%s," + " crm_state=%s, join_state=%s, expected=%s", + crm_str(ha_state), crm_str(ccm_state), + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); + + } else if (safe_str_eq(join_state, CRMD_JOINSTATE_PENDING)) { + crm_info("Node %s is not ready to run resources", this_node->details->uname); + this_node->details->standby = TRUE; + this_node->details->pending = TRUE; + online = TRUE; + + } else if (safe_str_eq(join_state, CRMD_JOINSTATE_NACK)) { + crm_warn("Node %s is not part of the cluster", this_node->details->uname); + this_node->details->standby = TRUE; + this_node->details->pending = TRUE; + online = TRUE; + + } else if (safe_str_eq(join_state, exp_state)) { + crm_info("Node %s is still coming up: %s", this_node->details->uname, join_state); + crm_info("\tha_state=%s, ccm_state=%s, crm_state=%s", + crm_str(ha_state), crm_str(ccm_state), crm_str(crm_state)); + this_node->details->standby = TRUE; + this_node->details->pending = TRUE; + online = TRUE; + + } else { + crm_warn("Node %s (%s) is un-expectedly down", + this_node->details->uname, this_node->details->id); + crm_info("\tha_state=%s, ccm_state=%s," + " crm_state=%s, join_state=%s, expected=%s", + crm_str(ha_state), crm_str(ccm_state), + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); + pe_fence_node(data_set, this_node, "because it is un-expectedly down"); + } + + } else if (crm_is_true(ccm_state) == FALSE && safe_str_eq(ha_state, DEADSTATUS) + && safe_str_eq(crm_state, OFFLINESTATUS) + && this_node->details->expected_up == FALSE) { + crm_debug("Node %s is down: join_state=%s, expected=%s", + this_node->details->uname, crm_str(join_state), crm_str(exp_state)); #if 0 - /* While a nice optimization, it causes the cluster to block until the node - * comes back online. Which is a serious problem if the cluster software - * is not configured to start at boot or stonith is configured to merely - * stop the node instead of restart it. - * Easily triggered by setting terminate=true for the DC - */ - } else if(do_terminate) { - crm_info("Node %s is %s after forced termination", - this_node->details->uname, crm_is_true(ccm_state)?"coming up":"going down"); - crm_debug("\tha_state=%s, ccm_state=%s," - " crm_state=%s, join_state=%s, expected=%s", - crm_str(ha_state), crm_str(ccm_state), - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); - - if(crm_is_true(ccm_state) == FALSE) { - this_node->details->standby = TRUE; - this_node->details->pending = TRUE; - online = TRUE; - } + /* While a nice optimization, it causes the cluster to block until the node + * comes back online. Which is a serious problem if the cluster software + * is not configured to start at boot or stonith is configured to merely + * stop the node instead of restart it. + * Easily triggered by setting terminate=true for the DC + */ + } else if (do_terminate) { + crm_info("Node %s is %s after forced termination", + this_node->details->uname, crm_is_true(ccm_state) ? "coming up" : "going down"); + crm_debug("\tha_state=%s, ccm_state=%s," + " crm_state=%s, join_state=%s, expected=%s", + crm_str(ha_state), crm_str(ccm_state), + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); + + if (crm_is_true(ccm_state) == FALSE) { + this_node->details->standby = TRUE; + this_node->details->pending = TRUE; + online = TRUE; + } #endif - - } else if(this_node->details->expected_up) { - /* mark it unclean */ - pe_fence_node(data_set, this_node, "because it is un-expectedly down"); - crm_info("\tha_state=%s, ccm_state=%s," - " crm_state=%s, join_state=%s, expected=%s", - crm_str(ha_state), crm_str(ccm_state), - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); + + } else if (this_node->details->expected_up) { + /* mark it unclean */ + pe_fence_node(data_set, this_node, "because it is un-expectedly down"); + crm_info("\tha_state=%s, ccm_state=%s," + " crm_state=%s, join_state=%s, expected=%s", + crm_str(ha_state), crm_str(ccm_state), + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } else { - crm_info("Node %s is down", this_node->details->uname); - crm_debug("\tha_state=%s, ccm_state=%s," - " crm_state=%s, join_state=%s, expected=%s", - crm_str(ha_state), crm_str(ccm_state), - crm_str(crm_state), crm_str(join_state), - crm_str(exp_state)); + crm_info("Node %s is down", this_node->details->uname); + crm_debug("\tha_state=%s, ccm_state=%s," + " crm_state=%s, join_state=%s, expected=%s", + crm_str(ha_state), crm_str(ccm_state), + crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } return online; } gboolean -determine_online_status( - xmlNode * node_state, node_t *this_node, pe_working_set_t *data_set) +determine_online_status(xmlNode * node_state, node_t * this_node, pe_working_set_t * data_set) { gboolean online = FALSE; const char *shutdown = NULL; const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); - - if(this_node == NULL) { - crm_config_err("No node to check"); - return online; + + if (this_node == NULL) { + crm_config_err("No node to check"); + return online; } this_node->details->shutdown = FALSE; this_node->details->expected_up = FALSE; shutdown = g_hash_table_lookup(this_node->details->attrs, XML_CIB_ATTR_SHUTDOWN); - if(shutdown != NULL && safe_str_neq("0", shutdown)) { - this_node->details->shutdown = TRUE; + if (shutdown != NULL && safe_str_neq("0", shutdown)) { + this_node->details->shutdown = TRUE; - } else if(safe_str_eq(exp_state, CRMD_JOINSTATE_MEMBER)) { - this_node->details->expected_up = TRUE; + } else if (safe_str_eq(exp_state, CRMD_JOINSTATE_MEMBER)) { + this_node->details->expected_up = TRUE; } - - if(is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { - online = determine_online_status_no_fencing( - data_set, node_state, this_node); - + + if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { + online = determine_online_status_no_fencing(data_set, node_state, this_node); + } else { - online = determine_online_status_fencing( - data_set, node_state, this_node); + online = determine_online_status_fencing(data_set, node_state, this_node); } - - if(online) { - this_node->details->online = TRUE; + + if (online) { + this_node->details->online = TRUE; } else { - /* remove node from contention */ - this_node->fixed = TRUE; - this_node->weight = -INFINITY; - } - - if(online && this_node->details->shutdown) { - /* dont run resources here */ - this_node->fixed = TRUE; - this_node->weight = -INFINITY; - } - - if(this_node->details->unclean) { - pe_proc_warn("Node %s is unclean", this_node->details->uname); - - } else if(this_node->details->online) { - crm_info("Node %s is %s", this_node->details->uname, - this_node->details->shutdown?"shutting down": - this_node->details->pending?"pending": - this_node->details->standby?"standby":"online"); - + /* remove node from contention */ + this_node->fixed = TRUE; + this_node->weight = -INFINITY; + } + + if (online && this_node->details->shutdown) { + /* dont run resources here */ + this_node->fixed = TRUE; + this_node->weight = -INFINITY; + } + + if (this_node->details->unclean) { + pe_proc_warn("Node %s is unclean", this_node->details->uname); + + } else if (this_node->details->online) { + crm_info("Node %s is %s", this_node->details->uname, + this_node->details->shutdown ? "shutting down" : + this_node->details->pending ? "pending" : + this_node->details->standby ? "standby" : "online"); + } else { - crm_debug_2("Node %s is offline", this_node->details->uname); + crm_debug_2("Node %s is offline", this_node->details->uname); } return online; } #define set_char(x) last_rsc_id[lpc] = x; complete = TRUE; char * clone_zero(const char *last_rsc_id) { int lpc = 0; char *zero = NULL; CRM_CHECK(last_rsc_id != NULL, return NULL); - if(last_rsc_id != NULL) { - lpc = strlen(last_rsc_id); - } - - while(--lpc > 0) { - switch(last_rsc_id[lpc]) { - case 0: - return NULL; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - case ':': - crm_malloc0(zero, lpc + 3); - memcpy(zero, last_rsc_id, lpc); - zero[lpc] = ':'; - zero[lpc+1] = '0'; - zero[lpc+2] = 0; - return zero; - } + if (last_rsc_id != NULL) { + lpc = strlen(last_rsc_id); + } + + while (--lpc > 0) { + switch (last_rsc_id[lpc]) { + case 0: + return NULL; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + case ':': + crm_malloc0(zero, lpc + 3); + memcpy(zero, last_rsc_id, lpc); + zero[lpc] = ':'; + zero[lpc + 1] = '0'; + zero[lpc + 2] = 0; + return zero; + } } return NULL; } char * increment_clone(char *last_rsc_id) { int lpc = 0; int len = 0; char *tmp = NULL; gboolean complete = FALSE; CRM_CHECK(last_rsc_id != NULL, return NULL); - if(last_rsc_id != NULL) { - len = strlen(last_rsc_id); - } - - lpc = len-1; - while(complete == FALSE && lpc > 0) { - switch (last_rsc_id[lpc]) { - case 0: - lpc--; - break; - case '0': - set_char('1'); - break; - case '1': - set_char('2'); - break; - case '2': - set_char('3'); - break; - case '3': - set_char('4'); - break; - case '4': - set_char('5'); - break; - case '5': - set_char('6'); - break; - case '6': - set_char('7'); - break; - case '7': - set_char('8'); - break; - case '8': - set_char('9'); - break; - case '9': - last_rsc_id[lpc] = '0'; - lpc--; - break; - case ':': - tmp = last_rsc_id; - crm_malloc0(last_rsc_id, len + 2); - memcpy(last_rsc_id, tmp, len); - last_rsc_id[++lpc] = '1'; - last_rsc_id[len] = '0'; - last_rsc_id[len+1] = 0; - complete = TRUE; - crm_free(tmp); - break; - default: - crm_err("Unexpected char: %c (%d)", - last_rsc_id[lpc], lpc); - break; - } + if (last_rsc_id != NULL) { + len = strlen(last_rsc_id); + } + + lpc = len - 1; + while (complete == FALSE && lpc > 0) { + switch (last_rsc_id[lpc]) { + case 0: + lpc--; + break; + case '0': + set_char('1'); + break; + case '1': + set_char('2'); + break; + case '2': + set_char('3'); + break; + case '3': + set_char('4'); + break; + case '4': + set_char('5'); + break; + case '5': + set_char('6'); + break; + case '6': + set_char('7'); + break; + case '7': + set_char('8'); + break; + case '8': + set_char('9'); + break; + case '9': + last_rsc_id[lpc] = '0'; + lpc--; + break; + case ':': + tmp = last_rsc_id; + crm_malloc0(last_rsc_id, len + 2); + memcpy(last_rsc_id, tmp, len); + last_rsc_id[++lpc] = '1'; + last_rsc_id[len] = '0'; + last_rsc_id[len + 1] = 0; + complete = TRUE; + crm_free(tmp); + break; + default: + crm_err("Unexpected char: %c (%d)", last_rsc_id[lpc], lpc); + break; + } } return last_rsc_id; } - static int get_clone(char *last_rsc_id) { int clone = 0; int lpc = 0; int len = 0; CRM_CHECK(last_rsc_id != NULL, return -1); - if(last_rsc_id != NULL) { - len = strlen(last_rsc_id); - } - - lpc = len-1; - while(lpc > 0) { - switch (last_rsc_id[lpc]) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - clone += (int)(last_rsc_id[lpc] - '0') * (len - lpc); - lpc--; - break; - case ':': - return clone; - break; - default: - crm_err("Unexpected char: %d (%c)", - lpc, last_rsc_id[lpc]); - return clone; - break; - } + if (last_rsc_id != NULL) { + len = strlen(last_rsc_id); + } + + lpc = len - 1; + while (lpc > 0) { + switch (last_rsc_id[lpc]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + clone += (int)(last_rsc_id[lpc] - '0') * (len - lpc); + lpc--; + break; + case ':': + return clone; + break; + default: + crm_err("Unexpected char: %d (%c)", lpc, last_rsc_id[lpc]); + return clone; + break; + } } return -1; } static resource_t * -create_fake_resource(const char *rsc_id, xmlNode *rsc_entry, pe_working_set_t *data_set) +create_fake_resource(const char *rsc_id, xmlNode * rsc_entry, pe_working_set_t * data_set) { resource_t *rsc = NULL; - xmlNode *xml_rsc = create_xml_node(NULL, XML_CIB_TAG_RESOURCE); + xmlNode *xml_rsc = create_xml_node(NULL, XML_CIB_TAG_RESOURCE); + copy_in_properties(xml_rsc, rsc_entry); crm_xml_add(xml_rsc, XML_ATTR_ID, rsc_id); crm_log_xml_debug(xml_rsc, "Orphan resource"); - - if(!common_unpack(xml_rsc, &rsc, NULL, data_set)) { - return NULL; + + if (!common_unpack(xml_rsc, &rsc, NULL, data_set)) { + return NULL; } set_bit(rsc->flags, pe_rsc_orphan); data_set->resources = g_list_append(data_set->resources, rsc); return rsc; } -extern resource_t *create_child_clone(resource_t *rsc, int sub_id, pe_working_set_t *data_set); +extern resource_t *create_child_clone(resource_t * rsc, int sub_id, pe_working_set_t * data_set); -static resource_t *find_clone(pe_working_set_t *data_set, node_t *node, resource_t *parent, const char *rsc_id) +static resource_t * +find_clone(pe_working_set_t * data_set, node_t * node, resource_t * parent, const char *rsc_id) { int len = 0; resource_t *rsc = NULL; char *base = clone_zero(rsc_id); char *alt_rsc_id = crm_strdup(rsc_id); CRM_ASSERT(parent != NULL); CRM_ASSERT(parent->variant == pe_clone || parent->variant == pe_master); - if(base) { - len = strlen(base); + if (base) { + len = strlen(base); } - if(len > 0) { - base[len-1] = 0; + if (len > 0) { + base[len - 1] = 0; } - + crm_debug_3("Looking for %s on %s in %s %d", - rsc_id, node->details->uname, parent->id, is_set(parent->flags, pe_rsc_unique)); - - if(is_set(parent->flags, pe_rsc_unique)) { - crm_debug_3("Looking for %s", rsc_id); - rsc = parent->fns->find_rsc(parent, rsc_id, NULL, pe_find_current); + rsc_id, node->details->uname, parent->id, is_set(parent->flags, pe_rsc_unique)); + + if (is_set(parent->flags, pe_rsc_unique)) { + crm_debug_3("Looking for %s", rsc_id); + rsc = parent->fns->find_rsc(parent, rsc_id, NULL, pe_find_current); } else { - crm_trace("Looking for %s on %s", base, node->details->uname); - rsc = parent->fns->find_rsc(parent, base, node, pe_find_partial|pe_find_current); - if(rsc != NULL && rsc->running_on) { - GListPtr gIter = parent->children; - rsc = NULL; - crm_debug_3("Looking for an existing orphan for %s: %s on %s", parent->id, rsc_id, node->details->uname); - - /* There is already an instance of this _anonymous_ clone active on "node". - * - * If there is a partially active orphan (only applies to clone groups) on - * the same node, use that. - * Otherwise create a new (orphaned) instance at "orphan_check:". - */ - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - node_t *loc = child->fns->location(child, NULL, TRUE); - - if(loc && loc->details == node->details) { - resource_t *tmp = child->fns->find_rsc(child, base, NULL, pe_find_partial|pe_find_current); - if(tmp && tmp->running_on == NULL) { - rsc = tmp; - break; - } - } - } - - goto orphan_check; - - } else if(((resource_t*)parent->children->data)->variant == pe_group) { - /* If we're grouped, we need to look for a peer thats active on $node - * and use their clone instance number - */ - resource_t *peer = parent->fns->find_rsc(parent, NULL, node, pe_find_clone|pe_find_current); - if(peer && peer->running_on) { - char buffer[256]; - int clone_num = get_clone(peer->id); - - snprintf(buffer, 256, "%s%d", base, clone_num); - rsc = parent->fns->find_rsc(parent, buffer, node, pe_find_current|pe_find_inactive); - if(rsc) { - crm_trace("Found someone active: %s on %s, becoming %s", peer->id, ((node_t*)peer->running_on->data)->details->uname, buffer); - } - } - } - - while(rsc == NULL) { - rsc = parent->fns->find_rsc(parent, alt_rsc_id, NULL, pe_find_current); - if(rsc == NULL) { - crm_trace("Unknown resource: %s", alt_rsc_id); - break; - } - - if(rsc->running_on == NULL) { - crm_trace("Resource %s: just right", alt_rsc_id); - break; - } - - crm_trace("Resource %s: already active", alt_rsc_id); - alt_rsc_id = increment_clone(alt_rsc_id); - rsc = NULL; - } + crm_trace("Looking for %s on %s", base, node->details->uname); + rsc = parent->fns->find_rsc(parent, base, node, pe_find_partial | pe_find_current); + if (rsc != NULL && rsc->running_on) { + GListPtr gIter = parent->children; + + rsc = NULL; + crm_debug_3("Looking for an existing orphan for %s: %s on %s", parent->id, rsc_id, + node->details->uname); + + /* There is already an instance of this _anonymous_ clone active on "node". + * + * If there is a partially active orphan (only applies to clone groups) on + * the same node, use that. + * Otherwise create a new (orphaned) instance at "orphan_check:". + */ + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + node_t *loc = child->fns->location(child, NULL, TRUE); + + if (loc && loc->details == node->details) { + resource_t *tmp = + child->fns->find_rsc(child, base, NULL, pe_find_partial | pe_find_current); + if (tmp && tmp->running_on == NULL) { + rsc = tmp; + break; + } + } + } + + goto orphan_check; + + } else if (((resource_t *) parent->children->data)->variant == pe_group) { + /* If we're grouped, we need to look for a peer thats active on $node + * and use their clone instance number + */ + resource_t *peer = + parent->fns->find_rsc(parent, NULL, node, pe_find_clone | pe_find_current); + if (peer && peer->running_on) { + char buffer[256]; + int clone_num = get_clone(peer->id); + + snprintf(buffer, 256, "%s%d", base, clone_num); + rsc = + parent->fns->find_rsc(parent, buffer, node, pe_find_current | pe_find_inactive); + if (rsc) { + crm_trace("Found someone active: %s on %s, becoming %s", peer->id, + ((node_t *) peer->running_on->data)->details->uname, buffer); + } + } + } + + while (rsc == NULL) { + rsc = parent->fns->find_rsc(parent, alt_rsc_id, NULL, pe_find_current); + if (rsc == NULL) { + crm_trace("Unknown resource: %s", alt_rsc_id); + break; + } + + if (rsc->running_on == NULL) { + crm_trace("Resource %s: just right", alt_rsc_id); + break; + } + + crm_trace("Resource %s: already active", alt_rsc_id); + alt_rsc_id = increment_clone(alt_rsc_id); + rsc = NULL; + } } orphan_check: - if(rsc == NULL) { - /* Create an extra orphan */ - resource_t *top = create_child_clone(parent, -1, data_set); - crm_debug("Created orphan for %s: %s on %s", parent->id, rsc_id, node->details->uname); - rsc = top->fns->find_rsc(top, base, NULL, pe_find_current|pe_find_partial); - CRM_ASSERT(rsc != NULL); - } - - crm_free(rsc->clone_name); rsc->clone_name = NULL; - if(safe_str_neq(rsc_id, rsc->id)) { - crm_info("Internally renamed %s on %s to %s%s", - rsc_id, node->details->uname, rsc->id, - is_set(rsc->flags, pe_rsc_orphan)?" (ORPHAN)":""); - rsc->clone_name = crm_strdup(rsc_id); - } - + if (rsc == NULL) { + /* Create an extra orphan */ + resource_t *top = create_child_clone(parent, -1, data_set); + + crm_debug("Created orphan for %s: %s on %s", parent->id, rsc_id, node->details->uname); + rsc = top->fns->find_rsc(top, base, NULL, pe_find_current | pe_find_partial); + CRM_ASSERT(rsc != NULL); + } + + crm_free(rsc->clone_name); + rsc->clone_name = NULL; + if (safe_str_neq(rsc_id, rsc->id)) { + crm_info("Internally renamed %s on %s to %s%s", + rsc_id, node->details->uname, rsc->id, + is_set(rsc->flags, pe_rsc_orphan) ? " (ORPHAN)" : ""); + rsc->clone_name = crm_strdup(rsc_id); + } + crm_free(alt_rsc_id); crm_free(base); return rsc; } static resource_t * -unpack_find_resource( - pe_working_set_t *data_set, node_t *node, const char *rsc_id, xmlNode *rsc_entry) +unpack_find_resource(pe_working_set_t * data_set, node_t * node, const char *rsc_id, + xmlNode * rsc_entry) { resource_t *rsc = NULL; resource_t *clone_parent = NULL; char *alt_rsc_id = crm_strdup(rsc_id); - + crm_debug_2("looking for %s", rsc_id); - + rsc = pe_find_resource(data_set->resources, alt_rsc_id); /* no match */ - if(rsc == NULL) { - /* Even when clone-max=0, we still create a single :0 orphan to match against */ - char *tmp = clone_zero(alt_rsc_id); - resource_t *clone0 = pe_find_resource(data_set->resources, tmp); - clone_parent = uber_parent(clone0); - crm_free(tmp); - - crm_debug_2("%s not found: %s", alt_rsc_id, clone_parent?clone_parent->id:"orphan"); + if (rsc == NULL) { + /* Even when clone-max=0, we still create a single :0 orphan to match against */ + char *tmp = clone_zero(alt_rsc_id); + resource_t *clone0 = pe_find_resource(data_set->resources, tmp); + + clone_parent = uber_parent(clone0); + crm_free(tmp); + + crm_debug_2("%s not found: %s", alt_rsc_id, clone_parent ? clone_parent->id : "orphan"); } else { - clone_parent = uber_parent(rsc); + clone_parent = uber_parent(rsc); } - if(clone_parent && clone_parent->variant > pe_group) { - rsc = find_clone(data_set, node, clone_parent, rsc_id); - CRM_ASSERT(rsc != NULL); + if (clone_parent && clone_parent->variant > pe_group) { + rsc = find_clone(data_set, node, clone_parent, rsc_id); + CRM_ASSERT(rsc != NULL); } - + crm_free(alt_rsc_id); return rsc; } static resource_t * -process_orphan_resource(xmlNode *rsc_entry, node_t *node, pe_working_set_t *data_set) +process_orphan_resource(xmlNode * rsc_entry, node_t * node, pe_working_set_t * data_set) { resource_t *rsc = NULL; - const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); - - crm_debug("Detected orphan resource %s on %s", rsc_id, node->details->uname); + const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); + + crm_debug("Detected orphan resource %s on %s", rsc_id, node->details->uname); rsc = create_fake_resource(rsc_id, rsc_entry, data_set); - - if(is_set(data_set->flags, pe_flag_stop_rsc_orphans) == FALSE) { - clear_bit(rsc->flags, pe_rsc_managed); - + + if (is_set(data_set->flags, pe_flag_stop_rsc_orphans) == FALSE) { + clear_bit(rsc->flags, pe_rsc_managed); + } else { - print_resource(LOG_DEBUG_3, "Added orphan", rsc, FALSE); - - CRM_CHECK(rsc != NULL, return NULL); - resource_location(rsc, NULL, -INFINITY, "__orphan_dont_run__", data_set); + print_resource(LOG_DEBUG_3, "Added orphan", rsc, FALSE); + + CRM_CHECK(rsc != NULL, return NULL); + resource_location(rsc, NULL, -INFINITY, "__orphan_dont_run__", data_set); } return rsc; } static void -process_rsc_state(resource_t *rsc, node_t *node, - enum action_fail_response on_fail, - xmlNode *migrate_op, - pe_working_set_t *data_set) +process_rsc_state(resource_t * rsc, node_t * node, + enum action_fail_response on_fail, + xmlNode * migrate_op, pe_working_set_t * data_set) { crm_debug_2("Resource %s is %s on %s: on_fail=%s", - rsc->id, role2text(rsc->role), - node->details->uname, fail2text(on_fail)); + rsc->id, role2text(rsc->role), node->details->uname, fail2text(on_fail)); /* process current state */ - if(rsc->role != RSC_ROLE_UNKNOWN) { - resource_t *iter = rsc; - while(iter) { - if(g_hash_table_lookup(iter->known_on, node->details->id) == NULL) { - node_t *n = node_copy(node); - g_hash_table_insert(iter->known_on, (gpointer)n->details->id, n); - } - if(is_set(iter->flags, pe_rsc_unique)) { - break; - } - iter = iter->parent; - } - } - - if(node->details->unclean) { - /* No extra processing needed - * Also allows resources to be started again after a node is shot - */ - on_fail = action_fail_ignore; - } - - switch(on_fail) { - case action_fail_ignore: - /* nothing to do */ - break; - - case action_fail_fence: - /* treat it as if it is still running - * but also mark the node as unclean - */ - pe_fence_node(data_set, node, "to recover from resource failure(s)"); - break; - - case action_fail_standby: - node->details->standby = TRUE; - node->details->standby_onfail = TRUE; - break; - - case action_fail_block: - /* is_managed == FALSE will prevent any - * actions being sent for the resource - */ - clear_bit(rsc->flags, pe_rsc_managed); - break; - - case action_fail_migrate: - /* make sure it comes up somewhere else - * or not at all - */ - resource_location(rsc, node, -INFINITY, - "__action_migration_auto__",data_set); - break; - - case action_fail_stop: - rsc->next_role = RSC_ROLE_STOPPED; - break; - - case action_fail_recover: - if(rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) { - set_bit(rsc->flags, pe_rsc_failed); - stop_action(rsc, node, FALSE); - } - break; - } - - if(rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) { - if(is_set(rsc->flags, pe_rsc_orphan)) { - if(is_set(rsc->flags, pe_rsc_managed)) { - crm_config_warn("Detected active orphan %s running on %s", - rsc->id, node->details->uname); - } else { - crm_config_warn("Cluster configured not to stop active orphans." - " %s must be stopped manually on %s", - rsc->id, node->details->uname); - } - } - - native_add_running(rsc, node, data_set); - if(on_fail != action_fail_ignore) { - set_bit(rsc->flags, pe_rsc_failed); - } - - } else if(rsc->clone_name) { - crm_debug_2("Resetting clone_name %s for %s (stopped)", - rsc->clone_name, rsc->id); - crm_free(rsc->clone_name); - rsc->clone_name = NULL; + if (rsc->role != RSC_ROLE_UNKNOWN) { + resource_t *iter = rsc; + + while (iter) { + if (g_hash_table_lookup(iter->known_on, node->details->id) == NULL) { + node_t *n = node_copy(node); + + g_hash_table_insert(iter->known_on, (gpointer) n->details->id, n); + } + if (is_set(iter->flags, pe_rsc_unique)) { + break; + } + iter = iter->parent; + } + } + + if (node->details->unclean) { + /* No extra processing needed + * Also allows resources to be started again after a node is shot + */ + on_fail = action_fail_ignore; + } + + switch (on_fail) { + case action_fail_ignore: + /* nothing to do */ + break; + + case action_fail_fence: + /* treat it as if it is still running + * but also mark the node as unclean + */ + pe_fence_node(data_set, node, "to recover from resource failure(s)"); + break; + + case action_fail_standby: + node->details->standby = TRUE; + node->details->standby_onfail = TRUE; + break; + + case action_fail_block: + /* is_managed == FALSE will prevent any + * actions being sent for the resource + */ + clear_bit(rsc->flags, pe_rsc_managed); + break; + + case action_fail_migrate: + /* make sure it comes up somewhere else + * or not at all + */ + resource_location(rsc, node, -INFINITY, "__action_migration_auto__", data_set); + break; + + case action_fail_stop: + rsc->next_role = RSC_ROLE_STOPPED; + break; + + case action_fail_recover: + if (rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) { + set_bit(rsc->flags, pe_rsc_failed); + stop_action(rsc, node, FALSE); + } + break; + } + + if (rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) { + if (is_set(rsc->flags, pe_rsc_orphan)) { + if (is_set(rsc->flags, pe_rsc_managed)) { + crm_config_warn("Detected active orphan %s running on %s", + rsc->id, node->details->uname); + } else { + crm_config_warn("Cluster configured not to stop active orphans." + " %s must be stopped manually on %s", + rsc->id, node->details->uname); + } + } + + native_add_running(rsc, node, data_set); + if (on_fail != action_fail_ignore) { + set_bit(rsc->flags, pe_rsc_failed); + } + + } else if (rsc->clone_name) { + crm_debug_2("Resetting clone_name %s for %s (stopped)", rsc->clone_name, rsc->id); + crm_free(rsc->clone_name); + rsc->clone_name = NULL; } else { - char *key = stop_key(rsc); - GListPtr possible_matches = find_actions(rsc->actions, key, node); - GListPtr gIter = possible_matches; - for(; gIter != NULL; gIter = gIter->next) { - action_t *stop = (action_t*)gIter->data; - stop->flags |= pe_action_optional; - } - - crm_free(key); + char *key = stop_key(rsc); + GListPtr possible_matches = find_actions(rsc->actions, key, node); + GListPtr gIter = possible_matches; + + for (; gIter != NULL; gIter = gIter->next) { + action_t *stop = (action_t *) gIter->data; + + stop->flags |= pe_action_optional; + } + + crm_free(key); } } -/* create active recurring operations as optional */ +/* create active recurring operations as optional */ static void -process_recurring(node_t *node, resource_t *rsc, - int start_index, int stop_index, - GListPtr sorted_op_list, pe_working_set_t *data_set) +process_recurring(node_t * node, resource_t * rsc, + int start_index, int stop_index, + GListPtr sorted_op_list, pe_working_set_t * data_set) { int counter = -1; const char *task = NULL; const char *status = NULL; GListPtr gIter = sorted_op_list; - - crm_debug_3("%s: Start index %d, stop index = %d", - rsc->id, start_index, stop_index); - - for(; gIter != NULL; gIter = gIter->next) { - xmlNode *rsc_op = (xmlNode*)gIter->data; - - int interval = 0; - char *key = NULL; - const char *id = ID(rsc_op); - const char *interval_s = NULL; - counter++; - - if(node->details->online == FALSE) { - crm_debug_4("Skipping %s/%s: node is offline", - rsc->id, node->details->uname); - break; - - /* Need to check if there's a monitor for role="Stopped" */ - } else if(start_index < stop_index && counter <= stop_index) { - crm_debug_4("Skipping %s/%s: resource is not active", - id, node->details->uname); - continue; - - } else if(counter < start_index) { - crm_debug_4("Skipping %s/%s: old %d", - id, node->details->uname, counter); - continue; - } - - interval_s = crm_element_value(rsc_op,XML_LRM_ATTR_INTERVAL); - interval = crm_parse_int(interval_s, "0"); - if(interval == 0) { - crm_debug_4("Skipping %s/%s: non-recurring", - id, node->details->uname); - continue; - } - - status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); - if(safe_str_eq(status, "-1")) { - crm_debug_4("Skipping %s/%s: status", - id, node->details->uname); - continue; - } - task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); - /* create the action */ - key = generate_op_key(rsc->id, task, interval); - crm_debug_3("Creating %s/%s", key, node->details->uname); - custom_action(rsc, key, task, node, TRUE, TRUE, data_set); + + crm_debug_3("%s: Start index %d, stop index = %d", rsc->id, start_index, stop_index); + + for (; gIter != NULL; gIter = gIter->next) { + xmlNode *rsc_op = (xmlNode *) gIter->data; + + int interval = 0; + char *key = NULL; + const char *id = ID(rsc_op); + const char *interval_s = NULL; + + counter++; + + if (node->details->online == FALSE) { + crm_debug_4("Skipping %s/%s: node is offline", rsc->id, node->details->uname); + break; + + /* Need to check if there's a monitor for role="Stopped" */ + } else if (start_index < stop_index && counter <= stop_index) { + crm_debug_4("Skipping %s/%s: resource is not active", id, node->details->uname); + continue; + + } else if (counter < start_index) { + crm_debug_4("Skipping %s/%s: old %d", id, node->details->uname, counter); + continue; + } + + interval_s = crm_element_value(rsc_op, XML_LRM_ATTR_INTERVAL); + interval = crm_parse_int(interval_s, "0"); + if (interval == 0) { + crm_debug_4("Skipping %s/%s: non-recurring", id, node->details->uname); + continue; + } + + status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); + if (safe_str_eq(status, "-1")) { + crm_debug_4("Skipping %s/%s: status", id, node->details->uname); + continue; + } + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); + /* create the action */ + key = generate_op_key(rsc->id, task, interval); + crm_debug_3("Creating %s/%s", key, node->details->uname); + custom_action(rsc, key, task, node, TRUE, TRUE, data_set); } } void -calculate_active_ops(GListPtr sorted_op_list, int *start_index, int *stop_index) +calculate_active_ops(GListPtr sorted_op_list, int *start_index, int *stop_index) { int counter = -1; const char *task = NULL; const char *status = NULL; GListPtr gIter = sorted_op_list; *stop_index = -1; *start_index = -1; - for(; gIter != NULL; gIter = gIter->next) { - xmlNode *rsc_op = (xmlNode*)gIter->data; - counter++; - - task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); - status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); - - if(safe_str_eq(task, CRMD_ACTION_STOP) - && safe_str_eq(status, "0")) { - *stop_index = counter; - - } else if(safe_str_eq(task, CRMD_ACTION_START)) { - *start_index = counter; - - } else if(*start_index <= *stop_index - && safe_str_eq(task, CRMD_ACTION_STATUS)) { - const char *rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC); - if(safe_str_eq(rc, "0") || safe_str_eq(rc, "8")) { - *start_index = counter; - } - } + for (; gIter != NULL; gIter = gIter->next) { + xmlNode *rsc_op = (xmlNode *) gIter->data; + + counter++; + + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); + status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); + + if (safe_str_eq(task, CRMD_ACTION_STOP) + && safe_str_eq(status, "0")) { + *stop_index = counter; + + } else if (safe_str_eq(task, CRMD_ACTION_START)) { + *start_index = counter; + + } else if (*start_index <= *stop_index && safe_str_eq(task, CRMD_ACTION_STATUS)) { + const char *rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC); + + if (safe_str_eq(rc, "0") || safe_str_eq(rc, "8")) { + *start_index = counter; + } + } } } - static void -unpack_lrm_rsc_state( - node_t *node, xmlNode * rsc_entry, pe_working_set_t *data_set) -{ +unpack_lrm_rsc_state(node_t * node, xmlNode * rsc_entry, pe_working_set_t * data_set) +{ GListPtr gIter = NULL; int stop_index = -1; int start_index = -1; enum rsc_role_e req_role = RSC_ROLE_UNKNOWN; const char *task = NULL; - const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); + const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); resource_t *rsc = NULL; GListPtr op_list = NULL; GListPtr sorted_op_list = NULL; xmlNode *migrate_op = NULL; xmlNode *rsc_op = NULL; - + enum action_fail_response on_fail = FALSE; enum rsc_role_e saved_role = RSC_ROLE_UNKNOWN; - + crm_debug_3("[%s] Processing %s on %s", - crm_element_name(rsc_entry), rsc_id, node->details->uname); + crm_element_name(rsc_entry), rsc_id, node->details->uname); /* extract operations */ op_list = NULL; sorted_op_list = NULL; - - for(rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { - if(crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { - op_list = g_list_prepend(op_list, rsc_op); - } + + for (rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { + if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { + op_list = g_list_prepend(op_list, rsc_op); + } } - if(op_list == NULL) { - /* if there are no operations, there is nothing to do */ - return; + if (op_list == NULL) { + /* if there are no operations, there is nothing to do */ + return; } /* find the resource */ rsc = unpack_find_resource(data_set, node, rsc_id, rsc_entry); - if(rsc == NULL) { - rsc = process_orphan_resource(rsc_entry, node, data_set); - } + if (rsc == NULL) { + rsc = process_orphan_resource(rsc_entry, node, data_set); + } CRM_ASSERT(rsc != NULL); - + /* process operations */ saved_role = rsc->role; on_fail = action_fail_ignore; rsc->role = RSC_ROLE_UNKNOWN; sorted_op_list = g_list_sort(op_list, sort_op_by_callid); - - for(gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { - xmlNode *rsc_op = (xmlNode*)gIter->data; - task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); - if(safe_str_eq(task, CRMD_ACTION_MIGRATED)) { - migrate_op = rsc_op; - } - - unpack_rsc_op(rsc, node, rsc_op, gIter->next, &on_fail, data_set); - } - - /* create active recurring operations as optional */ + + for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { + xmlNode *rsc_op = (xmlNode *) gIter->data; + + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); + if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) { + migrate_op = rsc_op; + } + + unpack_rsc_op(rsc, node, rsc_op, gIter->next, &on_fail, data_set); + } + + /* create active recurring operations as optional */ calculate_active_ops(sorted_op_list, &start_index, &stop_index); - process_recurring(node, rsc, start_index, stop_index, - sorted_op_list, data_set); - + process_recurring(node, rsc, start_index, stop_index, sorted_op_list, data_set); + /* no need to free the contents */ g_list_free(sorted_op_list); - + process_rsc_state(rsc, node, on_fail, migrate_op, data_set); - if(get_target_role(rsc, &req_role)) { - if(rsc->next_role == RSC_ROLE_UNKNOWN || req_role < rsc->next_role) { - crm_debug("%s: Overwriting calculated next role %s" - " with requested next role %s", - rsc->id, role2text(rsc->next_role), - role2text(req_role)); - rsc->next_role = req_role; - - } else if(req_role > rsc->next_role) { - crm_info("%s: Not overwriting calculated next role %s" - " with requested next role %s", - rsc->id, role2text(rsc->next_role), - role2text(req_role)); - } - } - - if(saved_role > rsc->role) { - rsc->role = saved_role; + if (get_target_role(rsc, &req_role)) { + if (rsc->next_role == RSC_ROLE_UNKNOWN || req_role < rsc->next_role) { + crm_debug("%s: Overwriting calculated next role %s" + " with requested next role %s", + rsc->id, role2text(rsc->next_role), role2text(req_role)); + rsc->next_role = req_role; + + } else if (req_role > rsc->next_role) { + crm_info("%s: Not overwriting calculated next role %s" + " with requested next role %s", + rsc->id, role2text(rsc->next_role), role2text(req_role)); + } + } + + if (saved_role > rsc->role) { + rsc->role = saved_role; } } gboolean -unpack_lrm_resources(node_t *node, xmlNode * lrm_rsc_list, pe_working_set_t *data_set) +unpack_lrm_resources(node_t * node, xmlNode * lrm_rsc_list, pe_working_set_t * data_set) { xmlNode *rsc_entry = NULL; + CRM_CHECK(node != NULL, return FALSE); crm_debug_3("Unpacking resources on %s", node->details->uname); - for(rsc_entry = __xml_first_child(lrm_rsc_list); rsc_entry != NULL; rsc_entry = __xml_next(rsc_entry)) { - if(crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) { - unpack_lrm_rsc_state(node, rsc_entry, data_set); - } + for (rsc_entry = __xml_first_child(lrm_rsc_list); rsc_entry != NULL; + rsc_entry = __xml_next(rsc_entry)) { + if (crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) { + unpack_lrm_rsc_state(node, rsc_entry, data_set); + } } - + return TRUE; } -static void set_active(resource_t *rsc) +static void +set_active(resource_t * rsc) { resource_t *top = uber_parent(rsc); - if(top && top->variant == pe_master) { - rsc->role = RSC_ROLE_SLAVE; + + if (top && top->variant == pe_master) { + rsc->role = RSC_ROLE_SLAVE; } else { - rsc->role = RSC_ROLE_STARTED; + rsc->role = RSC_ROLE_STARTED; } } -static void set_node_score(gpointer key, gpointer value, gpointer user_data) +static void +set_node_score(gpointer key, gpointer value, gpointer user_data) { node_t *node = value; int *score = user_data; + node->weight = *score; } #define STATUS_PATH_MAX 1024 -static xmlNode *find_lrm_op(const char *resource, const char *op, const char *node, const char *source, pe_working_set_t *data_set) +static xmlNode * +find_lrm_op(const char *resource, const char *op, const char *node, const char *source, + pe_working_set_t * data_set) { int offset = 0; char xpath[STATUS_PATH_MAX]; - offset += snprintf(xpath+offset, STATUS_PATH_MAX-offset, "//node_state[@uname='%s']", node); - offset += snprintf(xpath+offset, STATUS_PATH_MAX-offset, "//"XML_LRM_TAG_RESOURCE"[@id='%s']", resource); + offset += snprintf(xpath + offset, STATUS_PATH_MAX - offset, "//node_state[@uname='%s']", node); + offset += + snprintf(xpath + offset, STATUS_PATH_MAX - offset, "//" XML_LRM_TAG_RESOURCE "[@id='%s']", + resource); /* Need to check against transition_magic too? */ - if(source && safe_str_eq(op, CRMD_ACTION_MIGRATE)) { - offset += snprintf(xpath+offset, STATUS_PATH_MAX-offset, "/"XML_LRM_TAG_RSC_OP"[@operation='%s' and @migrate_target='%s']", op, source); - } else if(source && safe_str_eq(op, CRMD_ACTION_MIGRATED)) { - offset += snprintf(xpath+offset, STATUS_PATH_MAX-offset, "/"XML_LRM_TAG_RSC_OP"[@operation='%s' and @migrate_source='%s']", op, source); + if (source && safe_str_eq(op, CRMD_ACTION_MIGRATE)) { + offset += + snprintf(xpath + offset, STATUS_PATH_MAX - offset, + "/" XML_LRM_TAG_RSC_OP "[@operation='%s' and @migrate_target='%s']", op, + source); + } else if (source && safe_str_eq(op, CRMD_ACTION_MIGRATED)) { + offset += + snprintf(xpath + offset, STATUS_PATH_MAX - offset, + "/" XML_LRM_TAG_RSC_OP "[@operation='%s' and @migrate_source='%s']", op, + source); } else { - offset += snprintf(xpath+offset, STATUS_PATH_MAX-offset, "/"XML_LRM_TAG_RSC_OP"[@operation='%s']", op); + offset += + snprintf(xpath + offset, STATUS_PATH_MAX - offset, + "/" XML_LRM_TAG_RSC_OP "[@operation='%s']", op); } return get_xpath_object(xpath, data_set->input, LOG_DEBUG); } gboolean -unpack_rsc_op(resource_t *rsc, node_t *node, xmlNode *xml_op, GListPtr next, - enum action_fail_response *on_fail, pe_working_set_t *data_set) -{ +unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, GListPtr next, + enum action_fail_response * on_fail, pe_working_set_t * data_set) +{ int task_id = 0; - const char *id = NULL; - const char *key = NULL; - const char *task = NULL; - const char *magic = NULL; - const char *actual_rc = NULL; + const char *id = NULL; + const char *key = NULL; + const char *task = NULL; + const char *magic = NULL; + const char *actual_rc = NULL; + /* const char *target_rc = NULL; */ const char *task_status = NULL; - const char *interval_s = NULL; - const char *op_version = NULL; + const char *interval_s = NULL; + const char *op_version = NULL; int interval = 0; int task_status_i = -2; int actual_rc_i = 0; int target_rc = -1; int last_failure = 0; - + action_t *action = NULL; node_t *effective_node = NULL; resource_t *failed = NULL; gboolean expired = FALSE; gboolean is_probe = FALSE; gboolean clear_past_failure = FALSE; - - CRM_CHECK(rsc != NULL, return FALSE); - CRM_CHECK(node != NULL, return FALSE); + + CRM_CHECK(rsc != NULL, return FALSE); + CRM_CHECK(node != NULL, return FALSE); CRM_CHECK(xml_op != NULL, return FALSE); - id = ID(xml_op); - task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); + id = ID(xml_op); + task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); task_status = crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS); - op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION); - magic = crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC); - key = crm_element_value(xml_op, XML_ATTR_TRANSITION_KEY); + op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION); + magic = crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC); + key = crm_element_value(xml_op, XML_ATTR_TRANSITION_KEY); crm_element_value_int(xml_op, XML_LRM_ATTR_CALLID, &task_id); - + CRM_CHECK(id != NULL, return FALSE); CRM_CHECK(task != NULL, return FALSE); CRM_CHECK(task_status != NULL, return FALSE); task_status_i = crm_parse_int(task_status, NULL); CRM_CHECK(task_status_i <= LRM_OP_ERROR, return FALSE); CRM_CHECK(task_status_i >= LRM_OP_PENDING, return FALSE); - if(safe_str_eq(task, CRMD_ACTION_NOTIFY)) { - /* safe to ignore these */ - return TRUE; + if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) { + /* safe to ignore these */ + return TRUE; } - if(rsc->failure_timeout > 0) { - int last_run = 0; + if (rsc->failure_timeout > 0) { + int last_run = 0; - if(crm_element_value_int(xml_op, "last-rc-change", &last_run) == 0) { - time_t now = get_timet_now(data_set); - if(now > (last_run + rsc->failure_timeout)) { - expired = TRUE; - } - } + if (crm_element_value_int(xml_op, "last-rc-change", &last_run) == 0) { + time_t now = get_timet_now(data_set); + + if (now > (last_run + rsc->failure_timeout)) { + expired = TRUE; + } + } } - + crm_debug_2("Unpacking task %s/%s (call_id=%d, status=%s) on %s (role=%s)", - id, task, task_id, task_status, node->details->uname, - role2text(rsc->role)); + id, task, task_id, task_status, node->details->uname, role2text(rsc->role)); interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL); interval = crm_parse_int(interval_s, "0"); - - if(interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) { - is_probe = TRUE; + + if (interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) { + is_probe = TRUE; } - - if(node->details->unclean) { - crm_debug_2("Node %s (where %s is running) is unclean." - " Further action depends on the value of the stop's on-fail attribue", - node->details->uname, rsc->id); + + if (node->details->unclean) { + crm_debug_2("Node %s (where %s is running) is unclean." + " Further action depends on the value of the stop's on-fail attribue", + node->details->uname, rsc->id); } actual_rc = crm_element_value(xml_op, XML_LRM_ATTR_RC); - CRM_CHECK(actual_rc != NULL, return FALSE); + CRM_CHECK(actual_rc != NULL, return FALSE); actual_rc_i = crm_parse_int(actual_rc, NULL); - if(key) { - int dummy = 0; - char *dummy_string = NULL; - decode_transition_key(key, &dummy_string, &dummy, &dummy, &target_rc); - crm_free(dummy_string); - } - - if(task_status_i == LRM_OP_DONE && target_rc >= 0) { - if(target_rc == actual_rc_i) { - task_status_i = LRM_OP_DONE; - - } else { - task_status_i = LRM_OP_ERROR; - crm_debug("%s on %s returned %d (%s) instead of the expected value: %d (%s)", - id, node->details->uname, - actual_rc_i, execra_code2string(actual_rc_i), - target_rc, execra_code2string(target_rc)); - } - - } else if(task_status_i == LRM_OP_ERROR) { - /* let us decide that */ - task_status_i = LRM_OP_DONE; - } - - if(task_status_i == LRM_OP_NOTSUPPORTED) { - actual_rc_i = EXECRA_UNIMPLEMENT_FEATURE; - } - - if(task_status_i != actual_rc_i - && rsc->failure_timeout > 0 - && get_failcount(node, rsc, &last_failure, data_set) == 0) { - if(last_failure > 0) { - action_t *clear_op = NULL; - clear_op = custom_action( - rsc, crm_concat(rsc->id, CRM_OP_CLEAR_FAILCOUNT, '_'), - CRM_OP_CLEAR_FAILCOUNT, node, FALSE, TRUE, data_set); - - add_hash_param(clear_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); - crm_notice("Clearing expired failcount for %s on %s", rsc->id, node->details->uname); - } - } - - if(expired - && actual_rc_i != EXECRA_NOT_RUNNING - && actual_rc_i != EXECRA_RUNNING_MASTER - && actual_rc_i != EXECRA_OK) { - crm_notice("Ignoring expired failure %s (rc=%d, magic=%s) on %s", - id, actual_rc_i, magic, node->details->uname); - goto done; - } + if (key) { + int dummy = 0; + char *dummy_string = NULL; + + decode_transition_key(key, &dummy_string, &dummy, &dummy, &target_rc); + crm_free(dummy_string); + } + + if (task_status_i == LRM_OP_DONE && target_rc >= 0) { + if (target_rc == actual_rc_i) { + task_status_i = LRM_OP_DONE; + + } else { + task_status_i = LRM_OP_ERROR; + crm_debug("%s on %s returned %d (%s) instead of the expected value: %d (%s)", + id, node->details->uname, + actual_rc_i, execra_code2string(actual_rc_i), + target_rc, execra_code2string(target_rc)); + } + + } else if (task_status_i == LRM_OP_ERROR) { + /* let us decide that */ + task_status_i = LRM_OP_DONE; + } + + if (task_status_i == LRM_OP_NOTSUPPORTED) { + actual_rc_i = EXECRA_UNIMPLEMENT_FEATURE; + } + + if (task_status_i != actual_rc_i + && rsc->failure_timeout > 0 && get_failcount(node, rsc, &last_failure, data_set) == 0) { + if (last_failure > 0) { + action_t *clear_op = NULL; + + clear_op = custom_action(rsc, crm_concat(rsc->id, CRM_OP_CLEAR_FAILCOUNT, '_'), + CRM_OP_CLEAR_FAILCOUNT, node, FALSE, TRUE, data_set); + + add_hash_param(clear_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); + crm_notice("Clearing expired failcount for %s on %s", rsc->id, node->details->uname); + } + } + + if (expired + && actual_rc_i != EXECRA_NOT_RUNNING + && actual_rc_i != EXECRA_RUNNING_MASTER && actual_rc_i != EXECRA_OK) { + crm_notice("Ignoring expired failure %s (rc=%d, magic=%s) on %s", + id, actual_rc_i, magic, node->details->uname); + goto done; + } /* we could clean this up significantly except for old LRMs and CRMs that * didnt include target_rc and liked to remap status */ - switch(actual_rc_i) { - case EXECRA_NOT_RUNNING: - if(is_probe || target_rc == actual_rc_i) { - task_status_i = LRM_OP_DONE; - rsc->role = RSC_ROLE_STOPPED; - - /* clear any previous failure actions */ - *on_fail = action_fail_ignore; - rsc->next_role = RSC_ROLE_UNKNOWN; - - } else if(safe_str_neq(task, CRMD_ACTION_STOP)) { - task_status_i = LRM_OP_ERROR; - } - break; - - case EXECRA_RUNNING_MASTER: - if(is_probe) { - task_status_i = LRM_OP_DONE; - crm_notice("Operation %s found resource %s active in master mode on %s", - id, rsc->id, node->details->uname); - - } else if(target_rc == actual_rc_i) { - /* nothing to do */ - - } else if(target_rc >= 0) { - task_status_i = LRM_OP_ERROR; - - /* legacy code for pre-0.6.5 operations */ - } else if(safe_str_neq(task, CRMD_ACTION_STATUS) - || rsc->role != RSC_ROLE_MASTER) { - task_status_i = LRM_OP_ERROR; - if(rsc->role != RSC_ROLE_MASTER) { - crm_err("%s reported %s in master mode on %s", - id, rsc->id, - node->details->uname); - } - } - rsc->role = RSC_ROLE_MASTER; - break; - - case EXECRA_FAILED_MASTER: - rsc->role = RSC_ROLE_MASTER; - task_status_i = LRM_OP_ERROR; - break; - - case EXECRA_UNIMPLEMENT_FEATURE: - if(interval > 0) { - task_status_i = LRM_OP_NOTSUPPORTED; - break; - } - /* else: fall through */ - case EXECRA_INSUFFICIENT_PRIV: - case EXECRA_NOT_INSTALLED: - case EXECRA_INVALID_PARAM: - effective_node = node; - /* fall through */ - case EXECRA_NOT_CONFIGURED: - failed = rsc; - if(is_not_set(rsc->flags, pe_rsc_unique)) { - failed = uber_parent(failed); - } - - do_crm_log(actual_rc_i==EXECRA_NOT_INSTALLED?LOG_NOTICE:LOG_ERR, - "Hard error - %s failed with rc=%d: Preventing %s from re-starting %s %s", - id, actual_rc_i, failed->id, - effective_node?"on":"anywhere", - effective_node?effective_node->details->uname:"in the cluster"); - - resource_location(failed, effective_node, -INFINITY, "hard-error", data_set); - if(is_probe) { - /* treat these like stops */ - task = CRMD_ACTION_STOP; - task_status_i = LRM_OP_DONE; - crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname); - if(actual_rc_i != EXECRA_NOT_INSTALLED - || is_set(data_set->flags, pe_flag_symmetric_cluster)) { - if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) { - add_node_copy(data_set->failed, xml_op); - } - } - } - break; - - case EXECRA_OK: - if(is_probe && target_rc == 7) { - task_status_i = LRM_OP_DONE; - crm_notice("Operation %s found resource %s active on %s", - id, rsc->id, node->details->uname); - - /* legacy code for pre-0.6.5 operations */ - } else if(target_rc < 0 - && interval > 0 - && rsc->role == RSC_ROLE_MASTER) { - /* catch status ops that return 0 instead of 8 while they - * are supposed to be in master mode - */ - task_status_i = LRM_OP_ERROR; - } - - break; - - default: - if(task_status_i == LRM_OP_DONE) { - crm_info("Remapping %s (rc=%d) on %s to an ERROR", - id, actual_rc_i, node->details->uname); - task_status_i = LRM_OP_ERROR; - } - } - - if(task_status_i == LRM_OP_ERROR - || task_status_i == LRM_OP_TIMEOUT - || task_status_i == LRM_OP_NOTSUPPORTED) { - action = custom_action(rsc, crm_strdup(id), task, NULL, TRUE, FALSE, data_set); - if(expired) { - crm_notice("Ignoring expired failure (calculated) %s (rc=%d, magic=%s) on %s", - id, actual_rc_i, magic, node->details->uname); - goto done; - - } else if(action->on_fail == action_fail_ignore) { - crm_warn("Remapping %s (rc=%d) on %s to DONE: ignore", - id, actual_rc_i, node->details->uname); - task_status_i = LRM_OP_DONE; - set_bit(rsc->flags, pe_rsc_failure_ignored); - - crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname); - if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) { - add_node_copy(data_set->failed, xml_op); - } - } - } - - switch(task_status_i) { - case LRM_OP_PENDING: - if(safe_str_eq(task, CRMD_ACTION_START)) { - set_bit(rsc->flags, pe_rsc_start_pending); - set_active(rsc); - - } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { - rsc->role = RSC_ROLE_MASTER; - } - /* - * Intentionally ignoring pending migrate ops here; - * haven't decided if we need to do anything special - * with them yet... - */ - break; - - case LRM_OP_DONE: - crm_debug_3("%s/%s completed on %s", - rsc->id, task, node->details->uname); - - if(actual_rc_i == EXECRA_NOT_RUNNING) { - clear_past_failure = TRUE; - - } else if(safe_str_eq(task, CRMD_ACTION_START)) { - rsc->role = RSC_ROLE_STARTED; - clear_past_failure = TRUE; - - } else if(safe_str_eq(task, CRMD_ACTION_STOP)) { - rsc->role = RSC_ROLE_STOPPED; - clear_past_failure = TRUE; - - } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { - rsc->role = RSC_ROLE_MASTER; - clear_past_failure = TRUE; - - } else if(safe_str_eq(task, CRMD_ACTION_DEMOTE)) { - /* Demote from Master does not clear an error */ - rsc->role = RSC_ROLE_SLAVE; - - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATED)) { - rsc->role = RSC_ROLE_STARTED; - clear_past_failure = TRUE; - - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATE)) { - /* - * The normal sequence is (now): migrate_to(Src) -> migrate_from(Tgt) -> stop(Src) - * - * So if a migrate_to is followed by a stop, then we dont need to care what - * happended on the target node - * - * Without the stop, we need to look for a successful migrate_from. - * This would also imply we're no longer running on the source - * - * Without the stop, and without a migrate_from op we make sure the resource - * gets stopped on both source and target (assuming the target is up) - * - */ - int stop_id = 0; - xmlNode *stop_op = find_lrm_op(rsc->id, CRMD_ACTION_STOP, node->details->id, NULL, data_set); - - if(stop_op) { - crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id); - } - - if(stop_op == NULL || stop_id < task_id) { - int from_rc = 0, from_status = 0; - const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE); - const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET); - - node_t *target = pe_find_node(data_set->nodes, migrate_target); - xmlNode *migrate_from = find_lrm_op(rsc->id, CRMD_ACTION_MIGRATED, migrate_target, migrate_source, data_set); - - rsc->role = RSC_ROLE_STARTED; /* can be master? */ - if(migrate_from) { - crm_element_value_int(migrate_from, XML_LRM_ATTR_RC, &from_rc); - crm_element_value_int(migrate_from, XML_LRM_ATTR_OPSTATUS, &from_status); - crm_trace("%s op on %s exited with status=%d, rc=%d", - ID(migrate_from), migrate_target, from_status, from_rc); - } - - if(migrate_from && from_rc == EXECRA_OK && from_status == LRM_OP_DONE) { - crm_trace("Detected dangling migration op: %s on %s", ID(xml_op), migrate_source); - - /* all good - * just need to arrange for the stop action to get sent - * but _without_ affecting the target somehow - */ - rsc->role = RSC_ROLE_STOPPED; - rsc->dangling_migrations = g_list_prepend(rsc->dangling_migrations, node); - - } else if(migrate_from) { /* Failed */ - crm_trace("Marking active on %s %p %d", migrate_target, target, target->details->online); - if(target && target->details->online) { - native_add_running(rsc, target, data_set); - } - - } else { /* Pending or complete but erased */ - node_t *target = pe_find_node_id(data_set->nodes, migrate_target); - - crm_trace("Marking active on %s %p %d", migrate_target, target, target->details->online); - if(target && target->details->online) { - /* TODO: One day, figure out how to complete the migration - * For now, consider it active in both locations so it gets stopped everywhere - */ - native_add_running(rsc, target, data_set); - - } else { - /* Consider it failed here - forces a restart, prevents migration */ - set_bit_inplace(rsc->flags, pe_rsc_failed); - } - } - } - - } else if(rsc->role < RSC_ROLE_STARTED) { - /* start, migrate_to and migrate_from will land here */ - crm_debug_3("%s active on %s", - rsc->id, node->details->uname); - set_active(rsc); - } - - /* clear any previous failure actions */ - if(clear_past_failure) { - switch(*on_fail) { - case action_fail_block: - case action_fail_stop: - case action_fail_fence: - case action_fail_migrate: - case action_fail_standby: - crm_debug_2("%s.%s is not cleared by a completed stop", - rsc->id, fail2text(*on_fail)); - break; - - case action_fail_ignore: - case action_fail_recover: - *on_fail = action_fail_ignore; - rsc->next_role = RSC_ROLE_UNKNOWN; - } - } - break; - - case LRM_OP_ERROR: - case LRM_OP_TIMEOUT: - case LRM_OP_NOTSUPPORTED: - crm_warn("Processing failed op %s on %s: %s (%d)", - id, node->details->uname, - execra_code2string(actual_rc_i), actual_rc_i); - crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname); - if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) { - add_node_copy(data_set->failed, xml_op); - } - - if(*on_fail < action->on_fail) { - *on_fail = action->on_fail; - } - - if(safe_str_eq(task, CRMD_ACTION_STOP)) { - resource_location( - rsc, node, -INFINITY, "__stop_fail__", data_set); - - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATED)) { - int stop_id = 0; - int migrate_id = 0; - const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE); - const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET); - - xmlNode *stop_op = find_lrm_op(rsc->id, CRMD_ACTION_STOP, migrate_source, NULL, data_set); - xmlNode *migrate_op = find_lrm_op(rsc->id, CRMD_ACTION_MIGRATE, migrate_source, migrate_target, data_set); - - if(stop_op) { - crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id); - } - if(migrate_op) { - crm_element_value_int(migrate_op, XML_LRM_ATTR_CALLID, &migrate_id); - } - - /* Get our state right */ - rsc->role = RSC_ROLE_STARTED; /* can be master? */ - - if(stop_op == NULL || stop_id < migrate_id) { - node_t *source = pe_find_node(data_set->nodes, migrate_source); - - if(source && source->details->online) { - native_add_running(rsc, source, data_set); - } - } - - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATE)) { - int stop_id = 0; - int migrate_id = 0; - const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE); - const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET); - - xmlNode *stop_op = find_lrm_op(rsc->id, CRMD_ACTION_STOP, migrate_target, NULL, data_set); - xmlNode *migrate_op = find_lrm_op(rsc->id, CRMD_ACTION_MIGRATED, migrate_target, migrate_source, data_set); - - if(stop_op) { - crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id); - } - if(migrate_op) { - crm_element_value_int(migrate_op, XML_LRM_ATTR_CALLID, &migrate_id); - } - - /* Get our state right */ - rsc->role = RSC_ROLE_STARTED; /* can be master? */ - - if(stop_op == NULL || stop_id < migrate_id) { - node_t *target = pe_find_node(data_set->nodes, migrate_target); - - crm_trace("Stop: %p %d, Migrated: %p %d", stop_op, stop_id, migrate_op, migrate_id); - if(target && target->details->online) { - native_add_running(rsc, target, data_set); - } - - } else if(migrate_op == NULL) { - /* Make sure it gets cleaned up, the stop may pre-date the migrate_from */ - rsc->dangling_migrations = g_list_prepend(rsc->dangling_migrations, node); - } - - } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { - rsc->role = RSC_ROLE_MASTER; - - } else if(safe_str_eq(task, CRMD_ACTION_DEMOTE)) { - /* - * staying in role=master ends up putting the PE/TE into a loop - * setting role=slave is not dangerous because no master will be - * promoted until the failed resource has been fully stopped - */ - crm_warn("Forcing %s to stop after a failed demote action", rsc->id); - rsc->next_role = RSC_ROLE_STOPPED; - rsc->role = RSC_ROLE_SLAVE; - - } else if(compare_version("2.0", op_version) > 0 - && safe_str_eq(task, CRMD_ACTION_START)) { - crm_warn("Compatibility handling for failed op %s on %s", - id, node->details->uname); - resource_location( - rsc, node, -INFINITY, "__legacy_start__", data_set); - } - - if(rsc->role < RSC_ROLE_STARTED) { - set_active(rsc); - } - - crm_debug_2("Resource %s: role=%s, unclean=%s, on_fail=%s, fail_role=%s", - rsc->id, role2text(rsc->role), - node->details->unclean?"true":"false", - fail2text(action->on_fail), - role2text(action->fail_role)); - - if(action->fail_role != RSC_ROLE_STARTED - && rsc->next_role < action->fail_role) { - rsc->next_role = action->fail_role; - } - - if(action->fail_role == RSC_ROLE_STOPPED) { - int score = -INFINITY; - crm_err("Making sure %s doesn't come up again", rsc->id); - /* make sure it doesnt come up again */ - g_hash_table_destroy(rsc->allowed_nodes); - rsc->allowed_nodes = node_hash_from_list(data_set->nodes); - g_hash_table_foreach(rsc->allowed_nodes, set_node_score, &score); - } - - pe_free_action(action); - action = NULL; - break; - case LRM_OP_CANCELLED: - /* do nothing?? */ - pe_err("Dont know what to do for cancelled ops yet"); - break; + switch (actual_rc_i) { + case EXECRA_NOT_RUNNING: + if (is_probe || target_rc == actual_rc_i) { + task_status_i = LRM_OP_DONE; + rsc->role = RSC_ROLE_STOPPED; + + /* clear any previous failure actions */ + *on_fail = action_fail_ignore; + rsc->next_role = RSC_ROLE_UNKNOWN; + + } else if (safe_str_neq(task, CRMD_ACTION_STOP)) { + task_status_i = LRM_OP_ERROR; + } + break; + + case EXECRA_RUNNING_MASTER: + if (is_probe) { + task_status_i = LRM_OP_DONE; + crm_notice("Operation %s found resource %s active in master mode on %s", + id, rsc->id, node->details->uname); + + } else if (target_rc == actual_rc_i) { + /* nothing to do */ + + } else if (target_rc >= 0) { + task_status_i = LRM_OP_ERROR; + + /* legacy code for pre-0.6.5 operations */ + } else if (safe_str_neq(task, CRMD_ACTION_STATUS) + || rsc->role != RSC_ROLE_MASTER) { + task_status_i = LRM_OP_ERROR; + if (rsc->role != RSC_ROLE_MASTER) { + crm_err("%s reported %s in master mode on %s", + id, rsc->id, node->details->uname); + } + } + rsc->role = RSC_ROLE_MASTER; + break; + + case EXECRA_FAILED_MASTER: + rsc->role = RSC_ROLE_MASTER; + task_status_i = LRM_OP_ERROR; + break; + + case EXECRA_UNIMPLEMENT_FEATURE: + if (interval > 0) { + task_status_i = LRM_OP_NOTSUPPORTED; + break; + } + /* else: fall through */ + case EXECRA_INSUFFICIENT_PRIV: + case EXECRA_NOT_INSTALLED: + case EXECRA_INVALID_PARAM: + effective_node = node; + /* fall through */ + case EXECRA_NOT_CONFIGURED: + failed = rsc; + if (is_not_set(rsc->flags, pe_rsc_unique)) { + failed = uber_parent(failed); + } + + do_crm_log(actual_rc_i == EXECRA_NOT_INSTALLED ? LOG_NOTICE : LOG_ERR, + "Hard error - %s failed with rc=%d: Preventing %s from re-starting %s %s", + id, actual_rc_i, failed->id, + effective_node ? "on" : "anywhere", + effective_node ? effective_node->details->uname : "in the cluster"); + + resource_location(failed, effective_node, -INFINITY, "hard-error", data_set); + if (is_probe) { + /* treat these like stops */ + task = CRMD_ACTION_STOP; + task_status_i = LRM_OP_DONE; + crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname); + if (actual_rc_i != EXECRA_NOT_INSTALLED + || is_set(data_set->flags, pe_flag_symmetric_cluster)) { + if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) { + add_node_copy(data_set->failed, xml_op); + } + } + } + break; + + case EXECRA_OK: + if (is_probe && target_rc == 7) { + task_status_i = LRM_OP_DONE; + crm_notice("Operation %s found resource %s active on %s", + id, rsc->id, node->details->uname); + + /* legacy code for pre-0.6.5 operations */ + } else if (target_rc < 0 && interval > 0 && rsc->role == RSC_ROLE_MASTER) { + /* catch status ops that return 0 instead of 8 while they + * are supposed to be in master mode + */ + task_status_i = LRM_OP_ERROR; + } + + break; + + default: + if (task_status_i == LRM_OP_DONE) { + crm_info("Remapping %s (rc=%d) on %s to an ERROR", + id, actual_rc_i, node->details->uname); + task_status_i = LRM_OP_ERROR; + } + } + + if (task_status_i == LRM_OP_ERROR + || task_status_i == LRM_OP_TIMEOUT || task_status_i == LRM_OP_NOTSUPPORTED) { + action = custom_action(rsc, crm_strdup(id), task, NULL, TRUE, FALSE, data_set); + if (expired) { + crm_notice("Ignoring expired failure (calculated) %s (rc=%d, magic=%s) on %s", + id, actual_rc_i, magic, node->details->uname); + goto done; + + } else if (action->on_fail == action_fail_ignore) { + crm_warn("Remapping %s (rc=%d) on %s to DONE: ignore", + id, actual_rc_i, node->details->uname); + task_status_i = LRM_OP_DONE; + set_bit(rsc->flags, pe_rsc_failure_ignored); + + crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname); + if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) { + add_node_copy(data_set->failed, xml_op); + } + } + } + + switch (task_status_i) { + case LRM_OP_PENDING: + if (safe_str_eq(task, CRMD_ACTION_START)) { + set_bit(rsc->flags, pe_rsc_start_pending); + set_active(rsc); + + } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) { + rsc->role = RSC_ROLE_MASTER; + } + /* + * Intentionally ignoring pending migrate ops here; + * haven't decided if we need to do anything special + * with them yet... + */ + break; + + case LRM_OP_DONE: + crm_debug_3("%s/%s completed on %s", rsc->id, task, node->details->uname); + + if (actual_rc_i == EXECRA_NOT_RUNNING) { + clear_past_failure = TRUE; + + } else if (safe_str_eq(task, CRMD_ACTION_START)) { + rsc->role = RSC_ROLE_STARTED; + clear_past_failure = TRUE; + + } else if (safe_str_eq(task, CRMD_ACTION_STOP)) { + rsc->role = RSC_ROLE_STOPPED; + clear_past_failure = TRUE; + + } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) { + rsc->role = RSC_ROLE_MASTER; + clear_past_failure = TRUE; + + } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) { + /* Demote from Master does not clear an error */ + rsc->role = RSC_ROLE_SLAVE; + + } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) { + rsc->role = RSC_ROLE_STARTED; + clear_past_failure = TRUE; + + } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) { + /* + * The normal sequence is (now): migrate_to(Src) -> migrate_from(Tgt) -> stop(Src) + * + * So if a migrate_to is followed by a stop, then we dont need to care what + * happended on the target node + * + * Without the stop, we need to look for a successful migrate_from. + * This would also imply we're no longer running on the source + * + * Without the stop, and without a migrate_from op we make sure the resource + * gets stopped on both source and target (assuming the target is up) + * + */ + int stop_id = 0; + xmlNode *stop_op = + find_lrm_op(rsc->id, CRMD_ACTION_STOP, node->details->id, NULL, data_set); + + if (stop_op) { + crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id); + } + + if (stop_op == NULL || stop_id < task_id) { + int from_rc = 0, from_status = 0; + const char *migrate_source = + crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE); + const char *migrate_target = + crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET); + + node_t *target = pe_find_node(data_set->nodes, migrate_target); + xmlNode *migrate_from = + find_lrm_op(rsc->id, CRMD_ACTION_MIGRATED, migrate_target, migrate_source, + data_set); + + rsc->role = RSC_ROLE_STARTED; /* can be master? */ + if (migrate_from) { + crm_element_value_int(migrate_from, XML_LRM_ATTR_RC, &from_rc); + crm_element_value_int(migrate_from, XML_LRM_ATTR_OPSTATUS, &from_status); + crm_trace("%s op on %s exited with status=%d, rc=%d", + ID(migrate_from), migrate_target, from_status, from_rc); + } + + if (migrate_from && from_rc == EXECRA_OK && from_status == LRM_OP_DONE) { + crm_trace("Detected dangling migration op: %s on %s", ID(xml_op), + migrate_source); + + /* all good + * just need to arrange for the stop action to get sent + * but _without_ affecting the target somehow + */ + rsc->role = RSC_ROLE_STOPPED; + rsc->dangling_migrations = g_list_prepend(rsc->dangling_migrations, node); + + } else if (migrate_from) { /* Failed */ + crm_trace("Marking active on %s %p %d", migrate_target, target, + target->details->online); + if (target && target->details->online) { + native_add_running(rsc, target, data_set); + } + + } else { /* Pending or complete but erased */ + node_t *target = pe_find_node_id(data_set->nodes, migrate_target); + + crm_trace("Marking active on %s %p %d", migrate_target, target, + target->details->online); + if (target && target->details->online) { + /* TODO: One day, figure out how to complete the migration + * For now, consider it active in both locations so it gets stopped everywhere + */ + native_add_running(rsc, target, data_set); + + } else { + /* Consider it failed here - forces a restart, prevents migration */ + set_bit_inplace(rsc->flags, pe_rsc_failed); + } + } + } + + } else if (rsc->role < RSC_ROLE_STARTED) { + /* start, migrate_to and migrate_from will land here */ + crm_debug_3("%s active on %s", rsc->id, node->details->uname); + set_active(rsc); + } + + /* clear any previous failure actions */ + if (clear_past_failure) { + switch (*on_fail) { + case action_fail_block: + case action_fail_stop: + case action_fail_fence: + case action_fail_migrate: + case action_fail_standby: + crm_debug_2("%s.%s is not cleared by a completed stop", + rsc->id, fail2text(*on_fail)); + break; + + case action_fail_ignore: + case action_fail_recover: + *on_fail = action_fail_ignore; + rsc->next_role = RSC_ROLE_UNKNOWN; + } + } + break; + + case LRM_OP_ERROR: + case LRM_OP_TIMEOUT: + case LRM_OP_NOTSUPPORTED: + crm_warn("Processing failed op %s on %s: %s (%d)", + id, node->details->uname, execra_code2string(actual_rc_i), actual_rc_i); + crm_xml_add(xml_op, XML_ATTR_UNAME, node->details->uname); + if ((node->details->shutdown == FALSE) || (node->details->online == TRUE)) { + add_node_copy(data_set->failed, xml_op); + } + + if (*on_fail < action->on_fail) { + *on_fail = action->on_fail; + } + + if (safe_str_eq(task, CRMD_ACTION_STOP)) { + resource_location(rsc, node, -INFINITY, "__stop_fail__", data_set); + + } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) { + int stop_id = 0; + int migrate_id = 0; + const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE); + const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET); + + xmlNode *stop_op = + find_lrm_op(rsc->id, CRMD_ACTION_STOP, migrate_source, NULL, data_set); + xmlNode *migrate_op = + find_lrm_op(rsc->id, CRMD_ACTION_MIGRATE, migrate_source, migrate_target, + data_set); + + if (stop_op) { + crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id); + } + if (migrate_op) { + crm_element_value_int(migrate_op, XML_LRM_ATTR_CALLID, &migrate_id); + } + + /* Get our state right */ + rsc->role = RSC_ROLE_STARTED; /* can be master? */ + + if (stop_op == NULL || stop_id < migrate_id) { + node_t *source = pe_find_node(data_set->nodes, migrate_source); + + if (source && source->details->online) { + native_add_running(rsc, source, data_set); + } + } + + } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) { + int stop_id = 0; + int migrate_id = 0; + const char *migrate_source = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_SOURCE); + const char *migrate_target = crm_element_value(xml_op, XML_LRM_ATTR_MIGRATE_TARGET); + + xmlNode *stop_op = + find_lrm_op(rsc->id, CRMD_ACTION_STOP, migrate_target, NULL, data_set); + xmlNode *migrate_op = + find_lrm_op(rsc->id, CRMD_ACTION_MIGRATED, migrate_target, migrate_source, + data_set); + + if (stop_op) { + crm_element_value_int(stop_op, XML_LRM_ATTR_CALLID, &stop_id); + } + if (migrate_op) { + crm_element_value_int(migrate_op, XML_LRM_ATTR_CALLID, &migrate_id); + } + + /* Get our state right */ + rsc->role = RSC_ROLE_STARTED; /* can be master? */ + + if (stop_op == NULL || stop_id < migrate_id) { + node_t *target = pe_find_node(data_set->nodes, migrate_target); + + crm_trace("Stop: %p %d, Migrated: %p %d", stop_op, stop_id, migrate_op, + migrate_id); + if (target && target->details->online) { + native_add_running(rsc, target, data_set); + } + + } else if (migrate_op == NULL) { + /* Make sure it gets cleaned up, the stop may pre-date the migrate_from */ + rsc->dangling_migrations = g_list_prepend(rsc->dangling_migrations, node); + } + + } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) { + rsc->role = RSC_ROLE_MASTER; + + } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) { + /* + * staying in role=master ends up putting the PE/TE into a loop + * setting role=slave is not dangerous because no master will be + * promoted until the failed resource has been fully stopped + */ + crm_warn("Forcing %s to stop after a failed demote action", rsc->id); + rsc->next_role = RSC_ROLE_STOPPED; + rsc->role = RSC_ROLE_SLAVE; + + } else if (compare_version("2.0", op_version) > 0 + && safe_str_eq(task, CRMD_ACTION_START)) { + crm_warn("Compatibility handling for failed op %s on %s", id, node->details->uname); + resource_location(rsc, node, -INFINITY, "__legacy_start__", data_set); + } + + if (rsc->role < RSC_ROLE_STARTED) { + set_active(rsc); + } + + crm_debug_2("Resource %s: role=%s, unclean=%s, on_fail=%s, fail_role=%s", + rsc->id, role2text(rsc->role), + node->details->unclean ? "true" : "false", + fail2text(action->on_fail), role2text(action->fail_role)); + + if (action->fail_role != RSC_ROLE_STARTED && rsc->next_role < action->fail_role) { + rsc->next_role = action->fail_role; + } + + if (action->fail_role == RSC_ROLE_STOPPED) { + int score = -INFINITY; + + crm_err("Making sure %s doesn't come up again", rsc->id); + /* make sure it doesnt come up again */ + g_hash_table_destroy(rsc->allowed_nodes); + rsc->allowed_nodes = node_hash_from_list(data_set->nodes); + g_hash_table_foreach(rsc->allowed_nodes, set_node_score, &score); + } + + pe_free_action(action); + action = NULL; + break; + case LRM_OP_CANCELLED: + /* do nothing?? */ + pe_err("Dont know what to do for cancelled ops yet"); + break; } done: - crm_debug_3("Resource %s after %s: role=%s", - rsc->id, task, role2text(rsc->role)); + crm_debug_3("Resource %s after %s: role=%s", rsc->id, task, role2text(rsc->role)); pe_free_action(action); - + return TRUE; } gboolean -add_node_attrs(xmlNode *xml_obj, node_t *node, gboolean overwrite, pe_working_set_t *data_set) +add_node_attrs(xmlNode * xml_obj, node_t * node, gboolean overwrite, pe_working_set_t * data_set) { g_hash_table_insert(node->details->attrs, - crm_strdup("#"XML_ATTR_UNAME), - crm_strdup(node->details->uname)); + crm_strdup("#" XML_ATTR_UNAME), crm_strdup(node->details->uname)); g_hash_table_insert(node->details->attrs, - crm_strdup("#"XML_ATTR_ID), - crm_strdup(node->details->id)); - if(safe_str_eq(node->details->id, data_set->dc_uuid)) { - data_set->dc_node = node; - node->details->is_dc = TRUE; - g_hash_table_insert(node->details->attrs, - crm_strdup("#"XML_ATTR_DC), - crm_strdup(XML_BOOLEAN_TRUE)); + crm_strdup("#" XML_ATTR_ID), crm_strdup(node->details->id)); + if (safe_str_eq(node->details->id, data_set->dc_uuid)) { + data_set->dc_node = node; + node->details->is_dc = TRUE; + g_hash_table_insert(node->details->attrs, + crm_strdup("#" XML_ATTR_DC), crm_strdup(XML_BOOLEAN_TRUE)); } else { - g_hash_table_insert(node->details->attrs, - crm_strdup("#"XML_ATTR_DC), - crm_strdup(XML_BOOLEAN_FALSE)); + g_hash_table_insert(node->details->attrs, + crm_strdup("#" XML_ATTR_DC), crm_strdup(XML_BOOLEAN_FALSE)); } - - unpack_instance_attributes( - data_set->input, xml_obj, XML_TAG_ATTR_SETS, NULL, - node->details->attrs, NULL, overwrite, data_set->now); + + unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_ATTR_SETS, NULL, + node->details->attrs, NULL, overwrite, data_set->now); return TRUE; } static GListPtr -extract_operations(const char *node, const char *rsc, xmlNode *rsc_entry, gboolean active_filter) -{ +extract_operations(const char *node, const char *rsc, xmlNode * rsc_entry, gboolean active_filter) +{ int counter = -1; int stop_index = -1; int start_index = -1; xmlNode *rsc_op = NULL; - + GListPtr gIter = NULL; GListPtr op_list = NULL; GListPtr sorted_op_list = NULL; /* extract operations */ op_list = NULL; sorted_op_list = NULL; - - for(rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { - if(crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { - crm_xml_add(rsc_op, "resource", rsc); - crm_xml_add(rsc_op, XML_ATTR_UNAME, node); - op_list = g_list_prepend(op_list, rsc_op); - } - } - - if(op_list == NULL) { - /* if there are no operations, there is nothing to do */ - return NULL; - } - + + for (rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { + if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { + crm_xml_add(rsc_op, "resource", rsc); + crm_xml_add(rsc_op, XML_ATTR_UNAME, node); + op_list = g_list_prepend(op_list, rsc_op); + } + } + + if (op_list == NULL) { + /* if there are no operations, there is nothing to do */ + return NULL; + } + sorted_op_list = g_list_sort(op_list, sort_op_by_callid); - - /* create active recurring operations as optional */ - if(active_filter == FALSE) { - return sorted_op_list; + + /* create active recurring operations as optional */ + if (active_filter == FALSE) { + return sorted_op_list; } - + op_list = NULL; - + calculate_active_ops(sorted_op_list, &start_index, &stop_index); - for(gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { - xmlNode *rsc_op = (xmlNode*)gIter->data; - counter++; - - if(start_index < stop_index) { - crm_debug_4("Skipping %s: not active", ID(rsc_entry)); - break; - - } else if(counter < start_index) { - crm_debug_4("Skipping %s: old", ID(rsc_op)); - continue; - } - op_list = g_list_append(op_list, rsc_op); - } - + for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { + xmlNode *rsc_op = (xmlNode *) gIter->data; + + counter++; + + if (start_index < stop_index) { + crm_debug_4("Skipping %s: not active", ID(rsc_entry)); + break; + + } else if (counter < start_index) { + crm_debug_4("Skipping %s: old", ID(rsc_op)); + continue; + } + op_list = g_list_append(op_list, rsc_op); + } + g_list_free(sorted_op_list); return op_list; } -GListPtr find_operations( - const char *rsc, const char *node, gboolean active_filter, pe_working_set_t *data_set) +GListPtr +find_operations(const char *rsc, const char *node, gboolean active_filter, + pe_working_set_t * data_set) { GListPtr output = NULL; GListPtr intermediate = NULL; xmlNode *tmp = NULL; xmlNode *status = find_xml_node(data_set->input, XML_CIB_TAG_STATUS, TRUE); const char *uname = NULL; node_t *this_node = NULL; - + xmlNode *node_state = NULL; - for(node_state = __xml_first_child(status); node_state != NULL; node_state = __xml_next(node_state)) { - if(crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) { - uname = crm_element_value(node_state, XML_ATTR_UNAME); - if(node != NULL && safe_str_neq(uname, node)) { - continue; - } - - this_node = pe_find_node(data_set->nodes, uname); - CRM_CHECK(this_node != NULL, continue); - - determine_online_status(node_state, this_node, data_set); - - if(this_node->details->online || is_set(data_set->flags, pe_flag_stonith_enabled)) { - /* offline nodes run no resources... - * unless stonith is enabled in which case we need to - * make sure rsc start events happen after the stonith - */ - xmlNode *lrm_rsc = NULL; - tmp = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); - tmp = find_xml_node(tmp, XML_LRM_TAG_RESOURCES, FALSE); - - for(lrm_rsc = __xml_first_child(tmp); lrm_rsc != NULL; lrm_rsc = __xml_next(lrm_rsc)) { - if(crm_str_eq((const char *)lrm_rsc->name, XML_LRM_TAG_RESOURCE, TRUE)) { - - const char *rsc_id = crm_element_value(lrm_rsc, XML_ATTR_ID); - if(rsc != NULL && safe_str_neq(rsc_id, rsc)) { - continue; - } - - intermediate = extract_operations(uname, rsc_id, lrm_rsc, active_filter); - output = g_list_concat(output, intermediate); - } - } - } - } + + for (node_state = __xml_first_child(status); node_state != NULL; + node_state = __xml_next(node_state)) { + if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) { + uname = crm_element_value(node_state, XML_ATTR_UNAME); + if (node != NULL && safe_str_neq(uname, node)) { + continue; + } + + this_node = pe_find_node(data_set->nodes, uname); + CRM_CHECK(this_node != NULL, continue); + + determine_online_status(node_state, this_node, data_set); + + if (this_node->details->online || is_set(data_set->flags, pe_flag_stonith_enabled)) { + /* offline nodes run no resources... + * unless stonith is enabled in which case we need to + * make sure rsc start events happen after the stonith + */ + xmlNode *lrm_rsc = NULL; + + tmp = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); + tmp = find_xml_node(tmp, XML_LRM_TAG_RESOURCES, FALSE); + + for (lrm_rsc = __xml_first_child(tmp); lrm_rsc != NULL; + lrm_rsc = __xml_next(lrm_rsc)) { + if (crm_str_eq((const char *)lrm_rsc->name, XML_LRM_TAG_RESOURCE, TRUE)) { + + const char *rsc_id = crm_element_value(lrm_rsc, XML_ATTR_ID); + + if (rsc != NULL && safe_str_neq(rsc_id, rsc)) { + continue; + } + + intermediate = extract_operations(uname, rsc_id, lrm_rsc, active_filter); + output = g_list_concat(output, intermediate); + } + } + } + } } return output; } diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index e8011501dc..c4e0ac0ed5 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -1,1370 +1,1373 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 pe_working_set_t *pe_dataset = NULL; -extern xmlNode *get_object_root(const char *object_type,xmlNode *the_root); +extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root); void print_str_str(gpointer key, gpointer value, gpointer user_data); gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data); -void unpack_operation( - action_t *action, xmlNode *xml_obj, pe_working_set_t* data_set); +void unpack_operation(action_t * action, xmlNode * xml_obj, pe_working_set_t * data_set); node_t * -node_copy(node_t *this_node) +node_copy(node_t * this_node) { - node_t *new_node = NULL; + node_t *new_node = NULL; CRM_CHECK(this_node != NULL, return NULL); crm_malloc0(new_node, sizeof(node_t)); CRM_ASSERT(new_node != NULL); - - crm_debug_5("Copying %p (%s) to %p", - this_node, this_node->details->uname, new_node); - - new_node->weight = this_node->weight; - new_node->fixed = this_node->fixed; - new_node->details = this_node->details; - + + crm_debug_5("Copying %p (%s) to %p", this_node, this_node->details->uname, new_node); + + new_node->weight = this_node->weight; + new_node->fixed = this_node->fixed; + new_node->details = this_node->details; + return new_node; } /* any node in list1 or list2 and not in the other gets a score of -INFINITY */ void -node_list_exclude(GHashTable *hash, GListPtr list, gboolean merge_scores) +node_list_exclude(GHashTable * hash, GListPtr list, gboolean merge_scores) { GHashTable *result = hash; node_t *other_node = NULL; GListPtr gIter = list; - + GHashTableIter iter; node_t *node = NULL; - g_hash_table_iter_init (&iter, hash); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - - other_node = pe_find_node_id(list, node->details->id); - if(other_node == NULL) { - node->weight = -INFINITY; - } else if(merge_scores) { - node->weight = merge_weights(node->weight, other_node->weight); - } - } - - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - - other_node = pe_hash_table_lookup(result, node->details->id); - - if(other_node == NULL) { - node_t *new_node = node_copy(node); - new_node->weight = -INFINITY; - g_hash_table_insert(result, (gpointer)new_node->details->id, new_node); - } + + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + + other_node = pe_find_node_id(list, node->details->id); + if (other_node == NULL) { + node->weight = -INFINITY; + } else if (merge_scores) { + node->weight = merge_weights(node->weight, other_node->weight); + } + } + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + other_node = pe_hash_table_lookup(result, node->details->id); + + if (other_node == NULL) { + node_t *new_node = node_copy(node); + + new_node->weight = -INFINITY; + g_hash_table_insert(result, (gpointer) new_node->details->id, new_node); + } } } GHashTable * node_hash_from_list(GListPtr list) { GListPtr gIter = list; - GHashTable *result = g_hash_table_new_full( - crm_str_hash,g_str_equal, NULL, g_hash_destroy_str); + GHashTable *result = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + node_t *n = node_copy(node); - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - node_t *n = node_copy(node); - - g_hash_table_insert(result, (gpointer)n->details->id, n); + g_hash_table_insert(result, (gpointer) n->details->id, n); } return result; } -GListPtr +GListPtr node_list_dup(GListPtr list1, gboolean reset, gboolean filter) { GListPtr result = NULL; GListPtr gIter = list1; - for(; gIter != NULL; gIter = gIter->next) { - node_t *new_node = NULL; - node_t *this_node = (node_t*)gIter->data; - + for (; gIter != NULL; gIter = gIter->next) { + node_t *new_node = NULL; + node_t *this_node = (node_t *) gIter->data; - if(filter && this_node->weight < 0) { - continue; - } - - new_node = node_copy(this_node); - if(reset) { - new_node->weight = 0; - } - if(new_node != NULL) { - result = g_list_prepend(result, new_node); - } + if (filter && this_node->weight < 0) { + continue; + } + + new_node = node_copy(this_node); + if (reset) { + new_node->weight = 0; + } + if (new_node != NULL) { + result = g_list_prepend(result, new_node); + } } return result; } static gint sort_node_uname(gconstpointer a, gconstpointer b) { const node_t *node_a = a; const node_t *node_b = b; + return strcmp(node_a->details->uname, node_b->details->uname); } -void dump_node_scores_worker(int level, const char *file, const char *function, int line, - resource_t *rsc, const char *comment, GHashTable *nodes) +void +dump_node_scores_worker(int level, const char *file, const char *function, int line, + resource_t * rsc, const char *comment, GHashTable * nodes) { GHashTable *hash = nodes; GHashTableIter iter; node_t *node = NULL; - if(rsc) { - hash = rsc->allowed_nodes; - } - - if(rsc && is_set(rsc->flags, pe_rsc_orphan)) { - /* Don't show the allocation scores for orphans */ - return; - } - - if(level == 0) { - /* For now we want this in sorted order to keep the regression tests happy */ - GListPtr gIter = NULL; - GListPtr list = g_hash_table_get_values(hash); - list = g_list_sort(list, sort_node_uname); - - gIter = list; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - char *score = score2char(node->weight); - - if(rsc) { - printf("%s: %s allocation score on %s: %s\n", - comment, rsc->id, node->details->uname, score); - } else { - printf("%s: %s = %s\n", comment, node->details->uname, score); - } - crm_free(score); - } - - g_list_free(list); - - } else if(hash) { - g_hash_table_iter_init (&iter, hash); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - char *score = score2char(node->weight); - if(rsc) { - do_crm_log_alias(level, file, function, line, "%s: %s allocation score on %s: %s", - comment, rsc->id, node->details->uname, score); - } else { - do_crm_log_alias(level, file, function, line, "%s: %s = %s", comment, node->details->uname, score); - } - crm_free(score); - } - } - - if(rsc && rsc->children) { - GListPtr gIter = NULL; - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - dump_node_scores_worker(level, file, function, line, child, comment, nodes); - } + if (rsc) { + hash = rsc->allowed_nodes; + } + + if (rsc && is_set(rsc->flags, pe_rsc_orphan)) { + /* Don't show the allocation scores for orphans */ + return; + } + + if (level == 0) { + /* For now we want this in sorted order to keep the regression tests happy */ + GListPtr gIter = NULL; + GListPtr list = g_hash_table_get_values(hash); + + list = g_list_sort(list, sort_node_uname); + + gIter = list; + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + char *score = score2char(node->weight); + + if (rsc) { + printf("%s: %s allocation score on %s: %s\n", + comment, rsc->id, node->details->uname, score); + } else { + printf("%s: %s = %s\n", comment, node->details->uname, score); + } + crm_free(score); + } + + g_list_free(list); + + } else if (hash) { + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + char *score = score2char(node->weight); + + if (rsc) { + do_crm_log_alias(level, file, function, line, "%s: %s allocation score on %s: %s", + comment, rsc->id, node->details->uname, score); + } else { + do_crm_log_alias(level, file, function, line, "%s: %s = %s", comment, + node->details->uname, score); + } + crm_free(score); + } + } + + if (rsc && rsc->children) { + GListPtr gIter = NULL; + + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + dump_node_scores_worker(level, file, function, line, child, comment, nodes); + } } } static void append_dump_text(gpointer key, gpointer value, gpointer user_data) { char **dump_text = user_data; int len = 0; char *new_text = NULL; len = strlen(*dump_text) + strlen(" ") + strlen(key) + strlen("=") + strlen(value) + 1; crm_malloc0(new_text, len); sprintf(new_text, "%s %s=%s", *dump_text, (char *)key, (char *)value); crm_free(*dump_text); *dump_text = new_text; } void -dump_node_capacity(int level, const char *comment, node_t *node) +dump_node_capacity(int level, const char *comment, node_t * node) { int len = 0; char *dump_text = NULL; len = strlen(comment) + strlen(": ") + strlen(node->details->uname) + strlen(" capacity:") + 1; crm_malloc0(dump_text, len); sprintf(dump_text, "%s: %s capacity:", comment, node->details->uname); - + g_hash_table_foreach(node->details->utilization, append_dump_text, &dump_text); - if(level == 0) { - fprintf(stdout, "%s\n", dump_text); + if (level == 0) { + fprintf(stdout, "%s\n", dump_text); } else { - do_crm_log_unlikely(level, "%s", dump_text); + do_crm_log_unlikely(level, "%s", dump_text); } crm_free(dump_text); } void -dump_rsc_utilization(int level, const char *comment, resource_t *rsc, node_t *node) +dump_rsc_utilization(int level, const char *comment, resource_t * rsc, node_t * node) { int len = 0; char *dump_text = NULL; len = strlen(comment) + strlen(": ") + strlen(rsc->id) + strlen(" utilization on ") - + strlen(node->details->uname) + strlen(":") + 1; + + strlen(node->details->uname) + strlen(":") + 1; crm_malloc0(dump_text, len); sprintf(dump_text, "%s: %s utilization on %s:", comment, rsc->id, node->details->uname); g_hash_table_foreach(rsc->utilization, append_dump_text, &dump_text); - if(level == 0) { - fprintf(stdout, "%s\n", dump_text); + if (level == 0) { + fprintf(stdout, "%s\n", dump_text); } else { - do_crm_log_unlikely(level, "%s", dump_text); + do_crm_log_unlikely(level, "%s", dump_text); } crm_free(dump_text); } -gint sort_rsc_index(gconstpointer a, gconstpointer b) +gint +sort_rsc_index(gconstpointer a, gconstpointer b) { - const resource_t *resource1 = (const resource_t*)a; - const resource_t *resource2 = (const resource_t*)b; + const resource_t *resource1 = (const resource_t *)a; + const resource_t *resource2 = (const resource_t *)b; - if(a == NULL && b == NULL) { return 0; } - if(a == NULL) { return 1; } - if(b == NULL) { return -1; } - - if(resource1->sort_index > resource2->sort_index) { - return -1; + if (a == NULL && b == NULL) { + return 0; + } + if (a == NULL) { + return 1; } - - if(resource1->sort_index < resource2->sort_index) { - return 1; + if (b == NULL) { + return -1; + } + + if (resource1->sort_index > resource2->sort_index) { + return -1; + } + + if (resource1->sort_index < resource2->sort_index) { + return 1; } return 0; } -gint sort_rsc_priority(gconstpointer a, gconstpointer b) +gint +sort_rsc_priority(gconstpointer a, gconstpointer b) { - const resource_t *resource1 = (const resource_t*)a; - const resource_t *resource2 = (const resource_t*)b; + const resource_t *resource1 = (const resource_t *)a; + const resource_t *resource2 = (const resource_t *)b; - if(a == NULL && b == NULL) { return 0; } - if(a == NULL) { return 1; } - if(b == NULL) { return -1; } - - if(resource1->priority > resource2->priority) { - return -1; + if (a == NULL && b == NULL) { + return 0; } - - if(resource1->priority < resource2->priority) { - return 1; + if (a == NULL) { + return 1; + } + if (b == NULL) { + return -1; + } + + if (resource1->priority > resource2->priority) { + return -1; + } + + if (resource1->priority < resource2->priority) { + return 1; } return 0; } action_t * -custom_action(resource_t *rsc, char *key, const char *task, - node_t *on_node, gboolean optional, gboolean save_action, - pe_working_set_t *data_set) +custom_action(resource_t * rsc, char *key, const char *task, + node_t * on_node, gboolean optional, gboolean save_action, + pe_working_set_t * data_set) { action_t *action = NULL; GListPtr possible_matches = NULL; + CRM_CHECK(key != NULL, return NULL); CRM_CHECK(task != NULL, return NULL); - if(save_action && rsc != NULL) { - possible_matches = find_actions(rsc->actions, key, on_node); + if (save_action && rsc != NULL) { + possible_matches = find_actions(rsc->actions, key, on_node); } - - if(possible_matches != NULL) { - crm_free(key); - - if(g_list_length(possible_matches) > 1) { - pe_warn("Action %s for %s on %s exists %d times", - task, rsc?rsc->id:"", - on_node?on_node->details->uname:"", - g_list_length(possible_matches)); - } - - action = g_list_nth_data(possible_matches, 0); - crm_debug_4("Found existing action (%d) %s for %s on %s", - action->id, task, rsc?rsc->id:"", - on_node?on_node->details->uname:""); - g_list_free(possible_matches); - } - - if(action == NULL) { - if(save_action) { - crm_debug_4("Creating%s action %d: %s for %s on %s", - optional?"":" manditory", data_set->action_id, key, rsc?rsc->id:"", - on_node?on_node->details->uname:""); - } - - crm_malloc0(action, sizeof(action_t)); - if(save_action) { - action->id = data_set->action_id++; - } else { - action->id = 0; - } - action->rsc = rsc; - CRM_ASSERT(task != NULL); - action->task = crm_strdup(task); - if(on_node) { - action->node = node_copy(on_node); - } - action->uuid = key; - - set_bit_inplace(action->flags, pe_action_failure_is_fatal); - set_bit_inplace(action->flags, pe_action_runnable); - if(optional) { - set_bit_inplace(action->flags, pe_action_optional); - } else { - clear_bit_inplace(action->flags, pe_action_optional); - } + + if (possible_matches != NULL) { + crm_free(key); + + if (g_list_length(possible_matches) > 1) { + pe_warn("Action %s for %s on %s exists %d times", + task, rsc ? rsc->id : "", + on_node ? on_node->details->uname : "", g_list_length(possible_matches)); + } + + action = g_list_nth_data(possible_matches, 0); + crm_debug_4("Found existing action (%d) %s for %s on %s", + action->id, task, rsc ? rsc->id : "", + on_node ? on_node->details->uname : ""); + g_list_free(possible_matches); + } + + if (action == NULL) { + if (save_action) { + crm_debug_4("Creating%s action %d: %s for %s on %s", + optional ? "" : " manditory", data_set->action_id, key, + rsc ? rsc->id : "", on_node ? on_node->details->uname : ""); + } + + crm_malloc0(action, sizeof(action_t)); + if (save_action) { + action->id = data_set->action_id++; + } else { + action->id = 0; + } + action->rsc = rsc; + CRM_ASSERT(task != NULL); + action->task = crm_strdup(task); + if (on_node) { + action->node = node_copy(on_node); + } + action->uuid = key; + + set_bit_inplace(action->flags, pe_action_failure_is_fatal); + set_bit_inplace(action->flags, pe_action_runnable); + if (optional) { + set_bit_inplace(action->flags, pe_action_optional); + } else { + clear_bit_inplace(action->flags, pe_action_optional); + } /* Implied by crm_malloc0()... action->actions_before = NULL; action->actions_after = NULL; action->pseudo = FALSE; action->dumped = FALSE; action->processed = FALSE; action->seen_count = 0; */ - - action->extra = g_hash_table_new_full( - crm_str_hash, g_str_equal, free, free); - - action->meta = g_hash_table_new_full( - crm_str_hash, g_str_equal, free, free); - - if(save_action) { - data_set->actions = g_list_prepend( - data_set->actions, action); - } - - if(rsc != NULL) { - action->op_entry = find_rsc_op_entry(rsc, key); - - unpack_operation( - action, action->op_entry, data_set); - - if(save_action) { - rsc->actions = g_list_prepend( - rsc->actions, action); - } - } - - if(save_action) { - crm_debug_4("Action %d created", action->id); - } - } - - if(optional == FALSE && (action->flags & pe_action_optional)) { - crm_debug_2("Action %d (%s) marked manditory", - action->id, action->uuid); - clear_bit_inplace(action->flags, pe_action_optional); - } - - if(rsc != NULL) { - enum action_tasks a_task = text2task(action->task); - int warn_level = LOG_DEBUG_3; - if(save_action) { - warn_level = LOG_WARNING; - } - - if(is_set(action->flags, pe_action_have_node_attrs) == FALSE - && action->node != NULL - && action->op_entry != NULL) { - set_bit_inplace(action->flags, pe_action_have_node_attrs); - unpack_instance_attributes( - data_set->input, action->op_entry, XML_TAG_ATTR_SETS, - action->node->details->attrs, - action->extra, NULL, FALSE, data_set->now); - } - - if(is_set(action->flags, pe_action_pseudo)) { - /* leave untouched */ - - } else if(action->node == NULL) { - clear_bit_inplace(action->flags, pe_action_runnable); - - } else if(is_not_set(rsc->flags, pe_rsc_managed) - && g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL) == NULL) { - do_crm_log_unlikely(LOG_DEBUG, "Action %s (unmanaged)", - action->uuid); - set_bit_inplace(action->flags, pe_action_optional); + + action->extra = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free); + + action->meta = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free); + + if (save_action) { + data_set->actions = g_list_prepend(data_set->actions, action); + } + + if (rsc != NULL) { + action->op_entry = find_rsc_op_entry(rsc, key); + + unpack_operation(action, action->op_entry, data_set); + + if (save_action) { + rsc->actions = g_list_prepend(rsc->actions, action); + } + } + + if (save_action) { + crm_debug_4("Action %d created", action->id); + } + } + + if (optional == FALSE && (action->flags & pe_action_optional)) { + crm_debug_2("Action %d (%s) marked manditory", action->id, action->uuid); + clear_bit_inplace(action->flags, pe_action_optional); + } + + if (rsc != NULL) { + enum action_tasks a_task = text2task(action->task); + int warn_level = LOG_DEBUG_3; + + if (save_action) { + warn_level = LOG_WARNING; + } + + if (is_set(action->flags, pe_action_have_node_attrs) == FALSE + && action->node != NULL && action->op_entry != NULL) { + set_bit_inplace(action->flags, pe_action_have_node_attrs); + unpack_instance_attributes(data_set->input, action->op_entry, XML_TAG_ATTR_SETS, + action->node->details->attrs, + action->extra, NULL, FALSE, data_set->now); + } + + if (is_set(action->flags, pe_action_pseudo)) { + /* leave untouched */ + + } else if (action->node == NULL) { + clear_bit_inplace(action->flags, pe_action_runnable); + + } else if (is_not_set(rsc->flags, pe_rsc_managed) + && g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL) == NULL) { + do_crm_log_unlikely(LOG_DEBUG, "Action %s (unmanaged)", action->uuid); + set_bit_inplace(action->flags, pe_action_optional); /* action->runnable = FALSE; */ - } else if(action->node->details->online == FALSE) { - clear_bit_inplace(action->flags, pe_action_runnable); - do_crm_log(warn_level, "Action %s on %s is unrunnable (offline)", - action->uuid, action->node->details->uname); - if(is_set(action->rsc->flags, pe_rsc_managed) - && save_action - && a_task == stop_rsc) { - do_crm_log(warn_level, "Marking node %s unclean", - action->node->details->uname); - action->node->details->unclean = TRUE; - } - - } else if(action->node->details->pending) { - clear_bit_inplace(action->flags, pe_action_runnable); - do_crm_log(warn_level, "Action %s on %s is unrunnable (pending)", - action->uuid, action->node->details->uname); - - } else if(action->needs == rsc_req_nothing) { - crm_debug_3("Action %s doesnt require anything", - action->uuid); - set_bit_inplace(action->flags, pe_action_runnable); + } else if (action->node->details->online == FALSE) { + clear_bit_inplace(action->flags, pe_action_runnable); + do_crm_log(warn_level, "Action %s on %s is unrunnable (offline)", + action->uuid, action->node->details->uname); + if (is_set(action->rsc->flags, pe_rsc_managed) + && save_action && a_task == stop_rsc) { + do_crm_log(warn_level, "Marking node %s unclean", action->node->details->uname); + action->node->details->unclean = TRUE; + } + + } else if (action->node->details->pending) { + clear_bit_inplace(action->flags, pe_action_runnable); + do_crm_log(warn_level, "Action %s on %s is unrunnable (pending)", + action->uuid, action->node->details->uname); + + } else if (action->needs == rsc_req_nothing) { + crm_debug_3("Action %s doesnt require anything", action->uuid); + set_bit_inplace(action->flags, pe_action_runnable); #if 0 - /* - * No point checking this - * - if we dont have quorum we cant stonith anyway - */ - } else if(action->needs == rsc_req_stonith) { - crm_debug_3("Action %s requires only stonith", action->uuid); - action->runnable = TRUE; + /* + * No point checking this + * - if we dont have quorum we cant stonith anyway + */ + } else if (action->needs == rsc_req_stonith) { + crm_debug_3("Action %s requires only stonith", action->uuid); + action->runnable = TRUE; #endif - } else if(is_set(data_set->flags, pe_flag_have_quorum) == FALSE - && data_set->no_quorum_policy == no_quorum_stop) { - clear_bit_inplace(action->flags, pe_action_runnable); - crm_debug("%s\t%s (cancelled : quorum)", - action->node->details->uname, - action->uuid); - - } else if(is_set(data_set->flags, pe_flag_have_quorum) == FALSE - && data_set->no_quorum_policy == no_quorum_freeze) { - crm_debug_3("Check resource is already active"); - if(rsc->fns->active(rsc, TRUE) == FALSE) { - clear_bit_inplace(action->flags, pe_action_runnable); - crm_debug("%s\t%s (cancelled : quorum freeze)", - action->node->details->uname, - action->uuid); - } - - } else { - crm_debug_3("Action %s is runnable", action->uuid); - set_bit_inplace(action->flags, pe_action_runnable); - } - - if(save_action) { - switch(a_task) { - case stop_rsc: - set_bit(rsc->flags, pe_rsc_stopping); - break; - case start_rsc: - clear_bit(rsc->flags, pe_rsc_starting); - if(is_set(action->flags, pe_action_runnable)) { - set_bit(rsc->flags, pe_rsc_starting); - } - break; - default: - break; - } - } + } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE + && data_set->no_quorum_policy == no_quorum_stop) { + clear_bit_inplace(action->flags, pe_action_runnable); + crm_debug("%s\t%s (cancelled : quorum)", action->node->details->uname, action->uuid); + + } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE + && data_set->no_quorum_policy == no_quorum_freeze) { + crm_debug_3("Check resource is already active"); + if (rsc->fns->active(rsc, TRUE) == FALSE) { + clear_bit_inplace(action->flags, pe_action_runnable); + crm_debug("%s\t%s (cancelled : quorum freeze)", + action->node->details->uname, action->uuid); + } + + } else { + crm_debug_3("Action %s is runnable", action->uuid); + set_bit_inplace(action->flags, pe_action_runnable); + } + + if (save_action) { + switch (a_task) { + case stop_rsc: + set_bit(rsc->flags, pe_rsc_stopping); + break; + case start_rsc: + clear_bit(rsc->flags, pe_rsc_starting); + if (is_set(action->flags, pe_action_runnable)) { + set_bit(rsc->flags, pe_rsc_starting); + } + break; + default: + break; + } + } } return action; } void -unpack_operation( - action_t *action, xmlNode *xml_obj, pe_working_set_t* data_set) +unpack_operation(action_t * action, xmlNode * xml_obj, pe_working_set_t * data_set) { int value_i = 0; unsigned long long interval = 0; unsigned long long start_delay = 0; char *value_ms = NULL; const char *class = NULL; const char *value = NULL; const char *field = NULL; CRM_CHECK(action->rsc != NULL, return); unpack_instance_attributes(data_set->input, data_set->op_defaults, XML_TAG_META_SETS, NULL, - action->meta, NULL, FALSE, data_set->now); + action->meta, NULL, FALSE, data_set->now); - if(xml_obj) { + if (xml_obj) { xmlAttrPtr xIter = NULL; - for(xIter = xml_obj->properties; xIter; xIter = xIter->next) { + + for (xIter = xml_obj->properties; xIter; xIter = xIter->next) { const char *prop_name = (const char *)xIter->name; const char *prop_value = crm_element_value(xml_obj, prop_name); + g_hash_table_replace(action->meta, crm_strdup(prop_name), crm_strdup(prop_value)); } } - + unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_META_SETS, - NULL, action->meta, NULL, FALSE, data_set->now); - + NULL, action->meta, NULL, FALSE, data_set->now); + unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_ATTR_SETS, - NULL, action->meta, NULL, FALSE, data_set->now); - - g_hash_table_remove(action->meta, "id"); + NULL, action->meta, NULL, FALSE, data_set->now); + + g_hash_table_remove(action->meta, "id"); class = g_hash_table_lookup(action->rsc->meta, "class"); - + value = g_hash_table_lookup(action->meta, "requires"); - if(safe_str_eq(class, "stonith")) { - action->needs = rsc_req_nothing; - value = "nothing (fencing op)"; + if (safe_str_eq(class, "stonith")) { + action->needs = rsc_req_nothing; + value = "nothing (fencing op)"; - } else if(safe_str_eq(value, "nothing")) { - action->needs = rsc_req_nothing; + } else if (safe_str_eq(value, "nothing")) { + action->needs = rsc_req_nothing; - } else if(safe_str_eq(value, "quorum")) { - action->needs = rsc_req_quorum; + } else if (safe_str_eq(value, "quorum")) { + action->needs = rsc_req_quorum; + + } else if (is_set(data_set->flags, pe_flag_stonith_enabled) + && safe_str_eq(value, "fencing")) { + action->needs = rsc_req_stonith; - } else if(is_set(data_set->flags, pe_flag_stonith_enabled) - && safe_str_eq(value, "fencing")) { - action->needs = rsc_req_stonith; - } else { - if(value) { - crm_config_err("Invalid value for %s->requires: %s%s", - action->rsc->id, value, - is_set(data_set->flags, pe_flag_stonith_enabled)?"":" (stonith-enabled=false)"); - } + if (value) { + crm_config_err("Invalid value for %s->requires: %s%s", + action->rsc->id, value, + is_set(data_set->flags, + pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)"); + } - if (safe_str_eq(action->task, CRMD_ACTION_STATUS) - || safe_str_eq(action->task, CRMD_ACTION_NOTIFY)) { - action->needs = rsc_req_nothing; - value = "nothing (default)"; + if (safe_str_eq(action->task, CRMD_ACTION_STATUS) + || safe_str_eq(action->task, CRMD_ACTION_NOTIFY)) { + action->needs = rsc_req_nothing; + value = "nothing (default)"; - } else if (data_set->no_quorum_policy == no_quorum_stop - && safe_str_neq(action->task, CRMD_ACTION_START)) { - action->needs = rsc_req_nothing; - value = "nothing (default)"; + } else if (data_set->no_quorum_policy == no_quorum_stop + && safe_str_neq(action->task, CRMD_ACTION_START)) { + action->needs = rsc_req_nothing; + value = "nothing (default)"; - } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) { - action->needs = rsc_req_stonith; - value = "fencing (default)"; + } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) { + action->needs = rsc_req_stonith; + value = "fencing (default)"; - } else { - action->needs = rsc_req_quorum; - value = "quorum (default)"; - } + } else { + action->needs = rsc_req_quorum; + value = "quorum (default)"; + } } crm_debug_3("\tAction %s requires: %s", action->task, value); value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ON_FAIL); - if(safe_str_eq(action->task, CRMD_ACTION_STOP) - && safe_str_eq(value, "standby")) { - crm_config_err("on-fail=standby is not allowed for stop actions: %s", action->rsc->id); - value = NULL; + if (safe_str_eq(action->task, CRMD_ACTION_STOP) + && safe_str_eq(value, "standby")) { + crm_config_err("on-fail=standby is not allowed for stop actions: %s", action->rsc->id); + value = NULL; } - if(value == NULL) { + if (value == NULL) { - } else if(safe_str_eq(value, "block")) { - action->on_fail = action_fail_block; + } else if (safe_str_eq(value, "block")) { + action->on_fail = action_fail_block; + + } else if (safe_str_eq(value, "fence")) { + action->on_fail = action_fail_fence; + value = "node fencing"; + + if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { + crm_config_err("Specifying on_fail=fence and" " stonith-enabled=false makes no sense"); + action->on_fail = action_fail_stop; + action->fail_role = RSC_ROLE_STOPPED; + value = "stop resource"; + } + + } else if (safe_str_eq(value, "standby")) { + action->on_fail = action_fail_standby; + value = "node standby"; + + } else if (safe_str_eq(value, "ignore") + || safe_str_eq(value, "nothing")) { + action->on_fail = action_fail_ignore; + value = "ignore"; + + } else if (safe_str_eq(value, "migrate")) { + action->on_fail = action_fail_migrate; + value = "force migration"; + + } else if (safe_str_eq(value, "stop")) { + action->on_fail = action_fail_stop; + action->fail_role = RSC_ROLE_STOPPED; + value = "stop resource"; + + } else if (safe_str_eq(value, "restart")) { + action->on_fail = action_fail_recover; + value = "restart (and possibly migrate)"; - } else if(safe_str_eq(value, "fence")) { - action->on_fail = action_fail_fence; - value = "node fencing"; - - if(is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { - crm_config_err("Specifying on_fail=fence and" - " stonith-enabled=false makes no sense"); - action->on_fail = action_fail_stop; - action->fail_role = RSC_ROLE_STOPPED; - value = "stop resource"; - } - - } else if(safe_str_eq(value, "standby")) { - action->on_fail = action_fail_standby; - value = "node standby"; - - } else if(safe_str_eq(value, "ignore") - || safe_str_eq(value, "nothing")) { - action->on_fail = action_fail_ignore; - value = "ignore"; - - } else if(safe_str_eq(value, "migrate")) { - action->on_fail = action_fail_migrate; - value = "force migration"; - - } else if(safe_str_eq(value, "stop")) { - action->on_fail = action_fail_stop; - action->fail_role = RSC_ROLE_STOPPED; - value = "stop resource"; - - } else if(safe_str_eq(value, "restart")) { - action->on_fail = action_fail_recover; - value = "restart (and possibly migrate)"; - } else { - pe_err("Resource %s: Unknown failure type (%s)", - action->rsc->id, value); - value = NULL; + pe_err("Resource %s: Unknown failure type (%s)", action->rsc->id, value); + value = NULL; } - + /* defaults */ - if(value == NULL && safe_str_eq(action->task, CRMD_ACTION_STOP)) { - if(is_set(data_set->flags, pe_flag_stonith_enabled)) { - action->on_fail = action_fail_fence; - value = "resource fence (default)"; - - } else { - action->on_fail = action_fail_block; - value = "resource block (default)"; - } - - } else if(value == NULL) { - action->on_fail = action_fail_recover; - value = "restart (and possibly migrate) (default)"; + if (value == NULL && safe_str_eq(action->task, CRMD_ACTION_STOP)) { + if (is_set(data_set->flags, pe_flag_stonith_enabled)) { + action->on_fail = action_fail_fence; + value = "resource fence (default)"; + + } else { + action->on_fail = action_fail_block; + value = "resource block (default)"; + } + + } else if (value == NULL) { + action->on_fail = action_fail_recover; + value = "restart (and possibly migrate) (default)"; } - + crm_debug_3("\t%s failure handling: %s", action->task, value); value = NULL; - if(xml_obj != NULL) { - value = g_hash_table_lookup(action->meta, "role_after_failure"); + if (xml_obj != NULL) { + value = g_hash_table_lookup(action->meta, "role_after_failure"); } - if(value != NULL && action->fail_role == RSC_ROLE_UNKNOWN) { - action->fail_role = text2role(value); + if (value != NULL && action->fail_role == RSC_ROLE_UNKNOWN) { + action->fail_role = text2role(value); } /* defaults */ - if(action->fail_role == RSC_ROLE_UNKNOWN) { - if(safe_str_eq(action->task, CRMD_ACTION_PROMOTE)) { - action->fail_role = RSC_ROLE_SLAVE; - } else { - action->fail_role = RSC_ROLE_STARTED; - } + if (action->fail_role == RSC_ROLE_UNKNOWN) { + if (safe_str_eq(action->task, CRMD_ACTION_PROMOTE)) { + action->fail_role = RSC_ROLE_SLAVE; + } else { + action->fail_role = RSC_ROLE_STARTED; + } } - crm_debug_3("\t%s failure results in: %s", - action->task, role2text(action->fail_role)); + crm_debug_3("\t%s failure results in: %s", action->task, role2text(action->fail_role)); field = XML_LRM_ATTR_INTERVAL; value = g_hash_table_lookup(action->meta, field); - if(value != NULL) { - interval = crm_get_interval(value); - if(interval > 0) { - value_ms = crm_itoa(interval); - g_hash_table_replace(action->meta, crm_strdup(field), value_ms); - - } else { - g_hash_table_remove(action->meta, field); - } + if (value != NULL) { + interval = crm_get_interval(value); + if (interval > 0) { + value_ms = crm_itoa(interval); + g_hash_table_replace(action->meta, crm_strdup(field), value_ms); + + } else { + g_hash_table_remove(action->meta, field); + } } field = XML_OP_ATTR_START_DELAY; value = g_hash_table_lookup(action->meta, field); - if(value != NULL) { - value_i = crm_get_msec(value); - if(value_i < 0) { - value_i = 0; - } - start_delay = value_i; - value_ms = crm_itoa(value_i); - g_hash_table_replace(action->meta, crm_strdup(field), value_ms); - - } else if(interval > 0 && g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN)) { - char *date_str = NULL; - char *date_str_mutable = NULL; - ha_time_t *origin = NULL; - value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN); - date_str = crm_strdup(value); - date_str_mutable = date_str; - origin = parse_date(&date_str_mutable); - crm_free(date_str); - - if(origin == NULL) { - crm_config_err("Operation %s contained an invalid "XML_OP_ATTR_ORIGIN": %s", - ID(xml_obj), value); - - } else { - ha_time_t *delay = NULL; - int rc = compare_date(origin, data_set->now); - unsigned long long delay_s = 0; - - while(rc < 0) { - add_seconds(origin, interval/1000); - rc = compare_date(origin, data_set->now); - } - - delay = subtract_time(origin, data_set->now); - delay_s = date_in_seconds(delay); - /* log_date(LOG_DEBUG_5, "delay", delay, ha_log_date|ha_log_time|ha_log_local); */ - - crm_info("Calculated a start delay of %llus for %s", delay_s, ID(xml_obj)); - g_hash_table_replace(action->meta, crm_strdup(XML_OP_ATTR_START_DELAY), crm_itoa(delay_s * 1000)); - start_delay = delay_s * 1000; - free_ha_date(origin); - free_ha_date(delay); - } - } - + if (value != NULL) { + value_i = crm_get_msec(value); + if (value_i < 0) { + value_i = 0; + } + start_delay = value_i; + value_ms = crm_itoa(value_i); + g_hash_table_replace(action->meta, crm_strdup(field), value_ms); + + } else if (interval > 0 && g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN)) { + char *date_str = NULL; + char *date_str_mutable = NULL; + ha_time_t *origin = NULL; + + value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN); + date_str = crm_strdup(value); + date_str_mutable = date_str; + origin = parse_date(&date_str_mutable); + crm_free(date_str); + + if (origin == NULL) { + crm_config_err("Operation %s contained an invalid " XML_OP_ATTR_ORIGIN ": %s", + ID(xml_obj), value); + + } else { + ha_time_t *delay = NULL; + int rc = compare_date(origin, data_set->now); + unsigned long long delay_s = 0; + + while (rc < 0) { + add_seconds(origin, interval / 1000); + rc = compare_date(origin, data_set->now); + } + + delay = subtract_time(origin, data_set->now); + delay_s = date_in_seconds(delay); + /* log_date(LOG_DEBUG_5, "delay", delay, ha_log_date|ha_log_time|ha_log_local); */ + + crm_info("Calculated a start delay of %llus for %s", delay_s, ID(xml_obj)); + g_hash_table_replace(action->meta, crm_strdup(XML_OP_ATTR_START_DELAY), + crm_itoa(delay_s * 1000)); + start_delay = delay_s * 1000; + free_ha_date(origin); + free_ha_date(delay); + } + } field = XML_ATTR_TIMEOUT; value = g_hash_table_lookup(action->meta, field); - if(value == NULL) { - value = pe_pref( - data_set->config_hash, "default-action-timeout"); + if (value == NULL) { + value = pe_pref(data_set->config_hash, "default-action-timeout"); } value_i = crm_get_msec(value); - if(value_i < 0) { - value_i = 0; + if (value_i < 0) { + value_i = 0; } value_i += start_delay; value_ms = crm_itoa(value_i); g_hash_table_replace(action->meta, crm_strdup(field), value_ms); } xmlNode * -find_rsc_op_entry(resource_t *rsc, const char *key) +find_rsc_op_entry(resource_t * rsc, const char *key) { int number = 0; gboolean do_retry = TRUE; char *local_key = NULL; const char *name = NULL; const char *value = NULL; const char *interval = NULL; char *match_key = NULL; xmlNode *op = NULL; xmlNode *operation = NULL; retry: - for(operation = __xml_first_child(rsc->ops_xml); operation != NULL; operation = __xml_next(operation)) { - if(crm_str_eq((const char *)operation->name, "op", TRUE)) { - name = crm_element_value(operation, "name"); - interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); - value = crm_element_value(operation, "enabled"); - if(value && crm_is_true(value) == FALSE) { - continue; - } - - number = crm_get_interval(interval); - if(number < 0) { - continue; - } - - match_key = generate_op_key(rsc->id, name, number); - - if(safe_str_eq(key, match_key)) { - op = operation; - } - crm_free(match_key); - - if(op != NULL) { - crm_free(local_key); - return op; - } - } + for (operation = __xml_first_child(rsc->ops_xml); operation != NULL; + operation = __xml_next(operation)) { + if (crm_str_eq((const char *)operation->name, "op", TRUE)) { + name = crm_element_value(operation, "name"); + interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); + value = crm_element_value(operation, "enabled"); + if (value && crm_is_true(value) == FALSE) { + continue; + } + + number = crm_get_interval(interval); + if (number < 0) { + continue; + } + + match_key = generate_op_key(rsc->id, name, number); + + if (safe_str_eq(key, match_key)) { + op = operation; + } + crm_free(match_key); + + if (op != NULL) { + crm_free(local_key); + return op; + } + } } crm_free(local_key); - if(do_retry == FALSE) { - return NULL; + if (do_retry == FALSE) { + return NULL; } - + do_retry = FALSE; - if(strstr(key, CRMD_ACTION_MIGRATE) || strstr(key, CRMD_ACTION_MIGRATED)) { - local_key = generate_op_key(rsc->id, "migrate", 0); - key = local_key; - goto retry; - - } else if(strstr(key, "_notify_")) { - local_key = generate_op_key(rsc->id, "notify", 0); - key = local_key; - goto retry; - } - + if (strstr(key, CRMD_ACTION_MIGRATE) || strstr(key, CRMD_ACTION_MIGRATED)) { + local_key = generate_op_key(rsc->id, "migrate", 0); + key = local_key; + goto retry; + + } else if (strstr(key, "_notify_")) { + local_key = generate_op_key(rsc->id, "notify", 0); + key = local_key; + goto retry; + } + return NULL; } void -print_node(const char *pre_text, node_t *node, gboolean details) -{ - if(node == NULL) { - crm_debug_4("%s%s: ", - pre_text==NULL?"":pre_text, - pre_text==NULL?"":": "); - return; +print_node(const char *pre_text, node_t * node, gboolean details) +{ + if (node == NULL) { + crm_debug_4("%s%s: ", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": "); + return; } crm_debug_4("%s%s%sNode %s: (weight=%d, fixed=%s)", - pre_text==NULL?"":pre_text, - pre_text==NULL?"":": ", - node->details==NULL?"error ":node->details->online?"":"Unavailable/Unclean ", - node->details->uname, - node->weight, - node->fixed?"True":"False"); - - if(details && node != NULL && node->details != NULL) { - char *pe_mutable = crm_strdup("\t\t"); - GListPtr gIter = node->details->running_rsc; - crm_debug_4("\t\t===Node Attributes"); - g_hash_table_foreach(node->details->attrs, - print_str_str, pe_mutable); - crm_free(pe_mutable); - - crm_debug_4("\t\t=== Resources"); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - print_resource(LOG_DEBUG_4, "\t\t", rsc, FALSE); - } + pre_text == NULL ? "" : pre_text, + pre_text == NULL ? "" : ": ", + node->details == + NULL ? "error " : node->details->online ? "" : "Unavailable/Unclean ", + node->details->uname, node->weight, node->fixed ? "True" : "False"); + + if (details && node != NULL && node->details != NULL) { + char *pe_mutable = crm_strdup("\t\t"); + GListPtr gIter = node->details->running_rsc; + + crm_debug_4("\t\t===Node Attributes"); + g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable); + crm_free(pe_mutable); + + crm_debug_4("\t\t=== Resources"); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + print_resource(LOG_DEBUG_4, "\t\t", rsc, FALSE); + } } } /* * Used by the HashTable for-loop */ -void print_str_str(gpointer key, gpointer value, gpointer user_data) +void +print_str_str(gpointer key, gpointer value, gpointer user_data) { crm_debug_4("%s%s %s ==> %s", - user_data==NULL?"":(char*)user_data, - user_data==NULL?"":": ", - (char*)key, - (char*)value); + user_data == NULL ? "" : (char *)user_data, + user_data == NULL ? "" : ": ", (char *)key, (char *)value); } void -print_resource( - int log_level, const char *pre_text, resource_t *rsc, gboolean details) +print_resource(int log_level, const char *pre_text, resource_t * rsc, gboolean details) { long options = pe_print_log; - - if(rsc == NULL) { - do_crm_log(log_level-1, "%s%s: ", - pre_text==NULL?"":pre_text, - pre_text==NULL?"":": "); - return; + + if (rsc == NULL) { + do_crm_log(log_level - 1, "%s%s: ", + pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": "); + return; } - if(details) { - options |= pe_print_details; + if (details) { + options |= pe_print_details; } rsc->fns->print(rsc, pre_text, options, &log_level); } void -pe_free_action(action_t *action) +pe_free_action(action_t * action) { - if(action == NULL) { - return; + if (action == NULL) { + return; } - slist_basic_destroy(action->actions_before);/* action_warpper_t* */ - slist_basic_destroy(action->actions_after); /* action_warpper_t* */ - if(action->extra) { - g_hash_table_destroy(action->extra); + slist_basic_destroy(action->actions_before); /* action_warpper_t* */ + slist_basic_destroy(action->actions_after); /* action_warpper_t* */ + if (action->extra) { + g_hash_table_destroy(action->extra); } - if(action->meta) { - g_hash_table_destroy(action->meta); + if (action->meta) { + g_hash_table_destroy(action->meta); } crm_free(action->task); crm_free(action->uuid); crm_free(action->node); crm_free(action); } GListPtr -find_recurring_actions(GListPtr input, node_t *not_on_node) +find_recurring_actions(GListPtr input, node_t * not_on_node) { const char *value = NULL; GListPtr result = NULL; GListPtr gIter = input; + CRM_CHECK(input != NULL, return NULL); - - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - value = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL); - if(value == NULL) { - /* skip */ - } else if(safe_str_eq(value, "0")) { - /* skip */ - } else if(safe_str_eq(CRMD_ACTION_CANCEL, action->task)) { - /* skip */ - } else if(not_on_node == NULL) { - crm_debug_5("(null) Found: %s", action->uuid); - result = g_list_prepend(result, action); - - } else if(action->node == NULL) { - /* skip */ - } else if(action->node->details != not_on_node->details) { - crm_debug_5("Found: %s", action->uuid); - result = g_list_prepend(result, action); - } + + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + value = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL); + if (value == NULL) { + /* skip */ + } else if (safe_str_eq(value, "0")) { + /* skip */ + } else if (safe_str_eq(CRMD_ACTION_CANCEL, action->task)) { + /* skip */ + } else if (not_on_node == NULL) { + crm_debug_5("(null) Found: %s", action->uuid); + result = g_list_prepend(result, action); + + } else if (action->node == NULL) { + /* skip */ + } else if (action->node->details != not_on_node->details) { + crm_debug_5("Found: %s", action->uuid); + result = g_list_prepend(result, action); + } } return result; } enum action_tasks -get_complex_task(resource_t *rsc, const char *name, gboolean allow_non_atomic) +get_complex_task(resource_t * rsc, const char *name, gboolean allow_non_atomic) { enum action_tasks task = text2task(name); - if(rsc == NULL) { - return task; - - } else if(allow_non_atomic == FALSE || rsc->variant == pe_native) { - switch(task) { - case stopped_rsc: - case started_rsc: - case action_demoted: - case action_promoted: - crm_trace("Folding %s back into its atomic counterpart for %s", name, rsc->id); - return task-1; - break; - default: - break; - } + + if (rsc == NULL) { + return task; + + } else if (allow_non_atomic == FALSE || rsc->variant == pe_native) { + switch (task) { + case stopped_rsc: + case started_rsc: + case action_demoted: + case action_promoted: + crm_trace("Folding %s back into its atomic counterpart for %s", name, rsc->id); + return task - 1; + break; + default: + break; + } } return task; } action_t * -find_first_action(GListPtr input, const char *uuid, const char *task, node_t *on_node) +find_first_action(GListPtr input, const char *uuid, const char *task, node_t * on_node) { GListPtr gIter = NULL; + CRM_CHECK(uuid || task, return NULL); - - for(gIter = input; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - if(uuid != NULL && safe_str_neq(uuid, action->uuid)) { - continue; - - } else if(task != NULL && safe_str_neq(task, action->task)) { - continue; - - } else if(on_node == NULL) { - return action; - - } else if(action->node == NULL) { - continue; - - } else if(on_node->details == action->node->details) { - return action; - } + + for (gIter = input; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (uuid != NULL && safe_str_neq(uuid, action->uuid)) { + continue; + + } else if (task != NULL && safe_str_neq(task, action->task)) { + continue; + + } else if (on_node == NULL) { + return action; + + } else if (action->node == NULL) { + continue; + + } else if (on_node->details == action->node->details) { + return action; + } } return NULL; } GListPtr -find_actions(GListPtr input, const char *key, node_t *on_node) +find_actions(GListPtr input, const char *key, node_t * on_node) { GListPtr gIter = input; GListPtr result = NULL; + CRM_CHECK(key != NULL, return NULL); - - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - crm_debug_5("Matching %s against %s", key, action->uuid); - if(safe_str_neq(key, action->uuid)) { - continue; - - } else if(on_node == NULL) { - result = g_list_prepend(result, action); - - } else if(action->node == NULL) { - /* skip */ - crm_debug_2("While looking for %s action on %s, " - "found an unallocated one. Assigning" - " it to the requested node...", - key, on_node->details->uname); - - action->node = node_copy(on_node); - result = g_list_prepend(result, action); - - } else if(on_node->details == action->node->details) { - result = g_list_prepend(result, action); - } + + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + crm_debug_5("Matching %s against %s", key, action->uuid); + if (safe_str_neq(key, action->uuid)) { + continue; + + } else if (on_node == NULL) { + result = g_list_prepend(result, action); + + } else if (action->node == NULL) { + /* skip */ + crm_debug_2("While looking for %s action on %s, " + "found an unallocated one. Assigning" + " it to the requested node...", key, on_node->details->uname); + + action->node = node_copy(on_node); + result = g_list_prepend(result, action); + + } else if (on_node->details == action->node->details) { + result = g_list_prepend(result, action); + } } return result; } - GListPtr -find_actions_exact(GListPtr input, const char *key, node_t *on_node) +find_actions_exact(GListPtr input, const char *key, node_t * on_node) { GListPtr gIter = input; GListPtr result = NULL; + CRM_CHECK(key != NULL, return NULL); - - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - - crm_debug_5("Matching %s against %s", key, action->uuid); - if(safe_str_neq(key, action->uuid)) { - crm_debug_3("Key mismatch: %s vs. %s", - key, action->uuid); - continue; - - } else if(on_node == NULL || action->node == NULL) { - crm_debug_3("on_node=%p, action->node=%p", - on_node, action->node); - continue; - - } else if(safe_str_eq(on_node->details->id, - action->node->details->id)) { - result = g_list_prepend(result, action); - } - crm_debug_2("Node mismatch: %s vs. %s", - on_node->details->id, action->node->details->id); + + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + crm_debug_5("Matching %s against %s", key, action->uuid); + if (safe_str_neq(key, action->uuid)) { + crm_debug_3("Key mismatch: %s vs. %s", key, action->uuid); + continue; + + } else if (on_node == NULL || action->node == NULL) { + crm_debug_3("on_node=%p, action->node=%p", on_node, action->node); + continue; + + } else if (safe_str_eq(on_node->details->id, action->node->details->id)) { + result = g_list_prepend(result, action); + } + crm_debug_2("Node mismatch: %s vs. %s", on_node->details->id, action->node->details->id); } return result; } static void -resource_node_score(resource_t *rsc, node_t *node, int score, const char *tag) +resource_node_score(resource_t * rsc, node_t * node, int score, const char *tag) { node_t *match = NULL; - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - resource_node_score(child_rsc, node, score, tag); - } + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + resource_node_score(child_rsc, node, score, tag); + } } - - crm_debug_2("Setting %s for %s on %s: %d", - tag, rsc->id, node->details->uname, score); + + crm_debug_2("Setting %s for %s on %s: %d", tag, rsc->id, node->details->uname, score); match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id); - if(match == NULL) { - match = node_copy(node); - match->weight = merge_weights(score, node->weight); - g_hash_table_insert(rsc->allowed_nodes, (gpointer)match->details->id, match); + if (match == NULL) { + match = node_copy(node); + match->weight = merge_weights(score, node->weight); + g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match); } match->weight = merge_weights(match->weight, score); } void -resource_location(resource_t *rsc, node_t *node, int score, const char *tag, - pe_working_set_t *data_set) +resource_location(resource_t * rsc, node_t * node, int score, const char *tag, + pe_working_set_t * data_set) { - if(node != NULL) { - resource_node_score(rsc, node, score, tag); - - } else if(data_set != NULL) { - GListPtr gIter = data_set->nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - resource_node_score(rsc, node, score, tag); - } - + if (node != NULL) { + resource_node_score(rsc, node, score, tag); + + } else if (data_set != NULL) { + GListPtr gIter = data_set->nodes; + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + resource_node_score(rsc, node, score, tag); + } + } else { - GHashTableIter iter; - node_t *node = NULL; - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - resource_node_score(rsc, node, score, tag); - } + GHashTableIter iter; + node_t *node = NULL; + + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + resource_node_score(rsc, node, score, tag); + } } - if(node == NULL && score == -INFINITY) { - if(rsc->allocated_to) { - crm_info("Deallocating %s from %s", rsc->id, rsc->allocated_to->details->uname); - crm_free(rsc->allocated_to); - rsc->allocated_to = NULL; - } + if (node == NULL && score == -INFINITY) { + if (rsc->allocated_to) { + crm_info("Deallocating %s from %s", rsc->id, rsc->allocated_to->details->uname); + crm_free(rsc->allocated_to); + rsc->allocated_to = NULL; + } } } #define sort_return(an_int, why) do { \ crm_free(a_uuid); \ crm_free(b_uuid); \ crm_trace("%s (%d) %c %s (%d) : %s", \ a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \ b_xml_id, b_call_id, why); \ return an_int; \ } while(0) gint sort_op_by_callid(gconstpointer a, gconstpointer b) { char *a_uuid = NULL; char *b_uuid = NULL; const xmlNode *xml_a = a; const xmlNode *xml_b = b; - + const char *a_xml_id = crm_element_value_const(xml_a, XML_ATTR_ID); const char *b_xml_id = crm_element_value_const(xml_b, XML_ATTR_ID); const char *a_task_id = crm_element_value_const(xml_a, XML_LRM_ATTR_CALLID); const char *b_task_id = crm_element_value_const(xml_b, XML_LRM_ATTR_CALLID); const char *a_key = crm_element_value_const(xml_a, XML_ATTR_TRANSITION_MAGIC); const char *b_key = crm_element_value_const(xml_b, XML_ATTR_TRANSITION_MAGIC); int dummy = -1; - + int a_id = -1; int b_id = -1; int a_rc = -1; int b_rc = -1; int a_status = -1; int b_status = -1; - + int a_call_id = -1; int b_call_id = -1; - if(safe_str_eq(a_xml_id, b_xml_id)) { - /* We have duplicate lrm_rsc_op entries in the status - * section which is unliklely to be a good thing - * - we can handle it easily enough, but we need to get - * to the bottom of why its happening. - */ - pe_err("Duplicate lrm_rsc_op entries named %s", a_xml_id); - sort_return(0, "duplicate"); + if (safe_str_eq(a_xml_id, b_xml_id)) { + /* We have duplicate lrm_rsc_op entries in the status + * section which is unliklely to be a good thing + * - we can handle it easily enough, but we need to get + * to the bottom of why its happening. + */ + pe_err("Duplicate lrm_rsc_op entries named %s", a_xml_id); + sort_return(0, "duplicate"); } - - CRM_CHECK(a_task_id != NULL, sort_return(0, "bad id a")); - CRM_CHECK(a_task_id != NULL, sort_return(0, "bad id b")); + + CRM_CHECK(a_task_id != NULL, sort_return(0, "bad id a")); + CRM_CHECK(a_task_id != NULL, sort_return(0, "bad id b")); a_call_id = crm_parse_int(a_task_id, NULL); b_call_id = crm_parse_int(b_task_id, NULL); - - if(a_call_id == -1 && b_call_id == -1) { - /* both are pending ops so it doesnt matter since - * stops are never pending - */ - sort_return(0, "pending"); - } else if(a_call_id >= 0 && a_call_id < b_call_id) { - sort_return(-1, "call id"); + if (a_call_id == -1 && b_call_id == -1) { + /* both are pending ops so it doesnt matter since + * stops are never pending + */ + sort_return(0, "pending"); + + } else if (a_call_id >= 0 && a_call_id < b_call_id) { + sort_return(-1, "call id"); - } else if(b_call_id >= 0 && a_call_id > b_call_id) { - sort_return(1, "call id"); + } else if (b_call_id >= 0 && a_call_id > b_call_id) { + sort_return(1, "call id"); - } else if(b_call_id >= 0 && a_call_id == b_call_id) { - /* The last op and last_failed_op are the same */ - sort_return(0, "duplicate failure"); + } else if (b_call_id >= 0 && a_call_id == b_call_id) { + /* The last op and last_failed_op are the same */ + sort_return(0, "duplicate failure"); } - + /* now process pending ops */ CRM_CHECK(a_key != NULL && b_key != NULL, sort_return(0, "No key")); - CRM_CHECK(decode_transition_magic( - a_key, &a_uuid, &a_id, &dummy, &a_status, &a_rc, &dummy), - sort_return(0, "bad magic a")); - CRM_CHECK(decode_transition_magic( - b_key, &b_uuid, &b_id, &dummy, &b_status, &b_rc, &dummy), - sort_return(0, "bad magic b")); + CRM_CHECK(decode_transition_magic(a_key, &a_uuid, &a_id, &dummy, &a_status, &a_rc, &dummy), + sort_return(0, "bad magic a")); + CRM_CHECK(decode_transition_magic(b_key, &b_uuid, &b_id, &dummy, &b_status, &b_rc, &dummy), + sort_return(0, "bad magic b")); /* try and determin the relative age of the operation... * some pending operations (ie. a start) may have been supuerceeded * by a subsequent stop * * [a|b]_id == -1 means its a shutdown operation and _always_ comes last */ - if(safe_str_neq(a_uuid, b_uuid) || a_id == b_id) { - /* - * some of the logic in here may be redundant... - * - * if the UUID from the TE doesnt match then one better - * be a pending operation. - * pending operations dont survive between elections and joins - * because we query the LRM directly - */ - - CRM_CHECK(a_call_id == -1 || b_call_id == -1, sort_return(0, "odd")); - CRM_CHECK(a_call_id >= 0 || b_call_id >= 0, sort_return(0, "odd")); - - if(b_call_id == -1) { - sort_return(-1, "transition + call"); + if (safe_str_neq(a_uuid, b_uuid) || a_id == b_id) { + /* + * some of the logic in here may be redundant... + * + * if the UUID from the TE doesnt match then one better + * be a pending operation. + * pending operations dont survive between elections and joins + * because we query the LRM directly + */ + + CRM_CHECK(a_call_id == -1 || b_call_id == -1, sort_return(0, "odd")); + CRM_CHECK(a_call_id >= 0 || b_call_id >= 0, sort_return(0, "odd")); + + if (b_call_id == -1) { + sort_return(-1, "transition + call"); + + } else if (a_call_id == -1) { + sort_return(1, "transition + call"); + } - } else if(a_call_id == -1) { - sort_return(1, "transition + call"); - } - - } else if((a_id >= 0 && a_id < b_id) || b_id == -1) { - sort_return(-1, "transition"); + } else if ((a_id >= 0 && a_id < b_id) || b_id == -1) { + sort_return(-1, "transition"); - } else if((b_id >= 0 && a_id > b_id) || a_id == -1) { - sort_return(1, "transition"); + } else if ((b_id >= 0 && a_id > b_id) || a_id == -1) { + sort_return(1, "transition"); } /* we should never end up here */ - CRM_CHECK(FALSE, sort_return(0, "default")); + CRM_CHECK(FALSE, sort_return(0, "default")); } -time_t get_timet_now(pe_working_set_t *data_set) +time_t +get_timet_now(pe_working_set_t * data_set) { time_t now = 0; - if(data_set && data_set->now) { - now = data_set->now->tm_now; - } - - if(now == 0) { - /* eventually we should convert data_set->now into time_tm - * for now, its only triggered by PE regression tests - */ - now = time(NULL); - crm_crit("Defaulting to 'now'"); - if(data_set && data_set->now) { - data_set->now->tm_now = now; - } + + if (data_set && data_set->now) { + now = data_set->now->tm_now; + } + + if (now == 0) { + /* eventually we should convert data_set->now into time_tm + * for now, its only triggered by PE regression tests + */ + now = time(NULL); + crm_crit("Defaulting to 'now'"); + if (data_set && data_set->now) { + data_set->now->tm_now = now; + } } return now; } -struct fail_search -{ - resource_t *rsc; - - int count; - long long last; - char *key; -}; +struct fail_search { + resource_t *rsc; + int count; + long long last; + char *key; +}; -static void get_failcount_by_prefix(gpointer key_p, gpointer value, gpointer user_data) +static void +get_failcount_by_prefix(gpointer key_p, gpointer value, gpointer user_data) { struct fail_search *search = user_data; const char *key = key_p; - + const char *match = strstr(key, search->key); - if(match) { - if(strstr(key, "last-failure-") == key && (key+13) == match) { - search->last = crm_int_helper(value, NULL); - } else if(strstr(key, "fail-count-") == key && (key+11) == match) { - search->count += char2score(value); - } + if (match) { + if (strstr(key, "last-failure-") == key && (key + 13) == match) { + search->last = crm_int_helper(value, NULL); + + } else if (strstr(key, "fail-count-") == key && (key + 11) == match) { + search->count += char2score(value); + } } } -int get_failcount(node_t *node, resource_t *rsc, int *last_failure, pe_working_set_t *data_set) +int +get_failcount(node_t * node, resource_t * rsc, int *last_failure, pe_working_set_t * data_set) { - struct fail_search search = {rsc, 0, 0, NULL}; + struct fail_search search = { rsc, 0, 0, NULL }; search.key = crm_strdup(rsc->id); - if(is_not_set(rsc->flags, pe_rsc_unique)) { - int lpc = 0; + if (is_not_set(rsc->flags, pe_rsc_unique)) { + int lpc = 0; - search.rsc = uber_parent(rsc); + search.rsc = uber_parent(rsc); - /* Strip the clone incarnation */ - for(lpc = strlen(search.key); lpc > 0; lpc--) { - if(search.key[lpc] == ':') { - search.key[lpc+1] = 0; - break; - } - } + /* Strip the clone incarnation */ + for (lpc = strlen(search.key); lpc > 0; lpc--) { + if (search.key[lpc] == ':') { + search.key[lpc + 1] = 0; + break; + } + } - g_hash_table_foreach(node->details->attrs, get_failcount_by_prefix, &search); + g_hash_table_foreach(node->details->attrs, get_failcount_by_prefix, &search); } else { - /* Optimize the "normal" case */ - char *key = NULL; - const char *value = NULL; - - key = crm_concat("fail-count", rsc->id, '-'); - value = g_hash_table_lookup(node->details->attrs, key); - search.count = char2score(value); - crm_free(key); - - key = crm_concat("last-failure", rsc->id, '-'); - value = g_hash_table_lookup(node->details->attrs, key); - search.last = crm_int_helper(value, NULL); - crm_free(key); - } - - if(search.count != 0 && search.last != 0 && rsc->failure_timeout) { - if(last_failure) { - *last_failure = search.last; - } - if(search.last > 0) { - time_t now = get_timet_now(data_set); - if(now > (search.last + rsc->failure_timeout)) { - crm_notice("Failcount for %s on %s has expired (limit was %ds)", - search.rsc->id, node->details->uname, rsc->failure_timeout); - search.count = 0; - } - } - } - - if(search.count != 0) { - crm_info("%s has failed %s times on %s", - search.rsc->id, score2char(search.count), node->details->uname); - } - + /* Optimize the "normal" case */ + char *key = NULL; + const char *value = NULL; + + key = crm_concat("fail-count", rsc->id, '-'); + value = g_hash_table_lookup(node->details->attrs, key); + search.count = char2score(value); + crm_free(key); + + key = crm_concat("last-failure", rsc->id, '-'); + value = g_hash_table_lookup(node->details->attrs, key); + search.last = crm_int_helper(value, NULL); + crm_free(key); + } + + if (search.count != 0 && search.last != 0 && rsc->failure_timeout) { + if (last_failure) { + *last_failure = search.last; + } + if (search.last > 0) { + time_t now = get_timet_now(data_set); + + if (now > (search.last + rsc->failure_timeout)) { + crm_notice("Failcount for %s on %s has expired (limit was %ds)", + search.rsc->id, node->details->uname, rsc->failure_timeout); + search.count = 0; + } + } + } + + if (search.count != 0) { + crm_info("%s has failed %s times on %s", + search.rsc->id, score2char(search.count), node->details->uname); + } + crm_free(search.key); return search.count; } -gboolean get_target_role(resource_t *rsc, enum rsc_role_e *role) +gboolean +get_target_role(resource_t * rsc, enum rsc_role_e * role) { enum rsc_role_e local_role = RSC_ROLE_UNKNOWN; const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE); + CRM_CHECK(role != NULL, return FALSE); - - if(value == NULL - || safe_str_eq("started", value) - || safe_str_eq("default", value)) { - return FALSE; + + if (value == NULL || safe_str_eq("started", value) + || safe_str_eq("default", value)) { + return FALSE; } local_role = text2role(value); - if(local_role == RSC_ROLE_UNKNOWN) { - crm_config_err("%s: Unknown value for %s: %s", - rsc->id, XML_RSC_ATTR_TARGET_ROLE, value); - return FALSE; - - } else if(local_role > RSC_ROLE_STARTED) { - if(uber_parent(rsc)->variant == pe_master) { - if(local_role > RSC_ROLE_SLAVE) { - /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */ - return FALSE; - } - - } else { - crm_config_err("%s is not part of a master/slave resource, a %s of '%s' makes no sense", - rsc->id, XML_RSC_ATTR_TARGET_ROLE, value); - return FALSE; - } - } - + if (local_role == RSC_ROLE_UNKNOWN) { + crm_config_err("%s: Unknown value for %s: %s", rsc->id, XML_RSC_ATTR_TARGET_ROLE, value); + return FALSE; + + } else if (local_role > RSC_ROLE_STARTED) { + if (uber_parent(rsc)->variant == pe_master) { + if (local_role > RSC_ROLE_SLAVE) { + /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */ + return FALSE; + } + + } else { + crm_config_err("%s is not part of a master/slave resource, a %s of '%s' makes no sense", + rsc->id, XML_RSC_ATTR_TARGET_ROLE, value); + return FALSE; + } + } + *role = local_role; return TRUE; } diff --git a/lib/plugins/lrm/raexecstonith.c b/lib/plugins/lrm/raexecstonith.c index 04caeffdf7..be1672753f 100644 --- a/lib/plugins/lrm/raexecstonith.c +++ b/lib/plugins/lrm/raexecstonith.c @@ -1,270 +1,264 @@ /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * File: raexecocf.c * Author: Sun Jiang Dong * Copyright (c) 2004 International Business Machines * * This code implements the Resource Agent Plugin Module for LSB style. * It's a part of Local Resource Manager. Currently it's used by lrmd only. */ #include -#include +#include #include #include #include #include #include #include #include #include #include #if HAVE_HB_CONFIG_H -#include +# include #endif #if HAVE_GLUE_CONFIG_H -#include +# include #endif #include #include #include #include -#include /* Add it for compiling on OSX */ +#include /* Add it for compiling on OSX */ #include #include #include #include -# define PIL_PLUGINTYPE RA_EXEC_TYPE -# define PIL_PLUGINTYPE_S "RAExec" -# define PIL_PLUGINLICENSE LICENSE_PUBDOM -# define PIL_PLUGINLICENSEURL URL_PUBDOM +#define PIL_PLUGINTYPE RA_EXEC_TYPE +#define PIL_PLUGINTYPE_S "RAExec" +#define PIL_PLUGINLICENSE LICENSE_PUBDOM +#define PIL_PLUGINLICENSEURL URL_PUBDOM -# define PIL_PLUGIN stonith -# define PIL_PLUGIN_S "stonith" +#define PIL_PLUGIN stonith +#define PIL_PLUGIN_S "stonith" -static PIL_rc close_stonithRA(PILInterface*, void* ud_interface); +static PIL_rc close_stonithRA(PILInterface *, void *ud_interface); /* The begin of exported function list */ -static int execra(const char * rsc_id, - const char * rsc_type, - const char * provider, - const char * op_type, - const int timeout, - GHashTable * params); -static uniform_ret_execra_t map_ra_retvalue(int ret_execra - , const char * op_type, const char * std_output); +static int execra(const char *rsc_id, + const char *rsc_type, + const char *provider, + const char *op_type, const int timeout, GHashTable * params); +static uniform_ret_execra_t map_ra_retvalue(int ret_execra, const char *op_type, + const char *std_output); static int get_resource_list(GList ** rsc_info); -static char* get_resource_meta(const char* rsc_type, const char* provider); -static int get_provider_list(const char* op_type, GList ** providers); +static char *get_resource_meta(const char *rsc_type, const char *provider); +static int get_provider_list(const char *op_type, GList ** providers); /* The end of exported function list */ /* Rource agent execution plugin operations */ -static struct RAExecOps raops = -{ execra, - map_ra_retvalue, - get_resource_list, - get_provider_list, - get_resource_meta +static struct RAExecOps raops = { execra, + map_ra_retvalue, + get_resource_list, + get_provider_list, + get_resource_meta }; PIL_PLUGIN_BOILERPLATE2("1.0", Debug); -static const PILPluginImports* PluginImports; -static PILPlugin* OurPlugin; -static PILInterface* OurInterface; -static void* OurImports; -static void* interfprivate; +static const PILPluginImports *PluginImports; +static PILPlugin *OurPlugin; +static PILInterface *OurInterface; +static void *OurImports; +static void *interfprivate; /* * Our plugin initialization and registration function * It gets called when the plugin gets loaded. */ -PIL_rc -PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports); +PIL_rc PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports * imports); PIL_rc -PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports) +PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports * imports) { - /* Force the compiler to do a little type checking */ - (void)(PILPluginInitFun)PIL_PLUGIN_INIT; + /* Force the compiler to do a little type checking */ + (void)(PILPluginInitFun) PIL_PLUGIN_INIT; - PluginImports = imports; - OurPlugin = us; + PluginImports = imports; + OurPlugin = us; - /* Register ourself as a plugin */ - imports->register_plugin(us, &OurPIExports); + /* Register ourself as a plugin */ + imports->register_plugin(us, &OurPIExports); - /* Register our interfaces */ - return imports->register_interface(us, PIL_PLUGINTYPE_S, PIL_PLUGIN_S, - &raops, close_stonithRA, &OurInterface, &OurImports, - interfprivate); + /* Register our interfaces */ + return imports->register_interface(us, PIL_PLUGINTYPE_S, PIL_PLUGIN_S, + &raops, close_stonithRA, &OurInterface, &OurImports, + interfprivate); } static PIL_rc -close_stonithRA(PILInterface* pif, void* ud_interface) +close_stonithRA(PILInterface * pif, void *ud_interface) { - return PIL_OK; + return PIL_OK; } static int execra(const char *rsc_id, const char *rsc_type, const char *provider, - const char *op_type, const int timeout, GHashTable *params) + const char *op_type, const int timeout, GHashTable * params) { int rc = 0; stonith_key_value_t *device_params = NULL; stonith_t *stonith_api = NULL; provider = get_stonith_provider(rsc_type, provider); crm_log_init("lrm-stonith", LOG_INFO, FALSE, FALSE, 0, NULL); - - if ( 0 == STRNCMP_CONST(op_type, "meta-data")) { - char *meta = get_resource_meta(rsc_type, provider); - printf("%s", meta); - free(meta); - exit(0); + + if (0 == STRNCMP_CONST(op_type, "meta-data")) { + char *meta = get_resource_meta(rsc_type, provider); + + printf("%s", meta); + free(meta); + exit(0); } stonith_api = stonith_api_new(); rc = stonith_api->cmds->connect(stonith_api, "lrmd", NULL); - if(provider == NULL) { - crm_err("No such legacy stonith device: %s", rsc_type); - rc = st_err_unknown_device; - - } else if ( 0 == STRNCMP_CONST(op_type, "monitor") ) { - rc = stonith_api->cmds->call( - stonith_api, st_opt_sync_call, rsc_id, op_type, NULL, timeout); - - } else if ( 0 == STRNCMP_CONST(op_type, "start") ) { - char *key = NULL; - char *value = NULL; - GHashTableIter iter; - const char *agent = rsc_type; - - if(0 == STRNCMP_CONST(provider, "heartbeat")) { - agent = "fence_legacy"; - g_hash_table_replace(params, strdup("plugin"), strdup(rsc_type)); - } - - g_hash_table_iter_init( &iter, params ); - while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) { - device_params = stonith_key_value_add(device_params, key, value); - } - - rc = stonith_api->cmds->register_device( - stonith_api, st_opt_sync_call, rsc_id, provider, agent, device_params); - - } else if ( 0 == STRNCMP_CONST(op_type, "stop") ) { - rc = stonith_api->cmds->remove_device( - stonith_api, st_opt_sync_call, rsc_id); + if (provider == NULL) { + crm_err("No such legacy stonith device: %s", rsc_type); + rc = st_err_unknown_device; + + } else if (0 == STRNCMP_CONST(op_type, "monitor")) { + rc = stonith_api->cmds->call(stonith_api, st_opt_sync_call, rsc_id, op_type, NULL, timeout); + + } else if (0 == STRNCMP_CONST(op_type, "start")) { + char *key = NULL; + char *value = NULL; + GHashTableIter iter; + const char *agent = rsc_type; + + if (0 == STRNCMP_CONST(provider, "heartbeat")) { + agent = "fence_legacy"; + g_hash_table_replace(params, strdup("plugin"), strdup(rsc_type)); + } + + g_hash_table_iter_init(&iter, params); + while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { + device_params = stonith_key_value_add(device_params, key, value); + } + + rc = stonith_api->cmds->register_device(stonith_api, st_opt_sync_call, rsc_id, provider, + agent, device_params); + + } else if (0 == STRNCMP_CONST(op_type, "stop")) { + rc = stonith_api->cmds->remove_device(stonith_api, st_opt_sync_call, rsc_id); } crm_debug("%s_%s returned %d", rsc_id, op_type, rc); stonith_api->cmds->disconnect(stonith_api); stonith_api_delete(stonith_api); - + /* cl_log(LOG_DEBUG, "stonithRA orignal exit code=%d", exit_value); */ exit(map_ra_retvalue(rc, op_type, NULL)); } static uniform_ret_execra_t -map_ra_retvalue(int rc, const char * op_type, const char * std_output) +map_ra_retvalue(int rc, const char *op_type, const char *std_output) { - if(rc == st_err_unknown_device) { - if ( 0 == STRNCMP_CONST(op_type, "stop") ) { - rc = 0; + if (rc == st_err_unknown_device) { + if (0 == STRNCMP_CONST(op_type, "stop")) { + rc = 0; + + } else if (0 == STRNCMP_CONST(op_type, "start")) { + rc = 5; - } else if ( 0 == STRNCMP_CONST(op_type, "start") ) { - rc = 5; + } else { + rc = 7; + } - } else { - rc = 7; - } - } else if (rc < 0 || rc > EXECRA_STATUS_UNKNOWN) { - crm_warn("Mapped the invalid return code %d.", rc); - rc = EXECRA_UNKNOWN_ERROR; + crm_warn("Mapped the invalid return code %d.", rc); + rc = EXECRA_UNKNOWN_ERROR; } return rc; } static int get_resource_list(GList ** rsc_info) { stonith_t *stonith_api = NULL; stonith_key_value_t *devices = NULL; stonith_key_value_t *dIter = NULL; - - if ( rsc_info == NULL ) { - crm_err("Parameter error: get_resource_list"); - return -2; + + if (rsc_info == NULL) { + crm_err("Parameter error: get_resource_list"); + return -2; } stonith_api = stonith_api_new(); stonith_api->cmds->list(stonith_api, st_opt_sync_call, NULL, &devices, 0); stonith_api_delete(stonith_api); - for(dIter = devices; dIter; dIter = dIter->next) { - *rsc_info = g_list_append(*rsc_info, dIter->value); + for (dIter = devices; dIter; dIter = dIter->next) { + *rsc_info = g_list_append(*rsc_info, dIter->value); } - + stonith_key_value_freeall(devices, 1, 0); return 0; } static int -get_provider_list(const char* op_type, GList ** providers) +get_provider_list(const char *op_type, GList ** providers) { - if(providers == NULL) { - return -1; + if (providers == NULL) { + return -1; } - if(op_type == NULL) { - *providers = g_list_append(*providers, g_strdup("redhat")); - *providers = g_list_append(*providers, g_strdup("heartbeat")); - return 2; + if (op_type == NULL) { + *providers = g_list_append(*providers, g_strdup("redhat")); + *providers = g_list_append(*providers, g_strdup("heartbeat")); + return 2; } else { - const char *provider = get_stonith_provider(op_type, NULL); - if(provider) { - *providers = g_list_append(*providers, g_strdup(provider)); - return 1; - } + const char *provider = get_stonith_provider(op_type, NULL); + + if (provider) { + *providers = g_list_append(*providers, g_strdup(provider)); + return 1; + } } - + return 0; } static char * -get_resource_meta(const char* rsc_type, const char* provider) +get_resource_meta(const char *rsc_type, const char *provider) { char *buffer = NULL; stonith_t *stonith_api = stonith_api_new(); - stonith_api->cmds->metadata( - stonith_api, st_opt_sync_call, rsc_type, provider, &buffer, 0); + + stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, rsc_type, provider, &buffer, 0); stonith_api_delete(stonith_api); crm_debug("stonithRA plugin: got metadata: %s", buffer); - /* TODO: Convert to XML and ensure our standard actions exist */ return buffer; } - diff --git a/lib/transition/graph.c b/lib/transition/graph.c index 96d6d61f56..00301144b0 100644 --- a/lib/transition/graph.c +++ b/lib/transition/graph.c @@ -1,338 +1,328 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 */ /* */ - crm_graph_functions_t *graph_fns = NULL; - static gboolean -update_synapse_ready(synapse_t *synapse, int action_id) +update_synapse_ready(synapse_t * synapse, int action_id) { GListPtr lpc = NULL; gboolean updates = FALSE; + CRM_CHECK(synapse->executed == FALSE, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return FALSE); synapse->ready = TRUE; - for(lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) { - crm_action_t *prereq = (crm_action_t*)lpc->data; - - - crm_debug_3("Processing input %d", prereq->id); - - if(prereq->id == action_id) { - crm_debug_2("Marking input %d of synapse %d confirmed", - action_id, synapse->id); - prereq->confirmed = TRUE; - updates = TRUE; - - } else if(prereq->confirmed == FALSE) { - synapse->ready = FALSE; - } - + for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) { + crm_action_t *prereq = (crm_action_t *) lpc->data; + + crm_debug_3("Processing input %d", prereq->id); + + if (prereq->id == action_id) { + crm_debug_2("Marking input %d of synapse %d confirmed", action_id, synapse->id); + prereq->confirmed = TRUE; + updates = TRUE; + + } else if (prereq->confirmed == FALSE) { + synapse->ready = FALSE; + } + } - if(updates) { - crm_debug_2("Updated synapse %d", synapse->id); + if (updates) { + crm_debug_2("Updated synapse %d", synapse->id); } return updates; } + static gboolean -update_synapse_confirmed(synapse_t *synapse, int action_id) +update_synapse_confirmed(synapse_t * synapse, int action_id) { GListPtr lpc = NULL; gboolean updates = FALSE; gboolean is_confirmed = TRUE; - + CRM_CHECK(synapse->executed, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return TRUE); is_confirmed = TRUE; - for(lpc = synapse->actions; lpc != NULL; lpc = lpc->next) { - crm_action_t *action = (crm_action_t*)lpc->data; - - - crm_debug_3("Processing action %d", action->id); - - if(action->id == action_id) { - crm_debug_2("Confirmed: Action %d of Synapse %d", - action_id, synapse->id); - action->confirmed = TRUE; - updates = TRUE; - - } else if(action->confirmed == FALSE) { - is_confirmed = FALSE; - crm_debug_3("Synapse %d still not confirmed after action %d", - synapse->id, action_id); - } + for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) { + crm_action_t *action = (crm_action_t *) lpc->data; + + crm_debug_3("Processing action %d", action->id); + + if (action->id == action_id) { + crm_debug_2("Confirmed: Action %d of Synapse %d", action_id, synapse->id); + action->confirmed = TRUE; + updates = TRUE; + + } else if (action->confirmed == FALSE) { + is_confirmed = FALSE; + crm_debug_3("Synapse %d still not confirmed after action %d", synapse->id, action_id); + } } - if(is_confirmed && synapse->confirmed == FALSE) { - crm_debug_2("Confirmed: Synapse %d", synapse->id); - synapse->confirmed = TRUE; - updates = TRUE; + if (is_confirmed && synapse->confirmed == FALSE) { + crm_debug_2("Confirmed: Synapse %d", synapse->id); + synapse->confirmed = TRUE; + updates = TRUE; } - - if(updates) { - crm_debug_3("Updated synapse %d", synapse->id); + + if (updates) { + crm_debug_3("Updated synapse %d", synapse->id); } return updates; } gboolean -update_graph(crm_graph_t *graph, crm_action_t *action) +update_graph(crm_graph_t * graph, crm_action_t * action) { gboolean rc = FALSE; gboolean updates = FALSE; GListPtr lpc = NULL; - for(lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { - synapse_t *synapse = (synapse_t*)lpc->data; - - if (synapse->confirmed || synapse->failed) { - crm_debug_2("Synapse complete"); - - } else if (synapse->executed) { - crm_debug_2("Synapse executed"); - rc = update_synapse_confirmed(synapse, action->id); - - } else if(action->failed == FALSE || synapse->priority == INFINITY) { - rc = update_synapse_ready(synapse, action->id); - } - updates = updates || rc; + + for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { + synapse_t *synapse = (synapse_t *) lpc->data; + + if (synapse->confirmed || synapse->failed) { + crm_debug_2("Synapse complete"); + + } else if (synapse->executed) { + crm_debug_2("Synapse executed"); + rc = update_synapse_confirmed(synapse, action->id); + + } else if (action->failed == FALSE || synapse->priority == INFINITY) { + rc = update_synapse_ready(synapse, action->id); + } + updates = updates || rc; } - - if(updates) { - crm_debug_2("Updated graph with completed action %d", - action->id); + + if (updates) { + crm_debug_2("Updated graph with completed action %d", action->id); } return updates; } - static gboolean -should_fire_synapse(synapse_t *synapse) +should_fire_synapse(synapse_t * synapse) { GListPtr lpc = NULL; + CRM_CHECK(synapse->executed == FALSE, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return FALSE); - + crm_debug_3("Checking pre-reqs for %d", synapse->id); /* lookup prereqs */ synapse->ready = TRUE; - for(lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) { - crm_action_t *prereq = (crm_action_t*)lpc->data; - crm_debug_3("Processing input %d", prereq->id); - if(prereq->confirmed == FALSE) { - crm_debug_3("Inputs for synapse %d not satisfied", - synapse->id); - synapse->ready = FALSE; - break; - } + for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) { + crm_action_t *prereq = (crm_action_t *) lpc->data; + + crm_debug_3("Processing input %d", prereq->id); + if (prereq->confirmed == FALSE) { + crm_debug_3("Inputs for synapse %d not satisfied", synapse->id); + synapse->ready = FALSE; + break; + } } return synapse->ready; } - static gboolean -initiate_action(crm_graph_t *graph, crm_action_t *action) +initiate_action(crm_graph_t * graph, crm_action_t * action) { const char *id = NULL; + CRM_CHECK(action->executed == FALSE, return FALSE); id = ID(action->xml); CRM_CHECK(id != NULL, return FALSE); action->executed = TRUE; - if(action->type == action_type_pseudo){ - crm_debug_2("Executing pseudo-event: %d", action->id); - return graph_fns->pseudo(graph, action); - - } else if(action->type == action_type_rsc) { - crm_debug_2("Executing rsc-event: %d", action->id); - return graph_fns->rsc(graph, action); - - } else if(action->type == action_type_crm) { - const char *task = NULL; - task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); - CRM_CHECK(task != NULL, return FALSE); - - if(safe_str_eq(task, CRM_OP_FENCE)) { - crm_debug_2("Executing STONITH-event: %d", - action->id); - return graph_fns->stonith(graph, action); - } - - crm_debug_2("Executing crm-event: %d", action->id); - return graph_fns->crmd(graph, action); + if (action->type == action_type_pseudo) { + crm_debug_2("Executing pseudo-event: %d", action->id); + return graph_fns->pseudo(graph, action); + + } else if (action->type == action_type_rsc) { + crm_debug_2("Executing rsc-event: %d", action->id); + return graph_fns->rsc(graph, action); + + } else if (action->type == action_type_crm) { + const char *task = NULL; + + task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + CRM_CHECK(task != NULL, return FALSE); + + if (safe_str_eq(task, CRM_OP_FENCE)) { + crm_debug_2("Executing STONITH-event: %d", action->id); + return graph_fns->stonith(graph, action); + } + + crm_debug_2("Executing crm-event: %d", action->id); + return graph_fns->crmd(graph, action); } - + te_log_action(LOG_ERR, - "Failed on unsupported command type: %s (id=%s)", - crm_element_name(action->xml), id); + "Failed on unsupported command type: %s (id=%s)", + crm_element_name(action->xml), id); return FALSE; } static gboolean -fire_synapse(crm_graph_t *graph, synapse_t *synapse) +fire_synapse(crm_graph_t * graph, synapse_t * synapse) { GListPtr lpc = NULL; + CRM_CHECK(synapse != NULL, return FALSE); CRM_CHECK(synapse->ready, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return TRUE); - + crm_debug_2("Synapse %d fired", synapse->id); synapse->executed = TRUE; - for(lpc = synapse->actions; lpc != NULL; lpc = lpc->next) { - crm_action_t *action = (crm_action_t*)lpc->data; - - /* allow some leeway */ - gboolean passed = FALSE; - - /* Invoke the action and start the timer */ - passed = initiate_action(graph, action); - if(passed == FALSE) { - crm_err("Failed initiating <%s id=%d> in synapse %d", - crm_element_name(action->xml), - action->id, synapse->id); - synapse->confirmed = TRUE; - action->confirmed = TRUE; - action->failed = TRUE; - return FALSE; - } + for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) { + crm_action_t *action = (crm_action_t *) lpc->data; + + /* allow some leeway */ + gboolean passed = FALSE; + + /* Invoke the action and start the timer */ + passed = initiate_action(graph, action); + if (passed == FALSE) { + crm_err("Failed initiating <%s id=%d> in synapse %d", + crm_element_name(action->xml), action->id, synapse->id); + synapse->confirmed = TRUE; + action->confirmed = TRUE; + action->failed = TRUE; + return FALSE; + } } - + return TRUE; } int -run_graph(crm_graph_t *graph) +run_graph(crm_graph_t * graph) { GListPtr lpc = NULL; int stat_log_level = LOG_DEBUG; int pass_result = transition_active; const char *status = "In-progress"; - - if(graph_fns == NULL) { - set_default_graph_functions(); + + if (graph_fns == NULL) { + set_default_graph_functions(); } - if(graph == NULL) { - return transition_complete; + if (graph == NULL) { + return transition_complete; } graph->fired = 0; graph->pending = 0; graph->skipped = 0; graph->completed = 0; graph->incomplete = 0; crm_debug_2("Entering graph %d callback", graph->id); /* Pre-calculate the number of completed and in-flight operations */ - for(lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { - synapse_t *synapse = (synapse_t*)lpc->data; - - if (synapse->confirmed) { - crm_debug_3("Synapse %d complete", synapse->id); - graph->completed++; - - } else if(synapse->failed == FALSE && synapse->executed) { - crm_debug_2("Synapse %d: confirmation pending", synapse->id); - graph->pending++; - } + for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { + synapse_t *synapse = (synapse_t *) lpc->data; + + if (synapse->confirmed) { + crm_debug_3("Synapse %d complete", synapse->id); + graph->completed++; + + } else if (synapse->failed == FALSE && synapse->executed) { + crm_debug_2("Synapse %d: confirmation pending", synapse->id); + graph->pending++; + } } /* Now check if there is work to do */ - for(lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { - synapse_t *synapse = (synapse_t*)lpc->data; - - if(graph->batch_limit > 0 && graph->pending >= graph->batch_limit) { - crm_debug("Throttling output: batch limit (%d) reached", - graph->batch_limit); - break; - - } else if (synapse->failed) { - graph->skipped++; - continue; - - } else if (synapse->confirmed || synapse->executed) { - /* Already handled */ - continue; - } - - if(synapse->priority < graph->abort_priority) { - crm_debug_2("Skipping synapse %d: aborting", synapse->id); - graph->skipped++; - - } else if(should_fire_synapse(synapse)) { - crm_debug_2("Synapse %d fired", synapse->id); - graph->fired++; - CRM_CHECK(fire_synapse(graph, synapse), - stat_log_level = LOG_ERR; - graph->abort_priority = INFINITY; - graph->incomplete++; - graph->fired--); - - if (synapse->confirmed == FALSE) { - graph->pending++; - } - - } else { - crm_debug_2("Synapse %d cannot fire", synapse->id); - graph->incomplete++; - } + for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { + synapse_t *synapse = (synapse_t *) lpc->data; + + if (graph->batch_limit > 0 && graph->pending >= graph->batch_limit) { + crm_debug("Throttling output: batch limit (%d) reached", graph->batch_limit); + break; + + } else if (synapse->failed) { + graph->skipped++; + continue; + + } else if (synapse->confirmed || synapse->executed) { + /* Already handled */ + continue; + } + + if (synapse->priority < graph->abort_priority) { + crm_debug_2("Skipping synapse %d: aborting", synapse->id); + graph->skipped++; + + } else if (should_fire_synapse(synapse)) { + crm_debug_2("Synapse %d fired", synapse->id); + graph->fired++; + CRM_CHECK(fire_synapse(graph, synapse), stat_log_level = LOG_ERR; + graph->abort_priority = INFINITY; graph->incomplete++; graph->fired--); + + if (synapse->confirmed == FALSE) { + graph->pending++; + } + + } else { + crm_debug_2("Synapse %d cannot fire", synapse->id); + graph->incomplete++; + } } - if(graph->pending == 0 && graph->fired == 0) { - graph->complete = TRUE; - stat_log_level = LOG_NOTICE; - pass_result = transition_complete; - status = "Complete"; + if (graph->pending == 0 && graph->fired == 0) { + graph->complete = TRUE; + stat_log_level = LOG_NOTICE; + pass_result = transition_complete; + status = "Complete"; - if(graph->incomplete != 0 && graph->abort_priority <= 0) { - stat_log_level = LOG_WARNING; - pass_result = transition_terminated; - status = "Terminated"; + if (graph->incomplete != 0 && graph->abort_priority <= 0) { + stat_log_level = LOG_WARNING; + pass_result = transition_terminated; + status = "Terminated"; - } else if(graph->skipped != 0) { - status = "Stopped"; - } + } else if (graph->skipped != 0) { + status = "Stopped"; + } - } else if(graph->fired == 0) { - pass_result = transition_pending; + } else if (graph->fired == 0) { + pass_result = transition_pending; } - - do_crm_log(stat_log_level+1, - "===================================================="); + + do_crm_log(stat_log_level + 1, "===================================================="); do_crm_log(stat_log_level, - "Transition %d (Complete=%d, Pending=%d," - " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s", - graph->id, graph->completed, graph->pending, graph->fired, - graph->skipped, graph->incomplete, graph->source, status); - + "Transition %d (Complete=%d, Pending=%d," + " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s", + graph->id, graph->completed, graph->pending, graph->fired, + graph->skipped, graph->incomplete, graph->source, status); + return pass_result; } diff --git a/lib/transition/unpack.c b/lib/transition/unpack.c index 35a688b940..04c1aae3b7 100644 --- a/lib/transition/unpack.c +++ b/lib/transition/unpack.c @@ -1,323 +1,329 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 CRM_TRACE_INIT_DATA(transitioner); -static crm_action_t* -unpack_action(synapse_t *parent, xmlNode *xml_action) +static crm_action_t * +unpack_action(synapse_t * parent, xmlNode * xml_action) { - crm_action_t *action = NULL; + crm_action_t *action = NULL; xmlNode *action_copy = NULL; const char *value = crm_element_value(xml_action, XML_ATTR_ID); - if(value == NULL) { - crm_err("Actions must have an id!"); - crm_log_xml_debug_3(xml_action, "Action with missing id"); - return NULL; + if (value == NULL) { + crm_err("Actions must have an id!"); + crm_log_xml_debug_3(xml_action, "Action with missing id"); + return NULL; } - + action_copy = copy_xml(xml_action); crm_malloc0(action, sizeof(crm_action_t)); - if(action == NULL) { - return NULL; + if (action == NULL) { + return NULL; } - - action->id = crm_parse_int(value, NULL); + + action->id = crm_parse_int(value, NULL); action->type = action_type_rsc; - action->xml = action_copy; + action->xml = action_copy; action->synapse = parent; - - if(safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_RSC_OP)) { - action->type = action_type_rsc; - } else if(safe_str_eq(crm_element_name(action_copy), - XML_GRAPH_TAG_PSEUDO_EVENT)) { - action->type = action_type_pseudo; + if (safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_RSC_OP)) { + action->type = action_type_rsc; + + } else if (safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_PSEUDO_EVENT)) { + action->type = action_type_pseudo; - } else if(safe_str_eq(crm_element_name(action_copy), - XML_GRAPH_TAG_CRM_EVENT)) { - action->type = action_type_crm; + } else if (safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_CRM_EVENT)) { + action->type = action_type_crm; } action->params = xml2list(action_copy); value = g_hash_table_lookup(action->params, "CRM_meta_timeout"); - if(value != NULL) { - action->timeout = crm_parse_int(value, NULL); + if (value != NULL) { + action->timeout = crm_parse_int(value, NULL); } value = g_hash_table_lookup(action->params, "CRM_meta_interval"); - if(value != NULL) { - action->interval = crm_parse_int(value, NULL); + if (value != NULL) { + action->interval = crm_parse_int(value, NULL); } value = g_hash_table_lookup(action->params, "CRM_meta_can_fail"); - if(value != NULL) { - crm_str_to_boolean(value, &(action->can_fail)); + if (value != NULL) { + crm_str_to_boolean(value, &(action->can_fail)); } - - crm_debug_3("Action %d has timer set to %dms", - action->id, action->timeout); + + crm_debug_3("Action %d has timer set to %dms", action->id, action->timeout); return action; } static synapse_t * -unpack_synapse(crm_graph_t *new_graph, xmlNode *xml_synapse) +unpack_synapse(crm_graph_t * new_graph, xmlNode * xml_synapse) { const char *value = NULL; xmlNode *inputs = NULL; xmlNode *action_set = NULL; synapse_t *new_synapse = NULL; + CRM_CHECK(xml_synapse != NULL, return NULL); crm_debug_3("looking in synapse %s", ID(xml_synapse)); - + crm_malloc0(new_synapse, sizeof(synapse_t)); new_synapse->id = crm_parse_int(ID(xml_synapse), NULL); value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY); - if(value != NULL) { - new_synapse->priority = crm_parse_int(value, NULL); + if (value != NULL) { + new_synapse->priority = crm_parse_int(value, NULL); } - + new_graph->num_synapses++; - CRM_CHECK(new_synapse->id >= 0, crm_free(new_synapse); return NULL); - - crm_debug_3("look for actions in synapse %s", - crm_element_value(xml_synapse, XML_ATTR_ID)); - - for(action_set = __xml_first_child(xml_synapse); action_set != NULL; action_set = __xml_next(action_set)) { - if(crm_str_eq((const char *)action_set->name, "action_set", TRUE)) { - xmlNode *action = NULL; - for(action = __xml_first_child(action_set); action != NULL; action = __xml_next(action)) { - crm_action_t *new_action = unpack_action(new_synapse, action); - new_graph->num_actions++; - - if(new_action == NULL) { - continue; - } - crm_debug_3("Adding action %d to synapse %d", - new_action->id, new_synapse->id); - - new_synapse->actions = g_list_append( - new_synapse->actions, new_action); - } - } + CRM_CHECK(new_synapse->id >= 0, crm_free(new_synapse); + return NULL); + + crm_debug_3("look for actions in synapse %s", crm_element_value(xml_synapse, XML_ATTR_ID)); + + for (action_set = __xml_first_child(xml_synapse); action_set != NULL; + action_set = __xml_next(action_set)) { + if (crm_str_eq((const char *)action_set->name, "action_set", TRUE)) { + xmlNode *action = NULL; + + for (action = __xml_first_child(action_set); action != NULL; + action = __xml_next(action)) { + crm_action_t *new_action = unpack_action(new_synapse, action); + + new_graph->num_actions++; + + if (new_action == NULL) { + continue; + } + crm_debug_3("Adding action %d to synapse %d", new_action->id, new_synapse->id); + + new_synapse->actions = g_list_append(new_synapse->actions, new_action); + } + } } - crm_debug_3("look for inputs in synapse %s", ID(xml_synapse)); - - for(inputs = __xml_first_child(xml_synapse); inputs != NULL; inputs = __xml_next(inputs)) { - if(crm_str_eq((const char *)inputs->name, "inputs", TRUE)) { - xmlNode *trigger = NULL; - for(trigger = __xml_first_child(inputs); trigger != NULL; trigger = __xml_next(trigger)) { - xmlNode *input = NULL; - for(input = __xml_first_child(trigger); input != NULL; input = __xml_next(input)) { - crm_action_t *new_input = unpack_action( - new_synapse, input); - - if(new_input == NULL) { - continue; - } - - crm_debug_3("Adding input %d to synapse %d", - new_input->id, new_synapse->id); - - new_synapse->inputs = g_list_append( - new_synapse->inputs, new_input); - } - } - } + + for (inputs = __xml_first_child(xml_synapse); inputs != NULL; inputs = __xml_next(inputs)) { + if (crm_str_eq((const char *)inputs->name, "inputs", TRUE)) { + xmlNode *trigger = NULL; + + for (trigger = __xml_first_child(inputs); trigger != NULL; + trigger = __xml_next(trigger)) { + xmlNode *input = NULL; + + for (input = __xml_first_child(trigger); input != NULL; input = __xml_next(input)) { + crm_action_t *new_input = unpack_action(new_synapse, input); + + if (new_input == NULL) { + continue; + } + + crm_debug_3("Adding input %d to synapse %d", new_input->id, new_synapse->id); + + new_synapse->inputs = g_list_append(new_synapse->inputs, new_input); + } + } + } } - + return new_synapse; } crm_graph_t * -unpack_graph(xmlNode *xml_graph, const char *reference) +unpack_graph(xmlNode * xml_graph, const char *reference) { /* id = -1; new_graph->abort_priority = 0; new_graph->network_delay = -1; new_graph->transition_timeout = -1; new_graph->stonith_timeout = -1; new_graph->completion_action = tg_done; - if(reference) { - new_graph->source = crm_strdup(reference); + if (reference) { + new_graph->source = crm_strdup(reference); } else { - new_graph->source = crm_strdup("unknown"); + new_graph->source = crm_strdup("unknown"); } - - if(xml_graph != NULL) { - t_id = crm_element_value(xml_graph, "transition_id"); - CRM_CHECK(t_id != NULL, crm_free(new_graph); return NULL); - new_graph->id = crm_parse_int(t_id, "-1"); - - time = crm_element_value(xml_graph, "cluster-delay"); - CRM_CHECK(time != NULL, crm_free(new_graph); return NULL); - new_graph->network_delay = crm_get_msec(time); - - time = crm_element_value(xml_graph, "stonith-timeout"); - if(time == NULL) { - new_graph->stonith_timeout = new_graph->network_delay; - } else { - new_graph->stonith_timeout = crm_get_msec(time); - } - - t_id = crm_element_value(xml_graph, "batch-limit"); - new_graph->batch_limit = crm_parse_int(t_id, "0"); + + if (xml_graph != NULL) { + t_id = crm_element_value(xml_graph, "transition_id"); + CRM_CHECK(t_id != NULL, crm_free(new_graph); + return NULL); + new_graph->id = crm_parse_int(t_id, "-1"); + + time = crm_element_value(xml_graph, "cluster-delay"); + CRM_CHECK(time != NULL, crm_free(new_graph); + return NULL); + new_graph->network_delay = crm_get_msec(time); + + time = crm_element_value(xml_graph, "stonith-timeout"); + if (time == NULL) { + new_graph->stonith_timeout = new_graph->network_delay; + } else { + new_graph->stonith_timeout = crm_get_msec(time); + } + + t_id = crm_element_value(xml_graph, "batch-limit"); + new_graph->batch_limit = crm_parse_int(t_id, "0"); + } + + for (synapse = __xml_first_child(xml_graph); synapse != NULL; synapse = __xml_next(synapse)) { + if (crm_str_eq((const char *)synapse->name, "synapse", TRUE)) { + synapse_t *new_synapse = unpack_synapse(new_graph, synapse); + + if (new_synapse != NULL) { + new_graph->synapses = g_list_append(new_graph->synapses, new_synapse); + } + } } - - for(synapse = __xml_first_child(xml_graph); synapse != NULL; synapse = __xml_next(synapse)) { - if(crm_str_eq((const char *)synapse->name, "synapse", TRUE)) { - synapse_t *new_synapse = unpack_synapse(new_graph, synapse); - if(new_synapse != NULL) { - new_graph->synapses = g_list_append( - new_graph->synapses, new_synapse); - } - } - } crm_info("Unpacked transition %d: %d actions in %d synapses", - new_graph->id, new_graph->num_actions,new_graph->num_synapses); + new_graph->id, new_graph->num_actions, new_graph->num_synapses); return new_graph; } static void -destroy_action(crm_action_t *action) +destroy_action(crm_action_t * action) { - if(action->timer && action->timer->source_id != 0) { - crm_warn("Cancelling timer for action %d (src=%d)", - action->id, action->timer->source_id); - g_source_remove(action->timer->source_id); + if (action->timer && action->timer->source_id != 0) { + crm_warn("Cancelling timer for action %d (src=%d)", action->id, action->timer->source_id); + g_source_remove(action->timer->source_id); } - if(action->params) { - g_hash_table_destroy(action->params); + if (action->params) { + g_hash_table_destroy(action->params); } free_xml(action->xml); crm_free(action->timer); crm_free(action); } static void -destroy_synapse(synapse_t *synapse) +destroy_synapse(synapse_t * synapse) { - while(g_list_length(synapse->actions) > 0) { - crm_action_t *action = g_list_nth_data(synapse->actions, 0); - synapse->actions = g_list_remove(synapse->actions, action); - destroy_action(action); + while (g_list_length(synapse->actions) > 0) { + crm_action_t *action = g_list_nth_data(synapse->actions, 0); + + synapse->actions = g_list_remove(synapse->actions, action); + destroy_action(action); } - - while(g_list_length(synapse->inputs) > 0) { - crm_action_t *action = g_list_nth_data(synapse->inputs, 0); - synapse->inputs = g_list_remove(synapse->inputs, action); - destroy_action(action); + + while (g_list_length(synapse->inputs) > 0) { + crm_action_t *action = g_list_nth_data(synapse->inputs, 0); + + synapse->inputs = g_list_remove(synapse->inputs, action); + destroy_action(action); } crm_free(synapse); } void -destroy_graph(crm_graph_t *graph) +destroy_graph(crm_graph_t * graph) { - if(graph == NULL) { - return; + if (graph == NULL) { + return; } - while(g_list_length(graph->synapses) > 0) { - synapse_t *synapse = g_list_nth_data(graph->synapses, 0); - graph->synapses = g_list_remove(graph->synapses, synapse); - destroy_synapse(synapse); + while (g_list_length(graph->synapses) > 0) { + synapse_t *synapse = g_list_nth_data(graph->synapses, 0); + + graph->synapses = g_list_remove(graph->synapses, synapse); + destroy_synapse(synapse); } crm_free(graph->source); crm_free(graph); } -lrm_op_t *convert_graph_action(xmlNode *resource, crm_action_t *action, int status, int rc) +lrm_op_t * +convert_graph_action(xmlNode * resource, crm_action_t * action, int status, int rc) { xmlNode *xop = NULL; lrm_op_t *op = NULL; GHashTableIter iter; const char *name = NULL; const char *value = NULL; xmlNode *action_resource = NULL; CRM_CHECK(action != NULL, return NULL); CRM_CHECK(action->type == action_type_rsc, return NULL); - + action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE); - CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "Bad"); return NULL); + CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "Bad"); + return NULL); crm_malloc0(op, sizeof(lrm_op_t)); op->app_name = crm_strdup(crm_system_name); op->rsc_id = crm_strdup(ID(action_resource)); op->interval = action->interval; op->op_type = crm_strdup(crm_element_value(action->xml, XML_LRM_ATTR_TASK)); op->rc = rc; op->op_status = status; op->params = g_hash_table_new_full(crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - - g_hash_table_iter_init (&iter, action->params); - while (g_hash_table_iter_next (&iter, (void**)&name, (void**)&value)) { - g_hash_table_insert(op->params, crm_strdup(name), crm_strdup(value)); - } - - for(xop = __xml_first_child(resource); xop != NULL; xop = __xml_next(xop)) { - int tmp = 0; - crm_element_value_int(xop, XML_LRM_ATTR_CALLID, &tmp); - crm_info("Got call_id=%d for %s", tmp, ID(resource)); - if(tmp > op->call_id) { - op->call_id = tmp; - } + g_hash_destroy_str, g_hash_destroy_str); + + g_hash_table_iter_init(&iter, action->params); + while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) { + g_hash_table_insert(op->params, crm_strdup(name), crm_strdup(value)); } - + + for (xop = __xml_first_child(resource); xop != NULL; xop = __xml_next(xop)) { + int tmp = 0; + + crm_element_value_int(xop, XML_LRM_ATTR_CALLID, &tmp); + crm_info("Got call_id=%d for %s", tmp, ID(resource)); + if (tmp > op->call_id) { + op->call_id = tmp; + } + } + op->call_id++; return op; } diff --git a/lib/transition/utils.c b/lib/transition/utils.c index 03252b39c5..e1c054fd94 100644 --- a/lib/transition/utils.c +++ b/lib/transition/utils.c @@ -1,284 +1,280 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 */ /* */ - extern crm_graph_functions_t *graph_fns; static gboolean -pseudo_action_dummy(crm_graph_t *graph, crm_action_t *action) +pseudo_action_dummy(crm_graph_t * graph, crm_action_t * action) { static int fail = -1; - if(fail < 0) { - char *fail_s = getenv("PE_fail"); - if(fail_s) { - fail = crm_int_helper(fail_s, NULL); - } else { - fail = 0; - } + + if (fail < 0) { + char *fail_s = getenv("PE_fail"); + + if (fail_s) { + fail = crm_int_helper(fail_s, NULL); + } else { + fail = 0; + } } - + crm_debug_2("Dummy event handler: action %d executed", action->id); - if(action->id == fail) { - crm_err("Dummy event handler: pretending action %d failed", action->id); - action->failed = TRUE; - graph->abort_priority = INFINITY; + if (action->id == fail) { + crm_err("Dummy event handler: pretending action %d failed", action->id); + action->failed = TRUE; + graph->abort_priority = INFINITY; } action->confirmed = TRUE; update_graph(graph, action); return TRUE; } crm_graph_functions_t default_fns = { pseudo_action_dummy, pseudo_action_dummy, pseudo_action_dummy, pseudo_action_dummy }; void -set_default_graph_functions(void) +set_default_graph_functions(void) { graph_fns = &default_fns; } void -set_graph_functions(crm_graph_functions_t *fns) +set_graph_functions(crm_graph_functions_t * fns) { crm_info("Setting custom graph functions"); graph_fns = fns; CRM_ASSERT(graph_fns != NULL); CRM_ASSERT(graph_fns->rsc != NULL); CRM_ASSERT(graph_fns->crmd != NULL); CRM_ASSERT(graph_fns->pseudo != NULL); CRM_ASSERT(graph_fns->stonith != NULL); } const char * -transition_status(enum transition_status state) +transition_status(enum transition_status state) { - switch(state) { - case transition_active: - return "active"; - case transition_pending: - return "pending"; - case transition_complete: - return "complete"; - case transition_stopped: - return "stopped"; - case transition_terminated: - return "terminated"; - case transition_action_failed: - return "failed (action)"; - case transition_failed: - return "failed"; + switch (state) { + case transition_active: + return "active"; + case transition_pending: + return "pending"; + case transition_complete: + return "complete"; + case transition_stopped: + return "stopped"; + case transition_terminated: + return "terminated"; + case transition_action_failed: + return "failed (action)"; + case transition_failed: + return "failed"; } - return "unknown"; + return "unknown"; } - const char * actiontype2text(action_type_e type) { - switch(type) { - case action_type_pseudo: - return "pseduo"; - case action_type_rsc: - return "rsc"; - case action_type_crm: - return "crm"; - + switch (type) { + case action_type_pseudo: + return "pseduo"; + case action_type_rsc: + return "rsc"; + case action_type_crm: + return "crm"; + } return ""; } static void -print_elem(int log_level, const char *prefix, gboolean as_input, crm_action_t *action) +print_elem(int log_level, const char *prefix, gboolean as_input, crm_action_t * action) { int priority = 0; const char *key = NULL; const char *host = NULL; const char *class = "Action"; const char *state = "Pending"; - if(action->failed) { - state = "Failed"; + if (action->failed) { + state = "Failed"; - } else if(action->confirmed) { - state = "Completed"; + } else if (action->confirmed) { + state = "Completed"; - } else if(action->executed) { - state = "In-flight"; + } else if (action->executed) { + state = "In-flight"; - } else if(action->sent_update) { - state = "Update sent"; + } else if (action->sent_update) { + state = "Update sent"; } - if(as_input) { - class = "Input"; + if (as_input) { + class = "Input"; } - if(as_input == FALSE) { - priority = action->synapse->priority; + if (as_input == FALSE) { + priority = action->synapse->priority; } - + key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - - switch(action->type) { - case action_type_pseudo: - do_crm_log(log_level, - "%s[%s %d]: %s (id: %s, type: %s, priority: %d)", - prefix, class, action->id, state, key, - actiontype2text(action->type), - priority); - break; - case action_type_rsc: - do_crm_log(log_level, - "%s[%s %d]: %s (id: %s, loc: %s, priority: %d)", - prefix, class, action->id, state, key, host, - priority); - break; - case action_type_crm: - do_crm_log(log_level, - "%s[%s %d]: %s (id: %s, loc: %s, type: %s, priority: %d)", - prefix, class, action->id, state, key, host, - actiontype2text(action->type), - priority); - break; - default: - crm_err("%s[%s %d]: %s (id: %s, loc: %s, type: %s (unhandled), priority: %d)", - prefix, class, action->id, state, key, host, - actiontype2text(action->type), - priority); + + switch (action->type) { + case action_type_pseudo: + do_crm_log(log_level, + "%s[%s %d]: %s (id: %s, type: %s, priority: %d)", + prefix, class, action->id, state, key, + actiontype2text(action->type), priority); + break; + case action_type_rsc: + do_crm_log(log_level, + "%s[%s %d]: %s (id: %s, loc: %s, priority: %d)", + prefix, class, action->id, state, key, host, priority); + break; + case action_type_crm: + do_crm_log(log_level, + "%s[%s %d]: %s (id: %s, loc: %s, type: %s, priority: %d)", + prefix, class, action->id, state, key, host, + actiontype2text(action->type), priority); + break; + default: + crm_err("%s[%s %d]: %s (id: %s, loc: %s, type: %s (unhandled), priority: %d)", + prefix, class, action->id, state, key, host, + actiontype2text(action->type), priority); } - if(as_input == FALSE) { - return; + if (as_input == FALSE) { + return; } - - if(action->timer) { - do_crm_log(log_level, "%s\ttimeout=%d, timer=%d", prefix, - action->timeout, action->timer->source_id); + + if (action->timer) { + do_crm_log(log_level, "%s\ttimeout=%d, timer=%d", prefix, + action->timeout, action->timer->source_id); } - - if(action->confirmed == FALSE) { - crm_log_xml(LOG_DEBUG_3, "\t\t\tRaw xml: ", action->xml); + + if (action->confirmed == FALSE) { + crm_log_xml(LOG_DEBUG_3, "\t\t\tRaw xml: ", action->xml); } } void -print_action(int log_level, const char *prefix, crm_action_t *action) +print_action(int log_level, const char *prefix, crm_action_t * action) { print_elem(log_level, prefix, FALSE, action); } void -print_graph(unsigned int log_level, crm_graph_t *graph) +print_graph(unsigned int log_level, crm_graph_t * graph) { GListPtr lpc = NULL; - if(graph == NULL || graph->num_actions == 0) { - if(log_level > LOG_DEBUG) { - crm_debug("## Empty transition graph ##"); - } - return; + + if (graph == NULL || graph->num_actions == 0) { + if (log_level > LOG_DEBUG) { + crm_debug("## Empty transition graph ##"); + } + return; } - + do_crm_log(log_level, "Graph %d (%d actions in %d synapses):" - " batch-limit=%d jobs, network-delay=%dms", - graph->id, graph->num_actions, graph->num_synapses, - graph->batch_limit, graph->network_delay); - - for(lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { - synapse_t *synapse = (synapse_t*)lpc->data; - - do_crm_log(log_level, "Synapse %d %s (priority: %d)", - synapse->id, - synapse->confirmed?"was confirmed": - synapse->executed?"was executed": - "is pending", - synapse->priority); - - if(synapse->confirmed == FALSE) { - GListPtr lpc2 = NULL; - for(lpc2 = synapse->actions; lpc2 != NULL; lpc2 = lpc2->next) { - crm_action_t *action = (crm_action_t*)lpc2->data; - print_elem(log_level, " ", FALSE, action); - } - } - if(synapse->executed == FALSE) { - GListPtr lpc2 = NULL; - for(lpc2 = synapse->inputs; lpc2 != NULL; lpc2 = lpc2->next) { - crm_action_t *input = (crm_action_t*)lpc2->data; - print_elem(log_level, " * ", TRUE, input); - } - } + " batch-limit=%d jobs, network-delay=%dms", + graph->id, graph->num_actions, graph->num_synapses, + graph->batch_limit, graph->network_delay); + + for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { + synapse_t *synapse = (synapse_t *) lpc->data; + + do_crm_log(log_level, "Synapse %d %s (priority: %d)", + synapse->id, + synapse->confirmed ? "was confirmed" : + synapse->executed ? "was executed" : "is pending", synapse->priority); + + if (synapse->confirmed == FALSE) { + GListPtr lpc2 = NULL; + + for (lpc2 = synapse->actions; lpc2 != NULL; lpc2 = lpc2->next) { + crm_action_t *action = (crm_action_t *) lpc2->data; + + print_elem(log_level, " ", FALSE, action); + } + } + if (synapse->executed == FALSE) { + GListPtr lpc2 = NULL; + + for (lpc2 = synapse->inputs; lpc2 != NULL; lpc2 = lpc2->next) { + crm_action_t *input = (crm_action_t *) lpc2->data; + + print_elem(log_level, " * ", TRUE, input); + } + } } } -static const char *abort2text(enum transition_action abort_action) +static const char * +abort2text(enum transition_action abort_action) { - switch(abort_action) { - case tg_done: - return "done"; - case tg_stop: - return "stop"; - case tg_restart: - return "restart"; - case tg_shutdown: - return "shutdown"; + switch (abort_action) { + case tg_done: + return "done"; + case tg_stop: + return "stop"; + case tg_restart: + return "restart"; + case tg_shutdown: + return "shutdown"; } return "unknown"; } void -update_abort_priority( - crm_graph_t *graph, int priority, - enum transition_action action, const char *abort_reason) +update_abort_priority(crm_graph_t * graph, int priority, + enum transition_action action, const char *abort_reason) { - if(graph == NULL) { - return; + if (graph == NULL) { + return; } - - if(graph->abort_priority < priority) { - crm_info("Abort priority upgraded from %d to %d", - graph->abort_priority, priority); - graph->abort_priority = priority; - if(graph->abort_reason != NULL) { - crm_info("'%s' abort superceeded", - graph->abort_reason); - } - graph->abort_reason = abort_reason; + + if (graph->abort_priority < priority) { + crm_info("Abort priority upgraded from %d to %d", graph->abort_priority, priority); + graph->abort_priority = priority; + if (graph->abort_reason != NULL) { + crm_info("'%s' abort superceeded", graph->abort_reason); + } + graph->abort_reason = abort_reason; } - if(graph->completion_action < action) { - crm_info("Abort action %s superceeded by %s", - abort2text(graph->completion_action), abort2text(action)); - graph->completion_action = action; + if (graph->completion_action < action) { + crm_info("Abort action %s superceeded by %s", + abort2text(graph->completion_action), abort2text(action)); + graph->completion_action = action; } } -