Пример #1
0
crm_graph_t *
unpack_graph(xmlNode * xml_graph, const char *reference)
{
/*
  <transition_graph>
  <synapse>
  <action_set>
  <rsc_op id="2"
  ... 
  <inputs>
  <rsc_op id="2"
  ... 
*/
    crm_graph_t *new_graph = NULL;
    const char *t_id = NULL;
    const char *time = NULL;
    xmlNode *synapse = NULL;

    crm_malloc0(new_graph, sizeof(crm_graph_t));

    new_graph->id = -1;
    new_graph->abort_priority = 0;
    new_graph->network_delay = -1;
    new_graph->transition_timeout = -1;
    new_graph->stonith_timeout = -1;
    new_graph->completion_action = tg_done;

    new_graph->migrating = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                                 g_hash_destroy_str, g_hash_destroy_str);

    if (reference) {
        new_graph->source = crm_strdup(reference);
    } else {
        new_graph->source = crm_strdup("unknown");
    }

    if (xml_graph != NULL) {
        t_id = crm_element_value(xml_graph, "transition_id");
        CRM_CHECK(t_id != NULL, crm_free(new_graph);
                  return NULL);
        new_graph->id = crm_parse_int(t_id, "-1");

        time = crm_element_value(xml_graph, "cluster-delay");
        CRM_CHECK(time != NULL, crm_free(new_graph);
                  return NULL);
        new_graph->network_delay = crm_get_msec(time);

        time = crm_element_value(xml_graph, "stonith-timeout");
        if (time == NULL) {
            new_graph->stonith_timeout = new_graph->network_delay;
        } else {
            new_graph->stonith_timeout = crm_get_msec(time);
        }

        t_id = crm_element_value(xml_graph, "batch-limit");
        new_graph->batch_limit = crm_parse_int(t_id, "0");

        t_id = crm_element_value(xml_graph, "migration-limit");
        new_graph->migration_limit = crm_parse_int(t_id, "-1");
    }
Пример #2
0
static bool
startCib(const char *filename)
{
    gboolean active = FALSE;
    xmlNode *cib = readCibXmlFile(cib_root, filename, !preserve_status);

    if (activateCibXml(cib, TRUE, "start") == 0) {
        int port = 0;
        const char *port_s = NULL;

        active = TRUE;

        cib_read_config(config_hash, cib);

        port_s = crm_element_value(cib, "remote-tls-port");
        if (port_s) {
            port = crm_parse_int(port_s, "0");
            remote_tls_fd = init_remote_listener(port, TRUE);
        }

        port_s = crm_element_value(cib, "remote-clear-port");
        if (port_s) {
            port = crm_parse_int(port_s, "0");
            remote_fd = init_remote_listener(port, FALSE);
        }

        crm_info("CIB Initialization completed successfully");
    }

    return active;
}
Пример #3
0
static crm_action_t *
unpack_action(synapse_t * parent, xmlNode * xml_action)
{
    crm_action_t *action = NULL;
    const char *value = crm_element_value(xml_action, XML_ATTR_ID);

    if (value == NULL) {
        crm_err("Actions must have an id!");
        crm_log_xml_trace(xml_action, "Action with missing id");
        return NULL;
    }

    action = calloc(1, sizeof(crm_action_t));
    CRM_CHECK(action != NULL, return NULL);

    action->id = crm_parse_int(value, NULL);
    action->type = action_type_rsc;
    action->xml = copy_xml(xml_action);
    action->synapse = parent;

    if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_RSC_OP)) {
        action->type = action_type_rsc;

    } else if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_PSEUDO_EVENT)) {
        action->type = action_type_pseudo;

    } else if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_CRM_EVENT)) {
        action->type = action_type_crm;
    }

    action->params = xml2list(action->xml);

    value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
    if (value != NULL) {
        action->timeout = crm_parse_int(value, NULL);
    }

    /* Take start-delay into account for the timeout of the action timer */
    value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
    if (value != NULL) {
        action->timeout += crm_parse_int(value, NULL);
    }

    value = g_hash_table_lookup(action->params, "CRM_meta_interval");
    if (value != NULL) {
        action->interval = crm_parse_int(value, NULL);
    }

    value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
    if (value != NULL) {
        crm_str_to_boolean(value, &(action->can_fail));
    }

    crm_trace("Action %d has timer set to %dms", action->id, action->timeout);

    return action;
}
Пример #4
0
int
char2score(const char *score) 
{
	int score_f = 0;
	
	if(score == NULL) {
		
	} else if(safe_str_eq(score, MINUS_INFINITY_S)) {
		score_f = -INFINITY;
		
	} else if(safe_str_eq(score, INFINITY_S)) {
		score_f = INFINITY;
		
	} else if(safe_str_eq(score, "+"INFINITY_S)) {
		score_f = INFINITY;
		
	} else {
		score_f = crm_parse_int(score, NULL);
		if(score_f > 0 && score_f > INFINITY) {
			score_f = INFINITY;
			
		} else if(score_f < 0 && score_f < -INFINITY) {
			score_f = -INFINITY;
		}
	}
	
	return score_f;
}
Пример #5
0
/*!
 * \internal
 * \brief Read and return sequence number stored in a file series' .last file
 *
 * \param[in] directory Directory that contains the file series
 * \param[in] series Start of file name
 *
 * \return The last sequence number, or 0 on error
 */
