This source file includes following definitions.
- eval_rule
- pcmk__check_rules
- pcmk_check_rules
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/cib/internal.h>
13 #include <crm/common/cib.h>
14 #include <crm/common/iso8601.h>
15 #include <crm/common/xml.h>
16 #include <crm/pengine/internal.h>
17 #include <crm/pengine/rules_internal.h>
18 #include <pacemaker-internal.h>
19
20 #include "libpacemaker_private.h"
21
22 #define XPATH_NODE_RULE "//" PCMK_XE_RULE "[@" PCMK_XA_ID "='%s']"
23
24
25
26
27
28
29
30
31
32
33
34 static int
35 eval_rule(pcmk_scheduler_t *scheduler, const char *rule_id, const char **error)
36 {
37 xmlNodePtr cib_constraints = NULL;
38 xmlNodePtr match = NULL;
39 xmlXPathObjectPtr xpath_obj = NULL;
40 char *xpath = NULL;
41 int rc = pcmk_rc_ok;
42 int num_results = 0;
43
44 *error = NULL;
45
46
47 cib_constraints = pcmk_find_cib_element(scheduler->input,
48 PCMK_XE_CONSTRAINTS);
49
50
51
52
53
54
55
56
57
58
59 xpath = crm_strdup_printf(XPATH_NODE_RULE, rule_id);
60 xpath_obj = xpath_search(cib_constraints, xpath);
61 num_results = numXpathResults(xpath_obj);
62
63 free(xpath);
64 freeXpathObject(xpath_obj);
65
66 if (num_results == 0) {
67 *error = "Rule not found";
68 return ENXIO;
69 }
70
71 if (num_results > 1) {
72
73 *error = "Found more than one rule with matching ID";
74 return pcmk_rc_duplicate_id;
75 }
76
77
78 xpath = crm_strdup_printf(XPATH_NODE_RULE "//date_expression", rule_id);
79 xpath_obj = xpath_search(cib_constraints, xpath);
80 num_results = numXpathResults(xpath_obj);
81
82 free(xpath);
83 freeXpathObject(xpath_obj);
84
85 if (num_results != 1) {
86 if (num_results == 0) {
87 *error = "Rule does not have a date expression";
88 } else {
89 *error = "Rule has more than one date expression";
90 }
91 return EOPNOTSUPP;
92 }
93
94
95 xpath = crm_strdup_printf(XPATH_NODE_RULE
96 "//" PCMK_XE_DATE_EXPRESSION
97 "[@" PCMK_XA_OPERATION
98 "!='" PCMK_VALUE_DATE_SPEC "']",
99 rule_id);
100 xpath_obj = xpath_search(cib_constraints, xpath);
101 num_results = numXpathResults(xpath_obj);
102
103 free(xpath);
104
105 if (num_results == 0) {
106 freeXpathObject(xpath_obj);
107
108 xpath = crm_strdup_printf(XPATH_NODE_RULE
109 "//" PCMK_XE_DATE_EXPRESSION
110 "[@" PCMK_XA_OPERATION
111 "='" PCMK_VALUE_DATE_SPEC "' "
112 "and " PCMK_XE_DATE_SPEC
113 "/@" PCMK_XA_YEARS "]",
114 rule_id);
115 xpath_obj = xpath_search(cib_constraints, xpath);
116 num_results = numXpathResults(xpath_obj);
117
118 free(xpath);
119
120 if (num_results == 0) {
121 freeXpathObject(xpath_obj);
122 *error = "Rule must either not use " PCMK_XE_DATE_SPEC ", or use "
123 PCMK_XE_DATE_SPEC " with " PCMK_XA_YEARS "=";
124 return EOPNOTSUPP;
125 }
126 }
127
128 match = getXpathResult(xpath_obj, 0);
129
130
131
132
133 pcmk__assert((match != NULL)
134 && (pcmk__condition_type(match) == pcmk__condition_datetime));
135
136 rc = pcmk__evaluate_date_expression(match, scheduler->priv->now, NULL);
137 if ((rc != pcmk_rc_ok) && (rc != pcmk_rc_within_range)) {
138
139 *error = "Error parsing rule";
140 }
141
142 freeXpathObject(xpath_obj);
143 return rc;
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 int
160 pcmk__check_rules(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *date,
161 const char **rule_ids)
162 {
163 pcmk_scheduler_t *scheduler = NULL;
164 int rc = pcmk_rc_ok;
165
166 pcmk__assert(out != NULL);
167
168 if (rule_ids == NULL) {
169
170 return pcmk_rc_ok;
171 }
172
173 rc = pcmk__init_scheduler(out, input, date, &scheduler);
174 if (rc != pcmk_rc_ok) {
175 return rc;
176 }
177
178 for (const char **rule_id = rule_ids; *rule_id != NULL; rule_id++) {
179 const char *error = NULL;
180 int last_rc = eval_rule(scheduler, *rule_id, &error);
181
182 out->message(out, "rule-check", *rule_id, last_rc, error);
183
184 if (last_rc != pcmk_rc_ok) {
185 rc = last_rc;
186 }
187 }
188
189 pe_free_working_set(scheduler);
190 return rc;
191 }
192
193
194 int
195 pcmk_check_rules(xmlNodePtr *xml, xmlNodePtr input, const crm_time_t *date,
196 const char **rule_ids)
197 {
198 pcmk__output_t *out = NULL;
199 int rc = pcmk_rc_ok;
200
201 rc = pcmk__xml_output_new(&out, xml);
202 if (rc != pcmk_rc_ok) {
203 return rc;
204 }
205
206 pcmk__register_lib_messages(out);
207
208 rc = pcmk__check_rules(out, input, date, rule_ids);
209 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
210 return rc;
211 }