예제 #1
0
gboolean
crmd_authorize_message(xmlNode * client_msg, crmd_client_t * curr_client)
{
    /* check the best case first */
    const char *sys_from = crm_element_value(client_msg, F_CRM_SYS_FROM);
    char *uuid = NULL;
    char *client_name = NULL;
    char *major_version = NULL;
    char *minor_version = NULL;
    const char *filtered_from;
    gpointer table_key = NULL;
    gboolean auth_result = FALSE;
    struct crm_subsystem_s *the_subsystem = NULL;
    gboolean can_reply = FALSE; /* no-one has registered with this id */

    xmlNode *xml = NULL;
    const char *op = crm_element_value(client_msg, F_CRM_TASK);

    if (safe_str_neq(CRM_OP_HELLO, op)) {

        if (sys_from == NULL) {
            crm_warn("Message [%s] was had no value for %s... discarding",
                     crm_element_value(client_msg, XML_ATTR_REFERENCE), F_CRM_SYS_FROM);
            return FALSE;
        }

        filtered_from = sys_from;

        /* The CIB can have two names on the DC */
        if (strcasecmp(sys_from, CRM_SYSTEM_DCIB) == 0)
            filtered_from = CRM_SYSTEM_CIB;

        if (g_hash_table_lookup(ipc_clients, filtered_from) != NULL) {
            can_reply = TRUE;   /* reply can be routed */
        }

        crm_trace("Message reply can%s be routed from %s.", can_reply ? "" : " not", sys_from);

        if (can_reply == FALSE) {
            crm_warn("Message [%s] not authorized",
                     crm_element_value(client_msg, XML_ATTR_REFERENCE));
        }

        return can_reply;
    }

    crm_trace("received client join msg");
    crm_log_xml_trace(client_msg, "join");
    xml = get_message_xml(client_msg, F_CRM_DATA);
    auth_result = process_hello_message(xml, &uuid, &client_name, &major_version, &minor_version);

    if (auth_result == TRUE) {
        if (client_name == NULL || uuid == NULL) {
            crm_err("Bad client details (client_name=%s, uuid=%s)",
                    crm_str(client_name), crm_str(uuid));
            auth_result = FALSE;
        }
    }

    if (auth_result == TRUE) {
        /* check version */
        int mav = atoi(major_version);
        int miv = atoi(minor_version);

        crm_trace("Checking client version number");
        if (mav < 0 || miv < 0) {
            crm_err("Client version (%d:%d) is not acceptable", mav, miv);
            auth_result = FALSE;
        }
        crm_free(major_version);
        crm_free(minor_version);
    }

    if (safe_str_eq(CRM_SYSTEM_PENGINE, client_name)) {
        the_subsystem = pe_subsystem;

    } else if (safe_str_eq(CRM_SYSTEM_TENGINE, client_name)) {
        the_subsystem = te_subsystem;
    }

    /* TODO: Is this code required anymore?? */
    if (auth_result == TRUE && the_subsystem != NULL) {
        /* if we already have one of those clients
         * only applies to te, pe etc.  not admin clients
         */
        crm_err("Checking if %s is required/already connected", client_name);

        table_key = (gpointer) crm_strdup(client_name);

        if (is_set(fsa_input_register, the_subsystem->flag_connected)) {
            auth_result = FALSE;
            crm_free(table_key);
            table_key = NULL;
            crm_warn("Bit\t%.16llx set in %.16llx",
                     the_subsystem->flag_connected, fsa_input_register);
            crm_err("Client %s is already connected", client_name);

        } else if (FALSE == is_set(fsa_input_register, the_subsystem->flag_required)) {
            crm_warn("Bit\t%.16llx not set in %.16llx",
                     the_subsystem->flag_connected, fsa_input_register);
            crm_warn("Client %s joined but we dont need it", client_name);
            stop_subsystem(the_subsystem, TRUE);

        } else {
            the_subsystem->ipc = curr_client->client_channel;
            set_bit_inplace(fsa_input_register, the_subsystem->flag_connected);
        }

    } else {
        table_key = (gpointer) generate_hash_key(client_name, uuid);
    }

    if (auth_result == TRUE) {
        crm_trace("Accepted client %s", crm_str(table_key));

        curr_client->table_key = table_key;
        curr_client->sub_sys = crm_strdup(client_name);
        curr_client->uuid = crm_strdup(uuid);

        g_hash_table_insert(ipc_clients, table_key, curr_client->client_channel);

        send_hello_message(curr_client->client_channel, "n/a", CRM_SYSTEM_CRMD, "0", "1");

        crm_trace("Updated client list with %s", crm_str(table_key));

        crm_trace("Triggering FSA: %s", __FUNCTION__);
        mainloop_set_trigger(fsa_source);

        if (the_subsystem != NULL) {
            CRM_CHECK(the_subsystem->client == NULL,
                      process_client_disconnect(the_subsystem->client));
            the_subsystem->client = curr_client;
        }

    } else {
        crm_free(table_key);
        crm_warn("Rejected client logon request");
        curr_client->client_channel->ch_status = IPC_DISC_PENDING;
    }

    if (uuid != NULL)
        crm_free(uuid);
    if (minor_version != NULL)
        crm_free(minor_version);
    if (major_version != NULL)
        crm_free(major_version);
    if (client_name != NULL)
        crm_free(client_name);

    /* hello messages should never be processed further */
    return FALSE;
}
예제 #2
0
파일: election.c 프로젝트: dubrsl/pacemaker
/*	A_ELECTION_COUNT	*/
void
do_election_count_vote(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 age = 0;
    int election_id = -1;
    int log_level = LOG_INFO;
    gboolean use_born_on = FALSE;
    gboolean done = FALSE;
    gboolean we_loose = FALSE;
    const char *op = NULL;
    const char *vote_from = NULL;
    const char *election_owner = NULL;
    const char *reason = "unknown";
    crm_node_t *our_node = NULL, *your_node = NULL;
    ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg);

    static int election_wins = 0;

    time_t tm_now = time(NULL);
    static time_t expires = 0;
    static time_t last_election_loss = 0;

    /* if the membership copy is NULL we REALLY shouldnt be voting
     * the question is how we managed to get here.
     */

    CRM_CHECK(msg_data != NULL, return);
    CRM_CHECK(vote != NULL, crm_err("Bogus data from %s", msg_data->origin); return);
    CRM_CHECK(vote->msg != NULL, crm_err("Bogus data from %s", msg_data->origin); return);

    if(crm_peer_cache == NULL) {
        if(is_not_set(fsa_input_register, R_SHUTDOWN)) {
            crm_err("Internal error, no peer cache");
        }
        return;
    }

    op = crm_element_value(vote->msg, F_CRM_TASK);
    vote_from = crm_element_value(vote->msg, F_CRM_HOST_FROM);
    election_owner = crm_element_value(vote->msg, F_CRM_ELECTION_OWNER);
    crm_element_value_int(vote->msg, F_CRM_ELECTION_ID, &election_id);

    CRM_CHECK(vote_from != NULL, vote_from = fsa_our_uname);

    your_node = crm_get_peer(0, vote_from);
    our_node = crm_get_peer(0, fsa_our_uname);

    if (voted == NULL) {
        crm_debug("Created voted hash");
        voted = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                      g_hash_destroy_str, g_hash_destroy_str);
    }

    if (is_heartbeat_cluster()) {
        use_born_on = TRUE;
    } else if (is_classic_ais_cluster()) {
        use_born_on = TRUE;
    }

    if (cur_state == S_STARTING) {
        reason = "Still starting";
        we_loose = TRUE;

    } else if (our_node == NULL || crm_is_peer_active(our_node) == FALSE) {
        reason = "We are not part of the cluster";
        log_level = LOG_ERR;
        we_loose = TRUE;

    } else if (election_id != current_election_id && crm_str_eq(fsa_our_uuid, election_owner, TRUE)) {
        log_level = LOG_DEBUG_2;
        reason = "Superceeded";
        done = TRUE;

    } else if (your_node == NULL || crm_is_peer_active(your_node) == FALSE) {
        /* Possibly we cached the message in the FSA queue at a point that it wasn't */
        reason = "Peer is not part of our cluster";
        log_level = LOG_WARNING;
        done = TRUE;

    } else if (crm_str_eq(op, CRM_OP_NOVOTE, TRUE)) {
        char *op_copy = strdup(op);
        char *uname_copy = strdup(vote_from);

        CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE));

        /* update the list of nodes that have voted */
        g_hash_table_replace(voted, uname_copy, op_copy);
        reason = "Recorded";
        done = TRUE;

    } else {
        struct timeval your_age;
        const char *your_version = crm_element_value(vote->msg, F_CRM_VERSION);

        your_age.tv_sec = 0;
        your_age.tv_usec = 0;

        crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_S, (int *)&(your_age.tv_sec));
        crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_US, (int *)&(your_age.tv_usec));

        age = crm_compare_age(your_age);
        if(your_age.tv_sec == 0 && your_age.tv_usec == 0) {
            crm_log_xml_trace(vote->msg, "bad vote");
            crm_write_blackbox(0, NULL);
        }

        if (crm_str_eq(vote_from, fsa_our_uname, TRUE)) {
            char *op_copy = strdup(op);
            char *uname_copy = strdup(vote_from);

            CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE));

            /* update ourselves in the list of nodes that have voted */
            g_hash_table_replace(voted, uname_copy, op_copy);
            reason = "Recorded";
            done = TRUE;

        } else if (compare_version(your_version, CRM_FEATURE_SET) < 0) {
            reason = "Version";
            we_loose = TRUE;

        } else if (compare_version(your_version, CRM_FEATURE_SET) > 0) {
            reason = "Version";

        } else if (age < 0) {
            reason = "Uptime";
            we_loose = TRUE;

        } else if (age > 0) {
            reason = "Uptime";

            /* TODO: Check for y(our) born < 0 */
        } else if (use_born_on && your_node->born < our_node->born) {
            reason = "Born";
            we_loose = TRUE;

        } else if (use_born_on && your_node->born > our_node->born) {
            reason = "Born";

        } else if (fsa_our_uname == NULL) {
            reason = "Unknown host name";
            we_loose = TRUE;

        } else if (strcasecmp(fsa_our_uname, vote_from) > 0) {
            reason = "Host name";
            we_loose = TRUE;

        } else {
            reason = "Host name";
            CRM_ASSERT(strcasecmp(fsa_our_uname, vote_from) < 0);
/* cant happen...
 *	} else if(strcasecmp(fsa_our_uname, vote_from) == 0) {
 *
 */
        }
    }

    if (expires < tm_now) {
        election_wins = 0;
        expires = tm_now + STORM_INTERVAL;

    } else if (done == FALSE && we_loose == FALSE) {
        int peers = 1 + g_hash_table_size(crm_peer_cache);

        /* If every node has to vote down every other node, thats N*(N-1) total elections
         * Allow some leway before _really_ complaining
         */
        election_wins++;
        if (election_wins > (peers * peers)) {
            crm_warn("Election storm detected: %d elections in %d seconds", election_wins,
                     STORM_INTERVAL);
            election_wins = 0;
            expires = tm_now + STORM_INTERVAL;
            crm_write_blackbox(0, NULL);
        }
    }

    if (done) {
        do_crm_log(log_level + 1, "Election %d (current: %d, owner: %s): Processed %s from %s (%s)",
                   election_id, current_election_id, election_owner, op, vote_from, reason);

    } else if (we_loose) {
        xmlNode *novote = create_request(CRM_OP_NOVOTE, NULL, vote_from,
                                         CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);

        do_crm_log(log_level, "Election %d (owner: %s) lost: %s from %s (%s)",
                   election_id, election_owner, op, vote_from, reason);
        update_dc(NULL);

        crm_timer_stop(election_timeout);
        if (fsa_input_register & R_THE_DC) {
            crm_trace("Give up the DC to %s", vote_from);
            register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);
            fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local);

        } else if (cur_state != S_STARTING) {
            crm_trace("We werent the DC anyway");
            register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
        }

        crm_xml_add(novote, F_CRM_ELECTION_OWNER, election_owner);
        crm_xml_add_int(novote, F_CRM_ELECTION_ID, election_id);

        send_cluster_message(crm_get_peer(0, vote_from), crm_msg_crmd, novote, TRUE);
        free_xml(novote);

        last_election_loss = tm_now;

    } else {
        do_crm_log(log_level, "Election %d (owner: %s) pass: %s from %s (%s)",
                   election_id, election_owner, op, vote_from, reason);

        if (last_election_loss) {

            if (tm_now - last_election_loss < (time_t) loss_dampen) {
                crm_info("Election %d ignore: We already lost an election less than %ds ago (%s)",
                         election_id, loss_dampen, ctime(&last_election_loss));
                update_dc(NULL);
                return;
            }
            last_election_loss = 0;
        }

        register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
        g_hash_table_destroy(voted);
        voted = NULL;
    }
}
예제 #3
0
파일: graph.c 프로젝트: esimone74/pacemaker
static char *
convert_non_atomic_uuid(char *old_uuid, resource_t * rsc, gboolean allow_notify,
                        gboolean free_original)
{
    int interval = 0;
    char *uuid = NULL;
    char *rid = NULL;
    char *raw_task = NULL;
    int task = no_action;

    crm_trace("Processing %s", old_uuid);
    if (old_uuid == NULL) {
        return NULL;

    } else if (strstr(old_uuid, "notify") != NULL) {
        goto done;              /* no conversion */

    } else if (rsc->variant < pe_group) {
        goto done;              /* no conversion */
    }

    CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval));
    if (interval > 0) {
        goto done;              /* no conversion */
    }

    task = text2task(raw_task);
    switch (task) {
        case stop_rsc:
        case start_rsc:
        case action_notify:
        case action_promote:
        case action_demote:
            break;
        case stopped_rsc:
        case started_rsc:
        case action_notified:
        case action_promoted:
        case action_demoted:
            task--;
            break;
        case monitor_rsc:
        case shutdown_crm:
        case stonith_node:
            task = no_action;
            break;
        default:
            crm_err("Unknown action: %s", raw_task);
            task = no_action;
            break;
    }

    if (task != no_action) {
        if (is_set(rsc->flags, pe_rsc_notify) && allow_notify) {
            uuid = generate_notify_key(rid, "confirmed-post", task2text(task + 1));

        } else {
            uuid = generate_op_key(rid, task2text(task + 1), 0);
        }
        crm_trace("Converted %s -> %s", old_uuid, uuid);
    }

  done:
    if (uuid == NULL) {
        uuid = crm_strdup(old_uuid);
    }

    if (free_original) {
        crm_free(old_uuid);
    }

    crm_free(raw_task);
    crm_free(rid);
    return uuid;
}
예제 #4
0
svc_action_t *
resources_action_create(const char *name, const char *standard, const char *provider,
                        const char *agent, const char *action, int interval, int timeout,
                        GHashTable * params, enum svc_action_flags flags)
{
    svc_action_t *op = NULL;

    /*
     * Do some up front sanity checks before we go off and
     * build the svc_action_t instance.
     */

    if (crm_strlen_zero(name)) {
        crm_err("A service or resource action must have a name.");
        goto return_error;
    }

    if (crm_strlen_zero(standard)) {
        crm_err("A service action must have a valid standard.");
        goto return_error;
    }

    if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) {
        crm_err("An OCF resource action must have a provider.");
        goto return_error;
    }

    if (crm_strlen_zero(agent)) {
        crm_err("A service or resource action must have an agent.");
        goto return_error;
    }

    if (crm_strlen_zero(action)) {
        crm_err("A service or resource action must specify an action.");
        goto return_error;
    }

    if (safe_str_eq(action, "monitor") && (
#if SUPPORT_HEARTBEAT
        safe_str_eq(standard, "heartbeat") ||
#endif
        safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) {
        action = "status";
    }

    /*
     * Sanity checks passed, proceed!
     */

    op = calloc(1, sizeof(svc_action_t));
    op->opaque = calloc(1, sizeof(svc_action_private_t));
    op->opaque->pending = NULL;
    op->rsc = strdup(name);
    op->action = strdup(action);
    op->interval = interval;
    op->timeout = timeout;
    op->standard = strdup(standard);
    op->agent = strdup(agent);
    op->sequence = ++operations;
    op->flags = flags;

    if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) {
        goto return_error;
    }

    if (strcasecmp(op->standard, "service") == 0) {
        const char *expanded = resources_find_service_class(op->agent);

        if(expanded) {
            crm_debug("Found a %s agent for %s/%s", expanded, op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup(expanded);

        } else {
            crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup("lsb");
        }
        CRM_ASSERT(op->standard);
    }

    if (strcasecmp(op->standard, "ocf") == 0) {
        op->provider = strdup(provider);
        op->params = params;
        params = NULL;

        if (asprintf(&op->opaque->exec, "%s/resource.d/%s/%s", OCF_ROOT_DIR, provider, agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(action);

    } else if (strcasecmp(op->standard, "lsb") == 0) {
        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
             * of tacking on the LSB_ROOT_DIR path to the front */
            op->opaque->exec = strdup(op->agent);
        } else if (asprintf(&op->opaque->exec, "%s/%s", LSB_ROOT_DIR, op->agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(op->action);
        op->opaque->args[2] = NULL;
#if SUPPORT_HEARTBEAT
    } else if (strcasecmp(op->standard, "heartbeat") == 0) {
        int index;
        int param_num;
        char buf_tmp[20];
        void *value_tmp;

        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
             * of tacking on the HB_RA_DIR path to the front */
            op->opaque->exec = strdup(op->agent);
        } else if (asprintf(&op->opaque->exec, "%s/%s", HB_RA_DIR, op->agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);

        /* The "heartbeat" agent class only has positional arguments,
         * which we keyed by their decimal position number. */
        param_num = 1;
	for (index = 1; index <= MAX_ARGC - 3; index++ ) {
            snprintf(buf_tmp, sizeof(buf_tmp), "%d", index);
            value_tmp = g_hash_table_lookup(params, buf_tmp);
            if (value_tmp == NULL) {
                /* maybe: strdup("") ??
                 * But the old lrmd did simply continue as well. */
                continue;
            }
            op->opaque->args[param_num++] = strdup(value_tmp);
        }

	/* Add operation code as the last argument, */
	/* and the teminating NULL pointer */
        op->opaque->args[param_num++] = strdup(op->action);
        op->opaque->args[param_num] = NULL;
#endif
#if SUPPORT_SYSTEMD
    } else if (strcasecmp(op->standard, "systemd") == 0) {
        op->opaque->exec = strdup("systemd-dbus");
#endif
#if SUPPORT_UPSTART
    } else if (strcasecmp(op->standard, "upstart") == 0) {
        op->opaque->exec = strdup("upstart-dbus");
#endif
    } else if (strcasecmp(op->standard, "service") == 0) {
        op->opaque->exec = strdup(SERVICE_SCRIPT);
        op->opaque->args[0] = strdup(SERVICE_SCRIPT);
        op->opaque->args[1] = strdup(agent);
        op->opaque->args[2] = strdup(action);

#if SUPPORT_NAGIOS
    } else if (strcasecmp(op->standard, "nagios") == 0) {
        int index = 0;

        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
             * of tacking on the NAGIOS_PLUGIN_DIR path to the front */
            op->opaque->exec = strdup(op->agent);

        } else if (asprintf(&op->opaque->exec, "%s/%s", NAGIOS_PLUGIN_DIR, op->agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }

        op->opaque->args[0] = strdup(op->opaque->exec);
        index = 1;

        if (safe_str_eq(op->action, "monitor") && op->interval == 0) {
            /* Invoke --version for a nagios probe */
            op->opaque->args[index] = strdup("--version");
            index++;

        } else if (params) {
            GHashTableIter iter;
            char *key = NULL;
            char *value = NULL;
            static int args_size = sizeof(op->opaque->args) / sizeof(char *);

            g_hash_table_iter_init(&iter, params);

            while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
                   index <= args_size - 3) {
                int len = 3;
                char *long_opt = NULL;

                if (safe_str_eq(key, XML_ATTR_CRM_VERSION) || strstr(key, CRM_META "_")) {
                    continue;
                }

                len += strlen(key);
                long_opt = calloc(1, len);
                sprintf(long_opt, "--%s", key);
                long_opt[len - 1] = 0;

                op->opaque->args[index] = long_opt;
                op->opaque->args[index + 1] = strdup(value);
                index += 2;
            }
        }
        op->opaque->args[index] = NULL;
#endif

    } else {
        crm_err("Unknown resource standard: %s", op->standard);
        services_action_free(op);
        op = NULL;
    }

    if(params) {
        g_hash_table_destroy(params);
    }
    return op;

  return_error:
    if(params) {
        g_hash_table_destroy(params);
    }
    services_action_free(op);

    return NULL;
}
예제 #5
0
파일: tengine.c 프로젝트: jjzhang/pacemaker
/*	 A_TE_START, A_TE_STOP, A_TE_RESTART	*/
void
do_te_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 init_ok = TRUE;

    if (action & A_TE_STOP) {
        if (transition_graph) {
            destroy_graph(transition_graph);
            transition_graph = NULL;
        }

        if (fsa_cib_conn) {
            fsa_cib_conn->cmds->del_notify_callback(
                fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff);
        }

        clear_bit(fsa_input_register, te_subsystem->flag_connected);
        crm_info("Transitioner is now inactive");
    }

    if ((action & A_TE_START) == 0) {
        return;

    } else if (is_set(fsa_input_register, te_subsystem->flag_connected)) {
        crm_debug("The transitioner is already active");
        return;

    } else if ((action & A_TE_START) && cur_state == S_STOPPING) {
        crm_info("Ignoring request to start %s while shutting down", te_subsystem->name);
        return;
    }

    te_uuid = crm_generate_uuid();
    crm_info("Registering TE UUID: %s", te_uuid);

    if (transition_trigger == NULL) {
        transition_trigger = mainloop_add_trigger(G_PRIORITY_LOW, te_graph_trigger, NULL);
    }

    if (pcmk_ok !=
        fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) {
        crm_err("Could not set CIB notification callback");
        init_ok = FALSE;
    }

    if (pcmk_ok != fsa_cib_conn->cmds->set_op_callback(fsa_cib_conn, global_cib_callback)) {
        crm_err("Could not set CIB global callback");
        init_ok = FALSE;
    }

    if (init_ok) {
        set_graph_functions(&te_graph_fns);

        if (transition_graph) {
            destroy_graph(transition_graph);
        }

        /* create a blank one */
        crm_debug("Transitioner is now active");
        transition_graph = create_blank_graph();
        set_bit(fsa_input_register, te_subsystem->flag_connected);
    }
}
예제 #6
0
int
main(int argc, char **argv, char **envp)
{
    int flag = 0;
    int index = 0;
    int bump_log_num = 0;
    const char *option = NULL;

    /* If necessary, create PID1 now before any FDs are opened */
    spawn_pidone(argc, argv, envp);

#ifndef ENABLE_PCMK_REMOTE
    crm_log_preinit("pacemaker-execd", argc, argv);
    crm_set_options(NULL, "[options]", long_options,
                    "Resource agent executor daemon for cluster nodes");
#else
    crm_log_preinit("pacemaker-remoted", argc, argv);
    crm_set_options(NULL, "[options]", long_options,
                    "Resource agent executor daemon for Pacemaker Remote nodes");
#endif

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

        switch (flag) {
            case 'l':
                crm_add_logfile(optarg);
                break;
            case 'p':
                setenv("PCMK_remote_port", optarg, 1);
                break;
            case 'V':
                bump_log_num++;
                break;
            case '?':
            case '$':
                crm_help(flag, CRM_EX_OK);
                break;
            default:
                crm_help('?', CRM_EX_USAGE);
                break;
        }
    }

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

    while (bump_log_num > 0) {
        crm_bump_log_level(argc, argv);
        bump_log_num--;
    }

    option = daemon_option("logfacility");
    if(option && safe_str_neq(option, "none")) {
        setenv("HA_LOGFACILITY", option, 1);  /* Used by the ocf_log/ha_log OCF macro */
    }

    option = daemon_option("logfile");
    if(option && safe_str_neq(option, "none")) {
        setenv("HA_LOGFILE", option, 1);      /* Used by the ocf_log/ha_log OCF macro */

        if (daemon_option_enabled(crm_system_name, "debug")) {
            setenv("HA_DEBUGLOG", option, 1); /* Used by the ocf_log/ha_debug OCF macro */
        }
    }

    /* The presence of this variable allegedly controls whether child
     * processes like httpd will try and use Systemd's sd_notify
     * API
     */
    unsetenv("NOTIFY_SOCKET");

    /* Used by RAs - Leave owned by root */
    crm_build_path(CRM_RSCTMP_DIR, 0755);

    rsc_list = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_rsc);
    ipcs = mainloop_add_ipc_server(CRM_SYSTEM_LRMD, QB_IPC_SHM, &lrmd_ipc_callbacks);
    if (ipcs == NULL) {
        crm_err("Failed to create IPC server: shutting down and inhibiting respawn");
        crm_exit(CRM_EX_FATAL);
    }