int
get_last_sequence(const char *directory, const char *series)
{
    FILE *file_strm = NULL;
    int start = 0, length = 0, read_len = 0;
    char *series_file = NULL;
    char *buffer = NULL;
    int seq = 0;
    int len = 36;

    CRM_CHECK(directory != NULL, return 0);
    CRM_CHECK(series != NULL, return 0);

    len += strlen(directory);
    len += strlen(series);
    series_file = malloc(len);
    CRM_CHECK(series_file != NULL, return 0);
    sprintf(series_file, "%s/%s.last", directory, series);

    file_strm = fopen(series_file, "r");
    if (file_strm == NULL) {
        crm_debug("Series file %s does not exist", series_file);
        free(series_file);
        return 0;
    }

    /* see how big the file is */
    start = ftell(file_strm);
    fseek(file_strm, 0L, SEEK_END);
    length = ftell(file_strm);
    fseek(file_strm, 0L, start);

    CRM_ASSERT(length >= 0);
    CRM_ASSERT(start == ftell(file_strm));

    if (length <= 0) {
        crm_info("%s was not valid", series_file);
        free(buffer);
        buffer = NULL;

    } else {
        crm_trace("Reading %d bytes from file", length);
        buffer = calloc(1, (length + 1));
        read_len = fread(buffer, 1, length, file_strm);
        if (read_len != length) {
            crm_err("Calculated and read bytes differ: %d vs. %d", length, read_len);
            free(buffer);
            buffer = NULL;
        }
    }

    seq = crm_parse_int(buffer, "0");
    fclose(file_strm);

    crm_trace("Found %d in %s", seq, series_file);

    free(series_file);
    free(buffer);
    return seq;
}
Пример #6
0
int copies_per_node(resource_t * rsc) 
{
    /* Strictly speaking, there should be a 'copies_per_node' addition
     * to the resource function table and each case would be a
     * function.  However that would be serious overkill to return an
     * int.  In fact, it seems to me that both function tables
     * could/should be replaced by resources.{c,h} full of
     * rsc_{some_operation} functions containing a switch as below
     * which calls out to functions named {variant}_{some_operation}
     * as needed.
     */
    switch(rsc->variant) {
        case pe_unknown:
            return 0;
        case pe_native:
        case pe_group:
            return 1;
        case pe_clone:
        case pe_master:
            {
                const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX);
                return crm_parse_int(max_clones_node, "1");
            }
        case pe_container:
            {
                container_variant_data_t *data = NULL;
                get_container_variant_data(data, rsc);
                return data->replicas_per_host;
            }
    }
    return 0;
}
Пример #7
0
static void
do_calculate_utilization(gpointer key, gpointer value, gpointer user_data)
{
    const char *current = NULL;
    char *result = NULL;
    struct calculate_data *data = user_data;

    current = g_hash_table_lookup(data->current_utilization, key);
    if (data->plus) {
        result = crm_itoa(crm_parse_int(current, "0") + crm_parse_int(value, "0"));
        g_hash_table_replace(data->current_utilization, strdup(key), result);

    } else if (current) {
        result = crm_itoa(crm_parse_int(current, "0") - crm_parse_int(value, "0"));
        g_hash_table_replace(data->current_utilization, strdup(key), result);
    }
}
Пример #8
0
gboolean
master_unpack(resource_t * rsc, pe_working_set_t * data_set)
{
    const char *master_max = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_MASTER_MAX);
    const char *master_node_max = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_MASTER_NODEMAX);

    g_hash_table_replace(rsc->meta, strdup("stateful"), strdup(XML_BOOLEAN_TRUE));
    if (clone_unpack(rsc, data_set)) {
        clone_variant_data_t *clone_data = NULL;

        get_clone_variant_data(clone_data, rsc);
        clone_data->master_max = crm_parse_int(master_max, "1");
        clone_data->master_node_max = crm_parse_int(master_node_max, "1");
        return TRUE;
    }
    return FALSE;
}
Пример #9
0
static void
do_compare_capacity1(gpointer key, gpointer value, gpointer user_data)
{
    int node1_capacity = 0;
    int node2_capacity = 0;
    struct compare_data *data = user_data;

    node1_capacity = crm_parse_int(value, "0");
    node2_capacity =
        crm_parse_int(g_hash_table_lookup(data->node2->details->utilization, key), "0");

    if (node1_capacity > node2_capacity) {
        data->result--;
    } else if (node1_capacity < node2_capacity) {
        data->result++;
    }
}
static int get_target_rc(crm_action_t *action) 
{
	const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC);

	if(target_rc_s != NULL) {
		return crm_parse_int(target_rc_s, "0");
	}
	return 0;
}
Пример #11
0
int
cli_resource_print_operations(const char *rsc_id, const char *host_uname, bool active,
                         pe_working_set_t * data_set)
{
    resource_t *rsc = NULL;
    int opts = pe_print_printf | pe_print_rsconly | pe_print_suppres_nl;
    GListPtr ops = find_operations(rsc_id, host_uname, active, data_set);
    GListPtr lpc = NULL;

    if (print_pending) {
        opts |= pe_print_pending;
    }

    for (lpc = ops; lpc != NULL; lpc = lpc->next) {
        xmlNode *xml_op = (xmlNode *) lpc->data;

        const char *op_rsc = crm_element_value(xml_op, "resource");
        const char *last = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
        const char *status_s = crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS);
        const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
        int status = crm_parse_int(status_s, "0");

        rsc = pe_find_resource(data_set->resources, op_rsc);
        if(rsc) {
            rsc->fns->print(rsc, "", opts, stdout);
        } else {
            fprintf(stdout, "Unknown resource %s", op_rsc);
        }

        fprintf(stdout, ": %s (node=%s, call=%s, rc=%s",
                op_key ? op_key : ID(xml_op),
                crm_element_value(xml_op, XML_ATTR_UNAME),
                crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
                crm_element_value(xml_op, XML_LRM_ATTR_RC));
        if (last) {
            time_t run_at = crm_parse_int(last, "0");

            fprintf(stdout, ", last-rc-change=%s, exec=%sms",
                    crm_strip_trailing_newline(ctime(&run_at)), crm_element_value(xml_op, XML_RSC_OP_T_EXEC));
        }
        fprintf(stdout, "): %s\n", services_lrm_status_str(status));
    }
    return pcmk_ok;
}
Пример #12
0
static void
check_capacity(gpointer key, gpointer value, gpointer user_data)
{
    int required = 0;
    int remaining = 0;
    struct capacity_data *data = user_data;

    required = crm_parse_int(value, "0");
    remaining = crm_parse_int(g_hash_table_lookup(data->node->details->utilization, key), "0");

    if (required > remaining) {
        CRM_ASSERT(data->rsc_id);
        CRM_ASSERT(data->node);

        crm_debug("Node %s has no enough %s for %s: required=%d remaining=%d",
                  data->node->details->uname, (char *)key, data->rsc_id, required, remaining);
        data->is_enough = FALSE;
    }
}
Пример #13
0
gint
cib_GCompareFunc(gconstpointer a, gconstpointer b)
{
    const xmlNode *a_msg = a;
    const xmlNode *b_msg = b;

    int msg_a_id = 0;
    int msg_b_id = 0;
    const char *value = NULL;

    value = crm_element_value_const(a_msg, F_CIB_CALLID);
    msg_a_id = crm_parse_int(value, NULL);

    value = crm_element_value_const(b_msg, F_CIB_CALLID);
    msg_b_id = crm_parse_int(value, NULL);

    if (msg_a_id == msg_b_id) {
        return 0;
    } else if (msg_a_id < msg_b_id) {
        return -1;
    }
    return 1;
}
Пример #14
0
static unsigned int
pick_ipc_buffer(int max)
{
    static int global_max = 0;

    if(global_max == 0) {
        const char *env = getenv("PCMK_ipc_buffer");

        if (env) {
            global_max = crm_parse_int(env, "0");
        } else {
            global_max = MAX_MSG_SIZE;
        }
    }

    return QB_MAX(max, global_max);
}
Пример #15
0
cib_t *
cib_new(void)
{
    const char *value = getenv("CIB_shadow");

    if (value && value[0] != 0) {
        return cib_shadow_new(value);
    }

    value = getenv("CIB_file");
    if (value) {
        return cib_file_new(value);
    }

    value = getenv("CIB_port");
    if (value) {
        gboolean encrypted = TRUE;
        int port = crm_parse_int(value, NULL);
        const char *server = getenv("CIB_server");
        const char *user = getenv("CIB_user");
        const char *pass = getenv("CIB_passwd");

        value = getenv("CIB_encrypted");
        if (value && crm_is_true(value) == FALSE) {
            crm_info("Disabling TLS");
            encrypted = FALSE;
        }

        if (user == NULL) {
            user = CRM_DAEMON_USER;
            crm_info("Defaulting to user: %s", user);
        }

        if (server == NULL) {
            server = "localhost";
            crm_info("Defaulting to localhost");
        }

        return cib_remote_new(server, user, pass, port, encrypted);
    }

    return cib_native_new();
}
Пример #16
0
static void CancelXmlOp(resource_t *rsc, xmlNode *xml_op, node_t *active_node,
			const char *reason, pe_working_set_t *data_set) 
{
    int interval = 0;
    action_t *cancel = NULL;

    char *key = NULL;
    const char *task = NULL;
    const char *call_id = NULL;
    const char *op_version = NULL;
    const char *interval_s = NULL;
    
    CRM_CHECK(xml_op != NULL, return);
    CRM_CHECK(active_node != NULL, return);

    task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
    call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
    op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
    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);
    
    crm_info("Action %s on %s will be stopped: %s",
	     key, active_node->details->uname, reason?reason:"unknown");

    cancel = custom_action(rsc, crm_strdup(key), RSC_CANCEL,
			   active_node, FALSE, TRUE, data_set);

    crm_free(cancel->task);
    cancel->task = crm_strdup(RSC_CANCEL);
    
    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;
}
Пример #17
0
static void
do_compare_capacity2(gpointer key, gpointer value, gpointer user_data)
{
    int node1_capacity = 0;
    int node2_capacity = 0;
    struct compare_data *data = user_data;

    if (g_hash_table_lookup_extended(data->node1->details->utilization, key, NULL, NULL)) {
        return;
    }

    node1_capacity = 0;
    node2_capacity = crm_parse_int(value, "0");

    if (node1_capacity > node2_capacity) {
        data->result--;
    } else if (node1_capacity < node2_capacity) {
        data->result++;
    }
}
Пример #18
0
static int
pick_ipc_buffer(int max)
{
    const char *env = getenv("PCMK_ipc_buffer");

    if(env) {
        max = crm_parse_int(env, "0");
    }

    if(max <= 0) {
        max = MAX_MSG_SIZE;
    }

    if(max < MIN_MSG_SIZE) {
        max = MIN_MSG_SIZE;
    }

    crm_trace("Using max message size of %d", max);
    return max;
}
Пример #19
0
static enum crmd_fsa_input
handle_failcount_op(xmlNode * stored_msg)
{
    const char *rsc = NULL;
    const char *uname = NULL;
    const char *op = NULL;
    const char *interval = NULL;
    int interval_ms = 0;
    gboolean is_remote_node = FALSE;
    xmlNode *xml_op = get_message_xml(stored_msg, F_CRM_DATA);

    if (xml_op) {
        xmlNode *xml_rsc = first_named_child(xml_op, XML_CIB_TAG_RESOURCE);
        xmlNode *xml_attrs = first_named_child(xml_op, XML_TAG_ATTRS);

        if (xml_rsc) {
            rsc = ID(xml_rsc);
        }
        if (xml_attrs) {
            op = crm_element_value(xml_attrs,
                                   CRM_META "_" XML_RSC_ATTR_CLEAR_OP);
            interval = crm_element_value(xml_attrs,
                                         CRM_META "_" XML_RSC_ATTR_CLEAR_INTERVAL);
            interval_ms = crm_parse_int(interval, "0");
        }
    }
    uname = crm_element_value(xml_op, XML_LRM_ATTR_TARGET);

    if ((rsc == NULL) || (uname == NULL)) {
        crm_log_xml_warn(stored_msg, "invalid failcount op");
        return I_NULL;
    }

    if (crm_element_value(xml_op, XML_LRM_ATTR_ROUTER_NODE)) {
        is_remote_node = TRUE;
    }
    update_attrd_clear_failures(uname, rsc, op, interval, is_remote_node);
    lrm_clear_last_failure(rsc, uname, op, interval_ms);

    return I_NULL;
}
Пример #20
0
int
char2score(const char *score) 
{
	int score_f = 0;
	
	if(score == NULL) {
		
	} else if(safe_str_eq(score, MINUS_INFINITY_S)) {
		score_f = -node_score_infinity;
		
	} else if(safe_str_eq(score, INFINITY_S)) {
		score_f = node_score_infinity;
		
	} else if(safe_str_eq(score, "+"INFINITY_S)) {
		score_f = node_score_infinity;
		
	} else if(safe_str_eq(score, "red")) {
		score_f = node_score_red;

	} else if(safe_str_eq(score, "yellow")) {
		score_f = node_score_yellow;

	} else if(safe_str_eq(score, "green")) {
		score_f = node_score_green;

	} else {
		score_f = crm_parse_int(score, NULL);
		if(score_f > 0 && score_f > node_score_infinity) {
			score_f = node_score_infinity;
			
		} else if(score_f < 0 && score_f < -node_score_infinity) {
			score_f = -node_score_infinity;
		}
	}
	
	return score_f;
}
Пример #21
0
gboolean
test_attr_expression(xmlNode * expr, GHashTable * hash, crm_time_t * now)
{
    gboolean accept = FALSE;
    int cmp = 0;
    const char *h_val = NULL;

    const char *op = NULL;
    const char *type = NULL;
    const char *attr = NULL;
    const char *value = NULL;

    attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE);
    op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION);
    value = crm_element_value(expr, XML_EXPR_ATTR_VALUE);
    type = crm_element_value(expr, XML_EXPR_ATTR_TYPE);

    if (attr == NULL || op == NULL) {
        pe_err("Invlaid attribute or operation in expression"
               " (\'%s\' \'%s\' \'%s\')", crm_str(attr), crm_str(op), crm_str(value));
        return FALSE;
    }

    if (hash != NULL) {
        h_val = (const char *)g_hash_table_lookup(hash, attr);
    }

    if (value != NULL && h_val != NULL) {
        if (type == NULL) {
            if (safe_str_eq(op, "lt")
                || safe_str_eq(op, "lte")
                || safe_str_eq(op, "gt")
                || safe_str_eq(op, "gte")) {
                type = "number";

            } else {
                type = "string";
            }
            crm_trace("Defaulting to %s based comparison for '%s' op", type, op);
        }

        if (safe_str_eq(type, "string")) {
            cmp = strcasecmp(h_val, value);

        } else if (safe_str_eq(type, "number")) {
            int h_val_f = crm_parse_int(h_val, NULL);
            int value_f = crm_parse_int(value, NULL);

            if (h_val_f < value_f) {
                cmp = -1;
            } else if (h_val_f > value_f) {
                cmp = 1;
            } else {
                cmp = 0;
            }

        } else if (safe_str_eq(type, "version")) {
            cmp = compare_version(h_val, value);

        }

    } else if (value == NULL && h_val == NULL) {
        cmp = 0;
    } else if (value == NULL) {
        cmp = 1;
    } else {
        cmp = -1;
    }

    if (safe_str_eq(op, "defined")) {
        if (h_val != NULL) {
            accept = TRUE;
        }

    } else if (safe_str_eq(op, "not_defined")) {
        if (h_val == NULL) {
            accept = TRUE;
        }

    } else if (safe_str_eq(op, "eq")) {
        if ((h_val == value) || cmp == 0) {
            accept = TRUE;
        }

    } else if (safe_str_eq(op, "ne")) {
        if ((h_val == NULL && value != NULL)
            || (h_val != NULL && value == NULL)
            || cmp != 0) {
            accept = TRUE;
        }

    } else if (value == NULL || h_val == NULL) {
        /* the comparision is meaningless from this point on */
        accept = FALSE;

    } else if (safe_str_eq(op, "lt")) {
        if (cmp < 0) {
            accept = TRUE;
        }

    } else if (safe_str_eq(op, "lte")) {
        if (cmp <= 0) {
            accept = TRUE;
        }

    } else if (safe_str_eq(op, "gt")) {
        if (cmp > 0) {
            accept = TRUE;
        }

    } else if (safe_str_eq(op, "gte")) {
        if (cmp >= 0) {
            accept = TRUE;
        }
    }

    return accept;
}
Пример #22
0
static char *
create_action_name(action_t * action)
{
    char *action_name = NULL;
    const char *prefix = NULL;
    const char *action_host = NULL;
    const char *task = action->task;

    if (action->node) {
        action_host = action->node->details->uname;
    } else if (is_not_set(action->flags, pe_action_pseudo)) {
        action_host = "<none>";
    }

    if (safe_str_eq(action->task, RSC_CANCEL)) {
        prefix = "Cancel ";
        task = "monitor";       /* TO-DO: Hack! */
    }

    if (action->rsc && action->rsc->clone_name) {
        char *key = NULL;
        const char *name = action->rsc->clone_name;
        const char *interval_s = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL);

        int interval = crm_parse_int(interval_s, "0");

        if (safe_str_eq(action->task, RSC_NOTIFY)
                || safe_str_eq(action->task, RSC_NOTIFIED)) {
            const char *n_type = g_hash_table_lookup(action->meta, "notify_key_type");
            const char *n_task = g_hash_table_lookup(action->meta, "notify_key_operation");

            CRM_ASSERT(n_type != NULL);
            CRM_ASSERT(n_task != NULL);
            key = generate_notify_key(name, n_type, n_task);

        } else {
            key = generate_op_key(name, task, interval);
        }

        if (action_host) {
            action_name = crm_strdup_printf("%s%s %s", prefix ? prefix : "", key, action_host);
        } else {
            action_name = crm_strdup_printf("%s%s", prefix ? prefix : "", key);
        }
        free(key);

    } else if (safe_str_eq(action->task, CRM_OP_FENCE)) {
        const char *op = g_hash_table_lookup(action->meta, "stonith_action");

        action_name = crm_strdup_printf("%s%s '%s' %s", prefix ? prefix : "", action->task, op, action_host);

    } else if (action->rsc && action_host) {
        action_name = crm_strdup_printf("%s%s %s", prefix ? prefix : "", action->uuid, action_host);

    } else if (action_host) {
        action_name = crm_strdup_printf("%s%s %s", prefix ? prefix : "", action->task, action_host);

    } else {
        action_name = crm_strdup_printf("%s", action->uuid);
    }

    if(action_numbers) {
        char *with_id = crm_strdup_printf("%s (%d)", action_name, action->id);

        free(action_name);
        action_name = with_id;
    }
    return action_name;
}
Пример #23
0
/**
 * This is the main function to update resource table v2.
 * Return the number of resources.
 */
