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-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 
  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: %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 
  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                   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 
 199 static void
 200 unpack_rsc_location(xmlNode *xml_obj, pe_resource_t *rsc, 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 *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 
 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;
 297 
 298         rsc = pcmk__find_constraint_resource(data_set->resources, value);
 299         unpack_rsc_location(xml_obj, rsc, 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) != 0) {
 314             pcmk__config_err("Ignoring constraint '%s' because "
 315                              XML_LOC_ATTR_SOURCE_PATTERN
 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
 365 static int
 366 unpack_location_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
     /* [previous][next][first][last][top][bottom][index][help] */
 367                      pe_working_set_t *data_set)
 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));
 384         return pcmk_rc_unpack_error;
 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);
 402         return pcmk_rc_unpack_error;
 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;
 418         return pcmk_rc_unpack_error;
 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
 439 static int
 440 unpack_location_set(xmlNode *location, xmlNode *set, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)"));
 455         return pcmk_rc_unpack_error;
 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 
 464         resource = pcmk__find_constraint_resource(data_set->resources,
 465                                                   ID(xml_rsc));
 466         if (resource == NULL) {
 467             pcmk__config_err("%s: No resource found for %s",
 468                              set_id, ID(xml_rsc));
 469             return pcmk_rc_unpack_error;
 470         }
 471 
 472         unpack_rsc_location(location, resource, role, local_score, data_set,
 473                             NULL);
 474     }
 475 
 476     return pcmk_rc_ok;
 477 }
 478 
 479 void
 480 pcmk__unpack_location(xmlNode *xml_obj, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 522 /*!
 523  * \internal
 524  * \brief Add a new location constraint to a cluster working set
 525  *
 526  * \param[in]     id             XML ID of location constraint
 527  * \param[in,out] rsc            Resource in location constraint
 528  * \param[in]     node_weight    Constraint score
 529  * \param[in]     discover_mode  Resource discovery option for constraint
 530  * \param[in]     node           Node in constraint (or NULL if rule-based)
 531  * \param[in,out] data_set       Cluster working set to add constraint to
 532  *
 533  * \return Newly allocated location constraint
 534  * \note The result will be added to \p data_set and should not be freed
 535  *       separately.
 536  */
 537 pe__location_t *
 538 pcmk__new_location(const char *id, pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 539                    int node_weight, const char *discover_mode,
 540                    pe_node_t *node, pe_working_set_t *data_set)
 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",
 564                          pcmk__str_null_matches|pcmk__str_casei)) {
 565             new_con->discover_mode = pe_discover_always;
 566 
 567         } else if (pcmk__str_eq(discover_mode, "never", pcmk__str_casei)) {
 568             new_con->discover_mode = pe_discover_never;
 569 
 570         } else if (pcmk__str_eq(discover_mode, "exclusive", pcmk__str_casei)) {
 571             new_con->discover_mode = pe_discover_exclusive;
 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 
 586         data_set->placement_constraints = g_list_prepend(data_set->placement_constraints,
 587                                                          new_con);
 588         rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
 589     }
 590 
 591     return new_con;
 592 }
 593 
 594 /*!
 595  * \internal
 596  * \brief Apply all location constraints
 597  *
 598  * \param[in,out] data_set       Cluster working set
 599  */
 600 void
 601 pcmk__apply_locations(pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 
 611 /*!
 612  * \internal
 613  * \brief Apply a location constraint to a resource's allowed node scores
 614  *
 615  * \param[in,out] rsc         Resource to apply constraint to
 616  * \param[in,out] location    Location constraint to apply
 617  *
 618  * \note This does not consider the resource's children, so the resource's
 619  *       apply_location() method should be used instead in most cases.
 620  */
 621 void
 622 pcmk__apply_location(pe_resource_t *rsc, pe__location_t *location)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

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