Beispiel #1
0
static attribute_t *
create_attribute(xmlNode *xml)
{
    int dampen = 0;
    const char *value = crm_element_value_copy(xml, F_ATTRD_DAMPEN);
    attribute_t *a = calloc(1, sizeof(attribute_t));

    a->id      = crm_element_value_copy(xml, F_ATTRD_ATTRIBUTE);
    a->set     = crm_element_value_copy(xml, F_ATTRD_SET);
    a->uuid    = crm_element_value_copy(xml, F_ATTRD_KEY);
    a->values = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_attribute_value);

#if ENABLE_ACL
    crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
    a->user = crm_element_value_copy(xml, F_ATTRD_USER);
#endif

    if(value) {
        dampen = crm_get_msec(value);
        crm_trace("Created attribute %s with delay %dms (%s)", a->id, dampen, value);
    } else {
        crm_trace("Created attribute %s with no delay", a->id);
    }

    if(dampen > 0) {
        a->timeout_ms = dampen;
        a->timer = mainloop_timer_add(strdup(a->id), a->timeout_ms, FALSE, attribute_timer_cb, a);
    }

    g_hash_table_replace(attributes, a->id, a);
    return a;
}
Beispiel #2
0
static async_command_t *create_async_command(xmlNode *msg) 
{
    async_command_t *cmd = NULL;
    xmlNode *op = get_xpath_object("//@"F_STONITH_ACTION, msg, LOG_ERR);
    const char *action = crm_element_value(op, F_STONITH_ACTION);

    CRM_CHECK(action != NULL, crm_log_xml_warn(msg, "NoAction"); return NULL);

    crm_log_xml_trace(msg, "Command");
    crm_malloc0(cmd, sizeof(async_command_t));
    crm_element_value_int(msg, F_STONITH_CALLID,   &(cmd->id));
    crm_element_value_int(msg, F_STONITH_CALLOPTS, &(cmd->options));
    crm_element_value_int(msg, F_STONITH_TIMEOUT,  &(cmd->timeout));

    cmd->timeout *= 1000;
    cmd->origin = crm_element_value_copy(msg, F_ORIG);
    cmd->remote = crm_element_value_copy(msg, F_STONITH_REMOTE);
    cmd->client = crm_element_value_copy(msg, F_STONITH_CLIENTID);
    cmd->op     = crm_element_value_copy(msg, F_STONITH_OPERATION);
    cmd->action = crm_strdup(action);
    cmd->victim = crm_element_value_copy(op, F_STONITH_TARGET);
    cmd->done   = st_child_done;

    CRM_CHECK(cmd->op != NULL, crm_log_xml_warn(msg, "NoOp"); free_async_command(cmd); return NULL);
    CRM_CHECK(cmd->client != NULL, crm_log_xml_warn(msg, "NoClient"));
    return cmd;
}
Beispiel #3
0
int
cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset)
{
    char *new_value = NULL;
    char *old_value = NULL;
    int int_value = -1;

    if (reset == FALSE && crm_element_value(xml_obj, field) != NULL) {
        old_value = crm_element_value_copy(xml_obj, field);
    }
    if (old_value != NULL) {
        new_value = calloc(1, 128);
        int_value = atoi(old_value);
        sprintf(new_value, "%d", ++int_value);
    } else {
        new_value = strdup("1");
    }

    crm_trace("%s %d(%s)->%s", field, int_value, crm_str(old_value), crm_str(new_value));
    crm_xml_add(xml_obj, field, new_value);

    free(new_value);
    free(old_value);

    return pcmk_ok;
}
Beispiel #4
0
enum cib_errors 
cib_update_counter(crm_data_t *xml_obj, const char *field, gboolean reset)
{
	char *new_value = NULL;
	char *old_value = NULL;
	int  int_value  = -1;
	
	if(reset == FALSE && crm_element_value(xml_obj, field) != NULL) {
		old_value = crm_element_value_copy(xml_obj, field);
	}
	if(old_value != NULL) {
		crm_malloc0(new_value, 128);
		int_value = atoi(old_value);
		sprintf(new_value, "%d", ++int_value);
	} else {
		new_value = crm_strdup("1");
	}

	crm_debug_4("%s %d(%s)->%s",
		  field, int_value, crm_str(old_value), crm_str(new_value));
	crm_xml_add(xml_obj, field, new_value);

	crm_free(new_value);
	crm_free(old_value);

	return cib_ok;
}
Beispiel #5
0
/*
 * Unpack everything
 * At the end you'll have:
 *  - A list of nodes
 *  - A list of resources (each with any dependencies on other resources)
 *  - A list of constraints between resources and nodes
 *  - A list of constraints between start/stop actions
 *  - A list of nodes that need to be stonith'd
 *  - A list of nodes that need to be shutdown
 *  - A list of the possible stop/start actions (without dependencies)
 */
gboolean
cluster_status(pe_working_set_t *data_set)
{
	xmlNode * config          = get_object_root(
		XML_CIB_TAG_CRMCONFIG,   data_set->input);
	xmlNode * cib_nodes       = get_object_root(
		XML_CIB_TAG_NODES,       data_set->input);
	xmlNode * cib_resources   = get_object_root(
		XML_CIB_TAG_RESOURCES,   data_set->input);
	xmlNode * cib_status      = get_object_root(
		XML_CIB_TAG_STATUS,      data_set->input);
 	const char *value = crm_element_value(
		data_set->input, XML_ATTR_HAVE_QUORUM);
	
	crm_debug_3("Beginning unpack");
	
	/* reset remaining global variables */
	
	if(data_set->input == NULL) {
		return FALSE;
	}

	if(data_set->now == NULL) {
	    data_set->now = new_ha_date(TRUE);
	}
	
	if(data_set->input != NULL
	   && crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) {
		/* this should always be present */
		data_set->dc_uuid = crm_element_value_copy(
			data_set->input, XML_ATTR_DC_UUID);
	}	
	
	clear_bit_inplace(data_set->flags, pe_flag_have_quorum);
	if(crm_is_true(value)) {
	    set_bit_inplace(data_set->flags, pe_flag_have_quorum);
	}

	data_set->op_defaults = get_object_root(XML_CIB_TAG_OPCONFIG, data_set->input);
	data_set->rsc_defaults = get_object_root(XML_CIB_TAG_RSCCONFIG, data_set->input);

 	unpack_config(config, data_set);
	
	if(is_set(data_set->flags, pe_flag_have_quorum) == FALSE
	   && data_set->no_quorum_policy != no_quorum_ignore) {
		crm_warn("We do not have quorum"
			 " - fencing and resource management disabled");
	}
	
 	unpack_nodes(cib_nodes, data_set);
 	unpack_resources(cib_resources, data_set);
 	unpack_status(cib_status, data_set);
	
	return TRUE;
}
Beispiel #6
0
static gboolean
exec_stonith_action(crm_graph_t *graph, crm_action_t *action)
{
	char *target = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);

	qb_enter();

	qb_log(LOG_WARNING, "Skipping STONITH %s op (not fencing %s)\n",
	       crm_element_value(action->xml, "operation"), target);
	crm_free(target);

	action->confirmed = TRUE;
	update_graph(graph, action);
	graph_updated = TRUE;

	qb_leave();
	return TRUE;
}
Beispiel #7
0
/*!
 * \internal
 * \brief Convert xml fence-history to a hash-table like stonith_remote_op_list
 *
 * \param[in] history   Fence-history in xml
 *
 * \return Fence-history as hash-table
 */
