root/lib/pacemaker/pcmk_sched_location.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_node_score
  2. generate_location_rule
  3. unpack_rsc_location
  4. unpack_simple_location
  5. unpack_location_tags
  6. unpack_location_set
  7. pcmk__unpack_location
  8. pcmk__new_location
  9. pcmk__apply_locations
  10. pcmk__apply_location

   1 /*
   2  * Copyright 2004-2021 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 
  19 #include "libpacemaker_private.h"
  20 
  21 static int
  22 get_node_score(const char *rule, const char *score, bool raw,
     /* [previous][next][first][last][top][bottom][index][help] */
  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: node %s did not have a value for %s",
  38                       rule, node->details->uname, score);
  39             score_f = -INFINITY;
  40 
  41         } else {
  42             crm_debug("Rule %s: node %s had value %s for %s",
  43                       rule, node->details->uname, attr_score, score);
  44             score_f = char2score(attr_score);
  45         }
  46     }
  47     return score_f;
  48 }
  49 
  50 static pe__location_t *
  51 generate_location_rule(pe_resource_t *rsc, xmlNode *rule_xml,
     /* [previous][next][first][last][top][bottom][index][help] */
  52                        const char *discovery, crm_time_t *next_change,
  53                        pe_working_set_t *data_set,
  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);
  77     boolean = crm_element_value(rule_xml, XML_RULE_ATTR_BOOLEAN_OP);
  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) {
  89         score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE_ATTRIBUTE);
  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                   node->details->uname);
 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 = pe__add_scores(local->weight, score_f);
 168             }
 169             crm_trace("node %s now has weight %d",
 170                       node->details->uname, local->weight);
 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("node %s did not match", node->details->uname);
 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 
 199 static void
 200 unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc_lh, const char *role,
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *id_lh = 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_lh == NULL) {
 211         pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
 212                           "does not exist", id, id_lh);
 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_lh, 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_lh, 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 
 257             pe__update_recheck_time(t, data_set);
 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:
 277                 case RSC_ROLE_UNPROMOTED:
 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 
 289 static void
 290 unpack_simple_location(xmlNode *xml_obj, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 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_lh;
 297 
 298         rsc_lh = pcmk__find_constraint_resource(data_set->resources, value);
 299         unpack_rsc_location(xml_obj, rsc_lh, NULL, NULL, data_set, NULL);
 300     }
 301 
 302     value = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE_PATTERN);
 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)) {
 314             pcmk__config_err("Ignoring constraint '%s' because "
 315                              XML_LOC_ATTR_SOURCE_PATTERN
 316                              " has invalid value '%s'", id, value);
 317             regfree(r_patt);
 318             free(r_patt);
 319             return;
 320         }
 321 
 322         for (rIter = data_set->resources; rIter; rIter = rIter->next) {
 323             pe_resource_t *r = rIter->data;
 324             int nregs = 0;
 325             regmatch_t *pmatch = NULL;
 326             int status;
 327 
 328             if(r_patt->re_nsub > 0) {
 329                 nregs = r_patt->re_nsub + 1;
 330             } else {
 331                 nregs = 1;
 332             }
 333             pmatch = calloc(nregs, sizeof(regmatch_t));
 334 
 335             status = regexec(r_patt, r->id, nregs, pmatch, 0);
 336 
 337             if (!invert && (status == 0)) {
 338                 pe_re_match_data_t re_match_data = {
 339                                                 .string = r->id,
 340                                                 .nregs = nregs,
 341                                                 .pmatch = pmatch
 342                                                };
 343 
 344                 crm_debug("'%s' matched '%s' for %s", r->id, value, id);
 345                 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set,
 346                                     &re_match_data);
 347 
 348             } else if (invert && (status != 0)) {
 349                 crm_debug("'%s' is an inverted match of '%s' for %s",
 350                           r->id, value, id);
 351                 unpack_rsc_location(xml_obj, r, NULL, NULL, data_set, NULL);
 352 
 353             } else {
 354                 crm_trace("'%s' does not match '%s' for %s", r->id, value, id);
 355             }
 356 
 357             free(pmatch);
 358         }
 359 
 360         regfree(r_patt);
 361         free(r_patt);
 362     }
 363 }
 364 
 365 // \return Standard Pacemaker return code
 366 static int
 367 unpack_location_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
     /* [previous][next][first][last][top][bottom][index][help] */
 368                      pe_working_set_t *data_set)
 369 {
 370     const char *id = NULL;
 371     const char *id_lh = NULL;
 372     const char *state_lh = NULL;
 373     pe_resource_t *rsc_lh = NULL;
 374     pe_tag_t *tag_lh = NULL;
 375     xmlNode *rsc_set_lh = NULL;
 376 
 377     *expanded_xml = NULL;
 378 
 379     CRM_CHECK(xml_obj != NULL, return pcmk_rc_schema_validation);
 380 
 381     id = ID(xml_obj);
 382     if (id == NULL) {
 383         pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
 384                          crm_element_name(xml_obj));
 385         return pcmk_rc_schema_validation;
 386     }
 387 
 388     // Check whether there are any resource sets with template or tag references
 389     *expanded_xml = pcmk__expand_tags_in_sets(xml_obj, data_set);
 390     if (*expanded_xml != NULL) {
 391         crm_log_xml_trace(*expanded_xml, "Expanded rsc_location");
 392         return pcmk_rc_ok;
 393     }
 394 
 395     id_lh = crm_element_value(xml_obj, XML_LOC_ATTR_SOURCE);
 396     if (id_lh == NULL) {
 397         return pcmk_rc_ok;
 398     }
 399 
 400     if (!pcmk__valid_resource_or_tag(data_set, id_lh, &rsc_lh, &tag_lh)) {
 401         pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
 402                          "valid resource or tag", id, id_lh);
 403         return pcmk_rc_schema_validation;
 404 
 405     } else if (rsc_lh != NULL) {
 406         // No template is referenced
 407         return pcmk_rc_ok;
 408     }
 409 
 410     state_lh = crm_element_value(xml_obj, XML_RULE_ATTR_ROLE);
 411 
 412     *expanded_xml = copy_xml(xml_obj);
 413 
 414     // Convert template/tag reference in "rsc" into resource_set under constraint
 415     if (!pcmk__tag_to_set(*expanded_xml, &rsc_set_lh, XML_LOC_ATTR_SOURCE,
 416                           false, data_set)) {
 417         free_xml(*expanded_xml);
 418         *expanded_xml = NULL;
 419         return pcmk_rc_schema_validation;
 420     }
 421 
 422     if (rsc_set_lh != NULL) {
 423         if (state_lh != NULL) {
 424             // Move "rsc-role" into converted resource_set as "role" attribute
 425             crm_xml_add(rsc_set_lh, "role", state_lh);
 426             xml_remove_prop(*expanded_xml, XML_RULE_ATTR_ROLE);
 427         }
 428         crm_log_xml_trace(*expanded_xml, "Expanded rsc_location");
 429 
 430     } else {
 431         // No sets
 432         free_xml(*expanded_xml);
 433         *expanded_xml = NULL;
 434     }
 435 
 436     return pcmk_rc_ok;
 437 }
 438 
 439 // \return Standard Pacemaker return code
 440 static int
 441 unpack_location_set(xmlNode *location, xmlNode *set, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 442 {
 443     xmlNode *xml_rsc = NULL;
 444     pe_resource_t *resource = NULL;
 445     const char *set_id;
 446     const char *role;
 447     const char *local_score;
 448 
 449     CRM_CHECK(set != NULL, return pcmk_rc_schema_validation);
 450 
 451     set_id = ID(set);
 452     if (set_id == NULL) {
 453         pcmk__config_err("Ignoring " XML_CONS_TAG_RSC_SET " without "
 454                          XML_ATTR_ID " in constraint '%s'",
 455                          crm_str(ID(location)));
 456         return pcmk_rc_schema_validation;
 457     }
 458 
 459     role = crm_element_value(set, "role");
 460     local_score = crm_element_value(set, XML_RULE_ATTR_SCORE);
 461 
 462     for (xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
 463          xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
 464 
 465         resource = pcmk__find_constraint_resource(data_set->resources,
 466                                                   ID(xml_rsc));
 467         if (resource == NULL) {
 468             pcmk__config_err("%s: No resource found for %s",
 469                              set_id, ID(xml_rsc));
 470             return pcmk_rc_schema_validation;
 471         }
 472 
 473         unpack_rsc_location(location, resource, role, local_score, data_set,
 474                             NULL);
 475     }
 476 
 477     return pcmk_rc_ok;
 478 }
 479 
 480 void
 481 pcmk__unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 482 {
 483     xmlNode *set = NULL;
 484     bool any_sets = false;
 485 
 486     xmlNode *orig_xml = NULL;
 487     xmlNode *expanded_xml = NULL;
 488 
 489     if (unpack_location_tags(xml_obj, &expanded_xml, data_set) != pcmk_rc_ok) {
 490         return;
 491     }
 492 
 493     if (expanded_xml) {
 494         orig_xml = xml_obj;
 495         xml_obj = expanded_xml;
 496     }
 497 
 498     for (set = first_named_child(xml_obj, XML_CONS_TAG_RSC_SET); set != NULL;
 499          set = crm_next_same_xml(set)) {
 500 
 501         any_sets = true;
 502         set = expand_idref(set, data_set->input);
 503         if ((set == NULL) // Configuration error, message already logged
 504             || (unpack_location_set(xml_obj, set, data_set) != pcmk_rc_ok)) {
 505 
 506             if (expanded_xml) {
 507                 free_xml(expanded_xml);
 508             }
 509             return;
 510         }
 511     }
 512 
 513     if (expanded_xml) {
 514         free_xml(expanded_xml);
 515         xml_obj = orig_xml;
 516     }
 517 
 518     if (!any_sets) {
 519         unpack_simple_location(xml_obj, data_set);
 520     }
 521 }
 522 
 523 /*!
 524  * \internal
 525  * \brief Add a new location constraint to a cluster working set
 526  *
 527  * \param[in] id             XML ID of location constraint
 528  * \param[in] rsc            Resource in location constraint
 529  * \param[in] node_weight    Constraint score
 530  * \param[in] discover_mode  Resource discovery option for constraint
 531  * \param[in] node           Node in location constraint (or NULL if rule-based)
 532  * \param[in] data_set       Cluster working set to add constraint to
 533  *
 534  * \return Newly allocated location constraint
 535  * \note The result will be added to \p data_set and should not be freed
 536  *       separately.
 537  */
 538 pe__location_t *
 539 pcmk__new_location(const char *id, pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 540                    int node_weight, const char *discover_mode,
 541                    pe_node_t *node, pe_working_set_t *data_set)
 542 {
 543     pe__location_t *new_con = NULL;
 544 
 545     if ((rsc == NULL) || (id == NULL)) {
 546         pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
 547         return NULL;
 548 
 549     } else if (node == NULL) {
 550         CRM_CHECK(node_weight == 0, return NULL);
 551     }
 552 
 553     new_con = calloc(1, sizeof(pe__location_t));
 554     if (new_con != NULL) {
 555         new_con->id = strdup(id);
 556         new_con->rsc_lh = rsc;
 557         new_con->node_list_rh = NULL;
 558         new_con->role_filter = RSC_ROLE_UNKNOWN;
 559 
 560         if (pcmk__str_eq(discover_mode, "always",
 561                          pcmk__str_null_matches|pcmk__str_casei)) {
 562             new_con->discover_mode = pe_discover_always;
 563 
 564         } else if (pcmk__str_eq(discover_mode, "never", pcmk__str_casei)) {
 565             new_con->discover_mode = pe_discover_never;
 566 
 567         } else if (pcmk__str_eq(discover_mode, "exclusive", pcmk__str_casei)) {
 568             new_con->discover_mode = pe_discover_exclusive;
 569             rsc->exclusive_discover = TRUE;
 570 
 571         } else {
 572             pe_err("Invalid " XML_LOCATION_ATTR_DISCOVERY " value %s "
 573                    "in location constraint", discover_mode);
 574         }
 575 
 576         if (node != NULL) {
 577             pe_node_t *copy = pe__copy_node(node);
 578 
 579             copy->weight = node_weight;
 580             new_con->node_list_rh = g_list_prepend(NULL, copy);
 581         }
 582 
 583         data_set->placement_constraints = g_list_prepend(data_set->placement_constraints,
 584                                                          new_con);
 585         rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
 586     }
 587 
 588     return new_con;
 589 }
 590 
 591 /*!
 592  * \internal
 593  * \brief Apply all location constraints
 594  *
 595  * \param[in] data_set       Cluster working set
 596  */
 597 void
 598 pcmk__apply_locations(pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 599 {
 600     for (GList *iter = data_set->placement_constraints;
 601          iter != NULL; iter = iter->next) {
 602         pe__location_t *location = iter->data;
 603 
 604         location->rsc_lh->cmds->rsc_location(location->rsc_lh, location);
 605     }
 606 }
 607 
 608 /*!
 609  * \internal
 610  * \brief Apply a location constraint to a resource's allowed node weights
 611  *
 612  * \param[in] constraint  Location constraint to apply
 613  * \param[in] rsc         Resource to apply constraint to
 614  */
 615 void
 616 pcmk__apply_location(pe__location_t *constraint, pe_resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 617 {
 618     bool need_role = false;
 619 
 620     CRM_CHECK((constraint != NULL) && (rsc != NULL), return);
 621 
 622     // If a role was specified, ensure constraint is applicable
 623     need_role = (constraint->role_filter > RSC_ROLE_UNKNOWN);
 624     if (need_role && (constraint->role_filter != rsc->next_role)) {
 625         pe_rsc_trace(rsc,
 626                      "Not applying %s to %s because role will be %s not %s",
 627                      constraint->id, rsc->id, role2text(rsc->next_role),
 628                      role2text(constraint->role_filter));
 629         return;
 630     }
 631 
 632     if (constraint->node_list_rh == NULL) {
 633         pe_rsc_trace(rsc, "Not applying %s to %s because no nodes match",
 634                      constraint->id, rsc->id);
 635         return;
 636     }
 637 
 638     pe_rsc_trace(rsc, "Applying %s%s%s to %s", constraint->id,
 639                  (need_role? " for role " : ""),
 640                  (need_role? role2text(constraint->role_filter) : ""), rsc->id);
 641 
 642     for (GList *gIter = constraint->node_list_rh; gIter != NULL;
 643          gIter = gIter->next) {
 644 
 645         pe_node_t *node = (pe_node_t *) gIter->data;
 646         pe_node_t *weighted_node = NULL;
 647 
 648         weighted_node = (pe_node_t *) pe_hash_table_lookup(rsc->allowed_nodes,
 649                                                            node->details->id);
 650         if (weighted_node == NULL) {
 651             pe_rsc_trace(rsc, "* = %d on %s",
 652                          node->weight, node->details->uname);
 653             weighted_node = pe__copy_node(node);
 654             g_hash_table_insert(rsc->allowed_nodes,
 655                                 (gpointer) weighted_node->details->id,
 656                                 weighted_node);
 657         } else {
 658             pe_rsc_trace(rsc, "* + %d on %s",
 659                          node->weight, node->details->uname);
 660             weighted_node->weight = pe__add_scores(weighted_node->weight,
 661                                                    node->weight);
 662         }
 663 
 664         if (weighted_node->rsc_discover_mode < constraint->discover_mode) {
 665             if (constraint->discover_mode == pe_discover_exclusive) {
 666                 rsc->exclusive_discover = TRUE;
 667             }
 668             /* exclusive > never > always... always is default */
 669             weighted_node->rsc_discover_mode = constraint->discover_mode;
 670         }
 671     }
 672 }

/* [previous][next][first][last][top][bottom][index][help] */