Example #1
0
crm_client_t *
crm_client_new(qb_ipcs_connection_t * c, uid_t uid_client, gid_t gid_client)
{
    static uid_t uid_server = 0;
    static gid_t gid_cluster = 0;

    crm_client_t *client = NULL;

    CRM_LOG_ASSERT(c);
    if (c == NULL) {
        return NULL;
    }

    if (gid_cluster == 0) {
        uid_server = getuid();
        if(crm_user_lookup(CRM_DAEMON_USER, NULL, &gid_cluster) < 0) {
            static bool have_error = FALSE;
            if(have_error == FALSE) {
                crm_warn("Could not find group for user %s", CRM_DAEMON_USER);
                have_error = TRUE;
            }
        }
    }

    if(gid_cluster != 0 && gid_client != 0) {
        uid_t best_uid = -1; /* Passing -1 to chown(2) means don't change */

        if(uid_client == 0 || uid_server == 0) { /* Someone is priveliged, but the other may not be */
            best_uid = QB_MAX(uid_client, uid_server);
            crm_trace("Allowing user %u to clean up after disconnect", best_uid);
        }

        crm_trace("Giving access to group %u", gid_cluster);
        qb_ipcs_connection_auth_set(c, best_uid, gid_cluster, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    }

    crm_client_init();

    /* TODO: Do our own auth checking, return NULL if unauthorized */
    client = calloc(1, sizeof(crm_client_t));

    client->ipcs = c;
    client->kind = CRM_CLIENT_IPC;
    client->pid = crm_ipcs_client_pid(c);

    client->id = crm_generate_uuid();

    crm_debug("Connecting %p for uid=%d gid=%d pid=%u id=%s", c, uid_client, gid_client, client->pid, client->id);

#if ENABLE_ACL
    client->user = uid2username(uid_client);
#endif

    g_hash_table_insert(client_connections, c, client);
    return client;
}
Example #2
0
crm_client_t *
crm_client_new(qb_ipcs_connection_t * c, uid_t uid_client, gid_t gid_client)
{
    static gid_t uid_cluster = 0;
    static gid_t gid_cluster = 0;

    crm_client_t *client = NULL;

    CRM_LOG_ASSERT(c);
    if (c == NULL) {
        return NULL;
    }

    if (uid_cluster == 0) {
        if (crm_user_lookup(CRM_DAEMON_USER, &uid_cluster, &gid_cluster) < 0) {
            static bool have_error = FALSE;
            if(have_error == FALSE) {
                crm_warn("Could not find user and group IDs for user %s",
                         CRM_DAEMON_USER);
                have_error = TRUE;
            }
        }
    }

    if (uid_client != 0) {
        crm_trace("Giving access to group %u", gid_cluster);
        /* Passing -1 to chown(2) means don't change */
        qb_ipcs_connection_auth_set(c, -1, gid_cluster, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    }

    crm_client_init();

    /* TODO: Do our own auth checking, return NULL if unauthorized */
    client = crm_client_alloc(c);
    client->ipcs = c;
    client->kind = CRM_CLIENT_IPC;
    client->pid = crm_ipcs_client_pid(c);

    if ((uid_client == 0) || (uid_client == uid_cluster)) {
        /* Remember when a connection came from root or hacluster */
        set_bit(client->flags, crm_client_flag_ipc_privileged);
    }

    crm_debug("Connecting %p for uid=%d gid=%d pid=%u id=%s", c, uid_client, gid_client, client->pid, client->id);

#if ENABLE_ACL
    client->user = uid2username(uid_client);
#endif
    return client;
}
Example #3
0
gboolean
crm_add_logfile(const char *filename)
{
    struct stat parent;
    int fd = 0, rc = 0;
    FILE *logfile = NULL;
    char *parent_dir = NULL;
    char *filename_cp;

    static gboolean have_logfile = FALSE;

    if (filename == NULL && have_logfile == FALSE) {
        filename = "/var/log/pacemaker.log";
    }

    if (filename == NULL) {
        return FALSE;           /* Nothing to do */
    }

    /* Check the parent directory */
    filename_cp = strdup(filename);
    parent_dir = dirname(filename_cp);
    rc = stat(parent_dir, &parent);

    if (rc != 0) {
        crm_err("Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
        free(filename_cp);
        return FALSE;
    }
    free(filename_cp);

    errno = 0;
    logfile = fopen(filename, "a");
    if(logfile == NULL) {
        crm_err("%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
                pcmk_strerror(errno), errno, filename, geteuid(), getegid());
        return FALSE;
    }

    /* Check/Set permissions if we're root */
    if (geteuid() == 0) {
        struct stat st;
        uid_t pcmk_uid = 0;
        gid_t pcmk_gid = 0;
        gboolean fix = FALSE;
        int logfd = fileno(logfile);

        rc = fstat(logfd, &st);
        if (rc < 0) {
            crm_perror(LOG_WARNING, "Cannot stat %s", filename);
            fclose(logfile);
            return FALSE;
        }

        if(crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) == 0) {
            if (st.st_gid != pcmk_gid) {
                /* Wrong group */
                fix = TRUE;
            } else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
                /* Not read/writable by the correct group */
                fix = TRUE;
            }
        }

        if (fix) {
            rc = fchown(logfd, pcmk_uid, pcmk_gid);
            if (rc < 0) {
                crm_warn("Cannot change the ownership of %s to user %s and gid %d",
                         filename, CRM_DAEMON_USER, pcmk_gid);
            }

            rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
            if (rc < 0) {
                crm_warn("Cannot change the mode of %s to rw-rw----", filename);
            }

            fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
                    pcmk_uid, pcmk_gid, filename);
            if (fflush(logfile) < 0 || fsync(logfd) < 0) {
                crm_err("Couldn't write out logfile: %s", filename);
            }
        }
    }

    /* Close and reopen with libqb */
    fclose(logfile);
    fd = qb_log_file_open(filename);

    if (fd < 0) {
        crm_perror(LOG_WARNING, "Couldn't send additional logging to %s", filename);
        return FALSE;
    }

    crm_notice("Additional logging available in %s", filename);
    qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
    /* qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1);  Turn on synchronous writes */

    /* Enable callsites */
    crm_update_callsites();
    have_logfile = TRUE;
    return TRUE;
}
Example #4
0
gboolean
mcp_read_config(void)
{
    int rc = CS_OK;
    int retries = 0;
    cmap_handle_t local_handle;
    uint64_t config = 0;

    // There can be only one possibility
    do {
        rc = cmap_initialize(&local_handle);
        if (rc != CS_OK) {
            retries++;
            printf("cmap connection setup failed: %s.  Retrying in %ds\n", cs_strerror(rc), retries);
            crm_info("cmap connection setup failed: %s.  Retrying in %ds", cs_strerror(rc), retries);
            sleep(retries);

        } else {
            break;
        }

    } while (retries < 5);

    if (rc != CS_OK) {
        printf("Could not connect to Cluster Configuration Database API, error %d\n", rc);
        crm_warn("Could not connect to Cluster Configuration Database API, error %d", rc);
        return FALSE;
    }

    stack = get_cluster_type();
    crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));

    /* =::=::= Should we be here =::=::= */
    if (stack == pcmk_cluster_corosync) {
        set_daemon_option("cluster_type", "corosync");
        set_daemon_option("quorum_type", "corosync");

    } else {
        crm_err("Unsupported stack type: %s", name_for_cluster_type(stack));
        return FALSE;
    }

    /* =::=::= Logging =::=::= */
    if (daemon_option("debug")) {
        /* Syslog logging is already setup by crm_log_init() */

    } else {
        /* Check corosync */
        char *debug_enabled = NULL;

        get_config_opt(config, local_handle, "logging.debug", &debug_enabled, "off");

        if (crm_is_true(debug_enabled)) {
            set_daemon_option("debug", "1");
            if (get_crm_log_level() < LOG_DEBUG) {
                set_crm_log_level(LOG_DEBUG);
            }

        } else {
            set_daemon_option("debug", "0");
        }

        free(debug_enabled);
    }

    if(local_handle){
        gid_t gid = 0;
        if (crm_user_lookup(CRM_DAEMON_USER, NULL, &gid) < 0) {
            crm_warn("Could not authorize group with corosync " CRM_XS
                     " No group found for user %s", CRM_DAEMON_USER);

        } else {
            char key[PATH_MAX];
            snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
            rc = cmap_set_uint8(local_handle, key, 1);
            if (rc != CS_OK) {
                crm_warn("Could not authorize group with corosync "CRM_XS
                         " group=%u rc=%d (%s)", gid, rc, ais_error2text(rc));
            }
        }
    }
    cmap_finalize(local_handle);

    return TRUE;
}
Example #5
0
int
main(int argc, char **argv)
{
    int rc;
    int flag;
    int argerr = 0;

    int option_index = 0;
    gboolean shutdown = FALSE;

    uid_t pcmk_uid = 0;
    gid_t pcmk_gid = 0;
    struct rlimit cores;
    crm_ipc_t *old_instance = NULL;
    qb_ipcs_service_t *ipcs = NULL;
    const char *facility = daemon_option("logfacility");
    static crm_cluster_t cluster;

    crm_log_preinit(NULL, argc, argv);
    crm_set_options(NULL, "mode [options]", long_options, "Start/Stop Pacemaker\n");
    mainloop_add_signal(SIGHUP, pcmk_ignore);
    mainloop_add_signal(SIGQUIT, pcmk_sigquit);

    while (1) {
        flag = crm_get_option(argc, argv, &option_index);
        if (flag == -1)
            break;

        switch (flag) {
            case 'V':
                crm_bump_log_level(argc, argv);
                break;
            case 'f':
                /* Legacy */
                break;
            case 'p':
                pid_file = optarg;
                break;
            case '$':
            case '?':
                crm_help(flag, EX_OK);
                break;
            case 'S':
                shutdown = TRUE;
                break;
            case 'F':
                printf("Pacemaker %s (Build: %s)\n Supporting v%s: %s\n", PACEMAKER_VERSION, BUILD_VERSION,
                       CRM_FEATURE_SET, CRM_FEATURES);
                crm_exit(pcmk_ok);
            default:
                printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
                ++argerr;
                break;
        }
    }

    if (optind < argc) {
        printf("non-option ARGV-elements: ");
        while (optind < argc)
            printf("%s ", argv[optind++]);
        printf("\n");
    }
    if (argerr) {
        crm_help('?', EX_USAGE);
    }


    setenv("LC_ALL", "C", 1);
    setenv("HA_LOGD", "no", 1);

    set_daemon_option("mcp", "true");
    set_daemon_option("use_logd", "off");

    crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);

    /* Restore the original facility so that mcp_read_config() does the right thing */
    set_daemon_option("logfacility", facility);

    crm_debug("Checking for old instances of %s", CRM_SYSTEM_MCP);
    old_instance = crm_ipc_new(CRM_SYSTEM_MCP, 0);
    crm_ipc_connect(old_instance);

    if (shutdown) {
        crm_debug("Terminating previous instance");
        while (crm_ipc_connected(old_instance)) {
            xmlNode *cmd =
                create_request(CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_MCP, CRM_SYSTEM_MCP, NULL);

            crm_debug(".");
            crm_ipc_send(old_instance, cmd, 0, 0, NULL);
            free_xml(cmd);

            sleep(2);
        }
        crm_ipc_close(old_instance);
        crm_ipc_destroy(old_instance);
        crm_exit(pcmk_ok);

    } else if (crm_ipc_connected(old_instance)) {
        crm_ipc_close(old_instance);
        crm_ipc_destroy(old_instance);
        crm_err("Pacemaker is already active, aborting startup");
        crm_exit(DAEMON_RESPAWN_STOP);
    }

    crm_ipc_close(old_instance);
    crm_ipc_destroy(old_instance);

    if (mcp_read_config() == FALSE) {
        crm_notice("Could not obtain corosync config data, exiting");
        crm_exit(ENODATA);
    }

    crm_notice("Starting Pacemaker %s (Build: %s): %s", PACEMAKER_VERSION, BUILD_VERSION, CRM_FEATURES);
    mainloop = g_main_new(FALSE);
    sysrq_init();

    rc = getrlimit(RLIMIT_CORE, &cores);
    if (rc < 0) {
        crm_perror(LOG_ERR, "Cannot determine current maximum core size.");
    } else {
        if (cores.rlim_max == 0 && geteuid() == 0) {
            cores.rlim_max = RLIM_INFINITY;
        } else {
            crm_info("Maximum core file size is: %lu", (unsigned long)cores.rlim_max);
        }
        cores.rlim_cur = cores.rlim_max;

        rc = setrlimit(RLIMIT_CORE, &cores);
        if (rc < 0) {
            crm_perror(LOG_ERR,
                       "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) {
            crm_perror(LOG_ERR, "Could not enable /proc/sys/kernel/core_uses_pid");
        }
#endif
    }
    rc = pcmk_ok;

    if (crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) < 0) {
        crm_err("Cluster user %s does not exist, aborting Pacemaker startup", CRM_DAEMON_USER);
        crm_exit(ENOKEY);
    }

    mkdir(CRM_STATE_DIR, 0750);
    mcp_chown(CRM_STATE_DIR, pcmk_uid, pcmk_gid);

    /* Used to store core files in */
    crm_build_path(CRM_CORE_DIR, 0775);
    mcp_chown(CRM_CORE_DIR, pcmk_uid, pcmk_gid);

    /* Used to store blackbox dumps in */
    crm_build_path(CRM_BLACKBOX_DIR, 0755);
    mcp_chown(CRM_BLACKBOX_DIR, pcmk_uid, pcmk_gid);

    /* Used to store policy engine inputs in */
    crm_build_path(PE_STATE_DIR, 0755);
    mcp_chown(PE_STATE_DIR, pcmk_uid, pcmk_gid);

    /* Used to store the cluster configuration */
    crm_build_path(CRM_CONFIG_DIR, 0755);
    mcp_chown(CRM_CONFIG_DIR, pcmk_uid, pcmk_gid);

    /* Resource agent paths are constructed by the lrmd */

    ipcs = mainloop_add_ipc_server(CRM_SYSTEM_MCP, QB_IPC_NATIVE, &mcp_ipc_callbacks);
    if (ipcs == NULL) {
        crm_err("Couldn't start IPC server");
        crm_exit(EIO);
    }

    /* Allows us to block shutdown */
    if (cluster_connect_cfg(&local_nodeid) == FALSE) {
        crm_err("Couldn't connect to Corosync's CFG service");
        crm_exit(ENOPROTOOPT);
    }

    if(pcmk_locate_sbd() > 0) {
        setenv("PCMK_watchdog", "true", 1);
    } else {
        setenv("PCMK_watchdog", "false", 1);
    }

    find_and_track_existing_processes();

    cluster.destroy = mcp_cpg_destroy;
    cluster.cpg.cpg_deliver_fn = mcp_cpg_deliver;
    cluster.cpg.cpg_confchg_fn = mcp_cpg_membership;

    crm_set_autoreap(FALSE);

    if(cluster_connect_cpg(&cluster) == FALSE) {
        crm_err("Couldn't connect to Corosync's CPG service");
        rc = -ENOPROTOOPT;
    }

    if (rc == pcmk_ok && is_corosync_cluster()) {
        /* Keep the membership list up-to-date for crm_node to query */
        if(cluster_connect_quorum(mcp_quorum_callback, mcp_quorum_destroy) == FALSE) {
            rc = -ENOTCONN;
        }
    }

