You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
heartbeat/lib/crm/pengine/native.c

421 lines
11 KiB

/*
* 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/pengine/status.h>
#include <crm/pengine/rules.h>
#include <crm/pengine/complex.h>
#include <unpack.h>
#include <utils.h>
#include <crm/msg_xml.h>
#define DELETE_THEN_REFRESH 1
#define VARIANT_NATIVE 1
#include <lib/crm/pengine/variant.h>
void
native_add_running(resource_t *rsc, node_t *node, pe_working_set_t *data_set)
{
CRM_CHECK(node != NULL, return);
slist_iter(
a_node, node_t, rsc->running_on, lpc,
CRM_CHECK(a_node != NULL, return);
if(safe_str_eq(a_node->details->id, node->details->id)) {
return;
}
);
crm_debug_3("Adding %s to %s", rsc->id, node->details->uname);
rsc->running_on = g_list_append(rsc->running_on, node);
if(rsc->variant == pe_native) {
node->details->running_rsc = g_list_append(
node->details->running_rsc, rsc);
}
if(is_not_set(rsc->flags, pe_rsc_managed)) {
crm_info("resource %s isnt managed", rsc->id);
resource_location(rsc, node, INFINITY,
"not_managed_default", data_set);
return;
}
if(rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) {
const char *type = crm_element_value(rsc->xml, XML_ATTR_TYPE);
const char *class = crm_element_value(
rsc->xml, XML_AGENT_ATTR_CLASS);
/* these are errors because hardly any gets it right
* at the moment and this way the might notice
*/
pe_proc_err("Resource %s::%s:%s appears to be active on %d nodes.",
class, type, rsc->id, g_list_length(rsc->running_on));
cl_log(LOG_ERR, "See %s for more information.",
HAURL("v2/faq/resource_too_active"));
if(rsc->recovery_type == recovery_stop_only) {
crm_debug("Making sure %s doesn't come up again", rsc->id);
/* make sure it doesnt come up again */
pe_free_shallow_adv(rsc->allowed_nodes, TRUE);
rsc->allowed_nodes = node_list_dup(
data_set->nodes, FALSE, FALSE);
slist_iter(
node, node_t, rsc->allowed_nodes, lpc,
node->weight = -INFINITY;
);
} else if(rsc->recovery_type == recovery_block) {
clear_bit(rsc->flags, pe_rsc_managed);
}
} else {
crm_debug_3("Resource %s is active on: %s",
rsc->id, node->details->uname);
}
if(rsc->parent != NULL) {
native_add_running(rsc->parent, node, data_set);
}
}
gboolean native_unpack(resource_t *rsc, pe_working_set_t *data_set)
{
native_variant_data_t *native_data = NULL;
crm_debug_3("Processing resource %s...", rsc->id);
crm_malloc0(native_data, sizeof(native_variant_data_t));
rsc->allowed_nodes = NULL;
rsc->running_on = NULL;
rsc->variant_opaque = native_data;
return TRUE;
}
resource_t *
native_find_child(resource_t *rsc, const char *id)
{
if(rsc->children) {
return pe_find_resource(rsc->children, id);
}
return NULL;
}
GListPtr native_children(resource_t *rsc)
{
return rsc->children;
}
static void
hash_copy_field(gpointer key, gpointer value, gpointer user_data)
{
const char *name = key;
const char *s_value = value;
GHashTable *hash_copy = user_data;
g_hash_table_insert(hash_copy, crm_strdup(name), crm_strdup(s_value));
}
char *
native_parameter(
resource_t *rsc, node_t *node, gboolean create, const char *name,
pe_working_set_t *data_set)
{
char *value_copy = NULL;
const char *value = NULL;
GHashTable *hash = rsc->parameters;
GHashTable *local_hash = NULL;
CRM_CHECK(rsc != NULL, return NULL);
CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
crm_debug_2("Looking up %s in %s", name, rsc->id);
if(create) {
if(node != NULL) {
crm_debug_2("Creating hash with node %s",
node->details->uname);
} else {
crm_debug_2("Creating default hash");
}
local_hash = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
g_hash_table_foreach(
rsc->parameters, hash_copy_field, local_hash);
unpack_instance_attributes(
rsc->xml, XML_TAG_ATTR_SETS,
node?node->details->attrs:NULL,
local_hash, NULL, data_set->now);
hash = local_hash;
}
value = g_hash_table_lookup(hash, name);
if(value == NULL) {
/* try meta attributes instead */
value = g_hash_table_lookup(rsc->meta, name);
}
if(value != NULL) {
value_copy = crm_strdup(value);
}
if(local_hash != NULL) {
g_hash_table_destroy(local_hash);
}
return value_copy;
}
gboolean native_active(resource_t *rsc, gboolean all)
{
slist_iter(
a_node, node_t, rsc->running_on, lpc,
if(a_node->details->online == FALSE) {
crm_debug("Resource %s: node %s is offline",
rsc->id, a_node->details->uname);
} else if(a_node->details->unclean) {
crm_debug("Resource %s: node %s is unclean",
rsc->id, a_node->details->uname);
} else {
crm_debug("Resource %s active on %s",
rsc->id, a_node->details->uname);
return TRUE;
}
);
return FALSE;
}
struct print_data_s
{
long options;
void *print_data;
};
static void native_print_attr(gpointer key, gpointer value, gpointer user_data)
{
long options = ((struct print_data_s*)user_data)->options;
void *print_data = ((struct print_data_s*)user_data)->print_data;
status_print("Option: %s = %s\n", (char*)key, (char*)value);
}
void
native_print(
resource_t *rsc, const char *pre_text, long options, void *print_data)
{
node_t *node = NULL;
const char *prov = NULL;
const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
if(safe_str_eq(class, "ocf")) {
prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
}
if(rsc->running_on != NULL) {
node = rsc->running_on->data;
}
if(options & pe_print_html) {
if(is_not_set(rsc->flags, pe_rsc_managed)) {
status_print("<font color=\"yellow\">");
} else if(is_set(rsc->flags, pe_rsc_failed)) {
status_print("<font color=\"red\">");
} else if(rsc->variant == pe_native
&& g_list_length(rsc->running_on) == 0) {
status_print("<font color=\"red\">");
} else if(g_list_length(rsc->running_on) > 1) {
status_print("<font color=\"orange\">");
} else {
status_print("<font color=\"green\">");
}
}
if((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
const char *desc = NULL;
desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
status_print("%s%s\t(%s%s%s:%s%s)%s%s",
pre_text?pre_text:"", rsc->id,
prov?prov:"", prov?"::":"",
class, crm_element_value(rsc->xml, XML_ATTR_TYPE),
is_set(rsc->flags, pe_rsc_orphan)?" ORPHANED":"",
desc?": ":"", desc?desc:"");
} else {
status_print("%s%s\t(%s%s%s:%s%s):\t%s %s%s%s",
pre_text?pre_text:"", rsc->id,
prov?prov:"", prov?"::":"",
class, crm_element_value(rsc->xml, XML_ATTR_TYPE),
is_set(rsc->flags, pe_rsc_orphan)?" ORPHANED":"",
(rsc->variant!=pe_native)?"":role2text(rsc->role),
(rsc->variant!=pe_native)?"":node!=NULL?node->details->uname:"",
is_set(rsc->flags, pe_rsc_managed)?"":" (unmanaged)",
is_set(rsc->flags, pe_rsc_failed)?" FAILED":"");
#if CURSES_ENABLED
if(options & pe_print_ncurses) {
move(-1, 0);
}
#endif
}
if(options & pe_print_html) {
status_print(" </font> ");
}
if((options & pe_print_rsconly)) {
} else if(g_list_length(rsc->running_on) > 1) {
if(options & pe_print_html) {
status_print("<ul>\n");
} else if((options & pe_print_printf)
|| (options & pe_print_ncurses)) {
status_print("[");
}
slist_iter(node, node_t, rsc->running_on, lpc,
if(options & pe_print_html) {
status_print("<li>\n%s",
node->details->uname);
} else if((options & pe_print_printf)
|| (options & pe_print_ncurses)) {
status_print("\t%s", node->details->uname);
} else if((options & pe_print_log)) {
status_print("\t%d : %s",
lpc, node->details->uname);
} else {
status_print("%s", node->details->uname);
}
if(options & pe_print_html) {
status_print("</li>\n");
}
);
if(options & pe_print_html) {
status_print("</ul>\n");
} else if((options & pe_print_printf)
|| (options & pe_print_ncurses)) {
status_print(" ]");
}
}
if(options & pe_print_html) {
status_print("<br/>\n");
} else if((options & pe_print_printf) || (options & pe_print_ncurses)) {
status_print("\n");
}
if(options & pe_print_details) {
struct print_data_s pdata;
pdata.options = options;
pdata.print_data = print_data;
g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
}
if(options & pe_print_dev) {
status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
is_set(rsc->flags, pe_rsc_provisional)?"provisional, ":"",
is_set(rsc->flags, pe_rsc_runnable)?"":"non-startable, ",
crm_element_name(rsc->xml),
(double)rsc->priority);
status_print("%s\tAllowed Nodes", pre_text);
slist_iter(node, node_t, rsc->allowed_nodes, lpc,
status_print("%s\t * %s %d",
pre_text,
node->details->uname,
node->weight);
);
}
if(options & pe_print_max_details) {
status_print("%s\t=== Allowed Nodes\n", pre_text);
slist_iter(
node, node_t, rsc->allowed_nodes, lpc,
print_node("\t", node, FALSE);
);
}
}
void native_free(resource_t *rsc)
{
crm_debug_4("Freeing resource action list (not the data)");
common_free(rsc);
}
enum rsc_role_e
native_resource_state(const resource_t *rsc, gboolean current)
{
enum rsc_role_e role = rsc->next_role;
if(current) {
role = rsc->role;
}
crm_debug_2("%s state: %s", rsc->id, role2text(role));
return role;
}
node_t *native_location(resource_t *rsc, GListPtr *list, gboolean current)
{
node_t *one = NULL;
GListPtr result = NULL;
if(rsc->children) {
slist_iter(child, resource_t, rsc->children, lpc,
child->fns->location(child, &result, current);
);
} else if(current && rsc->running_on) {
result = g_list_copy(rsc->running_on);
} else if(current == FALSE && rsc->allocated_to) {
result = g_list_append(NULL, rsc->allocated_to);
}
if(result && g_list_length(result) == 1) {
one = g_list_nth_data(result, 0);
}
if(list) {
slist_iter(node, node_t, result, lpc,
if(*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
*list = g_list_append(*list, node);
}
);
}
g_list_free(result);
return one;
}