diff --git a/lib/crm/pengine/rules.c b/lib/crm/pengine/rules.c index 4c367e272b..c656273b2c 100644 --- a/lib/crm/pengine/rules.c +++ b/lib/crm/pengine/rules.c @@ -1,622 +1,622 @@ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include #include #include #include #include ha_time_t *parse_xml_duration(ha_time_t *start, crm_data_t *duration_spec); gboolean test_date_expression(crm_data_t *time_expr, ha_time_t *now); gboolean cron_range_satisfied(ha_time_t *now, crm_data_t *cron_spec); gboolean test_attr_expression( crm_data_t *expr, GHashTable *hash, ha_time_t *now); gboolean test_role_expression( crm_data_t *expr, enum rsc_role_e role, ha_time_t *now); gboolean test_ruleset(crm_data_t *ruleset, GHashTable *node_hash, ha_time_t *now) { gboolean ruleset_default = TRUE; xml_child_iter_filter( ruleset, rule, XML_TAG_RULE, ruleset_default = FALSE; if(test_rule(rule, node_hash, RSC_ROLE_UNKNOWN, now)) { return TRUE; } ); return ruleset_default; } gboolean test_rule(crm_data_t *rule, GHashTable *node_hash, enum rsc_role_e role, ha_time_t *now) { gboolean test = TRUE; gboolean empty = TRUE; gboolean passed = TRUE; gboolean do_and = TRUE; const char *value = crm_element_value(rule, "boolean_op"); if(safe_str_eq(value, "or")) { do_and = FALSE; passed = FALSE; } crm_debug_2("Testing rule %s", ID(rule)); xml_child_iter( rule, expr, test = test_expression(expr, node_hash, role, now); empty = FALSE; if(test && do_and == FALSE) { crm_debug_3("Expression %s/%s passed", ID(rule), ID(expr)); return TRUE; } else if(test == FALSE && do_and) { crm_debug_3("Expression %s/%s failed", ID(rule), ID(expr)); return FALSE; } ); if(empty) { crm_err("Invalid Rule %s: rules must contain at least one expression", ID(rule)); } crm_debug_2("Rule %s %s", ID(rule), passed?"passed":"failed"); return passed; } gboolean test_expression(crm_data_t *expr, GHashTable *node_hash, enum rsc_role_e role, ha_time_t *now) { gboolean accept = FALSE; const char *uname = NULL; switch(find_expression_type(expr)) { case nested_rule: accept = test_rule(expr, node_hash, role, now); break; case attr_expr: case loc_expr: /* these expressions can never succeed if there is * no node to compare with */ if(node_hash != NULL) { accept = test_attr_expression(expr, node_hash, now); } break; case time_expr: accept = test_date_expression(expr, now); break; case role_expr: accept = test_role_expression(expr, role, now); break; default: CRM_CHECK(FALSE /* bad type */, return FALSE); accept = FALSE; } if(node_hash) { uname = g_hash_table_lookup(node_hash, "#uname"); } crm_debug_2("Expression %s %s on %s", ID(expr), accept?"passed":"failed", uname?uname:"all ndoes"); return accept; } enum expression_type find_expression_type(crm_data_t *expr) { const char *tag = NULL; const char *attr = NULL; attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE); tag = crm_element_name(expr); if(safe_str_eq(tag, "date_expression")) { return time_expr; } else if(safe_str_eq(tag, XML_TAG_RULE)) { return nested_rule; } else if(safe_str_neq(tag, "expression")) { return not_expr; } else if(safe_str_eq(attr, "#uname") || safe_str_eq(attr, "#id")) { return loc_expr; } else if(safe_str_eq(attr, "#role")) { return role_expr; } return attr_expr; } gboolean test_role_expression( crm_data_t *expr, enum rsc_role_e role, ha_time_t *now) { gboolean accept = FALSE; const char *op = NULL; const char *value = NULL; if(role == RSC_ROLE_UNKNOWN) { return accept; } value = crm_element_value(expr, XML_EXPR_ATTR_VALUE); op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION); if(safe_str_eq(op, "defined")) { if(role > RSC_ROLE_STARTED) { accept = TRUE; } } else if(safe_str_eq(op, "not_defined")) { if(role < RSC_ROLE_SLAVE && role > RSC_ROLE_UNKNOWN) { accept = TRUE; } } else if(safe_str_eq(op, "eq")) { if(text2role(value) == role) { accept = TRUE; } } else if(safe_str_eq(op, "ne")) { /* we will only test "ne" wtih master/slave roles style */ if(role < RSC_ROLE_SLAVE && role > RSC_ROLE_UNKNOWN) { accept = FALSE; } else if(text2role(value) != role) { accept = TRUE; } } return accept; } gboolean test_attr_expression(crm_data_t *expr, GHashTable *hash, ha_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 || (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; } /* As per the nethack rules: * * moon period = 29.53058 days ~= 30, year = 365.2422 days * days moon phase advances on first day of year compared to preceding year * = 365.2422 - 12*29.53058 ~= 11 * years in Metonic cycle (time until same phases fall on the same days of * the month) = 18.6 ~= 19 * moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30 * (29 as initial condition) * current phase in days = first day phase + days elapsed in year * 6 moons ~= 177 days * 177 ~= 8 reported phases * 22 * + 11/22 for rounding * * 0-7, with 0: new, 4: full */ static int phase_of_the_moon(ha_time_t *now) { int epact, diy, goldn; diy = now->yeardays; goldn = (now->years % 19) + 1; epact = (11 * goldn + 18) % 30; if ((epact == 25 && goldn > 11) || epact == 24) epact++; return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 ); } #define cron_check(xml_field, time_field) \ value = crm_element_value(cron_spec, xml_field); \ if(value != NULL) { \ gboolean pass = TRUE; \ decodeNVpair(value, '-', &value_low, &value_high); \ if(value_low == NULL) { \ value_low = crm_strdup(value); \ } \ value_low_i = crm_parse_int(value_low, "0"); \ value_high_i = crm_parse_int(value_high, "-1"); \ if(value_high_i < 0) { \ if(value_low_i != time_field) { \ pass = FALSE; \ } \ } else if(value_low_i > time_field) { \ pass = FALSE; \ } else if(value_high_i < time_field) { \ pass = FALSE; \ } \ crm_free(value_low); \ crm_free(value_high); \ if(pass == FALSE) { \ crm_debug("Condition '%s' in %s: failed", value, xml_field); \ return pass; \ } \ crm_debug("Condition '%s' in %s: passed", value, xml_field); \ } gboolean cron_range_satisfied(ha_time_t *now, crm_data_t *cron_spec) { const char *value = NULL; char *value_low = NULL; char *value_high = NULL; int value_low_i = 0; int value_high_i = 0; CRM_CHECK(now != NULL, return FALSE); cron_check("seconds", now->seconds); cron_check("minutes", now->minutes); cron_check("hours", now->hours); cron_check("monthdays", now->days); cron_check("weekdays", now->weekdays); cron_check("yeardays", now->yeardays); cron_check("weeks", now->weeks); cron_check("months", now->months); cron_check("years", now->years); cron_check("weekyears", now->weekyears); cron_check("moon", phase_of_the_moon(now)); return TRUE; } #define update_field(xml_field, time_fn) \ value = crm_element_value(duration_spec, xml_field); \ if(value != NULL) { \ int value_i = crm_parse_int(value, "0"); \ time_fn(end, value_i); \ } ha_time_t * parse_xml_duration(ha_time_t *start, crm_data_t *duration_spec) { ha_time_t *end = NULL; const char *value = NULL; end = new_ha_date(FALSE); ha_set_time(end, start, TRUE); update_field("years", add_years); update_field("months", add_months); update_field("weeks", add_weeks); update_field("days", add_days); update_field("hours", add_hours); update_field("minutes", add_minutes); update_field("seconds", add_seconds); return end; } gboolean test_date_expression(crm_data_t *time_expr, ha_time_t *now) { ha_time_t *start = NULL; ha_time_t *end = NULL; const char *value = NULL; char *value_copy = NULL; char *value_copy_start = NULL; const char *op = crm_element_value(time_expr, "operation"); crm_data_t *duration_spec = NULL; crm_data_t *date_spec = NULL; gboolean passed = FALSE; crm_debug_2("Testing expression: %s", ID(time_expr)); duration_spec = cl_get_struct(time_expr, "duration"); date_spec = cl_get_struct(time_expr, "date_spec"); value = crm_element_value(time_expr, "start"); if(value != NULL) { value_copy = crm_strdup(value); value_copy_start = value_copy; start = parse_date(&value_copy); crm_free(value_copy_start); } value = crm_element_value(time_expr, "end"); if(value != NULL) { value_copy = crm_strdup(value); value_copy_start = value_copy; end = parse_date(&value_copy); crm_free(value_copy_start); } - if(start != NULL && end == NULL) { + if(start != NULL && end == NULL && duration_spec != NULL) { end = parse_xml_duration(start, duration_spec); } if(op == NULL) { op = "in_range"; } if(safe_str_eq(op, "date_spec") || safe_str_eq(op, "in_range")) { if(start != NULL && compare_date(start, now) > 0) { passed = FALSE; } else if(end != NULL && compare_date(end, now) < 0) { passed = FALSE; } else if(safe_str_eq(op, "in_range")) { passed = TRUE; } else { passed = cron_range_satisfied(now, date_spec); } } else if(safe_str_eq(op, "gt") && compare_date(start, now) < 0) { passed = TRUE; } else if(safe_str_eq(op, "lt") && compare_date(end, now) > 0) { passed = TRUE; } else if(safe_str_eq(op, "eq") && compare_date(start, now) == 0) { passed = TRUE; } else if(safe_str_eq(op, "neq") && compare_date(start, now) != 0) { passed = TRUE; } free_ha_date(start); free_ha_date(end); return passed; } typedef struct sorted_set_s { const char *name; const char *special_name; int score; crm_data_t *attr_set; GHashTable *node_hash; GHashTable *hash; ha_time_t *now; } sorted_set_t; static gint sort_pairs(gconstpointer a, gconstpointer b) { const sorted_set_t *pair_a = a; const sorted_set_t *pair_b = b; if(a == NULL && b == NULL) { return 0; } else if(a == NULL) { return 1; } else if(b == NULL) { return -1; } if(safe_str_eq(pair_a->name, pair_a->special_name)) { return -1; } else if(safe_str_eq(pair_b->name, pair_a->special_name)) { return 1; } if(pair_a->score < pair_b->score) { return 1; } else if(pair_a->score > pair_b->score) { return -1; } return 0; } static void populate_hash(crm_data_t *nvpair_list, GHashTable *hash) { const char *name = NULL; const char *value = NULL; xml_child_iter_filter( nvpair_list, an_attr, XML_CIB_TAG_NVPAIR, name = crm_element_value(an_attr, XML_NVPAIR_ATTR_NAME); crm_debug_4("Setting attribute: %s", name); value = crm_element_value( an_attr, XML_NVPAIR_ATTR_VALUE); if(name == NULL || value == NULL) { continue; } else if(safe_str_eq(value, "#default")) { continue; } else if(g_hash_table_lookup(hash, name) == NULL) { g_hash_table_insert( hash, crm_strdup(name), crm_strdup(value)); } ); } static void unpack_attr_set(gpointer data, gpointer user_data) { sorted_set_t *pair = data; sorted_set_t *unpack_data = user_data; crm_data_t *attributes = NULL; if(test_ruleset(pair->attr_set, unpack_data->node_hash, unpack_data->now) == FALSE) { return; } crm_debug_3("Adding attributes from %s", pair->name); attributes = cl_get_struct(pair->attr_set, XML_TAG_ATTRS); populate_hash(attributes, unpack_data->hash); } static void free_pair(gpointer data, gpointer user_data) { sorted_set_t *pair = data; crm_free(pair); } void unpack_instance_attributes( crm_data_t *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, ha_time_t *now) { GListPtr sorted = NULL; const char *score = NULL; sorted_set_t *pair = NULL; if(xml_obj == NULL) { crm_debug_4("No instance attributes"); return; } crm_debug_4("Checking for attributes"); xml_child_iter_filter( xml_obj, attr_set, set_name, pair = NULL; crm_malloc0(pair, sizeof(sorted_set_t)); pair->name = ID(attr_set); pair->special_name = always_first; pair->attr_set = attr_set; score = crm_element_value(attr_set, XML_RULE_ATTR_SCORE); pair->score = char2score(score); sorted = g_list_prepend(sorted, pair); ); if(pair != NULL) { pair->hash = hash; pair->node_hash = node_hash; pair->now = now; } sorted = g_list_sort(sorted, sort_pairs); g_list_foreach(sorted, unpack_attr_set, pair); g_list_foreach(sorted, free_pair, NULL); g_list_free(sorted); } diff --git a/pengine/testcases/bug-1718.xml b/pengine/testcases/bug-1718.xml index 9413d8b505..98e716eb6e 100644 --- a/pengine/testcases/bug-1718.xml +++ b/pengine/testcases/bug-1718.xml @@ -1,203 +1,202 @@ - diff --git a/pengine/testcases/date-1.xml b/pengine/testcases/date-1.xml index bc09f0890a..1f3e2671df 100644 --- a/pengine/testcases/date-1.xml +++ b/pengine/testcases/date-1.xml @@ -1,70 +1,68 @@ - - - + diff --git a/pengine/testcases/inc1.xml b/pengine/testcases/inc1.xml index 27a8b55176..4add1f9115 100644 --- a/pengine/testcases/inc1.xml +++ b/pengine/testcases/inc1.xml @@ -1,51 +1,51 @@ - + diff --git a/pengine/testcases/inc7.xml b/pengine/testcases/inc7.xml index 18f61996a2..b7e6bbe92c 100644 --- a/pengine/testcases/inc7.xml +++ b/pengine/testcases/inc7.xml @@ -1,70 +1,70 @@ - + diff --git a/pengine/testcases/novell-239079.xml b/pengine/testcases/novell-239079.xml index a13abe907e..902dbc281d 100644 --- a/pengine/testcases/novell-239079.xml +++ b/pengine/testcases/novell-239079.xml @@ -1,116 +1,116 @@ - + diff --git a/pengine/testcases/novell-239087.xml b/pengine/testcases/novell-239087.xml index da97b0e820..2c739f796e 100644 --- a/pengine/testcases/novell-239087.xml +++ b/pengine/testcases/novell-239087.xml @@ -1,131 +1,131 @@ - - + + diff --git a/pengine/testcases/orphan-0.xml b/pengine/testcases/orphan-0.xml index 68f08ba052..5ddfe0f25e 100644 --- a/pengine/testcases/orphan-0.xml +++ b/pengine/testcases/orphan-0.xml @@ -1,152 +1,147 @@ - - - - - diff --git a/pengine/testcases/orphan-1.xml b/pengine/testcases/orphan-1.xml index 11afd87952..bdd4a4ce61 100644 --- a/pengine/testcases/orphan-1.xml +++ b/pengine/testcases/orphan-1.xml @@ -1,152 +1,147 @@ - - - - - diff --git a/pengine/testcases/params-0.xml b/pengine/testcases/params-0.xml index 205454aaef..44b3fec4f1 100644 --- a/pengine/testcases/params-0.xml +++ b/pengine/testcases/params-0.xml @@ -1,161 +1,161 @@ - + - + - + - + - + diff --git a/pengine/testcases/params-1.xml b/pengine/testcases/params-1.xml index d5c45ff720..d7ecd996ed 100644 --- a/pengine/testcases/params-1.xml +++ b/pengine/testcases/params-1.xml @@ -1,167 +1,167 @@ - + diff --git a/pengine/testcases/params-4.xml b/pengine/testcases/params-4.xml index cf254fccf3..8f4a85a482 100644 --- a/pengine/testcases/params-4.xml +++ b/pengine/testcases/params-4.xml @@ -1,167 +1,167 @@ - + diff --git a/pengine/testcases/probe-0.dot b/pengine/testcases/probe-0.dot index a13b8ca44c..3023569d24 100644 --- a/pengine/testcases/probe-0.dot +++ b/pengine/testcases/probe-0.dot @@ -1,35 +1,35 @@ digraph "g" { -"configstoreclone:0_monitor_0 32c47" -> "probe_complete 32c47" [ style = bold] -"configstoreclone:0_monitor_0 32c47" [ style=bold color="green" fontcolor="black" ] -"configstoreclone:0_monitor_0 32c48" -> "probe_complete 32c48" [ style = bold] -"configstoreclone:0_monitor_0 32c48" [ style=bold color="green" fontcolor="black" ] -"configstoreclone:0_post_notify_start_0 32c48" -> "configstorecloneset_confirmed-post_notify_start_0" [ style = bold] -"configstoreclone:0_post_notify_start_0 32c48" [ style=bold color="green" fontcolor="black" ] -"configstoreclone:0_start_0 32c48" -> "configstorecloneset_running_0" [ style = bold] -"configstoreclone:0_start_0 32c48" [ style=bold color="green" fontcolor="black" ] -"configstoreclone:1_post_notify_start_0 32c47" -> "configstorecloneset_confirmed-post_notify_start_0" [ style = bold] -"configstoreclone:1_post_notify_start_0 32c47" [ style=bold color="green" fontcolor="black" ] -"configstoreclone:1_start_0 32c47" -> "configstorecloneset_running_0" [ style = bold] -"configstoreclone:1_start_0 32c47" [ style=bold color="green" fontcolor="black" ] +"configstoreclone:0_monitor_0 x32c47" -> "probe_complete x32c47" [ style = bold] +"configstoreclone:0_monitor_0 x32c47" [ style=bold color="green" fontcolor="black" ] +"configstoreclone:0_monitor_0 x32c48" -> "probe_complete x32c48" [ style = bold] +"configstoreclone:0_monitor_0 x32c48" [ style=bold color="green" fontcolor="black" ] +"configstoreclone:0_post_notify_start_0 x32c48" -> "configstorecloneset_confirmed-post_notify_start_0" [ style = bold] +"configstoreclone:0_post_notify_start_0 x32c48" [ style=bold color="green" fontcolor="black" ] +"configstoreclone:0_start_0 x32c48" -> "configstorecloneset_running_0" [ style = bold] +"configstoreclone:0_start_0 x32c48" [ style=bold color="green" fontcolor="black" ] +"configstoreclone:1_post_notify_start_0 x32c47" -> "configstorecloneset_confirmed-post_notify_start_0" [ style = bold] +"configstoreclone:1_post_notify_start_0 x32c47" [ style=bold color="green" fontcolor="black" ] +"configstoreclone:1_start_0 x32c47" -> "configstorecloneset_running_0" [ style = bold] +"configstoreclone:1_start_0 x32c47" [ style=bold color="green" fontcolor="black" ] "configstorecloneset_confirmed-post_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "configstorecloneset_confirmed-pre_notify_start_0" -> "configstorecloneset_start_0" [ style = bold] "configstorecloneset_confirmed-pre_notify_start_0" [ style=bold color="green" fontcolor="orange" ] -"configstorecloneset_post_notify_start_0" -> "configstoreclone:0_post_notify_start_0 32c48" [ style = bold] -"configstorecloneset_post_notify_start_0" -> "configstoreclone:1_post_notify_start_0 32c47" [ style = bold] +"configstorecloneset_post_notify_start_0" -> "configstoreclone:0_post_notify_start_0 x32c48" [ style = bold] +"configstorecloneset_post_notify_start_0" -> "configstoreclone:1_post_notify_start_0 x32c47" [ style = bold] "configstorecloneset_post_notify_start_0" -> "configstorecloneset_confirmed-post_notify_start_0" [ style = bold] "configstorecloneset_post_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "configstorecloneset_pre_notify_start_0" -> "configstorecloneset_confirmed-pre_notify_start_0" [ style = bold] "configstorecloneset_pre_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "configstorecloneset_running_0" -> "configstorecloneset_post_notify_start_0" [ style = bold] "configstorecloneset_running_0" [ style=bold color="green" fontcolor="orange" ] -"configstorecloneset_start_0" -> "configstoreclone:0_start_0 32c48" [ style = bold] -"configstorecloneset_start_0" -> "configstoreclone:1_start_0 32c47" [ style = bold] +"configstorecloneset_start_0" -> "configstoreclone:0_start_0 x32c48" [ style = bold] +"configstorecloneset_start_0" -> "configstoreclone:1_start_0 x32c47" [ style = bold] "configstorecloneset_start_0" -> "configstorecloneset_running_0" [ style = bold] "configstorecloneset_start_0" [ style=bold color="green" fontcolor="orange" ] -"probe_complete 32c47" -> "probe_complete" [ style = bold] -"probe_complete 32c47" [ style=bold color="green" fontcolor="black" ] -"probe_complete 32c48" -> "probe_complete" [ style = bold] -"probe_complete 32c48" [ style=bold color="green" fontcolor="black" ] +"probe_complete x32c47" -> "probe_complete" [ style = bold] +"probe_complete x32c47" [ style=bold color="green" fontcolor="black" ] +"probe_complete x32c48" -> "probe_complete" [ style = bold] +"probe_complete x32c48" [ style=bold color="green" fontcolor="black" ] "probe_complete" -> "configstorecloneset_start_0" [ style = bold] "probe_complete" [ style=bold color="green" fontcolor="orange" ] } diff --git a/pengine/testcases/probe-0.exp b/pengine/testcases/probe-0.exp index 001360e579..5c7f230a6b 100644 --- a/pengine/testcases/probe-0.exp +++ b/pengine/testcases/probe-0.exp @@ -1,195 +1,195 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/pengine/testcases/probe-0.xml b/pengine/testcases/probe-0.xml index 5723e417d8..d660b73eed 100644 --- a/pengine/testcases/probe-0.xml +++ b/pengine/testcases/probe-0.xml @@ -1,131 +1,131 @@ - - + + - + - + diff --git a/pengine/testcases/rec-rsc-9.xml b/pengine/testcases/rec-rsc-9.xml index 671ca5d5e9..d5d92dd86b 100644 --- a/pengine/testcases/rec-rsc-9.xml +++ b/pengine/testcases/rec-rsc-9.xml @@ -1,51 +1,51 @@ - - + + diff --git a/xml/constraints.rng b/xml/constraints.rng new file mode 100644 index 0000000000..417f64c948 --- /dev/null +++ b/xml/constraints.rng @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + promote + demote + stop + + + + + + Stopped + Started + Master + Slave + + + + + + + + + + + + diff --git a/xml/crm-1.0.dtd b/xml/crm-1.0.dtd new file mode 100644 index 0000000000..09b97d89ec --- /dev/null +++ b/xml/crm-1.0.dtd @@ -0,0 +1,864 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/crm.dtd b/xml/crm.dtd new file mode 100644 index 0000000000..09b97d89ec --- /dev/null +++ b/xml/crm.dtd @@ -0,0 +1,864 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/crm.xsl b/xml/crm.xsl new file mode 100644 index 0000000000..5bb1b4a842 --- /dev/null +++ b/xml/crm.xsl @@ -0,0 +1,176 @@ + + + + + + +

