Пример #1
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;
}
Пример #2
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;
}