static GHashTable *
stonith_xml_history_to_list(xmlNode *history)
{
    xmlNode *xml_op = NULL;
    GHashTable *rv = NULL;

    init_stonith_remote_op_hash_table(&rv);

    CRM_LOG_ASSERT(rv != NULL);

    for (xml_op = __xml_first_child(history); xml_op != NULL;
         xml_op = __xml_next(xml_op)) {
        remote_fencing_op_t *op = NULL;
        char *id = crm_element_value_copy(xml_op, F_STONITH_REMOTE_OP_ID);
        int completed, state;

        if (!id) {
            crm_warn("History to convert to hashtable has no id in entry");
            continue;
        }

        crm_trace("Attaching op %s to hashtable", id);

        op = calloc(1, sizeof(remote_fencing_op_t));

        op->id = id;
        op->target = crm_element_value_copy(xml_op, F_STONITH_TARGET);
        op->action = crm_element_value_copy(xml_op, F_STONITH_ACTION);
        op->originator = crm_element_value_copy(xml_op, F_STONITH_ORIGIN);
        op->delegate = crm_element_value_copy(xml_op, F_STONITH_DELEGATE);
        op->client_name = crm_element_value_copy(xml_op, F_STONITH_CLIENTNAME);
        crm_element_value_int(xml_op, F_STONITH_DATE, &completed);
        op->completed = (time_t) completed;
        crm_element_value_int(xml_op, F_STONITH_STATE, &state);
        op->state = (enum op_state) state;

        g_hash_table_replace(rv, id, op);
        CRM_LOG_ASSERT(g_hash_table_lookup(rv, id) != NULL);
    }

    return rv;
}
Beispiel #8
0
static void
do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    xmlNode *cmd = NULL;
    pid_t watchdog = pcmk_locate_sbd();

    if (rc != pcmk_ok) {
        crm_err("Could not retrieve the Cluster Information Base: %s "
                CRM_XS " rc=%d call=%d", pcmk_strerror(rc), rc, call_id);
        register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
        return;

    } else if (call_id != fsa_pe_query) {
        crm_trace("Skipping superseded CIB query: %d (current=%d)", call_id, fsa_pe_query);
        return;

    } else if (AM_I_DC == FALSE || is_set(fsa_input_register, R_PE_CONNECTED) == FALSE) {
        crm_debug("No need to invoke the scheduler anymore");
        return;

    } else if (fsa_state != S_POLICY_ENGINE) {
        crm_debug("Discarding scheduler request in state: %s",
                  fsa_state2string(fsa_state));
        return;

    /* this callback counts as 1 */
    } else if (num_cib_op_callbacks() > 1) {
        crm_debug("Re-asking for the CIB: %d other peer updates still pending",
                  (num_cib_op_callbacks() - 1));
        sleep(1);
        register_fsa_action(A_PE_INVOKE);
        return;

    } else if (fsa_state != S_POLICY_ENGINE) {
        crm_err("Invoking scheduler in state: %s", fsa_state2string(fsa_state));
        return;
    }

    CRM_LOG_ASSERT(output != NULL);

    // Refresh the remote node cache when the scheduler is invoked
    crm_remote_peer_cache_refresh(output);

    crm_xml_add(output, XML_ATTR_DC_UUID, fsa_our_uuid);
    crm_xml_add_int(output, XML_ATTR_HAVE_QUORUM, fsa_has_quorum);

    force_local_option(output, XML_ATTR_HAVE_WATCHDOG, watchdog?"true":"false");

    if (ever_had_quorum && crm_have_quorum == FALSE) {
        crm_xml_add_int(output, XML_ATTR_QUORUM_PANIC, 1);
    }

    cmd = create_request(CRM_OP_PECALC, output, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_DC, NULL);

    free(fsa_pe_ref);
    fsa_pe_ref = crm_element_value_copy(cmd, XML_ATTR_REFERENCE);

    rc = pe_subsystem_send(cmd);
    if (rc < 0) {
        crm_err("Could not contact the scheduler: %s " CRM_XS " rc=%d",
                pcmk_strerror(rc), rc);
        register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
    }
    crm_debug("Invoking the scheduler: query=%d, ref=%s, seq=%llu, quorate=%d",
              fsa_pe_query, fsa_pe_ref, crm_peer_seq, fsa_has_quorum);
    free_xml(cmd);
}
Beispiel #9
0
void
attrd_client_message(crm_client_t *client, xmlNode *xml)
{
    bool broadcast = FALSE;
    static int plus_plus_len = 5;
    const char *op = crm_element_value(xml, F_ATTRD_TASK);

    if(safe_str_eq(op, "peer-remove")) {
        const char *host = crm_element_value(xml, F_ATTRD_HOST);

        crm_info("Client %s is requesting all values for %s be removed", client->name, host);
        if(host) {
            broadcast = TRUE;
        }

    } else if(safe_str_eq(op, "update")) {
        attribute_t *a = NULL;
        attribute_value_t *v = NULL;
        char *key = crm_element_value_copy(xml, F_ATTRD_KEY);
        char *set = crm_element_value_copy(xml, F_ATTRD_SET);
        char *host = crm_element_value_copy(xml, F_ATTRD_HOST);
        const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
        const char *value = crm_element_value(xml, F_ATTRD_VALUE);

        a = g_hash_table_lookup(attributes, attr);

        if(host == NULL) {
            crm_trace("Inferring host");
            host = strdup(attrd_cluster->uname);
            crm_xml_add(xml, F_ATTRD_HOST, host);
            crm_xml_add_int(xml, F_ATTRD_HOST_ID, attrd_cluster->nodeid);
        }

        if (value) {
            int offset = 1;
            int int_value = 0;
            int value_len = strlen(value);

            if (value_len < (plus_plus_len + 2)
                || value[plus_plus_len] != '+'
                || (value[plus_plus_len + 1] != '+' && value[plus_plus_len + 1] != '=')) {
                goto send;
            }

            if(a) {
                v = g_hash_table_lookup(a->values, host);
            }
            if(v) {
                int_value = char2score(v->current);
            }

            if (value[plus_plus_len + 1] != '+') {
                const char *offset_s = value + (plus_plus_len + 2);

                offset = char2score(offset_s);
            }
            int_value += offset;

            if (int_value > INFINITY) {
                int_value = INFINITY;
            }

            crm_info("Expanded %s=%s to %d", attr, value, int_value);
            crm_xml_add_int(xml, F_ATTRD_VALUE, int_value);
        }

      send:

        if(peer_writer == NULL && election_state(writer) != election_in_progress) {
            crm_info("Starting an election to determine the writer");
            election_vote(writer);
        }

        crm_info("Broadcasting %s[%s] = %s%s", attr, host, value, election_state(writer) == election_won?" (writer)":"");
        broadcast = TRUE;

        free(key);
        free(set);
        free(host);
    }

    if(broadcast) {
        crm_xml_add_int(xml, F_ATTRD_WRITER, election_state(writer));
        send_cluster_message(NULL, crm_msg_attrd, xml, TRUE);
    }
}
Beispiel #10
0
gboolean
cib_remote_listen(int ssock, gpointer data)
{
    int lpc = 0;
    int csock = 0;
    unsigned laddr;
    time_t now = 0;
    time_t start = time(NULL);
    struct sockaddr_in addr;

#ifdef HAVE_GNUTLS_GNUTLS_H
    gnutls_session *session = NULL;
#endif
    cib_client_t *new_client = NULL;

    xmlNode *login = NULL;
    const char *user = NULL;
    const char *pass = NULL;
    const char *tmp = NULL;

    cl_uuid_t client_id;
    char uuid_str[UU_UNPARSE_SIZEOF];

#ifdef HAVE_DECL_NANOSLEEP
    const struct timespec sleepfast = { 0, 10000000 };  /* 10 millisec */
#endif

    /* accept the connection */
    laddr = sizeof(addr);
    csock = accept(ssock, (struct sockaddr *)&addr, &laddr);
    crm_debug("New %s connection from %s",
              ssock == remote_tls_fd ? "secure" : "clear-text", inet_ntoa(addr.sin_addr));

    if (csock == -1) {
        crm_err("accept socket failed");
        return TRUE;
    }

    if (ssock == remote_tls_fd) {
#ifdef HAVE_GNUTLS_GNUTLS_H
        /* create gnutls session for the server socket */
        session = create_tls_session(csock, GNUTLS_SERVER);
        if (session == NULL) {
            crm_err("TLS session creation failed");
            close(csock);
            return TRUE;
        }
#endif
    }

    do {
        crm_trace("Iter: %d", lpc++);
        if (ssock == remote_tls_fd) {
#ifdef HAVE_GNUTLS_GNUTLS_H
            login = cib_recv_remote_msg(session, TRUE);
#endif
        } else {
            login = cib_recv_remote_msg(GINT_TO_POINTER(csock), FALSE);
        }
        if (login != NULL) {
            break;
        }
#ifdef HAVE_DECL_NANOSLEEP
        nanosleep(&sleepfast, NULL);
#else
        sleep(1);
#endif
        now = time(NULL);

        /* Peers have 3s to connect */
    } while (login == NULL && (start - now) < 4);

    crm_log_xml_info(login, "Login: "******"cib_command")) {
        crm_err("Wrong tag: %s", tmp);
        goto bail;
    }

    tmp = crm_element_value(login, "op");
    if (safe_str_neq(tmp, "authenticate")) {
        crm_err("Wrong operation: %s", tmp);
        goto bail;
    }

    user = crm_element_value(login, "user");
    pass = crm_element_value(login, "password");

    /* Non-root daemons can only validate the password of the
     * user they're running as
     */
    if (check_group_membership(user, CRM_DAEMON_GROUP) == FALSE) {
        crm_err("User is not a member of the required group");
        goto bail;

    } else if (authenticate_user(user, pass) == FALSE) {
        crm_err("PAM auth failed");
        goto bail;
    }

    /* send ACK */
    crm_malloc0(new_client, sizeof(cib_client_t));
    num_clients++;
    new_client->channel_name = "remote";
    new_client->name = crm_element_value_copy(login, "name");

    cl_uuid_generate(&client_id);
    cl_uuid_unparse(&client_id, uuid_str);

    CRM_CHECK(new_client->id == NULL, crm_free(new_client->id));
    new_client->id = crm_strdup(uuid_str);

