21 #include <sys/types.h>
42 gboolean ruleset_default = TRUE;
47 ruleset_default = FALSE;
59 return ruleset_default;
69 gboolean empty = TRUE;
70 gboolean passed = TRUE;
71 gboolean do_and = TRUE;
72 const char *value = NULL;
82 for (expr = __xml_first_child_element(rule); expr != NULL;
83 expr = __xml_next_element(expr)) {
89 if (test && do_and == FALSE) {
93 }
else if (test == FALSE && do_and) {
100 crm_err(
"Invalid Rule %s: rules must contain at least one expression",
ID(rule));
103 crm_trace(
"Rule %s %s",
ID(rule), passed ?
"passed" :
"failed");
128 gboolean accept = FALSE;
129 const char *
uname = NULL;
133 accept =
pe_test_rule(expr, node_hash, role, now, next_change,
141 if (node_hash != NULL) {
154 #if ENABLE_VERSIONED_ATTRS
156 if (node_hash && g_hash_table_lookup_extended(node_hash,
176 ID(expr), accept ?
"passed" :
"failed", uname ? uname :
"all nodes");
183 const char *tag = NULL;
184 const char *attr = NULL;
187 tag = crm_element_name(expr);
206 #if ENABLE_VERSIONED_ATTRS
218 gboolean accept = FALSE;
219 const char *op = NULL;
220 const char *value = NULL;
260 gboolean accept = FALSE;
261 gboolean attr_allocated = FALSE;
263 const char *h_val = NULL;
264 GHashTable *table = NULL;
266 const char *op = NULL;
267 const char *
type = NULL;
268 const char *attr = NULL;
269 const char *value = NULL;
270 const char *value_source = NULL;
278 if (attr == NULL || op == NULL) {
279 pe_err(
"Invalid attribute or operation in expression"
285 if (match_data->
re) {
289 attr = (
const char *) resolved_attr;
290 attr_allocated = TRUE;
295 table = match_data->
params;
297 table = match_data->
meta;
302 const char *param_name = value;
303 const char *param_value = NULL;
305 if (param_name && param_name[0]) {
306 if ((param_value = (
const char *)g_hash_table_lookup(table, param_name))) {
313 h_val = (
const char *)g_hash_table_lookup(hash, attr);
316 if (attr_allocated) {
321 if (value != NULL && h_val != NULL) {
332 crm_trace(
"Defaulting to %s based comparison for '%s' op", type, op);
336 cmp = strcasecmp(h_val, value);
342 if (h_val_f < value_f) {
344 }
else if (h_val_f > value_f) {
355 }
else if (value == NULL && h_val == NULL) {
357 }
else if (value == NULL) {
374 if ((h_val == value) || cmp == 0) {
379 if ((h_val == NULL && value != NULL)
380 || (h_val != NULL && value == NULL)
385 }
else if (value == NULL || h_val == NULL) {
433 uint32_t epact, diy, goldn;
438 goldn = (y % 19) + 1;
439 epact = (11 * goldn + 18) % 30;
440 if ((epact == 25 && goldn > 11) || epact == 24)
443 return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
447 check_one(xmlNode *cron_spec,
const char *xml_field, uint32_t time_field) {
459 }
else if (low == high) {
461 if (time_field < low) {
463 }
else if (time_field > high) {
468 }
else if (low != -1 && high != -1) {
470 if (time_field < low) {
472 }
else if (time_field > high) {
477 }
else if (low == -1) {
480 }
else if (high == -1) {
487 crm_debug(
"Condition '%s' in %s: passed", value, xml_field);
489 crm_debug(
"Condition '%s' in %s: failed", value, xml_field);
496 check_passes(
int rc) {
505 #define CHECK_ONE(spec, name, var) do { \
506 int subpart_rc = check_one(spec, name, var); \
507 if (check_passes(subpart_rc) == FALSE) { \
515 uint32_t h, m, s, y, d, w;
537 CHECK_ONE(cron_spec,
"moon", phase_of_the_moon(now));
546 #define update_field(xml_field, time_fn) \
547 value = crm_element_value(duration_spec, xml_field); \
548 if(value != NULL) { \
549 int value_i = crm_parse_int(value, "0"); \
550 time_fn(end, value_i); \
557 const char *value = NULL;
601 if ((next_change != NULL) && (t != NULL)) {
625 const char *value = NULL;
628 xmlNode *duration_spec = NULL;
629 xmlNode *date_spec = NULL;
634 crm_trace(
"Testing expression: %s",
ID(time_expr));
648 if (start != NULL && end == NULL && duration_spec != NULL) {
653 if ((start == NULL) && (end == NULL)) {
657 crm_time_set_if_earlier(next_change, start);
662 if (end && next_change) {
665 crm_time_set_if_earlier(next_change, end);
683 crm_time_set_if_earlier(next_change, start);
691 crm_time_set_if_earlier(next_change, end);
703 typedef struct sorted_set_s {
706 const char *special_name;
711 sort_pairs(gconstpointer a, gconstpointer b)
716 if (a == NULL && b == NULL) {
718 }
else if (a == NULL) {
720 }
else if (b == NULL) {
724 if (
safe_str_eq(pair_a->name, pair_a->special_name)) {
727 }
else if (
safe_str_eq(pair_b->name, pair_a->special_name)) {
731 if (pair_a->score < pair_b->score) {
733 }
else if (pair_a->score > pair_b->score) {
740 populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
742 const char *
name = NULL;
743 const char *value = NULL;
744 const char *old_value = NULL;
745 xmlNode *list = nvpair_list;
746 xmlNode *an_attr = NULL;
748 name = crm_element_name(list->children);
750 list = list->children;
753 for (an_attr = __xml_first_child_element(list); an_attr != NULL;
754 an_attr = __xml_next_element(an_attr)) {
764 crm_trace(
"Setting attribute: %s", name);
770 if (name == NULL || value == NULL) {
775 old_value = g_hash_table_lookup(hash, name);
779 crm_trace(
"Removing value for %s (%s)", name, value);
780 g_hash_table_remove(hash, name);
784 }
else if (old_value == NULL) {
785 g_hash_table_insert(hash, strdup(name), strdup(value));
787 }
else if (overwrite) {
788 crm_debug(
"Overwriting value of %s: %s -> %s", name, old_value, value);
789 g_hash_table_replace(hash, strdup(name), strdup(value));
795 #if ENABLE_VERSIONED_ATTRS
797 get_versioned_rule(xmlNode * attr_set)
799 xmlNode * rule = NULL;
800 xmlNode * expr = NULL;
802 for (rule = __xml_first_child_element(attr_set); rule != NULL;
803 rule = __xml_next_element(rule)) {
806 for (expr = __xml_first_child_element(rule); expr != NULL;
807 expr = __xml_next_element(expr)) {
820 add_versioned_attributes(xmlNode * attr_set, xmlNode * versioned_attrs)
822 xmlNode *attr_set_copy = NULL;
823 xmlNode *rule = NULL;
824 xmlNode *expr = NULL;
826 if (!attr_set || !versioned_attrs) {
832 rule = get_versioned_rule(attr_set_copy);
838 expr = __xml_first_child_element(rule);
839 while (expr != NULL) {
841 xmlNode *node = expr;
843 expr = __xml_next_element(expr);
846 expr = __xml_next_element(expr);
854 typedef struct unpack_data_s {
856 GHashTable *node_hash;
864 unpack_attr_set(gpointer
data, gpointer user_data)
870 unpack_data->now, unpack_data->next_change)) {
874 #if ENABLE_VERSIONED_ATTRS
875 if (get_versioned_rule(pair->attr_set) && !(unpack_data->node_hash &&
876 g_hash_table_lookup_extended(unpack_data->node_hash,
883 crm_trace(
"Adding attributes from %s", pair->name);
884 populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite, unpack_data->top);
887 #if ENABLE_VERSIONED_ATTRS
889 unpack_versioned_attr_set(gpointer data, gpointer user_data)
895 unpack_data->now, unpack_data->next_change)) {
896 add_versioned_attributes(pair->attr_set, unpack_data->hash);
913 make_pairs(xmlNode *top, xmlNode *xml_obj,
const char *set_name,
914 const char *always_first)
917 const char *score = NULL;
919 xmlNode *attr_set = NULL;
921 if (xml_obj == NULL) {
927 for (attr_set = __xml_first_child_element(xml_obj); attr_set != NULL;
928 attr_set = __xml_next_element(attr_set)) {
931 if (set_name == NULL ||
crm_str_eq((
const char *)attr_set->name, set_name, TRUE)) {
934 if (attr_set == NULL) {
939 pair->name =
ID(attr_set);
940 pair->special_name = always_first;
941 pair->attr_set = attr_set;
946 unsorted = g_list_prepend(unsorted, pair);
949 return g_list_sort(unsorted, sort_pairs);
968 unpack_nvpair_blocks(xmlNode *top, xmlNode *xml_obj,
const char *set_name,
969 GHashTable *node_hash,
void *hash,
970 const char *always_first, gboolean overwrite,
974 GList *pairs = make_pairs(top, xml_obj, set_name, always_first);
979 .node_hash = node_hash,
981 .overwrite = overwrite,
982 .next_change = next_change,
986 g_list_foreach(pairs, unpack_func, &data);
987 g_list_free_full(pairs, free);
1006 GHashTable *node_hash, GHashTable *hash,
1007 const char *always_first, gboolean overwrite,
1010 unpack_nvpair_blocks(top, xml_obj, set_name, node_hash, hash, always_first,
1011 overwrite, now, next_change, unpack_attr_set);
1014 #if ENABLE_VERSIONED_ATTRS
1016 pe_unpack_versioned_attributes(xmlNode *top, xmlNode *xml_obj,
1017 const char *set_name, GHashTable *node_hash,
1021 unpack_nvpair_blocks(top, xml_obj, set_name, node_hash, hash, NULL, FALSE,
1022 now, next_change, unpack_versioned_attr_set);
1031 const char *p, *last_match_index;
1032 char *p_dst, *result = NULL;
1034 if (pcmk__str_empty(
string) || !match_data) {
1038 p = last_match_index = string;
1041 if (*p ==
'%' && *(p + 1) && isdigit(*(p + 1))) {
1043 if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
1044 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
1045 len += p - last_match_index + (match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so);
1046 last_match_index = p + 2;
1052 len += p - last_match_index + 1;
1059 p_dst = result = calloc(1, len);
1063 if (*p ==
'%' && *(p + 1) && isdigit(*(p + 1))) {
1065 if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
1066 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
1068 int match_len = match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so;
1069 memcpy(p_dst, match_data->
string + match_data->
pmatch[i].rm_so, match_len);
1083 #if ENABLE_VERSIONED_ATTRS
1085 pe_unpack_versioned_parameters(xmlNode *versioned_params,
const char *ra_version)
1087 GHashTable *hash = crm_str_table_new();
1089 if (versioned_params && ra_version) {
1090 GHashTable *node_hash = crm_str_table_new();
1091 xmlNode *attr_set = __xml_first_child_element(versioned_params);
1095 strdup(ra_version));
1097 crm_element_name(attr_set), node_hash, hash, NULL,
1101 g_hash_table_destroy(node_hash);
1127 const char *set_name, GHashTable *node_hash,
1128 GHashTable *hash,
const char *always_first,
1140 return pe_test_rule(rule, node_hash, role, now, NULL, NULL);
1147 .
re = re_match_data,
1151 return pe_test_rule(rule, node_hash, role, now, NULL, &match_data);
1158 return pe_test_rule(rule, node_hash, role, now, NULL, match_data);
1171 .
re = re_match_data,
1188 GHashTable *node_hash, GHashTable *hash,
1189 const char *always_first, gboolean overwrite,
1192 unpack_nvpair_blocks(top, xml_obj, set_name, node_hash, hash, always_first,
1193 overwrite, now, NULL, unpack_attr_set);
#define CRM_CHECK(expr, failure_action)
int pe_cron_range_satisfied(crm_time_t *now, xmlNode *cron_spec)
void crm_time_add_years(crm_time_t *dt, int value)
void crm_time_add_seconds(crm_time_t *dt, int value)
Add a given number of seconds to a date/time or duration.
gboolean safe_str_neq(const char *a, const char *b)
void pe_unpack_nvpairs(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table.
#define XML_EXPR_ATTR_TYPE
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
struct crm_time_s crm_time_t
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
#define XML_RULE_ATTR_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)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
int char2score(const char *score)
#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
#define CHECK_ONE(spec, name, var)
gboolean pe_test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
Evaluate one rule subelement (pass/fail)
#define CRM_ATTR_RA_VERSION
gboolean pe_test_role_expression(xmlNode *expr, enum rsc_role_e role, crm_time_t *now)
#define XML_CIB_TAG_NVPAIR
void crm_time_add_hours(crm_time_t *dt, int value)
enum expression_type find_expression_type(xmlNode *expr)
#define CRM_TRACE_INIT_DATA(name)
int pe_eval_date_expression(xmlNode *time_expr, crm_time_t *now, crm_time_t *next_change)
xmlNode * copy_xml(xmlNode *src_node)
gboolean pe_test_date_expression(xmlNode *time_expr, crm_time_t *now, crm_time_t *next_change)
#define crm_debug(fmt, args...)
crm_time_t * pe_parse_xml_duration(crm_time_t *start, xmlNode *duration_spec)
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.
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)
#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.
void crm_time_add_minutes(crm_time_t *dt, int value)
#define XML_EXPR_ATTR_OPERATION
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
void free_xml(xmlNode *child)
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
void populate_hash(xmlNode *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length)
gboolean pe_test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now, pe_match_data_t *match_data)
struct unpack_data_s unpack_data_t
struct sorted_set_s sorted_set_t
gboolean test_ruleset(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now)
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 pe_test_expression_full(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_match_data_t *match_data)
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
gboolean pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now, crm_time_t *next_change)
Evaluate any rules contained by given XML element.
int crm_time_compare(crm_time_t *dt, crm_time_t *rhs)
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)
int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child)
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)
gboolean test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)
#define safe_str_eq(a, b)
char int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end)
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
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
void crm_time_free(crm_time_t *dt)
gboolean test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)