#ifdef ENABLE_PCMK_REMOTE
    if (lrmd_init_remote_tls_server() < 0) {
        crm_err("Failed to create TLS listener: shutting down and staying down");
        crm_exit(CRM_EX_FATAL);
    }
    ipc_proxy_init();
#endif

    mainloop_add_signal(SIGTERM, lrmd_shutdown);
    mainloop = g_main_loop_new(NULL, FALSE);
    crm_info("Starting");
    g_main_loop_run(mainloop);

    /* should never get here */
    lrmd_exit(NULL);
    return CRM_EX_OK;
}
예제 #7
0
static void
action_synced_wait(svc_action_t * op, sigset_t mask)
{

#ifndef HAVE_SYS_SIGNALFD_H
    CRM_ASSERT(FALSE);
#else
    int status = 0;
    int timeout = op->timeout;
    int sfd = -1;
    time_t start = -1;
    struct pollfd fds[3];
    int wait_rc = 0;

    sfd = signalfd(-1, &mask, SFD_NONBLOCK);
    if (sfd < 0) {
        crm_perror(LOG_ERR, "signalfd() failed");
    }

    fds[0].fd = op->opaque->stdout_fd;
    fds[0].events = POLLIN;
    fds[0].revents = 0;

    fds[1].fd = op->opaque->stderr_fd;
    fds[1].events = POLLIN;
    fds[1].revents = 0;

    fds[2].fd = sfd;
    fds[2].events = POLLIN;
    fds[2].revents = 0;

    crm_trace("Waiting for %d", op->pid);
    start = time(NULL);
    do {
        int poll_rc = poll(fds, 3, timeout);

        if (poll_rc > 0) {
            if (fds[0].revents & POLLIN) {
                svc_read_output(op->opaque->stdout_fd, op, FALSE);
            }

            if (fds[1].revents & POLLIN) {
                svc_read_output(op->opaque->stderr_fd, op, TRUE);
            }

            if (fds[2].revents & POLLIN) {
                struct signalfd_siginfo fdsi;
                ssize_t s;

                s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
                if (s != sizeof(struct signalfd_siginfo)) {
                    crm_perror(LOG_ERR, "Read from signal fd %d failed", sfd);

                } else if (fdsi.ssi_signo == SIGCHLD) {
                    wait_rc = waitpid(op->pid, &status, WNOHANG);

                    if (wait_rc < 0){
                        crm_perror(LOG_ERR, "waitpid() for %d failed", op->pid);

                    } else if (wait_rc > 0) {
                        break;
                    }
                }
            }

        } else if (poll_rc == 0) {
            timeout = 0;
            break;

        } else if (poll_rc < 0) {
            if (errno != EINTR) {
                crm_perror(LOG_ERR, "poll() failed");
                break;
            }
        }

        timeout = op->timeout - (time(NULL) - start) * 1000;

    } while ((op->timeout < 0 || timeout > 0));

    crm_trace("Child done: %d", op->pid);
    if (wait_rc <= 0) {
        int killrc = kill(op->pid, SIGKILL);

        op->rc = PCMK_OCF_UNKNOWN_ERROR;
        if (op->timeout > 0 && timeout <= 0) {
            op->status = PCMK_LRM_OP_TIMEOUT;
            crm_warn("%s:%d - timed out after %dms", op->id, op->pid, op->timeout);

        } else {
            op->status = PCMK_LRM_OP_ERROR;
        }

        if (killrc && errno != ESRCH) {
            crm_err("kill(%d, KILL) failed: %d", op->pid, errno);
        }
        /*
         * From sigprocmask(2):
         * It is not possible to block SIGKILL or SIGSTOP.  Attempts to do so are silently ignored.
         *
         * This makes it safe to skip WNOHANG here
         */
        waitpid(op->pid, &status, 0);

    } else if (WIFEXITED(status)) {
        op->status = PCMK_LRM_OP_DONE;
        op->rc = WEXITSTATUS(status);
        crm_info("Managed %s process %d exited with rc=%d", op->id, op->pid, op->rc);

    } else if (WIFSIGNALED(status)) {
        int signo = WTERMSIG(status);

        op->status = PCMK_LRM_OP_ERROR;
        crm_err("Managed %s process %d exited with signal=%d", op->id, op->pid, signo);
    }
#ifdef WCOREDUMP
    if (WCOREDUMP(status)) {
        crm_err("Managed %s process %d dumped core", op->id, op->pid);
    }
#endif

    svc_read_output(op->opaque->stdout_fd, op, FALSE);
    svc_read_output(op->opaque->stderr_fd, op, TRUE);

    close(op->opaque->stdout_fd);
    close(op->opaque->stderr_fd);
    close(sfd);

#endif

}
예제 #8
0
int
main(int argc, char **argv)
{
    int flag = 0;
    int index = 0;
    int argerr = 0;
    crm_ipc_t *old_instance = NULL;

    attrd_init_mainloop();
    crm_log_preinit(NULL, argc, argv);
    crm_set_options(NULL, "[options]", long_options,
                    "Daemon for aggregating and atomically storing node attribute updates into the CIB");

    mainloop_add_signal(SIGTERM, attrd_shutdown);

     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, CRM_EX_OK);
                break;
            default:
                ++argerr;
                break;
        }
    }

    if (optind > argc) {
        ++argerr;
    }

    if (argerr) {
        crm_help('?', CRM_EX_USAGE);
    }

    crm_log_init(T_ATTRD, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
    crm_notice("Starting Pacemaker node attribute manager");

    old_instance = crm_ipc_new(T_ATTRD, 0);
    if (crm_ipc_connect(old_instance)) {
        /* IPC end-point already up */
        crm_ipc_close(old_instance);
        crm_ipc_destroy(old_instance);
        crm_err("pacemaker-attrd is already active, aborting startup");
        crm_exit(CRM_EX_OK);
    } else {
        /* not up or not authentic, we'll proceed either way */
        crm_ipc_destroy(old_instance);
        old_instance = NULL;
    }

    attributes = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_attribute);

    /* Connect to the CIB before connecting to the cluster or listening for IPC.
     * This allows us to assume the CIB is connected whenever we process a
     * cluster or IPC message (which also avoids start-up race conditions).
     */
    if (attrd_cib_connect(10) != pcmk_ok) {
        attrd_exit_status = CRM_EX_FATAL;
        goto done;
    }
    crm_info("CIB connection active");

    if (attrd_cluster_connect() != pcmk_ok) {
        attrd_exit_status = CRM_EX_FATAL;
        goto done;
    }
    crm_info("Cluster connection active");

    // Initialization that requires the cluster to be connected
    attrd_election_init();
    attrd_cib_init();

    /* Set a private attribute for ourselves with the protocol version we
     * support. This lets all nodes determine the minimum supported version
     * across all nodes. It also ensures that the writer learns our node name,
     * so it can send our attributes to the CIB.
     */
    attrd_broadcast_protocol();

    attrd_init_ipc(&ipcs, attrd_ipc_dispatch);
    crm_notice("Pacemaker node attribute manager successfully started and accepting connections");
    attrd_run_mainloop();

  done:
    crm_info("Shutting down attribute manager");

    attrd_election_fini();
    attrd_ipc_fini();
    attrd_lrmd_disconnect();
    attrd_cib_disconnect();
    g_hash_table_destroy(attributes);

    crm_exit(attrd_exit_status);
}
예제 #9
0
파일: upstart.c 프로젝트: kjperry/pacemaker
GList *
upstart_job_listall(void)
{
    GList *units = NULL;
    DBusMessageIter args;
    DBusMessageIter unit;
    DBusMessage *msg = NULL;
    DBusMessage *reply = NULL;
    const char *method = "GetAllJobs";
    DBusError error;
    int lpc = 0;

    if (upstart_init() == FALSE) {
        return NULL;
    }

/*
  com.ubuntu.Upstart0_6.GetAllJobs (out <Array of ObjectPath> jobs)
*/

    dbus_error_init(&error);
    msg = dbus_message_new_method_call(BUS_NAME, // target for the method call
                                       BUS_PATH, // object to call on
                                       UPSTART_06_API, // interface to call on
                                       method); // method name
    CRM_ASSERT(msg != NULL);

    reply = pcmk_dbus_send_recv(msg, upstart_proxy, &error);
    dbus_message_unref(msg);

    if(error.name) {
        crm_err("Call to %s failed: %s", method, error.name);
        return NULL;

    } else if (!dbus_message_iter_init(reply, &args)) {
        crm_err("Call to %s failed: Message has no arguments", method);
        dbus_message_unref(reply);
        return NULL;
    }

    if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __FUNCTION__, __LINE__)) {
        crm_err("Call to %s failed: Message has invalid arguments", method);
        dbus_message_unref(reply);
        return NULL;
    }

    dbus_message_iter_recurse(&args, &unit);
    while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) {
        DBusBasicValue value;
        const char *job = NULL;
        char *path = NULL;

        if(!pcmk_dbus_type_check(reply, &unit, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) {
            continue;
        }

        dbus_message_iter_get_basic(&unit, &value);

        if(value.str) {
            int llpc = 0;
            path = value.str;
            job = value.str;
            while (path[llpc] != 0) {
                if (path[llpc] == '/') {
                    job = path + llpc + 1;
                }
                llpc++;
            }
            lpc++;
            crm_trace("%s -> %s\n", path, job);
            units = g_list_append(units, fix_upstart_name(job));
        }
        dbus_message_iter_next (&unit);
    }

    dbus_message_unref(reply);
    crm_trace("Found %d upstart jobs", lpc);
    return units;
}
예제 #10
0
static gboolean
mainloop_gio_callback(GIOChannel *gio, GIOCondition condition, gpointer data)
{
    gboolean keep = TRUE;
    mainloop_io_t *client = data;

    if(condition & G_IO_IN) {
        if(client->ipc) {
            long rc = 0;
            int max = 10;
            do {
                rc = crm_ipc_read(client->ipc);
                if(rc <= 0) {
                    crm_trace("Message acquisition from %s[%p] failed: %s (%ld)",
                              client->name, client, pcmk_strerror(rc), rc);

                } else if(client->dispatch_fn_ipc) {
                    const char *buffer = crm_ipc_buffer(client->ipc);
                    crm_trace("New message from %s[%p] = %d", client->name, client, rc, condition);
                    if(client->dispatch_fn_ipc(buffer, rc, client->userdata) < 0) {
                        crm_trace("Connection to %s no longer required", client->name);
                        keep = FALSE;
                    }
                }

            } while(keep && rc > 0 && --max > 0);

        } else {
            crm_trace("New message from %s[%p]", client->name, client);
            if(client->dispatch_fn_io) {
                if(client->dispatch_fn_io(client->userdata) < 0) {
                    crm_trace("Connection to %s no longer required", client->name);
                    keep = FALSE;
                }
            }
        }
    }

    if(client->ipc && crm_ipc_connected(client->ipc) == FALSE) {
        crm_err("Connection to %s[%p] closed (I/O condition=%d)", client->name, client, condition);
        keep = FALSE;

    } else if(condition & (G_IO_HUP|G_IO_NVAL|G_IO_ERR)) {
        crm_trace("The connection %s[%p] has been closed (I/O condition=%d, refcount=%d)",
                  client->name, client, condition, mainloop_gio_refcount(client));
        keep = FALSE;

    } else if((condition & G_IO_IN) == 0) {
        /*
          #define 	GLIB_SYSDEF_POLLIN     =1
          #define 	GLIB_SYSDEF_POLLPRI    =2
          #define 	GLIB_SYSDEF_POLLOUT    =4
          #define 	GLIB_SYSDEF_POLLERR    =8
          #define 	GLIB_SYSDEF_POLLHUP    =16
          #define 	GLIB_SYSDEF_POLLNVAL   =32

          typedef enum
          {
            G_IO_IN	GLIB_SYSDEF_POLLIN,
            G_IO_OUT	GLIB_SYSDEF_POLLOUT,
            G_IO_PRI	GLIB_SYSDEF_POLLPRI,
            G_IO_ERR	GLIB_SYSDEF_POLLERR,
            G_IO_HUP	GLIB_SYSDEF_POLLHUP,
            G_IO_NVAL	GLIB_SYSDEF_POLLNVAL
          } GIOCondition;

          A bitwise combination representing a condition to watch for on an event source.

          G_IO_IN	There is data to read.
          G_IO_OUT	Data can be written (without blocking).
          G_IO_PRI	There is urgent data to read.
          G_IO_ERR	Error condition.
          G_IO_HUP	Hung up (the connection has been broken, usually for pipes and sockets).
          G_IO_NVAL	Invalid request. The file descriptor is not open.    
        */
        crm_err("Strange condition: %d", condition);
    }

    /* keep == FALSE results in mainloop_gio_destroy() being called
     * just before the source is removed from mainloop
     */
    return keep;
}
예제 #11
0
static bool throttle_cib_load(float *load) 
{
/*
       /proc/[pid]/stat
              Status information about the process.  This is used by ps(1).  It is defined in /usr/src/linux/fs/proc/array.c.

              The fields, in order, with their proper scanf(3) format specifiers, are:

              pid %d      (1) The process ID.

              comm %s     (2) The filename of the executable, in parentheses.  This is visible whether or not the executable is swapped out.

              state %c    (3) One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging.

              ppid %d     (4) The PID of the parent.

              pgrp %d     (5) The process group ID of the process.

              session %d  (6) The session ID of the process.

              tty_nr %d   (7) The controlling terminal of the process.  (The minor device number is contained in the combination of bits 31 to 20 and 7 to 0; the major device number is in bits 15 to 8.)

              tpgid %d    (8) The ID of the foreground process group of the controlling terminal of the process.

              flags %u (%lu before Linux 2.6.22)
                          (9) The kernel flags word of the process.  For bit meanings, see the PF_* defines in the Linux kernel source file include/linux/sched.h.  Details depend on the kernel version.

              minflt %lu  (10) The number of minor faults the process has made which have not required loading a memory page from disk.

              cminflt %lu (11) The number of minor faults that the process's waited-for children have made.

              majflt %lu  (12) The number of major faults the process has made which have required loading a memory page from disk.

              cmajflt %lu (13) The number of major faults that the process's waited-for children have made.

              utime %lu   (14) Amount of time that this process has been scheduled in user mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).  This includes guest time, guest_time (time spent running a virtual CPU, see below), so that applications that are not aware of the guest time field do not lose that time from their calculations.

              stime %lu   (15) Amount of time that this process has been scheduled in kernel mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
 */

    static char *loadfile = NULL;
    static time_t last_call = 0;
    static long ticks_per_s = 0;
    static unsigned long last_utime, last_stime;

    char buffer[64*1024];
    FILE *stream = NULL;
    time_t now = time(NULL);

    if(load == NULL) {
        return FALSE;
    } else {
        *load = 0.0;
    }

    if(loadfile == NULL) {
        last_call = 0;
        last_utime = 0;
        last_stime = 0;
        loadfile = find_cib_loadfile();
        ticks_per_s = sysconf(_SC_CLK_TCK);
        crm_trace("Found %s", loadfile);
    }

    stream = fopen(loadfile, "r");
    if(stream == NULL) {
        int rc = errno;

        crm_warn("Couldn't read %s: %s (%d)", loadfile, pcmk_strerror(rc), rc);
        free(loadfile); loadfile = NULL;
        return FALSE;
    }

    if(fgets(buffer, sizeof(buffer), stream)) {
        char *comm = calloc(1, 256);
        char state = 0;
        int rc = 0, pid = 0, ppid = 0, pgrp = 0, session = 0, tty_nr = 0, tpgid = 0;
        unsigned long flags = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0, utime = 0, stime = 0;

        rc = sscanf(buffer,  "%d %[^ ] %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu",
                    &pid, comm, &state,
                    &ppid, &pgrp, &session, &tty_nr, &tpgid,
                    &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime);
        free(comm);

        if(rc != 15) {
            crm_err("Only %d of 15 fields found in %s", rc, loadfile);
            fclose(stream);
            return FALSE;

        } else if(last_call > 0
           && last_call < now
           && last_utime <= utime
           && last_stime <= stime) {

            time_t elapsed = now - last_call;
            unsigned long delta_utime = utime - last_utime;
            unsigned long delta_stime = stime - last_stime;

            *load = (delta_utime + delta_stime); /* Cast to a float before division */
            *load /= ticks_per_s;
            *load /= elapsed;
            crm_debug("cib load: %f (%lu ticks in %ds)", *load, delta_utime + delta_stime, elapsed);

        } else {
            crm_debug("Init %lu + %lu ticks at %d (%lu tps)", utime, stime, now, ticks_per_s);
        }

        last_call = now;
        last_utime = utime;
        last_stime = stime;

        fclose(stream);
        return TRUE;
    }

    fclose(stream);
    return FALSE;
}
int
main(int argc, char *argv[])
{
    int argerr = 0;
    int flag;
    int index = 0;
    int rc = 0;
    servicelog *slog = NULL;
    struct sl_event *event = NULL;
    uint64_t event_id = 0;

    crm_log_cli_init("notifyServicelogEvent");
    crm_set_options(NULL, "event_id ", long_options,
                    "Gets called upon events written to servicelog database");

    if (argc < 2) {
        argerr++;
    }

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

        switch (flag) {
            case '?':
            case '$':
                crm_help(flag, CRM_EX_OK);
                break;
            default:
                ++argerr;
                break;
        }
    }

    if (argc - optind != 1) {
        ++argerr;
    }

    if (argerr) {
        crm_help('?', CRM_EX_USAGE);
    }

    openlog("notifyServicelogEvent", LOG_NDELAY, LOG_USER);

    if (sscanf(argv[optind], "%" U64TS, &event_id) != 1) {
        crm_err("Error: could not read event_id from args!");

        rc = 1;
        goto cleanup;
    }

    if (event_id == 0) {
        crm_err("Error: event_id is 0!");

        rc = 1;
        goto cleanup;
    }

    rc = servicelog_open(&slog, 0);     /* flags is one of SL_FLAG_xxx */

    if (!slog) {
        crm_err("Error: servicelog_open failed, rc = %d", rc);

        rc = 1;
        goto cleanup;
    }

    if (slog) {
        rc = servicelog_event_get(slog, event_id, &event);
    }

    if (rc == 0) {
        STATUS status = STATUS_GREEN;
        const char *health_component = "#health-ipmi";
        const char *health_status = NULL;

        crm_debug("Event id = %" U64T ", Log timestamp = %s, Event timestamp = %s",
                  event_id, ctime(&(event->time_logged)), ctime(&(event->time_event)));

        status = event2status(event);

        health_status = status2char(status);

        if (health_status) {
            gboolean rc;

            /* @TODO pass attrd_opt_remote when appropriate */
            rc = (attrd_update_delegate(NULL, 'v', NULL, health_component,
                                        health_status, NULL, NULL, NULL, NULL,
                                        attrd_opt_none) > 0);
            crm_debug("Updating attribute ('%s', '%s') = %d",
                      health_component, health_status, rc);
        } else {
            crm_err("Error: status2char failed, status = %d", status);
            rc = 1;
        }
    } else {
        crm_err("Error: servicelog_event_get failed, rc = %d", rc);
    }

  cleanup:
    if (event) {
        servicelog_event_free(event);
    }

    if (slog) {
        servicelog_close(slog);
    }

    closelog();

    return rc;
}
예제 #13
0
int
register_fsa_input_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input,
                       void *data, long long with_actions,
                       gboolean prepend, const char *raised_from)
{
    unsigned old_len = g_list_length(fsa_message_queue);
    fsa_data_t *fsa_data = NULL;

    last_data_id++;
    CRM_CHECK(raised_from != NULL, raised_from = "<unknown>");

    crm_trace("%s %s FSA input %d (%s) (cause=%s) %s data",
                raised_from, prepend ? "prepended" : "appended", last_data_id,
                fsa_input2string(input), fsa_cause2string(cause), data ? "with" : "without");

    if (input == I_WAIT_FOR_EVENT) {
        do_fsa_stall = TRUE;
        crm_debug("Stalling the FSA pending further input: cause=%s", fsa_cause2string(cause));
        if (old_len > 0) {
            crm_warn("%s stalled the FSA with pending inputs", raised_from);
            fsa_dump_queue(LOG_DEBUG);
        }
        if (data == NULL) {
            set_bit_inplace(fsa_actions, with_actions);
            with_actions = A_NOTHING;
            return 0;
        }
        crm_err("%s stalled the FSA with data - this may be broken", raised_from);
    }

    if (input == I_NULL && with_actions == A_NOTHING /* && data == NULL */ ) {
        /* no point doing anything */
        crm_err("Cannot add entry to queue: no input and no action");
        return 0;
    }

    crm_malloc0(fsa_data, sizeof(fsa_data_t));
    fsa_data->id = last_data_id;
    fsa_data->fsa_input = input;
    fsa_data->fsa_cause = cause;
    fsa_data->origin = raised_from;
    fsa_data->data = NULL;
    fsa_data->data_type = fsa_dt_none;
    fsa_data->actions = with_actions;

    if (with_actions != A_NOTHING) {
        crm_trace("Adding actions %.16llx to input", with_actions);
    }

    if (data != NULL) {
        switch (cause) {
            case C_FSA_INTERNAL:
            case C_CRMD_STATUS_CALLBACK:
            case C_IPC_MESSAGE:
            case C_HA_MESSAGE:
                crm_trace("Copying %s data from %s as a HA msg",
                            fsa_cause2string(cause), raised_from);
                CRM_CHECK(((ha_msg_input_t *) data)->msg != NULL,
                          crm_err("Bogus data from %s", raised_from));
                fsa_data->data = copy_ha_msg_input(data);
                fsa_data->data_type = fsa_dt_ha_msg;
                break;

            case C_LRM_OP_CALLBACK:
                crm_trace("Copying %s data from %s as lrm_op_t",
                            fsa_cause2string(cause), raised_from);
                fsa_data->data = copy_lrm_op((lrm_op_t *) data);
                fsa_data->data_type = fsa_dt_lrm;
                break;

            case C_CCM_CALLBACK:
            case C_SUBSYSTEM_CONNECT:
            case C_LRM_MONITOR_CALLBACK:
            case C_TIMER_POPPED:
            case C_SHUTDOWN:
            case C_HEARTBEAT_FAILED:
            case C_HA_DISCONNECT:
            case C_ILLEGAL:
            case C_UNKNOWN:
            case C_STARTUP:
                crm_err("Copying %s data (from %s)"
                        " not yet implemented", fsa_cause2string(cause), raised_from);
                exit(1);
                break;
        }
        crm_trace("%s data copied", fsa_cause2string(fsa_data->fsa_cause));
    }

    /* make sure to free it properly later */
    if (prepend) {
        crm_trace("Prepending input");
        fsa_message_queue = g_list_prepend(fsa_message_queue, fsa_data);
    } else {
        fsa_message_queue = g_list_append(fsa_message_queue, fsa_data);
    }

    crm_trace("Queue len: %d", g_list_length(fsa_message_queue));

    fsa_dump_queue(LOG_DEBUG_2);

    if (old_len == g_list_length(fsa_message_queue)) {
        crm_err("Couldnt add message to the queue");
    }

    if (fsa_source) {
        crm_trace("Triggering FSA: %s", __FUNCTION__);
        mainloop_set_trigger(fsa_source);
    }
    return last_data_id;
}
예제 #14
0
enum crmd_fsa_input
handle_request(xmlNode * stored_msg)
{
    xmlNode *msg = NULL;
    const char *op = crm_element_value(stored_msg, F_CRM_TASK);

    /* Optimize this for the DC - it has the most to do */

    if (op == NULL) {
        crm_log_xml_err(stored_msg, "Bad message");
        return I_NULL;
    }

    /*========== DC-Only Actions ==========*/
    if (AM_I_DC) {
        if (strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) {
            return I_NODE_JOIN;

        } else if (strcmp(op, CRM_OP_JOIN_REQUEST) == 0) {
            return I_JOIN_REQUEST;

        } else if (strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) {
            return I_JOIN_RESULT;

        } else if (strcmp(op, CRM_OP_SHUTDOWN) == 0) {
            const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
            gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);

            if (is_set(fsa_input_register, R_SHUTDOWN)) {
                crm_info("Shutting ourselves down (DC)");
                return I_STOP;

            } else if (dc_match) {
                crm_err("We didnt ask to be shut down, yet our"
                        " TE is telling us too." " Better get out now!");
                return I_TERMINATE;

            } else if (fsa_state != S_STOPPING) {
                crm_err("Another node is asking us to shutdown" " but we think we're ok.");
                return I_ELECTION;
            }

        } else if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
            /* a slave wants to shut down */
            /* create cib fragment and add to message */
            return handle_shutdown_request(stored_msg);
        }
    }

    /*========== common actions ==========*/
    if (strcmp(op, CRM_OP_NOVOTE) == 0) {
        ha_msg_input_t fsa_input;

        fsa_input.msg = stored_msg;
        register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
                               A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);

    } else if (strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) {
        return handle_failcount_op(stored_msg);

    } else if (strcmp(op, CRM_OP_VOTE) == 0) {
        /* count the vote and decide what to do after that */
        ha_msg_input_t fsa_input;

        fsa_input.msg = stored_msg;
        register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input,
                               A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__);

        /* Sometimes we _must_ go into S_ELECTION */
        if (fsa_state == S_HALT) {
            crm_debug("Forcing an election from S_HALT");
            return I_ELECTION;
#if 0
        } else if (AM_I_DC) {
            /* This is the old way of doing things but what is gained? */
            return I_ELECTION;
#endif
        }

    } else if (strcmp(op, CRM_OP_JOIN_OFFER) == 0) {
        crm_debug("Raising I_JOIN_OFFER: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
        return I_JOIN_OFFER;

    } else if (strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) {
        crm_debug("Raising I_JOIN_RESULT: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
        return I_JOIN_RESULT;

    } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0
               || strcmp(op, CRM_OP_LRM_FAIL) == 0
               || strcmp(op, CRM_OP_LRM_REFRESH) == 0 || strcmp(op, CRM_OP_REPROBE) == 0) {

        crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD);
        return I_ROUTER;

    } else if (strcmp(op, CRM_OP_NOOP) == 0) {
        return I_NULL;

    } else if (strcmp(op, CRM_OP_LOCAL_SHUTDOWN) == 0) {

        crm_shutdown(SIGTERM);
        /*return I_SHUTDOWN; */
        return I_NULL;

        /*========== (NOT_DC)-Only Actions ==========*/
    } else if (AM_I_DC == FALSE && strcmp(op, CRM_OP_SHUTDOWN) == 0) {

        const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);
        gboolean dc_match = safe_str_eq(host_from, fsa_our_dc);

        if (dc_match || fsa_our_dc == NULL) {
            if (is_set(fsa_input_register, R_SHUTDOWN) == FALSE) {
                crm_err("We didn't ask to be shut down, yet our" " DC is telling us too.");
                set_bit_inplace(fsa_input_register, R_STAYDOWN);
                return I_STOP;
            }
            crm_info("Shutting down");
            return I_STOP;

        } else {
            crm_warn("Discarding %s op from %s", op, host_from);
        }

    } else if (strcmp(op, CRM_OP_PING) == 0) {
        /* eventually do some stuff to figure out
         * if we /are/ ok
         */
        const char *sys_to = crm_element_value(stored_msg, F_CRM_SYS_TO);
        xmlNode *ping = createPingAnswerFragment(sys_to, "ok");

        crm_xml_add(ping, "crmd_state", fsa_state2string(fsa_state));

        crm_info("Current ping state: %s", fsa_state2string(fsa_state));

        msg = create_reply(stored_msg, ping);
        relay_message(msg, TRUE);

        free_xml(ping);
        free_xml(msg);

        /* probably better to do this via signals on the
         * local node
         */
    } else if (strcmp(op, CRM_OP_DEBUG_UP) == 0) {
        crm_bump_log_level();
        crm_info("Debug set to %d", get_crm_log_level());

    } else if (strcmp(op, CRM_OP_DEBUG_DOWN) == 0) {
        alter_debug(DEBUG_DEC);
        crm_info("Debug set to %d", get_crm_log_level());

    } else {
        crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC ? "the DC" : "non-DC node");
        crm_log_xml_err(stored_msg, "Unexpected");
    }

    return I_NULL;
}
예제 #15
0
파일: corosync.c 프로젝트: beess/pacemaker
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;
}
예제 #16
0
파일: upstart.c 프로젝트: kjperry/pacemaker
gboolean
upstart_job_exec(svc_action_t * op, gboolean synchronous)
{
    char *job = NULL;
    int arg_wait = TRUE;
    const char *arg_env = "pacemaker=1";
    const char *action = op->action;

    DBusError error;
    DBusMessage *msg = NULL;
    DBusMessage *reply = NULL;
    DBusMessageIter iter, array_iter;

    op->rc = PCMK_OCF_UNKNOWN_ERROR;
    CRM_ASSERT(upstart_init());

    if (safe_str_eq(op->action, "meta-data")) {
        op->stdout_data = upstart_job_metadata(op->agent);
        op->rc = PCMK_OCF_OK;
        goto cleanup;
    }

    if(!upstart_job_by_name(op->agent, &job)) {
        crm_debug("Could not obtain job named '%s' to %s", op->agent, action);
        if (!g_strcmp0(action, "stop")) {
            op->rc = PCMK_OCF_OK;

        } else {
            op->rc = PCMK_OCF_NOT_INSTALLED;
            op->status = PCMK_LRM_OP_NOT_INSTALLED;
        }
        goto cleanup;
    }

    if (safe_str_eq(op->action, "monitor") || safe_str_eq(action, "status")) {
        if (upstart_job_running(op->agent)) {
            op->rc = PCMK_OCF_OK;
        } else {
            op->rc = PCMK_OCF_NOT_RUNNING;
        }
        goto cleanup;

    } else if (!g_strcmp0(action, "start")) {
        action = "Start";
    } else if (!g_strcmp0(action, "stop")) {
        action = "Stop";
    } else if (!g_strcmp0(action, "restart")) {
        action = "Restart";
    } else {
        op->rc = PCMK_OCF_UNIMPLEMENT_FEATURE;
        goto cleanup;
    }

    crm_debug("Calling %s for %s on %s", action, op->rsc, job);

    msg = dbus_message_new_method_call(BUS_NAME, // target for the method call
                                       job, // object to call on
                                       UPSTART_JOB_IFACE, // interface to call on
                                       action); // method name
    CRM_ASSERT(msg != NULL);

    dbus_message_iter_init_append (msg, &iter);

    CRM_LOG_ASSERT(dbus_message_iter_open_container (&iter,
                                                     DBUS_TYPE_ARRAY,
                                                     DBUS_TYPE_STRING_AS_STRING,
                                                     &array_iter));

    CRM_LOG_ASSERT(dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &arg_env));
    CRM_LOG_ASSERT(dbus_message_iter_close_container (&iter, &array_iter));

    CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg_wait, DBUS_TYPE_INVALID));

    if (synchronous == FALSE) {
        free(job);
        return pcmk_dbus_send(msg, upstart_proxy, upstart_async_dispatch, op);
    }

    dbus_error_init(&error);
    reply = pcmk_dbus_send_recv(msg, upstart_proxy, &error);

    if(error.name) {
        if(!upstart_mask_error(op, error.name)) {
            crm_err("Could not issue %s for %s: %s (%s)", action, op->rsc, error.name, job);
        }

    } else if (!g_strcmp0(op->action, "stop")) {
        /* No return vaue */
        op->rc = PCMK_OCF_OK;

    } else if(!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) {
        crm_warn("Call to %s passed but return type was unexpected", op->action);
        op->rc = PCMK_OCF_OK;

    } else {
        const char *path = NULL;

        dbus_message_get_args (reply, NULL,
                               DBUS_TYPE_OBJECT_PATH, &path,
                               DBUS_TYPE_INVALID);
        crm_info("Call to %s passed: %s", op->action, path);
        op->rc = PCMK_OCF_OK;
    }


  cleanup:
    free(job);
    if(msg) {
        dbus_message_unref(msg);
    }

    if(reply) {
        dbus_message_unref(reply);
    }

    if (synchronous == FALSE) {
        operation_finalize(op);
        return TRUE;
    }
    return op->rc == PCMK_OCF_OK;
}
예제 #17
0
파일: main.c 프로젝트: huiser/pacemaker
int
main(int argc, char **argv)
{
    int flag;
    int argerr = 0;
    gboolean allow_cores = TRUE;
    IPC_Channel *old_instance = NULL;

    crm_system_name = CRM_SYSTEM_PENGINE;
    mainloop_add_signal(SIGTERM, pengine_shutdown);

    while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
        switch (flag) {
            case 'V':
                alter_debug(DEBUG_INC);
                break;
            case 'h':          /* Help message */
                usage(crm_system_name, LSB_EXIT_OK);
                break;
            case 'c':
                allow_cores = TRUE;
                break;
            default:
                ++argerr;
                break;
        }
    }

    if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) {
        pe_metadata();
        return 0;
    }

    if (optind > argc) {
        ++argerr;
    }

    if (argerr) {
        usage(crm_system_name, LSB_EXIT_GENERIC);
    }

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

    if (crm_is_writable(PE_STATE_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) {
        crm_err("Bad permissions on " PE_STATE_DIR ". Terminating");
        fprintf(stderr, "ERROR: Bad permissions on " PE_STATE_DIR ". See logs for details\n");
        fflush(stderr);
        return 100;
    }

    ipc_server = crm_strdup(CRM_SYSTEM_PENGINE);

    /* find any previous instances and shut them down */
    crm_debug("Checking for old instances of %s", crm_system_name);
    old_instance = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE);
    while (old_instance != NULL) {
        xmlNode *cmd =
            create_request(CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_PENGINE, NULL);

        crm_warn("Terminating previous PE instance");
        send_ipc_message(old_instance, cmd);
        free_xml(cmd);

        sleep(2);

        old_instance->ops->destroy(old_instance);
        old_instance = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE);
    }

    crm_debug("Init server comms");
    if (init_server_ipc_comms(ipc_server, pe_client_connect, default_ipc_connection_destroy)) {
        crm_err("Couldn't start IPC server");
        return 1;
    }

    /* Create the mainloop and run it... */
    crm_info("Starting %s", crm_system_name);

    mainloop = g_main_new(FALSE);
    g_main_run(mainloop);