#if SUPPORT_CMAN
    if (rc == pcmk_ok && is_cman_cluster()) {
        init_cman_connection(mcp_cman_dispatch, mcp_cman_destroy);
    }
#endif

    if(rc == pcmk_ok) {
        local_name = get_local_node_name();
        update_node_processes(local_nodeid, local_name, get_process_list());

        mainloop_add_signal(SIGTERM, pcmk_shutdown);
        mainloop_add_signal(SIGINT, pcmk_shutdown);

        init_children_processes();

        crm_info("Starting mainloop");

        g_main_run(mainloop);
    }

    if (ipcs) {
        crm_trace("Closing IPC server");
        mainloop_del_ipc_server(ipcs);
        ipcs = NULL;
    }

    g_main_destroy(mainloop);

    cluster_disconnect_cpg(&cluster);
    cluster_disconnect_cfg();

    crm_info("Exiting %s", crm_system_name);

    return crm_exit(rc);
}
Example #6
0
static gboolean
start_child(pcmk_child_t * child)
{
    int lpc = 0;
    uid_t uid = 0;
    gid_t gid = 0;
    struct rlimit oflimits;
    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");
    enum cluster_type_e stack = get_cluster_type();

    child->active_before_startup = FALSE;

    if (child->command == NULL) {
        crm_info("Nothing to do for child \"%s\"", child->name);
        return TRUE;
    }

    if (env_callgrind != NULL && crm_is_true(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 (env_valgrind != NULL && crm_is_true(env_valgrind)) {
        use_valgrind = TRUE;

    } else if (env_valgrind != NULL && strstr(env_valgrind, child->name)) {
        use_valgrind = TRUE;
    }

    if (use_valgrind && strlen(VALGRIND_BIN) == 0) {
        crm_warn("Cannot enable valgrind for %s:"
                 " The location of the valgrind binary is unknown", child->name);
        use_valgrind = FALSE;
    }

    if (child->uid) {
        if (crm_user_lookup(child->uid, &uid, &gid) < 0) {
            crm_err("Invalid user (%s) for %s: not found", child->uid, child->name);
            return FALSE;
        }
        crm_info("Using uid=%u and group=%u for process %s", uid, gid, child->name);
    }

    child->pid = fork();
    CRM_ASSERT(child->pid != -1);

    if (child->pid > 0) {
        /* parent */
        mainloop_child_add(child->pid, 0, child->name, child, pcmk_child_exit);

        crm_info("Forked child %d for process %s%s", child->pid, child->name,
                 use_valgrind ? " (valgrind enabled: " VALGRIND_BIN ")" : "");
        update_node_processes(local_nodeid, NULL, get_process_list());
        return TRUE;

    } else {
        /* Start a new session */
        (void)setsid();

        /* Setup the two alternate arg arrarys */
        opts_vgrind[0] = strdup(VALGRIND_BIN);
        if (use_callgrind) {
            opts_vgrind[1] = strdup("--tool=callgrind");
            opts_vgrind[2] = strdup("--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p");
            opts_vgrind[3] = strdup(child->command);
            opts_vgrind[4] = NULL;
        } else {
            opts_vgrind[1] = strdup(child->command);
            opts_vgrind[2] = NULL;
            opts_vgrind[3] = NULL;
            opts_vgrind[4] = NULL;
        }
        opts_default[0] = strdup(child->command);;

        if(gid) {
            if(stack == pcmk_cluster_corosync) {
                /* Drop root privileges completely
                 *
                 * We can do this because we set uidgid.gid.${gid}=1
                 * via CMAP which allows these processes to connect to
                 * corosync
                 */
                if (setgid(gid) < 0) {
                    crm_perror(LOG_ERR, "Could not set group to %d", gid);
                }

                /* Keep the root group (so we can access corosync), but add the haclient group (so we can access ipc) */
            } else if (initgroups(child->uid, gid) < 0) {
                crm_err("Cannot initialize groups for %s: %s (%d)", child->uid, pcmk_strerror(errno), errno);
            }
        }

        if (uid && setuid(uid) < 0) {
            crm_perror(LOG_ERR, "Could not set user to %d (%s)", uid, child->uid);
        }

        /* Close all open file descriptors */
        getrlimit(RLIMIT_NOFILE, &oflimits);
        for (lpc = 0; 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 (use_valgrind) {
            (void)execvp(VALGRIND_BIN, opts_vgrind);
        } else {
            (void)execvp(child->command, opts_default);
        }
        crm_perror(LOG_ERR, "FATAL: Cannot exec %s", child->command);
        crm_exit(DAEMON_RESPAWN_STOP);
    }
    return TRUE;                /* never reached */
}
Example #7
0
gboolean
mcp_read_config(void)
{
    int rc = CS_OK;
    int retries = 0;

    const char *const_value = NULL;

#if HAVE_CONFDB
    char *value = NULL;
    confdb_handle_t config = 0;
    confdb_handle_t top_handle = 0;
    hdb_handle_t local_handle;
    static confdb_callbacks_t callbacks = { };

    do {
        rc = confdb_initialize(&config, &callbacks);
        if (rc != CS_OK) {
            retries++;
            printf("confdb connection setup failed: %s.  Retrying in %ds\n", ais_error2text(rc), retries);
            crm_info("confdb connection setup failed: %s.  Retrying in %ds", ais_error2text(rc), retries);
            sleep(retries);

        } else {
            break;
        }

    } while (retries < 5);
#elif HAVE_CMAP
    cmap_handle_t local_handle;
    uint64_t config = 0;

    /* There can be only one (possibility if confdb isn't around) */
    do {
        rc = cmap_initialize(&local_handle);
        if (rc != CS_OK) {
            retries++;
            printf("cmap connection setup failed: %s.  Retrying in %ds\n", cs_strerror(rc), retries);
            crm_info("cmap connection setup failed: %s.  Retrying in %ds", cs_strerror(rc), retries);
            sleep(retries);

        } else {
            break;
        }

    } while (retries < 5);
#endif

    if (rc != CS_OK) {
        printf("Could not connect to Cluster Configuration Database API, error %d\n", rc);
        crm_warn("Could not connect to Cluster Configuration Database API, error %d", rc);
        return FALSE;
    }

    stack = get_cluster_type();
    crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));

    /* =::=::= Should we be here =::=::= */
    if (stack == pcmk_cluster_corosync) {
        set_daemon_option("cluster_type", "corosync");
        set_daemon_option("quorum_type", "corosync");

#if HAVE_CONFDB
    } else if (stack == pcmk_cluster_cman) {
        set_daemon_option("cluster_type", "cman");
        set_daemon_option("quorum_type", "cman");
        enable_crmd_as_root(TRUE);

    } else if (stack == pcmk_cluster_classic_ais) {
        set_daemon_option("cluster_type", "openais");
        set_daemon_option("quorum_type", "pcmk");

        /* Look for a service block to indicate our plugin is loaded */
        top_handle = config_find_init(config);
        local_handle = config_find_next(config, "service", top_handle);

        while (local_handle) {
            get_config_opt(config, local_handle, "name", &value, NULL);
            if (safe_str_eq("pacemaker", value)) {
                get_config_opt(config, local_handle, "ver", &value, "0");
                if (safe_str_eq(value, "1")) {
                    get_config_opt(config, local_handle, "use_logd", &value, "no");
                    set_daemon_option("use_logd", value);
                    set_daemon_option("LOGD", value);

                    get_config_opt(config, local_handle, "use_mgmtd", &value, "no");
                    enable_mgmtd(crm_is_true(value));

                } else {
                    crm_err("We can only start Pacemaker from init if using version 1"
                            " of the Pacemaker plugin for Corosync.  Terminating.");
                    crm_exit(DAEMON_RESPAWN_STOP);
                }
                break;
            }
            local_handle = config_find_next(config, "service", top_handle);
        }
        free(value);

#endif
    } else {
        crm_err("Unsupported stack type: %s", name_for_cluster_type(stack));
        return FALSE;
    }

#if HAVE_CONFDB
    top_handle = config_find_init(config);
    local_handle = config_find_next(config, "logging", top_handle);
#endif

    /* =::=::= Logging =::=::= */
    if (daemon_option("debug")) {
        /* Syslog logging is already setup by crm_log_init() */

    } else {
        /* Check corosync */
        char *debug_enabled = NULL;

        get_config_opt(config, local_handle, KEY_PREFIX "debug", &debug_enabled, "off");

        if (crm_is_true(debug_enabled)) {
            set_daemon_option("debug", "1");
            if (get_crm_log_level() < LOG_DEBUG) {
                set_crm_log_level(LOG_DEBUG);
            }

        } else {
            set_daemon_option("debug", "0");
        }

        free(debug_enabled);
    }

    const_value = daemon_option("debugfile");
    if (daemon_option("logfile")) {
        /* File logging is already setup by crm_log_init() */

    } else if(const_value) {
        /* From when we cared what options heartbeat used */
        set_daemon_option("logfile", const_value);
        crm_add_logfile(const_value);

    } else {
        /* Check corosync */
        char *logfile = NULL;
        char *logfile_enabled = NULL;

        get_config_opt(config, local_handle, KEY_PREFIX "to_logfile", &logfile_enabled, "on");
        get_config_opt(config, local_handle, KEY_PREFIX "logfile", &logfile, "/var/log/pacemaker.log");

        if (crm_is_true(logfile_enabled) == FALSE) {
            crm_trace("File logging disabled in corosync");

        } else if (crm_add_logfile(logfile)) {
            set_daemon_option("logfile", logfile);

        } else {
            crm_err("Couldn't create logfile: %s", logfile);
            set_daemon_option("logfile", "none");
        }

        free(logfile);
        free(logfile_enabled);
    }

    if (daemon_option("logfacility")) {
        /* Syslog logging is already setup by crm_log_init() */

    } else {
        /* Check corosync */
        char *syslog_enabled = NULL;
        char *syslog_facility = NULL;

        get_config_opt(config, local_handle, KEY_PREFIX "to_syslog", &syslog_enabled, "on");
        get_config_opt(config, local_handle, KEY_PREFIX "syslog_facility", &syslog_facility, "daemon");

        if (crm_is_true(syslog_enabled) == FALSE) {
            qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
            set_daemon_option("logfacility", "none");

        } else {
            qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(syslog_facility));
            qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
            set_daemon_option("logfacility", syslog_facility);
        }

        free(syslog_enabled);
        free(syslog_facility);
    }

    const_value = daemon_option("logfacility");
    if (const_value) {
        /* cluster-glue module needs HA_LOGFACILITY */
        setenv("HA_LOGFACILITY", const_value, 1);
    }

#if HAVE_CONFDB
    confdb_finalize(config);
#elif HAVE_CMAP
    if(local_handle){
        gid_t gid = 0;
        if (crm_user_lookup(CRM_DAEMON_USER, NULL, &gid) < 0) {
            crm_warn("Could not authorize group with corosync " CRM_XS
                     " No group found for user %s", CRM_DAEMON_USER);

        } else {
            char key[PATH_MAX];
            snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
            rc = cmap_set_uint8(local_handle, key, 1);
            if (rc != CS_OK) {
                crm_warn("Could not authorize group with corosync "CRM_XS
                         " group=%u rc=%d (%s)", gid, rc, ais_error2text(rc));
            }
        }
    }
    cmap_finalize(local_handle);
#endif

    return TRUE;
}
Example #8
0
gboolean
read_config(void)
{
    int rc = CS_OK;
    int retries = 0;
    gboolean have_log = FALSE;

    const char *const_value = NULL;

    char *logging_debug = NULL;
    char *logging_logfile = NULL;
    char *logging_to_logfile = NULL;
    char *logging_to_syslog = NULL;
    char *logging_syslog_facility = NULL;

#if HAVE_CONFDB
    char *value = NULL;
    confdb_handle_t config = 0;
    confdb_handle_t top_handle = 0;
    hdb_handle_t local_handle;
    static confdb_callbacks_t callbacks = { };

    do {
        rc = confdb_initialize(&config, &callbacks);
        if (rc != CS_OK) {
            retries++;
            printf("confdb connection setup failed: %s.  Retrying in %ds\n", ais_error2text(rc), retries);
            crm_info("confdb connection setup failed: %s.  Retrying in %ds", ais_error2text(rc), retries);
            sleep(retries);

        } else {
            break;
        }

    } while (retries < 5);
#elif HAVE_CMAP
    cmap_handle_t local_handle;
    uint64_t config = 0;

    /* There can be only one (possibility if confdb isn't around) */
    do {
        rc = cmap_initialize(&local_handle);
        if (rc != CS_OK) {
            retries++;
            printf("cmap connection setup failed: %s.  Retrying in %ds\n", cs_strerror(rc), retries);
            crm_info("cmap connection setup failed: %s.  Retrying in %ds", cs_strerror(rc), retries);
            sleep(retries);

        } else {
            break;
        }

    } while (retries < 5);
#endif

    if (rc != CS_OK) {
        printf("Could not connect to Cluster Configuration Database API, error %d\n", rc);
        crm_warn("Could not connect to Cluster Configuration Database API, error %d", rc);
        return FALSE;
    }

    stack = get_cluster_type();
    crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));

    /* =::=::= Should we be here =::=::= */
    if (stack == pcmk_cluster_corosync) {
        set_daemon_option("cluster_type", "corosync");
        set_daemon_option("quorum_type", "corosync");

#if HAVE_CONFDB
    } else if (stack == pcmk_cluster_cman) {
        set_daemon_option("cluster_type", "cman");
        set_daemon_option("quorum_type", "cman");
        enable_crmd_as_root(TRUE);

    } else if (stack == pcmk_cluster_classic_ais) {
        set_daemon_option("cluster_type", "openais");
        set_daemon_option("quorum_type", "pcmk");

        /* Look for a service block to indicate our plugin is loaded */
        top_handle = config_find_init(config);
        local_handle = config_find_next(config, "service", top_handle);

        while (local_handle) {
            get_config_opt(config, local_handle, "name", &value, NULL);
            if (safe_str_eq("pacemaker", value)) {
                get_config_opt(config, local_handle, "ver", &value, "0");
                if (safe_str_eq(value, "1")) {
                    get_config_opt(config, local_handle, "use_logd", &value, "no");
                    set_daemon_option("use_logd", value);
                    set_daemon_option("LOGD", value);

                    get_config_opt(config, local_handle, "use_mgmtd", &value, "no");
                    enable_mgmtd(crm_is_true(value));

                } else {
                    crm_err("We can only start Pacemaker from init if using version 1"
                            " of the Pacemaker plugin for Corosync.  Terminating.");
                    crm_exit(DAEMON_RESPAWN_STOP);
                }
                break;
            }
            local_handle = config_find_next(config, "service", top_handle);
        }
        free(value);

#endif
    } else {
        crm_err("Unsupported stack type: %s", name_for_cluster_type(stack));
        return FALSE;
    }

