pacemaker 3.0.1-16e74fc4da
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-2024 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>
17#include <crm/pengine/status.h>
18#include <pacemaker-internal.h>
19
21
31static bool
32parse_location_role(const char *role_spec, enum rsc_role_e *role)
33{
34 if (role_spec == NULL) {
35 *role = pcmk_role_unknown;
36 return true;
37 }
38
39 *role = pcmk_parse_role(role_spec);
40 switch (*role) {
42 return false;
43
46 /* Any promotable clone instance cannot be promoted without being in
47 * the unpromoted role first. Therefore, any constraint for the
48 * started or unpromoted role applies to every role.
49 */
50 *role = pcmk_role_unknown;
51 break;
52
53 default:
54 break;
55 }
56 return true;
57}
58
72static const char *
73score_attribute_name(const xmlNode *rule_xml, char **allocated,
74 const pcmk_rule_input_t *rule_input)
75{
76 const char *name = NULL;
77
79 if (name == NULL) {
80 return NULL;
81 }
82
83 /* A score attribute name may use submatches extracted from a
84 * resource ID regular expression. For example, if score-attribute is
85 * "loc-\1", rsc-pattern is "ip-(.*)", and the resource ID is "ip-db", then
86 * the score attribute name is "loc-db".
87 */
88 if ((rule_input->rsc_id != NULL) && (rule_input->rsc_id_nmatches > 0)) {
89 *allocated = pcmk__replace_submatches(name, rule_input->rsc_id,
90 rule_input->rsc_id_submatches,
91 rule_input->rsc_id_nmatches);
92 if (*allocated != NULL) {
93 name = *allocated;
94 }
95 }
96 return name;
97}
98
108static int
109score_from_rule(const xmlNode *rule_xml, int *score)
110{
111 int rc = pcmk_rc_ok;
112 const char *score_s = crm_element_value(rule_xml, PCMK_XA_SCORE);
113
114 if (score_s == NULL) { // Not possible with schema validation enabled
115 pcmk__config_err("Ignoring location constraint rule %s because "
116 "neither " PCMK_XA_SCORE " nor "
117 PCMK_XA_SCORE_ATTRIBUTE " was specified",
118 pcmk__xe_id(rule_xml));
120 }
121
122 rc = pcmk_parse_score(score_s, score, 0);
123 if (rc != pcmk_rc_ok) { // Not possible with schema validation enabled
124 pcmk__config_err("Ignoring location constraint rule %s because "
125 "'%s' is not a valid " PCMK_XA_SCORE ": %s",
126 pcmk__xe_id(rule_xml), score_s, pcmk_rc_str(rc));
128 }
129
130 return pcmk_rc_ok;
131}
132
147static int
148score_from_attr(const char *constraint_id, const char *attr_name,
149 const pcmk_node_t *node, const pcmk_resource_t *rsc, int *score)
150{
151 int rc = pcmk_rc_ok;
152 const char *target = NULL;
153 const char *score_s = NULL;
154
155 target = g_hash_table_lookup(rsc->priv->meta,
157 score_s = pcmk__node_attr(node, attr_name, target, pcmk__rsc_node_current);
158 if (pcmk__str_empty(score_s)) {
159 crm_info("Ignoring location %s for %s on %s "
160 "because it has no node attribute %s",
161 constraint_id, rsc->id, pcmk__node_name(node), attr_name);
162 return ENXIO;
163 }
164
165 rc = pcmk_parse_score(score_s, score, 0);
166 if (rc != pcmk_rc_ok) {
167 crm_warn("Ignoring location %s for node %s because node "
168 "attribute %s value '%s' is not a valid score: %s",
169 constraint_id, pcmk__node_name(node), attr_name,
170 score_s, pcmk_rc_str(rc));
171 return rc;
172 }
173 return pcmk_rc_ok;
174}
175
192static bool
193generate_location_rule(pcmk_resource_t *rsc, xmlNode *rule_xml,
194 const char *discovery, crm_time_t *next_change,
195 pcmk_rule_input_t *rule_input, const char *constraint_id)
196{
197 const char *rule_id = NULL;
198 const char *score_attr = NULL;
199 const char *boolean = NULL;
200 const char *role_spec = NULL;
201
202 GList *iter = NULL;
203 int score = 0;
204 char *local_score_attr = NULL;
205 pcmk__location_t *location_rule = NULL;
206 enum rsc_role_e role = pcmk_role_unknown;
208
209 rule_xml = pcmk__xe_resolve_idref(rule_xml, rsc->priv->scheduler->input);
210 if (rule_xml == NULL) {
211 return false; // Error already logged
212 }
213
214 rule_id = crm_element_value(rule_xml, PCMK_XA_ID);
215 if (rule_id == NULL) {
216 pcmk__config_err("Ignoring location constraint '%s' because its rule "
217 "has no " PCMK_XA_ID,
218 constraint_id);
219 return false;
220 }
221
222 boolean = crm_element_value(rule_xml, PCMK_XA_BOOLEAN_OP);
223 role_spec = crm_element_value(rule_xml, PCMK_XA_ROLE);
224
225 if (parse_location_role(role_spec, &role)) {
226 crm_trace("Setting rule %s role filter to %s", rule_id, role_spec);
227 } else {
228 pcmk__config_err("Ignoring location constraint '%s' because rule '%s' "
229 "has invalid " PCMK_XA_ROLE " '%s'",
230 constraint_id, rule_id, role_spec);
231 return false;
232 }
233
234 combine = pcmk__parse_combine(boolean);
235 switch (combine) {
237 case pcmk__combine_or:
238 break;
239
240 default: // Not possible with schema validation enabled
241 pcmk__config_err("Ignoring location constraint '%s' because rule "
242 "'%s' has invalid " PCMK_XA_BOOLEAN_OP " '%s'",
243 constraint_id, rule_id, boolean);
244 return false;
245 }
246
247 /* Users may configure the rule with either a score or the name of a
248 * node attribute whose value should be used as the constraint score for
249 * that node.
250 */
251 score_attr = score_attribute_name(rule_xml, &local_score_attr, rule_input);
252 if ((score_attr == NULL)
253 && (score_from_rule(rule_xml, &score) != pcmk_rc_ok)) {
254 return false;
255 }
256
257 location_rule = pcmk__new_location(rule_id, rsc, 0, discovery, NULL);
258 CRM_CHECK(location_rule != NULL, return NULL);
259
260 location_rule->role_filter = role;
261
262 for (iter = rsc->priv->scheduler->nodes;
263 iter != NULL; iter = iter->next) {
264
265 pcmk_node_t *node = iter->data;
266 pcmk_node_t *local = NULL;
267
268 rule_input->node_attrs = node->priv->attrs;
269 rule_input->rsc_params = pe_rsc_params(rsc, node,
270 rsc->priv->scheduler);
271
272 if (pcmk_evaluate_rule(rule_xml, rule_input,
273 next_change) != pcmk_rc_ok) {
274 continue;
275 }
276
277 if ((score_attr != NULL)
278 && (score_from_attr(constraint_id, score_attr, node, rsc,
279 &score) != pcmk_rc_ok)) {
280 continue; // Message already logged
281 }
282
283 local = pe__copy_node(node);
284 location_rule->nodes = g_list_prepend(location_rule->nodes, local);
285 local->assign->score = score;
286 pcmk__rsc_trace(rsc,
287 "Location %s score for %s on %s is %s via rule %s",
288 constraint_id, rsc->id, pcmk__node_name(node),
289 pcmk_readable_score(score), rule_id);
290 }
291
292 free(local_score_attr);
293
294 if (location_rule->nodes == NULL) {
295 crm_trace("No matching nodes for location constraint rule %s", rule_id);
296 } else {
297 crm_trace("Location constraint rule %s matched %d nodes",
298 rule_id, g_list_length(location_rule->nodes));
299 }
300 return true;
301}
302
303static void
304unpack_rsc_location(xmlNode *xml_obj, pcmk_resource_t *rsc,
305 const char *role_spec, const char *score,
306 char *rsc_id_match, int rsc_id_nmatches,
307 regmatch_t *rsc_id_submatches)
308{
309 const char *rsc_id = crm_element_value(xml_obj, PCMK_XA_RSC);
310 const char *id = crm_element_value(xml_obj, PCMK_XA_ID);
311 const char *node = crm_element_value(xml_obj, PCMK_XA_NODE);
312 const char *discovery = crm_element_value(xml_obj,
314
315 if (rsc == NULL) {
316 pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
317 "does not exist", id, rsc_id);
318 return;
319 }
320
321 if (score == NULL) {
322 score = crm_element_value(xml_obj, PCMK_XA_SCORE);
323 }
324
325 if ((node != NULL) && (score != NULL)) {
326 int score_i = 0;
327 int rc = pcmk_rc_ok;
328 pcmk_node_t *match = pcmk_find_node(rsc->priv->scheduler, node);
329 enum rsc_role_e role = pcmk_role_unknown;
330 pcmk__location_t *location = NULL;
331
332 if (match == NULL) {
333 crm_info("Ignoring location constraint %s "
334 "because '%s' is not a known node",
335 pcmk__s(id, "without ID"), node);
336 return;
337 }
338
339 rc = pcmk_parse_score(score, &score_i, 0);
340 if (rc != pcmk_rc_ok) { // Not possible with schema validation enabled
341 pcmk__config_err("Ignoring location constraint %s "
342 "because '%s' is not a valid score", id, score);
343 return;
344 }
345
346 if (role_spec == NULL) {
347 role_spec = crm_element_value(xml_obj, PCMK_XA_ROLE);
348 }
349 if (parse_location_role(role_spec, &role)) {
350 crm_trace("Setting location constraint %s role filter: %s",
351 id, role_spec);
352 } else { // Not possible with schema validation enabled
353 pcmk__config_err("Ignoring location constraint %s "
354 "because '%s' is not a valid " PCMK_XA_ROLE,
355 id, role_spec);
356 return;
357 }
358
359 location = pcmk__new_location(id, rsc, score_i, discovery, match);
360 if (location == NULL) {
361 return; // Error already logged
362 }
363 location->role_filter = role;
364
365 } else {
366 crm_time_t *next_change = crm_time_new_undefined();
367 xmlNode *rule_xml = pcmk__xe_first_child(xml_obj, PCMK_XE_RULE, NULL,
368 NULL);
369 pcmk_rule_input_t rule_input = {
370 .now = rsc->priv->scheduler->priv->now,
371 .rsc_meta = rsc->priv->meta,
372 .rsc_id = rsc_id_match,
373 .rsc_id_submatches = rsc_id_submatches,
374 .rsc_id_nmatches = rsc_id_nmatches,
375 };
376
377 generate_location_rule(rsc, rule_xml, discovery, next_change,
378 &rule_input, id);
379
380 /* If there is a point in the future when the evaluation of a rule will
381 * change, make sure the scheduler is re-run by that time.
382 */
383 if (crm_time_is_defined(next_change)) {
384 time_t t = (time_t) crm_time_get_seconds_since_epoch(next_change);
385
387 "location rule evaluation");
388 }
389 crm_time_free(next_change);
390 }
391}
392
393static void
394unpack_simple_location(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
395{
396 const char *id = crm_element_value(xml_obj, PCMK_XA_ID);
397 const char *value = crm_element_value(xml_obj, PCMK_XA_RSC);
398
399 if (value) {
400 pcmk_resource_t *rsc;
401
403 unpack_rsc_location(xml_obj, rsc, NULL, NULL, NULL, 0, NULL);
404 }
405
406 value = crm_element_value(xml_obj, PCMK_XA_RSC_PATTERN);
407 if (value) {
408 regex_t regex;
409 bool invert = false;
410
411 if (value[0] == '!') {
412 value++;
413 invert = true;
414 }
415
416 if (regcomp(&regex, value, REG_EXTENDED) != 0) {
417 pcmk__config_err("Ignoring constraint '%s' because "
419 " has invalid value '%s'", id, value);
420 return;
421 }
422
423 for (GList *iter = scheduler->priv->resources;
424 iter != NULL; iter = iter->next) {
425
426 pcmk_resource_t *r = iter->data;
427 int nregs = 0;
428 regmatch_t *pmatch = NULL;
429 int status;
430
431 if (regex.re_nsub > 0) {
432 nregs = regex.re_nsub + 1;
433 } else {
434 nregs = 1;
435 }
436 pmatch = pcmk__assert_alloc(nregs, sizeof(regmatch_t));
437
438 status = regexec(&regex, r->id, nregs, pmatch, 0);
439
440 if (!invert && (status == 0)) {
441 crm_debug("'%s' matched '%s' for %s", r->id, value, id);
442 unpack_rsc_location(xml_obj, r, NULL, NULL, r->id, nregs,
443 pmatch);
444
445 } else if (invert && (status != 0)) {
446 crm_debug("'%s' is an inverted match of '%s' for %s",
447 r->id, value, id);
448 unpack_rsc_location(xml_obj, r, NULL, NULL, NULL, 0, NULL);
449
450 } else {
451 crm_trace("'%s' does not match '%s' for %s", r->id, value, id);
452 }
453
454 free(pmatch);
455 }
456
457 // @TODO Maybe log a notice if we did not match any resources
458
459 regfree(&regex);
460 }
461}
462
463// \return Standard Pacemaker return code
464static int
465unpack_location_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
467{
468 const char *id = NULL;
469 const char *rsc_id = NULL;
470 const char *state = NULL;
471 pcmk_resource_t *rsc = NULL;
472 pcmk__idref_t *tag = NULL;
473 xmlNode *rsc_set = NULL;
474
475 *expanded_xml = NULL;
476
477 CRM_CHECK(xml_obj != NULL, return EINVAL);
478
479 id = pcmk__xe_id(xml_obj);
480 if (id == NULL) {
481 pcmk__config_err("Ignoring <%s> constraint without " PCMK_XA_ID,
482 xml_obj->name);
484 }
485
486 // Check whether there are any resource sets with template or tag references
487 *expanded_xml = pcmk__expand_tags_in_sets(xml_obj, scheduler);
488 if (*expanded_xml != NULL) {
489 crm_log_xml_trace(*expanded_xml, "Expanded " PCMK_XE_RSC_LOCATION);
490 return pcmk_rc_ok;
491 }
492
493 rsc_id = crm_element_value(xml_obj, PCMK_XA_RSC);
494 if (rsc_id == NULL) {
495 return pcmk_rc_ok;
496 }
497
498 if (!pcmk__valid_resource_or_tag(scheduler, rsc_id, &rsc, &tag)) {
499 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
500 "valid resource or tag", id, rsc_id);
502
503 } else if (rsc != NULL) {
504 // No template is referenced
505 return pcmk_rc_ok;
506 }
507
508 state = crm_element_value(xml_obj, PCMK_XA_ROLE);
509
510 *expanded_xml = pcmk__xml_copy(NULL, xml_obj);
511
512 /* Convert any template or tag reference into constraint
513 * PCMK_XE_RESOURCE_SET
514 */
515 if (!pcmk__tag_to_set(*expanded_xml, &rsc_set, PCMK_XA_RSC,
516 false, scheduler)) {
517 pcmk__xml_free(*expanded_xml);
518 *expanded_xml = NULL;
520 }
521
522 if (rsc_set != NULL) {
523 if (state != NULL) {
524 /* Move PCMK_XA_RSC_ROLE into converted PCMK_XE_RESOURCE_SET as
525 * PCMK_XA_ROLE attribute
526 */
527 crm_xml_add(rsc_set, PCMK_XA_ROLE, state);
528 pcmk__xe_remove_attr(*expanded_xml, PCMK_XA_ROLE);
529 }
530 crm_log_xml_trace(*expanded_xml, "Expanded " PCMK_XE_RSC_LOCATION);
531
532 } else {
533 // No sets
534 pcmk__xml_free(*expanded_xml);
535 *expanded_xml = NULL;
536 }
537
538 return pcmk_rc_ok;
539}
540
541// \return Standard Pacemaker return code
542static int
543unpack_location_set(xmlNode *location, xmlNode *set,
545{
546 xmlNode *xml_rsc = NULL;
547 pcmk_resource_t *resource = NULL;
548 const char *set_id;
549 const char *role;
550 const char *local_score;
551
552 CRM_CHECK(set != NULL, return EINVAL);
553
554 set_id = pcmk__xe_id(set);
555 if (set_id == NULL) {
556 pcmk__config_err("Ignoring " PCMK_XE_RESOURCE_SET " without "
557 PCMK_XA_ID " in constraint '%s'",
558 pcmk__s(pcmk__xe_id(location), "(missing ID)"));
560 }
561
562 role = crm_element_value(set, PCMK_XA_ROLE);
563 local_score = crm_element_value(set, PCMK_XA_SCORE);
564
565 for (xml_rsc = pcmk__xe_first_child(set, PCMK_XE_RESOURCE_REF, NULL, NULL);
566 xml_rsc != NULL;
567 xml_rsc = pcmk__xe_next(xml_rsc, PCMK_XE_RESOURCE_REF)) {
568
570 pcmk__xe_id(xml_rsc));
571 if (resource == NULL) {
572 pcmk__config_err("%s: No resource found for %s",
573 set_id, pcmk__xe_id(xml_rsc));
575 }
576
577 unpack_rsc_location(location, resource, role, local_score, NULL, 0,
578 NULL);
579 }
580
581 return pcmk_rc_ok;
582}
583
584void
586{
587 xmlNode *set = NULL;
588 bool any_sets = false;
589
590 xmlNode *orig_xml = NULL;
591 xmlNode *expanded_xml = NULL;
592
593 if (unpack_location_tags(xml_obj, &expanded_xml, scheduler) != pcmk_rc_ok) {
594 return;
595 }
596
597 if (expanded_xml) {
598 orig_xml = xml_obj;
599 xml_obj = expanded_xml;
600 }
601
602 for (set = pcmk__xe_first_child(xml_obj, PCMK_XE_RESOURCE_SET, NULL, NULL);
603 set != NULL; set = pcmk__xe_next(set, PCMK_XE_RESOURCE_SET)) {
604
605 any_sets = true;
607 if ((set == NULL) // Configuration error, message already logged
608 || (unpack_location_set(xml_obj, set, scheduler) != pcmk_rc_ok)) {
609
610 if (expanded_xml) {
611 pcmk__xml_free(expanded_xml);
612 }
613 return;
614 }
615 }
616
617 if (expanded_xml) {
618 pcmk__xml_free(expanded_xml);
619 xml_obj = orig_xml;
620 }
621
622 if (!any_sets) {
623 unpack_simple_location(xml_obj, scheduler);
624 }
625}
626
643 int node_score, const char *probe_mode, pcmk_node_t *node)
644{
645 pcmk__location_t *new_con = NULL;
646
647 CRM_CHECK((node != NULL) || (node_score == 0), return NULL);
648
649 if (id == NULL) {
650 pcmk__config_err("Invalid constraint: no ID specified");
651 return NULL;
652 }
653
654 if (rsc == NULL) {
655 pcmk__config_err("Invalid constraint %s: no resource specified", id);
656 return NULL;
657 }
658
659 new_con = pcmk__assert_alloc(1, sizeof(pcmk__location_t));
660 new_con->id = pcmk__str_copy(id);
661 new_con->rsc = rsc;
662 new_con->nodes = NULL;
664
665 if (pcmk__str_eq(probe_mode, PCMK_VALUE_ALWAYS,
668
669 } else if (pcmk__str_eq(probe_mode, PCMK_VALUE_NEVER, pcmk__str_casei)) {
670 new_con->probe_mode = pcmk__probe_never;
671
672 } else if (pcmk__str_eq(probe_mode, PCMK_VALUE_EXCLUSIVE,
676
677 } else {
678 pcmk__config_err("Invalid " PCMK_XA_RESOURCE_DISCOVERY " value %s "
679 "in location constraint", probe_mode);
680 }
681
682 if (node != NULL) {
683 pcmk_node_t *copy = pe__copy_node(node);
684
685 copy->assign->score = node_score;
686 new_con->nodes = g_list_prepend(NULL, copy);
687 }
688
690 g_list_prepend(rsc->priv->scheduler->priv->location_constraints,
691 new_con);
693 g_list_prepend(rsc->priv->location_constraints, new_con);
694
695 return new_con;
696}
697
704void
706{
707 for (GList *iter = scheduler->priv->location_constraints;
708 iter != NULL; iter = iter->next) {
709 pcmk__location_t *location = iter->data;
710
711 location->rsc->priv->cmds->apply_location(location->rsc, location);
712 }
713}
714
725void
727{
728 bool need_role = false;
729
730 pcmk__assert((rsc != NULL) && (location != NULL));
731
732 // If a role was specified, ensure constraint is applicable
733 need_role = (location->role_filter > pcmk_role_unknown);
734 if (need_role && (location->role_filter != rsc->priv->next_role)) {
735 pcmk__rsc_trace(rsc,
736 "Not applying %s to %s because role will be %s not %s",
737 location->id, rsc->id,
739 pcmk_role_text(location->role_filter));
740 return;
741 }
742
743 if (location->nodes == NULL) {
744 pcmk__rsc_trace(rsc, "Not applying %s to %s because no nodes match",
745 location->id, rsc->id);
746 return;
747 }
748
749 for (GList *iter = location->nodes; iter != NULL; iter = iter->next) {
750 pcmk_node_t *node = iter->data;
751 pcmk_node_t *allowed_node = NULL;
752
753 allowed_node = g_hash_table_lookup(rsc->priv->allowed_nodes,
754 node->priv->id);
755
756 pcmk__rsc_trace(rsc, "Applying %s%s%s to %s score on %s: %c %s",
757 location->id,
758 (need_role? " for role " : ""),
759 (need_role? pcmk_role_text(location->role_filter) : ""),
760 rsc->id, pcmk__node_name(node),
761 ((allowed_node == NULL)? '=' : '+'),
763
764 if (allowed_node == NULL) {
765 allowed_node = pe__copy_node(node);
766 g_hash_table_insert(rsc->priv->allowed_nodes,
767 (gpointer) allowed_node->priv->id,
768 allowed_node);
769 } else {
770 allowed_node->assign->score =
771 pcmk__add_scores(allowed_node->assign->score,
772 node->assign->score);
773 }
774
775 if (allowed_node->assign->probe_mode < location->probe_mode) {
776 if (location->probe_mode == pcmk__probe_exclusive) {
778 }
779 /* exclusive > never > always... always is default */
780 allowed_node->assign->probe_mode = location->probe_mode;
781 }
782 }
783}
const char * pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target, enum pcmk__rsc_node node_type)
Definition attrs.c:114
const char * name
Definition cib.c:26
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:246
int pcmk_evaluate_rule(xmlNode *rule, const pcmk_rule_input_t *rule_input, crm_time_t *next_change)
Evaluate a single rule, including all its conditions.
Definition rules.c:1304
GHashTable * pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Get a table of resource parameters.
Definition complex.c:462
gboolean local
Definition cpg.c:2
A dumping ground.
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition iso8601.c:374
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:129
struct crm_time_s crm_time_t
Definition iso8601.h:32
G_GNUC_INTERNAL pcmk_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr, bool convert_rsc, const pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pcmk_scheduler_t *scheduler, const char *id, pcmk_resource_t **rsc, pcmk__idref_t **tag)
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_warn(fmt, args...)
Definition logging.h:360
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_debug(fmt, args...)
Definition logging.h:368
#define crm_log_xml_trace(xml, text)
Definition logging.h:378
#define crm_trace(fmt, args...)
Definition logging.h:370
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
pcmk_scheduler_t * scheduler
@ pcmk__probe_always
@ pcmk__probe_exclusive
@ pcmk__probe_never
#define PCMK_VALUE_EXCLUSIVE
Definition options.h:152
#define PCMK_META_CONTAINER_ATTRIBUTE_TARGET
Definition options.h:86
#define PCMK_VALUE_NEVER
Definition options.h:179
#define PCMK_VALUE_ALWAYS
Definition options.h:133
const char * target
Definition pcmk_fence.c:31
void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
pcmk__location_t * pcmk__new_location(const char *id, pcmk_resource_t *rsc, int node_score, const char *probe_mode, pcmk_node_t *node)
void pcmk__apply_locations(pcmk_scheduler_t *scheduler)
void pcmk__unpack_location(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
Definition utils.c:124
@ pcmk__rsc_exclusive_probes
#define pcmk__set_rsc_flags(resource, flags_to_set)
@ pcmk__rsc_node_current
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:617
@ pcmk_rc_ok
Definition results.h:159
@ pcmk_rc_unpack_error
Definition results.h:122
#define pcmk__assert(expr)
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition roles.c:23
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition roles.c:51
rsc_role_e
Definition roles.h:34
@ pcmk_role_started
Started.
Definition roles.h:37
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:35
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:38
pcmk__combine
@ pcmk__combine_or
@ pcmk__combine_unknown
@ pcmk__combine_and
char * pcmk__replace_submatches(const char *string, const char *match, const regmatch_t submatches[], int nmatches)
Definition rules.c:614
enum pcmk__combine pcmk__parse_combine(const char *combine)
Definition rules.c:831
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
Definition scheduler.c:282
#define pcmk__rsc_trace(rsc, fmt, args...)
void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
Definition scheduler.c:321
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
Definition scores.c:34
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition scores.c:102
int pcmk__add_scores(int score1, int score2)
Definition scores.c:159
Cluster status and scheduling.
@ pcmk__str_null_matches
@ pcmk__str_casei
#define pcmk__str_copy(str)
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
Location constraint object.
enum pcmk__probe_mode probe_mode
enum rsc_role_e role_filter
pcmk_resource_t * rsc
enum pcmk__probe_mode probe_mode
pcmk_scheduler_t * scheduler
const pcmk__assignment_methods_t * cmds
pcmk__resource_private_t * priv
Definition resources.h:61
pcmk__scheduler_private_t * priv
Definition scheduler.h:99
GList * nodes
Definition scheduler.h:97
xmlNode * input
Definition scheduler.h:81
pcmk__node_private_t * priv
Definition nodes.h:85
struct pcmk__node_assignment * assign
Definition nodes.h:79
Data used to evaluate a rule (any NULL items are ignored)
Definition rules.h:57
const regmatch_t * rsc_id_submatches
Resource pattern submatches (as set by regexec()) for rsc_id.
Definition rules.h:99
int rsc_id_nmatches
Number of entries in rsc_id_submatches.
Definition rules.h:102
GHashTable * node_attrs
Definition rules.h:77
const char * rsc_id
Resource ID to compare against a location constraint's resource pattern.
Definition rules.h:96
GHashTable * rsc_params
Definition rules.h:86
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml_element.c:43
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
xmlNode * pcmk__xe_resolve_idref(xmlNode *xml, xmlNode *search)
Definition xml_idref.c:85
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition xml.c:832
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
#define PCMK_XA_SCORE
Definition xml_names.h:396
#define PCMK_XA_SCORE_ATTRIBUTE
Definition xml_names.h:397
#define PCMK_XE_RULE
Definition xml_names.h:191
#define PCMK_XE_RESOURCE_REF
Definition xml_names.h:177
#define PCMK_XA_ID
Definition xml_names.h:301
#define PCMK_XA_ROLE
Definition xml_names.h:387
#define PCMK_XA_BOOLEAN_OP
Definition xml_names.h:240
#define PCMK_XA_NODE
Definition xml_names.h:335
#define PCMK_XE_RESOURCE_SET
Definition xml_names.h:178
#define PCMK_XA_RESOURCE_DISCOVERY
Definition xml_names.h:384
#define PCMK_XE_RSC_LOCATION
Definition xml_names.h:188
#define PCMK_XA_RSC_PATTERN
Definition xml_names.h:389
#define PCMK_XA_RSC
Definition xml_names.h:388