#if HAVE_LIBXML2
    crm_xml_cleanup();
#endif

    crm_info("Exiting %s", crm_system_name);
    return 0;
}
예제 #18
0
const char *
pcmk_strerror(int rc)
{
    int error = abs(rc);

    if (error == 0) {
        return "OK";
    } else if (error < PCMK_ERROR_OFFSET) {
        return strerror(error);
    }

    switch (error) {
        case pcmk_err_generic:
            return "Generic Pacemaker error";
        case pcmk_err_no_quorum:
            return "Operation requires quorum";
        case pcmk_err_schema_validation:
            return "Update does not conform to the configured schema";
        case pcmk_err_transform_failed:
            return "Schema transform failed";
        case pcmk_err_old_data:
            return "Update was older than existing configuration";
        case pcmk_err_diff_failed:
            return "Application of an update diff failed";
        case pcmk_err_diff_resync:
            return "Application of an update diff failed, requesting a full refresh";
        case pcmk_err_cib_modified:
            return "The on-disk configuration was manually modified";
        case pcmk_err_cib_backup:
            return "Could not archive the previous configuration";
        case pcmk_err_cib_save:
            return "Could not save the new configuration to disk";
        case pcmk_err_cib_corrupt:
            return "Could not parse on-disk configuration";
        case pcmk_err_multiple:
            return "Resource active on multiple nodes";
        case pcmk_err_node_unknown:
            return "Node not found";
        case pcmk_err_already:
            return "Situation already as requested";
        case pcmk_err_bad_nvpair:
            return "Bad name/value pair given";
        case pcmk_err_schema_unchanged:
            return "Schema is already the latest available";

            /* The following cases will only be hit on systems for which they are non-standard */
            /* coverity[dead_error_condition] False positive on non-Linux */
        case ENOTUNIQ:
            return "Name not unique on network";
            /* coverity[dead_error_condition] False positive on non-Linux */
        case ECOMM:
            return "Communication error on send";
            /* coverity[dead_error_condition] False positive on non-Linux */
        case ELIBACC:
            return "Can not access a needed shared library";
            /* coverity[dead_error_condition] False positive on non-Linux */
        case EREMOTEIO:
            return "Remote I/O error";
            /* coverity[dead_error_condition] False positive on non-Linux */
        case EUNATCH:
            return "Protocol driver not attached";
            /* coverity[dead_error_condition] False positive on non-Linux */
        case ENOKEY:
            return "Required key not available";
    }

    crm_err("Unknown error code: %d", rc);
    return "Unknown error";
}
예제 #19
0
static void
action_launch_child(svc_action_t *op)
{
    int lpc;

    /* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library.
     * Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well. 
     * We do not want this to be inherited by the child process. By resetting this the signal
     * to the default behavior, we avoid some potential odd problems that occur during OCF
     * scripts when SIGPIPE is ignored by the environment. */
    signal(SIGPIPE, SIG_DFL);

#if defined(HAVE_SCHED_SETSCHEDULER)
    if (sched_getscheduler(0) != SCHED_OTHER) {
        struct sched_param sp;

        memset(&sp, 0, sizeof(sp));
        sp.sched_priority = 0;

        if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
            crm_perror(LOG_ERR, "Could not reset scheduling policy to SCHED_OTHER for %s", op->id);
        }
    }