#if HAVE_CONFDB
    top_handle = config_find_init(config);
    local_handle = config_find_next(config, "logging", top_handle);
#endif

    /* =::=::= Logging =::=::= */
    get_config_opt(config, local_handle, KEY_PREFIX "debug", &logging_debug, "off");

    const_value = daemon_option("debugfile");
    if (const_value) {
        logging_to_logfile = strdup("on");
        logging_logfile = strdup(const_value);
        crm_trace("Using debugfile setting from the environment: %s", logging_logfile);

    } else {
        get_config_opt(config, local_handle, KEY_PREFIX "to_logfile", &logging_to_logfile, "off");
        get_config_opt(config, local_handle, KEY_PREFIX "logfile", &logging_logfile,
                       "/var/log/pacemaker");
    }

    const_value = daemon_option("logfacility");
    if (const_value) {
        logging_syslog_facility = strdup(const_value);
        crm_trace("Using logfacility setting from the environment: %s", logging_syslog_facility);

        if (safe_str_eq(logging_syslog_facility, "none")) {
            logging_to_syslog = strdup("off");
        } else {
            logging_to_syslog = strdup("on");
        }

    } else {
        get_config_opt(config, local_handle, KEY_PREFIX "to_syslog", &logging_to_syslog, "on");
        get_config_opt(config, local_handle, KEY_PREFIX "syslog_facility", &logging_syslog_facility,
                       "daemon");
    }

