Page MenuHomeClusterLabs Projects

utils.c
No OneTemporary

/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <lha_internal.h>
#include <crm/msg_xml.h>
#include <allocate.h>
#include <utils.h>
#include <lib/crm/pengine/utils.h>
void
print_rsc_to_node(const char *pre_text, rsc_to_node_t *cons, gboolean details)
{
if(cons == NULL) {
crm_debug_4("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_debug_4("%s%s%s Constraint %s (%p) - %d nodes:",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
"rsc_to_node",
cons->id, cons,
g_list_length(cons->node_list_rh));
if(details == FALSE) {
crm_debug_4("\t%s (node placement rule)",
safe_val3(NULL, cons, rsc_lh, id));
slist_iter(
node, node_t, cons->node_list_rh, lpc,
print_node("\t\t-->", node, FALSE)
);
}
}
void
print_rsc_colocation(const char *pre_text, rsc_colocation_t *cons, gboolean details)
{
if(cons == NULL) {
crm_debug_4("%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
crm_debug_4("%s%s%s Constraint %s (%p):",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
XML_CONS_TAG_RSC_DEPEND, cons->id, cons);
if(details == FALSE) {
crm_debug_4("\t%s --> %s, %d",
safe_val3(NULL, cons, rsc_lh, id),
safe_val3(NULL, cons, rsc_rh, id),
cons->score);
}
}
void
pe_free_ordering(GListPtr constraints)
{
GListPtr iterator = constraints;
while(iterator != NULL) {
order_constraint_t *order = iterator->data;
iterator = iterator->next;
crm_free(order->lh_action_task);
crm_free(order->rh_action_task);
crm_free(order);
}
if(constraints != NULL) {
g_list_free(constraints);
}
}
void
pe_free_rsc_to_node(GListPtr constraints)
{
GListPtr iterator = constraints;
while(iterator != NULL) {
rsc_to_node_t *cons = iterator->data;
iterator = iterator->next;
pe_free_shallow(cons->node_list_rh);
crm_free(cons);
}
if(constraints != NULL) {
g_list_free(constraints);
}
}
rsc_to_node_t *
rsc2node_new(const char *id, resource_t *rsc,
int node_weight, node_t *foo_node, pe_working_set_t *data_set)
{
rsc_to_node_t *new_con = NULL;
if(rsc == NULL || id == NULL) {
pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
return NULL;
} else if(foo_node == NULL) {
CRM_CHECK(node_weight == 0, return NULL);
}
crm_malloc0(new_con, sizeof(rsc_to_node_t));
if(new_con != NULL) {
new_con->id = id;
new_con->rsc_lh = rsc;
new_con->node_list_rh = NULL;
new_con->role_filter = RSC_ROLE_UNKNOWN;
if(foo_node != NULL) {
node_t *copy = node_copy(foo_node);
copy->weight = node_weight;
new_con->node_list_rh = g_list_append(NULL, copy);
}
data_set->placement_constraints = g_list_append(
data_set->placement_constraints, new_con);
rsc->rsc_location = g_list_append(rsc->rsc_location, new_con);
}
return new_con;
}
const char *
ordering_type2text(enum pe_ordering type)
{
const char *result = "<unknown>";
if(type & pe_order_implies_left) {
/* was: mandatory */
result = "right_implies_left";
} else if(type & pe_order_implies_right) {
/* was: recover */
result = "left_implies_right";
} else if(type & pe_order_optional) {
/* pure ordering, nothing implied */
result = "optional";
} else if(type & pe_order_runnable_left) {
result = "runnable";
} else {
crm_err("Unknown ordering type: %.3x", type);
}
return result;
}
gboolean
can_run_resources(const node_t *node)
{
if(node == NULL) {
return FALSE;
}
if(node->details->online == FALSE
|| node->details->shutdown
|| node->details->unclean
|| node->details->standby) {
crm_debug_2("%s: online=%d, unclean=%d, standby=%d",
node->details->uname, node->details->online,
node->details->unclean, node->details->standby);
return FALSE;
}
return TRUE;
}
/* return -1 if 'a' is more preferred
* return 1 if 'b' is more preferred
*/
gint sort_node_weight(gconstpointer a, gconstpointer b)
{
int level = LOG_DEBUG_3;
const node_t *node1 = (const node_t*)a;
const node_t *node2 = (const node_t*)b;
int node1_weight = 0;
int node2_weight = 0;
if(a == NULL) { return 1; }
if(b == NULL) { return -1; }
node1_weight = node1->weight;
node2_weight = node2->weight;
if(can_run_resources(node1) == FALSE) {
node1_weight = -INFINITY;
}
if(can_run_resources(node2) == FALSE) {
node2_weight = -INFINITY;
}
if(node1_weight > node2_weight) {
do_crm_log(level, "%s (%d) > %s (%d) : weight",
node1->details->uname, node1_weight,
node2->details->uname, node2_weight);
return -1;
}
if(node1_weight < node2_weight) {
do_crm_log(level, "%s (%d) < %s (%d) : weight",
node1->details->uname, node1_weight,
node2->details->uname, node2_weight);
return 1;
}
do_crm_log(level, "%s (%d) == %s (%d) : weight",
node1->details->uname, node1_weight,
node2->details->uname, node2_weight);
/* now try to balance resources across the cluster */
if(node1->details->num_resources
< node2->details->num_resources) {
do_crm_log(level, "%s (%d) < %s (%d) : resources",
node1->details->uname, node1->details->num_resources,
node2->details->uname, node2->details->num_resources);
return -1;
} else if(node1->details->num_resources
> node2->details->num_resources) {
do_crm_log(level, "%s (%d) > %s (%d) : resources",
node1->details->uname, node1->details->num_resources,
node2->details->uname, node2->details->num_resources);
return 1;
}
do_crm_log(level, "%s = %s", node1->details->uname, node2->details->uname);
return 0;
}
gboolean
native_assign_node(resource_t *rsc, GListPtr nodes, node_t *chosen)
{
int multiple = 0;
CRM_ASSERT(rsc->variant == pe_native);
rsc->provisional = FALSE;
slist_iter(candidate, node_t, nodes, lpc,
crm_debug("Color %s, Node[%d] %s: %d", rsc->id, lpc,
candidate->details->uname, candidate->weight);
if(chosen->weight > 0
&& candidate->details->unclean == FALSE
&& candidate->weight == chosen->weight) {
multiple++;
}
);
if(chosen == NULL) {
crm_debug("Could not allocate a node for %s", rsc->id);
rsc->next_role = RSC_ROLE_STOPPED;
return FALSE;
} else if(can_run_resources(chosen) == FALSE || chosen->weight < 0) {
crm_debug("All nodes for resource %s are unavailable"
", unclean or shutting down", rsc->id);
rsc->next_role = RSC_ROLE_STOPPED;
return FALSE;
}
if(rsc->next_role == RSC_ROLE_UNKNOWN) {
rsc->next_role = RSC_ROLE_STARTED;
}
if(multiple > 1) {
int log_level = LOG_INFO;
char *score = score2char(chosen->weight);
if(chosen->weight >= INFINITY) {
log_level = LOG_WARNING;
}
do_crm_log(log_level, "%d nodes with equal score (%s) for"
" running the listed resources (chose %s):",
multiple, score, chosen->details->uname);
crm_free(score);
}
/* todo: update the old node for each resource to reflect its
* new resource count
*/
if(rsc->allocated_to) {
node_t *old = rsc->allocated_to;
old->details->allocated_rsc = g_list_remove(
old->details->allocated_rsc, rsc);
old->details->num_resources--;
old->count--;
}
crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id);
crm_free(rsc->allocated_to);
rsc->allocated_to = node_copy(chosen);
chosen->details->allocated_rsc = g_list_append(chosen->details->allocated_rsc, rsc);
chosen->details->num_resources++;
chosen->count++;
return TRUE;
}
void
convert_non_atomic_task(resource_t *rsc, order_constraint_t *order)
{
int interval = 0;
char *rid = NULL;
char *raw_task = NULL;
int task = no_action;
char *old_uuid = order->lh_action_task;
crm_debug("Processing %s", old_uuid);
if(order->lh_action_task == NULL
|| strstr(order->lh_action_task, "notify") != NULL) {
/* no conversion */
return;
}
CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval));
task = text2task(raw_task);
switch(task) {
case stop_rsc:
case start_rsc:
case action_notify:
case action_promote:
case action_demote:
break;
case stopped_rsc:
case started_rsc:
case action_notified:
case action_promoted:
case action_demoted:
task--;
break;
case monitor_rsc:
case shutdown_crm:
case stonith_node:
task = no_action;
break;
default:
crm_err("Unknown action: %s", raw_task);
task = no_action;
break;
}
if(task != no_action) {
if(rsc->notify) {
order->lh_action_task = generate_notify_key(
rsc->id, "confirmed-post",
task2text(task));
} else {
order->lh_action_task = generate_op_key(
rsc->id, task2text(task+1), 0);
}
crm_debug("Converted %s -> %s",
old_uuid, order->lh_action_task);
crm_free(old_uuid);
}
crm_free(raw_task);
crm_free(rid);
}
void
order_actions(
action_t *lh_action, action_t *rh_action, enum pe_ordering order)
{
action_wrapper_t *wrapper = NULL;
GListPtr list = NULL;
crm_debug_2("Ordering Action %s before %s",
lh_action->uuid, rh_action->uuid);
log_action(LOG_DEBUG_4, "LH (order_actions)", lh_action, FALSE);
log_action(LOG_DEBUG_4, "RH (order_actions)", rh_action, FALSE);
crm_malloc0(wrapper, sizeof(action_wrapper_t));
wrapper->action = rh_action;
wrapper->type = order;
list = lh_action->actions_after;
list = g_list_append(list, wrapper);
lh_action->actions_after = list;
wrapper = NULL;
/* order |= pe_order_implies_right; */
/* order ^= pe_order_implies_right; */
crm_malloc0(wrapper, sizeof(action_wrapper_t));
wrapper->action = lh_action;
wrapper->type = order;
list = rh_action->actions_before;
list = g_list_append(list, wrapper);
rh_action->actions_before = list;
}
void
log_action(unsigned int log_level, const char *pre_text, action_t *action, gboolean details)
{
const char *node_uname = NULL;
const char *node_uuid = NULL;
if(action == NULL) {
do_crm_log(log_level, "%s%s: <NULL>",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ");
return;
}
if(action->pseudo) {
node_uname = NULL;
node_uuid = NULL;
} else if(action->node != NULL) {
node_uname = action->node->details->uname;
node_uuid = action->node->details->id;
} else {
node_uname = "<none>";
node_uuid = NULL;
}
switch(text2task(action->task)) {
case stonith_node:
case shutdown_crm:
do_crm_log(log_level,
"%s%s%sAction %d: %s%s%s%s%s%s",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
action->pseudo?"Pseduo ":action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
action->id, action->uuid,
node_uname?"\ton ":"",
node_uname?node_uname:"",
node_uuid?"\t\t(":"",
node_uuid?node_uuid:"",
node_uuid?")":"");
break;
default:
do_crm_log(log_level,
"%s%s%sAction %d: %s %s%s%s%s%s%s",
pre_text==NULL?"":pre_text,
pre_text==NULL?"":": ",
action->optional?"Optional ":action->pseudo?"Pseduo ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
action->id, action->uuid,
safe_val3("<none>", action, rsc, id),
node_uname?"\ton ":"",
node_uname?node_uname:"",
node_uuid?"\t\t(":"",
node_uuid?node_uuid:"",
node_uuid?")":"");
break;
}
if(details) {
do_crm_log(log_level+1, "\t\t====== Preceeding Actions");
slist_iter(
other, action_wrapper_t, action->actions_before, lpc,
log_action(log_level+1, "\t\t", other->action, FALSE);
);
do_crm_log(log_level+1, "\t\t====== Subsequent Actions");
slist_iter(
other, action_wrapper_t, action->actions_after, lpc,
log_action(log_level+1, "\t\t", other->action, FALSE);
);
do_crm_log(log_level+1, "\t\t====== End");
} else {
do_crm_log(log_level, "\t\t(seen=%d, before=%d, after=%d)",
action->seen_count,
g_list_length(action->actions_before),
g_list_length(action->actions_after));
}
}
resource_t *uber_parent(resource_t *rsc)
{
resource_t *parent = rsc;
while(parent != NULL && parent->parent != NULL) {
parent = parent->parent;
}
return parent;
}
action_t *get_pseudo_op(const char *name, pe_working_set_t *data_set)
{
action_t *op = NULL;
const char *op_s = name;
GListPtr possible_matches = NULL;
possible_matches = find_actions(data_set->actions, name, NULL);
if(possible_matches != NULL) {
if(g_list_length(possible_matches) > 1) {
pe_warn("Action %s exists %d times",
name, g_list_length(possible_matches));
}
op = g_list_nth_data(possible_matches, 0);
g_list_free(possible_matches);
} else {
op = custom_action(NULL, crm_strdup(op_s), op_s,
NULL, TRUE, TRUE, data_set);
op->pseudo = TRUE;
op->runnable = TRUE;
}
return op;
}
gboolean can_run_any(GListPtr nodes)
{
if(nodes == NULL) {
return FALSE;
}
slist_iter(
node, node_t, nodes, lpc,
if(can_run_resources(node) && node->weight >= 0) {
return TRUE;
}
);
return FALSE;
}

File Metadata

Mime Type
text/x-c
Expires
Thu, Jun 5, 11:05 PM (4 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1864605
Default Alt Text
utils.c (13 KB)

Event Timeline