This source file includes following definitions.
- evaluate_lifetime
- pcmk__unpack_constraints
- pcmk__find_constraint_resource
- find_constraint_tag
- pcmk__valid_resource_or_tag
- pcmk__expand_tags_in_sets
- pcmk__tag_to_set
- pcmk__create_internal_constraints
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <sys/types.h>
14 #include <stdbool.h>
15 #include <regex.h>
16 #include <glib.h>
17
18 #include <crm/crm.h>
19 #include <crm/cib.h>
20 #include <crm/msg_xml.h>
21 #include <crm/common/xml.h>
22 #include <crm/common/xml_internal.h>
23 #include <crm/common/iso8601.h>
24 #include <crm/pengine/status.h>
25 #include <crm/pengine/internal.h>
26 #include <crm/pengine/rules.h>
27 #include <pacemaker-internal.h>
28 #include "libpacemaker_private.h"
29
30 static bool
31 evaluate_lifetime(xmlNode *lifetime, pcmk_scheduler_t *scheduler)
32 {
33 bool result = FALSE;
34 crm_time_t *next_change = crm_time_new_undefined();
35
36 result = pe_evaluate_rules(lifetime, NULL, scheduler->now, next_change);
37 if (crm_time_is_defined(next_change)) {
38 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
39
40 pe__update_recheck_time(recheck, scheduler, "constraint lifetime");
41 }
42 crm_time_free(next_change);
43 return result;
44 }
45
46
47
48
49
50
51
52
53
54
55 void
56 pcmk__unpack_constraints(pcmk_scheduler_t *scheduler)
57 {
58 xmlNode *xml_constraints = pcmk_find_cib_element(scheduler->input,
59 XML_CIB_TAG_CONSTRAINTS);
60
61 for (xmlNode *xml_obj = pcmk__xe_first_child(xml_constraints);
62 xml_obj != NULL; xml_obj = pcmk__xe_next(xml_obj)) {
63
64 xmlNode *lifetime = NULL;
65 const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
66 const char *tag = (const char *) xml_obj->name;
67
68 if (id == NULL) {
69 pcmk__config_err("Ignoring <%s> constraint without "
70 XML_ATTR_ID, tag);
71 continue;
72 }
73
74 crm_trace("Unpacking %s constraint '%s'", tag, id);
75
76 lifetime = first_named_child(xml_obj, "lifetime");
77 if (lifetime != NULL) {
78 pcmk__config_warn("Support for 'lifetime' attribute (in %s) is "
79 "deprecated (the rules it contains should "
80 "instead be direct descendants of the "
81 "constraint object)", id);
82 }
83
84 if ((lifetime != NULL) && !evaluate_lifetime(lifetime, scheduler)) {
85 crm_info("Constraint %s %s is not active", tag, id);
86
87 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_ORDER, tag, pcmk__str_none)) {
88 pcmk__unpack_ordering(xml_obj, scheduler);
89
90 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_DEPEND, tag, pcmk__str_none)) {
91 pcmk__unpack_colocation(xml_obj, scheduler);
92
93 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_LOCATION, tag,
94 pcmk__str_none)) {
95 pcmk__unpack_location(xml_obj, scheduler);
96
97 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_TICKET, tag, pcmk__str_none)) {
98 pcmk__unpack_rsc_ticket(xml_obj, scheduler);
99
100 } else {
101 pe_err("Unsupported constraint type: %s", tag);
102 }
103 }
104 }
105
106 pcmk_resource_t *
107 pcmk__find_constraint_resource(GList *rsc_list, const char *id)
108 {
109 if (id == NULL) {
110 return NULL;
111 }
112 for (GList *iter = rsc_list; iter != NULL; iter = iter->next) {
113 pcmk_resource_t *parent = iter->data;
114 pcmk_resource_t *match = parent->fns->find_rsc(parent, id, NULL,
115 pcmk_rsc_match_history);
116
117 if (match != NULL) {
118 if (!pcmk__str_eq(match->id, id, pcmk__str_none)) {
119
120 match = uber_parent(match);
121 crm_debug("Found %s for %s", match->id, id);
122 }
123 return match;
124 }
125 }
126 crm_trace("No match for %s", id);
127 return NULL;
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141 static bool
142 find_constraint_tag(const pcmk_scheduler_t *scheduler, const char *id,
143 pcmk_tag_t **tag)
144 {
145 *tag = NULL;
146
147
148 if (g_hash_table_lookup_extended(scheduler->template_rsc_sets, id,
149 NULL, (gpointer *) tag)) {
150 if (*tag == NULL) {
151 crm_warn("No resource is derived from template '%s'", id);
152 return false;
153 }
154 return true;
155 }
156
157
158 if (g_hash_table_lookup_extended(scheduler->tags, id,
159 NULL, (gpointer *) tag)) {
160 if (*tag == NULL) {
161 crm_warn("No resource is tagged with '%s'", id);
162 return false;
163 }
164 return true;
165 }
166
167 crm_warn("No template or tag named '%s'", id);
168 return false;
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 bool
185 pcmk__valid_resource_or_tag(const pcmk_scheduler_t *scheduler, const char *id,
186 pcmk_resource_t **rsc, pcmk_tag_t **tag)
187 {
188 if (rsc != NULL) {
189 *rsc = pcmk__find_constraint_resource(scheduler->resources, id);
190 if (*rsc != NULL) {
191 return true;
192 }
193 }
194
195 if ((tag != NULL) && find_constraint_tag(scheduler, id, tag)) {
196 return true;
197 }
198
199 return false;
200 }
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 xmlNode *
217 pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pcmk_scheduler_t *scheduler)
218 {
219 xmlNode *new_xml = NULL;
220 bool any_refs = false;
221
222
223 if (first_named_child(xml_obj, XML_CONS_TAG_RSC_SET) == NULL) {
224 return NULL;
225 }
226
227 new_xml = copy_xml(xml_obj);
228
229 for (xmlNode *set = first_named_child(new_xml, XML_CONS_TAG_RSC_SET);
230 set != NULL; set = crm_next_same_xml(set)) {
231
232 GList *tag_refs = NULL;
233 GList *iter = NULL;
234
235 for (xmlNode *xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
236 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
237
238 pcmk_resource_t *rsc = NULL;
239 pcmk_tag_t *tag = NULL;
240
241 if (!pcmk__valid_resource_or_tag(scheduler, ID(xml_rsc), &rsc,
242 &tag)) {
243 pcmk__config_err("Ignoring resource sets for constraint '%s' "
244 "because '%s' is not a valid resource or tag",
245 ID(xml_obj), ID(xml_rsc));
246 free_xml(new_xml);
247 return NULL;
248
249 } else if (rsc) {
250 continue;
251
252 } else if (tag) {
253
254 xmlNode *last_ref = xml_rsc;
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 for (iter = tag->refs; iter != NULL; iter = iter->next) {
276 const char *obj_ref = iter->data;
277 xmlNode *new_rsc_ref = NULL;
278
279 new_rsc_ref = xmlNewDocRawNode(set->doc, NULL,
280 (pcmkXmlStr)
281 XML_TAG_RESOURCE_REF,
282 NULL);
283 crm_xml_add(new_rsc_ref, XML_ATTR_ID, obj_ref);
284 xmlAddNextSibling(last_ref, new_rsc_ref);
285
286 last_ref = new_rsc_ref;
287 }
288
289 any_refs = true;
290
291
292
293
294 tag_refs = g_list_append(tag_refs, xml_rsc);
295 }
296 }
297
298
299
300
301
302
303
304
305
306
307
308 for (iter = tag_refs; iter != NULL; iter = iter->next) {
309 xmlNode *tag_ref = iter->data;
310
311 free_xml(tag_ref);
312 }
313 g_list_free(tag_refs);
314 }
315
316 if (!any_refs) {
317 free_xml(new_xml);
318 new_xml = NULL;
319 }
320 return new_xml;
321 }
322
323
324
325
326
327
328
329
330
331
332
333
334 bool
335 pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr,
336 bool convert_rsc, const pcmk_scheduler_t *scheduler)
337 {
338 const char *cons_id = NULL;
339 const char *id = NULL;
340
341 pcmk_resource_t *rsc = NULL;
342 pcmk_tag_t *tag = NULL;
343
344 *rsc_set = NULL;
345
346 CRM_CHECK((xml_obj != NULL) && (attr != NULL), return false);
347
348 cons_id = ID(xml_obj);
349 if (cons_id == NULL) {
350 pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
351 xml_obj->name);
352 return false;
353 }
354
355 id = crm_element_value(xml_obj, attr);
356 if (id == NULL) {
357 return true;
358 }
359
360 if (!pcmk__valid_resource_or_tag(scheduler, id, &rsc, &tag)) {
361 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
362 "valid resource or tag", cons_id, id);
363 return false;
364
365 } else if (tag) {
366
367
368
369
370 *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
371 crm_xml_add(*rsc_set, XML_ATTR_ID, id);
372
373 for (GList *iter = tag->refs; iter != NULL; iter = iter->next) {
374 const char *obj_ref = iter->data;
375 xmlNode *rsc_ref = NULL;
376
377 rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
378 crm_xml_add(rsc_ref, XML_ATTR_ID, obj_ref);
379 }
380
381
382 pcmk__xe_set_bool_attr(*rsc_set, "sequential", false);
383
384 } else if ((rsc != NULL) && convert_rsc) {
385
386
387
388
389 xmlNode *rsc_ref = NULL;
390
391 *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
392 crm_xml_add(*rsc_set, XML_ATTR_ID, id);
393
394 rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
395 crm_xml_add(rsc_ref, XML_ATTR_ID, id);
396
397 } else {
398 return true;
399 }
400
401
402 if (*rsc_set != NULL) {
403 xml_remove_prop(xml_obj, attr);
404 }
405
406 return true;
407 }
408
409
410
411
412
413
414
415 void
416 pcmk__create_internal_constraints(pcmk_scheduler_t *scheduler)
417 {
418 crm_trace("Create internal constraints");
419 for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
420 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
421
422 rsc->cmds->internal_constraints(rsc);
423 }
424 }