pacemaker 2.1.6-6fdc9deea29
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_sched_location.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2023 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdbool.h>
13#include <glib.h>
14
15#include <crm/crm.h>
16#include <crm/pengine/status.h>
17#include <pacemaker-internal.h>
18
20
21static int
22get_node_score(const char *rule, const char *score, bool raw,
23 pe_node_t *node, pe_resource_t *rsc)
24{
25 int score_f = 0;
26
27 if (score == NULL) {
28 pe_err("Rule %s: no score specified. Assuming 0.", rule);
29
30 } else if (raw) {
31 score_f = char2score(score);
32
33 } else {
34 const char *attr_score = pe_node_attribute_calculated(node, score, rsc);
35
36 if (attr_score == NULL) {
37 crm_debug("Rule %s: %s did not have a value for %s",
38 rule, pe__node_name(node), score);
39 score_f = -INFINITY;
40
41 } else {
42 crm_debug("Rule %s: %s had value %s for %s",
43 rule, pe__node_name(node), attr_score, score);
44 score_f = char2score(attr_score);
45 }
46 }
47 return score_f;
48}
49
50static pe__location_t *
51generate_location_rule(pe_resource_t *rsc, xmlNode *rule_xml,
52 const char *discovery, crm_time_t *next_change,
54 pe_re_match_data_t *re_match_data)
55{
56 const char *rule_id = NULL;
57 const char *score = NULL;
58 const char *boolean = NULL;
59 const char *role = NULL;
60
61 GList *gIter = NULL;
62 GList *match_L = NULL;
63
64 bool do_and = true;
65 bool accept = true;
66 bool raw_score = true;
67 bool score_allocated = false;
68
69 pe__location_t *location_rule = NULL;
70
71 rule_xml = expand_idref(rule_xml, data_set->input);
72 if (rule_xml == NULL) {
73 return NULL;
74 }
75
76 rule_id = crm_element_value(rule_xml, XML_ATTR_ID);
78 role = crm_element_value(rule_xml, XML_RULE_ATTR_ROLE);
79
80 crm_trace("Processing rule: %s", rule_id);
81
82 if ((role != NULL) && (text2role(role) == RSC_ROLE_UNKNOWN)) {
83 pe_err("Bad role specified for %s: %s", rule_id, role);
84 return NULL;
85 }
86
87 score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE);
88 if (score == NULL) {
90 if (score != NULL) {
91 raw_score = false;
92 }
93 }
94 if (pcmk__str_eq(boolean, "or", pcmk__str_casei)) {
95 do_and = false;
96 }
97
98 location_rule = pcmk__new_location(rule_id, rsc, 0, discovery, NULL,
99 data_set);
100
101 if (location_rule == NULL) {
102 return NULL;
103 }
104
105 if ((re_match_data != NULL) && (re_match_data->nregs > 0)
106 && (re_match_data->pmatch[0].rm_so != -1) && !raw_score) {
107
108 char *result = pe_expand_re_matches(score, re_match_data);
109
110 if (result != NULL) {
111 score = result;
112 score_allocated = true;
113 }
114 }
115
116 if (role != NULL) {
117 crm_trace("Setting role filter: %s", role);
118 location_rule->role_filter = text2role(role);
119 if (location_rule->role_filter == RSC_ROLE_UNPROMOTED) {
120 /* Any promotable clone cannot be promoted without being in the
121 * unpromoted role first. Ergo, any constraint for the unpromoted
122 * role applies to every role.
123 */
124 location_rule->role_filter = RSC_ROLE_UNKNOWN;
125 }
126 }
127 if (do_and) {
128 GList *gIter = NULL;
129
130 match_L = pcmk__copy_node_list(data_set->nodes, true);
131 for (gIter = match_L; gIter != NULL; gIter = gIter->next) {
132 pe_node_t *node = (pe_node_t *) gIter->data;
133
134 node->weight = get_node_score(rule_id, score, raw_score, node, rsc);
135 }
136 }
137
138 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
139 int score_f = 0;
140 pe_node_t *node = (pe_node_t *) gIter->data;
141 pe_match_data_t match_data = {
142 .re = re_match_data,
143 .params = pe_rsc_params(rsc, node, data_set),
144 .meta = rsc->meta,
145 };
146
147 accept = pe_test_rule(rule_xml, node->details->attrs, RSC_ROLE_UNKNOWN,
148 data_set->now, next_change, &match_data);
149
150 crm_trace("Rule %s %s on %s", ID(rule_xml), accept? "passed" : "failed",
151 pe__node_name(node));
152
153 score_f = get_node_score(rule_id, score, raw_score, node, rsc);
154
155 if (accept) {
156 pe_node_t *local = pe_find_node_id(match_L, node->details->id);
157
158 if ((local == NULL) && do_and) {
159 continue;
160
161 } else if (local == NULL) {
162 local = pe__copy_node(node);
163 match_L = g_list_append(match_L, local);
164 }
165
166 if (!do_and) {
167 local->weight = pcmk__add_scores(local->weight, score_f);
168 }
169 crm_trace("%s has score %s after %s", pe__node_name(node),
170 pcmk_readable_score(local->weight), rule_id);
171
172 } else if (do_and && !accept) {
173 // Remove it
174 pe_node_t *delete = pe_find_node_id(match_L, node->details->id);
175
176 if (delete != NULL) {
177 match_L = g_list_remove(match_L, delete);
178 crm_trace("%s did not match", pe__node_name(node));
179 }
180 free(delete);
181 }
182 }
183
184 if (score_allocated) {
185 free((char *)score);
186 }
187
188 location_rule->node_list_rh = match_L;
189 if (location_rule->node_list_rh == NULL) {
190 crm_trace("No matching nodes for rule %s", rule_id);
191 return NULL;
192 }
193
194 crm_trace("%s: %d nodes matched",
195 rule_id, g_list_length(location_rule->node_list_rh));
196 return location_rule;
197}
198
199static void
200unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc, const char *role,
201 const char *score, pe_working_set_t *data_set,
202 pe_re_match_data_t *re_match_data)
203{
204 pe__location_t *location = NULL;
205 const char *rsc_id = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
206 const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
207 const char *node = crm_element_value(xml_obj, XML_CIB_TAG_NODE);
208 const char *discovery = crm_element_value(xml_obj, XML_LOCATION_ATTR_DISCOVERY);
209
210 if (rsc == NULL) {
211 pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
212 "does not exist", id, rsc_id);
213 return;
214 }
215
216 if (score == NULL) {
217 score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE);
218 }
219
220 if ((node != NULL) && (score != NULL)) {
221 int score_i = char2score(score);
222 pe_node_t *match = pe_find_node(data_set->nodes, node);
223
224 if (!match) {
225 return;
226 }
227 location = pcmk__new_location(id, rsc, score_i, discovery, match,
228 data_set);
229
230 } else {
231 bool empty = true;
232 crm_time_t *next_change = crm_time_new_undefined();
233
234 /* This loop is logically parallel to pe_evaluate_rules(), except
235 * instead of checking whether any rule is active, we set up location
236 * constraints for each active rule.
237 */
238 for (xmlNode *rule_xml = first_named_child(xml_obj, XML_TAG_RULE);
239 rule_xml != NULL; rule_xml = crm_next_same_xml(rule_xml)) {
240 empty = false;
241 crm_trace("Unpacking %s/%s", id, ID(rule_xml));
242 generate_location_rule(rsc, rule_xml, discovery, next_change,
243 data_set, re_match_data);
244 }
245
246 if (empty) {
247 pcmk__config_err("Ignoring constraint '%s' because it contains "
248 "no rules", id);
249 }
250
251 /* If there is a point in the future when the evaluation of a rule will
252 * change, make sure the scheduler is re-run by that time.
253 */
254 if (crm_time_is_defined(next_change)) {
255 time_t t = (time_t) crm_time_get_seconds_since_epoch(next_change);
256
258 }
259 crm_time_free(next_change);
260 return;
261 }
262
263 if (role == NULL) {
264 role = crm_element_value(xml_obj, XML_RULE_ATTR_ROLE);
265 }
266
267 if ((location != NULL) && (role != NULL)) {
268 if (text2role(role) == RSC_ROLE_UNKNOWN) {
269 pe_err("Invalid constraint %s: Bad role %s", id, role);
270 return;
271
272 } else {
273 enum rsc_role_e r = text2role(role);
274 switch(r) {
275 case RSC_ROLE_UNKNOWN:
276 case RSC_ROLE_STARTED:
278 /* Applies to all */
279 location->role_filter = RSC_ROLE_UNKNOWN;
280 break;
281 default:
282 location->role_filter = r;
283 break;
284 }
285 }
286 }
287}
288
289static void
290unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set)
291{
292 const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
293 const char *value = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
294
295 if (value) {
296 pe_resource_t *rsc;
297
299 unpack_rsc_location(xml_obj, rsc, NULL, NULL, data_set, NULL);
300 }
301
303 if (value) {
304 regex_t *r_patt = calloc(1, sizeof(regex_t));
305 bool invert = false;
306 GList *rIter = NULL;
307
308 if (value[0] == '!') {
309 value++;
310 invert = true;
311 }
312
313 if (regcomp(r_patt, value, REG_EXTENDED) != 0) {
314 pcmk__config_err("Ignoring constraint '%s' because "
316 " has invalid value '%s'", id, value);
317 free(r_patt);
318 return;
319 }
320
321 for (rIter = data_set->resources; rIter; rIter = rIter->next) {
322 pe_resource_t *r = rIter->data;
323 int nregs = 0;
324 regmatch_t *pmatch = NULL;
325 int status;
326
327 if(r_patt->re_nsub > 0) {
328 nregs = r_patt->re_nsub + 1;
329 } else {
330 nregs = 1;
331 }
332 pmatch = calloc(nregs, sizeof(regmatch_t));
333
334 status = regexec(r_patt, r->id, nregs, pmatch, 0);
335
336 if (!invert && (status == 0)) {
337 pe_re_match_data_t re_match_data = {
338 .string = r->id,
339 .nregs = nregs,
340 .pmatch = pmatch
341 };
342
343 crm_debug("'%s' matched '%s' for %s", r->id, value, id);
344 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set,
345 &re_match_data);
346
347 } else if (invert && (status != 0)) {
348 crm_debug("'%s' is an inverted match of '%s' for %s",
349 r->id, value, id);
350 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
351
352 } else {
353 crm_trace("'%s' does not match '%s' for %s", r->id, value, id);
354 }
355
356 free(pmatch);
357 }
358
359 regfree(r_patt);
360 free(r_patt);
361 }
362}
363
364// \return Standard Pacemaker return code
365static int
366unpack_location_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
368{
369 const char *id = NULL;
370 const char *rsc_id = NULL;
371 const char *state = NULL;
372 pe_resource_t *rsc = NULL;
373 pe_tag_t *tag = NULL;
374 xmlNode *rsc_set = NULL;
375
376 *expanded_xml = NULL;
377
378 CRM_CHECK(xml_obj != NULL, return EINVAL);
379
380 id = ID(xml_obj);
381 if (id == NULL) {
382 pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
383 crm_element_name(xml_obj));
385 }
386
387 // Check whether there are any resource sets with template or tag references
388 *expanded_xml = pcmk__expand_tags_in_sets(xml_obj, data_set);
389 if (*expanded_xml != NULL) {
390 crm_log_xml_trace(*expanded_xml, "Expanded rsc_location");
391 return pcmk_rc_ok;
392 }
393
394 rsc_id = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
395 if (rsc_id == NULL) {
396 return pcmk_rc_ok;
397 }
398
399 if (!pcmk__valid_resource_or_tag(data_set, rsc_id, &rsc, &tag)) {
400 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
401 "valid resource or tag", id, rsc_id);
403
404 } else if (rsc != NULL) {
405 // No template is referenced
406 return pcmk_rc_ok;
407 }
408
409 state = crm_element_value(xml_obj, XML_RULE_ATTR_ROLE);
410
411 *expanded_xml = copy_xml(xml_obj);
412
413 // Convert template/tag reference in "rsc" into resource_set under constraint
414 if (!pcmk__tag_to_set(*expanded_xml, &rsc_set, XML_LOC_ATTR_SOURCE,
415 false, data_set)) {
416 free_xml(*expanded_xml);
417 *expanded_xml = NULL;
419 }
420
421 if (rsc_set != NULL) {
422 if (state != NULL) {
423 // Move "rsc-role" into converted resource_set as "role" attribute
424 crm_xml_add(rsc_set, "role", state);
425 xml_remove_prop(*expanded_xml, XML_RULE_ATTR_ROLE);
426 }
427 crm_log_xml_trace(*expanded_xml, "Expanded rsc_location");
428
429 } else {
430 // No sets
431 free_xml(*expanded_xml);
432 *expanded_xml = NULL;
433 }
434
435 return pcmk_rc_ok;
436}
437
438// \return Standard Pacemaker return code
439static int
440unpack_location_set(xmlNode *location, xmlNode *set, pe_working_set_t *data_set)
441{
442 xmlNode *xml_rsc = NULL;
443 pe_resource_t *resource = NULL;
444 const char *set_id;
445 const char *role;
446 const char *local_score;
447
448 CRM_CHECK(set != NULL, return EINVAL);
449
450 set_id = ID(set);
451 if (set_id == NULL) {
452 pcmk__config_err("Ignoring " XML_CONS_TAG_RSC_SET " without "
453 XML_ATTR_ID " in constraint '%s'",
454 pcmk__s(ID(location), "(missing ID)"));
456 }
457
458 role = crm_element_value(set, "role");
459 local_score = crm_element_value(set, XML_RULE_ATTR_SCORE);
460
461 for (xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
462 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
463
465 ID(xml_rsc));
466 if (resource == NULL) {
467 pcmk__config_err("%s: No resource found for %s",
468 set_id, ID(xml_rsc));
470 }
471
472 unpack_rsc_location(location, resource, role, local_score, data_set,
473 NULL);
474 }
475
476 return pcmk_rc_ok;
477}
478
479void
481{
482 xmlNode *set = NULL;
483 bool any_sets = false;
484
485 xmlNode *orig_xml = NULL;
486 xmlNode *expanded_xml = NULL;
487
488 if (unpack_location_tags(xml_obj, &expanded_xml, data_set) != pcmk_rc_ok) {
489 return;
490 }
491
492 if (expanded_xml) {
493 orig_xml = xml_obj;
494 xml_obj = expanded_xml;
495 }
496
497 for (set = first_named_child(xml_obj, XML_CONS_TAG_RSC_SET); set != NULL;
498 set = crm_next_same_xml(set)) {
499
500 any_sets = true;
501 set = expand_idref(set, data_set->input);
502 if ((set == NULL) // Configuration error, message already logged
503 || (unpack_location_set(xml_obj, set, data_set) != pcmk_rc_ok)) {
504
505 if (expanded_xml) {
506 free_xml(expanded_xml);
507 }
508 return;
509 }
510 }
511
512 if (expanded_xml) {
513 free_xml(expanded_xml);
514 xml_obj = orig_xml;
515 }
516
517 if (!any_sets) {
518 unpack_simple_location(xml_obj, data_set);
519 }
520}
521
539 int node_weight, const char *discover_mode,
541{
542 pe__location_t *new_con = NULL;
543
544 if (id == NULL) {
545 pe_err("Invalid constraint: no ID specified");
546 return NULL;
547
548 } else if (rsc == NULL) {
549 pe_err("Invalid constraint %s: no resource specified", id);
550 return NULL;
551
552 } else if (node == NULL) {
553 CRM_CHECK(node_weight == 0, return NULL);
554 }
555
556 new_con = calloc(1, sizeof(pe__location_t));
557 if (new_con != NULL) {
558 new_con->id = strdup(id);
559 new_con->rsc_lh = rsc;
560 new_con->node_list_rh = NULL;
561 new_con->role_filter = RSC_ROLE_UNKNOWN;
562
563 if (pcmk__str_eq(discover_mode, "always",
566
567 } else if (pcmk__str_eq(discover_mode, "never", pcmk__str_casei)) {
569
570 } else if (pcmk__str_eq(discover_mode, "exclusive", pcmk__str_casei)) {
572 rsc->exclusive_discover = TRUE;
573
574 } else {
575 pe_err("Invalid " XML_LOCATION_ATTR_DISCOVERY " value %s "
576 "in location constraint", discover_mode);
577 }
578
579 if (node != NULL) {
580 pe_node_t *copy = pe__copy_node(node);
581
582 copy->weight = node_weight;
583 new_con->node_list_rh = g_list_prepend(NULL, copy);
584 }
585
587 new_con);
588 rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
589 }
590
591 return new_con;
592}
593
600void
602{
603 for (GList *iter = data_set->placement_constraints;
604 iter != NULL; iter = iter->next) {
605 pe__location_t *location = iter->data;
606
607 location->rsc_lh->cmds->apply_location(location->rsc_lh, location);
608 }
609}
610
621void
623{
624 bool need_role = false;
625
626 CRM_CHECK((rsc != NULL) && (location != NULL), return);
627
628 // If a role was specified, ensure constraint is applicable
629 need_role = (location->role_filter > RSC_ROLE_UNKNOWN);
630 if (need_role && (location->role_filter != rsc->next_role)) {
631 pe_rsc_trace(rsc,
632 "Not applying %s to %s because role will be %s not %s",
633 location->id, rsc->id, role2text(rsc->next_role),
634 role2text(location->role_filter));
635 return;
636 }
637
638 if (location->node_list_rh == NULL) {
639 pe_rsc_trace(rsc, "Not applying %s to %s because no nodes match",
640 location->id, rsc->id);
641 return;
642 }
643
644 pe_rsc_trace(rsc, "Applying %s%s%s to %s", location->id,
645 (need_role? " for role " : ""),
646 (need_role? role2text(location->role_filter) : ""), rsc->id);
647
648 for (GList *gIter = location->node_list_rh; gIter != NULL;
649 gIter = gIter->next) {
650
651 pe_node_t *node = (pe_node_t *) gIter->data;
652 pe_node_t *weighted_node = NULL;
653
654 weighted_node = (pe_node_t *) pe_hash_table_lookup(rsc->allowed_nodes,
655 node->details->id);
656 if (weighted_node == NULL) {
657 pe_rsc_trace(rsc, "* = %d on %s",
658 node->weight, pe__node_name(node));
659 weighted_node = pe__copy_node(node);
660 g_hash_table_insert(rsc->allowed_nodes,
661 (gpointer) weighted_node->details->id,
662 weighted_node);
663 } else {
664 pe_rsc_trace(rsc, "* + %d on %s",
665 node->weight, pe__node_name(node));
666 weighted_node->weight = pcmk__add_scores(weighted_node->weight,
667 node->weight);
668 }
669
670 if (weighted_node->rsc_discover_mode < location->discover_mode) {
671 if (location->discover_mode == pe_discover_exclusive) {
672 rsc->exclusive_discover = TRUE;
673 }
674 /* exclusive > never > always... always is default */
675 weighted_node->rsc_discover_mode = location->discover_mode;
676 }
677 }
678}
int pcmk__add_scores(int score1, int score2)
Definition scores.c:116
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition scores.c:86
int char2score(const char *score)
Get the integer value of a score string.
Definition scores.c:36
const char * role2text(enum rsc_role_e role)
Definition common.c:450
rsc_role_e
Possible roles that a resource can be in.
Definition common.h:92
@ RSC_ROLE_STARTED
Definition common.h:95
@ RSC_ROLE_UNKNOWN
Definition common.h:93
@ RSC_ROLE_UNPROMOTED
Definition common.h:96
enum rsc_role_e text2role(const char *role)
Definition common.c:479
GHashTable * pe_rsc_params(pe_resource_t *rsc, const pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Definition complex.c:436
gboolean local
Definition cpg.c:2
A dumping ground.
#define INFINITY
Definition crm.h:99
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition iso8601.c:359
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:150
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
Definition iso8601.c:142
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition iso8601.c:126
struct crm_time_s crm_time_t
Definition iso8601.h:32
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pe_working_set_t *data_set, const char *id, pe_resource_t **rsc, pe_tag_t **tag)
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pe_working_set_t *data_set)
G_GNUC_INTERNAL pe_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, const pe_working_set_t *data_set)
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define crm_debug(fmt, args...)
Definition logging.h:380
#define crm_log_xml_trace(xml, text)
Definition logging.h:389
#define crm_trace(fmt, args...)
Definition logging.h:381
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
#define XML_LOCATION_ATTR_DISCOVERY
Definition msg_xml.h:370
#define XML_TAG_RESOURCE_REF
Definition msg_xml.h:229
#define XML_RULE_ATTR_BOOLEAN_OP
Definition msg_xml.h:354
#define ID(x)
Definition msg_xml.h:480
#define XML_LOC_ATTR_SOURCE_PATTERN
Definition msg_xml.h:386
#define XML_RULE_ATTR_SCORE
Definition msg_xml.h:351
#define XML_RULE_ATTR_ROLE
Definition msg_xml.h:353
#define XML_TAG_RULE
Definition msg_xml.h:350
#define XML_CONS_TAG_RSC_SET
Definition msg_xml.h:367
#define XML_ATTR_ID
Definition msg_xml.h:147
#define XML_RULE_ATTR_SCORE_ATTRIBUTE
Definition msg_xml.h:352
#define XML_CIB_TAG_NODE
Definition msg_xml.h:218
#define XML_LOC_ATTR_SOURCE
Definition msg_xml.h:385
pe_working_set_t * data_set
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:496
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:302
pcmk__action_result_t result
Definition pcmk_fence.c:35
void pcmk__unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
pe__location_t * pcmk__new_location(const char *id, pe_resource_t *rsc, int node_weight, const char *discover_mode, pe_node_t *node, pe_working_set_t *data_set)
void pcmk__apply_locations(pe_working_set_t *data_set)
void pcmk__apply_location(pe_resource_t *rsc, pe__location_t *location)
GList * pcmk__copy_node_list(const GList *list, bool reset)
@ pe_discover_exclusive
Definition pe_types.h:502
@ pe_discover_always
Definition pe_types.h:500
@ pe_discover_never
Definition pe_types.h:501
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
const char * pe_node_attribute_calculated(const pe_node_t *node, const char *name, const pe_resource_t *rsc)
Definition common.c:518
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
Definition utils.c:715
pe_node_t * pe__copy_node(const pe_node_t *this_node)
Definition utils.c:89
#define pe_err(fmt...)
Definition internal.h:52
@ pcmk_rc_ok
Definition results.h:151
@ pcmk_rc_unpack_error
Definition results.h:115
char * pe_expand_re_matches(const char *string, const pe_re_match_data_t *match_data)
Expand any regular expression submatches (%0-%9) in a string.
Definition rules.c:560
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
Definition rules.c:55
Cluster status and scheduling.
pe_node_t * pe_find_node(const GList *node_list, const char *node_name)
Find a node by name in a list of nodes.
Definition status.c:473
pe_node_t * pe_find_node_id(const GList *node_list, const char *id)
Find a node by ID in a list of nodes.
Definition status.c:448
@ pcmk__str_null_matches
@ pcmk__str_casei
enum pe_discover_e discover_mode
Definition internal.h:195
pe_resource_t * rsc_lh
Definition internal.h:193
enum rsc_role_e role_filter
Definition internal.h:194
pe_re_match_data_t * re
Definition common.h:176
int weight
Definition pe_types.h:265
int rsc_discover_mode
Definition pe_types.h:269
struct pe_node_shared_s * details
Definition pe_types.h:268
GHashTable * attrs
Definition pe_types.h:257
const char * id
Definition pe_types.h:231
regmatch_t * pmatch
Definition common.h:172
char * string
Definition common.h:170
GList * rsc_location
Definition pe_types.h:390
GHashTable * meta
Definition pe_types.h:405
gboolean exclusive_discover
Definition pe_types.h:377
GHashTable * allowed_nodes
Definition pe_types.h:400
resource_alloc_functions_t * cmds
Definition pe_types.h:359
enum rsc_role_e next_role
Definition pe_types.h:403
xmlNode * input
Definition pe_types.h:160
GList * resources
Definition pe_types.h:181
GList * placement_constraints
Definition pe_types.h:182
crm_time_t * now
Definition pe_types.h:161
void(* apply_location)(pe_resource_t *rsc, pe__location_t *location)
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Definition xml.c:2593
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2521
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2547
void free_xml(xmlNode *child)
Definition xml.c:813
xmlNode * copy_xml(xmlNode *src_node)
Definition xml.c:819
void xml_remove_prop(xmlNode *obj, const char *name)
Definition xml.c:1735