static int
update_resources_recursively(GListPtr reslist, GListPtr nodelist, int index)
{
    GListPtr gIter1 = NULL;

    if (reslist == NULL) {
        return index;
    }
    /*
     * Set resource info to resource table v2 from data_set,
     * and add it to Glib's array.
     */
    for(gIter1 = reslist; gIter1 != NULL; gIter1 = gIter1->next) {
        resource_t *rsc = gIter1->data;
        GListPtr gIter2 = NULL;

        cl_log(LOG_DEBUG, "resource %s processing.", rsc->id);

        for(gIter2 = nodelist; gIter2 != NULL; gIter2 = gIter2->next) {
            node_t *node = gIter2->data;
            struct hb_rsinfov2 *rsinfo;
            enum rsc_role_e rsstate;

            rsinfo = (struct hb_rsinfov2 *) malloc(sizeof(struct hb_rsinfov2));
            if (!rsinfo) {
                cl_log(LOG_CRIT, "malloc resource info v2 failed.");
                return HA_FAIL;
            }

            rsinfo->resourceid = strdup(rsc->id);
            rsinfo->type = PE_OBJ_TYPES2AGENTTYPE(rsc->variant);

            /* using a temp var to suppress casting warning of the compiler */
            rsstate = rsc->fns->state(rsc, TRUE);
            {
                GListPtr running_on_nodes = NULL;

                rsc->fns->location(rsc, &running_on_nodes, TRUE);
                if (pe_find_node_id(
                    running_on_nodes, node->details->id) == NULL) {
                    /*
                     * if the resource is not running on current node,
                     * its status is "stopped(1)".
                     */
                    rsstate = RSC_ROLE_STOPPED;
                }
               g_list_free(running_on_nodes);
            }
            rsinfo->status = RSC_ROLE_E2AGENTSTATUS(rsstate);
            rsinfo->node = strdup(node->details->uname);

            if (is_not_set(rsc->flags, pe_rsc_managed)) {
                rsinfo->is_managed = LHARESOURCEISMANAGED_UNMANAGED;
            } else {
                rsinfo->is_managed = LHARESOURCEISMANAGED_MANAGED;
            }

            /* get fail-count from <status> */
            {
                char *attr_name = NULL;
                char *attr_value = NULL;
                crm_data_t *tmp_xml = NULL;

                attr_name = crm_concat("fail-count", rsinfo->resourceid, '-');
                attr_value = g_hash_table_lookup(node->details->attrs,
                    attr_name); 
                rsinfo->failcount = crm_parse_int(attr_value, "0");
                free(attr_name);
                free_xml(tmp_xml);
             }

            if (rsc->parent != NULL) {
                rsinfo->parent = strdup(rsc->parent->id);
            } else {
                rsinfo->parent = strdup("");
            }

            /*
             * if the resource stops, and its fail-count is 0,
             * don't list it up.
             */ 
            if (rsinfo->status != LHARESOURCESTATUS_STOPPED || 
                   rsinfo->failcount > 0) {
                rsinfo->index = index++;
                g_ptr_array_add(gResourceTableV2, (gpointer *)rsinfo);
            } else {
                free(rsinfo->resourceid);
                free(rsinfo->node);
                free(rsinfo->parent);
                free(rsinfo);
            }

        } /* end slist_iter(node) */

        /* add resources recursively for group/clone/master */
        index = update_resources_recursively(rsc->children,
            nodelist, index);

    } /* end slist_iter(rsc) */

    return index;
}
Пример #24
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;
}
Пример #25
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_CHECK(diff != NULL, return FALSE);
    CRM_CHECK(old != NULL, return FALSE);

    value = crm_element_value(old, XML_ATTR_GENERATION_ADMIN);
    this_admin_epoch = crm_parse_int(value, "0");
    crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION_ADMIN, this_admin_epoch, value);

    value = crm_element_value(old, XML_ATTR_GENERATION);
    this_epoch = crm_parse_int(value, "0");
    crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION, this_epoch, value);

    value = crm_element_value(old, XML_ATTR_NUMUPDATES);
    this_updates = crm_parse_int(value, "0");
    crm_debug_3("%s=%d (%s)", XML_ATTR_NUMUPDATES, this_updates, value);

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

    value = NULL;