#endif
    if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
        crm_perror(LOG_ERR, "Could not reset process priority to 0 for %s", op->id);
    }

    /* Man: The call setpgrp() is equivalent to setpgid(0,0)
     * _and_ compiles on BSD variants too
     * need to investigate if it works the same too.
     */
    setpgid(0, 0);

    /* close all descriptors except stdin/out/err and channels to logd */
    for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) {
        close(lpc);
    }

#if SUPPORT_CIBSECRETS
    if (replace_secret_params(op->rsc, op->params) < 0) {
        /* replacing secrets failed! */
        if (safe_str_eq(op->action,"stop")) {
            /* don't fail on stop! */
            crm_info("proceeding with the stop operation for %s", op->rsc);

        } else {
            crm_err("failed to get secrets for %s, "
                    "considering resource not configured", op->rsc);
            _exit(PCMK_OCF_NOT_CONFIGURED);
        }
    }
#endif
    /* Setup environment correctly */
    add_OCF_env_vars(op);

    /* execute the RA */
    execvp(op->opaque->exec, op->opaque->args);

    /* Most cases should have been already handled by stat() */
    services_handle_exec_error(op, errno);

    _exit(op->rc);
}
예제 #20
0
void
tengine_stonith_callback(stonith_t * stonith, stonith_callback_data_t * data)
{
    char *uuid = NULL;
    int stonith_id = -1;
    int transition_id = -1;
    crm_action_t *action = NULL;
    int call_id = data->call_id;
    int rc = data->rc;
    char *userdata = data->userdata;

    CRM_CHECK(userdata != NULL, return);
    crm_notice("Stonith operation %d/%s: %s (%d)", call_id, (char *)userdata,
               pcmk_strerror(rc), rc);

    if (AM_I_DC == FALSE) {
        return;
    }

    /* crm_info("call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s", */
    /*       op->call_id, op->optype, op->node_name, op->op_result, */
    /*       (char *)op->node_list, op->private_data); */

    /* filter out old STONITH actions */
    CRM_CHECK(decode_transition_key(userdata, &uuid, &transition_id, &stonith_id, NULL),
              goto bail);

    if (transition_graph->complete || stonith_id < 0 || safe_str_neq(uuid, te_uuid)
        || transition_graph->id != transition_id) {
        crm_info("Ignoring STONITH action initiated outside of the current transition");
        goto bail;
    }

    action = get_action(stonith_id, FALSE);
    if (action == NULL) {
        crm_err("Stonith action not matched");
        goto bail;
    }

    stop_te_timer(action->timer);
    if (rc == pcmk_ok) {
        const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
        const char *uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);
        const char *op = crm_meta_value(action->params, "stonith_action"); 

        crm_info("Stonith operation %d for %s passed", call_id, target);
        if (action->confirmed == FALSE) {
            te_action_confirmed(action);
            if (safe_str_eq("on", op)) {
                const char *value = NULL;
                char *now = crm_itoa(time(NULL));

                update_attrd(target, CRM_ATTR_UNFENCED, now, NULL, FALSE);
                free(now);

                value = crm_meta_value(action->params, XML_OP_ATTR_DIGESTS_ALL);
                update_attrd(target, CRM_ATTR_DIGESTS_ALL, value, NULL, FALSE);

                value = crm_meta_value(action->params, XML_OP_ATTR_DIGESTS_SECURE);
                update_attrd(target, CRM_ATTR_DIGESTS_SECURE, value, NULL, FALSE);

            } else if (action->sent_update == FALSE) {
                send_stonith_update(action, target, uuid);
                action->sent_update = TRUE;
            }
        }
        st_fail_count_reset(target);

    } else {
        const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
        enum transition_action abort_action = tg_restart;

        action->failed = TRUE;
        crm_notice("Stonith operation %d for %s failed (%s): aborting transition.",
                   call_id, target, pcmk_strerror(rc));

        /* If no fence devices were available, there's no use in immediately
         * checking again, so don't start a new transition in that case.
         */
        if (rc == -ENODEV) {
            crm_warn("No devices found in cluster to fence %s, giving up",
                     target);
            abort_action = tg_stop;
        }

        /* Increment the fail count now, so abort_for_stonith_failure() can
         * check it. Non-DC nodes will increment it in tengine_stonith_notify().
         */
        st_fail_count_increment(target);
        abort_for_stonith_failure(abort_action, target, NULL);
    }

    update_graph(transition_graph, action);
    trigger_graph();

  bail:
    free(userdata);
    free(uuid);
    return;
}
예제 #21
0
/* Returns FALSE if 'op' should be free'd by the caller */
gboolean
services_os_action_execute(svc_action_t * op, gboolean synchronous)
{
    int stdout_fd[2];
    int stderr_fd[2];
    sigset_t mask;
    sigset_t old_mask;
    struct stat st;

    if (pipe(stdout_fd) < 0) {
        crm_err("pipe() failed");
    }

    if (pipe(stderr_fd) < 0) {
        crm_err("pipe() failed");
    }

    /* Fail fast */
    if(stat(op->opaque->exec, &st) != 0) {
        int rc = errno;
        crm_warn("Cannot execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
        services_handle_exec_error(op, rc);
        if (!synchronous) {
            return operation_finalize(op);
        }
        return FALSE;
    }

    if (synchronous) {
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        sigemptyset(&old_mask);

        if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
            crm_perror(LOG_ERR, "sigprocmask() failed");
        }
    }

    op->pid = fork();
    switch (op->pid) {
        case -1:
            {
                int rc = errno;

                close(stdout_fd[0]);
                close(stdout_fd[1]);
                close(stderr_fd[0]);
                close(stderr_fd[1]);

                crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
                services_handle_exec_error(op, rc);
                if (!synchronous) {
                    return operation_finalize(op);
                }
                return FALSE;
            }
        case 0:                /* Child */
            close(stdout_fd[0]);
            close(stderr_fd[0]);
            if (STDOUT_FILENO != stdout_fd[1]) {
                if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
                    crm_err("dup2() failed (stdout)");
                }
                close(stdout_fd[1]);
            }
            if (STDERR_FILENO != stderr_fd[1]) {
                if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
                    crm_err("dup2() failed (stderr)");
                }
                close(stderr_fd[1]);
            }

            action_launch_child(op);
    }

    /* Only the parent reaches here */
    close(stdout_fd[1]);
    close(stderr_fd[1]);

    op->opaque->stdout_fd = stdout_fd[0];
    set_fd_opts(op->opaque->stdout_fd, O_NONBLOCK);

    op->opaque->stderr_fd = stderr_fd[0];
    set_fd_opts(op->opaque->stderr_fd, O_NONBLOCK);

    if (synchronous) {
        action_synced_wait(op, mask);

        if (sigismember(&old_mask, SIGCHLD) == 0) {
            if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) {
                crm_perror(LOG_ERR, "sigprocmask() to unblocked failed");
            }
        }

    } else {

        crm_trace("Async waiting for %d - %s", op->pid, op->opaque->exec);
        mainloop_child_add_with_flags(op->pid,
                                      op->timeout,
                                      op->id,
                                      op,
                                      (op->flags & SVC_ACTION_LEAVE_GROUP) ? mainloop_leave_pid_group : 0,
                                      operation_finished);


        op->opaque->stdout_gsource = mainloop_add_fd(op->id,
                                                     G_PRIORITY_LOW,
                                                     op->opaque->stdout_fd, op, &stdout_callbacks);

        op->opaque->stderr_gsource = mainloop_add_fd(op->id,
                                                     G_PRIORITY_LOW,
                                                     op->opaque->stderr_fd, op, &stderr_callbacks);
    }

    return TRUE;
}
예제 #22
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;
}
예제 #23
0
파일: tengine.c 프로젝트: jjzhang/pacemaker
/*	 A_TE_INVOKE, A_TE_CANCEL	*/
void
do_te_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)
{

    if (AM_I_DC == FALSE || (fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE))) {
        crm_notice("No need to invoke the TE (%s) in state %s",
                   fsa_action2string(action), fsa_state2string(fsa_state));
        return;
    }

    if (action & A_TE_CANCEL) {
        crm_debug("Cancelling the transition: %s",
                  transition_graph->complete ? "inactive" : "active");
        abort_transition(INFINITY, tg_restart, "Peer Cancelled", NULL);
        if (transition_graph->complete == FALSE) {
            crmd_fsa_stall(NULL);
        }

    } else if (action & A_TE_HALT) {
        crm_debug("Halting the transition: %s", transition_graph->complete ? "inactive" : "active");
        abort_transition(INFINITY, tg_stop, "Peer Halt", NULL);
        if (transition_graph->complete == FALSE) {
            crmd_fsa_stall(NULL);
        }

    } else if (action & A_TE_INVOKE) {
        const char *value = NULL;
        xmlNode *graph_data = NULL;
        ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg);
        const char *ref = crm_element_value(input->msg, XML_ATTR_REFERENCE);
        const char *graph_file = crm_element_value(input->msg, F_CRM_TGRAPH);
        const char *graph_input = crm_element_value(input->msg, F_CRM_TGRAPH_INPUT);

        if (graph_file == NULL && input->xml == NULL) {
            crm_log_xml_err(input->msg, "Bad command");
            register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
            return;
        }

        if (transition_graph->complete == FALSE) {
            crm_info("Another transition is already active");
            abort_transition(INFINITY, tg_restart, "Transition Active", NULL);
            return;
        }

        if (fsa_pe_ref == NULL || safe_str_neq(fsa_pe_ref, ref)) {
            crm_info("Transition is redundant: %s vs. %s", crm_str(fsa_pe_ref), crm_str(ref));
            abort_transition(INFINITY, tg_restart, "Transition Redundant", NULL);
        }

        graph_data = input->xml;

        if (graph_data == NULL && graph_file != NULL) {
            graph_data = filename2xml(graph_file);
        }

        if (is_timer_started(transition_timer)) {
            crm_debug("The transitioner wait for a transition timer");
            return;
        }

        CRM_CHECK(graph_data != NULL,
                  crm_err("Input raised by %s is invalid", msg_data->origin);
                  crm_log_xml_err(input->msg, "Bad command");
                  return);

        destroy_graph(transition_graph);
        transition_graph = unpack_graph(graph_data, graph_input);
        CRM_CHECK(transition_graph != NULL, transition_graph = create_blank_graph(); return);
        crm_info("Processing graph %d (ref=%s) derived from %s", transition_graph->id, ref,
                 graph_input);

        value = crm_element_value(graph_data, "failed-stop-offset");
        if (value) {
            free(failed_stop_offset);
            failed_stop_offset = strdup(value);
        }

        value = crm_element_value(graph_data, "failed-start-offset");
        if (value) {
            free(failed_start_offset);
            failed_start_offset = strdup(value);
        }

        trigger_graph();
        print_graph(LOG_DEBUG_2, transition_graph);

        if (graph_data != input->xml) {
            free_xml(graph_data);
        }
    }
}
예제 #24
0
void
te_update_diff(const char *event, HA_Message *msg)
{
	int rc = -1;
	const char *op = NULL;
	crm_data_t *diff = NULL;
	crm_data_t *aborted = NULL;
	const char *set_name = NULL;

	int diff_add_updates = 0;
	int diff_add_epoch  = 0;
	int diff_add_admin_epoch = 0;

	int diff_del_updates = 0;
	int diff_del_epoch  = 0;
	int diff_del_admin_epoch = 0;
	
	if(msg == NULL) {
		crm_err("NULL update");
		return;
	}		

	ha_msg_value_int(msg, F_CIB_RC, &rc);	
	op = cl_get_string(msg, F_CIB_OPERATION);

	if(rc < cib_ok) {
		crm_debug_2("Ignoring failed %s operation: %s",
			    op, cib_error2string(rc));
		return;
	} 	

	diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);

	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);
	
	crm_debug("Processing diff (%s): %d.%d.%d -> %d.%d.%d", op,
		  diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
		  diff_add_admin_epoch,diff_add_epoch,diff_add_updates);
	log_cib_diff(LOG_DEBUG_2, diff, op);

	set_name = "diff-added";
	if(diff != NULL) {
		crm_data_t *section = NULL;
		crm_data_t *change_set = find_xml_node(diff, set_name, FALSE);
		change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE);

		if(change_set != NULL) {
			crm_debug_2("Checking status changes");
			section=get_object_root(XML_CIB_TAG_STATUS,change_set);
		}
		
		if(section != NULL) {
			extract_event(section);
		}
		crm_debug_2("Checking change set: %s", set_name);
		aborted = need_abort(change_set);
	}
	
	set_name = "diff-removed";
	if(diff != NULL && aborted == NULL) {
		crm_data_t *attrs = NULL;
		crm_data_t *status = NULL;
		crm_data_t *change_set = find_xml_node(diff, set_name, FALSE);
		change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE);

		crm_debug_2("Checking change set: %s", set_name);
		aborted = need_abort(change_set);		

		if(aborted == NULL && change_set != NULL) {
			status = get_object_root(XML_CIB_TAG_STATUS, change_set);
		
			xml_child_iter_filter(
				status, node_state, XML_CIB_TAG_STATE,
				
				attrs = find_xml_node(
					node_state, XML_TAG_TRANSIENT_NODEATTRS, FALSE);
				
				if(attrs != NULL) {
					crm_info("Aborting on "XML_TAG_TRANSIENT_NODEATTRS" deletions");
					abort_transition(INFINITY, tg_restart,
							 XML_TAG_TRANSIENT_NODEATTRS, attrs);
				}
				);
예제 #25
0
파일: election.c 프로젝트: dubrsl/pacemaker
/*	A_ELECTION_VOTE	*/
void
do_election_vote(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)
{
    struct timeval age;
    xmlNode *vote = NULL;
    gboolean not_voting = FALSE;

    /* don't vote if we're in one of these states or wanting to shut down */
    switch (cur_state) {
        case S_STARTING:
        case S_RECOVERY:
        case S_STOPPING:
        case S_TERMINATE:
            crm_warn("Not voting in election, we're in state %s", fsa_state2string(cur_state));
            not_voting = TRUE;
            break;
        default:
            break;
    }

    if (not_voting == FALSE) {
        if (is_set(fsa_input_register, R_STARTING)) {
            not_voting = TRUE;
        }
    }

    if (not_voting) {
        if (AM_I_DC) {
            register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);

        } else {
            register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
        }
        return;
    }

    vote = create_request(CRM_OP_VOTE, NULL, NULL, CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);

    current_election_id++;
    crm_xml_add(vote, F_CRM_ELECTION_OWNER, fsa_our_uuid);
    crm_xml_add_int(vote, F_CRM_ELECTION_ID, current_election_id);

    crm_uptime(&age);
    crm_xml_add_int(vote, F_CRM_ELECTION_AGE_S, age.tv_sec);
    crm_xml_add_int(vote, F_CRM_ELECTION_AGE_US, age.tv_usec);

    send_cluster_message(NULL, crm_msg_crmd, vote, TRUE);
    free_xml(vote);

    crm_debug("Started election %d", current_election_id);
    if (voted) {
        g_hash_table_destroy(voted);
    }
    voted = NULL;

    if (cur_state == S_ELECTION || cur_state == S_RELEASE_DC) {
        crm_timer_start(election_timeout);

    } else if (cur_state != S_INTEGRATION) {
        crm_err("Broken? Voting in state %s", fsa_state2string(cur_state));
    }

    return;
}
예제 #26
0
파일: crmadmin.c 프로젝트: fghaas/pacemaker
int
main(int argc, char **argv)
{
    int option_index = 0;
    int argerr = 0;
    int flag;

    crm_log_init(NULL, LOG_ERR, FALSE, TRUE, argc, argv);
    crm_set_options(NULL, "command [options]", long_options,
                    "Development tool for performing some crmd-specific commands."
                    "\n  Likely to be replaced by crm_node in the future");
    if (argc < 2) {
        crm_help('?', LSB_EXIT_EINVAL);
    }

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

        switch (flag) {
            case 'V':
                BE_VERBOSE = TRUE;
                admin_verbose = XML_BOOLEAN_TRUE;
                crm_bump_log_level();
                break;
            case 't':
                message_timeout_ms = atoi(optarg);
                if (message_timeout_ms < 1) {
                    message_timeout_ms = 30 * 1000;
                }
                break;

            case '$':
            case '?':
                crm_help(flag, LSB_EXIT_OK);
                break;
            case 'D':
                DO_WHOIS_DC = TRUE;
                break;
            case 'B':
                BASH_EXPORT = TRUE;
                break;
            case 'K':
                DO_RESET = TRUE;
                crm_debug_2("Option %c => %s", flag, optarg);
                dest_node = crm_strdup(optarg);
                crmd_operation = CRM_OP_LOCAL_SHUTDOWN;
                break;
            case 'q':
                BE_SILENT = TRUE;
                break;
            case 'i':
                DO_DEBUG = debug_inc;
                crm_debug_2("Option %c => %s", flag, optarg);
                dest_node = crm_strdup(optarg);
                break;
            case 'd':
                DO_DEBUG = debug_dec;
                crm_debug_2("Option %c => %s", flag, optarg);
                dest_node = crm_strdup(optarg);
                break;
            case 'S':
                DO_HEALTH = TRUE;
                crm_debug_2("Option %c => %s", flag, optarg);
                dest_node = crm_strdup(optarg);
                break;
            case 'E':
                DO_ELECT_DC = TRUE;
                break;
            case 'N':
                DO_NODE_LIST = TRUE;
                break;
            case 'H':
                DO_HEALTH = TRUE;
                break;
            default:
                printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
                ++argerr;
                break;
        }
    }

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

    if (optind > argc) {
        ++argerr;
    }

    if (argerr) {
        crm_help('?', LSB_EXIT_GENERIC);
    }

    if (do_init()) {
        int res = 0;

        res = do_work();
        if (res > 0) {
            /* wait for the reply by creating a mainloop and running it until
             * the callbacks are invoked...
             */
            mainloop = g_main_new(FALSE);
            expected_responses++;
            crm_debug_2("Waiting for %d replies from the local CRM", expected_responses);

            message_timer_id = g_timeout_add(message_timeout_ms, admin_message_timeout, NULL);

            g_main_run(mainloop);

        } else if (res < 0) {
            crm_err("No message to send");
            operation_status = -1;
        }
    } else {
        crm_warn("Init failed, could not perform requested operations");
        operation_status = -2;
    }

    crm_debug_2("%s exiting normally", crm_system_name);
    return operation_status;
}
예제 #27
0
static void
stonith_peer_cs_destroy(gpointer user_data)
{
    crm_err("Corosync connection terminated");
    stonith_shutdown(0);
}
예제 #28
0
파일: crmadmin.c 프로젝트: fghaas/pacemaker
int
do_work(void)
{
    int ret = 1;

    /* construct the request */
    xmlNode *msg_data = NULL;
    gboolean all_is_good = TRUE;

    msg_options = create_xml_node(NULL, XML_TAG_OPTIONS);
    crm_xml_add(msg_options, XML_ATTR_VERBOSE, admin_verbose);
    crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");

    if (DO_HEALTH == TRUE) {
        crm_debug_2("Querying the system");

        sys_to = CRM_SYSTEM_DC;

        if (dest_node != NULL) {
            sys_to = CRM_SYSTEM_CRMD;
            crmd_operation = CRM_OP_PING;

            if (BE_VERBOSE) {
                expected_responses = 1;
            }

            crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");

        } else {
            crm_info("Cluster-wide health not available yet");
            all_is_good = FALSE;
        }

    } else if (DO_ELECT_DC) {
        /* tell the local node to initiate an election */

        sys_to = CRM_SYSTEM_CRMD;
        crmd_operation = CRM_OP_VOTE;

        crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");

        dest_node = NULL;

        ret = 0;                /* no return message */

    } else if (DO_WHOIS_DC) {
        sys_to = CRM_SYSTEM_DC;
        crmd_operation = CRM_OP_PING;

        crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");

        dest_node = NULL;

    } else if (DO_NODE_LIST) {

        cib_t *the_cib = cib_new();
        xmlNode *output = NULL;

        enum cib_errors rc = the_cib->cmds->signon(the_cib, crm_system_name, cib_command);

        if (rc != cib_ok) {
            return -1;
        }

        output = get_cib_copy(the_cib);
        do_find_node_list(output);

        free_xml(output);
        the_cib->cmds->signoff(the_cib);
        exit(rc);

    } else if (DO_RESET) {
        /* tell dest_node to initiate the shutdown proceedure
         *
         * if dest_node is NULL, the request will be sent to the
         *   local node
         */
        sys_to = CRM_SYSTEM_CRMD;
        crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");

        ret = 0;                /* no return message */

    } else if (DO_DEBUG == debug_inc) {
        /* tell dest_node to increase its debug level
         *
         * if dest_node is NULL, the request will be sent to the
         *   local node
         */
        sys_to = CRM_SYSTEM_CRMD;
        crmd_operation = CRM_OP_DEBUG_UP;

        ret = 0;                /* no return message */

    } else if (DO_DEBUG == debug_dec) {
        /* tell dest_node to increase its debug level
         *
         * if dest_node is NULL, the request will be sent to the
         *   local node
         */
        sys_to = CRM_SYSTEM_CRMD;
        crmd_operation = CRM_OP_DEBUG_DOWN;

        ret = 0;                /* no return message */

    } else {
        crm_err("Unknown options");
        all_is_good = FALSE;
    }

    if (all_is_good == FALSE) {
        crm_err("Creation of request failed.  No message to send");
        return -1;
    }

/* send it */
    if (crmd_channel == NULL) {
        crm_err("The IPC connection is not valid, cannot send anything");
        return -1;
    }

    if (sys_to == NULL) {
        if (dest_node != NULL) {
            sys_to = CRM_SYSTEM_CRMD;
        } else {
            sys_to = CRM_SYSTEM_DC;
        }
    }

    {
        xmlNode *cmd = create_request(crmd_operation, msg_data, dest_node, sys_to,
                                      crm_system_name, admin_uuid);

        send_ipc_message(crmd_channel, cmd);
        free_xml(cmd);
    }

    return ret;
}
예제 #29
0
svc_action_t *resources_action_create(
    const char *name, const char *standard, const char *provider, const char *agent,
    const char *action, int interval, int timeout, GHashTable *params)
{
    svc_action_t *op;

    /*
     * Do some up front sanity checks before we go off and
     * build the svc_action_t instance.
     */

    if (crm_strlen_zero(name)) {
        crm_err("A service or resource action must have a name.");
        return NULL;
    }

    if (crm_strlen_zero(standard)) {
        crm_err("A service action must have a valid standard.");
        return NULL;
    }

    if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) {
        crm_err("An OCF resource action must have a provider.");
        return NULL;
    }

    if (crm_strlen_zero(agent)) {
        crm_err("A service or resource action must have an agent.");
        return NULL;
    }

    if (crm_strlen_zero(action)) {
        crm_err("A service or resource action must specify an action.");
        return NULL;
    }

    if (safe_str_eq(action, "monitor") && (safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) {
        action = "status";
    }

    /*
     * Sanity checks passed, proceed!
     */

    op = calloc(1, sizeof(svc_action_t));
    op->opaque = calloc(1, sizeof(svc_action_private_t));
    op->rsc = strdup(name);
    op->action = strdup(action);
    op->interval = interval;
    op->timeout = timeout;
    op->standard = strdup(standard);
    op->agent = strdup(agent);
    op->sequence = ++operations;
    if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) {
        goto return_error;
    }

    if(strcasecmp(op->standard, "service") == 0) {
        /* Work it out and then fall into the if-else block below.
         * Priority is:
         * - lsb
         * - systemd
         * - upstart
         */
        int rc = 0;
        struct stat st;
        char *path = NULL;

#ifdef LSB_ROOT_DIR
        rc = asprintf(&path, "%s/%s", LSB_ROOT_DIR, op->agent);
        if(rc > 0 && stat(path, &st) == 0) {
            crm_debug("Found an lsb agent for %s/% the", op->rsc, op->agent);
            free(path);
            free(op->standard);
            op->standard = strdup("lsb");
            goto expanded;
        }
        free(path);
#endif

#if SUPPORT_SYSTEMD
        if(systemd_unit_exists(op->agent)) {
            crm_debug("Found a systemd agent for %s/%s", op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup("systemd");
            goto expanded;
        }
#endif

#if SUPPORT_UPSTART
        if(upstart_job_exists(op->agent)) {
            crm_debug("Found an upstart agent for %s/%s", op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup("upstart");
            goto expanded;
        }
#endif

        crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent);
    }

expanded:
    if(strcasecmp(op->standard, "ocf") == 0) {
        op->provider = strdup(provider);
        op->params = params;

        if (asprintf(&op->opaque->exec, "%s/resource.d/%s/%s",
                     OCF_ROOT_DIR, provider, agent) == -1) {
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(action);

    } else if(strcasecmp(op->standard, "lsb") == 0) {
        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
            * of tacking on the LSB_ROOT_DIR path to the front */
            op->opaque->exec = strdup(op->agent);
        } else if (asprintf(&op->opaque->exec, "%s/%s", LSB_ROOT_DIR, op->agent) == -1) {
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(op->action);
        op->opaque->args[2] = NULL;

#if SUPPORT_SYSTEMD
    } else if(strcasecmp(op->standard, "systemd") == 0) {
        op->opaque->exec = strdup("systemd-dbus");
#endif
#if SUPPORT_UPSTART
    } else if(strcasecmp(op->standard, "upstart") == 0) {
        op->opaque->exec = strdup("upstart-dbus");
#endif
    } else if(strcasecmp(op->standard, "service") == 0) {
        op->opaque->exec = strdup(SERVICE_SCRIPT);
        op->opaque->args[0] = strdup(SERVICE_SCRIPT);
        op->opaque->args[1] = strdup(agent);
        op->opaque->args[2] = strdup(action);

    } else {
        crm_err("Unknown resource standard: %s", op->standard);
        services_action_free(op);
        op = NULL;
    }

    return op;

return_error:
    services_action_free(op);

    return NULL;
}
예제 #30
0
gboolean
relay_message(xmlNode * msg, gboolean originated_locally)
{
    int dest = 1;
    int is_for_dc = 0;
    int is_for_dcib = 0;
    int is_for_te = 0;
    int is_for_crm = 0;
    int is_for_cib = 0;
    int is_local = 0;
    gboolean processing_complete = FALSE;
    const char *host_to = crm_element_value(msg, F_CRM_HOST_TO);
    const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO);
    const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM);
    const char *type = crm_element_value(msg, F_TYPE);
    const char *msg_error = NULL;

    crm_trace("Routing message %s", crm_element_value(msg, XML_ATTR_REFERENCE));

    if (msg == NULL) {
        msg_error = "Cannot route empty message";

    } else if (safe_str_eq(CRM_OP_HELLO, crm_element_value(msg, F_CRM_TASK))) {
        /* quietly ignore */
        processing_complete = TRUE;

    } else if (safe_str_neq(type, T_CRM)) {
        msg_error = "Bad message type";

    } else if (sys_to == NULL) {
        msg_error = "Bad message destination: no subsystem";
    }

    if (msg_error != NULL) {
        processing_complete = TRUE;
        crm_err("%s", msg_error);
        crm_log_xml_warn(msg, "bad msg");
    }

    if (processing_complete) {
        return TRUE;
    }

    processing_complete = TRUE;

    is_for_dc = (strcasecmp(CRM_SYSTEM_DC, sys_to) == 0);
    is_for_dcib = (strcasecmp(CRM_SYSTEM_DCIB, sys_to) == 0);
    is_for_te = (strcasecmp(CRM_SYSTEM_TENGINE, sys_to) == 0);
    is_for_cib = (strcasecmp(CRM_SYSTEM_CIB, sys_to) == 0);
    is_for_crm = (strcasecmp(CRM_SYSTEM_CRMD, sys_to) == 0);

    is_local = 0;
    if (host_to == NULL || strlen(host_to) == 0) {
        if (is_for_dc || is_for_te) {
            is_local = 0;

        } else if (is_for_crm && originated_locally) {
            is_local = 0;

        } else {
            is_local = 1;
        }

    } else if (safe_str_eq(fsa_our_uname, host_to)) {
        is_local = 1;
    }

    if (is_for_dc || is_for_dcib || is_for_te) {
        if (AM_I_DC && is_for_te) {
            ROUTER_RESULT("Message result: Local relay");
            send_msg_via_ipc(msg, sys_to);

        } else if (AM_I_DC) {
            ROUTER_RESULT("Message result: DC/CRMd process");
            processing_complete = FALSE;        /* more to be done by caller */
        } else if (originated_locally && safe_str_neq(sys_from, CRM_SYSTEM_PENGINE)
                   && safe_str_neq(sys_from, CRM_SYSTEM_TENGINE)) {

            /* Neither the TE or PE should be sending messages
             *   to DC's on other nodes
             *
             * By definition, if we are no longer the DC, then
             *   the PE or TE's data should be discarded
             */

#if SUPPORT_COROSYNC
            if (is_openais_cluster()) {
                dest = text2msg_type(sys_to);
            }
#endif
            ROUTER_RESULT("Message result: External relay to DC");
            send_cluster_message(host_to, dest, msg, TRUE);

        } else {
            /* discard */
            ROUTER_RESULT("Message result: Discard, not DC");
        }

    } else if (is_local && (is_for_crm || is_for_cib)) {
        ROUTER_RESULT("Message result: CRMd process");
        processing_complete = FALSE;    /* more to be done by caller */

    } else if (is_local) {
        ROUTER_RESULT("Message result: Local relay");
        send_msg_via_ipc(msg, sys_to);

    } else {
#if SUPPORT_COROSYNC
        if (is_openais_cluster()) {
            dest = text2msg_type(sys_to);
        }
#endif
        ROUTER_RESULT("Message result: External relay");
        send_cluster_message(host_to, dest, msg, TRUE);
    }

    return processing_complete;
}