pacemaker  2.1.8-3980678f03
Scalable High-Availability cluster resource manager
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 <crm/pengine/rules.h>
19 #include <pacemaker-internal.h>
20 
21 #include "libpacemaker_private.h"
22 
23 static int
24 get_node_score(const char *rule, const char *score, bool raw,
25  pcmk_node_t *node, pcmk_resource_t *rsc)
26 {
27  int score_f = 0;
28 
29  if (score == NULL) {
30  pcmk__config_warn("Rule %s: no score specified (assuming 0)", rule);
31 
32  } else if (raw) {
33  score_f = char2score(score);
34 
35  } else {
36  const char *target = NULL;
37  const char *attr_score = NULL;
38 
39  target = g_hash_table_lookup(rsc->meta,
41 
42  attr_score = pcmk__node_attr(node, score, target,
44  if (attr_score == NULL) {
45  crm_debug("Rule %s: %s did not have a value for %s",
46  rule, pcmk__node_name(node), score);
47  score_f = -PCMK_SCORE_INFINITY;
48 
49  } else {
50  crm_debug("Rule %s: %s had value %s for %s",
51  rule, pcmk__node_name(node), attr_score, score);
52  score_f = char2score(attr_score);
53  }
54  }
55  return score_f;
56 }
57 
67 static bool
68 parse_location_role(const char *role_spec, enum rsc_role_e *role)
69 {
70  if (role_spec == NULL) {
71  *role = pcmk_role_unknown;
72  return true;
73  }
74 
75  *role = pcmk_parse_role(role_spec);
76  switch (*role) {
77  case pcmk_role_unknown:
78  return false;
79 
80  case pcmk_role_started:
82  /* Any promotable clone instance cannot be promoted without being in
83  * the unpromoted role first. Therefore, any constraint for the
84  * started or unpromoted role applies to every role.
85  */
86  *role = pcmk_role_unknown;
87  break;
88 
89  default:
90  break;
91  }
92  return true;
93 }
94 
110 static bool
111 generate_location_rule(pcmk_resource_t *rsc, xmlNode *rule_xml,
112  const char *discovery, crm_time_t *next_change,
113  pcmk_rule_input_t *rule_input)
114 {
115  const char *rule_id = NULL;
116  const char *score = NULL;
117  const char *boolean = NULL;
118  const char *role_spec = NULL;
119 
120  GList *iter = NULL;
121 
122  bool raw_score = true;
123  bool score_allocated = false;
124 
125  pcmk__location_t *location_rule = NULL;
126  enum rsc_role_e role = pcmk_role_unknown;
127  enum pcmk__combine combine = pcmk__combine_unknown;
128 
129  rule_xml = expand_idref(rule_xml, rsc->cluster->input);
130  if (rule_xml == NULL) {
131  return false; // Error already logged
132  }
133 
134  rule_id = crm_element_value(rule_xml, PCMK_XA_ID);
135  if (rule_id == NULL) {
136  pcmk__config_err("Ignoring " PCMK_XE_RULE " without " PCMK_XA_ID
137  " in location constraint");
138  return false;
139  }
140 
141  boolean = crm_element_value(rule_xml, PCMK_XA_BOOLEAN_OP);
142  role_spec = crm_element_value(rule_xml, PCMK_XA_ROLE);
143 
144  if (parse_location_role(role_spec, &role)) {
145  crm_trace("Setting rule %s role filter to %s", rule_id, role_spec);
146  } else {
147  pcmk__config_err("Ignoring rule %s: Invalid " PCMK_XA_ROLE " '%s'",
148  rule_id, role_spec);
149  return false;
150  }
151 
152  crm_trace("Processing location constraint rule %s", rule_id);
153 
154  score = crm_element_value(rule_xml, PCMK_XA_SCORE);
155  if (score == NULL) {
156  score = crm_element_value(rule_xml, PCMK_XA_SCORE_ATTRIBUTE);
157  if (score != NULL) {
158  raw_score = false;
159  }
160  }
161 
162  combine = pcmk__parse_combine(boolean);
163  switch (combine) {
164  case pcmk__combine_and:
165  case pcmk__combine_or:
166  break;
167 
168  default:
169  /* @COMPAT When we can break behavioral backward compatibility,
170  * return false
171  */
172  pcmk__config_warn("Location constraint rule %s has invalid "
173  PCMK_XA_BOOLEAN_OP " value '%s', using default "
174  "'" PCMK_VALUE_AND "'",
175  rule_id, boolean);
176  combine = pcmk__combine_and;
177  break;
178  }
179 
180  location_rule = pcmk__new_location(rule_id, rsc, 0, discovery, NULL);
181  CRM_CHECK(location_rule != NULL, return NULL);
182 
183  location_rule->role_filter = role;
184 
185  if ((rule_input->rsc_id != NULL) && (rule_input->rsc_id_nmatches > 0)
186  && !raw_score) {
187 
188  char *result = pcmk__replace_submatches(score, rule_input->rsc_id,
189  rule_input->rsc_id_submatches,
190  rule_input->rsc_id_nmatches);
191 
192  if (result != NULL) {
193  score = result;
194  score_allocated = true;
195  }
196  }
197 
198  for (iter = rsc->cluster->nodes; iter != NULL; iter = iter->next) {
199  pcmk_node_t *node = iter->data;
200 
201  rule_input->node_attrs = node->details->attrs;
202  rule_input->rsc_params = pe_rsc_params(rsc, node, rsc->cluster);
203 
204  if (pcmk_evaluate_rule(rule_xml, rule_input,
205  next_change) == pcmk_rc_ok) {
207 
208  location_rule->nodes = g_list_prepend(location_rule->nodes, local);
209  local->weight = get_node_score(rule_id, score, raw_score, node,
210  rsc);
211  crm_trace("%s has score %s after %s", pcmk__node_name(node),
212  pcmk_readable_score(local->weight), rule_id);
213  }
214  }
215 
216  if (score_allocated) {
217  free((char *)score);
218  }
219 
220  if (location_rule->nodes == NULL) {
221  crm_trace("No matching nodes for location constraint rule %s", rule_id);
222  } else {
223  crm_trace("Location constraint rule %s matched %d nodes",
224  rule_id, g_list_length(location_rule->nodes));
225  }
226  return true;
227 }
228 
229 static void
230 unpack_rsc_location(xmlNode *xml_obj, pcmk_resource_t *rsc,
231  const char *role_spec, const char *score,
232  char *rsc_id_match, int rsc_id_nmatches,
233  regmatch_t *rsc_id_submatches)
234 {
235  const char *rsc_id = crm_element_value(xml_obj, PCMK_XA_RSC);
236  const char *id = crm_element_value(xml_obj, PCMK_XA_ID);
237  const char *node = crm_element_value(xml_obj, PCMK_XE_NODE);
238  const char *discovery = crm_element_value(xml_obj,
240 
241  if (rsc == NULL) {
242  pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
243  "does not exist", id, rsc_id);
244  return;
245  }
246 
247  if (score == NULL) {
248  score = crm_element_value(xml_obj, PCMK_XA_SCORE);
249  }
250 
251  if ((node != NULL) && (score != NULL)) {
252  int score_i = char2score(score);
253  pcmk_node_t *match = pcmk_find_node(rsc->cluster, node);
254  enum rsc_role_e role = pcmk_role_unknown;
255  pcmk__location_t *location = NULL;
256 
257  if (match == NULL) {
258  crm_info("Ignoring location constraint %s "
259  "because '%s' is not a known node",
260  pcmk__s(id, "without ID"), node);
261  return;
262  }
263 
264  if (role_spec == NULL) {
265  role_spec = crm_element_value(xml_obj, PCMK_XA_ROLE);
266  }
267  if (parse_location_role(role_spec, &role)) {
268  crm_trace("Setting location constraint %s role filter: %s",
269  id, role_spec);
270  } else {
271  /* @COMPAT The previous behavior of creating the constraint ignoring
272  * the role is retained for now, but we should ignore the entire
273  * constraint when we can break backward compatibility.
274  */
275  pcmk__config_err("Ignoring role in constraint %s: "
276  "Invalid value '%s'", id, role_spec);
277  }
278 
279  location = pcmk__new_location(id, rsc, score_i, discovery, match);
280  if (location == NULL) {
281  return; // Error already logged
282  }
283  location->role_filter = role;
284 
285  } else {
286  bool empty = true;
287  crm_time_t *next_change = crm_time_new_undefined();
288  pcmk_rule_input_t rule_input = {
289  .now = rsc->cluster->now,
290  .rsc_meta = rsc->meta,
291  .rsc_id = rsc_id_match,
292  .rsc_id_submatches = rsc_id_submatches,
293  .rsc_id_nmatches = rsc_id_nmatches,
294  };
295 
296  /* This loop is logically parallel to pcmk__evaluate_rules(), except
297  * instead of checking whether any rule is active, we set up location
298  * constraints for each active rule.
299  *
300  * @COMPAT When we can break backward compatibility, limit location
301  * constraints to a single rule, for consistency with other contexts.
302  * Since a rule may contain other rules, this does not prohibit any
303  * existing use cases.
304  */
305  for (xmlNode *rule_xml = pcmk__xe_first_child(xml_obj, PCMK_XE_RULE,
306  NULL, NULL);
307  rule_xml != NULL; rule_xml = pcmk__xe_next_same(rule_xml)) {
308 
309  if (generate_location_rule(rsc, rule_xml, discovery, next_change,
310  &rule_input)) {
311  if (empty) {
312  empty = false;
313  continue;
314  }
316  "Support for multiple " PCMK_XE_RULE
317  " elements in a location constraint is "
318  "deprecated and will be removed in a future "
319  "release (use a single new rule combining the "
320  "previous rules with " PCMK_XA_BOOLEAN_OP
321  " set to '" PCMK_VALUE_OR "' instead)");
322  }
323  }
324 
325  if (empty) {
326  pcmk__config_err("Ignoring constraint '%s' because it contains "
327  "no valid rules", id);
328  }
329 
330  /* If there is a point in the future when the evaluation of a rule will
331  * change, make sure the scheduler is re-run by that time.
332  */
333  if (crm_time_is_defined(next_change)) {
334  time_t t = (time_t) crm_time_get_seconds_since_epoch(next_change);
335 
337  "location rule evaluation");
338  }
339  crm_time_free(next_change);
340  }
341 }
342 
343 static void
344 unpack_simple_location(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
345 {
346  const char *id = crm_element_value(xml_obj, PCMK_XA_ID);
347  const char *value = crm_element_value(xml_obj, PCMK_XA_RSC);
348 
349  if (value) {
350  pcmk_resource_t *rsc;
351 
353  unpack_rsc_location(xml_obj, rsc, NULL, NULL, NULL, 0, NULL);
354  }
355 
356  value = crm_element_value(xml_obj, PCMK_XA_RSC_PATTERN);
357  if (value) {
358  regex_t regex;
359  bool invert = false;
360 
361  if (value[0] == '!') {
362  value++;
363  invert = true;
364  }
365 
366  if (regcomp(&regex, value, REG_EXTENDED) != 0) {
367  pcmk__config_err("Ignoring constraint '%s' because "
369  " has invalid value '%s'", id, value);
370  return;
371  }
372 
373  for (GList *iter = scheduler->resources; iter != NULL;
374  iter = iter->next) {
375 
376  pcmk_resource_t *r = iter->data;
377  int nregs = 0;
378  regmatch_t *pmatch = NULL;
379  int status;
380 
381  if (regex.re_nsub > 0) {
382  nregs = regex.re_nsub + 1;
383  } else {
384  nregs = 1;
385  }
386  pmatch = pcmk__assert_alloc(nregs, sizeof(regmatch_t));
387 
388  status = regexec(&regex, r->id, nregs, pmatch, 0);
389 
390  if (!invert && (status == 0)) {
391  crm_debug("'%s' matched '%s' for %s", r->id, value, id);
392  unpack_rsc_location(xml_obj, r, NULL, NULL, r->id, nregs,
393  pmatch);
394 
395  } else if (invert && (status != 0)) {
396  crm_debug("'%s' is an inverted match of '%s' for %s",
397  r->id, value, id);
398  unpack_rsc_location(xml_obj, r, NULL, NULL, NULL, 0, NULL);
399 
400  } else {
401  crm_trace("'%s' does not match '%s' for %s", r->id, value, id);
402  }
403 
404  free(pmatch);
405  }
406 
407  regfree(&regex);
408  }
409 }
410 
411 // \return Standard Pacemaker return code
412 static int
413 unpack_location_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
415 {
416  const char *id = NULL;
417  const char *rsc_id = NULL;
418  const char *state = NULL;
419  pcmk_resource_t *rsc = NULL;
420  pcmk_tag_t *tag = NULL;
421  xmlNode *rsc_set = NULL;
422 
423  *expanded_xml = NULL;
424 
425  CRM_CHECK(xml_obj != NULL, return EINVAL);
426 
427  id = pcmk__xe_id(xml_obj);
428  if (id == NULL) {
429  pcmk__config_err("Ignoring <%s> constraint without " PCMK_XA_ID,
430  xml_obj->name);
431  return pcmk_rc_unpack_error;
432  }
433 
434  // Check whether there are any resource sets with template or tag references
435  *expanded_xml = pcmk__expand_tags_in_sets(xml_obj, scheduler);
436  if (*expanded_xml != NULL) {
437  crm_log_xml_trace(*expanded_xml, "Expanded " PCMK_XE_RSC_LOCATION);
438  return pcmk_rc_ok;
439  }
440 
441  rsc_id = crm_element_value(xml_obj, PCMK_XA_RSC);
442  if (rsc_id == NULL) {
443  return pcmk_rc_ok;
444  }
445 
446  if (!pcmk__valid_resource_or_tag(scheduler, rsc_id, &rsc, &tag)) {
447  pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
448  "valid resource or tag", id, rsc_id);
449  return pcmk_rc_unpack_error;
450 
451  } else if (rsc != NULL) {
452  // No template is referenced
453  return pcmk_rc_ok;
454  }
455 
456  state = crm_element_value(xml_obj, PCMK_XA_ROLE);
457 
458  *expanded_xml = pcmk__xml_copy(NULL, xml_obj);
459 
460  /* Convert any template or tag reference into constraint
461  * PCMK_XE_RESOURCE_SET
462  */
463  if (!pcmk__tag_to_set(*expanded_xml, &rsc_set, PCMK_XA_RSC,
464  false, scheduler)) {
465  free_xml(*expanded_xml);
466  *expanded_xml = NULL;
467  return pcmk_rc_unpack_error;
468  }
469 
470  if (rsc_set != NULL) {
471  if (state != NULL) {
472  /* Move PCMK_XA_RSC_ROLE into converted PCMK_XE_RESOURCE_SET as
473  * PCMK_XA_ROLE attribute
474  */
475  crm_xml_add(rsc_set, PCMK_XA_ROLE, state);
476  pcmk__xe_remove_attr(*expanded_xml, PCMK_XA_ROLE);
477  }
478  crm_log_xml_trace(*expanded_xml, "Expanded " PCMK_XE_RSC_LOCATION);
479 
480  } else {
481  // No sets
482  free_xml(*expanded_xml);
483  *expanded_xml = NULL;
484  }
485 
486  return pcmk_rc_ok;
487 }
488 
489 // \return Standard Pacemaker return code
490 static int
491 unpack_location_set(xmlNode *location, xmlNode *set,
493 {
494  xmlNode *xml_rsc = NULL;
495  pcmk_resource_t *resource = NULL;
496  const char *set_id;
497  const char *role;
498  const char *local_score;
499 
500  CRM_CHECK(set != NULL, return EINVAL);
501 
502  set_id = pcmk__xe_id(set);
503  if (set_id == NULL) {
504  pcmk__config_err("Ignoring " PCMK_XE_RESOURCE_SET " without "
505  PCMK_XA_ID " in constraint '%s'",
506  pcmk__s(pcmk__xe_id(location), "(missing ID)"));
507  return pcmk_rc_unpack_error;
508  }
509 
510  role = crm_element_value(set, PCMK_XA_ROLE);
511  local_score = crm_element_value(set, PCMK_XA_SCORE);
512 
513  for (xml_rsc = pcmk__xe_first_child(set, PCMK_XE_RESOURCE_REF, NULL, NULL);
514  xml_rsc != NULL; xml_rsc = pcmk__xe_next_same(xml_rsc)) {
515 
517  pcmk__xe_id(xml_rsc));
518  if (resource == NULL) {
519  pcmk__config_err("%s: No resource found for %s",
520  set_id, pcmk__xe_id(xml_rsc));
521  return pcmk_rc_unpack_error;
522  }
523 
524  unpack_rsc_location(location, resource, role, local_score, NULL, 0,
525  NULL);
526  }
527 
528  return pcmk_rc_ok;
529 }
530 
531 void
533 {
534  xmlNode *set = NULL;
535  bool any_sets = false;
536 
537  xmlNode *orig_xml = NULL;
538  xmlNode *expanded_xml = NULL;
539 
540  if (unpack_location_tags(xml_obj, &expanded_xml, scheduler) != pcmk_rc_ok) {
541  return;
542  }
543 
544  if (expanded_xml) {
545  orig_xml = xml_obj;
546  xml_obj = expanded_xml;
547  }
548 
549  for (set = pcmk__xe_first_child(xml_obj, PCMK_XE_RESOURCE_SET, NULL, NULL);
550  set != NULL; set = pcmk__xe_next_same(set)) {
551 
552  any_sets = true;
553  set = expand_idref(set, scheduler->input);
554  if ((set == NULL) // Configuration error, message already logged
555  || (unpack_location_set(xml_obj, set, scheduler) != pcmk_rc_ok)) {
556 
557  if (expanded_xml) {
558  free_xml(expanded_xml);
559  }
560  return;
561  }
562  }
563 
564  if (expanded_xml) {
565  free_xml(expanded_xml);
566  xml_obj = orig_xml;
567  }
568 
569  if (!any_sets) {
570  unpack_simple_location(xml_obj, scheduler);
571  }
572 }
573 
589 pcmk__new_location(const char *id, pcmk_resource_t *rsc,
590  int node_score, const char *discover_mode, pcmk_node_t *node)
591 {
592  pcmk__location_t *new_con = NULL;
593 
594  CRM_CHECK((node != NULL) || (node_score == 0), return NULL);
595 
596  if (id == NULL) {
597  pcmk__config_err("Invalid constraint: no ID specified");
598  return NULL;
599  }
600 
601  if (rsc == NULL) {
602  pcmk__config_err("Invalid constraint %s: no resource specified", id);
603  return NULL;
604  }
605 
606  new_con = pcmk__assert_alloc(1, sizeof(pcmk__location_t));
607  new_con->id = pcmk__str_copy(id);
608  new_con->rsc = rsc;
609  new_con->nodes = NULL;
610  new_con->role_filter = pcmk_role_unknown;
611 
612  if (pcmk__str_eq(discover_mode, PCMK_VALUE_ALWAYS,
614  new_con->discover_mode = pcmk_probe_always;
615 
616  } else if (pcmk__str_eq(discover_mode, PCMK_VALUE_NEVER,
617  pcmk__str_casei)) {
618  new_con->discover_mode = pcmk_probe_never;
619 
620  } else if (pcmk__str_eq(discover_mode, PCMK_VALUE_EXCLUSIVE,
621  pcmk__str_casei)) {
623  rsc->exclusive_discover = TRUE;
624 
625  } else {
626  pcmk__config_err("Invalid " PCMK_XA_RESOURCE_DISCOVERY " value %s "
627  "in location constraint", discover_mode);
628  }
629 
630  if (node != NULL) {
631  pcmk_node_t *copy = pe__copy_node(node);
632 
633  copy->weight = node_score;
634  new_con->nodes = g_list_prepend(NULL, copy);
635  }
636 
637  rsc->cluster->placement_constraints = g_list_prepend(
638  rsc->cluster->placement_constraints, new_con);
639  rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
640 
641  return new_con;
642 }
643 
650 void
652 {
653  for (GList *iter = scheduler->placement_constraints;
654  iter != NULL; iter = iter->next) {
655  pcmk__location_t *location = iter->data;
656 
657  location->rsc->cmds->apply_location(location->rsc, location);
658  }
659 }
660 
671 void
673 {
674  bool need_role = false;
675 
676  CRM_ASSERT((rsc != NULL) && (location != NULL));
677 
678  // If a role was specified, ensure constraint is applicable
679  need_role = (location->role_filter > pcmk_role_unknown);
680  if (need_role && (location->role_filter != rsc->next_role)) {
681  pcmk__rsc_trace(rsc,
682  "Not applying %s to %s because role will be %s not %s",
683  location->id, rsc->id, pcmk_role_text(rsc->next_role),
684  pcmk_role_text(location->role_filter));
685  return;
686  }
687 
688  if (location->nodes == NULL) {
689  pcmk__rsc_trace(rsc, "Not applying %s to %s because no nodes match",
690  location->id, rsc->id);
691  return;
692  }
693 
694  for (GList *iter = location->nodes; iter != NULL; iter = iter->next) {
695  pcmk_node_t *node = iter->data;
696  pcmk_node_t *allowed_node = g_hash_table_lookup(rsc->allowed_nodes,
697  node->details->id);
698 
699  pcmk__rsc_trace(rsc, "Applying %s%s%s to %s score on %s: %c %s",
700  location->id,
701  (need_role? " for role " : ""),
702  (need_role? pcmk_role_text(location->role_filter) : ""),
703  rsc->id, pcmk__node_name(node),
704  ((allowed_node == NULL)? '=' : '+'),
705  pcmk_readable_score(node->weight));
706 
707  if (allowed_node == NULL) {
708  allowed_node = pe__copy_node(node);
709  g_hash_table_insert(rsc->allowed_nodes,
710  (gpointer) allowed_node->details->id,
711  allowed_node);
712  } else {
713  allowed_node->weight = pcmk__add_scores(allowed_node->weight,
714  node->weight);
715  }
716 
717  if (allowed_node->rsc_discover_mode < location->discover_mode) {
718  if (location->discover_mode == pcmk_probe_exclusive) {
719  rsc->exclusive_discover = TRUE;
720  }
721  /* exclusive > never > always... always is default */
722  allowed_node->rsc_discover_mode = location->discover_mode;
723  }
724  }
725 }
pcmk_assignment_methods_t * cmds
Definition: resources.h:413
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition: iso8601.c:129
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
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:103
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition: xml.c:883
A dumping ground.
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
Definition: utils.c:89
pcmk_scheduler_t * cluster
Definition: resources.h:408
GHashTable * attrs
Definition: nodes.h:142
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition: roles.c:23
const crm_time_t * now
Current time for rule evaluation purposes.
Definition: rules.h:59
enum pcmk__combine pcmk__parse_combine(const char *combine)
Definition: rules.c:902
Data used to evaluate a rule (any NULL items are ignored)
Definition: rules.h:57
GHashTable * rsc_params
Definition: rules.h:86
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
Definition: iso8601.c:142
void pcmk__unpack_location(xmlNode *xml_obj, pcmk_scheduler_t *scheduler)
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition: scores.c:86
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)
struct crm_time_s crm_time_t
Definition: iso8601.h:32
pcmk__location_t * pcmk__new_location(const char *id, pcmk_resource_t *rsc, int node_score, const char *discover_mode, pcmk_node_t *node)
#define pcmk__config_warn(fmt...)
#define pcmk__rsc_trace(rsc, fmt, args...)
#define PCMK_META_CONTAINER_ATTRIBUTE_TARGET
Definition: options.h:85
#define PCMK_VALUE_OR
Definition: options.h:187
#define PCMK_XA_RESOURCE_DISCOVERY
Definition: xml_names.h:379
#define PCMK_XE_RESOURCE_REF
Definition: xml_names.h:173
enum rsc_role_e next_role
Definition: resources.h:465
gboolean exclusive_discover
Definition: resources.h:432
#define pcmk__config_err(fmt...)
GHashTable * meta
Definition: resources.h:467
#define PCMK_VALUE_AND
Definition: options.h:133
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:301
#define PCMK_XA_RSC
Definition: xml_names.h:383
int rsc_id_nmatches
Number of entries in rsc_id_submatches.
Definition: rules.h:102
#define PCMK_XA_SCORE_ATTRIBUTE
Definition: xml_names.h:392
void pcmk__apply_locations(pcmk_scheduler_t *scheduler)
#define PCMK_VALUE_NEVER
Definition: options.h:177
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition: roles.c:59
GList * resources
Definition: scheduler.h:231
pcmk__combine
gboolean local
Definition: cpg.c:50
int weight
Definition: nodes.h:162
char * pcmk__replace_submatches(const char *string, const char *match, const regmatch_t submatches[], int nmatches)
Definition: rules.c:685
#define PCMK_VALUE_ALWAYS
Definition: options.h:132
#define crm_debug(fmt, args...)
Definition: logging.h:402
#define PCMK_XE_RSC_LOCATION
Definition: xml_names.h:184
G_GNUC_INTERNAL pcmk_resource_t * pcmk__find_constraint_resource(GList *rsc_list, const char *id)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:440
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:1385
int char2score(const char *score)
Get the integer value of a score string.
Definition: scores.c:36
#define crm_trace(fmt, args...)
Definition: logging.h:404
struct pe_node_shared_s * details
Definition: nodes.h:167
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
Definition: xml.c:2152
Unpromoted.
Definition: roles.h:38
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
Definition: xml.c:652
rsc_role_e
Definition: roles.h:34
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
#define PCMK_XA_ID
Definition: xml_names.h:296
pcmk_resource_t * rsc
#define PCMK_XA_SCORE
Definition: xml_names.h:391
G_GNUC_INTERNAL bool pcmk__valid_resource_or_tag(const pcmk_scheduler_t *scheduler, const char *id, pcmk_resource_t **rsc, pcmk_tag_t **tag)
void free_xml(xmlNode *child)
Definition: xml.c:867
void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:116
xmlNode * input
Definition: scheduler.h:196
#define pcmk__str_copy(str)
#define pcmk__warn_once(wo_flag, fmt...)
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition: iso8601.c:359
#define PCMK_XE_RULE
Definition: xml_names.h:187
void pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
Definition: utils.c:694
int rsc_discover_mode
Definition: nodes.h:170
const char * id
Definition: nodes.h:72
const char * target
Definition: pcmk_fence.c:29
#define PCMK_XE_NODE
Definition: xml_names.h:133
Cluster status and scheduling.
pcmk__action_result_t result
Definition: pcmk_fence.c:35
#define PCMK_VALUE_EXCLUSIVE
Definition: options.h:150
pcmk_scheduler_t * scheduler
#define CRM_ASSERT(expr)
Definition: results.h:42
const regmatch_t * rsc_id_submatches
Resource pattern submatches (as set by regexec()) for rsc_id.
Definition: rules.h:99
#define PCMK_XE_RESOURCE_SET
Definition: xml_names.h:174
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:118
Started.
Definition: roles.h:37
Definition: tags.h:29
GList * rsc_location
Definition: resources.h:443
enum rsc_role_e role_filter
#define PCMK_XA_RSC_PATTERN
Definition: xml_names.h:384
GHashTable * node_attrs
Operation interval that rule applies to.
Definition: rules.h:77
#define PCMK_XA_BOOLEAN_OP
Definition: xml_names.h:235
GList * placement_constraints
Definition: scheduler.h:232
#define crm_log_xml_trace(xml, text)
Definition: logging.h:412
Resource role is unknown.
Definition: roles.h:35
enum pe_discover_e discover_mode
Location constraint object.
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:484
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:297
const char * rsc_id
Resource ID to compare against a location constraint&#39;s resource pattern.
Definition: rules.h:96
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2108
G_GNUC_INTERNAL xmlNode * pcmk__expand_tags_in_sets(xmlNode *xml_obj, const pcmk_scheduler_t *scheduler)
#define PCMK_XA_ROLE
Definition: xml_names.h:382
crm_time_t * now
Definition: scheduler.h:198
#define crm_info(fmt, args...)
Definition: logging.h:399
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:24
GHashTable * allowed_nodes
Definition: resources.h:462
Where resource is running.
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:150