#if ENABLE_ACL
    new_client->user = crm_strdup(user);
#endif

    new_client->callback_id = NULL;
    if (ssock == remote_tls_fd) {
#ifdef HAVE_GNUTLS_GNUTLS_H
        new_client->encrypted = TRUE;
        new_client->channel = (void *)session;
#endif
    } else {
        new_client->channel = GINT_TO_POINTER(csock);
    }

    free_xml(login);
    login = create_xml_node(NULL, "cib_result");
    crm_xml_add(login, F_CIB_OPERATION, CRM_OP_REGISTER);
    crm_xml_add(login, F_CIB_CLIENTID, new_client->id);
    cib_send_remote_msg(new_client->channel, login, new_client->encrypted);
    free_xml(login);

    new_client->source =
        (void *)G_main_add_fd(G_PRIORITY_DEFAULT, csock, FALSE, cib_remote_msg, new_client,
                              cib_remote_connection_destroy);

    g_hash_table_insert(client_list, new_client->id, new_client);

    return TRUE;

  bail:
    if (ssock == remote_tls_fd) {
#ifdef HAVE_GNUTLS_GNUTLS_H
        gnutls_bye(*session, GNUTLS_SHUT_RDWR);
        gnutls_deinit(*session);
        gnutls_free(session);
#endif
    }
    close(csock);
    free_xml(login);
    return TRUE;
}
Beispiel #11
0
/*
 * Unpack everything
 * At the end you'll have:
 *  - A list of nodes
 *  - A list of resources (each with any dependencies on other resources)
 *  - A list of constraints between resources and nodes
 *  - A list of constraints between start/stop actions
 *  - A list of nodes that need to be stonith'd
 *  - A list of nodes that need to be shutdown
 *  - A list of the possible stop/start actions (without dependencies)
 */
gboolean
cluster_status(pe_working_set_t * data_set)
{
    xmlNode *config = get_xpath_object("//"XML_CIB_TAG_CRMCONFIG, data_set->input, LOG_TRACE);
    xmlNode *cib_nodes = get_xpath_object("//"XML_CIB_TAG_NODES, data_set->input, LOG_TRACE);
    xmlNode *cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
    xmlNode *cib_status = get_xpath_object("//"XML_CIB_TAG_STATUS, data_set->input, LOG_TRACE);
    xmlNode *cib_tags = get_xpath_object("//"XML_CIB_TAG_TAGS, data_set->input, LOG_TRACE);
    const char *value = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);

    crm_trace("Beginning unpack");
    pe_dataset = data_set;

    /* reset remaining global variables */
    data_set->failed = create_xml_node(NULL, "failed-ops");

    if (data_set->input == NULL) {
        return FALSE;
    }

    if (data_set->now == NULL) {
        data_set->now = crm_time_new(NULL);
    }

    if (data_set->dc_uuid == NULL
        && data_set->input != NULL
        && crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) {
        /* this should always be present */
        data_set->dc_uuid = crm_element_value_copy(data_set->input, XML_ATTR_DC_UUID);
    }

    clear_bit(data_set->flags, pe_flag_have_quorum);
    if (crm_is_true(value)) {
        set_bit(data_set->flags, pe_flag_have_quorum);
    }

    data_set->op_defaults = get_xpath_object("//"XML_CIB_TAG_OPCONFIG, data_set->input, LOG_TRACE);
    data_set->rsc_defaults = get_xpath_object("//"XML_CIB_TAG_RSCCONFIG, data_set->input, LOG_TRACE);

    unpack_config(config, data_set);

   if (is_not_set(data_set->flags, pe_flag_quick_location)
       && is_not_set(data_set->flags, pe_flag_have_quorum)
       && data_set->no_quorum_policy != no_quorum_ignore) {
        crm_warn("Fencing and resource management disabled due to lack of quorum");
    }

    unpack_nodes(cib_nodes, data_set);

    if(is_not_set(data_set->flags, pe_flag_quick_location)) {
        unpack_remote_nodes(cib_resources, data_set);
    }

    unpack_resources(cib_resources, data_set);
    unpack_tags(cib_tags, data_set);

    if(is_not_set(data_set->flags, pe_flag_quick_location)) {
        unpack_status(cib_status, data_set);
    }

    set_bit(data_set->flags, pe_flag_have_status);
    return TRUE;
}
Beispiel #12
0
/*!
 * \internal
 * \brief Respond to a client update request
 *
 * \param[in] xml         Root of request XML
 *
 * \return void
 */
