| /* |
| * Copyright 2004-2019 the Pacemaker project contributors |
| * |
| * The version control history for this file may have further details. |
| * |
| * This source code is licensed under the GNU General Public License version 2 |
| * or later (GPLv2+) WITHOUT ANY WARRANTY. |
| */ |
| |
| #include <crm_internal.h> |
| |
| #include <sys/param.h> |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <unistd.h> |
| |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| |
| #include <crm/crm.h> |
| #include <crm/common/ipc.h> |
| #include <crm/common/xml.h> |
| |
| #include <crmd.h> |
| #include <crmd_fsa.h> |
| #include <crmd_messages.h> |
| |
| #define OPTARGS "hV" |
| |
| void usage(const char *cmd, int exit_status); |
| int crmd_init(void); |
| void crmd_hamsg_callback(const xmlNode * msg, void *private_data); |
| extern void init_dotfile(void); |
| |
| GMainLoop *crmd_mainloop = NULL; |
| |
| /* *INDENT-OFF* */ |
| static struct crm_option long_options[] = { |
| /* Top-level Options */ |
| {"help", 0, 0, '?', "\tThis text"}, |
| {"verbose", 0, 0, 'V', "\tIncrease debug output"}, |
| |
| {0, 0, 0, 0} |
| }; |
| /* *INDENT-ON* */ |
| |
| int |
| main(int argc, char **argv) |
| { |
| int flag; |
| int index = 0; |
| int argerr = 0; |
| crm_ipc_t *old_instance = NULL; |
| |
| crmd_mainloop = g_main_new(FALSE); |
| crm_log_preinit(NULL, argc, argv); |
| crm_set_options(NULL, "[options]", long_options, |
| "Daemon for aggregating resource and node failures as well as co-ordinating the cluster's response"); |
| |
| while (1) { |
| flag = crm_get_option(argc, argv, &index); |
| if (flag == -1) |
| break; |
| |
| switch (flag) { |
| case 'V': |
| crm_bump_log_level(argc, argv); |
| break; |
| case 'h': /* Help message */ |
| crm_help(flag, EX_OK); |
| break; |
| default: |
| ++argerr; |
| break; |
| } |
| } |
| |
| if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { |
| crmd_metadata(); |
| return 0; |
| } else if (argc - optind == 1 && safe_str_eq("version", argv[optind])) { |
| fprintf(stdout, "CRM Version: %s (%s)\n", PACEMAKER_VERSION, BUILD_VERSION); |
| return 0; |
| } |
| |
| crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE); |
| crm_info("CRM Git Version: %s (%s)", PACEMAKER_VERSION, BUILD_VERSION); |
| |
| if (optind > argc) { |
| ++argerr; |
| } |
| |
| if (argerr) { |
| crm_help('?', EX_USAGE); |
| } |
| |
| old_instance = crm_ipc_new(CRM_SYSTEM_CRMD, 0); |
| if (crm_ipc_connect(old_instance)) { |
| /* IPC end-point already up */ |
| crm_ipc_close(old_instance); |
| crm_ipc_destroy(old_instance); |
| crm_err("crmd is already active, aborting startup"); |
| crm_exit(EX_OK); |
| } else { |
| /* not up or not authentic, we'll proceed either way */ |
| crm_ipc_destroy(old_instance); |
| old_instance = NULL; |
| } |
| |
| if (pcmk__daemon_can_write(PE_STATE_DIR, NULL) == FALSE) { |
| crm_err("Terminating due to bad permissions on " PE_STATE_DIR); |
| fprintf(stderr, |
| "ERROR: Bad permissions on " PE_STATE_DIR " (see logs for details)\n"); |
| fflush(stderr); |
| return 100; |
| |
| } else if (pcmk__daemon_can_write(CRM_CONFIG_DIR, NULL) == FALSE) { |
| crm_err("Terminating due to bad permissions on " CRM_CONFIG_DIR); |
| fprintf(stderr, |
| "ERROR: Bad permissions on " CRM_CONFIG_DIR " (see logs for details)\n"); |
| fflush(stderr); |
| return 100; |
| } |
| |
| return crmd_init(); |
| } |
| |
| static void |
| log_deprecation_warnings() |
| { |
| enum cluster_type_e cluster_type = get_cluster_type(); |
| |
| if (cluster_type != pcmk_cluster_corosync) { |
| crm_warn("Support for cluster infrastructure %s " |
| " is deprecated and will be removed in a future release", |
| name_for_cluster_type(cluster_type)); |
| |
| } |
| |
| #if ENABLE_SNMP |
| crm_warn("Compile-time support for crm_mon SNMP options" |
| " is deprecated and will be removed in a future release" |
| " (configure alerts instead)", |
| name_for_cluster_type(cluster_type)); |
| #endif |
| #if ENABLE_ESMTP |
| crm_warn("Compile-time support for crm_mon SMTP options" |
| " is deprecated and will be removed in a future release" |
| " (configure alerts instead)", |
| name_for_cluster_type(cluster_type)); |
| #endif |
| |
| if (getenv("LRMD_MAX_CHILDREN")) { |
| crm_warn("The LRMD_MAX_CHILDREN environment variable" |
| " is deprecated and will be removed in a future release" |
| " (use PCMK_node_action_limit instead)"); |
| } |
| } |
| |
| int |
| crmd_init(void) |
| { |
| int exit_code = 0; |
| enum crmd_fsa_state state; |
| |
| log_deprecation_warnings(); |
| |
| fsa_state = S_STARTING; |
| fsa_input_register = 0; /* zero out the regester */ |
| |
| init_dotfile(); |
| crm_debug("Starting %s", crm_system_name); |
| register_fsa_input(C_STARTUP, I_STARTUP, NULL); |
| |
| crm_peer_init(); |
| state = s_crmd_fsa(C_STARTUP); |
| |
| if (state == S_PENDING || state == S_STARTING) { |
| /* Create the mainloop and run it... */ |
| crm_trace("Starting %s's mainloop", crm_system_name); |
| |
| #ifdef REALTIME_SUPPORT |
| static int crm_realtime = 1; |
| |
| if (crm_realtime == 1) { |
| cl_enable_realtime(); |
| } else if (crm_realtime == 0) { |
| cl_disable_realtime(); |
| } |
| cl_make_realtime(SCHED_RR, 5, 64, 64); |
| #endif |
| g_main_run(crmd_mainloop); |
| if (is_set(fsa_input_register, R_STAYDOWN)) { |
| crm_info("Inhibiting automated respawn"); |
| exit_code = 100; |
| } |
| |
| } else { |
| crm_err("Startup of %s failed. Current state: %s", |
| crm_system_name, fsa_state2string(state)); |
| exit_code = 1; |
| } |
| |
| crm_info("%lu stopped: %s (%d)", |
| (unsigned long) getpid(), pcmk_strerror(exit_code), exit_code); |
| return crmd_fast_exit(exit_code); |
| } |