This source file includes following definitions.
- pcmk__unpack_constraints
- pcmk__find_constraint_resource
- find_constraint_tag
- pcmk__parse_constraint_role
- 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/common/scheduler.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 <pacemaker-internal.h>
27 #include "libpacemaker_private.h"
28
29
30
31
32
33
34
35
36
37
38 void
39 pcmk__unpack_constraints(pcmk_scheduler_t *scheduler)
40 {
41 xmlNode *xml_constraints = pcmk_find_cib_element(scheduler->input,
42 PCMK_XE_CONSTRAINTS);
43
44 for (xmlNode *xml_obj = pcmk__xe_first_child(xml_constraints, NULL, NULL,
45 NULL);
46 xml_obj != NULL; xml_obj = pcmk__xe_next(xml_obj, NULL)) {
47
48 const char *id = crm_element_value(xml_obj, PCMK_XA_ID);
49 const char *tag = (const char *) xml_obj->name;
50
51 if (id == NULL) {
52 pcmk__config_err("Ignoring <%s> constraint without "
53 PCMK_XA_ID, tag);
54 continue;
55 }
56
57 crm_trace("Unpacking %s constraint '%s'", tag, id);
58
59 if (pcmk__str_eq(PCMK_XE_RSC_ORDER, tag, pcmk__str_none)) {
60 pcmk__unpack_ordering(xml_obj, scheduler);
61
62 } else if (pcmk__str_eq(PCMK_XE_RSC_COLOCATION, tag, pcmk__str_none)) {
63 pcmk__unpack_colocation(xml_obj, scheduler);
64
65 } else if (pcmk__str_eq(PCMK_XE_RSC_LOCATION, tag, pcmk__str_none)) {
66 pcmk__unpack_location(xml_obj, scheduler);
67
68 } else if (pcmk__str_eq(PCMK_XE_RSC_TICKET, tag, pcmk__str_none)) {
69 pcmk__unpack_rsc_ticket(xml_obj, scheduler);
70
71 } else {
72 pcmk__config_err("Unsupported constraint type: %s", tag);
73 }
74 }
75 }
76
77 pcmk_resource_t *
78 pcmk__find_constraint_resource(GList *rsc_list, const char *id)
79 {
80 if (id == NULL) {
81 return NULL;
82 }
83 for (GList *iter = rsc_list; iter != NULL; iter = iter->next) {
84 pcmk_resource_t *parent = iter->data;
85 pcmk_resource_t *match = NULL;
86
87 match = parent->priv->fns->find_rsc(parent, id, NULL,
88 pcmk_rsc_match_history);
89 if (match != NULL) {
90 if (!pcmk__str_eq(match->id, id, pcmk__str_none)) {
91
92 match = uber_parent(match);
93 crm_debug("Found %s for %s", match->id, id);
94 }
95 return match;
96 }
97 }
98 crm_trace("No match for %s", id);
99 return NULL;
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113 static bool
114 find_constraint_tag(const pcmk_scheduler_t *scheduler, const char *id,
115 pcmk__idref_t **tag)
116 {
117 *tag = NULL;
118
119
120 if (g_hash_table_lookup_extended(scheduler->priv->templates, id,
121 NULL, (gpointer *) tag)) {
122 if (*tag == NULL) {
123 crm_notice("No resource is derived from template '%s'", id);
124 return false;
125 }
126 return true;
127 }
128
129
130 if (g_hash_table_lookup_extended(scheduler->priv->tags, id,
131 NULL, (gpointer *) tag)) {
132 if (*tag == NULL) {
133 crm_notice("No resource is tagged with '%s'", id);
134 return false;
135 }
136 return true;
137 }
138
139 pcmk__config_warn("No resource, template, or tag named '%s'", id);
140 return false;
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 int
158 pcmk__parse_constraint_role(const char *id, const char *role_spec,
159 enum rsc_role_e *role)
160 {
161 *role = pcmk_parse_role(role_spec);
162 switch (*role) {
163 case pcmk_role_unknown:
164 if (role_spec != NULL) {
165 pcmk__config_err("Ignoring constraint %s: Invalid role '%s'",
166 id, role_spec);
167 return pcmk_rc_unpack_error;
168 }
169 break;
170
171 case pcmk_role_started:
172 *role = pcmk_role_unknown;
173 break;
174
175 default:
176 break;
177 }
178 return pcmk_rc_ok;
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 bool
195 pcmk__valid_resource_or_tag(const pcmk_scheduler_t *scheduler, const char *id,
196 pcmk_resource_t **rsc, pcmk__idref_t **tag)
197 {
198 if (rsc != NULL) {
199 *rsc = pcmk__find_constraint_resource(scheduler->priv->resources, id);
200 if (*rsc != NULL) {
201 return true;
202 }
203 }
204
205 if ((tag != NULL) && find_constraint_tag(scheduler, id, tag)) {
206 return true;
207 }
208
209 return false;
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 xmlNode *
230 pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pcmk_scheduler_t *scheduler)
231 {
232 xmlNode *new_xml = NULL;
233 bool any_refs = false;
234
235
236 if (pcmk__xe_first_child(xml_obj, PCMK_XE_RESOURCE_SET, NULL,
237 NULL) == NULL) {
238 return NULL;
239 }
240
241 new_xml = pcmk__xml_copy(NULL, xml_obj);
242
243 for (xmlNode *set = pcmk__xe_first_child(new_xml, PCMK_XE_RESOURCE_SET,
244 NULL, NULL);
245 set != NULL; set = pcmk__xe_next(set, PCMK_XE_RESOURCE_SET)) {
246
247 GList *tag_refs = NULL;
248 GList *iter = NULL;
249
250 for (xmlNode *xml_rsc = pcmk__xe_first_child(set, PCMK_XE_RESOURCE_REF,
251 NULL, NULL);
252 xml_rsc != NULL;
253 xml_rsc = pcmk__xe_next(xml_rsc, PCMK_XE_RESOURCE_REF)) {
254
255 pcmk_resource_t *rsc = NULL;
256 pcmk__idref_t *tag = NULL;
257
258 if (!pcmk__valid_resource_or_tag(scheduler, pcmk__xe_id(xml_rsc),
259 &rsc, &tag)) {
260 pcmk__config_err("Ignoring resource sets for constraint '%s' "
261 "because '%s' is not a valid resource or tag",
262 pcmk__xe_id(xml_obj), pcmk__xe_id(xml_rsc));
263 pcmk__xml_free(new_xml);
264 return NULL;
265
266 } else if (rsc) {
267 continue;
268
269 } else if (tag) {
270
271
272
273 xmlNode *last_ref = xml_rsc;
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 for (iter = tag->refs; iter != NULL; iter = iter->next) {
295 const char *ref_id = iter->data;
296 xmlNode *new_ref = pcmk__xe_create(set,
297 PCMK_XE_RESOURCE_REF);
298
299 crm_xml_add(new_ref, PCMK_XA_ID, ref_id);
300 xmlAddNextSibling(last_ref, new_ref);
301
302 last_ref = new_ref;
303 }
304
305 any_refs = true;
306
307
308
309
310 tag_refs = g_list_append(tag_refs, xml_rsc);
311 }
312 }
313
314
315
316
317
318
319
320
321
322
323
324 for (iter = tag_refs; iter != NULL; iter = iter->next) {
325 xmlNode *tag_ref = iter->data;
326
327 pcmk__xml_free(tag_ref);
328 }
329 g_list_free(tag_refs);
330 }
331
332 if (!any_refs) {
333 pcmk__xml_free(new_xml);
334 new_xml = NULL;
335 }
336 return new_xml;
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350 bool
351 pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr,
352 bool convert_rsc, const pcmk_scheduler_t *scheduler)
353 {
354 const char *cons_id = NULL;
355 const char *id = NULL;
356
357 pcmk_resource_t *rsc = NULL;
358 pcmk__idref_t *tag = NULL;
359
360 *rsc_set = NULL;
361
362 CRM_CHECK((xml_obj != NULL) && (attr != NULL), return false);
363
364 cons_id = pcmk__xe_id(xml_obj);
365 if (cons_id == NULL) {
366 pcmk__config_err("Ignoring <%s> constraint without " PCMK_XA_ID,
367 xml_obj->name);
368 return false;
369 }
370
371 id = crm_element_value(xml_obj, attr);
372 if (id == NULL) {
373 return true;
374 }
375
376 if (!pcmk__valid_resource_or_tag(scheduler, id, &rsc, &tag)) {
377 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
378 "valid resource or tag", cons_id, id);
379 return false;
380
381 } else if (tag) {
382
383
384
385
386 *rsc_set = pcmk__xe_create(xml_obj, PCMK_XE_RESOURCE_SET);
387 crm_xml_add(*rsc_set, PCMK_XA_ID, id);
388
389 for (GList *iter = tag->refs; iter != NULL; iter = iter->next) {
390 const char *obj_ref = iter->data;
391 xmlNode *rsc_ref = NULL;
392
393 rsc_ref = pcmk__xe_create(*rsc_set, PCMK_XE_RESOURCE_REF);
394 crm_xml_add(rsc_ref, PCMK_XA_ID, obj_ref);
395 }
396
397
398 pcmk__xe_set_bool_attr(*rsc_set, PCMK_XA_SEQUENTIAL, false);
399
400 } else if ((rsc != NULL) && convert_rsc) {
401
402
403
404
405 xmlNode *rsc_ref = NULL;
406
407 *rsc_set = pcmk__xe_create(xml_obj, PCMK_XE_RESOURCE_SET);
408 crm_xml_add(*rsc_set, PCMK_XA_ID, id);
409
410 rsc_ref = pcmk__xe_create(*rsc_set, PCMK_XE_RESOURCE_REF);
411 crm_xml_add(rsc_ref, PCMK_XA_ID, id);
412
413 } else {
414 return true;
415 }
416
417
418 if (*rsc_set != NULL) {
419 pcmk__xe_remove_attr(xml_obj, attr);
420 }
421
422 return true;
423 }
424
425
426
427
428
429
430
431 void
432 pcmk__create_internal_constraints(pcmk_scheduler_t *scheduler)
433 {
434 crm_trace("Create internal constraints");
435 for (GList *iter = scheduler->priv->resources;
436 iter != NULL; iter = iter->next) {
437
438 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
439
440 rsc->priv->cmds->internal_constraints(rsc);
441 }
442 }