diff --git a/crm/crmd/cib.c b/crm/crmd/cib.c index 8f9d4c7e6c..c0233be0af 100644 --- a/crm/crmd/cib.c +++ b/crm/crmd/cib.c @@ -1,281 +1,281 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include /* for access */ #include #include #include /* for calls to open */ #include /* for calls to open */ #include /* for calls to open */ #include /* for getpwuid */ #include /* for initgroups */ #include /* for getrlimit */ #include /* for getrlimit */ #include #include #include #include #include #include #include #include struct crm_subsystem_s *cib_subsystem = NULL; /* A_CIB_STOP, A_CIB_START, A_CIB_RESTART, */ enum crmd_fsa_input do_cib_control(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { enum crmd_fsa_input result = I_NULL; struct crm_subsystem_s *this_subsys = cib_subsystem; long long stop_actions = A_CIB_STOP; long long start_actions = A_CIB_START; if(action & stop_actions) { /* dont do anything, its embedded now */ } if(action & start_actions) { if(cur_state != S_STOPPING) { if(startCib(CIB_FILENAME) == FALSE) result = I_FAIL; } else { crm_info("Ignoring request to start %s after shutdown", - this_subsys->command); + this_subsys->name); } } return result; } /* A_CIB_INVOKE, A_CIB_BUMPGEN, A_UPDATE_NODESTATUS */ enum crmd_fsa_input do_cib_invoke(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { xmlNodePtr cib_msg = NULL; xmlNodePtr answer = NULL; xmlNodePtr new_options = NULL; const char *section = NULL; enum crmd_fsa_input result = I_NULL; if(msg_data->data != NULL) { cib_msg = (xmlNodePtr)msg_data->data; } if(action & A_CIB_INVOKE || action & A_CIB_INVOKE_LOCAL) { /* gboolean is_update = FALSE; */ xmlNodePtr msg_copy = copy_xml_node_recursive(cib_msg); xmlNodePtr options = find_xml_node(msg_copy, XML_TAG_OPTIONS); const char *sys_from = xmlGetProp(msg_copy, XML_ATTR_SYSFROM); const char *host_from= xmlGetProp(msg_copy, XML_ATTR_HOSTFROM); const char *type = xmlGetProp(options, XML_ATTR_MSGTYPE); const char *op = xmlGetProp(options, XML_ATTR_OP); crm_xml_devel(msg_copy, "[CIB update]"); if(cib_msg == NULL) { crm_err("No message for CIB command"); return I_NULL; /* I_ERROR */ } else if(op == NULL) { crm_xml_devel(msg_copy, "Invalid CIB Message"); return I_NULL; /* I_ERROR */ } if(AM_I_DC && safe_str_eq(op, CRM_OP_RETRIVE_CIB) && safe_str_eq(type, XML_ATTR_RESPONSE)) { /* we actually need to process this as a REPLACE, * not pretty, but fake the op type... */ crm_debug("Mapping %s reply to a %s request", CRM_OP_RETRIVE_CIB, CRM_OP_REPLACE); set_xml_property_copy( options, XML_ATTR_OP, CRM_OP_REPLACE); crm_xml_devel(msg_copy, "[CIB revised update]"); } else if(safe_str_eq(op, CRM_OP_RETRIVE_CIB)) { crm_debug("is dc? %d, type=%s", AM_I_DC, type); } set_xml_property_copy(msg_copy, XML_ATTR_SYSTO, "cib"); answer = process_cib_message(msg_copy, TRUE); if(action & A_CIB_INVOKE) { if(AM_I_DC == FALSE) { if(relay_message(answer, TRUE) == FALSE) { crm_err("Confused what to do with cib result"); crm_xml_devel(answer, "Couldnt route: "); result = I_ERROR; } } else if(strcmp(op, CRM_OP_CREATE) == 0 || strcmp(op, CRM_OP_UPDATE) == 0 || strcmp(op, CRM_OP_DELETE) == 0 || strcmp(op, CRM_OP_REPLACE) == 0 || strcmp(op, CRM_OP_RETRIVE_CIB) == 0 || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) { register_fsa_input( C_IPC_MESSAGE, I_CIB_UPDATE, cib_msg); } else if(strcmp(op, CRM_OP_RETRIVE_CIB) == 0) { crm_info("Retrieved latest CIB from %s", host_from); set_bit_inplace(fsa_input_register,R_HAVE_CIB); } else if(strcmp(op, CRM_OP_ERASE) == 0) { /* regenerate everyone's state and our node entry */ register_fsa_input( C_UNKNOWN, I_ELECTION_DC, NULL); } /* the TENGINE will get CC'd by other means. */ if(AM_I_DC && sys_from != NULL && safe_str_neq(sys_from, CRM_SYSTEM_TENGINE) && safe_str_neq(sys_from, CRM_SYSTEM_CRMD) && safe_str_neq(sys_from, CRM_SYSTEM_DC) && relay_message(answer, TRUE) == FALSE) { crm_err("Confused what to do with cib result"); crm_xml_devel(answer, "Couldnt route: "); result = I_ERROR; } /* } else { */ /* put_message(answer); */ /* return I_REQUEST; */ } return result; } else if(action & A_CIB_BUMPGEN) { /* xmlNodePtr options = find_xml_node(cib_msg, XML_TAG_OPTIONS); */ /* const char *op = xmlGetProp(options, XML_ATTR_OP); */ if(AM_I_DC == FALSE) { return I_NULL; } /* check if the response was ok before next bit */ /* if(safe_str_neq(op, CRM_OP_WELCOME)) { */ /* set the section so that we dont always send the * whole thing */ section = get_xml_attr( cib_msg, XML_TAG_OPTIONS, XML_ATTR_FILTER_TYPE, FALSE); /* } */ if(section != NULL) { new_options = set_xml_attr( NULL, XML_TAG_OPTIONS, XML_ATTR_FILTER_TYPE, section, TRUE); } answer = process_cib_request( CRM_OP_BUMP, new_options, NULL); free_xml(new_options); if(answer == NULL) { crm_err("Result of BUMP in %s was NULL", __FUNCTION__); return I_FAIL; } send_request(NULL, answer, CRM_OP_REPLACE, NULL, CRM_SYSTEM_CRMD, NULL); free_xml(answer); } else { crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } return I_NULL; } enum crmd_fsa_input invoke_local_cib(xmlNodePtr msg_options, xmlNodePtr msg_data, const char *operation) { enum crmd_fsa_input result = I_NULL; xmlNodePtr request = NULL; fsa_data_t *fsa_data = NULL; msg_options = set_xml_attr(msg_options, XML_TAG_OPTIONS, XML_ATTR_OP, operation, TRUE); request = create_request(msg_options, msg_data, NULL, CRM_SYSTEM_CIB, AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD, NULL, NULL); crm_malloc(fsa_data, sizeof(fsa_data_t)); fsa_data->fsa_input = I_CIB_UPDATE; fsa_data->fsa_cause = C_IPC_MESSAGE; fsa_data->data = request; result = do_cib_invoke( A_CIB_INVOKE_LOCAL, C_FSA_INTERNAL, fsa_state, I_CIB_OP, fsa_data); crm_free(fsa_data); free_xml(request); return I_NULL; } diff --git a/crm/crmd/control.c b/crm/crmd/control.c index eb0f425a2a..0174e99032 100644 --- a/crm/crmd/control.c +++ b/crm/crmd/control.c @@ -1,623 +1,631 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include extern void crmd_ha_connection_destroy(gpointer user_data); extern gboolean stop_all_resources(void); void crm_shutdown(int nsig); IPC_WaitConnection *wait_channel_init(char daemonsocket[]); gboolean register_with_ha(ll_cluster_t *hb_cluster, const char *client_name); int init_server_ipc_comms( const char *child, gboolean (*channel_client_connect)( IPC_Channel *newclient, gpointer user_data), void (*channel_connection_destroy)(gpointer user_data)); GHashTable *ipc_clients = NULL; /* A_HA_CONNECT */ enum crmd_fsa_input do_ha_control(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { gboolean registered = FALSE; if(action & A_HA_DISCONNECT) { if(fsa_cluster_conn != NULL) { fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn); } } if(action & A_HA_CONNECT) { if(fsa_cluster_conn == NULL) fsa_cluster_conn = ll_cluster_new("heartbeat"); /* make sure we are disconnected first */ fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn); registered = register_with_ha( fsa_cluster_conn, crm_system_name); if(registered == FALSE) { return I_FAIL; } } if(action & ~(A_HA_CONNECT|A_HA_DISCONNECT)) { crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } return I_NULL; } /* A_SHUTDOWN */ enum crmd_fsa_input do_shutdown(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { enum crmd_fsa_input next_input = I_NULL; enum crmd_fsa_input tmp = I_NULL; /* just in case */ set_bit_inplace(fsa_input_register, R_SHUTDOWN); /* last attempt to shut these down */ if(is_set(fsa_input_register, R_PE_CONNECTED)) { crm_warn("Last attempt to shutdown the PolicyEngine"); tmp = do_pe_control(A_PE_STOP, cause, cur_state, current_input, msg_data); if(tmp != I_NULL) { next_input = I_ERROR; crm_err("Failed to shutdown the PolicyEngine"); } } if(is_set(fsa_input_register, R_TE_CONNECTED)) { crm_warn("Last attempt to shutdown the Transitioner"); tmp = do_pe_control(A_TE_STOP, cause, cur_state, current_input, msg_data); if(tmp != I_NULL) { next_input = I_ERROR; crm_err("Failed to shutdown the Transitioner"); } } crm_info("Stopping all remaining local resources"); stop_all_resources(); return next_input; } /* A_SHUTDOWN_REQ */ enum crmd_fsa_input do_shutdown_req(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { enum crmd_fsa_input next_input = I_NULL; if(send_request(NULL, NULL, CRM_OP_SHUTDOWN_REQ, NULL, CRM_SYSTEM_DC, NULL) == FALSE){ next_input = I_ERROR; } return next_input; } /* A_EXIT_0, A_EXIT_1 */ enum crmd_fsa_input do_exit(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { if(action & A_EXIT_0) { crm_info("Performing %s - gracefully exiting the CRMd\n", fsa_action2string(action)); g_main_quit(crmd_mainloop); } else { crm_warn("Performing %s - forcefully exiting the CRMd\n", fsa_action2string(action)); exit(1); } return I_NULL; } /* A_STARTUP */ enum crmd_fsa_input do_startup(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { int was_error = 0; int interval = 1; /* seconds between DC heartbeats */ crm_info("Register PID"); register_pid(PID_FILE, FALSE, crm_shutdown); - /* Async get client status information in the cluster */ - fsa_cluster_conn->llc_ops->client_status( - fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD, -1); - ipc_clients = g_hash_table_new(&g_str_hash, &g_str_equal); if(was_error == 0) { crm_info("Init server comms"); was_error = init_server_ipc_comms( CRM_SYSTEM_CRMD, crmd_client_connect, default_ipc_connection_destroy); } /* set up the timers */ crm_malloc(dc_heartbeat, sizeof(fsa_timer_t)); crm_malloc(integration_timer, sizeof(fsa_timer_t)); crm_malloc(finalization_timer, sizeof(fsa_timer_t)); crm_malloc(election_trigger, sizeof(fsa_timer_t)); crm_malloc(election_timeout, sizeof(fsa_timer_t)); crm_malloc(shutdown_escalation_timer, sizeof(fsa_timer_t)); crm_malloc(wait_timer, sizeof(fsa_timer_t)); interval = interval * 1000; if(election_trigger != NULL) { election_trigger->source_id = -1; election_trigger->period_ms = -1; election_trigger->fsa_input = I_DC_TIMEOUT; election_trigger->callback = timer_popped; } else { was_error = TRUE; } if(dc_heartbeat != NULL) { dc_heartbeat->source_id = -1; dc_heartbeat->period_ms = -1; dc_heartbeat->fsa_input = I_NULL; dc_heartbeat->callback = do_dc_heartbeat; } else { was_error = TRUE; } if(election_timeout != NULL) { election_timeout->source_id = -1; election_timeout->period_ms = -1; election_timeout->fsa_input = I_ELECTION_DC; election_timeout->callback = timer_popped; } else { was_error = TRUE; } if(integration_timer != NULL) { integration_timer->source_id = -1; integration_timer->period_ms = -1; integration_timer->fsa_input = I_INTEGRATED; integration_timer->callback = timer_popped; } else { was_error = TRUE; } if(finalization_timer != NULL) { finalization_timer->source_id = -1; finalization_timer->period_ms = -1; finalization_timer->fsa_input = I_FINALIZED; finalization_timer->callback = timer_popped; } else { was_error = TRUE; } if(shutdown_escalation_timer != NULL) { shutdown_escalation_timer->source_id = -1; shutdown_escalation_timer->period_ms = -1; shutdown_escalation_timer->fsa_input = I_TERMINATE; shutdown_escalation_timer->callback = timer_popped; } else { was_error = TRUE; } if(wait_timer != NULL) { wait_timer->source_id = -1; wait_timer->period_ms = 3*1000; wait_timer->fsa_input = I_NULL; wait_timer->callback = timer_popped; } else { was_error = TRUE; } /* set up the sub systems */ crm_malloc(cib_subsystem, sizeof(struct crm_subsystem_s)); crm_malloc(te_subsystem, sizeof(struct crm_subsystem_s)); crm_malloc(pe_subsystem, sizeof(struct crm_subsystem_s)); if(cib_subsystem != NULL) { - cib_subsystem->pid = 0; - cib_subsystem->path = crm_strdup(BIN_DIR); - cib_subsystem->name = crm_strdup(CRM_SYSTEM_CIB); - cib_subsystem->command = BIN_DIR"/cib"; - cib_subsystem->flag = R_CIB_CONNECTED; + cib_subsystem->pid = -1; + cib_subsystem->flag = R_CIB_CONNECTED; + cib_subsystem->path = BIN_DIR; + cib_subsystem->name = CRM_SYSTEM_CIB; + cib_subsystem->command = BIN_DIR"/"CRM_SYSTEM_CIB; + cib_subsystem->args = "-VVc"; + } else { was_error = TRUE; } if(te_subsystem != NULL) { - te_subsystem->pid = 0; - te_subsystem->path = crm_strdup(BIN_DIR); - te_subsystem->name = crm_strdup(CRM_SYSTEM_TENGINE); - te_subsystem->command = BIN_DIR"/tengine"; - te_subsystem->flag = R_TE_CONNECTED; + te_subsystem->pid = -1; + te_subsystem->flag = R_TE_CONNECTED; + te_subsystem->path = BIN_DIR; + te_subsystem->name = CRM_SYSTEM_TENGINE; + te_subsystem->command = BIN_DIR"/"CRM_SYSTEM_TENGINE; + te_subsystem->args = "-VVc"; + } else { was_error = TRUE; } if(pe_subsystem != NULL) { - pe_subsystem->pid = 0; - pe_subsystem->path = crm_strdup(BIN_DIR); - pe_subsystem->name = crm_strdup(CRM_SYSTEM_PENGINE); - pe_subsystem->command = BIN_DIR"/pengine"; - pe_subsystem->flag = R_PE_CONNECTED; + pe_subsystem->pid = -1; + pe_subsystem->flag = R_PE_CONNECTED; + pe_subsystem->path = BIN_DIR; + pe_subsystem->name = CRM_SYSTEM_PENGINE; + pe_subsystem->command = BIN_DIR"/"CRM_SYSTEM_PENGINE; + pe_subsystem->args = "-VVc"; + } else { was_error = TRUE; } if(was_error) return I_FAIL; return I_NULL; } /* A_STOP */ enum crmd_fsa_input do_stop(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { /* nothing to do yet */ /* todo: shut down any remaining CRM resources */ return I_NULL; } /* A_STARTED */ enum crmd_fsa_input do_started(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { if(is_set(fsa_input_register, R_CCM_DATA) == FALSE /* || is_set(fsa_input_register, R_PE_CONNECTED) == FALSE */ /* || is_set(fsa_input_register, R_TE_CONNECTED) == FALSE */ || is_set(fsa_input_register, R_LRM_CONNECTED) == FALSE ) { crm_info("Delaying start, some systems not connected %.16llx (%.16llx)", fsa_input_register, (long long)R_CCM_DATA|R_LRM_CONNECTED); crmd_fsa_stall(); return I_NULL; } else if(is_set(fsa_input_register, R_PEER_DATA) == FALSE) { struct ha_msg* msg = NULL; /* try reading from HA */ crm_info("Delaying start, some systems not connected %.16llx (%.16llx)", fsa_input_register, (long long)R_PEER_DATA); crm_debug("Looking for a HA message"); msg = fsa_cluster_conn->llc_ops->readmsg(fsa_cluster_conn, 0); if(msg != NULL) { crm_debug("There was a HA message"); ha_msg_del(msg); } startTimer(wait_timer); crmd_fsa_stall(); return I_NULL; } crm_info("The local CRM is operational"); clear_bit_inplace(fsa_input_register, R_STARTING); register_fsa_input(msg_data->fsa_cause, I_PENDING, NULL); return I_NULL; } /* A_RECOVER */ enum crmd_fsa_input do_recover(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { crm_err("Action %s (%.16llx) not supported\n", fsa_action2string(action), action); return I_SHUTDOWN; } /* A_READCONFIG */ enum crmd_fsa_input do_read_config(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { xmlNodePtr cib_copy = get_cib_copy(); xmlNodePtr config = get_object_root(XML_CIB_TAG_CRMCONFIG, cib_copy); xml_child_iter( config, iter, XML_CIB_TAG_NVPAIR, const char *name = xmlGetProp(iter, XML_NVPAIR_ATTR_NAME); const char *value = xmlGetProp(iter, XML_NVPAIR_ATTR_VALUE); if(name == NULL || value == NULL) { continue; } else if(safe_str_eq(name, "dc_heartbeat")) { dc_heartbeat->period_ms = atoi(value); } else if(safe_str_eq(name, "dc_deadtime")) { election_trigger->period_ms = atoi(value); } else if(safe_str_eq(name, "shutdown_escalation")) { shutdown_escalation_timer->period_ms = atoi(value); } else if(safe_str_eq(name, "join_reannouce")) { fsa_join_reannouce = atoi(value); } ); if(dc_heartbeat->period_ms < 1) { /* sensible default */ dc_heartbeat->period_ms = 1000; } if(election_trigger->period_ms < 1) { /* sensible default */ election_trigger->period_ms = dc_heartbeat->period_ms * 4; } if(shutdown_escalation_timer->period_ms < 1) { /* sensible default */ shutdown_escalation_timer->period_ms = election_trigger->period_ms * 3 *10;/* 10 for testing */ } if(fsa_join_reannouce < 0) { fsa_join_reannouce = 100; /* how many times should we let * go by before reannoucning * ourselves to the DC */ } election_timeout->period_ms = dc_heartbeat->period_ms * 6; integration_timer->period_ms = dc_heartbeat->period_ms * 6; finalization_timer->period_ms = dc_heartbeat->period_ms * 6; return I_NULL; } void crm_shutdown(int nsig) { CL_SIGNAL(nsig, crm_shutdown); if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) { if(is_set(fsa_input_register, R_SHUTDOWN)) { crm_err("Escalating the shutdown"); register_fsa_input(C_SHUTDOWN, I_ERROR, NULL); s_crmd_fsa(C_SHUTDOWN); } else { set_bit_inplace(fsa_input_register, R_SHUTDOWN); if(is_set(fsa_input_register, R_SHUTDOWN)) { /* cant rely on this... */ startTimer(shutdown_escalation_timer); register_fsa_input(C_SHUTDOWN, I_SHUTDOWN, NULL); s_crmd_fsa(C_SHUTDOWN); } else { crm_err("Could not set R_SHUTDOWN"); exit(LSB_EXIT_ENOTSUPPORTED); } } } else { crm_info("exit from shutdown"); exit(LSB_EXIT_OK); } return; } 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(g_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) { cl_perror("Can't create wait channel of type %s", IPC_ANYTYPE); exit(1); } mask = umask(mask); g_hash_table_destroy(attrs); return wait_ch; } int init_server_ipc_comms( const char *child, 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, WORKING_DIR "/%s", child); 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, wait_ch, channel_connection_destroy); crm_debug("Listening on: %s", commpath); return 0; } #define safe_val3(def, t,u,v) (t?t->u?t->u->v:def:def) gboolean register_with_ha(ll_cluster_t *hb_cluster, const char *client_name) { int facility; if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) { crm_crit("cluster errmsg function unavailable"); } crm_info("Signing in with Heartbeat"); if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) { crm_err("Cannot sign on with heartbeat: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } /* change the logging facility to the one used by heartbeat daemon */ crm_info("Switching to Heartbeat logger"); if (( facility = hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) { cl_log_set_facility(facility); } crm_verbose("Facility: %d", facility); crm_debug("Be informed of CRM messages"); if (HA_OK != hb_cluster->llc_ops->set_msg_callback( hb_cluster, T_CRM, crmd_ha_msg_callback, hb_cluster)){ crm_err("Cannot set msg callback: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } #if 0 crm_debug("Be informed of Node Status changes"); if (HA_OK != hb_cluster->llc_ops->set_nstatus_callback( hb_cluster, crmd_ha_status_callback, hb_cluster)){ crm_err("Cannot set nstatus callback: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } #endif crm_debug("Be informed of CRM Client Status changes"); if (HA_OK != hb_cluster->llc_ops->set_cstatus_callback( hb_cluster, crmd_client_status_callback, hb_cluster)) { crm_err("Cannot set cstatus callback: %s\n", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } crm_debug("Adding channel to mainloop"); G_main_add_IPC_Channel( G_PRIORITY_HIGH, hb_cluster->llc_ops->ipcchan(hb_cluster), FALSE, crmd_ha_msg_dispatch, hb_cluster /* userdata */, crmd_ha_connection_destroy); crm_debug("Finding our node name"); if ((fsa_our_uname = hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) { crm_err("get_mynodeid() failed"); return FALSE; } crm_info("FSA Hostname: %s", fsa_our_uname); + /* Async get client status information in the cluster */ + crm_debug("Requesting an initial dump of CRMD client_status"); + fsa_cluster_conn->llc_ops->client_status( + fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD, -1); + + return TRUE; } diff --git a/crm/crmd/crmd_fsa.h b/crm/crmd/crmd_fsa.h index 30171f1c9c..c522f4ad60 100644 --- a/crm/crmd/crmd_fsa.h +++ b/crm/crmd/crmd_fsa.h @@ -1,126 +1,127 @@ -/* $Id: crmd_fsa.h,v 1.31 2004/10/12 21:05:53 andrew Exp $ */ +/* $Id: crmd_fsa.h,v 1.32 2004/11/24 15:37:44 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CRMD_FSA__H #define CRMD_FSA__H #include #include #include #include #include #include #include struct crmd_ccm_data_s { oc_ev_membership_t *oc; oc_ed_t *event; }; struct oc_node_list_s { int members_size; GHashTable *members; /* contents: oc_node_t * */ int new_members_size; GHashTable *new_members; /* contents: oc_node_t * */ int dead_members_size; GHashTable *dead_members; /* contents: oc_node_t * */ }; typedef struct oc_node_list_s oc_node_list_t; /* copy from struct client_child in heartbeat.h * * Plus a couple of other things */ struct crm_subsystem_s { - pid_t pid; /* Process id of child process */ - const char* command; /* What command to run? */ - const char* path; /* Path (argv[0])? */ -/* extras */ - const char* name; - IPC_Channel *ipc; /* How can we communicate with it */ - long long flag; /* */ + pid_t pid; /* Process id of child process */ + const char* name; /* executable name */ + const char* path; /* Command location */ + const char* command; /* Command with path */ + const char* args; /* Command arguments */ + + IPC_Channel *ipc; /* How can we communicate with it */ + long long flag; /* */ }; typedef struct fsa_timer_s fsa_timer_t; struct fsa_timer_s { guint source_id; /* timer source id */ int period_ms; /* timer period */ enum crmd_fsa_input fsa_input; gboolean (*callback)(gpointer data); }; typedef struct fsa_data_s fsa_data_t; struct fsa_data_s { int id; enum crmd_fsa_input fsa_input; enum crmd_fsa_cause fsa_cause; long long actions; const char *where; void *data; }; extern enum crmd_fsa_state s_crmd_fsa(enum crmd_fsa_cause cause); /* Global FSA stuff */ extern volatile gboolean do_fsa_stall; extern volatile enum crmd_fsa_state fsa_state; extern oc_node_list_t *fsa_membership_copy; extern ll_cluster_t *fsa_cluster_conn; extern ll_lrm_t *fsa_lrm_conn; extern volatile long long fsa_input_register; extern volatile long long fsa_actions; extern const char *fsa_our_uname; extern char *fsa_pe_ref; /* the last invocation of the PE */ extern char *fsa_our_dc; extern GListPtr fsa_message_queue; extern fsa_timer_t *election_trigger; /* */ extern fsa_timer_t *election_timeout; /* */ extern fsa_timer_t *shutdown_escalation_timer; /* */ extern fsa_timer_t *dc_heartbeat; extern fsa_timer_t *integration_timer; extern fsa_timer_t *finalization_timer; extern fsa_timer_t *wait_timer; extern int fsa_join_reannouce; extern struct crm_subsystem_s *cib_subsystem; extern struct crm_subsystem_s *te_subsystem; extern struct crm_subsystem_s *pe_subsystem; /* these two should be moved elsewhere... */ extern xmlNodePtr do_update_cib_nodes(xmlNodePtr updates, gboolean overwrite); extern gboolean do_dc_heartbeat(gpointer data); #define AM_I_DC is_set(fsa_input_register, R_THE_DC) #define AM_I_OPERATIONAL (is_set(fsa_input_register, R_STARTING)==FALSE) #include #include #endif diff --git a/crm/crmd/subsystems.c b/crm/crmd/subsystems.c index a52ac6ba05..ce95cca46d 100644 --- a/crm/crmd/subsystems.c +++ b/crm/crmd/subsystems.c @@ -1,174 +1,182 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include /* for access */ #include #include #include /* for calls to open */ #include /* for calls to open */ #include /* for calls to open */ #include /* for getpwuid */ #include /* for initgroups */ #include /* for getrlimit */ #include /* for getrlimit */ #include #include #include #include #include #include #include #include gboolean stop_subsystem(struct crm_subsystem_s* the_subsystem) { crm_info("Stopping sub-system \"%s\"", the_subsystem->name); if (the_subsystem->pid <= 0) { - crm_err("Client %s not running yet", the_subsystem->command); + crm_err("Client %s not running yet", the_subsystem->name); } else if(! is_set(fsa_input_register, the_subsystem->flag) ) { /* running but not yet connected */ crm_warn("Stopping %s before it had connected", the_subsystem->name); kill(the_subsystem->pid, -9); the_subsystem->pid = -1; } else { crm_info("Sending quit message to %s.", the_subsystem->name); send_request(NULL,NULL, CRM_OP_QUIT, NULL, the_subsystem->name, NULL); } return TRUE; } gboolean start_subsystem(struct crm_subsystem_s* the_subsystem) { pid_t pid; struct stat buf; int s_res; unsigned int j; struct rlimit oflimits; const char *devnull = "/dev/null"; - crm_info("Starting sub-system \"%s\"", the_subsystem->command); + crm_info("Starting sub-system \"%s\"", the_subsystem->name); if (the_subsystem->pid > 0) { crm_warn("Client %s already running as pid %d", - the_subsystem->command, (int) the_subsystem->pid); + the_subsystem->name, (int) the_subsystem->pid); /* starting a started X is not an error */ return TRUE; } /* * We want to ensure that the exec will succeed before * we bother forking. */ if (access(the_subsystem->path, F_OK|X_OK) != 0) { cl_perror("Cannot (access) exec %s", the_subsystem->path); return FALSE; } s_res = stat(the_subsystem->command, &buf); if(s_res != 0) { cl_perror("Cannot (stat) exec %s", the_subsystem->command); return FALSE; } /* We need to fork so we can make child procs not real time */ switch(pid=fork()) { case -1: crm_err("Cannot fork."); return FALSE; default: /* Parent */ the_subsystem->pid = pid; return TRUE; case 0: /* Child */ break; } - crm_info("Executing \"%s\" (pid %d)", - the_subsystem->command, (int) getpid()); + crm_info("Executing \"%s %s\" (pid %d)", + the_subsystem->command, the_subsystem->args, (int) getpid()); /* A precautionary measure */ getrlimit(RLIMIT_NOFILE, &oflimits); for (j=0; j < oflimits.rlim_cur; ++j) { close(j); } (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ - (void)execl("/bin/sh", "sh", "-c", the_subsystem->command, - (const char *)NULL); + { + char* const start_args[] = { + crm_strdup(the_subsystem->args), + NULL + }; + + (void)execv(the_subsystem->command, start_args); + } /* Should not happen */ - cl_perror("FATAL: Cannot exec %s", the_subsystem->command); + cl_perror("FATAL: Cannot exec %s %s", + the_subsystem->command, the_subsystem->args); + exit(100); /* Suppress respawning */ return TRUE; /* never reached */ } void cleanup_subsystem(struct crm_subsystem_s *the_subsystem) { int pid_status = -1; the_subsystem->ipc = NULL; clear_bit_inplace(fsa_input_register, the_subsystem->flag); /* Forcing client to die */ kill(the_subsystem->pid, -9); /* cleanup the ps entry */ waitpid(the_subsystem->pid, &pid_status, WNOHANG); the_subsystem->pid = -1; if(is_set(fsa_input_register, R_THE_DC)) { /* this wasnt supposed to happen */ crm_err("The %s subsystem terminated unexpectedly", the_subsystem->name); register_fsa_input(C_IPC_MESSAGE, I_ERROR, NULL); s_crmd_fsa(C_IPC_MESSAGE); } }