Exemplo n.º 1
0
void destroy_crm_node(gpointer data)
{
    crm_node_t *node = data;
    crm_debug_2("Destroying entry for node %u", node->id);

    crm_free(node->addr);
    crm_free(node->uname);
    crm_free(node->state);
    crm_free(node->uuid);
    crm_free(node);
}
Exemplo n.º 2
0
void
cib_remote_connection_destroy(gpointer user_data)
{
    cib_client_t *client = user_data;

    if(client == NULL) {
	return;
    }

    crm_debug_2("Cleaning up after client disconnect: %s/%s/%s",
	      crm_str(client->name), client->channel_name, client->id);
	    
    if(client->id != NULL) {
	if(!g_hash_table_remove(client_list, client->id)) {
	    crm_err("Client %s not found in the hashtable", client->name);
	}
    }

    if(client->source != NULL) {
	/* Should this even be necessary? */
	crm_debug_2("Deleting %s (%p) from mainloop", client->name, client->source);
	G_main_del_fd((GFDSource *)client->source); 
	client->source = NULL;
    }
    
    crm_debug_2("Destroying %s (%p)", client->name, user_data);
    num_clients--;
    crm_debug_2("Num unfree'd clients: %d", num_clients);
    crm_free(client->name);
    crm_free(client->callback_id);
    crm_free(client->id);
    crm_free(client);
    crm_debug_2("Freed the cib client");

    if(cib_shutdown_flag && g_hash_table_size(client_list) == 0) {
	crm_info("All clients disconnected...");
	initiate_exit();
    }
    
    return;
}
Exemplo n.º 3
0
enum cib_errors 
cib_process_quit(
	const char *op, int options, const char *section, crm_data_t *input,
	crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer)
{
	enum cib_errors result = cib_ok;
	crm_debug_2("Processing \"%s\" event", op);

	crm_warn("The CRMd has asked us to exit... complying");
	exit(0);
	return result;
}
Exemplo n.º 4
0
gboolean
te_graph_trigger(gpointer user_data)
{
    enum transition_status graph_rc = -1;

    if (transition_graph == NULL) {
        crm_debug("Nothing to do");
        return TRUE;
    }

    crm_debug_2("Invoking graph %d in state %s", transition_graph->id, fsa_state2string(fsa_state));

    switch (fsa_state) {
    case S_STARTING:
    case S_PENDING:
    case S_NOT_DC:
    case S_HALT:
    case S_ILLEGAL:
    case S_STOPPING:
    case S_TERMINATE:
        return TRUE;
        break;
    default:
        break;
    }

    if (transition_graph->complete == FALSE) {
        graph_rc = run_graph(transition_graph);
        print_graph(LOG_DEBUG_3, transition_graph);

        if (graph_rc == transition_active) {
            crm_debug_3("Transition not yet complete");
            return TRUE;

        } else if (graph_rc == transition_pending) {
            crm_debug_3("Transition not yet complete - no actions fired");
            return TRUE;
        }

        if (graph_rc != transition_complete) {
            crm_err("Transition failed: %s", transition_status(graph_rc));
            print_graph(LOG_WARNING, transition_graph);
        }
    }

    crm_info("Transition %d is now complete", transition_graph->id);
    transition_graph->complete = TRUE;
    notify_crmd(transition_graph);

    return TRUE;
}
Exemplo n.º 5
0
enum cib_errors
cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    xmlNode *obj_root = NULL;

    crm_debug_2("Processing \"%s\" event", op);

    if (options & cib_xpath) {
        return cib_process_xpath(op, options, section, req, input,
                                 existing_cib, result_cib, answer);
    }

    if (input == NULL) {
        crm_err("Cannot perform modification with no data");
        return cib_NOOBJECT;
    }

    obj_root = get_object_root(section, *result_cib);

    crm_validate_data(input);
    crm_validate_data(*result_cib);

    if (obj_root == NULL) {
        xmlNode *tmp_section = NULL;
        const char *path = get_object_parent(section);

        if (path == NULL) {
            return cib_bad_section;
        }

        tmp_section = create_xml_node(NULL, section);
        cib_process_xpath(CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer);
        free_xml(tmp_section);

        obj_root = get_object_root(section, *result_cib);
    }

    CRM_CHECK(obj_root != NULL, return cib_unknown);

    if (update_xml_child(obj_root, input) == FALSE) {
        if (options & cib_can_create) {
            add_node_copy(obj_root, input);
        } else {
            return cib_NOTEXISTS;
        }
    }

    return cib_ok;
}
Exemplo n.º 6
0
enum cib_errors
cib_process_bump(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    enum cib_errors result = cib_ok;

    crm_debug_2("Processing \"%s\" event for epoch=%s",
                op, crm_str(crm_element_value(existing_cib, XML_ATTR_GENERATION)));

    *answer = NULL;
    cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);

    return result;
}
Exemplo n.º 7
0
static void
check_actions_for(crm_data_t *rsc_entry, node_t *node, pe_working_set_t *data_set)
{
	const char *id = NULL;
	const char *task = NULL;
	int interval = 0;
	const char *interval_s = NULL;
	GListPtr op_list = NULL;
	GListPtr sorted_op_list = NULL;
	const char *rsc_id = ID(rsc_entry);
	gboolean is_probe = FALSE;
	int start_index = 0, stop_index = 0;
	resource_t *rsc = pe_find_resource(data_set->resources, rsc_id);

	CRM_CHECK(rsc != NULL, return);
	CRM_CHECK(node != NULL, return);
	CRM_CHECK(rsc_id != NULL, return);
	if(is_set(rsc->flags, pe_rsc_orphan)) {
		crm_debug_2("Skipping param check for %s: orphan", rsc->id);
		return;
		
	} else if(pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
		crm_debug_2("Skipping param check for %s: no longer active on %s",
			    rsc->id, node->details->uname);
		return;
	}
	
	crm_debug_3("Processing %s on %s", rsc->id, node->details->uname);
	
	if(check_rsc_parameters(rsc, node, rsc_entry, data_set)) {
	    DeleteRsc(rsc, node, FALSE, data_set);
	}
	
	xml_child_iter_filter(
		rsc_entry, rsc_op, XML_LRM_TAG_RSC_OP,
		op_list = g_list_append(op_list, rsc_op);
		);
Exemplo n.º 8
0
enum cib_errors 
cib_process_delete(
	const char *op, int options, const char *section, crm_data_t *input,
	crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer)
{
	crm_data_t *obj_root = NULL;
	crm_debug_2("Processing \"%s\" event", op);

	if(input == NULL) {
		crm_err("Cannot perform modification with no data");
		return cib_NOOBJECT;
	}
	
	obj_root = get_object_root(section, *result_cib);
	
	crm_validate_data(input);
	crm_validate_data(*result_cib);

	if(replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) {
		crm_debug_2("No matching object to delete");
	}
	
	return cib_ok;
}
Exemplo n.º 9
0
gboolean
send_msg_via_ipc(xmlNode * msg, const char *sys)
{
    gboolean send_ok = TRUE;
    IPC_Channel *client_channel;

    client_channel = (IPC_Channel *) g_hash_table_lookup(ipc_clients, sys);

    if (crm_element_value(msg, F_CRM_HOST_FROM) == NULL) {
        crm_xml_add(msg, F_CRM_HOST_FROM, fsa_our_uname);
    }

    if (client_channel != NULL) {
        crm_debug_3("Sending message via channel %s.", sys);
        send_ok = send_ipc_message(client_channel, msg);

    } else if (sys != NULL && strcmp(sys, CRM_SYSTEM_TENGINE) == 0) {
        xmlNode *data = get_message_xml(msg, F_CRM_DATA);

        process_te_message(msg, data);

    } else if (sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) {
        fsa_data_t fsa_data;
        ha_msg_input_t fsa_input;

        fsa_input.msg = msg;
        fsa_input.xml = get_message_xml(msg, F_CRM_DATA);

        fsa_data.id = 0;
        fsa_data.actions = 0;
        fsa_data.data = &fsa_input;
        fsa_data.fsa_input = I_MESSAGE;
        fsa_data.fsa_cause = C_IPC_MESSAGE;
        fsa_data.origin = __FUNCTION__;
        fsa_data.data_type = fsa_dt_ha_msg;

#ifdef FSA_TRACE
        crm_debug_2("Invoking action A_LRM_INVOKE (%.16llx)", A_LRM_INVOKE);
#endif
        do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE, fsa_state, I_MESSAGE, &fsa_data);

    } else {
        crm_err("Unknown Sub-system (%s)... discarding message.", crm_str(sys));
        send_ok = FALSE;
    }

    return send_ok;
}
Exemplo n.º 10
0
enum cib_errors
cib_process_erase(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    enum cib_errors result = cib_ok;

    crm_debug_2("Processing \"%s\" event", op);
    *answer = NULL;
    free_xml(*result_cib);
    *result_cib = createEmptyCib();

    copy_in_properties(*result_cib, existing_cib);
    cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);

    return result;
}
Exemplo n.º 11
0
void
group_create_actions(resource_t * rsc, pe_working_set_t * data_set)
{
    action_t *op = NULL;
    const char *value = NULL;
    GListPtr gIter = rsc->children;

    crm_debug_2("Creating actions for %s", rsc->id);

    for (; gIter != NULL; gIter = gIter->next) {
        resource_t *child_rsc = (resource_t *) gIter->data;

        child_rsc->cmds->create_actions(child_rsc, data_set);
        group_update_pseudo_status(rsc, child_rsc);
    }

    op = start_action(rsc, NULL, TRUE /* !group_data->child_starting */ );
    set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable);

    op = custom_action(rsc, started_key(rsc),
                       RSC_STARTED, NULL, TRUE /* !group_data->child_starting */ , TRUE, data_set);
    set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable);

    op = stop_action(rsc, NULL, TRUE /* !group_data->child_stopping */ );
    set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable);

    op = custom_action(rsc, stopped_key(rsc),
                       RSC_STOPPED, NULL, TRUE /* !group_data->child_stopping */ , TRUE, data_set);
    set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable);

    value = g_hash_table_lookup(rsc->meta, "stateful");
    if (crm_is_true(value)) {
        op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set);
        set_bit_inplace(op->flags, pe_action_pseudo);
        set_bit_inplace(op->flags, pe_action_runnable);
        op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set);
        set_bit_inplace(op->flags, pe_action_pseudo);
        set_bit_inplace(op->flags, pe_action_runnable);

        op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set);
        set_bit_inplace(op->flags, pe_action_pseudo);
        set_bit_inplace(op->flags, pe_action_runnable);
        op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set);
        set_bit_inplace(op->flags, pe_action_pseudo);
        set_bit_inplace(op->flags, pe_action_runnable);
    }
}
Exemplo n.º 12
0
gboolean
te_connect_stonith(gpointer user_data)
{
    int lpc = 0;
    int rc = stonith_ok;

    if (stonith_api == NULL) {
        stonith_api = stonith_api_new();
    }

    if (stonith_api->state != stonith_disconnected) {
        crm_debug_2("Still connected");
        return TRUE;
    }

    for (lpc = 0; lpc < 30; lpc++) {
        crm_info("Attempting connection to fencing daemon...");

        sleep(1);
        rc = stonith_api->cmds->connect(stonith_api, crm_system_name, NULL);

        if (rc == stonith_ok) {
            break;
        }

        if (user_data != NULL) {
            crm_err("Sign-in failed: triggered a retry");
            mainloop_set_trigger(stonith_reconnect);
            return TRUE;
        }

        crm_err("Sign-in failed: pausing and trying again in 2s...");
        sleep(1);
    }

    CRM_CHECK(rc == stonith_ok, return TRUE);   /* If not, we failed 30 times... just get out */
    stonith_api->cmds->register_notification(stonith_api, T_STONITH_NOTIFY_DISCONNECT,
            tengine_stonith_connection_destroy);

    stonith_api->cmds->register_notification(stonith_api, STONITH_OP_FENCE, tengine_stonith_notify);

    crm_info("Connected");
    return TRUE;
}
Exemplo n.º 13
0
static gboolean
resource_ipc_callback(IPC_Channel * server, void *private_data)
{
    int lpc = 0;
    xmlNode *msg = NULL;
    gboolean stay_connected = TRUE;
	
    while(IPC_ISRCONN(server)) {
	if(server->ops->is_message_pending(server) == 0) {
	    break;
	}

	msg = xmlfromIPC(server, MAX_IPC_DELAY);
	if (msg == NULL) {
	    break;
	}

	lpc++;
	fprintf(stderr, ".");
	crm_log_xml(LOG_DEBUG_2, "[inbound]", msg);

	crmd_replies_needed--;
	if(crmd_replies_needed == 0) {
	    fprintf(stderr, "\n");
	    crm_debug("Got all the replies we expected");
	    exit(0);
	}

	free_xml(msg);
	msg = NULL;

	if(server->ch_status != IPC_CONNECT) {
	    break;
	}
    }
	
    crm_debug_2("Processed %d messages (%d)", lpc, server->ch_status);
    
    if (server->ch_status != IPC_CONNECT) {
	stay_connected = FALSE;
    }

    return stay_connected;
}
Exemplo n.º 14
0
node_t *
group_color(resource_t *rsc, pe_working_set_t *data_set)
{
	node_t *node = NULL;
	node_t *group_node = NULL;
	group_variant_data_t *group_data = NULL;
	get_group_variant_data(group_data, rsc);

	if(is_not_set(rsc->flags, pe_rsc_provisional)) {
		return rsc->allocated_to;
	}
	crm_debug_2("Processing %s", rsc->id);
	if(is_set(rsc->flags, pe_rsc_allocating)) {
		crm_debug("Dependency loop detected involving %s", rsc->id);
		return NULL;
	}
	
	if(group_data->first_child == NULL) {
	    /* nothign to allocate */
	    clear_bit(rsc->flags, pe_rsc_provisional);
	    return NULL;
	}
	
	set_bit(rsc->flags, pe_rsc_allocating);
	rsc->role = group_data->first_child->role;
	
	group_data->first_child->rsc_cons = g_list_concat(
		group_data->first_child->rsc_cons, rsc->rsc_cons);
	rsc->rsc_cons = NULL;

	group_data->first_child->rsc_cons_lhs = g_list_concat(
		group_data->first_child->rsc_cons_lhs, rsc->rsc_cons_lhs);
	rsc->rsc_cons_lhs = NULL;
	
	dump_node_scores(show_scores?0:scores_log_level, rsc, __PRETTY_FUNCTION__, rsc->allowed_nodes);
	
	slist_iter(
		child_rsc, resource_t, rsc->children, lpc,

		node = child_rsc->cmds->color(child_rsc, data_set);
		if(group_node == NULL) {
		    group_node = node;
		}
		);
Exemplo n.º 15
0
enum cib_errors 
cib_process_default(
	const char *op, int options, const char *section, crm_data_t *input,
	crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer)
{
	enum cib_errors result = cib_ok;
	crm_debug_2("Processing \"%s\" event", op);
	*answer = NULL;

	if(op == NULL) {
		result = cib_operation;
		crm_err("No operation specified");
		
	} else if(strcasecmp(CRM_OP_NOOP, op) == 0) {
		;

	} else {
		result = cib_NOTSUPPORTED;
		crm_err("Action [%s] is not supported by the CIB", op);
	}
	return result;
}
Exemplo n.º 16
0
enum cib_errors 
cib_process_erase(
	const char *op, int options, const char *section, crm_data_t *input,
	crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer)
{
	crm_data_t *local_diff = NULL;
	enum cib_errors result = cib_ok;

	crm_debug_2("Processing \"%s\" event", op);
	*answer = NULL;
	free_xml(*result_cib);
	*result_cib = createEmptyCib();

	copy_in_properties(*result_cib, existing_cib);	
	cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);
	
	local_diff = diff_cib_object(existing_cib, *result_cib, FALSE);
	cib_replace_notify(*result_cib, result, local_diff);
	free_xml(local_diff);
	
	return result;
}
Exemplo n.º 17
0
gboolean
stop_te_timer(crm_action_timer_t *timer)
{
	const char *timer_desc = "action timer";
	
	if(timer == NULL) {
		return FALSE;
	}
	if(timer->reason == timeout_abort) {
		timer_desc = "global timer";
	}
	
	if(timer->source_id != 0) {
		crm_debug_2("Stopping %s", timer_desc);
		Gmain_timeout_remove(timer->source_id);
		timer->source_id = 0;

	} else {
		return FALSE;
	}

	return TRUE;
}
Exemplo n.º 18
0
enum cib_errors
cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    xmlNode *obj_root = NULL;
    enum cib_errors result = cib_ok;

    crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section));

    if (options & cib_xpath) {
        return cib_process_xpath(op, options, section, req, input,
                                 existing_cib, result_cib, answer);
    }

    CRM_CHECK(*answer == NULL, free_xml(*answer));
    *answer = NULL;

    if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) {
        section = NULL;
    }

    obj_root = get_object_root(section, existing_cib);

    if (obj_root == NULL) {
        result = cib_NOTEXISTS;

    } else {
        *answer = obj_root;
    }

    if (result == cib_ok && *answer == NULL) {
        crm_err("Error creating query response");
        result = cib_output_data;
    }

    return result;
}
Exemplo n.º 19
0
static gboolean
start_global_timer(crm_action_timer_t *timer, int timeout)
{
	CRM_ASSERT(timer != NULL);
	CRM_CHECK(timer > 0, return FALSE);
	CRM_CHECK(timer->source_id == 0, return FALSE);

	if(timeout <= 0) {
		crm_err("Tried to start timer with period: %d", timeout);

	} else if(timer->source_id == 0) {
		crm_debug_2("Starting abort timer: %dms", timeout);
		timer->timeout = timeout;
		timer->source_id = Gmain_timeout_add(
			timeout, global_timer_callback, (void*)timer);
		CRM_ASSERT(timer->source_id != 0);
		return TRUE;

	} else {
		crm_err("Timer is already active with period: %d", timer->timeout);
	}
	
	return FALSE;		
}
Exemplo n.º 20
0
void
handle_response(xmlNode * stored_msg)
{
    const char *op = crm_element_value(stored_msg, F_CRM_TASK);

    if (op == NULL) {
        crm_log_xml(LOG_ERR, "Bad message", stored_msg);

    } else if (AM_I_DC && strcmp(op, CRM_OP_PECALC) == 0) {
        /* Check if the PE answer been superceeded by a subsequent request? */
        const char *msg_ref = crm_element_value(stored_msg, XML_ATTR_REFERENCE);

        if (msg_ref == NULL) {
            crm_err("%s - Ignoring calculation with no reference", op);

        } else if (safe_str_eq(msg_ref, fsa_pe_ref)) {
            ha_msg_input_t fsa_input;

            fsa_input.msg = stored_msg;
            register_fsa_input_later(C_IPC_MESSAGE, I_PE_SUCCESS, &fsa_input);
            crm_debug_2("Completed: %s...", fsa_pe_ref);

        } else {
            crm_info("%s calculation %s is obsolete", op, msg_ref);
        }

    } else if (strcmp(op, CRM_OP_VOTE) == 0
               || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0 || strcmp(op, CRM_OP_SHUTDOWN) == 0) {

    } else {
        const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM);

        crm_err("Unexpected response (op=%s, src=%s) sent to the %s",
                op, host_from, AM_I_DC ? "DC" : "CRMd");
    }
}
Exemplo n.º 21
0
static gboolean
update_synapse_ready(synapse_t *synapse, int action_id) 
{
	gboolean updates = FALSE;
	CRM_CHECK(synapse->executed == FALSE, return FALSE);
	CRM_CHECK(synapse->confirmed == FALSE, return FALSE);

	synapse->ready = TRUE;
	slist_iter(
		prereq, crm_action_t, synapse->inputs, lpc,
		
		crm_debug_3("Processing input %d", prereq->id);
		
		if(prereq->id == action_id) {
			crm_debug_2("Marking input %d of synapse %d confirmed",
				    action_id, synapse->id);
			prereq->confirmed = TRUE;
			updates = TRUE;

		} else if(prereq->confirmed == FALSE) {
			synapse->ready = FALSE;
		}
		
		);
Exemplo n.º 22
0
gboolean
cib_action_update(crm_action_t * action, int status, int op_rc)
{
    lrm_op_t *op = NULL;
    xmlNode *state = NULL;
    xmlNode *rsc = NULL;
    xmlNode *xml_op = NULL;
    xmlNode *action_rsc = NULL;

    enum cib_errors rc = cib_ok;

    const char *name = NULL;
    const char *value = NULL;
    const char *rsc_id = NULL;
    const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
    const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
    const char *task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
    const char *target_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);

    int call_options = cib_quorum_override | cib_scope_local;
    int target_rc = get_target_rc(action);

    if (status == LRM_OP_PENDING) {
        crm_debug("%s %d: Recording pending operation %s on %s",
                  crm_element_name(action->xml), action->id, task_uuid, target);
    } else {
        crm_warn("%s %d: %s on %s timed out",
                 crm_element_name(action->xml), action->id, task_uuid, target);
    }

    action_rsc = find_xml_node(action->xml, XML_CIB_TAG_RESOURCE, TRUE);
    if (action_rsc == NULL) {
        return FALSE;
    }

    rsc_id = ID(action_rsc);
    CRM_CHECK(rsc_id != NULL, crm_log_xml_err(action->xml, "Bad:action");
              return FALSE);

/*
  update the CIB

<node_state id="hadev">
      <lrm>
        <lrm_resources>
          <lrm_resource id="rsc2" last_op="start" op_code="0" target="hadev"/>
*/

    state = create_xml_node(NULL, XML_CIB_TAG_STATE);

    crm_xml_add(state, XML_ATTR_UUID, target_uuid);
    crm_xml_add(state, XML_ATTR_UNAME, target);

    rsc = create_xml_node(state, XML_CIB_TAG_LRM);
    crm_xml_add(rsc, XML_ATTR_ID, target_uuid);

    rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCES);
    rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCE);
    crm_xml_add(rsc, XML_ATTR_ID, rsc_id);

    name = XML_ATTR_TYPE;
    value = crm_element_value(action_rsc, name);
    crm_xml_add(rsc, name, value);
    name = XML_AGENT_ATTR_CLASS;
    value = crm_element_value(action_rsc, name);
    crm_xml_add(rsc, name, value);
    name = XML_AGENT_ATTR_PROVIDER;
    value = crm_element_value(action_rsc, name);
    crm_xml_add(rsc, name, value);

    op = convert_graph_action(NULL, action, status, op_rc);
    op->call_id = -1;
    op->user_data = generate_transition_key(transition_graph->id, action->id, target_rc, te_uuid);

    xml_op = create_operation_update(rsc, op, CRM_FEATURE_SET, target_rc, __FUNCTION__, LOG_INFO);
    free_lrm_op(op);

    crm_debug_3("Updating CIB with \"%s\" (%s): %s %s on %s",
                status < 0 ? "new action" : XML_ATTR_TIMEOUT,
                crm_element_name(action->xml), crm_str(task), rsc_id, target);
    crm_log_xml_trace(xml_op, "Op");

    rc = fsa_cib_conn->cmds->update(fsa_cib_conn, XML_CIB_TAG_STATUS, state, call_options);

    crm_debug_2("Updating CIB with %s action %d: %s on %s (call_id=%d)",
                op_status2text(status), action->id, task_uuid, target, rc);

    add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, cib_action_updated);
    free_xml(state);

    action->sent_update = TRUE;

    if (rc < cib_ok) {
        return FALSE;
    }

    return TRUE;
}
Exemplo n.º 23
0
int
main(int argc, char ** argv)
{
    int lpc;
    int flag;
    int rc = 0;
    int argerr = 0;
    int max_msg_types = DIMOF(cib_pipe_ops);

    int command_options = 0;
    gboolean changed = FALSE;
    gboolean force_flag = FALSE;
    gboolean dangerous_cmd = FALSE;
	
    char *buffer = NULL;
    const char *section = NULL;
    const char *input_xml = NULL;
    const char *input_file = NULL;
    const char *cib_action = NULL;
	
    xmlNode *input = NULL;
    xmlNode *output = NULL;
    xmlNode *result_cib = NULL;
    xmlNode *current_cib = NULL;

    gboolean query = FALSE;
    cib_op_t *fn = NULL;
    
#ifdef HAVE_GETOPT_H
    int option_index = 0;
    static struct option long_options[] = {
	{CIB_OP_ERASE,   0, 0, 'E'},
	{CIB_OP_QUERY,   0, 0, 'Q'},
	{CIB_OP_CREATE,  0, 0, 'C'},
	{CIB_OP_REPLACE, 0, 0, 'R'},
	{CIB_OP_UPDATE,  0, 0, 'U'},
	{CIB_OP_MODIFY,  0, 0, 'M'},
	{"patch",	 0, 0, 'P'},
	{CIB_OP_DELETE,  0, 0, 'D'},
	{CIB_OP_BUMP,    0, 0, 'B'},
	{"md5-sum",	 0, 0, '5'},

	{"force",	0, 0, 'f'},
	{"xml-file",    1, 0, 'x'},
	{"xml-text",    1, 0, 'X'},
	{"xml-save",    1, 0, 'S'},
	{"obj_type",    1, 0, 'o'},

	{"verbose",     0, 0, 'V'},
	{"help",        0, 0, '?'},

	{0, 0, 0, 0}
    };
#endif
	
    crm_log_init("cibpipe", LOG_ERR, FALSE, FALSE, 0, NULL);

    while (1) {
#ifdef HAVE_GETOPT_H
	flag = getopt_long(argc, argv, OPTARGS,
			   long_options, &option_index);
#else
	flag = getopt(argc, argv, OPTARGS);
#endif
	if (flag == -1)
	    break;
		
	switch(flag) {
	    case 'E':
		cib_action = CIB_OP_ERASE;
		dangerous_cmd = TRUE;
		break;
	    case 'Q':
		cib_action = CIB_OP_QUERY;
		break;
	    case 'P':
		cib_action = CIB_OP_APPLY_DIFF;
		break;
	    case 'S':
		cib_action = CIB_OP_SYNC;
		break;
	    case 'U':
	    case 'M':
		cib_action = CIB_OP_MODIFY;
		break;
	    case 'R':
		cib_action = CIB_OP_REPLACE;
		break;
	    case 'C':
		cib_action = CIB_OP_CREATE;
		break;
	    case 'D':
		cib_action = CIB_OP_DELETE;
		break;
	    case '5':
		cib_action = "md5-sum";
		break;
	    case 'd':
		cib_action = CIB_OP_DELETE_ALT;
		break;
	    case 'm':
		cib_action = CIB_OP_ISMASTER;
		command_options |= cib_scope_local;
		break;
	    case 'B':
		cib_action = CIB_OP_BUMP;
		break;
	    case 'o':
		crm_debug_2("Option %c => %s", flag, optarg);
		section = crm_strdup(optarg);
		break;
	    case 'x':
		crm_debug_2("Option %c => %s", flag, optarg);
		input_file = crm_strdup(optarg);
		break;
	    case 'X':
		crm_debug_2("Option %c => %s", flag, optarg);
		input_xml = crm_strdup(optarg);
		break;
	    case 'f':
		force_flag = TRUE;
		command_options |= cib_quorum_override;
		break;		    
	    case 'V':
		alter_debug(DEBUG_INC);
		cl_log_enable_stderr(1);
		break;
	    case '?':		/* Help message */
		usage(crm_system_name, LSB_EXIT_OK);
		break;
	    default:
		++argerr;
		break;
	}
    }

    if (cib_action == NULL) {
	++argerr;
    }
    
    if (optind > argc) {
	++argerr;
    }
    
    if (argerr) {
	usage(crm_system_name, LSB_EXIT_GENERIC);
    }
	
    if(dangerous_cmd && force_flag == FALSE) {
	fprintf(stderr, "The supplied command is considered dangerous."
		"  To prevent accidental destruction of the cluster,"
		" the --force flag is required in order to proceed.\n");
	fflush(stderr);
	usage(crm_system_name, LSB_EXIT_GENERIC);	    
    }

    if(input_file != NULL) {
	input = filename2xml(input_file);
	if(input == NULL) {
	    fprintf(stderr, "Couldn't parse input file: %s\n", input_file);
	    return 1;
	}
	    
    } else if(input_xml != NULL) {
	input = string2xml(input_xml);
	if(input == NULL) {
	    fprintf(stderr, "Couldn't parse input string: %s\n", input_xml);
	    return 1;
	}
    }

    if(input && safe_str_eq(cib_action, CIB_OP_QUERY)) {
	current_cib = copy_xml(input);

    } else {
	current_cib = stdin2xml();
	if(current_cib == NULL && safe_str_neq(cib_action, CIB_OP_ERASE)) {
	    fprintf(stderr, "Couldn't parse existing CIB from STDIN.\n");
	    return 1;
	}
    }
	
	
    if(current_cib == NULL) {
	current_cib = createEmptyCib();
    }
    result_cib = copy_xml(current_cib);

    if(safe_str_eq(cib_action, "md5-sum")) {
	char *digest = NULL;
	digest = calculate_xml_digest(current_cib, FALSE, FALSE);
	fprintf(stdout, "%s\n", crm_str(digest));
	crm_free(digest);
	return 0;
    }

    
    /* read local config file */
    if(cib_action == NULL) {
	crm_err("No operation specified");
	return cib_operation;
    }

    for (lpc = 0; lpc < max_msg_types; lpc++) {
	if (safe_str_eq(cib_action, cib_pipe_ops[lpc].op)) {
	    fn = &(cib_pipe_ops[lpc].fn);
	    query = cib_pipe_ops[lpc].read_only;
	    break;
	}
    }
    
    if(fn == NULL) {
	rc = cib_NOTSUPPORTED;
    } else {
	rc = cib_perform_op(cib_action, command_options, fn, query,
			    section, NULL, input, TRUE, &changed,
			    current_cib, &result_cib, NULL, &output);
    }

    if(rc != cib_ok) {
	fprintf(stderr, "Call failed: %s\n", cib_error2string(rc));
	fprintf(stdout, "%c", 0);
	return -rc;    
    }

    cl_log_args(argc, argv);
    
    if(output) {
	buffer = dump_xml_formatted(output);
    } else {
	buffer = dump_xml_formatted(result_cib);
    }

    fprintf(stdout, "%s\n", buffer);
    fflush(stdout);
    
    crm_info("Done");
    return 0;
}
Exemplo n.º 24
0
int
main(int argc, char **argv)
{
	int argerr = 0;
	int flag;
	const char *source = NULL;
	char *admin_input_xml = NULL;
	char *admin_input_file = NULL;
	gboolean dangerous_cmd = FALSE;
	gboolean admin_input_stdin = FALSE;
	xmlNode *output = NULL;
	xmlNode *input = NULL;
	
	int option_index = 0;
	crm_log_init("cibadmin", LOG_CRIT, FALSE, FALSE, argc, argv);
	crm_set_options("V?$o:QDUCEX:t:Srwlsh:MmBfbRx:pP5N:A:uncd", "command [options] [data]", long_options,
			"Provides direct access to the cluster configuration."
			"\n\n Allows the configuration, or sections of it, to be queried, modified, replaced and deleted."
			"\n\n Where necessary, XML data will be obtained using the -X, -x, or -p options\n");

	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 't':
				message_timeout_ms = atoi(optarg);
				if(message_timeout_ms < 1) {
					message_timeout_ms = 30;
				}
				break;
			case 'A':
				obj_type = crm_strdup(optarg);
				command_options |= cib_xpath;
				break;
			case 'u':
				cib_action = CIB_OP_UPGRADE;
				dangerous_cmd = TRUE;
				break;
			case 'E':
				cib_action = CIB_OP_ERASE;
				dangerous_cmd = TRUE;
				break;
			case 'Q':
				cib_action = CIB_OP_QUERY;
				break;
			case 'P':
				cib_action = CIB_OP_APPLY_DIFF;
				break;
			case 'S':
				cib_action = CIB_OP_SYNC;
				break;
			case 'U':
			case 'M':
				cib_action = CIB_OP_MODIFY;
				break;
			case 'R':
				cib_action = CIB_OP_REPLACE;
				break;
			case 'C':
				cib_action = CIB_OP_CREATE;
				break;
			case 'D':
				cib_action = CIB_OP_DELETE;
				break;
			case '5':
				cib_action = "md5-sum";
				break;
			case 'c':
				command_options |= cib_can_create;
				break;
			case 'n':
				command_options |= cib_no_children;
				break;
			case 'm':
				cib_action = CIB_OP_ISMASTER;
				command_options |= cib_scope_local;
				break;
			case 'B':
				cib_action = CIB_OP_BUMP;
				break;
			case 'r':
				dangerous_cmd = TRUE;
				cib_action = CIB_OP_SLAVE;
				break;
			case 'w':
				dangerous_cmd = TRUE;
				cib_action = CIB_OP_MASTER;
				command_options |= cib_scope_local;
				break;
			case 'V':
				command_options = command_options | cib_verbose;
				cl_log_enable_stderr(TRUE);
				alter_debug(DEBUG_INC);
				break;
			case '?':
			case '$':
				crm_help(flag, LSB_EXIT_OK);
				break;
			case 'o':
				crm_debug_2("Option %c => %s", flag, optarg);
				obj_type = crm_strdup(optarg);
				break;
			case 'X':
				crm_debug_2("Option %c => %s", flag, optarg);
				admin_input_xml = crm_strdup(optarg);
				break;
			case 'x':
				crm_debug_2("Option %c => %s", flag, optarg);
				admin_input_file = crm_strdup(optarg);
				break;
			case 'p':
				admin_input_stdin = TRUE;
				break;
			case 'h':
				host = crm_strdup(optarg);
				break;
			case 'l':
				command_options |= cib_scope_local;
				break;
			case 'd':
				cib_action = CIB_OP_DELETE;
				command_options |= cib_multiple;
				dangerous_cmd = TRUE;
				break;
			case 'b':
				dangerous_cmd = TRUE;
				command_options |= cib_inhibit_bcast;
				command_options |= cib_scope_local;
				break;
			case 's':
				command_options |= cib_sync_call;
				break;
			case 'f':
				force_flag = TRUE;
				command_options |= cib_quorum_override;
				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");
		crm_help('?', LSB_EXIT_EINVAL);
	}

	if (optind > argc || cib_action == NULL) {
	    ++argerr;
	}
	
	if (argerr) {
		crm_help('?', LSB_EXIT_GENERIC);
	}

	if(dangerous_cmd && force_flag == FALSE) {
	    fprintf(stderr, "The supplied command is considered dangerous."
		    "  To prevent accidental destruction of the cluster,"
		    " the --force flag is required in order to proceed.\n");
	    fflush(stderr);
	    exit(LSB_EXIT_GENERIC);
	}
	
	if(admin_input_file != NULL) {
	    input = filename2xml(admin_input_file);
	    source = admin_input_file;
		
	} else if(admin_input_xml != NULL) {
	    source = "input string";
	    input = string2xml(admin_input_xml);

	} else if(admin_input_stdin) {
	    source = "STDIN";
	    input = stdin2xml();
	}
	
	if(input != NULL) {
	    crm_log_xml_debug(input, "[admin input]");

	} else if(source) {
	    fprintf(stderr, "Couldn't parse input from %s.\n", source);
	    return 1;
	}

	if(safe_str_eq(cib_action, "md5-sum")) {
	    char *digest = NULL;
	    if(input == NULL) {
		fprintf(stderr,
			"Please supply XML to process with -X, -x or -p\n");
		exit(1);
	    }
	    
	    digest = calculate_xml_digest(input, FALSE, FALSE);
	    fprintf(stderr, "Digest: ");
	    fprintf(stdout, "%s\n", crm_str(digest));
	    crm_free(digest);
	    exit(0);
	}
	
	exit_code = do_init();
	if(exit_code != cib_ok) {
		crm_err("Init failed, could not perform requested operations");
		fprintf(stderr, "Init failed, could not perform requested operations\n");
		return -exit_code;
	}	

	exit_code = do_work(input, command_options, &output);
	if (exit_code > 0) {
		/* wait for the reply by creating a mainloop and running it until
		 * the callbacks are invoked...
		 */
		request_id = exit_code;

		the_cib->cmds->register_callback(
		    the_cib, request_id, message_timeout_ms, FALSE, NULL,
		    "cibadmin_op_callback", cibadmin_op_callback);

		mainloop = g_main_new(FALSE);

		crm_debug_3("%s waiting for reply from the local CIB",
			 crm_system_name);
		
		crm_info("Starting mainloop");
		g_main_run(mainloop);
		
	} else if(exit_code < 0) {
		crm_err("Call failed: %s", cib_error2string(exit_code));
		fprintf(stderr, "Call failed: %s\n",
			cib_error2string(exit_code));
		operation_status = exit_code;

		if(exit_code == cib_dtd_validation) {
		    if(crm_str_eq(cib_action, CIB_OP_UPGRADE, TRUE)) {
			xmlNode *obj = NULL;
			int version = 0, rc = 0;
			rc = the_cib->cmds->query(the_cib, NULL, &obj, command_options);
			if(rc == cib_ok) {
			    update_validation(&obj, &version, TRUE, FALSE);
			}

		    } else if(output) {
			validate_xml_verbose(output);
		    }
		}
	}

	if(output != NULL) {
		char *buffer = dump_xml_formatted(output);
		fprintf(stdout, "%s\n", crm_str(buffer));
		crm_free(buffer);
	}

	the_cib->cmds->signoff(the_cib);
	
	crm_debug_3("%s exiting normally", crm_system_name);
	return -exit_code;
}
Exemplo n.º 25
0
static gboolean
check_action_definition(resource_t *rsc, node_t *active_node, crm_data_t *xml_op,
			pe_working_set_t *data_set)
{
	char *key = NULL;
	int interval = 0;
	const char *interval_s = NULL;
	
	gboolean did_change = FALSE;
	gboolean start_op = FALSE;

	crm_data_t *params_all = NULL;
	crm_data_t *params_restart = NULL;
	GHashTable *local_rsc_params = NULL;
	
	char *digest_all_calc = NULL;
	const char *digest_all = NULL;

	const char *restart_list = NULL;
	const char *digest_restart = NULL;
	char *digest_restart_calc = NULL;

	action_t *action = NULL;
	const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
	const char *op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);

	CRM_CHECK(active_node != NULL, return FALSE);

	interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL);
	interval = crm_parse_int(interval_s, "0");
	/* we need to reconstruct the key because of the way we used to construct resource IDs */
	key = generate_op_key(rsc->id, task, interval);

	if(interval > 0) {
		crm_data_t *op_match = NULL;

		crm_debug_2("Checking parameters for %s", key);
		op_match = find_rsc_op_entry(rsc, key);

		if(op_match == NULL && data_set->stop_action_orphans) {
			/* create a cancel action */
			action_t *cancel = NULL;
			char *cancel_key = NULL;
			const char *call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
			
			crm_info("Orphan action will be stopped: %s on %s",
				 key, active_node->details->uname);

			cancel_key = generate_op_key(
				rsc->id, CRMD_ACTION_CANCEL, interval);

			cancel = custom_action(
				rsc, cancel_key, CRMD_ACTION_CANCEL,
				active_node, FALSE, TRUE, data_set);

			add_hash_param(cancel->meta, XML_LRM_ATTR_TASK,     task);
			add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID,   call_id);
			add_hash_param(cancel->meta, XML_LRM_ATTR_INTERVAL, interval_s);

			custom_action_order(	
				rsc, stop_key(rsc), NULL,
				rsc, NULL, cancel,
				pe_order_optional, data_set);
			crm_free(key); key = NULL;
			return TRUE;

		} else if(op_match == NULL) {
			crm_debug("Orphan action detected: %s on %s",
				  key, active_node->details->uname);
			crm_free(key); key = NULL;
			return TRUE;
		}
	}

	action = custom_action(rsc, key, task, active_node, TRUE, FALSE, data_set);
	
	local_rsc_params = g_hash_table_new_full(
		g_str_hash, g_str_equal,
		g_hash_destroy_str, g_hash_destroy_str);
	
	unpack_instance_attributes(
		rsc->xml, XML_TAG_ATTR_SETS, active_node->details->attrs,
		local_rsc_params, NULL, data_set->now);
	
	params_all = create_xml_node(NULL, XML_TAG_PARAMS);
	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);
	g_hash_table_foreach(local_rsc_params, hash2field, params_all);

	filter_action_parameters(params_all, op_version);
	digest_all_calc = calculate_xml_digest(params_all, TRUE, FALSE);
	digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
	digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
	restart_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);

	if(crm_str_eq(task, CRMD_ACTION_START, TRUE)) {
		start_op = TRUE;
	}
	
	if(start_op && digest_restart) {
		params_restart = copy_xml(params_all);
		if(restart_list) {
			filter_reload_parameters(params_restart, restart_list);
		}

		digest_restart_calc = calculate_xml_digest(params_restart, TRUE, FALSE);
		if(safe_str_neq(digest_restart_calc, digest_restart)) {
			did_change = TRUE;
			crm_log_xml_info(params_restart, "params:restart");
			crm_warn("Parameters to %s on %s changed: recorded %s vs. %s (restart:%s) %s",
				 key, active_node->details->uname,
				 crm_str(digest_restart), digest_restart_calc,
				 op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
			
			key = generate_op_key(rsc->id, task, interval);
			custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
			goto cleanup;
		}
	}

	if(safe_str_neq(digest_all_calc, digest_all)) {
		action_t *op = NULL;
		did_change = TRUE;
		crm_log_xml_info(params_all, "params:all");
 		crm_warn("Parameters to %s on %s changed: recorded %s vs. %s (all:%s) %s",
			 key, active_node->details->uname,
			 crm_str(digest_all), digest_all_calc, op_version,
			 crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
		
		key = generate_op_key(rsc->id, task, interval);
		op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
		if(start_op && digest_restart) {
			op->allow_reload_conversion = TRUE;

		} else if(interval > 0) {
			custom_action_order(rsc, start_key(rsc), NULL,
					    NULL, crm_strdup(op->task), op,
					    pe_order_runnable_left, data_set);
		}
		
	}

  cleanup:
	free_xml(params_all);
	free_xml(params_restart);
	crm_free(digest_all_calc);
	crm_free(digest_restart_calc);
	g_hash_table_destroy(local_rsc_params);

	pe_free_action(action);
	
	return did_change;
}
Exemplo n.º 26
0
/*
	CRM_OP_JOIN_ACKNACKを送信後、ノードからCRM_OP_JOIN_CONFIRMメッセージが送られて来たときの処理
*/
void
do_dc_join_ack(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 join_id = -1;
	int call_id = 0;
	ha_msg_input_t *join_ack = fsa_typed_data(fsa_dt_ha_msg);

	const char *join_id_s  = NULL;
	const char *join_state = NULL;
	const char *op         = crm_element_value(join_ack->msg, F_CRM_TASK);
	const char *join_from  = crm_element_value(join_ack->msg, F_CRM_HOST_FROM);

	if(safe_str_neq(op, CRM_OP_JOIN_CONFIRM)) {
		/* CRM_OP_JOIN_CONFIRMメッセージ以外のメッセージは無視してログを出力 */
		crm_debug("Ignoring op=%s message from %s", op, join_from);
		return;
	} 

	crm_element_value_int(join_ack->msg, F_CRM_JOIN_ID, &join_id);
	join_id_s = crm_element_value(join_ack->msg, F_CRM_JOIN_ID);

	/* now update them to "member" */
	
	crm_debug_2("Processing ack from %s", join_from);

	/* CRM_OP_JOIN_CONFIRMを送ってきたノードがfinalized_nodesハッシュテーブルに含まれるかサーチする */
	join_state = (const char *)
		g_hash_table_lookup(finalized_nodes, join_from);
	
	if(join_state == NULL) {
		/* 含まれていない場合は、無視 */
		crm_err("Join not in progress: ignoring join-%d from %s",
			join_id, join_from);
		return;
		
	} else if(safe_str_neq(join_state, CRMD_JOINSTATE_MEMBER)) {
		crm_err("Node %s wasnt invited to join the cluster",join_from);
		/* 含まれていて、CRMD_JOINSTATE_MEMBER状態の場合は、finalized_nodesハッシュテーブルからCRM_OP_JOIN_CONFIRMを送ってきたノードを削除 */
		g_hash_table_remove(finalized_nodes, join_from);
		return;
		
	} else if(join_id != current_join_id) {
		crm_err("Invalid response from %s: join-%d vs. join-%d",
			join_from, join_id, current_join_id);
		/* JOIN_IDが異なる場合も、finalized_nodesハッシュテーブルからCRM_OP_JOIN_CONFIRMを送ってきたノードを削除 */
		g_hash_table_remove(finalized_nodes, join_from);
		return;
	}
	
	/* 上記以外の場合も、finalized_nodesハッシュテーブルからCRM_OP_JOIN_CONFIRMを送ってきたノードを削除 */
	g_hash_table_remove(finalized_nodes, join_from);
	
	/* confirmed_nodesハッシュテーブルにRM_OP_JOIN_CONFIRMを送ってきたノードでサーチ */
	if(g_hash_table_lookup(confirmed_nodes, join_from) != NULL) {
		/* 既に登録済みの場合は、エラーメッセージを表示 */
		crm_err("join-%d: hash already contains confirmation from %s",
			join_id, join_from);
	}

	/* confirmed_nodesハッシュテーブルにCRM_OP_JOIN_CONFIRMを送ってきたノードを追加 */
	g_hash_table_insert(
		confirmed_nodes, crm_strdup(join_from), crm_strdup(join_id_s));

	/* join完了ログを出す */
 	crm_info("join-%d: Updating node state to %s for %s",
 		 join_id, CRMD_JOINSTATE_MEMBER, join_from);

	/* update CIB with the current LRM status from the node
	 * We dont need to notify the TE of these updates, a transition will
	 *   be started in due time
	 */
	/* CIBからCRM_OP_JOIN_CONFIRMを送ってきたノードのXML_CIB_TAG_LRM情報を消去 */
	erase_status_tag(join_from, XML_CIB_TAG_LRM, cib_scope_local);
	/* CIBを更新 */
	/* CRM_OP_JOIN_CONFIRMを送ってきたノードのXML_CIB_TAG_LRM情報も追加される */
	/* クラスタ構成ノードのLRMD情報が最新で更新 */
	fsa_cib_update(XML_CIB_TAG_STATUS, join_ack->xml,
		       cib_scope_local|cib_quorum_override|cib_can_create, call_id);
	/* CIBの更新コールバックをセット */
	add_cib_op_callback(
		fsa_cib_conn, call_id, FALSE, NULL, join_update_complete_callback);
 	crm_debug("join-%d: Registered callback for LRM update %d",
		  join_id, call_id);
}
Exemplo n.º 27
0
void
cib_notify_client(gpointer key, gpointer value, gpointer user_data)
{

	IPC_Channel *ipc_client = NULL;
	HA_Message *update_msg = user_data;
	cib_client_t *client = value;
	const char *type = NULL;
	gboolean is_pre = FALSE;
	gboolean is_post = FALSE;	
	gboolean is_confirm = FALSE;
	gboolean is_replace = FALSE;
	gboolean is_diff = FALSE;
	gboolean do_send = FALSE;

	int qlen = 0;
	int max_qlen = 0;
	
	CRM_DEV_ASSERT(client != NULL);
	CRM_DEV_ASSERT(update_msg != NULL);

	type = cl_get_string(update_msg, F_SUBTYPE);
	CRM_DEV_ASSERT(type != NULL);

	if(client == NULL) {
		crm_warn("Skipping NULL client");
		return;

	} else if(client->channel == NULL) {
		crm_warn("Skipping client with NULL channel");
		return;

	} else if(client->name == NULL) {
		crm_debug_2("Skipping unnammed client / comamnd channel");
		return;
	}
	
	if(safe_str_eq(type, T_CIB_PRE_NOTIFY)) {
		is_pre = TRUE;
		
	} else if(safe_str_eq(type, T_CIB_POST_NOTIFY)) {
		is_post = TRUE;

	} else if(safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) {
		is_confirm = TRUE;

	} else if(safe_str_eq(type, T_CIB_DIFF_NOTIFY)) {
		is_diff = TRUE;

	} else if(safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) {
		is_replace = TRUE;
	}

	ipc_client = client->channel;
	qlen = ipc_client->send_queue->current_qlen;
	max_qlen = ipc_client->send_queue->max_qlen;

#if 1
	/* get_chan_status() causes memory to be allocated that isnt free'd
	 *   until the message is read (which messes up the memory stats) 
	 */
	if(ipc_client->ops->get_chan_status(ipc_client) != IPC_CONNECT) {
		crm_debug_2("Skipping notification to disconnected"
			    " client %s/%s", client->name, client->id);
		
	} else if(client->pre_notify && is_pre) {
		if(qlen < (int)(0.4 * max_qlen)) {
			do_send = TRUE;
		} else {
			crm_warn("Throttling pre-notifications due to"
				 " high load: queue=%d (max=%d)",
				 qlen, max_qlen);
		}
		 
	} else if(client->post_notify && is_post) {
		if(qlen < (int)(0.7 * max_qlen)) {
			do_send = TRUE;
		} else {
			crm_warn("Throttling post-notifications due to"
				 " extreme load: queue=%d (max=%d)",
				 qlen, max_qlen);
		}

		/* these are critical */
	} else
#endif
		if(client->diffs && is_diff) {
		do_send = TRUE;

	} else if(client->confirmations && is_confirm) {
		do_send = TRUE;

	} else if(client->replace && is_replace) {
		do_send = TRUE;
	}

	if(do_send) {
		crm_debug_2("Notifying client %s/%s of %s update (queue=%d)",
			    client->name, client->channel_name, type, qlen);

		if(ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) {
			/* We never want the CIB to exit because our client is slow */
			crm_crit("%s-notification of client %s/%s failed - queue saturated",
				 is_confirm?"Confirmation":is_post?"Post":"Pre",
				 client->name, client->id);
			
		} else if(send_ipc_message(ipc_client, update_msg) == FALSE) {
			crm_warn("Notification of client %s/%s failed",
				 client->name, client->id);
		}
		
	} else {
		crm_debug_3("Client %s/%s not interested in %s notifications",
			    client->name, client->channel_name, type);	
	}
}
Exemplo n.º 28
0
void
do_cib_notify(
	int options, const char *op, crm_data_t *update,
	enum cib_errors result, crm_data_t *result_data, const char *msg_type) 
{
	HA_Message *update_msg = NULL;
	const char *type = NULL;
	const char *id = NULL;

	update_msg = ha_msg_new(8);

	if(result_data != NULL) {
		id = crm_element_value(result_data, XML_ATTR_ID);
	}
	
	ha_msg_add(update_msg, F_TYPE, T_CIB_NOTIFY);
	ha_msg_add(update_msg, F_SUBTYPE, msg_type);
	ha_msg_add(update_msg, F_CIB_OPERATION, op);
	ha_msg_add_int(update_msg, F_CIB_RC, result);
	
	if(id != NULL) {
		ha_msg_add(update_msg, F_CIB_OBJID, id);
	}

	if(update != NULL) {
		crm_debug_4("Setting type to update->name: %s",
			    crm_element_name(update));
		ha_msg_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
		type = crm_element_name(update);

	} else if(result_data != NULL) {
		crm_debug_4("Setting type to new_obj->name: %s",
			    crm_element_name(result_data));
		ha_msg_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
		type = crm_element_name(result_data);
		
	} else {
		crm_debug_4("Not Setting type");
	}

	attach_cib_generation(update_msg, "cib_generation", the_cib);
	if(update != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE, update);
	}
	if(result_data != NULL) {
		add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
	}

	crm_debug_3("Notifying clients");
	g_hash_table_foreach(client_list, cib_notify_client, update_msg);
	crm_msg_del(update_msg);

	if(update == NULL) {
		if(result == cib_ok) {
			crm_debug_2("Operation %s (on section=%s) completed",
				    op, crm_str(type));
			
		} else {
			crm_warn("Operation %s (on section=%s) FAILED: (%d) %s",
				 op, crm_str(type), result,
				 cib_error2string(result));
		}
		
	} else {
		if(result == cib_ok) {
			crm_debug_2("Completed %s of <%s %s%s>",
				    op, crm_str(type), id?"id=":"", id?id:"");
			
		} else {
			crm_warn("%s of <%s %s%s> FAILED: %s", op,crm_str(type),
				 id?"id=":"", id?id:"", cib_error2string(result));
		}
	}

	crm_debug_3("Notify complete");
}
Exemplo n.º 29
0
gboolean
cib_remote_msg(int csock, gpointer data)
{
    const char *value = NULL;
    xmlNode *command = NULL;
    cib_client_t *client = data;

    crm_trace("%s callback", client->encrypted ? "secure" : "clear-text");

    command = cib_recv_remote_msg(client->channel, client->encrypted);
    if (command == NULL) {
        return FALSE;
    }

    value = crm_element_name(command);
    if (safe_str_neq(value, "cib_command")) {
        crm_log_xml(LOG_MSG, "Bad command: ", command);
        goto bail;
    }

    if (client->name == NULL) {
        value = crm_element_value(command, F_CLIENTNAME);
        if (value == NULL) {
            client->name = crm_strdup(client->id);
        } else {
            client->name = crm_strdup(value);
        }
    }

    if (client->callback_id == NULL) {
        value = crm_element_value(command, F_CIB_CALLBACK_TOKEN);
        if (value != NULL) {
            client->callback_id = crm_strdup(value);
            crm_debug_2("Callback channel for %s is %s", client->id, client->callback_id);

        } else {
            client->callback_id = crm_strdup(client->id);
        }
    }

    /* unset dangerous options */
    xml_remove_prop(command, F_ORIG);
    xml_remove_prop(command, F_CIB_HOST);
    xml_remove_prop(command, F_CIB_GLOBAL_UPDATE);

    crm_xml_add(command, F_TYPE, T_CIB);
    crm_xml_add(command, F_CIB_CLIENTID, client->id);
    crm_xml_add(command, F_CIB_CLIENTNAME, client->name);
#if ENABLE_ACL
    crm_xml_add(command, F_CIB_USER, client->user);
#endif

    if (crm_element_value(command, F_CIB_CALLID) == NULL) {
        cl_uuid_t call_id;
        char call_uuid[UU_UNPARSE_SIZEOF];

        /* fix the command */
        cl_uuid_generate(&call_id);
        cl_uuid_unparse(&call_id, call_uuid);
        crm_xml_add(command, F_CIB_CALLID, call_uuid);
    }

    if (crm_element_value(command, F_CIB_CALLOPTS) == NULL) {
        crm_xml_add_int(command, F_CIB_CALLOPTS, 0);
    }

    crm_log_xml(LOG_MSG, "Remote command: ", command);
    cib_common_callback_worker(command, client, FALSE, TRUE);
  bail:
    free_xml(command);
    command = NULL;
    return TRUE;
}
Exemplo n.º 30
0
enum cib_errors
cib_process_diff(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                 xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    unsigned int log_level = LOG_DEBUG;
    const char *reason = NULL;
    gboolean apply_diff = TRUE;
    enum cib_errors result = cib_ok;

    int this_updates = 0;
    int this_epoch = 0;
    int this_admin_epoch = 0;

    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;

    crm_debug_2("Processing \"%s\" event", op);

    cib_diff_version_details(input,
                             &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
                             &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);

    crm_element_value_int(existing_cib, XML_ATTR_GENERATION, &this_epoch);
    crm_element_value_int(existing_cib, XML_ATTR_NUMUPDATES, &this_updates);
    crm_element_value_int(existing_cib, XML_ATTR_GENERATION_ADMIN, &this_admin_epoch);

    if (this_epoch < 0) {
        this_epoch = 0;
    }
    if (this_updates < 0) {
        this_updates = 0;
    }
    if (this_admin_epoch < 0) {
        this_admin_epoch = 0;
    }

    if (diff_del_admin_epoch == diff_add_admin_epoch
        && diff_del_epoch == diff_add_epoch && diff_del_updates == diff_add_updates) {
        if (options & cib_force_diff) {
            apply_diff = FALSE;
            log_level = LOG_ERR;
            reason = "+ and - versions in the diff did not change in global update";
            crm_log_xml_warn(input, "Bad global update");

        } else if (diff_add_admin_epoch == -1 && diff_add_epoch == -1 && diff_add_updates == -1) {
            diff_add_epoch = this_epoch;
            diff_add_updates = this_updates + 1;
            diff_add_admin_epoch = this_admin_epoch;
            diff_del_epoch = this_epoch;
            diff_del_updates = this_updates;
            diff_del_admin_epoch = this_admin_epoch;

        } else {
            apply_diff = FALSE;
            log_level = LOG_ERR;
            reason = "+ and - versions in the diff did not change";
            log_cib_diff(LOG_ERR, input, __FUNCTION__);
        }
    }

    if (apply_diff && diff_del_admin_epoch > this_admin_epoch) {
        result = cib_diff_resync;
        apply_diff = FALSE;
        log_level = LOG_INFO;
        reason = "current \"" XML_ATTR_GENERATION_ADMIN "\" is less than required";

    } else if (apply_diff && diff_del_admin_epoch < this_admin_epoch) {
        apply_diff = FALSE;
        log_level = LOG_WARNING;
        reason = "current \"" XML_ATTR_GENERATION_ADMIN "\" is greater than required";

    } else if (apply_diff && diff_del_epoch > this_epoch) {
        result = cib_diff_resync;
        apply_diff = FALSE;
        log_level = LOG_INFO;
        reason = "current \"" XML_ATTR_GENERATION "\" is less than required";

    } else if (apply_diff && diff_del_epoch < this_epoch) {
        apply_diff = FALSE;
        log_level = LOG_WARNING;
        reason = "current \"" XML_ATTR_GENERATION "\" is greater than required";

    } else if (apply_diff && diff_del_updates > this_updates) {
        result = cib_diff_resync;
        apply_diff = FALSE;
        log_level = LOG_INFO;
        reason = "current \"" XML_ATTR_NUMUPDATES "\" is less than required";

    } else if (apply_diff && diff_del_updates < this_updates) {
        apply_diff = FALSE;
        log_level = LOG_WARNING;
        reason = "current \"" XML_ATTR_NUMUPDATES "\" is greater than required";
    }

    if (apply_diff) {
        free_xml(*result_cib);
        *result_cib = NULL;
        if (apply_xml_diff(existing_cib, input, result_cib) == FALSE) {
            log_level = LOG_NOTICE;
            reason = "Failed application of an update diff";

            if (options & cib_force_diff) {
                result = cib_diff_resync;
            }
        }
    }

    if (reason != NULL) {
        do_crm_log(log_level,
                   "Diff %d.%d.%d -> %d.%d.%d not applied to %d.%d.%d: %s",
                   diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
                   diff_add_admin_epoch, diff_add_epoch, diff_add_updates,
                   this_admin_epoch, this_epoch, this_updates, reason);

        crm_log_xml_trace(input, "Discarded diff");
        if (result == cib_ok) {
            result = cib_diff_failed;
        }

    } else if (apply_diff) {
        crm_debug_2("Diff %d.%d.%d -> %d.%d.%d was applied to %d.%d.%d",
                    diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
                    diff_add_admin_epoch, diff_add_epoch, diff_add_updates,
                    this_admin_epoch, this_epoch, this_updates);

    }
    return result;
}