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, pe_working_set_t *data_set)
32 {
33 bool result = FALSE;
34 crm_time_t *next_change = crm_time_new_undefined();
35
36 result = pe_evaluate_rules(lifetime, NULL, data_set->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, data_set);
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(pe_working_set_t *data_set)
57 {
58 xmlNode *xml_constraints = pcmk_find_cib_element(data_set->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 = crm_element_name(xml_obj);
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, data_set)) {
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_casei)) {
88 pcmk__unpack_ordering(xml_obj, data_set);
89
90 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_DEPEND, tag, pcmk__str_casei)) {
91 pcmk__unpack_colocation(xml_obj, data_set);
92
93 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_LOCATION, tag, pcmk__str_casei)) {
94 pcmk__unpack_location(xml_obj, data_set);
95
96 } else if (pcmk__str_eq(XML_CONS_TAG_RSC_TICKET, tag, pcmk__str_casei)) {
97 pcmk__unpack_rsc_ticket(xml_obj, data_set);
98
99 } else {
100 pe_err("Unsupported constraint type: %s", tag);
101 }
102 }
103 }
104
105 pe_resource_t *
106 pcmk__find_constraint_resource(GList *rsc_list, const char *id)
107 {
108 GList *rIter = NULL;
109
110 for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
111 pe_resource_t *parent = rIter->data;
112 pe_resource_t *match = parent->fns->find_rsc(parent, id, NULL,
113 pe_find_renamed);
114
115 if (match != NULL) {
116 if(!pcmk__str_eq(match->id, id, pcmk__str_casei)) {
117
118 match = uber_parent(match);
119 crm_debug("Found %s for %s", match->id, id);
120 }
121 return match;
122 }
123 }
124 crm_trace("No match for %s", id);
125 return NULL;
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139 static bool
140 find_constraint_tag(const pe_working_set_t *data_set, const char *id,
141 pe_tag_t **tag)
142 {
143 *tag = NULL;
144
145
146 if (g_hash_table_lookup_extended(data_set->template_rsc_sets, id,
147 NULL, (gpointer *) tag)) {
148 if (*tag == NULL) {
149 crm_warn("No resource is derived from template '%s'", id);
150 return false;
151 }
152 return true;
153 }
154
155
156 if (g_hash_table_lookup_extended(data_set->tags, id,
157 NULL, (gpointer *) tag)) {
158 if (*tag == NULL) {
159 crm_warn("No resource is tagged with '%s'", id);
160 return false;
161 }
162 return true;
163 }
164
165 crm_warn("No template or tag named '%s'", id);
166 return false;
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 bool
183 pcmk__valid_resource_or_tag(const pe_working_set_t *data_set, const char *id,
184 pe_resource_t **rsc, pe_tag_t **tag)
185 {
186 if (rsc != NULL) {
187 *rsc = pcmk__find_constraint_resource(data_set->resources, id);
188 if (*rsc != NULL) {
189 return true;
190 }
191 }
192
193 if ((tag != NULL) && find_constraint_tag(data_set, id, tag)) {
194 return true;
195 }
196
197 return false;
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 xmlNode *
215 pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pe_working_set_t *data_set)
216 {
217 xmlNode *new_xml = NULL;
218 bool any_refs = false;
219
220
221 if (first_named_child(xml_obj, XML_CONS_TAG_RSC_SET) == NULL) {
222 return NULL;
223 }
224
225 new_xml = copy_xml(xml_obj);
226
227 for (xmlNode *set = first_named_child(new_xml, XML_CONS_TAG_RSC_SET);
228 set != NULL; set = crm_next_same_xml(set)) {
229
230 GList *tag_refs = NULL;
231 GList *gIter = NULL;
232
233 for (xmlNode *xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
234 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
235
236 pe_resource_t *rsc = NULL;
237 pe_tag_t *tag = NULL;
238
239 if (!pcmk__valid_resource_or_tag(data_set, ID(xml_rsc), &rsc,
240 &tag)) {
241 pcmk__config_err("Ignoring resource sets for constraint '%s' "
242 "because '%s' is not a valid resource or tag",
243 ID(xml_obj), ID(xml_rsc));
244 free_xml(new_xml);
245 return NULL;
246
247 } else if (rsc) {
248 continue;
249
250 } else if (tag) {
251
252 xmlNode *last_ref = xml_rsc;
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
277 const char *obj_ref = (const char *) gIter->data;
278 xmlNode *new_rsc_ref = NULL;
279
280 new_rsc_ref = xmlNewDocRawNode(getDocPtr(set), NULL,
281 (pcmkXmlStr) XML_TAG_RESOURCE_REF, NULL);
282 crm_xml_add(new_rsc_ref, XML_ATTR_ID, obj_ref);
283 xmlAddNextSibling(last_ref, new_rsc_ref);
284
285 last_ref = new_rsc_ref;
286 }
287
288 any_refs = true;
289
290
291
292
293 tag_refs = g_list_append(tag_refs, xml_rsc);
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306
307 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
308 xmlNode *tag_ref = gIter->data;
309
310 free_xml(tag_ref);
311 }
312 g_list_free(tag_refs);
313 }
314
315 if (!any_refs) {
316 free_xml(new_xml);
317 new_xml = NULL;
318 }
319 return new_xml;
320 }
321
322
323
324
325
326
327
328
329
330
331
332 bool
333 pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr,
334 bool convert_rsc, const pe_working_set_t *data_set)
335 {
336 const char *cons_id = NULL;
337 const char *id = NULL;
338
339 pe_resource_t *rsc = NULL;
340 pe_tag_t *tag = NULL;
341
342 *rsc_set = NULL;
343
344 CRM_CHECK((xml_obj != NULL) && (attr != NULL), return false);
345
346 cons_id = ID(xml_obj);
347 if (cons_id == NULL) {
348 pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
349 crm_element_name(xml_obj));
350 return false;
351 }
352
353 id = crm_element_value(xml_obj, attr);
354 if (id == NULL) {
355 return true;
356 }
357
358 if (!pcmk__valid_resource_or_tag(data_set, id, &rsc, &tag)) {
359 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
360 "valid resource or tag", cons_id, id);
361 return false;
362
363 } else if (tag) {
364 GList *gIter = NULL;
365
366
367
368
369 *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
370 crm_xml_add(*rsc_set, XML_ATTR_ID, id);
371
372 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
373 const char *obj_ref = (const char *) gIter->data;
374 xmlNode *rsc_ref = NULL;
375
376 rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
377 crm_xml_add(rsc_ref, XML_ATTR_ID, obj_ref);
378 }
379
380
381 pcmk__xe_set_bool_attr(*rsc_set, "sequential", false);
382
383 } else if ((rsc != NULL) && convert_rsc) {
384
385
386 xmlNode *rsc_ref = NULL;
387
388 *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
389 crm_xml_add(*rsc_set, XML_ATTR_ID, id);
390
391 rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
392 crm_xml_add(rsc_ref, XML_ATTR_ID, id);
393
394 } else {
395 return true;
396 }
397
398
399 if (*rsc_set != NULL) {
400 xml_remove_prop(xml_obj, attr);
401 }
402
403 return true;
404 }
405
406
407
408
409
410
411
412 void
413 pcmk__create_internal_constraints(pe_working_set_t *data_set)
414 {
415 crm_trace("Create internal constraints");
416 for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
417 pe_resource_t *rsc = (pe_resource_t *) iter->data;
418
419 rsc->cmds->internal_constraints(rsc);
420 }
421 }