void
attrd_client_update(xmlNode *xml)
{
    attribute_t *a = NULL;
    attribute_value_t *v = NULL;
    char *key = crm_element_value_copy(xml, F_ATTRD_KEY);
    char *set = crm_element_value_copy(xml, F_ATTRD_SET);
    char *host = crm_element_value_copy(xml, F_ATTRD_HOST);
    const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
    const char *value = crm_element_value(xml, F_ATTRD_VALUE);
    const char *regex = crm_element_value(xml, F_ATTRD_REGEX);

    /* If a regex was specified, broadcast a message for each match */
    if ((attr == NULL) && regex) {
        GHashTableIter aIter;
        regex_t *r_patt = calloc(1, sizeof(regex_t));

        crm_debug("Setting %s to %s", regex, value);
        if (regcomp(r_patt, regex, REG_EXTENDED)) {
            crm_err("Bad regex '%s' for update", regex);

        } else {
            g_hash_table_iter_init(&aIter, attributes);
            while (g_hash_table_iter_next(&aIter, (gpointer *) & attr, NULL)) {
                int status = regexec(r_patt, attr, 0, NULL, 0);

                if (status == 0) {
                    crm_trace("Matched %s with %s", attr, regex);
                    crm_xml_add(xml, F_ATTRD_ATTRIBUTE, attr);
                    send_attrd_message(NULL, xml);
                }
            }
        }

        free(key);
        free(set);
        free(host);
        regfree(r_patt);
        free(r_patt);
        return;

    } else if (attr == NULL) {
        crm_err("Update request did not specify attribute or regular expression");
        return;
    }

    if (host == NULL) {
        crm_trace("Inferring host");
        host = strdup(attrd_cluster->uname);
        crm_xml_add(xml, F_ATTRD_HOST, host);
        crm_xml_add_int(xml, F_ATTRD_HOST_ID, attrd_cluster->nodeid);
    }

    a = g_hash_table_lookup(attributes, attr);

    /* If value was specified using ++ or += notation, expand to real value */
    if (value) {
        int offset = 1;
        int int_value = 0;
        static const int plus_plus_len = 5;

        if ((strlen(value) >= (plus_plus_len + 2)) && (value[plus_plus_len] == '+')
            && ((value[plus_plus_len + 1] == '+') || (value[plus_plus_len + 1] == '='))) {

            if (a) {
                v = g_hash_table_lookup(a->values, host);
            }
            if (v) {
                int_value = char2score(v->current);
            }

            if (value[plus_plus_len + 1] != '+') {
                const char *offset_s = value + (plus_plus_len + 2);

                offset = char2score(offset_s);
            }
            int_value += offset;

            if (int_value > INFINITY) {
                int_value = INFINITY;
            }

            crm_info("Expanded %s=%s to %d", attr, value, int_value);
            crm_xml_add_int(xml, F_ATTRD_VALUE, int_value);

            /* Replacing the value frees the previous memory, so re-query it */
            value = crm_element_value(xml, F_ATTRD_VALUE);
        }
    }

    if ((peer_writer == NULL) && (election_state(writer) != election_in_progress)) {
        crm_info("Starting an election to determine the writer");
        election_vote(writer);
    }

    crm_debug("Broadcasting %s[%s] = %s%s", attr, host, value,
              ((election_state(writer) == election_won)? " (writer)" : ""));

    free(key);
    free(set);
    free(host);

    send_attrd_message(NULL, xml); /* ends up at attrd_peer_message() */
}
Beispiel #13
0
void
filter_action_parameters(xmlNode *param_set, const char *version) 
{
	char *key = NULL;
	char *timeout = NULL;
	char *interval = NULL;
#if CRM_DEPRECATED_SINCE_2_0_5
	const char *filter_205[] = {
		XML_ATTR_TE_TARGET_RC,
		XML_ATTR_LRM_PROBE,
		XML_RSC_ATTR_START,
		XML_RSC_ATTR_NOTIFY,
		XML_RSC_ATTR_UNIQUE,
		XML_RSC_ATTR_MANAGED,
		XML_RSC_ATTR_PRIORITY,
		XML_RSC_ATTR_MULTIPLE,
		XML_RSC_ATTR_STICKINESS,
		XML_RSC_ATTR_FAIL_STICKINESS,
		XML_RSC_ATTR_TARGET_ROLE,

/* ignore clone fields */
		XML_RSC_ATTR_INCARNATION, 
		XML_RSC_ATTR_INCARNATION_MAX, 
		XML_RSC_ATTR_INCARNATION_NODEMAX,
		XML_RSC_ATTR_MASTER_MAX,
		XML_RSC_ATTR_MASTER_NODEMAX,
		
/* old field names */
		"role",
		"crm_role",
		"te-target-rc",
		
/* ignore notify fields */
 		"notify_stop_resource",
 		"notify_stop_uname",
 		"notify_start_resource",
 		"notify_start_uname",
 		"notify_active_resource",
 		"notify_active_uname",
 		"notify_inactive_resource",
 		"notify_inactive_uname",
 		"notify_promote_resource",
 		"notify_promote_uname",
 		"notify_demote_resource",
 		"notify_demote_uname",
 		"notify_master_resource",
 		"notify_master_uname",
 		"notify_slave_resource",
 		"notify_slave_uname"		
	};
#endif
	
	const char *attr_filter[] = {
		XML_ATTR_ID,
		XML_ATTR_CRM_VERSION,
		XML_LRM_ATTR_OP_DIGEST,
	};

	gboolean do_delete = FALSE;
	int lpc = 0;
	static int meta_len = 0;
	if(meta_len == 0) {
		meta_len  = strlen(CRM_META);
	}	
	
	if(param_set == NULL) {
		return;
	}

#if CRM_DEPRECATED_SINCE_2_0_5
 	if(version == NULL || compare_version("1.0.5", version) > 0) {
		for(lpc = 0; lpc < DIMOF(filter_205); lpc++) {
			xml_remove_prop(param_set, filter_205[lpc]); 
		}
	}
#endif

	for(lpc = 0; lpc < DIMOF(attr_filter); lpc++) {
		xml_remove_prop(param_set, attr_filter[lpc]); 
	}

	key = crm_meta_name(XML_LRM_ATTR_INTERVAL);
	interval = crm_element_value_copy(param_set, key);
	crm_free(key);

	key = crm_meta_name(XML_ATTR_TIMEOUT);
	timeout = crm_element_value_copy(param_set, key);
	
	xml_prop_iter(param_set, prop_name, prop_value,      
		      do_delete = FALSE;
		      if(strncasecmp(prop_name, CRM_META, meta_len) == 0) {
			      do_delete = TRUE;
		      }

		      if(do_delete) {
			      xml_remove_prop(param_set, prop_name);
		      }
		);
Beispiel #14
0
/*!
 * \internal
 * \brief Finalize a remote operation.
 *
 * \description This function has two code paths.
 *
 * Path 1. This node is the owner of the operation and needs
 *         to notify the cpg group via a broadcast as to the operation's
 *         results.
 *
 * Path 2. The cpg broadcast is received. All nodes notify their local
 *         stonith clients the operation results.
 *
 * So, The owner of the operation first notifies the cluster of the result,
 * and once that cpg notify is received back it notifies all the local clients.
 *
 * Nodes that are passive watchers of the operation will receive the
 * broadcast and only need to notify their local clients the operation finished.
 *
 * \param op, The fencing operation to finalize
 * \param data, The xml msg reply (if present) of the last delegated fencing
 *              operation.
 * \param dup, Is this operation a duplicate, if so treat it a little differently
 *             making sure the broadcast is not sent out.
 */
static void
remote_op_done(remote_fencing_op_t * op, xmlNode * data, int rc, int dup)
{
    int level = LOG_ERR;
    const char *subt = NULL;
    xmlNode *local_data = NULL;

    op->completed = time(NULL);
    clear_remote_op_timers(op);

    if (op->notify_sent == TRUE) {
        crm_err("Already sent notifications for '%s of %s by %s' (for=%s@%s.%.8s, state=%d): %s",
                op->action, op->target, op->delegate ? op->delegate : "<no-one>",
                op->client_name, op->originator, op->id, op->state, pcmk_strerror(rc));
        goto remote_op_done_cleanup;
    }

    if (!op->delegate && data) {
        op->delegate = crm_element_value_copy(data, F_ORIG);
    }

    if (data == NULL) {
        data = create_xml_node(NULL, "remote-op");
        local_data = data;
    }

    /* Tell everyone the operation is done, we will continue
     * with doing the local notifications once we receive
     * the broadcast back. */
    subt = crm_element_value(data, F_SUBTYPE);
    if (dup == FALSE && safe_str_neq(subt, "broadcast")) {
        /* Defer notification until the bcast message arrives */
        bcast_result_to_peers(op, rc);
        goto remote_op_done_cleanup;
    }

    if (rc == pcmk_ok || dup) {
        level = LOG_NOTICE;
    } else if (safe_str_neq(op->originator, stonith_our_uname)) {
        level = LOG_NOTICE;
    }

    do_crm_log(level,
               "Operation %s of %s by %s for %s@%s.%.8s: %s",
               op->action, op->target, op->delegate ? op->delegate : "<no-one>",
               op->client_name, op->originator, op->id, pcmk_strerror(rc));

    handle_local_reply_and_notify(op, data, rc);

    if (dup == FALSE) {
        handle_duplicates(op, data, rc);
    }

    /* Free non-essential parts of the record
     * Keep the record around so we can query the history
     */
    if (op->query_results) {
        g_list_free_full(op->query_results, free_remote_query);
        op->query_results = NULL;
    }

    if (op->request) {
        free_xml(op->request);
        op->request = NULL;
    }

  remote_op_done_cleanup:
    free_xml(local_data);
}
Beispiel #15
0
/*!
 * \internal
 * \brief Create a new remote stonith op
 * \param client, he local stonith client id that initaited the operation
 * \param request, The request from the client that started the operation
 * \param peer, Is this operation owned by another stonith peer? Operations
 *        owned by other peers are stored on all the stonith nodes, but only the
 *        owner executes the operation.  All the nodes get the results to the operation
 *        once the owner finishes executing it.
 */
void *
create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer)
{
    remote_fencing_op_t *op = NULL;
    xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, request, LOG_TRACE);
    int call_options = 0;

    if (remote_op_list == NULL) {
        remote_op_list = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_remote_op);
    }

    /* If this operation is owned by another node, check to make
     * sure we haven't already created this operation. */
    if (peer && dev) {
        const char *op_id = crm_element_value(dev, F_STONITH_REMOTE_OP_ID);

        CRM_CHECK(op_id != NULL, return NULL);

        op = g_hash_table_lookup(remote_op_list, op_id);
        if (op) {
            crm_debug("%s already exists", op_id);
            return op;
        }
    }

    op = calloc(1, sizeof(remote_fencing_op_t));

    crm_element_value_int(request, F_STONITH_TIMEOUT, (int *)&(op->base_timeout));

    if (peer && dev) {
        op->id = crm_element_value_copy(dev, F_STONITH_REMOTE_OP_ID);
    } else {
        op->id = crm_generate_uuid();
    }

    g_hash_table_replace(remote_op_list, op->id, op);
    CRM_LOG_ASSERT(g_hash_table_lookup(remote_op_list, op->id) != NULL);
    crm_trace("Created %s", op->id);

    op->state = st_query;
    op->replies_expected = fencing_active_peers();
    op->action = crm_element_value_copy(dev, F_STONITH_ACTION);
    op->originator = crm_element_value_copy(dev, F_STONITH_ORIGIN);
    op->delegate = crm_element_value_copy(dev, F_STONITH_DELEGATE); /* May not be set */
    op->created = time(NULL);

    if (op->originator == NULL) {
        /* Local or relayed request */
        op->originator = strdup(stonith_our_uname);
    }

    CRM_LOG_ASSERT(client != NULL);
    if (client) {
        op->client_id = strdup(client);
    }

    op->client_name = crm_element_value_copy(request, F_STONITH_CLIENTNAME);

    op->target = crm_element_value_copy(dev, F_STONITH_TARGET);
    op->request = copy_xml(request);    /* TODO: Figure out how to avoid this */
    crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options);
    op->call_options = call_options;
    
    crm_element_value_int(request, F_STONITH_CALLID, (int *)&(op->client_callid));

    crm_trace("%s new stonith op: %s - %s of %s for %s",
              (peer
               && dev) ? "Recorded" : "Generated", op->id, op->action, op->target, op->client_name);

    if (op->call_options & st_opt_cs_nodeid) {
        int nodeid = crm_atoi(op->target, NULL);
        crm_node_t *node = crm_get_peer(nodeid, NULL);

        /* Ensure the conversion only happens once */
        op->call_options &= ~st_opt_cs_nodeid;

        if (node && node->uname) {
            free(op->target);
            op->target = strdup(node->uname);
        } else {
            crm_warn("Could not expand nodeid '%s' into a host name (%p)", op->target, node);
        }
    }

    /* check to see if this is a duplicate operation of another in-flight operation */
    merge_duplicates(op);

    return op;
}
Beispiel #16
0
void
attrd_client_message(crm_client_t *client, xmlNode *xml)
{
    bool broadcast = FALSE;
    static int plus_plus_len = 5;
    const char *op = crm_element_value(xml, F_ATTRD_TASK);

    if(safe_str_eq(op, "peer-remove")) {
        const char *host = crm_element_value(xml, F_ATTRD_HOST);

        crm_info("Client %s is requesting all values for %s be removed", client->name, host);
        if(host) {
            broadcast = TRUE;
        }

    } else if(safe_str_eq(op, "update")) {
        attribute_t *a = NULL;
        attribute_value_t *v = NULL;
        char *key = crm_element_value_copy(xml, F_ATTRD_KEY);
        char *set = crm_element_value_copy(xml, F_ATTRD_SET);
        char *host = crm_element_value_copy(xml, F_ATTRD_HOST);
        const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
        const char *value = crm_element_value(xml, F_ATTRD_VALUE);
        const char *regex = crm_element_value(xml, F_ATTRD_REGEX);

        if(attr == NULL && regex) {
            GHashTableIter aIter;
            regex_t *r_patt = calloc(1, sizeof(regex_t));

            crm_debug("Setting %s to %s", regex, value);
            if (regcomp(r_patt, regex, REG_EXTENDED)) {
                crm_err("Bad regex '%s' for update", regex);

            } else {

                g_hash_table_iter_init(&aIter, attributes);
                while (g_hash_table_iter_next(&aIter, (gpointer *) & attr, NULL)) {
                    int status = regexec(r_patt, attr, 0, NULL, 0);

                    if(status == 0) {
                        crm_trace("Matched %s with %s", attr, regex);
                        crm_xml_add(xml, F_ATTRD_ATTRIBUTE, attr);
                        send_attrd_message(NULL, xml);
                    }
                }
            }

            free(key);
            free(set);
            free(host);

            regfree(r_patt);
            free(r_patt);
            return;

        } else if(host == NULL) {
            crm_trace("Inferring host");
            host = strdup(attrd_cluster->uname);
            crm_xml_add(xml, F_ATTRD_HOST, host);
            crm_xml_add_int(xml, F_ATTRD_HOST_ID, attrd_cluster->nodeid);
        }

        a = g_hash_table_lookup(attributes, attr);

        if (value) {
            int offset = 1;
            int int_value = 0;
            int value_len = strlen(value);

            if (value_len < (plus_plus_len + 2)
                || value[plus_plus_len] != '+'
                || (value[plus_plus_len + 1] != '+' && value[plus_plus_len + 1] != '=')) {
                goto send;
            }

            if(a) {
                v = g_hash_table_lookup(a->values, host);
            }
            if(v) {
                int_value = char2score(v->current);
            }

            if (value[plus_plus_len + 1] != '+') {
                const char *offset_s = value + (plus_plus_len + 2);

                offset = char2score(offset_s);
            }
            int_value += offset;

            if (int_value > INFINITY) {
                int_value = INFINITY;
            }

            crm_info("Expanded %s=%s to %d", attr, value, int_value);
            crm_xml_add_int(xml, F_ATTRD_VALUE, int_value);
        }

      send:

        if(peer_writer == NULL && election_state(writer) != election_in_progress) {
            crm_info("Starting an election to determine the writer");
            election_vote(writer);
        }

        crm_debug("Broadcasting %s[%s] = %s%s", attr, host, value, election_state(writer) == election_won?" (writer)":"");
        broadcast = TRUE;

        free(key);
        free(set);
        free(host);

    } else if(safe_str_eq(op, "refresh")) {
        crm_info("Updating all attributes");
        write_attributes(TRUE, FALSE);
    }

    if(broadcast) {
        /* Ends up at attrd_peer_message() */
        send_attrd_message(NULL, xml);
    }
}
Beispiel #17
0
/*!
 * \internal
 * \brief Respond to a client update request
 *
 * \param[in] xml         Root of request XML
 *
 * \return void
 */