#if HAVE_CONFDB
    confdb_finalize(config);
#elif HAVE_CMAP
    if(local_handle){
        gid_t gid = 0;
        if (crm_user_lookup(CRM_DAEMON_USER, NULL, &gid) < 0) {
            crm_warn("No group found for user %s", CRM_DAEMON_USER);

        } else {
            char key[PATH_MAX];
            snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
            rc = cmap_set_uint8(local_handle, key, 1);
            crm_notice("Configured corosync to accept connections from group %u: %s (%d)",
                       gid, ais_error2text(rc), rc);
        }
    }
    cmap_finalize(local_handle);
#endif

    if (daemon_option("debug")) {
        crm_trace("Using debug setting from the environment: %s", daemon_option("debug"));
        if (get_crm_log_level() < LOG_DEBUG && daemon_option_enabled("pacemakerd", "debug")) {
            set_crm_log_level(LOG_DEBUG);
        }

    } else if (crm_is_true(logging_debug)) {
        set_daemon_option("debug", "1");
        if (get_crm_log_level() < LOG_DEBUG) {
            set_crm_log_level(LOG_DEBUG);
        }

    } else {
        set_daemon_option("debug", "0");
    }

    if (crm_is_true(logging_to_logfile)) {
        if (crm_add_logfile(logging_logfile)) {
            /* What a cluster fsck, eventually we need to mandate /one/ */
            set_daemon_option("debugfile", logging_logfile);
            set_daemon_option("DEBUGLOG", logging_logfile);
            have_log = TRUE;

        } else {
            crm_err("Couldn't create logfile: %s", logging_logfile);
        }
    }

    if (have_log && crm_is_true(logging_to_syslog) == FALSE) {
        qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
        free(logging_syslog_facility);
        logging_syslog_facility = strdup("none");
        crm_info("User configured file based logging and explicitly disabled syslog.");

    } else if (crm_is_true(logging_to_syslog) == FALSE) {
        crm_err("Please enable some sort of logging, either 'to_logfile: on' or 'to_syslog: on'.");
        crm_err("If you use file logging, be sure to also define a value for 'logfile'");
    }

    set_daemon_option("logfacility", logging_syslog_facility);
    setenv("HA_LOGFACILITY", logging_syslog_facility, 1);

    free(logging_debug);
    free(logging_logfile);
    free(logging_to_logfile);
    free(logging_to_syslog);
    free(logging_syslog_facility);
    return TRUE;
}