Cluster Configuration: ..

+ +
+ + +
  • + Property Set: + +
  • +
    + + +
  • + Node () + +
  • +
    + + +
  • + Resource + ::: + +
      + + Preferred Locations: + + + +
    +
  • +
    + + + + + + + + + + + + +
  • +

    Resource Group

    +
    +
  • +
    + + +
  • +

    Cloned Resource

    +
    +
  • +
    + + +
  • + : + interval= + timeout= +
  • +
    + + + Options: + + + + + Location: +
    +
    + + +
    +
    + + +
  • + + + + + + + (score=) + +
  • +
    + + +
  • + ="" +
  • +
    + + +

    Cluster Options

    +
    +
    + + +

    Available Nodes

    +
      + +
    +
    + + +

    Configured Resources

    +
      + +
    +
    + + +

    Inter-Resource Relationships

    + + +
    + + + + + + +
      + +
    +
    + + + Operations: +
      + +
    +
    + + + + + + + + + + + + +
    +
      + Unknown Object: + +

      + +
    +
    +
    + + + + = + + + + +
    diff --git a/xml/nvset.rng b/xml/nvset.rng new file mode 100644 index 0000000000..363519ad34 --- /dev/null +++ b/xml/nvset.rng @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/pacemaker-1.0.rng b/xml/pacemaker-1.0.rng new file mode 100644 index 0000000000..ea5b256446 --- /dev/null +++ b/xml/pacemaker-1.0.rng @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + dtd + relax-ng + relax-ng-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + member + ping + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/regression.core.sh b/xml/regression.core.sh new file mode 100755 index 0000000000..4cc860b32f --- /dev/null +++ b/xml/regression.core.sh @@ -0,0 +1,90 @@ +#!/bin/bash + + # Copyright (C) 2004 Andrew Beekhof + # + # 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 + # + +verbose=$1 +io_dir=../pengine/testcases +diff_opts="--ignore-all-space -u -N" +failed=.regression.failed.diff +# zero out the error log +> $failed + +num_failed=0 +function do_test { + + base=$1; shift + name=$1; shift + input=$io_dir/${base}.xml + output=$io_dir/${base}.upgrade.xml + expected=$io_dir/${base}.expected.xml + + if [ ! -f $input ]; then + echo "Test $name ($base)... Error (PE : input)"; + num_failed=`expr $num_failed + 1` + return; + fi + + echo "Test $base : $name"; + if [ "$create_mode" != "true" -a ! -f $expected ]; then + : +# echo " Error (PE : expected)"; +# return; + fi + + xsltproc --novalid upgrade.xsl $input > $output + if [ $? != 0 ]; then + echo " * Failed (xml : xsltproc)"; + num_failed=`expr $num_failed + 1` + fi + + if [ ! -s $output ]; then + echo " Error (xml : no conversion)"; + num_failed=`expr $num_failed + 1` + rm $output + return; + fi + + xmllint --relaxng pacemaker-1.0.rng $output > /dev/null 2>&1 + + if [ $? != 0 ]; then + echo " * Failed (xml : xmllint)"; + num_failed=`expr $num_failed + 1` + xmllint --relaxng pacemaker-1.0.rng $output > /dev/null + cat -n $output + fi + + rm -f $output +} + +function test_results { + if [ $num_failed != 0 ]; then + if [ -s $failed ]; then + if [ "$verbose" = "-v" ]; then + echo "Results of $num_failed failed tests...." + less $failed + else + echo "Results of $num_failed failed tests are in $failed...." + echo "Use $0 -v to display them automatically." + fi + else + echo "$num_failed tests failed (no diff results)" + rm $failed + fi + fi +} + diff --git a/xml/regression.sh b/xml/regression.sh new file mode 100755 index 0000000000..146bd6b7ea --- /dev/null +++ b/xml/regression.sh @@ -0,0 +1,267 @@ +#!/bin/bash + + # Copyright (C) 2004 Andrew Beekhof + # + # 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 + # +. regression.core.sh +create_mode="true" +echo Generating test outputs for these tests... +# do_test + +echo Done. +echo "" + +echo Performing the following tests... +create_mode="false" + +echo "" +do_test simple1 "Offline " +do_test simple2 "Start " +do_test simple3 "Start 2 " +do_test simple4 "Start Failed" +do_test simple6 "Stop Start " +do_test simple7 "Shutdown " +#do_test simple8 "Stonith " +#do_test simple9 "Lower version" +#do_test simple10 "Higher version" +do_test simple11 "Priority (ne)" +do_test simple12 "Priority (eq)" +do_test simple8 "Stickiness" + +echo "" +do_test params-0 "Params: No change" +do_test params-1 "Params: Changed" +do_test params-2 "Params: Resource definition" +do_test params-4 "Params: Reload" +do_test novell-251689 "Resource definition change + target_role=stopped" + +echo "" +do_test orphan-0 "Orphan ignore" +do_test orphan-1 "Orphan stop" + +echo "" +do_test target-0 "Target Role : baseline" +do_test target-1 "Target Role : test" + +echo "" +do_test date-1 "Dates" -d "2005-020" +do_test date-2 "Date Spec - Pass" -d "2005-020T12:30" +do_test date-3 "Date Spec - Fail" -d "2005-020T11:30" +do_test probe-0 "Probe (anon clone)" +do_test probe-1 "Pending Probe" +do_test standby "Standby" +do_test comments "Comments" + +echo "" +do_test rsc_dep1 "Must not " +do_test rsc_dep3 "Must " +do_test rsc_dep5 "Must not 3 " +do_test rsc_dep7 "Must 3 " +do_test rsc_dep10 "Must (but cant)" +do_test rsc_dep2 "Must (running) " +do_test rsc_dep8 "Must (running : alt) " +do_test rsc_dep4 "Must (running + move)" + +echo "" +do_test order1 "Order start 1 " +do_test order2 "Order start 2 " +do_test order3 "Order stop " +do_test order4 "Order (multiple) " +do_test order5 "Order (move) " +do_test order6 "Order (move w/ restart) " +do_test order7 "Order (manditory) " +do_test order-optional "Order (score=0) " +do_test order-required "Order (score=INFINITY) " + +echo "" +do_test coloc-loop "Colocation - loop" +do_test coloc-many-one "Colocation - many-to-one" +do_test coloc-list "Colocation - many-to-one with list" +do_test coloc-group "Colocation - groups" + +#echo "" +#do_test agent1 "version: lt (empty)" +#do_test agent2 "version: eq " +#do_test agent3 "version: gt " + +echo "" +do_test attrs1 "string: eq (and) " +do_test attrs2 "string: lt / gt (and)" +do_test attrs3 "string: ne (or) " +do_test attrs4 "string: exists " +do_test attrs5 "string: not_exists " +do_test attrs6 "is_dc: true " +do_test attrs7 "is_dc: false " +do_test attrs8 "score_attribute " + +echo "" +do_test mon-rsc-1 "Schedule Monitor - start" +do_test mon-rsc-2 "Schedule Monitor - move " +do_test mon-rsc-3 "Schedule Monitor - pending start " +do_test mon-rsc-4 "Schedule Monitor - move/pending start" + +echo "" +do_test rec-rsc-0 "Resource Recover - no start " +do_test rec-rsc-1 "Resource Recover - start " +do_test rec-rsc-2 "Resource Recover - monitor " +do_test rec-rsc-3 "Resource Recover - stop - ignore" +do_test rec-rsc-4 "Resource Recover - stop - block " +do_test rec-rsc-5 "Resource Recover - stop - fence " +do_test rec-rsc-6 "Resource Recover - multiple - restart" +do_test rec-rsc-7 "Resource Recover - multiple - stop " +do_test rec-rsc-8 "Resource Recover - multiple - block " +do_test rec-rsc-9 "Resource Recover - group/group" + +echo "" +do_test quorum-1 "No quorum - ignore" +do_test quorum-2 "No quorum - freeze" +do_test quorum-3 "No quorum - stop " +do_test quorum-4 "No quorum - start anyway" +do_test quorum-5 "No quorum - start anyway (group)" +do_test quorum-6 "No quorum - start anyway (clone)" + +echo "" +do_test rec-node-1 "Node Recover - Startup - no fence" +do_test rec-node-2 "Node Recover - Startup - fence " +do_test rec-node-3 "Node Recover - HA down - no fence" +do_test rec-node-4 "Node Recover - HA down - fence " +do_test rec-node-5 "Node Recover - CRM down - no fence" +do_test rec-node-6 "Node Recover - CRM down - fence " +do_test rec-node-7 "Node Recover - no quorum - ignore " +do_test rec-node-8 "Node Recover - no quorum - freeze " +do_test rec-node-9 "Node Recover - no quorum - stop " +do_test rec-node-10 "Node Recover - no quorum - stop w/fence" +do_test rec-node-11 "Node Recover - CRM down w/ group - fence " +do_test rec-node-12 "Node Recover - nothing active - fence " +do_test rec-node-13 "Node Recover - failed resource + shutdown - fence " +do_test rec-node-15 "Node Recover - unknown lrm section" +do_test rec-node-14 "Serialize all stonith's" + +echo "" +do_test multi1 "Multiple Active (stop/start)" + +echo "" +do_test migrate-1 "Migrate (migrate)" +do_test migrate-2 "Migrate (stable)" +do_test migrate-3 "Migrate (failed migrate_to)" +do_test migrate-4 "Migrate (failed migrate_from)" +do_test novell-252693 "Migration in a stopping stack" +do_test novell-252693-2 "Migration in a starting stack" +do_test novell-252693-3 "Non-Migration in a starting and stopping stack" + +#echo "" +#do_test complex1 "Complex " + +echo "" +do_test group1 "Group " +do_test group2 "Group + Native " +do_test group3 "Group + Group " +do_test group4 "Group + Native (nothing)" +do_test group5 "Group + Native (move) " +do_test group6 "Group + Group (move) " +do_test group7 "Group colocation" +do_test group13 "Group colocation (cant run)" +do_test group8 "Group anti-colocation" +do_test group9 "Group recovery" +do_test group10 "Group partial recovery" +do_test group11 "Group target_role" +do_test group14 "Group stop (graph terminated)" +do_test group15 "-ve group colocation" +do_test bug-1573 "Partial stop of a group with two children" +do_test bug-1718 "Mandatory group ordering - Stop group_FUN" + +echo "" +do_test inc0 "Incarnation start" +do_test inc1 "Incarnation start order" +do_test inc2 "Incarnation silent restart, stop, move" +do_test inc3 "Inter-incarnation ordering, silent restart, stop, move" +do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)" +do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)" +do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2)" +do_test inc7 "Clone colocation" +do_test inc8 "Clone anti-colocation" +do_test inc9 "Non-unique clone" +do_test inc10 "Non-unique clone (stop)" +do_test inc11 "Primitive colocation with clones" +do_test inc12 "Clone shutdown" +do_test cloned-group "Make sure only the correct number of cloned groups are started" + +echo "" +do_test master-0 "Stopped -> Slave" +do_test master-1 "Stopped -> Promote" +do_test master-2 "Stopped -> Promote : notify" +do_test master-3 "Stopped -> Promote : master location" +do_test master-4 "Started -> Promote : master location" +do_test master-5 "Promoted -> Promoted" +do_test master-6 "Promoted -> Promoted (2)" +do_test master-7 "Promoted -> Fenced" +do_test master-8 "Promoted -> Fenced -> Moved" +do_test master-9 "Stopped + Promotable + No quorum" +do_test master-10 "Stopped -> Promotable : notify with monitor" +do_test master-11 "Stopped -> Promote : colocation" +do_test novell-239082 "Demote/Promote ordering" +do_test novell-239087 "Stable master placement" +do_test master-12 "Promotion based solely on rsc_location constraints" +do_test master-13 "Include preferences of colocated resources when placing master" +do_test master-demote "Ordering when actions depends on demoting a slave resource" +do_test master-ordering "Prevent resources from starting that need a master" +do_test bug-1765 "Master-Master Colocation (dont stop the slaves)" +do_test master-group "Promotion of cloned groups" + +echo "" +do_test managed-0 "Managed (reference)" +do_test managed-1 "Not managed - down " +do_test managed-2 "Not managed - up " + +echo "" +do_test interleave-0 "Interleave (reference)" +do_test interleave-1 "coloc - not interleaved" +do_test interleave-2 "coloc - interleaved " +do_test interleave-3 "coloc - interleaved (2)" + +echo "" +do_test notify-0 "Notify reference" +do_test notify-1 "Notify simple" +do_test notify-2 "Notify simple, confirm" +do_test notify-3 "Notify move, confirm" +do_test novell-239079 "Notification priority" +#do_test notify-2 "Notify - 764" + +echo "" +do_test 594 "OSDL #594" +do_test 662 "OSDL #662" +do_test 696 "OSDL #696" +do_test 726 "OSDL #726" +do_test 735 "OSDL #735" +do_test 764 "OSDL #764" +do_test 797 "OSDL #797" +do_test 829 "OSDL #829" +do_test 994 "OSDL #994" +do_test 1360 "OSDL #1360 - Clone stickiness" +do_test 1484 "OSDL #1484 - on_fail=stop" +do_test 1494 "OSDL #1494 - Clone stability" +do_test unrunnable-1 "Unrunnable" +do_test stonith-0 "Stonith loop - 1" +do_test stonith-1 "Stonith loop - 2" +do_test stonith-2 "Stonith loop - 3" +do_test bug-1572-1 "Recovery of groups depending on master/slave" +do_test bug-1572-2 "Recovery of groups depending on master/slave when the master is never re-promoted" +do_test bug-1685 "Depends-on-master ordering" +do_test bug-1822 "Dont promote partially active groups" + +echo "" + +test_results diff --git a/xml/resources.rng b/xml/resources.rng new file mode 100644 index 0000000000..d78e7ba113 --- /dev/null +++ b/xml/resources.rng @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + ocf + + + + + lsb + heartbeat + stonith + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Started + Slave + Master + + + + + + + nothing + quorum + fencing + + + + + + + ignore + block + stop + restart + fence + + + + + + + + + + + diff --git a/xml/rule.rng b/xml/rule.rng new file mode 100644 index 0000000000..2a507718c4 --- /dev/null +++ b/xml/rule.rng @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + or + and + + + + + + + + + + + + + + lt + gt + lte + gte + eq + ne + defined + not_defined + + + + + + + + + string + number + version + + + + + + + + + in_range + + + + + + + + + + + + + + + + + gt + + + + lt + + + + + + date_spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/score.rng b/xml/score.rng new file mode 100644 index 0000000000..ea55c78f4c --- /dev/null +++ b/xml/score.rng @@ -0,0 +1,18 @@ + + + + + + + + + + + INFINITY + +INFINITY + -INFINITY + + + + diff --git a/xml/upgrade.xsl b/xml/upgrade.xsl new file mode 100644 index 0000000000..86e9145ddc --- /dev/null +++ b/xml/upgrade.xsl @@ -0,0 +1,475 @@ + + + + + + + + + .auto- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .auto- + + + + + + + + + + + + + + + + + + + + true + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .auto- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + .meta + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + .meta + + + + + + + + + + + + + + + + + + + + + + + + + relax-ng + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + in_range + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + in_range + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .auto- + + + + + + + + +