void
attrd_client_update(xmlNode *xml)
{
    attribute_t *a = NULL;
    char *host = crm_element_value_copy(xml, F_ATTRD_HOST);
    const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
    const char *value = crm_element_value(xml, F_ATTRD_VALUE);
    const char *regex = crm_element_value(xml, F_ATTRD_REGEX);

    /* If a regex was specified, broadcast a message for each match */
    if ((attr == NULL) && regex) {
        GHashTableIter aIter;
        regex_t *r_patt = calloc(1, sizeof(regex_t));

        crm_debug("Setting %s to %s", regex, value);
        if (regcomp(r_patt, regex, REG_EXTENDED|REG_NOSUB)) {
            crm_err("Bad regex '%s' for update", regex);

        } else {
            g_hash_table_iter_init(&aIter, attributes);
            while (g_hash_table_iter_next(&aIter, (gpointer *) & attr, NULL)) {
                int status = regexec(r_patt, attr, 0, NULL, 0);

                if (status == 0) {
                    crm_trace("Matched %s with %s", attr, regex);
                    crm_xml_add(xml, F_ATTRD_ATTRIBUTE, attr);
                    send_attrd_message(NULL, xml);
                }
            }
        }

        free(host);
        regfree(r_patt);
        free(r_patt);
        return;

    } else if (attr == NULL) {
        crm_err("Update request did not specify attribute or regular expression");
        free(host);
        return;
    }

    if (host == NULL) {
        crm_trace("Inferring host");
        host = strdup(attrd_cluster->uname);
        crm_xml_add(xml, F_ATTRD_HOST, host);
        crm_xml_add_int(xml, F_ATTRD_HOST_ID, attrd_cluster->nodeid);
    }

    a = g_hash_table_lookup(attributes, attr);

    /* If value was specified using ++ or += notation, expand to real value */
    if (value) {
        if (attrd_value_needs_expansion(value)) {
            int int_value;
            attribute_value_t *v = NULL;

            if (a) {
                v = g_hash_table_lookup(a->values, host);
            }
            int_value = attrd_expand_value(value, (v? v->current : NULL));

            crm_info("Expanded %s=%s to %d", attr, value, int_value);
            crm_xml_add_int(xml, F_ATTRD_VALUE, int_value);

            /* Replacing the value frees the previous memory, so re-query it */
            value = crm_element_value(xml, F_ATTRD_VALUE);
        }
    }

    crm_debug("Broadcasting %s[%s]=%s%s", attr, host, value,
              (attrd_election_won()? " (writer)" : ""));

    free(host);

    send_attrd_message(NULL, xml); /* ends up at attrd_peer_message() */
}
Beispiel #18
0
static gboolean
exec_rsc_action(crm_graph_t *graph, crm_action_t *action)
{
	lrm_op_t *op = NULL;
	struct pe_operation *pe_op;
	const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC);
	xmlNode *action_rsc = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
	char *node = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);
	char *uuid;
	const char *tmp_provider;
	xmlNode *params_all;

	qb_enter();

	if (safe_str_eq(crm_element_value(action->xml, "operation"), "probe_complete")) {
		crm_free(node);
		action->confirmed = TRUE;
		update_graph(graph, action);
		graph_updated = TRUE;
		qb_leave();
		return TRUE;
	}

	if (action_rsc == NULL) {
		crm_log_xml_err(action->xml, "Bad");
		crm_free(node);
		qb_leave();
		return FALSE;
	}
	uuid = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET_UUID);

	pe_op = calloc(1, sizeof(struct pe_operation));
	pe_op->refcount = 1;
	pe_op->hostname = node;
	pe_op->node_uuid = uuid;
	pe_op->user_data = run_user_data;
	pe_op->rname = strdup(ID(action_rsc));
	pe_op->rclass = strdup(crm_element_value(action_rsc, XML_AGENT_ATTR_CLASS));
	tmp_provider = crm_element_value(action_rsc, XML_AGENT_ATTR_PROVIDER);
	if (tmp_provider) {
		pe_op->rprovider = strdup(tmp_provider);
	}
	pe_op->rtype = strdup(crm_element_value(action_rsc, XML_ATTR_TYPE));

	if (target_rc_s != NULL) {
		pe_op->target_outcome = crm_parse_int(target_rc_s, "0");
	}
	op = convert_graph_action(NULL, action, 0, pe_op->target_outcome);

	params_all = create_xml_node(NULL, XML_TAG_PARAMS);
	g_hash_table_foreach(op->params, hash2field, params_all);
