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 = get_object_root(XML_CIB_TAG_CONSTRAINTS,
59 data_set->input);
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 descendents 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(pe_working_set_t *data_set, const char *id, pe_tag_t **tag)
141 {
142 *tag = NULL;
143
144
145 if (g_hash_table_lookup_extended(data_set->template_rsc_sets, id,
146 NULL, (gpointer *) tag)) {
147 if (*tag == NULL) {
148 crm_warn("No resource is derived from template '%s'", id);
149 return false;
150 }
151 return true;
152 }
153
154
155 if (g_hash_table_lookup_extended(data_set->tags, id,
156 NULL, (gpointer *) tag)) {
157 if (*tag == NULL) {
158 crm_warn("No resource is tagged with '%s'", id);
159 return false;
160 }
161 return true;
162 }
163
164 crm_warn("No template or tag named '%s'", id);
165 return false;
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 bool
182 pcmk__valid_resource_or_tag(pe_working_set_t *data_set, const char *id,
183 pe_resource_t **rsc, pe_tag_t **tag)
184 {
185 if (rsc != NULL) {
186 *rsc = pcmk__find_constraint_resource(data_set->resources, id);
187 if (*rsc != NULL) {
188 return true;
189 }
190 }
191
192 if ((tag != NULL) && find_constraint_tag(data_set, id, tag)) {
193 return true;
194 }
195
196 return false;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 xmlNode *
214 pcmk__expand_tags_in_sets(xmlNode *xml_obj, pe_working_set_t *data_set)
215 {
216 xmlNode *new_xml = NULL;
217 bool any_refs = false;
218
219
220 if (first_named_child(xml_obj, XML_CONS_TAG_RSC_SET) == NULL) {
221 return NULL;
222 }
223
224 new_xml = copy_xml(xml_obj);
225
226 for (xmlNode *set = first_named_child(new_xml, XML_CONS_TAG_RSC_SET);
227 set != NULL; set = crm_next_same_xml(set)) {
228
229 GList *tag_refs = NULL;
230 GList *gIter = NULL;
231
232 for (xmlNode *xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
233 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
234
235 pe_resource_t *rsc = NULL;
236 pe_tag_t *tag = NULL;
237
238 if (!pcmk__valid_resource_or_tag(data_set, ID(xml_rsc), &rsc,
239 &tag)) {
240 pcmk__config_err("Ignoring resource sets for constraint '%s' "
241 "because '%s' is not a valid resource or tag",
242 ID(xml_obj), ID(xml_rsc));
243 free_xml(new_xml);
244 return NULL;
245
246 } else if (rsc) {
247 continue;
248
249 } else if (tag) {
250
251 xmlNode *last_ref = xml_rsc;
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
276 const char *obj_ref = (const char *) gIter->data;
277 xmlNode *new_rsc_ref = NULL;
278
279 new_rsc_ref = xmlNewDocRawNode(getDocPtr(set), NULL,
280 (pcmkXmlStr) XML_TAG_RESOURCE_REF, NULL);
281 crm_xml_add(new_rsc_ref, XML_ATTR_ID, obj_ref);
282 xmlAddNextSibling(last_ref, new_rsc_ref);
283
284 last_ref = new_rsc_ref;
285 }
286
287 any_refs = true;
288
289
290
291
292 tag_refs = g_list_append(tag_refs, xml_rsc);
293 }
294 }
295
296
297
298
299
300
301
302
303
304
305
306 for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
307 xmlNode *tag_ref = gIter->data;
308
309 free_xml(tag_ref);
310 }
311 g_list_free(tag_refs);
312 }
313
314 if (!any_refs) {
315 free_xml(new_xml);
316 new_xml = NULL;
317 }
318 return new_xml;
319 }
320
321
322
323
324
325
326
327
328
329
330
331 bool
332 pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr,
333 bool convert_rsc, pe_working_set_t *data_set)
334 {
335 const char *cons_id = NULL;
336 const char *id = NULL;
337
338 pe_resource_t *rsc = NULL;
339 pe_tag_t *tag = NULL;
340
341 *rsc_set = NULL;
342
343 CRM_CHECK((xml_obj != NULL) && (attr != NULL), return false);
344
345 cons_id = ID(xml_obj);
346 if (cons_id == NULL) {
347 pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
348 crm_element_name(xml_obj));
349 return false;
350 }
351
352 id = crm_element_value(xml_obj, attr);
353 if (id == NULL) {
354 return true;
355 }
356
357 if (!pcmk__valid_resource_or_tag(data_set, id, &rsc, &tag)) {
358 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
359 "valid resource or tag", cons_id, id);
360 return false;
361
362 } else if (tag) {
363 GList *gIter = NULL;
364
365
366
367
368 *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
369 crm_xml_add(*rsc_set, XML_ATTR_ID, id);
370
371 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
372 const char *obj_ref = (const char *) gIter->data;
373 xmlNode *rsc_ref = NULL;
374
375 rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
376 crm_xml_add(rsc_ref, XML_ATTR_ID, obj_ref);
377 }
378
379
380 crm_xml_add(*rsc_set, "sequential", XML_BOOLEAN_FALSE);
381
382 } else if ((rsc != NULL) && convert_rsc) {
383
384
385 xmlNode *rsc_ref = NULL;
386
387 *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
388 crm_xml_add(*rsc_set, XML_ATTR_ID, id);
389
390 rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
391 crm_xml_add(rsc_ref, XML_ATTR_ID, id);
392
393 } else {
394 return true;
395 }
396
397
398 if (*rsc_set != NULL) {
399 xml_remove_prop(xml_obj, attr);
400 }
401
402 return true;
403 }
404
405
406
407
408
409
410
411 void
412 pcmk__create_internal_constraints(pe_working_set_t *data_set)
413 {
414 crm_trace("Create internal constraints");
415 for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
416 pe_resource_t *rsc = (pe_resource_t *) iter->data;
417
418 rsc->cmds->internal_constraints(rsc, data_set);
419 }
420 }