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