22 #include <sys/types.h> 63 .match_data = match_data,
96 .match_data = match_data,
107 const char *tag = NULL;
108 const char *attr = NULL;
111 tag = crm_element_name(expr);
134 #if ENABLE_VERSIONED_ATTRS 166 .match_data = match_data,
194 uint32_t epact, diy, goldn;
199 goldn = (y % 19) + 1;
200 epact = (11 * goldn + 18) % 30;
201 if ((epact == 25 && goldn > 11) || epact == 24)
204 return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
208 check_one(xmlNode *cron_spec,
const char *xml_field, uint32_t time_field) {
220 }
else if (low == high) {
222 if (time_field < low) {
224 }
else if (time_field > high) {
229 }
else if (low != -1 && high != -1) {
231 if (time_field < low) {
233 }
else if (time_field > high) {
238 }
else if (low == -1) {
241 }
else if (high == -1) {
248 crm_debug(
"Condition '%s' in %s: passed", value, xml_field);
250 crm_debug(
"Condition '%s' in %s: failed", value, xml_field);
257 check_passes(
int rc) {
266 #define CHECK_ONE(spec, name, var) do { \ 267 int subpart_rc = check_one(spec, name, var); \ 268 if (check_passes(subpart_rc) == FALSE) { \ 276 uint32_t h, m, s, y, d, w;
298 CHECK_ONE(cron_spec,
"moon", phase_of_the_moon(now));
307 #define update_field(xml_field, time_fn) \ 308 value = crm_element_value(duration_spec, xml_field); \ 309 if(value != NULL) { \ 310 int value_i = crm_parse_int(value, "0"); \ 311 time_fn(end, value_i); \ 318 const char *value = NULL;
370 if ((next_change != NULL) && (t != NULL)) {
404 typedef struct sorted_set_s {
407 const char *special_name;
412 sort_pairs(gconstpointer a, gconstpointer b)
417 if (a == NULL && b == NULL) {
419 }
else if (a == NULL) {
421 }
else if (b == NULL) {
425 if (pcmk__str_eq(pair_a->name, pair_a->special_name,
pcmk__str_casei)) {
428 }
else if (pcmk__str_eq(pair_b->name, pair_a->special_name,
pcmk__str_casei)) {
432 if (pair_a->score < pair_b->score) {
434 }
else if (pair_a->score > pair_b->score) {
441 populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
443 const char *
name = NULL;
444 const char *value = NULL;
445 const char *old_value = NULL;
446 xmlNode *list = nvpair_list;
447 xmlNode *an_attr = NULL;
449 name = crm_element_name(list->children);
451 list = list->children;
454 for (an_attr = pcmk__xe_first_child(list); an_attr != NULL;
455 an_attr = pcmk__xe_next(an_attr)) {
470 if (
name == NULL || value == NULL) {
474 old_value = g_hash_table_lookup(hash,
name);
478 crm_trace(
"Letting %s default (removing explicit value \"%s\")",
480 g_hash_table_remove(hash,
name);
484 }
else if (old_value == NULL) {
486 g_hash_table_insert(hash, strdup(
name), strdup(value));
488 }
else if (overwrite) {
489 crm_trace(
"Setting %s=\"%s\" (overwriting old value \"%s\")",
490 name, value, old_value);
491 g_hash_table_replace(hash, strdup(
name), strdup(value));
497 #if ENABLE_VERSIONED_ATTRS 499 get_versioned_rule(xmlNode * attr_set)
501 xmlNode * rule = NULL;
502 xmlNode * expr = NULL;
504 for (rule = pcmk__xe_first_child(attr_set); rule != NULL;
505 rule = pcmk__xe_next(rule)) {
507 if (pcmk__str_eq((
const char *)rule->name,
XML_TAG_RULE,
509 for (expr = pcmk__xe_first_child(rule); expr != NULL;
510 expr = pcmk__xe_next(expr)) {
523 add_versioned_attributes(xmlNode * attr_set, xmlNode * versioned_attrs)
525 xmlNode *attr_set_copy = NULL;
526 xmlNode *rule = NULL;
527 xmlNode *expr = NULL;
529 if (!attr_set || !versioned_attrs) {
535 rule = get_versioned_rule(attr_set_copy);
541 expr = pcmk__xe_first_child(rule);
542 while (expr != NULL) {
544 xmlNode *node = expr;
546 expr = pcmk__xe_next(expr);
549 expr = pcmk__xe_next(expr);
557 typedef struct unpack_data_s {
566 unpack_attr_set(gpointer
data, gpointer user_data)
572 unpack_data->next_change)) {
576 #if ENABLE_VERSIONED_ATTRS 577 if (get_versioned_rule(pair->attr_set) && !(unpack_data->rule_data->node_hash &&
578 g_hash_table_lookup_extended(unpack_data->rule_data->node_hash,
585 crm_trace(
"Adding attributes from %s (score %d) %s overwrite",
586 pair->name, pair->score,
587 (unpack_data->overwrite?
"with" :
"without"));
588 populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite, unpack_data->top);
591 #if ENABLE_VERSIONED_ATTRS 593 unpack_versioned_attr_set(gpointer
data, gpointer user_data)
599 unpack_data->next_change)) {
600 add_versioned_attributes(pair->attr_set, unpack_data->hash);
617 make_pairs(xmlNode *top, xmlNode *xml_obj,
const char *set_name,
618 const char *always_first)
621 const char *score = NULL;
623 xmlNode *attr_set = NULL;
625 if (xml_obj == NULL) {
628 for (attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
629 attr_set = pcmk__xe_next(attr_set)) {
635 if (attr_set == NULL) {
640 pair->name =
ID(attr_set);
641 pair->special_name = always_first;
642 pair->attr_set = attr_set;
647 unsorted = g_list_prepend(unsorted, pair);
650 return g_list_sort(unsorted, sort_pairs);
668 unpack_nvpair_blocks(xmlNode *top, xmlNode *xml_obj,
const char *set_name,
669 void *hash,
const char *always_first, gboolean overwrite,
673 GList *pairs = make_pairs(top, xml_obj, set_name, always_first);
678 .overwrite = overwrite,
679 .next_change = next_change,
681 .rule_data = rule_data
684 g_list_foreach(pairs, unpack_func, &
data);
685 g_list_free_full(pairs, free);
692 const char *always_first, gboolean overwrite,
695 unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
696 overwrite, rule_data, next_change, unpack_attr_set);
714 GHashTable *node_hash, GHashTable *hash,
715 const char *always_first, gboolean overwrite,
728 always_first, overwrite, next_change);
731 #if ENABLE_VERSIONED_ATTRS 733 pe_eval_versioned_attributes(xmlNode *top, xmlNode *xml_obj,
const char *set_name,
737 unpack_nvpair_blocks(top, xml_obj, set_name, hash, NULL, FALSE, rule_data,
738 next_change, unpack_versioned_attr_set);
747 const char *p, *last_match_index;
748 char *p_dst, *result = NULL;
750 if (pcmk__str_empty(
string) || !match_data) {
754 p = last_match_index = string;
757 if (*p ==
'%' && *(p + 1) && isdigit(*(p + 1))) {
759 if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
760 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
761 len += p - last_match_index + (match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so);
762 last_match_index = p + 2;
768 len += p - last_match_index + 1;
775 p_dst = result = calloc(1, len);
779 if (*p ==
'%' && *(p + 1) && isdigit(*(p + 1))) {
781 if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
782 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
784 int match_len = match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so;
785 memcpy(p_dst, match_data->
string + match_data->
pmatch[i].rm_so, match_len);
799 #if ENABLE_VERSIONED_ATTRS 801 pe_unpack_versioned_parameters(xmlNode *versioned_params,
const char *ra_version)
803 GHashTable *hash = crm_str_table_new();
805 if (versioned_params && ra_version) {
806 GHashTable *node_hash = crm_str_table_new();
807 xmlNode *attr_set = pcmk__xe_first_child(versioned_params);
813 crm_element_name(attr_set), node_hash, hash, NULL,
817 g_hash_table_destroy(node_hash);
828 gboolean ruleset_default = TRUE;
833 ruleset_default = FALSE;
845 return ruleset_default;
851 xmlNode *expr = NULL;
852 gboolean test = TRUE;
853 gboolean empty = TRUE;
854 gboolean passed = TRUE;
855 gboolean do_and = TRUE;
856 const char *value = NULL;
866 for (expr = pcmk__xe_first_child(rule); expr != NULL;
867 expr = pcmk__xe_next(expr)) {
872 if (test && do_and == FALSE) {
876 }
else if (test == FALSE && do_and) {
883 crm_err(
"Invalid Rule %s: rules must contain at least one expression",
ID(rule));
886 crm_trace(
"Rule %s %s",
ID(rule), passed ?
"passed" :
"failed");
893 gboolean accept = FALSE;
894 const char *
uname = NULL;
926 #if ENABLE_VERSIONED_ATTRS 929 g_hash_table_lookup_extended(rule_data->
node_hash,
948 ID(expr), accept ?
"passed" :
"failed",
uname ?
uname :
"all nodes");
968 compare_attr_expr_vals(
const char *l_val,
const char *r_val,
const char *
type,
973 if (l_val != NULL && r_val != NULL) {
985 crm_trace(
"Defaulting to %s based comparison for '%s' op",
type, op);
989 cmp = strcasecmp(l_val, r_val);
998 if (rc1 == 0 && rc2 == 0) {
999 if (l_val_num < r_val_num) {
1001 }
else if (l_val_num > r_val_num) {
1008 crm_debug(
"Integer parse error. Comparing %s and %s as strings",
1010 cmp = compare_attr_expr_vals(l_val, r_val,
"string", op);
1021 if (l_val_num < r_val_num) {
1023 }
else if (l_val_num > r_val_num) {
1030 crm_debug(
"Floating-point parse error. Comparing %s and %s as " 1031 "strings", l_val, r_val);
1032 cmp = compare_attr_expr_vals(l_val, r_val,
"string", op);
1040 }
else if (l_val == NULL && r_val == NULL) {
1042 }
else if (r_val == NULL) {
1066 accept_attr_expr(
const char *l_val,
const char *r_val,
const char *
type,
1072 return (l_val != NULL);
1075 return (l_val == NULL);
1079 cmp = compare_attr_expr_vals(l_val, r_val,
type, op);
1087 }
else if (l_val == NULL || r_val == NULL) {
1110 gboolean attr_allocated = FALSE;
1111 const char *h_val = NULL;
1112 GHashTable *table = NULL;
1114 const char *op = NULL;
1115 const char *
type = NULL;
1116 const char *attr = NULL;
1117 const char *value = NULL;
1118 const char *value_source = NULL;
1126 if (attr == NULL || op == NULL) {
1127 pe_err(
"Invalid attribute or operation in expression" 1136 if (resolved_attr) {
1137 attr = (
const char *) resolved_attr;
1138 attr_allocated = TRUE;
1150 const char *param_name = value;
1151 const char *param_value = NULL;
1153 if (param_name && param_name[0]) {
1154 if ((param_value = (
const char *)g_hash_table_lookup(table, param_name))) {
1155 value = param_value;
1161 h_val = (
const char *)g_hash_table_lookup(rule_data->
node_hash, attr);
1164 if (attr_allocated) {
1169 return accept_attr_expr(h_val, value,
type, op);
1179 const char *value = NULL;
1182 xmlNode *duration_spec = NULL;
1183 xmlNode *date_spec = NULL;
1194 if (value != NULL) {
1198 if (value != NULL) {
1202 if (start != NULL && end == NULL && duration_spec != NULL) {
1207 if ((start == NULL) && (end == NULL)) {
1211 crm_time_set_if_earlier(next_change, start);
1216 if (end && next_change) {
1219 crm_time_set_if_earlier(next_change, end);
1228 if (start == NULL) {
1237 crm_time_set_if_earlier(next_change, start);
1245 crm_time_set_if_earlier(next_change, end);
1262 crm_trace(
"Testing op_defaults expression: %s",
ID(expr));
1264 if (rule_data->
op_data == NULL) {
1265 crm_trace(
"No operations data provided");
1270 if (interval == 0 && errno != 0) {
1271 crm_trace(
"Could not parse interval: %s", interval_s);
1291 gboolean accept = FALSE;
1292 const char *op = NULL;
1293 const char *value = NULL;
1336 crm_trace(
"Testing rsc_defaults expression: %s",
ID(expr));
1343 if (
class != NULL &&
1384 const char *set_name, GHashTable *node_hash,
1385 GHashTable *hash,
const char *always_first,
1397 return pe_test_rule(rule, node_hash, role, now, NULL, NULL);
1404 .
re = re_match_data,
1408 return pe_test_rule(rule, node_hash, role, now, NULL, &match_data);
1415 return pe_test_rule(rule, node_hash, role, now, NULL, match_data);
1428 .
re = re_match_data,
1445 GHashTable *node_hash, GHashTable *hash,
1446 const char *always_first, gboolean overwrite,
1458 unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
1459 overwrite, &rule_data, NULL, unpack_attr_set);
#define CRM_CHECK(expr, failure_action)
void crm_time_add_years(crm_time_t *dt, int value)
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)
Add a given number of seconds to a date/time or duration.
bool pcmk__char_in_any_str(int ch,...) G_GNUC_NULL_TERMINATED
#define XML_EXPR_ATTR_TYPE
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
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
xmlNode * first_named_child(const xmlNode *parent, const char *name)
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_LRM_ATTR_INTERVAL
#define XML_EXPR_ATTR_VALUE_SOURCE
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.
int pe_eval_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
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)
guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
#define CRM_ATTR_RA_VERSION
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_CIB_TAG_NVPAIR
gboolean pe_eval_rules(xmlNode *ruleset, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
void crm_time_add_hours(crm_time_t *dt, int value)
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)
xmlNode * copy_xml(xmlNode *src_node)
pe_match_data_t * match_data
int pe__eval_date_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
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)
pe_op_eval_data_t * op_data
#define crm_debug(fmt, args...)
gboolean pe_eval_subexpr(xmlNode *expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
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_attr_expression(xmlNode *expr, GHashTable *hash, 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)
#define XML_AGENT_ATTR_PROVIDER
Wrappers for and extensions to libxml2.
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
void crm_time_add_minutes(crm_time_t *dt, int value)
#define XML_EXPR_ATTR_OPERATION
gboolean pe__eval_role_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
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.
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)
int pcmk__scan_double(const char *text, double *result, const char *default_text, char **end_text)
pe_rsc_eval_data_t * rsc_data
gboolean pe_eval_expr(xmlNode *rule, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
#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)
crm_time_t * pe_parse_xml_duration(crm_time_t *start, xmlNode *duration_spec)
struct unpack_data_s unpack_data_t
CRM_TRACE_INIT_DATA(pe_rules)
long long crm_parse_ll(const char *text, const char *default_text)
Parse a long long integer value from a string.
struct sorted_set_s sorted_set_t
void pe_eval_nvpairs(xmlNode *top, xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *next_change)
gboolean pe_test_role_expression(xmlNode *expr, enum rsc_role_e role, 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__eval_op_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
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)
gboolean pe__eval_rsc_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
#define XML_NVPAIR_ATTR_VALUE
gboolean pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
int crm_time_compare(crm_time_t *dt, crm_time_t *rhs)
int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child)
int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end)
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)
enum expression_type find_expression_type(xmlNode *expr)
gboolean pe_test_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
int pe_cron_range_satisfied(crm_time_t *now, xmlNode *cron_spec)
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
#define XML_AGENT_ATTR_CLASS
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
void crm_time_free(crm_time_t *dt)