20 #include <sys/types.h> 37 gboolean ruleset_default = TRUE;
40 for (rule = __xml_first_child_element(ruleset); rule != NULL;
41 rule = __xml_next_element(rule)) {
44 ruleset_default = FALSE;
51 return ruleset_default;
76 gboolean empty = TRUE;
77 gboolean passed = TRUE;
78 gboolean do_and = TRUE;
79 const char *value = NULL;
89 for (expr = __xml_first_child_element(rule); expr != NULL;
90 expr = __xml_next_element(expr)) {
95 if (test && do_and == FALSE) {
99 }
else if (test == FALSE && do_and) {
106 crm_err(
"Invalid Rule %s: rules must contain at least one expression",
ID(rule));
109 crm_trace(
"Rule %s %s",
ID(rule), passed ?
"passed" :
"failed");
133 gboolean accept = FALSE;
134 const char *
uname = NULL;
145 if (node_hash != NULL) {
158 #ifdef ENABLE_VERSIONED_ATTRS 160 if (node_hash && g_hash_table_lookup_extended(node_hash,
180 ID(expr), accept ?
"passed" :
"failed", uname ? uname :
"all nodes");
187 const char *tag = NULL;
188 const char *attr = NULL;
191 tag = crm_element_name(expr);
210 #ifdef ENABLE_VERSIONED_ATTRS 222 gboolean accept = FALSE;
223 const char *op = NULL;
224 const char *value = NULL;
269 gboolean accept = FALSE;
270 gboolean attr_allocated = FALSE;
272 const char *h_val = NULL;
273 GHashTable *table = NULL;
275 const char *op = NULL;
276 const char *
type = NULL;
277 const char *attr = NULL;
278 const char *value = NULL;
279 const char *value_source = NULL;
287 if (attr == NULL || op == NULL) {
288 pe_err(
"Invalid attribute or operation in expression" 294 if (match_data->
re) {
298 attr = (
const char *) resolved_attr;
299 attr_allocated = TRUE;
304 table = match_data->
params;
306 table = match_data->
meta;
311 const char *param_name = value;
312 const char *param_value = NULL;
314 if (param_name && param_name[0]) {
315 if ((param_value = (
const char *)g_hash_table_lookup(table, param_name))) {
322 h_val = (
const char *)g_hash_table_lookup(hash, attr);
325 if (attr_allocated) {
330 if (value != NULL && h_val != NULL) {
341 crm_trace(
"Defaulting to %s based comparison for '%s' op", type, op);
345 cmp = strcasecmp(h_val, value);
351 if (h_val_f < value_f) {
353 }
else if (h_val_f > value_f) {
364 }
else if (value == NULL && h_val == NULL) {
366 }
else if (value == NULL) {
383 if ((h_val == value) || cmp == 0) {
388 if ((h_val == NULL && value != NULL)
389 || (h_val != NULL && value == NULL)
394 }
else if (value == NULL || h_val == NULL) {
447 goldn = (y % 19) + 1;
448 epact = (11 * goldn + 18) % 30;
449 if ((epact == 25 && goldn > 11) || epact == 24)
452 return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
456 decodeNVpair(
const char *srcstring,
char separator,
char **name,
char **value)
460 const char *temp = NULL;
466 crm_trace(
"Attempting to decode: [%s]", srcstring);
467 if (srcstring != NULL) {
468 len = strlen(srcstring);
470 if (srcstring[lpc] == separator) {
471 *name = calloc(1, lpc + 1);
475 memcpy(*name, srcstring, lpc);
487 *value = calloc(1, len + 1);
488 if (*value == NULL) {
491 temp = srcstring + lpc + 1;
492 memcpy(*value, temp, len);
493 (*value)[len] =
'\0';
511 #define cron_check(xml_field, time_field) \ 512 value = crm_element_value(cron_spec, xml_field); \ 513 if(value != NULL) { \ 514 gboolean pass = TRUE; \ 515 decodeNVpair(value, '-', &value_low, &value_high); \ 516 if(value_low == NULL) { \ 517 value_low = strdup(value); \ 519 value_low_i = crm_parse_int(value_low, "0"); \ 520 value_high_i = crm_parse_int(value_high, "-1"); \ 521 if(value_high_i < 0) { \ 522 if(value_low_i != time_field) { \ 525 } else if(value_low_i > time_field) { \ 527 } else if(value_high_i < time_field) { \ 532 if(pass == FALSE) { \ 533 crm_debug("Condition '%s' in %s: failed", value, xml_field); \ 536 crm_debug("Condition '%s' in %s: passed", value, xml_field); \ 542 const char *value = NULL;
543 char *value_low = NULL;
544 char *value_high = NULL;
547 int value_high_i = 0;
580 #define update_field(xml_field, time_fn) \ 581 value = crm_element_value(duration_spec, xml_field); \ 582 if(value != NULL) { \ 583 int value_i = crm_parse_int(value, "0"); \ 584 time_fn(end, value_i); \ 591 const char *value = NULL;
612 const char *value = NULL;
615 xmlNode *duration_spec = NULL;
616 xmlNode *date_spec = NULL;
618 gboolean passed = FALSE;
620 crm_trace(
"Testing expression: %s",
ID(time_expr));
634 if (start != NULL && end == NULL && duration_spec != NULL) {
670 typedef struct sorted_set_s {
673 const char *special_name;
678 sort_pairs(gconstpointer a, gconstpointer b)
683 if (a == NULL && b == NULL) {
685 }
else if (a == NULL) {
687 }
else if (b == NULL) {
691 if (
safe_str_eq(pair_a->name, pair_a->special_name)) {
694 }
else if (
safe_str_eq(pair_b->name, pair_a->special_name)) {
698 if (pair_a->score < pair_b->score) {
700 }
else if (pair_a->score > pair_b->score) {
707 populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
709 const char *name = NULL;
710 const char *value = NULL;
711 const char *old_value = NULL;
712 xmlNode *list = nvpair_list;
713 xmlNode *an_attr = NULL;
715 name = crm_element_name(list->children);
717 list = list->children;
720 for (an_attr = __xml_first_child_element(list); an_attr != NULL;
721 an_attr = __xml_next_element(an_attr)) {
731 crm_trace(
"Setting attribute: %s", name);
737 if (name == NULL || value == NULL) {
742 old_value = g_hash_table_lookup(hash, name);
746 crm_trace(
"Removing value for %s (%s)", name, value);
747 g_hash_table_remove(hash, name);
751 }
else if (old_value == NULL) {
752 g_hash_table_insert(hash, strdup(name), strdup(value));
754 }
else if (overwrite) {
755 crm_debug(
"Overwriting value of %s: %s -> %s", name, old_value, value);
756 g_hash_table_replace(hash, strdup(name), strdup(value));
762 #ifdef ENABLE_VERSIONED_ATTRS 764 get_versioned_rule(xmlNode * attr_set)
766 xmlNode * rule = NULL;
767 xmlNode * expr = NULL;
769 for (rule = __xml_first_child_element(attr_set); rule != NULL;
770 rule = __xml_next_element(rule)) {
773 for (expr = __xml_first_child_element(rule); expr != NULL;
774 expr = __xml_next_element(expr)) {
787 add_versioned_attributes(xmlNode * attr_set, xmlNode * versioned_attrs)
789 xmlNode *attr_set_copy = NULL;
790 xmlNode *rule = NULL;
791 xmlNode *expr = NULL;
793 if (!attr_set || !versioned_attrs) {
799 rule = get_versioned_rule(attr_set_copy);
805 expr = __xml_first_child_element(rule);
806 while (expr != NULL) {
808 xmlNode *node = expr;
810 expr = __xml_next_element(expr);
813 expr = __xml_next_element(expr);
821 typedef struct unpack_data_s {
823 GHashTable *node_hash;
830 unpack_attr_set(gpointer
data, gpointer user_data)
835 if (
test_ruleset(pair->attr_set, unpack_data->node_hash, unpack_data->now) == FALSE) {
839 #ifdef ENABLE_VERSIONED_ATTRS 840 if (get_versioned_rule(pair->attr_set) && !(unpack_data->node_hash &&
841 g_hash_table_lookup_extended(unpack_data->node_hash,
848 crm_trace(
"Adding attributes from %s", pair->name);
849 populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite, unpack_data->top);
852 #ifdef ENABLE_VERSIONED_ATTRS 854 unpack_versioned_attr_set(gpointer
data, gpointer user_data)
859 if (
test_ruleset(pair->attr_set, unpack_data->node_hash, unpack_data->now) == FALSE) {
863 add_versioned_attributes(pair->attr_set, unpack_data->hash);
868 make_pairs_and_populate_data(xmlNode * top, xmlNode * xml_obj,
const char *set_name,
869 GHashTable * node_hash,
void * hash,
const char *always_first,
873 const char *score = NULL;
875 xmlNode *attr_set = NULL;
877 if (xml_obj == NULL) {
883 for (attr_set = __xml_first_child_element(xml_obj); attr_set != NULL;
884 attr_set = __xml_next_element(attr_set)) {
887 if (set_name == NULL ||
crm_str_eq((
const char *)attr_set->name, set_name, TRUE)) {
890 if (attr_set == NULL) {
895 pair->name =
ID(attr_set);
896 pair->special_name = always_first;
897 pair->attr_set = attr_set;
902 unsorted = g_list_prepend(unsorted, pair);
908 data->node_hash = node_hash;
910 data->overwrite = overwrite;
915 return g_list_sort(unsorted, sort_pairs);
923 GHashTable * node_hash, GHashTable * hash,
const char *always_first,
927 GListPtr pairs = make_pairs_and_populate_data(top, xml_obj, set_name, node_hash, hash,
928 always_first, overwrite, now, &data);
931 g_list_foreach(pairs, unpack_attr_set, &data);
932 g_list_free_full(pairs, free);
936 #ifdef ENABLE_VERSIONED_ATTRS 938 pe_unpack_versioned_attributes(xmlNode * top, xmlNode * xml_obj,
const char *set_name,
939 GHashTable * node_hash, xmlNode * hash,
crm_time_t * now)
942 GListPtr pairs = make_pairs_and_populate_data(top, xml_obj, set_name, node_hash, hash,
943 NULL, FALSE, now, &data);
946 g_list_foreach(pairs, unpack_versioned_attr_set, &data);
947 g_list_free_full(pairs, free);
957 const char *p, *last_match_index;
958 char *p_dst, *result = NULL;
960 if (!
string ||
string[0] ==
'\0' || !match_data) {
964 p = last_match_index = string;
967 if (*p ==
'%' && *(p + 1) && isdigit(*(p + 1))) {
969 if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
970 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
971 len += p - last_match_index + (match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so);
972 last_match_index = p + 2;
978 len += p - last_match_index + 1;
985 p_dst = result = calloc(1, len);
989 if (*p ==
'%' && *(p + 1) && isdigit(*(p + 1))) {
991 if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
992 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
994 int match_len = match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so;
995 memcpy(p_dst, match_data->
string + match_data->
pmatch[i].rm_so, match_len);
1009 #ifdef ENABLE_VERSIONED_ATTRS 1011 pe_unpack_versioned_parameters(xmlNode *versioned_params,
const char *ra_version)
1013 GHashTable *hash = crm_str_table_new();
1015 if (versioned_params && ra_version) {
1016 GHashTable *node_hash = crm_str_table_new();
1017 xmlNode *attr_set = __xml_first_child_element(versioned_params);
1021 strdup(ra_version));
1023 node_hash, hash, NULL, FALSE, NULL);
1026 g_hash_table_destroy(node_hash);
#define CRM_CHECK(expr, failure_action)
void crm_time_add_years(crm_time_t *dt, int value)
#define cron_check(xml_field, time_field)
gboolean pe_test_rule_re(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_re_match_data_t *re_match_data)
void crm_time_add_seconds(crm_time_t *dt, int value)
gboolean safe_str_neq(const char *a, const char *b)
#define XML_EXPR_ATTR_TYPE
struct crm_time_s crm_time_t
gboolean test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)
#define XML_RULE_ATTR_SCORE
int char2score(const char *score)
gboolean pe_test_expression_re(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_re_match_data_t *re_match_data)
#define XML_EXPR_ATTR_VALUE_SOURCE
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
int crm_time_get_ordinal(crm_time_t *dt, uint32_t *y, uint32_t *d)
#define XML_NVPAIR_ATTR_NAME
gboolean test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now)
#define CRM_ATTR_RA_VERSION
#define XML_CIB_TAG_NVPAIR
void crm_time_add_hours(crm_time_t *dt, int value)
gboolean cron_range_satisfied(crm_time_t *now, xmlNode *cron_spec)
gboolean pe_test_expression_full(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_match_data_t *match_data)
gboolean pe_test_attr_expression_full(xmlNode *expr, GHashTable *hash, crm_time_t *now, pe_match_data_t *match_data)
xmlNode * copy_xml(xmlNode *src_node)
#define crm_debug(fmt, args...)
void crm_time_add_weeks(crm_time_t *dt, int value)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define XML_EXPR_ATTR_VALUE
void crm_time_add_months(crm_time_t *dt, int value)
#define crm_trace(fmt, args...)
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Wrappers for and extensions to libxml2.
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
gboolean test_date_expression(xmlNode *time_expr, crm_time_t *now)
void crm_time_add_minutes(crm_time_t *dt, int value)
#define XML_EXPR_ATTR_OPERATION
crm_time_t * parse_xml_duration(crm_time_t *start, xmlNode *duration_spec)
void free_xml(xmlNode *child)
gboolean pe_test_rule_full(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_match_data_t *match_data)
enum rsc_role_e text2role(const char *role)
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
#define XML_RULE_ATTR_BOOLEAN_OP
gboolean test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)
void populate_hash(xmlNode *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length)
struct unpack_data_s unpack_data_t
CRM_TRACE_INIT_DATA(pe_rules)
struct sorted_set_s sorted_set_t
int crm_time_get_gregorian(crm_time_t *dt, uint32_t *y, uint32_t *m, uint32_t *d)
#define crm_err(fmt, args...)
int crm_time_get_timeofday(crm_time_t *dt, uint32_t *h, uint32_t *m, uint32_t *s)
gboolean test_ruleset(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now)
void crm_time_set(crm_time_t *target, crm_time_t *source)
crm_time_t * crm_time_new(const char *string)
int compare_version(const char *version1, const char *version2)
#define XML_NVPAIR_ATTR_VALUE
int crm_time_compare(crm_time_t *dt, crm_time_t *rhs)
gboolean test_role_expression(xmlNode *expr, enum rsc_role_e role, crm_time_t *now)
int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child)
xmlNode * first_named_child(xmlNode *parent, const char *name)
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now)
#define safe_str_eq(a, b)
enum expression_type find_expression_type(xmlNode *expr)
int crm_time_get_isoweek(crm_time_t *dt, uint32_t *y, uint32_t *w, uint32_t *d)
#define XML_EXPR_ATTR_ATTRIBUTE
void crm_time_add_days(crm_time_t *dt, int value)
#define update_field(xml_field, time_fn)
enum crm_ais_msg_types type
void crm_time_free(crm_time_t *dt)