Пример #26
0
static gboolean
check_action_definition(resource_t *rsc, node_t *active_node, xmlNode *xml_op,
			pe_working_set_t *data_set)
{
	char *key = NULL;
	int interval = 0;
	const char *interval_s = NULL;
	
	gboolean did_change = FALSE;

	xmlNode *params_all = NULL;
	xmlNode *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);
    if(safe_str_eq(task, RSC_STOP)) {
	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) {
		xmlNode *op_match = NULL;

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

		if(op_match == NULL && is_set(data_set->flags, pe_flag_stop_action_orphans)) {
			CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set);
			crm_free(key);
			return TRUE;

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

	action = custom_action(rsc, key, task, active_node, TRUE, FALSE, data_set);
	/* key is free'd by custom_action() */
	
	local_rsc_params = g_hash_table_new_full(
		g_str_hash, g_str_equal,
		g_hash_destroy_str, g_hash_destroy_str);
	
	get_rsc_attributes(local_rsc_params, rsc, active_node, data_set);
	
	params_all = create_xml_node(NULL, XML_TAG_PARAMS);
	g_hash_table_foreach(local_rsc_params, hash2field, params_all);
	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, 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(interval == 0 && safe_str_eq(task, RSC_STATUS)) {
	/* Reload based on the start action not a probe */
	task = RSC_START;
	}
    
    if(digest_restart) {
	/* Changes that force a 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;
			key = generate_op_key(rsc->id, task, interval);
			crm_log_xml_info(params_restart, "params:restart");
	    crm_info("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));
			
			custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
			goto cleanup;
		}
	}

	if(safe_str_neq(digest_all_calc, digest_all)) {
	/* Changes that can potentially be handled by a reload */
		did_change = TRUE;
		crm_log_xml_info(params_all, "params:reload");
		key = generate_op_key(rsc->id, task, interval);
		crm_info("Parameters to %s on %s changed: recorded %s vs. %s (reload:%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));

	if(interval > 0) {
            action_t *op = NULL;
#if 0
	    /* Always reload/restart the entire resource */
	    op = custom_action(rsc, start_key(rsc), RSC_START, NULL, FALSE, TRUE, data_set);
	    update_action_flags(op, pe_action_allow_reload_conversion);
#else
	    /* Re-sending the recurring op is sufficient - the old one will be cancelled automatically */
	    op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
	    custom_action_order(rsc, start_key(rsc), NULL,
				NULL, NULL, op, pe_order_runnable_left, data_set);
#endif
	    
	} else if(digest_restart) {
	    crm_debug_2("Reloading '%s' action for resource %s", task, rsc->id);

            /* Allow this resource to reload - unless something else causes a full restart */
            set_bit(rsc->flags, pe_rsc_try_reload);

            /* Create these for now, it keeps the action IDs the same in the regression outputs */
            custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);

	} else {
	    crm_debug_2("Resource %s doesn't know how to reload", rsc->id);

	    /* Re-send the start/demote/promote op
	     * Recurring ops will be detected independantly
	     */
	    custom_action(rsc, key, task, NULL, FALSE, TRUE, 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;
}
Пример #27
0
gboolean
clone_unpack(resource_t * rsc, pe_working_set_t * data_set)
{
    int lpc = 0;
    const char *type = NULL;
    int num_xml_children = 0;
    xmlNode *a_child = NULL;
    xmlNode *xml_obj = rsc->xml;
    clone_variant_data_t *clone_data = NULL;

    const char *ordered = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ORDERED);
    const char *interleave = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERLEAVE);
    const char *max_clones = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_MAX);
    const char *max_clones_node = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION_NODEMAX);

    pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);

    clone_data = calloc(1, sizeof(clone_variant_data_t));
    rsc->variant_opaque = clone_data;
    clone_data->interleave = FALSE;
    clone_data->ordered = FALSE;

    clone_data->active_clones = 0;
    clone_data->xml_obj_child = NULL;
    clone_data->clone_node_max = crm_parse_int(max_clones_node, "1");

    if (max_clones) {
        clone_data->clone_max = crm_parse_int(max_clones, "1");

    } else if (g_list_length(data_set->nodes) > 0) {
        clone_data->clone_max = g_list_length(data_set->nodes);

    } else {
        clone_data->clone_max = 1;      /* Handy during crm_verify */
    }

    if (crm_is_true(interleave)) {
        clone_data->interleave = TRUE;
    }
    if (crm_is_true(ordered)) {
        clone_data->ordered = TRUE;
    }
    if ((rsc->flags & pe_rsc_unique) == 0 && clone_data->clone_node_max > 1) {
        crm_config_err("Anonymous clones (%s) may only support one copy per node", rsc->id);
        clone_data->clone_node_max = 1;
    }

    pe_rsc_trace(rsc, "Options for %s", rsc->id);
    pe_rsc_trace(rsc, "\tClone max: %d", clone_data->clone_max);
    pe_rsc_trace(rsc, "\tClone node max: %d", clone_data->clone_node_max);
    pe_rsc_trace(rsc, "\tClone is unique: %s",
                 is_set(rsc->flags, pe_rsc_unique) ? "true" : "false");

    clone_data->xml_obj_child = find_xml_node(xml_obj, XML_CIB_TAG_GROUP, FALSE);

    if (clone_data->xml_obj_child == NULL) {
        clone_data->xml_obj_child = find_xml_node(xml_obj, XML_CIB_TAG_RESOURCE, TRUE);
        for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next_element(a_child)) {
            if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_RESOURCE, TRUE)) {
                num_xml_children++;
            }
        }
    }

    if (clone_data->xml_obj_child == NULL) {
        crm_config_err("%s has nothing to clone", rsc->id);
        return FALSE;
    }

    for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next_element(a_child)) {
        if (crm_str_eq((const char *)a_child->name, type, TRUE)) {
            num_xml_children++;
        }
    }

    if (num_xml_children > 1) {
        crm_config_err("%s has too many children.  Only the first (%s) will be cloned.",
                       rsc->id, ID(clone_data->xml_obj_child));
    }

    /*
     * Make clones ever so slightly sticky by default
     *
     * This helps ensure clone instances are not shuffled around the cluster
     * for no benefit in situations when pre-allocation is not appropriate
     */
    if (g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_STICKINESS) == NULL) {
        add_hash_param(rsc->meta, XML_RSC_ATTR_STICKINESS, "1");
    }

    pe_rsc_trace(rsc, "\tClone is unique (fixed): %s",
                 is_set(rsc->flags, pe_rsc_unique) ? "true" : "false");
    clone_data->notify_confirm = is_set(rsc->flags, pe_rsc_notify);
    add_hash_param(rsc->meta, XML_RSC_ATTR_UNIQUE,
                   is_set(rsc->flags, pe_rsc_unique) ? XML_BOOLEAN_TRUE : XML_BOOLEAN_FALSE);

    for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
        if (create_child_clone(rsc, lpc, data_set) == NULL) {
            return FALSE;
        }
    }

    if (clone_data->clone_max == 0) {
        /* create one so that unpack_find_resource() will hook up
         * any orphans up to the parent correctly
         */
        if (create_child_clone(rsc, -1, data_set) == NULL) {
            return FALSE;
        }
    }

    pe_rsc_trace(rsc, "Added %d children to resource %s...", clone_data->clone_max, rsc->id);
    return TRUE;
}
Пример #28
0
int
main(int argc, char **argv)
{
    int argerr = 0;
    int flag;
    int attempts = 0;

#ifdef HAVE_GETOPT_H
    int option_index = 0;

    static struct option long_options[] = {
        /* Top-level Options */
        {"verbose", 0, 0, 'V'},
        {"help", 0, 0, '?'},
        {"log-diffs", 0, 0, 'd'},
        {"log-updates", 0, 0, 'u'},
        {"max-conn-fail", 1, 0, 'm'},
        {0, 0, 0, 0}
    };
#endif

    crm_log_cli_init("cibmon");

    crm_signal(SIGTERM, cibmon_shutdown);

    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 'V':
                crm_bump_log_level(argc, argv);
                break;
            case '?':
                usage(crm_system_name, EX_OK);
                break;
            case 'd':
                log_diffs = TRUE;
                break;
            case 'u':
                log_updates = TRUE;
                break;
            case 'm':
                max_failures = crm_parse_int(optarg, "30");
                break;
            default:
                printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag);
                ++argerr;
                break;
        }
    }

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

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

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

    cib = cib_new();

    do {
        sleep(1);
        exit_code = cib->cmds->signon(cib, crm_system_name, cib_query);

    } while (exit_code == -ENOTCONN && attempts++ < max_failures);

    if (exit_code != pcmk_ok) {
        crm_err("Signon to CIB failed: %s", pcmk_strerror(exit_code));
    }

    if (exit_code == pcmk_ok) {
        crm_debug("Setting dnotify");
        exit_code = cib->cmds->set_connection_dnotify(cib, cib_connection_destroy);
    }

    crm_debug("Setting diff callback");
    exit_code = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, cibmon_diff);

    if (exit_code != pcmk_ok) {
        crm_err("Failed to set %s callback: %s", T_CIB_DIFF_NOTIFY, pcmk_strerror(exit_code));
    }

    if (exit_code != pcmk_ok) {
        crm_err("Setup failed, could not monitor CIB actions");
        return -exit_code;
    }

    mainloop = g_main_new(FALSE);
    crm_info("Starting mainloop");
    g_main_run(mainloop);
    crm_trace("%s exiting normally", crm_system_name);
    fflush(stderr);
    return -exit_code;
}
Пример #29
0
static synapse_t *
unpack_synapse(crm_graph_t * new_graph, xmlNode * xml_synapse)
{
    const char *value = NULL;
    xmlNode *inputs = NULL;
    xmlNode *action_set = NULL;
    synapse_t *new_synapse = NULL;

    CRM_CHECK(xml_synapse != NULL, return NULL);
    crm_trace("looking in synapse %s", ID(xml_synapse));

    new_synapse = calloc(1, sizeof(synapse_t));
    new_synapse->id = crm_parse_int(ID(xml_synapse), NULL);

    value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
    if (value != NULL) {
        new_synapse->priority = crm_parse_int(value, NULL);
    }

    new_graph->num_synapses++;
    CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
              return NULL);

    crm_trace("look for actions in synapse %s", crm_element_value(xml_synapse, XML_ATTR_ID));

    for (action_set = __xml_first_child(xml_synapse); action_set != NULL;
         action_set = __xml_next(action_set)) {
        if (crm_str_eq((const char *)action_set->name, "action_set", TRUE)) {
            xmlNode *action = NULL;

            for (action = __xml_first_child(action_set); action != NULL;
                 action = __xml_next(action)) {
                crm_action_t *new_action = unpack_action(new_synapse, action);

                new_graph->num_actions++;

                if (new_action == NULL) {
                    continue;
                }
                crm_trace("Adding action %d to synapse %d", new_action->id, new_synapse->id);

                new_synapse->actions = g_list_append(new_synapse->actions, new_action);
            }
        }
    }

    crm_trace("look for inputs in synapse %s", ID(xml_synapse));

    for (inputs = __xml_first_child(xml_synapse); inputs != NULL; inputs = __xml_next(inputs)) {
        if (crm_str_eq((const char *)inputs->name, "inputs", TRUE)) {
            xmlNode *trigger = NULL;

            for (trigger = __xml_first_child(inputs); trigger != NULL;
                 trigger = __xml_next(trigger)) {
                xmlNode *input = NULL;

                for (input = __xml_first_child(trigger); input != NULL; input = __xml_next(input)) {
                    crm_action_t *new_input = unpack_action(new_synapse, input);

                    if (new_input == NULL) {
                        continue;
                    }

                    crm_trace("Adding input %d to synapse %d", new_input->id, new_synapse->id);

                    new_synapse->inputs = g_list_append(new_synapse->inputs, new_input);
                }
            }
        }
    }

    return new_synapse;
}
Пример #30
0
void
te_update_diff(const char *event, xmlNode *msg)
{
	int rc = -1;
	const char *op = NULL;

	xmlNode *diff = NULL;
	xmlNode *cib_top = NULL;
	xmlXPathObject *xpathObj = NULL;

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

	int diff_del_updates     = 0;
	int diff_del_epoch       = 0;
	int diff_del_admin_epoch = 0;
	
	CRM_CHECK(msg != NULL, return);
	crm_element_value_int(msg, F_CIB_RC, &rc);	

	if(transition_graph == NULL) {
	    crm_debug_3("No graph");
	    return;

	} else if(rc < cib_ok) {
	    crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc));
	    return;

	} else if(transition_graph->complete == TRUE
		  && fsa_state != S_IDLE
		  && fsa_state != S_TRANSITION_ENGINE
		  && fsa_state != S_POLICY_ENGINE) {
	    crm_debug_2("Filter state=%s, complete=%d", fsa_state2string(fsa_state), transition_graph->complete);
	    return;
	} 	

	op = crm_element_value(msg, F_CIB_OPERATION);
	diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);

	cib_diff_version_details(
		diff,
		&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, 
		&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
	
	crm_debug("Processing diff (%s): %d.%d.%d -> %d.%d.%d (%s)", op,
		  diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
		  diff_add_admin_epoch,diff_add_epoch,diff_add_updates,
		  fsa_state2string(fsa_state));
	log_cib_diff(LOG_DEBUG_2, diff, op);

	/* Process anything that was added */
	cib_top = get_xpath_object("//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_TAG_CIB, diff, LOG_ERR);
	if(need_abort(cib_top)) {
	    goto bail; /* configuration changed */
	}

	/* Process anything that was removed */
	cib_top = get_xpath_object("//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_REMOVED"//"XML_TAG_CIB, diff, LOG_ERR);
	if(need_abort(cib_top)) {
	    goto bail; /* configuration changed */
	}

	/* Transient Attributes - Added/Updated */
	xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_TAG_TRANSIENT_NODEATTRS"//"XML_CIB_TAG_NVPAIR);
	if(xpathObj && xpathObj->nodesetval->nodeNr > 0) {
	    int lpc;
	    for(lpc = 0; lpc < xpathObj->nodesetval->nodeNr; lpc++) {
		xmlNode *attr = getXpathResult(xpathObj, lpc);
		const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
		const char *value = NULL;
		
		if(safe_str_eq(CRM_OP_PROBED, name)) {
		    value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE);
		}

		if(crm_is_true(value) == FALSE) {
		    abort_transition(INFINITY, tg_restart, "Transient attribute: update", attr);
		    crm_log_xml_debug_2(attr, "Abort");
		    goto bail;
		}
	    }

	} else if(xpathObj) {
	    xmlXPathFreeObject(xpathObj);
	}
	
	/* Transient Attributes - Removed */
	xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_REMOVED"//"XML_TAG_TRANSIENT_NODEATTRS);
	if(xpathObj && xpathObj->nodesetval->nodeNr > 0) {
	    xmlNode *aborted = getXpathResult(xpathObj, 0);
	    abort_transition(INFINITY, tg_restart, "Transient attribute: removal", aborted);
	    goto bail;

	} else if(xpathObj) {
	    xmlXPathFreeObject(xpathObj);
	}

	/* Check for node state updates... possibly from a shutdown we requested */
	xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_STATE);
	if(xpathObj) {
	    int lpc = 0, max = xpathObj->nodesetval->nodeNr;
	    for(lpc = 0; lpc < max; lpc++) {
		xmlNode *node = getXpathResult(xpathObj, lpc);
		const char *event_node = crm_element_value(node, XML_ATTR_ID);
		const char *ccm_state  = crm_element_value(node, XML_CIB_ATTR_INCCM);
		const char *ha_state   = crm_element_value(node, XML_CIB_ATTR_HASTATE);
		const char *shutdown_s = crm_element_value(node, XML_CIB_ATTR_SHUTDOWN);
		const char *crmd_state = crm_element_value(node, XML_CIB_ATTR_CRMDSTATE);

		if(safe_str_eq(ccm_state, XML_BOOLEAN_FALSE)
		   || safe_str_eq(ha_state, DEADSTATUS)
		   || safe_str_eq(crmd_state, CRMD_JOINSTATE_DOWN)) {
		    crm_action_t *shutdown = match_down_event(0, event_node, NULL);
		    
		    if(shutdown != NULL) {
			const char *task = crm_element_value(shutdown->xml, XML_LRM_ATTR_TASK);
			if(safe_str_neq(task, CRM_OP_FENCE)) {
			    /* Wait for stonithd to tell us it is complete via tengine_stonith_callback() */
			    update_graph(transition_graph, shutdown);
			    trigger_graph();
			}
			
		    } else {
			crm_info("Stonith/shutdown of %s not matched", event_node);
			abort_transition(INFINITY, tg_restart, "Node failure", node);
		    }			
		    fail_incompletable_actions(transition_graph, event_node);
		}
	 
		if(shutdown_s) {
		    int shutdown = crm_parse_int(shutdown_s, NULL);
		    if(shutdown > 0) {
			crm_info("Aborting on "XML_CIB_ATTR_SHUTDOWN" attribute for %s", event_node);
			abort_transition(INFINITY, tg_restart, "Shutdown request", node);
		    }
		}
	    }
	    xmlXPathFreeObject(xpathObj);
	}

	/*
	 * Check for and fast-track the processing of LRM refreshes
	 * In large clusters this can result in _huge_ speedups
	 *
	 * Unfortunately we can only do so when there are no pending actions
	 * Otherwise we could miss updates we're waiting for and stall 
	 *
	 */
	xpathObj = NULL;
	if(transition_graph->pending == 0) {
	    xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_LRM_TAG_RESOURCE);
	}
	
	if(xpathObj) {
	    int updates = xpathObj->nodesetval->nodeNr;
	    if(updates > 1) {
		/* Updates by, or in response to, TE actions will never contain updates
		 * for more than one resource at a time
		 */
		crm_info("Detected LRM refresh - %d resources updated: Skipping all resource events", updates);
		abort_transition(INFINITY, tg_restart, "LRM Refresh", diff);
		goto bail;
	    }
	    xmlXPathFreeObject(xpathObj);
	}

	/* Process operation updates */
	xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_LRM_TAG_RSC_OP);
	if(xpathObj) {
	    process_resource_updates(xpathObj);
	    xmlXPathFreeObject(xpathObj);
	}
	
	/* Detect deleted (as opposed to replaced or added) actions - eg. crm_resource -C */ 
	xpathObj = xpath_search(diff, "//"XML_TAG_DIFF_REMOVED"//"XML_LRM_TAG_RSC_OP);
	if(xpathObj) {
	    int lpc = 0, max = xpathObj->nodesetval->nodeNr;
	    
	    for(lpc = 0; lpc < max; lpc++) {
		int max = 0;
		const char *op_id = NULL;
		char *rsc_op_xpath = NULL;
		xmlXPathObject *op_match = NULL;
		xmlNode *match = getXpathResult(xpathObj, lpc);
		CRM_CHECK(match != NULL, continue);

		op_id = ID(match);

		max = strlen(rsc_op_template) + strlen(op_id) + 1;
		crm_malloc0(rsc_op_xpath, max);
		snprintf(rsc_op_xpath, max, rsc_op_template, op_id);
		
		op_match = xpath_search(diff, rsc_op_xpath);
		if(op_match == NULL || op_match->nodesetval->nodeNr == 0) {
		    /* Prevent false positives by matching cancelations too */
		    const char *node = get_node_id(match);
		    crm_action_t *cancelled = get_cancel_action(op_id, node);

		    if(cancelled == NULL) {
			crm_debug("No match for deleted action %s (%s on %s)", rsc_op_xpath, op_id, node);
			abort_transition(INFINITY, tg_restart, "Resource op removal", match);
			if(op_match) {
			    xmlXPathFreeObject(op_match);
			}
			crm_free(rsc_op_xpath);
			goto bail;

		    } else {
			crm_debug("Deleted lrm_rsc_op %s on %s was for graph event %d",
				  op_id, node, cancelled->id);
		    }
		}

		if(op_match) {
		    xmlXPathFreeObject(op_match);
		}
		crm_free(rsc_op_xpath);
	    }
	}

  bail:
	if(xpathObj) {
	    xmlXPathFreeObject(xpathObj);
	}
}