/*
 * TODO at some point.
	g_hash_table_foreach(action->extra, hash2field, params_all);
	g_hash_table_foreach(rsc->parameters, hash2field, params_all);
	g_hash_table_foreach(action->meta, hash2metafield, params_all);
*/
	filter_action_parameters(params_all, PE_CRM_VERSION);
	pe_op->op_digest = calculate_operation_digest(params_all, PE_CRM_VERSION);

	pe_op->method = strdup(op->op_type);

	pe_op->params = qb_skiplist_create();
	if (op->params != NULL) {
		g_hash_table_foreach(op->params, dup_attr, pe_op->params);
	}

	pe_op->interval = op->interval;
	pe_op->timeout = op->timeout;
	if (pe_op->timeout == 0) {
		if (pe_op->interval == 0) {
			pe_op->timeout = PE_DEFAULT_TIMEOUT;
		} else {
			pe_op->timeout = pe_op->interval / 2;
		}
	}
	pe_op->action = action;
	pe_op->graph = graph;
	pe_op->action_id = action->id;
	pe_op->graph_id = graph->id;
	pe_op->time_execed = qb_util_stopwatch_create();

	free_lrm_op(op);
	free_xml(params_all);

	run_fn(pe_op);

	qb_leave();

	return TRUE;
}
Beispiel #19
0
static int
cib_remote_msg(gpointer data)
{
    xmlNode *command = NULL;
    crm_client_t *client = data;
    int disconnected = 0;
    int timeout = client->remote->authenticated ? -1 : 1000;

    crm_trace("%s callback", client->kind != CRM_CLIENT_TCP ? "secure" : "clear-text");

#ifdef HAVE_GNUTLS_GNUTLS_H
    if (client->kind == CRM_CLIENT_TLS && (client->remote->tls_handshake_complete == FALSE)) {
        int rc = pcmk__read_handshake_data(client);

        if (rc == 0) {
            /* No more data is available at the moment. Just return for now;
             * we'll get invoked again once the client sends more.
             */
            return 0;
        } else if (rc < 0) {
            crm_err("TLS handshake with remote CIB client failed: %s "
                    CRM_XS " rc=%d", gnutls_strerror(rc), rc);
            return -1;
        }

        crm_debug("TLS handshake with remote CIB client completed");
        client->remote->tls_handshake_complete = TRUE;
        if (client->remote->auth_timeout) {
            g_source_remove(client->remote->auth_timeout);
        }

        // Require the client to authenticate within this time
        client->remote->auth_timeout = g_timeout_add(REMOTE_AUTH_TIMEOUT,
                                                     remote_auth_timeout_cb,
                                                     client);
        return 0;
    }
#endif

    crm_remote_recv(client->remote, timeout, &disconnected);

    /* must pass auth before we will process anything else */
    if (client->remote->authenticated == FALSE) {
        xmlNode *reg;

#if ENABLE_ACL
        const char *user = NULL;
#endif
        command = crm_remote_parse_buffer(client->remote);
        if (cib_remote_auth(command) == FALSE) {
            free_xml(command);
            return -1;
        }

        crm_notice("Remote CIB client connection accepted");
        client->remote->authenticated = TRUE;
        g_source_remove(client->remote->auth_timeout);
        client->remote->auth_timeout = 0;
        client->name = crm_element_value_copy(command, "name");

#if ENABLE_ACL
        user = crm_element_value(command, "user");
        if (user) {
            client->user = strdup(user);
        }
#endif

        /* send ACK */
        reg = create_xml_node(NULL, "cib_result");
        crm_xml_add(reg, F_CIB_OPERATION, CRM_OP_REGISTER);
        crm_xml_add(reg, F_CIB_CLIENTID, client->id);
        crm_remote_send(client->remote, reg);
        free_xml(reg);
        free_xml(command);
    }

    command = crm_remote_parse_buffer(client->remote);
    while (command) {
        crm_trace("Remote client message received");
        cib_handle_remote_msg(client, command);
        free_xml(command);
        command = crm_remote_parse_buffer(client->remote);
    }

    if (disconnected) {
        crm_trace("Remote CIB client disconnected while reading from it");
        return -1;
    }

    return 0;
}
Beispiel #20
0
static void remote_op_done(remote_fencing_op_t *op, xmlNode *data, int rc) 
{
    xmlNode *reply = NULL;
    xmlNode *local_data = NULL;
    xmlNode *notify_data = NULL;

    op->completed = time(NULL);

    if(op->query_timer) {
        g_source_remove(op->query_timer);
        op->query_timer = 0;
    }
    if(op->op_timer) {
        g_source_remove(op->op_timer);
        op->op_timer = 0;
    }

    if(data == NULL) {
        data = create_xml_node(NULL, "remote-op");
        local_data = data;
    } else {
        op->delegate = crm_element_value_copy(data, F_ORIG);
    }

    crm_xml_add_int(data, "state", op->state);
    crm_xml_add(data, F_STONITH_TARGET,    op->target);
    crm_xml_add(data, F_STONITH_OPERATION, op->action); 

    if(op->request != NULL) {
        reply = stonith_construct_reply(op->request, NULL, data, rc);
        crm_xml_add(reply, F_STONITH_DELEGATE,  op->delegate);
        do_crm_log(rc==pcmk_ok?LOG_NOTICE:LOG_ERR,
               "Operation %s of %s by %s for %s[%s]: %s",
               op->action, op->target, op->delegate?op->delegate:"<no-one>",
               op->originator, op->client_id, pcmk_strerror(rc));

    } else {
        crm_err("Already sent notifications for '%s of %s by %s' (op=%s, for=%s, state=%d): %s",
                op->action, op->target, op->delegate, op->id, op->client_id, op->state,
                pcmk_strerror(rc));
        return;
    }

    if(reply) {
        do_local_reply(reply, op->client_id, op->call_options & st_opt_sync_call, FALSE);
    }

    /* Do notification with a clean data object */
    notify_data = create_xml_node(NULL, T_STONITH_NOTIFY_FENCE);
    crm_xml_add_int(notify_data, "state", op->state);
    crm_xml_add_int(notify_data, F_STONITH_RC,    rc);
    crm_xml_add(notify_data, F_STONITH_TARGET,    op->target);
    crm_xml_add(notify_data, F_STONITH_OPERATION, op->action); 
    crm_xml_add(notify_data, F_STONITH_DELEGATE,  op->delegate);
    crm_xml_add(notify_data, F_STONITH_REMOTE,    op->id);
    crm_xml_add(notify_data, F_STONITH_ORIGIN,    op->originator);
    crm_xml_add(notify_data, F_STONITH_CLIENTID,  op->client_id);
    crm_xml_add(notify_data, F_STONITH_CLIENTNAME,  op->client_name);

    do_stonith_notify(0, T_STONITH_NOTIFY_FENCE, rc, notify_data, NULL);

    free_xml(notify_data);
    free_xml(local_data);
    free_xml(reply);

    /* Free non-essential parts of the record
     * Keep the record around so we can query the history
     */
    if(op->query_results) {
        g_list_free_full(op->query_results, free_remote_query);
        op->query_results = NULL;
    }

    if(op->request) {
        free_xml(op->request);
        op->request = NULL;
    }
}
Beispiel #21
0
void *create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer)
{
    remote_fencing_op_t *op = NULL;
    xmlNode *dev = get_xpath_object("//@"F_STONITH_TARGET, request, LOG_TRACE);

    if(remote_op_list == NULL) {
        remote_op_list = g_hash_table_new_full(
        crm_str_hash, g_str_equal, NULL, free_remote_op);
    }

    if(peer && dev) {
        const char *peer_id = crm_element_value(dev, F_STONITH_REMOTE);
        CRM_CHECK(peer_id != NULL, return NULL);

        op = g_hash_table_lookup(remote_op_list, peer_id);
        if(op) {
            crm_debug("%s already exists", peer_id);
            return op;
        }
    }

    op = calloc(1, sizeof(remote_fencing_op_t));
    crm_element_value_int(request, F_STONITH_TIMEOUT, (int*)&(op->base_timeout));

    if(peer && dev) {
        op->id = crm_element_value_copy(dev, F_STONITH_REMOTE);
        crm_trace("Recorded new stonith op: %s", op->id);
    } else {
        op->id = crm_generate_uuid();
        crm_trace("Generated new stonith op: %s", op->id);
    }

    g_hash_table_replace(remote_op_list, op->id, op);
    CRM_LOG_ASSERT(g_hash_table_lookup(remote_op_list, op->id) != NULL);

    op->state = st_query;
    op->action = crm_element_value_copy(dev, F_STONITH_ACTION);
    op->originator = crm_element_value_copy(dev, F_STONITH_OWNER);

    if(op->originator == NULL) {
        /* Local request */
        op->originator = strdup(stonith_our_uname);
    }

    if(client) {
        op->client_id = strdup(client);
    }

    op->client_name = crm_element_value_copy(request, F_STONITH_CLIENTNAME);

    op->target = crm_element_value_copy(dev, F_STONITH_TARGET);
    op->request = copy_xml(request); /* TODO: Figure out how to avoid this */
    crm_element_value_int(request, F_STONITH_CALLOPTS, (int*)&(op->call_options));

    if(op->call_options & st_opt_cs_nodeid) {
        int nodeid = crm_atoi(op->target, NULL);
        crm_node_t *node = crm_get_peer(nodeid, NULL);

        /* Ensure the conversion only happens once */
        op->call_options &= ~st_opt_cs_nodeid;

        if(node) {
            free(op->target);
            op->target = strdup(node->uname);
        }
    }

    if(stonith_topology_next(op) != pcmk_ok) {
        op->state = st_failed;
    }
    return op;
}
Beispiel #22
0
int
cib_native_signon_raw(cib_t * cib, const char *name, enum cib_conn_type type, int *async_fd)
{
    int rc = pcmk_ok;
    const char *channel = NULL;
    cib_native_opaque_t *native = cib->variant_opaque;

    static struct ipc_client_callbacks cib_callbacks = {
        .dispatch = cib_native_dispatch_internal,
        .destroy = cib_native_destroy
    };

    cib->call_timeout = MAX_IPC_DELAY;

    if (type == cib_command) {
        cib->state = cib_connected_command;
        channel = cib_channel_rw;

    } else if (type == cib_command_nonblocking) {
        cib->state = cib_connected_command;
        channel = cib_channel_shm;

    } else if (type == cib_query) {
        cib->state = cib_connected_query;
        channel = cib_channel_ro;

    } else {
        return -ENOTCONN;
    }

    crm_trace("Connecting %s channel", channel);

    if (async_fd != NULL) {
        native->ipc = crm_ipc_new(channel, 0);

        if (native->ipc && crm_ipc_connect(native->ipc)) {
            *async_fd = crm_ipc_get_fd(native->ipc);

        } else if (native->ipc) {
            rc = -ENOTCONN;
        }

    } else {
        native->source =
            mainloop_add_ipc_client(channel, G_PRIORITY_HIGH, 512 * 1024 /* 512k */ , cib,
                                    &cib_callbacks);
        native->ipc = mainloop_get_ipc_client(native->source);
    }

    if (rc != pcmk_ok || native->ipc == NULL || crm_ipc_connected(native->ipc) == FALSE) {
        crm_debug("Connection unsuccessful (%d %p)", rc, native->ipc);
        rc = -ENOTCONN;
    }

    if (rc == pcmk_ok) {
        xmlNode *reply = NULL;
        xmlNode *hello = create_xml_node(NULL, "cib_command");

        crm_xml_add(hello, F_TYPE, T_CIB);
        crm_xml_add(hello, F_CIB_OPERATION, CRM_OP_REGISTER);
        crm_xml_add(hello, F_CIB_CLIENTNAME, name);
        crm_xml_add_int(hello, F_CIB_CALLOPTS, cib_sync_call);

        if (crm_ipc_send(native->ipc, hello, crm_ipc_client_response, -1, &reply) > 0) {
            const char *msg_type = crm_element_value(reply, F_CIB_OPERATION);

            rc = pcmk_ok;
            crm_log_xml_trace(reply, "reg-reply");

            if (safe_str_neq(msg_type, CRM_OP_REGISTER)) {
                crm_err("Invalid registration message: %s", msg_type);
                rc = -EPROTO;

            } else {
                native->token = crm_element_value_copy(reply, F_CIB_CLIENTID);
                if (native->token == NULL) {
                    rc = -EPROTO;
                }
            }
            free_xml(reply);

        } else {
            rc = -ECOMM;
        }

        free_xml(hello);
    }

    if (rc == pcmk_ok) {
        crm_debug("Connection to CIB successful");
        return pcmk_ok;
    }

    crm_debug("Connection to CIB failed: %s", pcmk_strerror(rc));
    cib_native_signoff(cib);
    return rc;
}