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
60 xpath = crm_strdup_printf(XPATH_NODE_RULE, rule_id);
61 xpath_obj = xpath_search(cib_constraints, xpath);
62 num_results = numXpathResults(xpath_obj);
63
64 free(xpath);
65 freeXpathObject(xpath_obj);
66
67 if (num_results == 0) {
68 *error = "Rule not found";
69 return ENXIO;
70 }
71
72 if (num_results > 1) {
73
74 *error = "Found more than one rule with matching ID";
75 return pcmk_rc_duplicate_id;
76 }
77
78
79 xpath = crm_strdup_printf(XPATH_NODE_RULE "//date_expression", rule_id);
80 xpath_obj = xpath_search(cib_constraints, xpath);
81 num_results = numXpathResults(xpath_obj);
82
83 free(xpath);
84 freeXpathObject(xpath_obj);
85
86 if (num_results != 1) {
87 if (num_results == 0) {
88 *error = "Rule does not have a date expression";
89 } else {
90 *error = "Rule has more than one date expression";
91 }
92 return EOPNOTSUPP;
93 }
94
95
96 xpath = crm_strdup_printf(XPATH_NODE_RULE
97 "//" PCMK_XE_DATE_EXPRESSION
98 "[@" PCMK_XA_OPERATION
99 "!='" PCMK_VALUE_DATE_SPEC "']",
100 rule_id);
101 xpath_obj = xpath_search(cib_constraints, xpath);
102 num_results = numXpathResults(xpath_obj);
103
104 free(xpath);
105
106 if (num_results == 0) {
107 freeXpathObject(xpath_obj);
108
109 xpath = crm_strdup_printf(XPATH_NODE_RULE
110 "//" PCMK_XE_DATE_EXPRESSION
111 "[@" PCMK_XA_OPERATION
112 "='" PCMK_VALUE_DATE_SPEC "' "
113 "and " PCMK_XE_DATE_SPEC
114 "/@" PCMK_XA_YEARS " "
115 "and not(" PCMK_XE_DATE_SPEC
116 "/@" PCMK__XA_MOON ")]",
117 rule_id);
118 xpath_obj = xpath_search(cib_constraints, xpath);
119 num_results = numXpathResults(xpath_obj);
120
121 free(xpath);
122
123 if (num_results == 0) {
124 freeXpathObject(xpath_obj);
125 *error = "Rule must either not use " PCMK_XE_DATE_SPEC ", or use "
126 PCMK_XE_DATE_SPEC " with " PCMK_XA_YEARS "= but not "
127 PCMK__XA_MOON "=";
128 return EOPNOTSUPP;
129 }
130 }
131
132 match = getXpathResult(xpath_obj, 0);
133
134
135
136
137 pcmk__assert((match != NULL)
138 && (pcmk__condition_type(match) == pcmk__condition_datetime));
139
140 rc = pcmk__evaluate_date_expression(match, scheduler->now, NULL);
141 if (rc == pcmk_rc_undetermined) {
142 *error = "Error parsing rule";
143 }
144
145 freeXpathObject(xpath_obj);
146 return rc;
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 int
163 pcmk__check_rules(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *date,
164 const char **rule_ids)
165 {
166 pcmk_scheduler_t *scheduler = NULL;
167 int rc = pcmk_rc_ok;
168
169 pcmk__assert(out != NULL);
170
171 if (rule_ids == NULL) {
172
173 return pcmk_rc_ok;
174 }
175
176 rc = pcmk__init_scheduler(out, input, date, &scheduler);
177 if (rc != pcmk_rc_ok) {
178 return rc;
179 }
180
181 for (const char **rule_id = rule_ids; *rule_id != NULL; rule_id++) {
182 const char *error = NULL;
183 int last_rc = eval_rule(scheduler, *rule_id, &error);
184
185 out->message(out, "rule-check", *rule_id, last_rc, error);
186
187 if (last_rc != pcmk_rc_ok) {
188 rc = last_rc;
189 }
190 }
191
192 pe_free_working_set(scheduler);
193 return rc;
194 }
195
196
197 int
198 pcmk_check_rules(xmlNodePtr *xml, xmlNodePtr input, const crm_time_t *date,
199 const char **rule_ids)
200 {
201 pcmk__output_t *out = NULL;
202 int rc = pcmk_rc_ok;
203
204 rc = pcmk__xml_output_new(&out, xml);
205 if (rc != pcmk_rc_ok) {
206 return rc;
207 }
208
209 pcmk__register_lib_messages(out);
210
211 rc = pcmk__check_rules(out, input, date, rule_ids);
212 pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
213 return rc;
214 }