root/lib/pengine/complex.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_resource_type
  2. get_resource_typename
  3. dup_attr
  4. get_meta_attributes
  5. get_rsc_attributes
  6. pe_get_versioned_attributes
  7. template_op_key
  8. unpack_template
  9. add_template_rsc
  10. handle_rsc_isolation
  11. check_deprecated_stonith
  12. common_unpack
  13. common_update_score
  14. is_parent
  15. uber_parent
  16. common_free

   1 /*
   2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This library is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2.1 of the License, or (at your option) any later version.
   8  *
   9  * This library is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 
  19 #include <crm_internal.h>
  20 
  21 #include <crm/pengine/rules.h>
  22 #include <crm/pengine/internal.h>
  23 #include <crm/msg_xml.h>
  24 
  25 #include <unpack.h>
  26 
  27 void populate_hash(xmlNode * nvpair_list, GHashTable * hash, const char **attrs, int attrs_length);
  28 
  29 resource_object_functions_t resource_class_functions[] = {
  30     {
  31      native_unpack,
  32      native_find_rsc,
  33      native_parameter,
  34      native_print,
  35      native_active,
  36      native_resource_state,
  37      native_location,
  38      native_free
  39     },
  40     {
  41      group_unpack,
  42      native_find_rsc,
  43      native_parameter,
  44      group_print,
  45      group_active,
  46      group_resource_state,
  47      native_location,
  48      group_free
  49     },
  50     {
  51      clone_unpack,
  52      native_find_rsc,
  53      native_parameter,
  54      clone_print,
  55      clone_active,
  56      clone_resource_state,
  57      native_location,
  58      clone_free
  59     },
  60     {
  61      master_unpack,
  62      native_find_rsc,
  63      native_parameter,
  64      clone_print,
  65      clone_active,
  66      clone_resource_state,
  67      native_location,
  68      clone_free
  69     },
  70     {
  71      container_unpack,
  72      native_find_rsc,
  73      native_parameter,
  74      container_print,
  75      container_active,
  76      container_resource_state,
  77      native_location,
  78      container_free
  79     }
  80 };
  81 
  82 enum pe_obj_types
  83 get_resource_type(const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85     if (safe_str_eq(name, XML_CIB_TAG_RESOURCE)) {
  86         return pe_native;
  87 
  88     } else if (safe_str_eq(name, XML_CIB_TAG_GROUP)) {
  89         return pe_group;
  90 
  91     } else if (safe_str_eq(name, XML_CIB_TAG_INCARNATION)) {
  92         return pe_clone;
  93 
  94     } else if (safe_str_eq(name, XML_CIB_TAG_MASTER)) {
  95         return pe_master;
  96 
  97     } else if (safe_str_eq(name, XML_CIB_TAG_CONTAINER)) {
  98         return pe_container;
  99     }
 100 
 101     return pe_unknown;
 102 }
 103 
 104 const char *
 105 get_resource_typename(enum pe_obj_types type)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107     switch (type) {
 108         case pe_native:
 109             return XML_CIB_TAG_RESOURCE;
 110         case pe_group:
 111             return XML_CIB_TAG_GROUP;
 112         case pe_clone:
 113             return XML_CIB_TAG_INCARNATION;
 114         case pe_master:
 115             return XML_CIB_TAG_MASTER;
 116         case pe_container:
 117             return XML_CIB_TAG_CONTAINER;
 118         case pe_unknown:
 119             return "unknown";
 120     }
 121     return "<unknown>";
 122 }
 123 
 124 static void
 125 dup_attr(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127     add_hash_param(user_data, key, value);
 128 }
 129 
 130 void
 131 get_meta_attributes(GHashTable * meta_hash, resource_t * rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 132                     node_t * node, pe_working_set_t * data_set)
 133 {
 134     GHashTable *node_hash = NULL;
 135     const char *version = crm_element_value(data_set->input, XML_ATTR_CRM_VERSION);
 136 
 137     if (node) {
 138         node_hash = node->details->attrs;
 139     }
 140 
 141     if (rsc->xml) {
 142         xmlAttrPtr xIter = NULL;
 143 
 144         for (xIter = rsc->xml->properties; xIter; xIter = xIter->next) {
 145             const char *prop_name = (const char *)xIter->name;
 146             const char *prop_value = crm_element_value(rsc->xml, prop_name);
 147 
 148             add_hash_param(meta_hash, prop_name, prop_value);
 149         }
 150     }
 151 
 152     unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_META_SETS, node_hash,
 153                                meta_hash, NULL, FALSE, data_set->now);
 154 
 155     if(version == NULL || compare_version(version, "3.0.9") < 0) {
 156         /* populate from the regular attributes until the GUI can create
 157          * meta attributes
 158          */
 159         unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
 160                                    meta_hash, NULL, FALSE, data_set->now);
 161     }
 162 
 163     /* set anything else based on the parent */
 164     if (rsc->parent != NULL) {
 165         g_hash_table_foreach(rsc->parent->meta, dup_attr, meta_hash);
 166     }
 167 
 168     /* and finally check the defaults */
 169     unpack_instance_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_META_SETS,
 170                                node_hash, meta_hash, NULL, FALSE, data_set->now);
 171 }
 172 
 173 void
 174 get_rsc_attributes(GHashTable * meta_hash, resource_t * rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 175                    node_t * node, pe_working_set_t * data_set)
 176 {
 177     GHashTable *node_hash = NULL;
 178 
 179     if (node) {
 180         node_hash = node->details->attrs;
 181     }
 182 
 183     unpack_instance_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
 184                                meta_hash, NULL, FALSE, data_set->now);
 185 
 186     /* set anything else based on the parent */
 187     if (rsc->parent != NULL) {
 188         get_rsc_attributes(meta_hash, rsc->parent, node, data_set);
 189 
 190     } else {
 191         /* and finally check the defaults */
 192         unpack_instance_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_ATTR_SETS,
 193                                    node_hash, meta_hash, NULL, FALSE, data_set->now);
 194     }
 195 }
 196 
 197 #if ENABLE_VERSIONED_ATTRS
 198 void
 199 pe_get_versioned_attributes(xmlNode * meta_hash, resource_t * rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 200                             node_t * node, pe_working_set_t * data_set)
 201 {
 202     GHashTable *node_hash = NULL;
 203 
 204     if (node) {
 205         node_hash = node->details->attrs;
 206     }
 207 
 208     pe_unpack_versioned_attributes(data_set->input, rsc->xml, XML_TAG_ATTR_SETS, node_hash,
 209                                    meta_hash, data_set->now);
 210 
 211     /* set anything else based on the parent */
 212     if (rsc->parent != NULL) {
 213         pe_get_versioned_attributes(meta_hash, rsc->parent, node, data_set);
 214 
 215     } else {
 216         /* and finally check the defaults */
 217         pe_unpack_versioned_attributes(data_set->input, data_set->rsc_defaults, XML_TAG_ATTR_SETS,
 218                                        node_hash, meta_hash, data_set->now);
 219     }
 220 }
 221 #endif
 222 
 223 static char *
 224 template_op_key(xmlNode * op)
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226     const char *name = crm_element_value(op, "name");
 227     const char *role = crm_element_value(op, "role");
 228     char *key = NULL;
 229 
 230     if (role == NULL || crm_str_eq(role, RSC_ROLE_STARTED_S, TRUE)
 231         || crm_str_eq(role, RSC_ROLE_SLAVE_S, TRUE)) {
 232         role = RSC_ROLE_UNKNOWN_S;
 233     }
 234 
 235     key = crm_concat(name, role, '-');
 236     return key;
 237 }
 238 
 239 static gboolean
 240 unpack_template(xmlNode * xml_obj, xmlNode ** expanded_xml, pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242     xmlNode *cib_resources = NULL;
 243     xmlNode *template = NULL;
 244     xmlNode *new_xml = NULL;
 245     xmlNode *child_xml = NULL;
 246     xmlNode *rsc_ops = NULL;
 247     xmlNode *template_ops = NULL;
 248     const char *template_ref = NULL;
 249     const char *clone = NULL;
 250     const char *id = NULL;
 251 
 252     if (xml_obj == NULL) {
 253         pe_err("No resource object for template unpacking");
 254         return FALSE;
 255     }
 256 
 257     template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
 258     if (template_ref == NULL) {
 259         return TRUE;
 260     }
 261 
 262     id = ID(xml_obj);
 263     if (id == NULL) {
 264         pe_err("'%s' object must have a id", crm_element_name(xml_obj));
 265         return FALSE;
 266     }
 267 
 268     if (crm_str_eq(template_ref, id, TRUE)) {
 269         pe_err("The resource object '%s' should not reference itself", id);
 270         return FALSE;
 271     }
 272 
 273     cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
 274     if (cib_resources == NULL) {
 275         pe_err("No resources configured");
 276         return FALSE;
 277     }
 278 
 279     template = find_entity(cib_resources, XML_CIB_TAG_RSC_TEMPLATE, template_ref);
 280     if (template == NULL) {
 281         pe_err("No template named '%s'", template_ref);
 282         return FALSE;
 283     }
 284 
 285     new_xml = copy_xml(template);
 286     xmlNodeSetName(new_xml, xml_obj->name);
 287     crm_xml_replace(new_xml, XML_ATTR_ID, id);
 288 
 289     clone = crm_element_value(xml_obj, XML_RSC_ATTR_INCARNATION);
 290     if(clone) {
 291         crm_xml_add(new_xml, XML_RSC_ATTR_INCARNATION, clone);
 292     }
 293 
 294     template_ops = find_xml_node(new_xml, "operations", FALSE);
 295 
 296     for (child_xml = __xml_first_child(xml_obj); child_xml != NULL;
 297          child_xml = __xml_next_element(child_xml)) {
 298         xmlNode *new_child = NULL;
 299 
 300         new_child = add_node_copy(new_xml, child_xml);
 301 
 302         if (crm_str_eq((const char *)new_child->name, "operations", TRUE)) {
 303             rsc_ops = new_child;
 304         }
 305     }
 306 
 307     if (template_ops && rsc_ops) {
 308         xmlNode *op = NULL;
 309         GHashTable *rsc_ops_hash =
 310             g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, NULL);
 311 
 312         for (op = __xml_first_child(rsc_ops); op != NULL; op = __xml_next_element(op)) {
 313             char *key = template_op_key(op);
 314 
 315             g_hash_table_insert(rsc_ops_hash, key, op);
 316         }
 317 
 318         for (op = __xml_first_child(template_ops); op != NULL; op = __xml_next_element(op)) {
 319             char *key = template_op_key(op);
 320 
 321             if (g_hash_table_lookup(rsc_ops_hash, key) == NULL) {
 322                 add_node_copy(rsc_ops, op);
 323             }
 324 
 325             free(key);
 326         }
 327 
 328         if (rsc_ops_hash) {
 329             g_hash_table_destroy(rsc_ops_hash);
 330         }
 331 
 332         free_xml(template_ops);
 333     }
 334 
 335     /*free_xml(*expanded_xml); */
 336     *expanded_xml = new_xml;
 337 
 338     /* Disable multi-level templates for now */
 339     /*if(unpack_template(new_xml, expanded_xml, data_set) == FALSE) {
 340        free_xml(*expanded_xml);
 341        *expanded_xml = NULL;
 342 
 343        return FALSE;
 344        } */
 345 
 346     return TRUE;
 347 }
 348 
 349 static gboolean
 350 add_template_rsc(xmlNode * xml_obj, pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352     const char *template_ref = NULL;
 353     const char *id = NULL;
 354 
 355     if (xml_obj == NULL) {
 356         pe_err("No resource object for processing resource list of template");
 357         return FALSE;
 358     }
 359 
 360     template_ref = crm_element_value(xml_obj, XML_CIB_TAG_RSC_TEMPLATE);
 361     if (template_ref == NULL) {
 362         return TRUE;
 363     }
 364 
 365     id = ID(xml_obj);
 366     if (id == NULL) {
 367         pe_err("'%s' object must have a id", crm_element_name(xml_obj));
 368         return FALSE;
 369     }
 370 
 371     if (crm_str_eq(template_ref, id, TRUE)) {
 372         pe_err("The resource object '%s' should not reference itself", id);
 373         return FALSE;
 374     }
 375 
 376     if (add_tag_ref(data_set->template_rsc_sets, template_ref, id) == FALSE) {
 377         return FALSE;
 378     }
 379 
 380     return TRUE;
 381 }
 382 
 383 static void
 384 handle_rsc_isolation(resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386     resource_t *top = uber_parent(rsc);
 387     resource_t *iso = rsc;
 388     const char *wrapper = NULL;
 389     const char *value;
 390 
 391     /* check for isolation wrapper mapping if the parent doesn't have one set
 392      * isolation mapping is enabled by default. For safety, we are allowing isolation
 393      * to be disabled by setting the meta attr, isolation=false. */
 394     value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ISOLATION);
 395     if (top->isolation_wrapper == NULL && (value == NULL || crm_is_true(value))) {
 396         if (g_hash_table_lookup(rsc->parameters, "pcmk_docker_image")) {
 397             wrapper = "docker-wrapper";
 398         }
 399         /* add more isolation technologies here as we expand */
 400     } else if (top->isolation_wrapper) {
 401         goto set_rsc_opts;
 402     }
 403 
 404     if (wrapper == NULL) {
 405         return;
 406     }
 407 
 408     /* if this is a cloned primitive/group, go head and set the isolation wrapper at
 409      * at the clone level. this is really the only sane thing to do in this situation.
 410      * This allows someone to clone an isolated resource without having to shuffle
 411      * around the isolation attributes to the clone parent */
 412     if (top == rsc->parent && pe_rsc_is_clone(top)) {
 413         iso = top;
 414     }
 415 
 416     iso->isolation_wrapper = wrapper;
 417     set_bit(top->flags, pe_rsc_unique);
 418 
 419 set_rsc_opts:
 420     pe_warn_once(pe_wo_isolation, "Support for 'isolation' resource meta-attribute"
 421                                   " is deprecated and will be removed in a future release"
 422                                   " (use bundle syntax instead)");
 423 
 424     clear_bit(rsc->flags, pe_rsc_allow_migrate);
 425     set_bit(rsc->flags, pe_rsc_unique);
 426     if (pe_rsc_is_clone(top)) {
 427         add_hash_param(rsc->meta, XML_RSC_ATTR_UNIQUE, XML_BOOLEAN_TRUE);
 428     }
 429 }
 430 
 431 static void
 432 check_deprecated_stonith(resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 433 {
 434     GHashTableIter iter;
 435     char *key;
 436 
 437     g_hash_table_iter_init(&iter, rsc->parameters);
 438     while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) {
 439         if (crm_starts_with(key, "pcmk_")) {
 440             char *cmp = key + 5; // the part after "pcmk_"
 441 
 442             if (!strcmp(cmp, "poweroff_action")) {
 443                 pe_warn_once(pe_wo_poweroff,
 444                              "Support for the 'pcmk_poweroff_action' stonith resource parameter"
 445                              " is deprecated and will be removed in a future version"
 446                              " (use 'pcmk_off_action' instead)");
 447 
 448             } else if (!strcmp(cmp, "arg_map")) {
 449                 pe_warn_once(pe_wo_arg_map,
 450                              "Support for the 'pcmk_arg_map' stonith resource parameter"
 451                              " is deprecated and will be removed in a future version"
 452                              " (use 'pcmk_host_argument' instead)");
 453 
 454             } else if (crm_ends_with(cmp, "_cmd")) {
 455                 pe_warn_once(pe_wo_stonith_cmd,
 456                              "Support for the 'pcmk_*_cmd' stonith resource parameters"
 457                              " is deprecated and will be removed in a future version"
 458                              " (use 'pcmk_*_action' instead)");
 459             }
 460         }
 461     }
 462 }
 463 
 464 gboolean
 465 common_unpack(xmlNode * xml_obj, resource_t ** rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 466               resource_t * parent, pe_working_set_t * data_set)
 467 {
 468     bool isdefault = FALSE;
 469     xmlNode *expanded_xml = NULL;
 470     xmlNode *ops = NULL;
 471     resource_t *top = NULL;
 472     const char *value = NULL;
 473     const char *rclass = NULL; /* Look for this after any templates have been expanded */
 474     const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
 475     int container_remote_node = 0;
 476     int baremetal_remote_node = 0;
 477     bool has_versioned_params = FALSE;
 478 
 479     crm_log_xml_trace(xml_obj, "Processing resource input...");
 480 
 481     if (id == NULL) {
 482         pe_err("Must specify id tag in <resource>");
 483         return FALSE;
 484 
 485     } else if (rsc == NULL) {
 486         pe_err("Nowhere to unpack resource into");
 487         return FALSE;
 488 
 489     }
 490 
 491     if (unpack_template(xml_obj, &expanded_xml, data_set) == FALSE) {
 492         return FALSE;
 493     }
 494 
 495     *rsc = calloc(1, sizeof(resource_t));
 496     (*rsc)->cluster = data_set;
 497 
 498     if (expanded_xml) {
 499         crm_log_xml_trace(expanded_xml, "Expanded resource...");
 500         (*rsc)->xml = expanded_xml;
 501         (*rsc)->orig_xml = xml_obj;
 502 
 503     } else {
 504         (*rsc)->xml = xml_obj;
 505         (*rsc)->orig_xml = NULL;
 506     }
 507 
 508     /* Do not use xml_obj from here on, use (*rsc)->xml in case templates are involved */
 509     rclass = crm_element_value((*rsc)->xml, XML_AGENT_ATTR_CLASS);
 510     (*rsc)->parent = parent;
 511 
 512     ops = find_xml_node((*rsc)->xml, "operations", FALSE);
 513     (*rsc)->ops_xml = expand_idref(ops, data_set->input);
 514 
 515     (*rsc)->variant = get_resource_type(crm_element_name((*rsc)->xml));
 516     if ((*rsc)->variant == pe_unknown) {
 517         pe_err("Unknown resource type: %s", crm_element_name((*rsc)->xml));
 518         free(*rsc);
 519         return FALSE;
 520     }
 521 
 522     (*rsc)->parameters = crm_str_table_new();
 523 
 524 #if ENABLE_VERSIONED_ATTRS
 525     (*rsc)->versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
 526 #endif
 527 
 528     (*rsc)->meta = crm_str_table_new();
 529 
 530     (*rsc)->allowed_nodes =
 531         g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
 532 
 533     (*rsc)->known_on = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
 534 
 535     value = crm_element_value((*rsc)->xml, XML_RSC_ATTR_INCARNATION);
 536     if (value) {
 537         (*rsc)->id = crm_concat(id, value, ':');
 538         add_hash_param((*rsc)->meta, XML_RSC_ATTR_INCARNATION, value);
 539 
 540     } else {
 541         (*rsc)->id = strdup(id);
 542     }
 543 
 544     (*rsc)->fns = &resource_class_functions[(*rsc)->variant];
 545     pe_rsc_trace((*rsc), "Unpacking resource...");
 546 
 547     get_meta_attributes((*rsc)->meta, *rsc, NULL, data_set);
 548     get_rsc_attributes((*rsc)->parameters, *rsc, NULL, data_set);
 549 #if ENABLE_VERSIONED_ATTRS
 550     pe_get_versioned_attributes((*rsc)->versioned_parameters, *rsc, NULL, data_set);
 551 #endif
 552 
 553     (*rsc)->flags = 0;
 554     set_bit((*rsc)->flags, pe_rsc_runnable);
 555     set_bit((*rsc)->flags, pe_rsc_provisional);
 556 
 557     if (is_set(data_set->flags, pe_flag_is_managed_default)) {
 558         set_bit((*rsc)->flags, pe_rsc_managed);
 559     }
 560 
 561     (*rsc)->rsc_cons = NULL;
 562     (*rsc)->rsc_tickets = NULL;
 563     (*rsc)->actions = NULL;
 564     (*rsc)->role = RSC_ROLE_STOPPED;
 565     (*rsc)->next_role = RSC_ROLE_UNKNOWN;
 566 
 567     (*rsc)->recovery_type = recovery_stop_start;
 568     (*rsc)->stickiness = data_set->default_resource_stickiness;
 569     (*rsc)->migration_threshold = INFINITY;
 570     (*rsc)->failure_timeout = 0;
 571 
 572     value = g_hash_table_lookup((*rsc)->meta, XML_CIB_ATTR_PRIORITY);
 573     (*rsc)->priority = crm_parse_int(value, "0");
 574     (*rsc)->effective_priority = (*rsc)->priority;
 575 
 576     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_NOTIFY);
 577     if (crm_is_true(value)) {
 578         set_bit((*rsc)->flags, pe_rsc_notify);
 579     }
 580 
 581     if (xml_contains_remote_node((*rsc)->xml)) {
 582         (*rsc)->is_remote_node = TRUE;
 583         if (g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_CONTAINER)) {
 584             container_remote_node = 1;
 585         } else {
 586             baremetal_remote_node = 1;
 587         }
 588     }
 589 
 590     value = g_hash_table_lookup((*rsc)->meta, XML_OP_ATTR_ALLOW_MIGRATE);
 591 #if ENABLE_VERSIONED_ATTRS
 592     has_versioned_params = xml_has_children((*rsc)->versioned_parameters);
 593 #endif
 594     if (crm_is_true(value) && has_versioned_params) {
 595         pe_rsc_trace((*rsc), "Migration is disabled for resources with versioned parameters");
 596     } else if (crm_is_true(value)) {
 597         set_bit((*rsc)->flags, pe_rsc_allow_migrate);
 598     } else if ((value == NULL) && baremetal_remote_node && !has_versioned_params) {
 599         /* by default, we want baremetal remote-nodes to be able
 600          * to float around the cluster without having to stop all the
 601          * resources within the remote-node before moving. Allowing
 602          * migration support enables this feature. If this ever causes
 603          * problems, migration support can be explicitly turned off with
 604          * allow-migrate=false.
 605          * We don't support migration for versioned resources, though. */
 606         set_bit((*rsc)->flags, pe_rsc_allow_migrate);
 607     }
 608 
 609     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MANAGED);
 610     if (value != NULL && safe_str_neq("default", value)) {
 611         gboolean bool_value = TRUE;
 612 
 613         crm_str_to_boolean(value, &bool_value);
 614         if (bool_value == FALSE) {
 615             clear_bit((*rsc)->flags, pe_rsc_managed);
 616         } else {
 617             set_bit((*rsc)->flags, pe_rsc_managed);
 618         }
 619     }
 620 
 621     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MAINTENANCE);
 622     if (value != NULL && safe_str_neq("default", value)) {
 623         gboolean bool_value = FALSE;
 624 
 625         crm_str_to_boolean(value, &bool_value);
 626         if (bool_value == TRUE) {
 627             clear_bit((*rsc)->flags, pe_rsc_managed);
 628             set_bit((*rsc)->flags, pe_rsc_maintenance);
 629         }
 630 
 631     } else if (is_set(data_set->flags, pe_flag_maintenance_mode)) {
 632         clear_bit((*rsc)->flags, pe_rsc_managed);
 633         set_bit((*rsc)->flags, pe_rsc_maintenance);
 634     }
 635 
 636     pe_rsc_trace((*rsc), "Options for %s", (*rsc)->id);
 637 
 638     handle_rsc_isolation(*rsc);
 639 
 640     top = uber_parent(*rsc);
 641     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE);
 642     if (crm_is_true(value) || pe_rsc_is_clone(top) == FALSE) {
 643         set_bit((*rsc)->flags, pe_rsc_unique);
 644     }
 645 
 646     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_RESTART);
 647     if (safe_str_eq(value, "restart")) {
 648         (*rsc)->restart_type = pe_restart_restart;
 649         pe_rsc_trace((*rsc), "\tDependency restart handling: restart");
 650 
 651     } else {
 652         (*rsc)->restart_type = pe_restart_ignore;
 653         pe_rsc_trace((*rsc), "\tDependency restart handling: ignore");
 654     }
 655 
 656     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_MULTIPLE);
 657     if (safe_str_eq(value, "stop_only")) {
 658         (*rsc)->recovery_type = recovery_stop_only;
 659         pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop only");
 660 
 661     } else if (safe_str_eq(value, "block")) {
 662         (*rsc)->recovery_type = recovery_block;
 663         pe_rsc_trace((*rsc), "\tMultiple running resource recovery: block");
 664 
 665     } else {
 666         (*rsc)->recovery_type = recovery_stop_start;
 667         pe_rsc_trace((*rsc), "\tMultiple running resource recovery: stop/start");
 668     }
 669 
 670     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_STICKINESS);
 671     if (value != NULL && safe_str_neq("default", value)) {
 672         (*rsc)->stickiness = char2score(value);
 673     }
 674 
 675     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_STICKINESS);
 676     if (value != NULL && safe_str_neq("default", value)) {
 677         (*rsc)->migration_threshold = char2score(value);
 678 
 679     } else if (value == NULL) {
 680         /* Make a best-effort guess at a migration threshold for people with 0.6 configs
 681          * try with underscores and hyphens, from both the resource and global defaults section
 682          */
 683         const char *legacy = NULL;
 684 
 685         legacy = g_hash_table_lookup((*rsc)->meta,
 686                                      "resource-failure-stickiness");
 687         if (legacy == NULL) {
 688             legacy = g_hash_table_lookup((*rsc)->meta,
 689                                          "resource_failure_stickiness");
 690         }
 691         if (legacy) {
 692             value = legacy;
 693             pe_warn_once(pe_wo_rsc_failstick,
 694                          "Support for 'resource-failure-stickiness' resource meta-attribute"
 695                          " is deprecated and will be removed in a future release"
 696                          " (use 'migration-threshold' resource meta-attribute instead)");
 697         }
 698 
 699         legacy = g_hash_table_lookup(data_set->config_hash,
 700                                      "default-resource-failure-stickiness");
 701         if (legacy == NULL) {
 702             legacy = g_hash_table_lookup(data_set->config_hash,
 703                                          "default_resource_failure_stickiness");
 704         }
 705         if (legacy) {
 706             if (value == NULL) {
 707                 value = legacy;
 708             }
 709             pe_warn_once(pe_wo_default_rscfs,
 710                          "Support for 'default-resource-failure-stickiness' cluster option"
 711                          " is deprecated and will be removed in a future release"
 712                          " (use 'migration-threshold' in rsc_defaults instead)");
 713         }
 714 
 715         if (value) {
 716             int fail_sticky = char2score(value);
 717 
 718             if (fail_sticky == -INFINITY) {
 719                 (*rsc)->migration_threshold = 1;
 720                 pe_rsc_info((*rsc),
 721                             "Set a migration threshold of %d for %s based on a failure-stickiness of %s",
 722                             (*rsc)->migration_threshold, (*rsc)->id, value);
 723 
 724             } else if ((*rsc)->stickiness != 0 && fail_sticky != 0) {
 725                 (*rsc)->migration_threshold = (*rsc)->stickiness / fail_sticky;
 726                 if ((*rsc)->migration_threshold < 0) {
 727                     /* Make sure it's positive */
 728                     (*rsc)->migration_threshold = 0 - (*rsc)->migration_threshold;
 729                 }
 730                 (*rsc)->migration_threshold += 1;
 731                 pe_rsc_info((*rsc),
 732                             "Calculated a migration threshold for %s of %d based on a stickiness of %d/%s",
 733                             (*rsc)->id, (*rsc)->migration_threshold, (*rsc)->stickiness, value);
 734             }
 735         }
 736     }
 737 
 738     if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH)) {
 739         set_bit(data_set->flags, pe_flag_have_stonith_resource);
 740         set_bit((*rsc)->flags, pe_rsc_fence_device);
 741         check_deprecated_stonith(*rsc);
 742     }
 743 
 744     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_REQUIRES);
 745 
 746   handle_requires_pref:
 747     if (safe_str_eq(value, "nothing")) {
 748 
 749     } else if (safe_str_eq(value, "quorum")) {
 750         set_bit((*rsc)->flags, pe_rsc_needs_quorum);
 751 
 752     } else if (safe_str_eq(value, "unfencing")) {
 753         if (is_set((*rsc)->flags, pe_rsc_fence_device)) {
 754             crm_config_warn("%s is a fencing device but requires (un)fencing", (*rsc)->id);
 755             value = "quorum";
 756             isdefault = TRUE;
 757             goto handle_requires_pref;
 758 
 759         } else if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
 760             crm_config_warn("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
 761             value = "quorum";
 762             isdefault = TRUE;
 763             goto handle_requires_pref;
 764 
 765         } else {
 766             set_bit((*rsc)->flags, pe_rsc_needs_fencing);
 767             set_bit((*rsc)->flags, pe_rsc_needs_unfencing);
 768         }
 769 
 770     } else if (safe_str_eq(value, "fencing")) {
 771         set_bit((*rsc)->flags, pe_rsc_needs_fencing);
 772         if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
 773             crm_config_warn("%s requires fencing but fencing is disabled", (*rsc)->id);
 774         }
 775 
 776     } else {
 777         if (value) {
 778             crm_config_err("Invalid value for %s->requires: %s%s",
 779                            (*rsc)->id, value,
 780                            is_set(data_set->flags, pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)");
 781         }
 782 
 783         isdefault = TRUE;
 784         if(is_set((*rsc)->flags, pe_rsc_fence_device)) {
 785             value = "quorum";
 786 
 787         } else if (is_set(data_set->flags, pe_flag_enable_unfencing)) {
 788             value = "unfencing";
 789 
 790         } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
 791             value = "fencing";
 792 
 793         } else if (data_set->no_quorum_policy == no_quorum_ignore) {
 794             value = "nothing";
 795 
 796         } else {
 797             value = "quorum";
 798         }
 799         goto handle_requires_pref;
 800     }
 801 
 802     pe_rsc_trace((*rsc), "\tRequired to start: %s%s", value, isdefault?" (default)":"");
 803     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT);
 804     if (value != NULL) {
 805         /* call crm_get_msec() and convert back to seconds */
 806         (*rsc)->failure_timeout = (crm_get_msec(value) / 1000);
 807     }
 808 
 809     if (baremetal_remote_node) {
 810         value = g_hash_table_lookup((*rsc)->parameters, XML_REMOTE_ATTR_RECONNECT_INTERVAL);
 811         if (value) {
 812             /* reconnect delay works by setting failure_timeout and preventing the
 813              * connection from starting until the failure is cleared. */
 814             (*rsc)->remote_reconnect_interval = (crm_get_msec(value) / 1000);
 815             /* we want to override any default failure_timeout in use when remote
 816              * reconnect_interval is in use. */ 
 817             (*rsc)->failure_timeout = (*rsc)->remote_reconnect_interval;
 818         }
 819     }
 820 
 821     get_target_role(*rsc, &((*rsc)->next_role));
 822     pe_rsc_trace((*rsc), "\tDesired next state: %s",
 823                  (*rsc)->next_role != RSC_ROLE_UNKNOWN ? role2text((*rsc)->next_role) : "default");
 824 
 825     if ((*rsc)->fns->unpack(*rsc, data_set) == FALSE) {
 826         return FALSE;
 827     }
 828 
 829     if (is_set(data_set->flags, pe_flag_symmetric_cluster)) {
 830         // This tag must stay exactly the same because it is tested elsewhere
 831         resource_location(*rsc, NULL, 0, "symmetric_default", data_set);
 832     } else if (container_remote_node) {
 833         /* remote resources tied to a container resource must always be allowed
 834          * to opt-in to the cluster. Whether the connection resource is actually
 835          * allowed to be placed on a node is dependent on the container resource */
 836         resource_location(*rsc, NULL, 0, "remote_connection_default", data_set);
 837     }
 838 
 839     pe_rsc_trace((*rsc), "\tAction notification: %s",
 840                  is_set((*rsc)->flags, pe_rsc_notify) ? "required" : "not required");
 841 
 842     (*rsc)->utilization = crm_str_table_new();
 843 
 844     unpack_instance_attributes(data_set->input, (*rsc)->xml, XML_TAG_UTILIZATION, NULL,
 845                                (*rsc)->utilization, NULL, FALSE, data_set->now);
 846 
 847 /*      data_set->resources = g_list_append(data_set->resources, (*rsc)); */
 848 
 849     if (expanded_xml) {
 850         if (add_template_rsc(xml_obj, data_set) == FALSE) {
 851             return FALSE;
 852         }
 853     }
 854     return TRUE;
 855 }
 856 
 857 void
 858 common_update_score(resource_t * rsc, const char *id, int score)
     /* [previous][next][first][last][top][bottom][index][help] */
 859 {
 860     node_t *node = NULL;
 861 
 862     node = pe_hash_table_lookup(rsc->allowed_nodes, id);
 863     if (node != NULL) {
 864         pe_rsc_trace(rsc, "Updating score for %s on %s: %d + %d", rsc->id, id, node->weight, score);
 865         node->weight = merge_weights(node->weight, score);
 866     }
 867 
 868     if (rsc->children) {
 869         GListPtr gIter = rsc->children;
 870 
 871         for (; gIter != NULL; gIter = gIter->next) {
 872             resource_t *child_rsc = (resource_t *) gIter->data;
 873 
 874             common_update_score(child_rsc, id, score);
 875         }
 876     }
 877 }
 878 
 879 gboolean
 880 is_parent(resource_t *child, resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 881 {
 882     resource_t *parent = child;
 883 
 884     if (parent == NULL || rsc == NULL) {
 885         return FALSE;
 886     }
 887     while (parent->parent != NULL) {
 888         if (parent->parent == rsc) {
 889             return TRUE;
 890         }
 891         parent = parent->parent;
 892     }
 893     return FALSE;
 894 }
 895 
 896 resource_t *
 897 uber_parent(resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 898 {
 899     resource_t *parent = rsc;
 900 
 901     if (parent == NULL) {
 902         return NULL;
 903     }
 904     while (parent->parent != NULL && parent->parent->variant != pe_container) {
 905         parent = parent->parent;
 906     }
 907     return parent;
 908 }
 909 
 910 void
 911 common_free(resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 912 {
 913     if (rsc == NULL) {
 914         return;
 915     }
 916 
 917     pe_rsc_trace(rsc, "Freeing %s %d", rsc->id, rsc->variant);
 918 
 919     g_list_free(rsc->rsc_cons);
 920     g_list_free(rsc->rsc_cons_lhs);
 921     g_list_free(rsc->rsc_tickets);
 922     g_list_free(rsc->dangling_migrations);
 923 
 924     if (rsc->parameters != NULL) {
 925         g_hash_table_destroy(rsc->parameters);
 926     }
 927 #if ENABLE_VERSIONED_ATTRS
 928     if (rsc->versioned_parameters != NULL) {
 929         free_xml(rsc->versioned_parameters);
 930     }
 931 #endif
 932     if (rsc->meta != NULL) {
 933         g_hash_table_destroy(rsc->meta);
 934     }
 935     if (rsc->utilization != NULL) {
 936         g_hash_table_destroy(rsc->utilization);
 937     }
 938 
 939     if (rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
 940         free_xml(rsc->xml);
 941         rsc->xml = NULL;
 942         free_xml(rsc->orig_xml);
 943         rsc->orig_xml = NULL;
 944 
 945         /* if rsc->orig_xml, then rsc->xml is an expanded xml from a template */
 946     } else if (rsc->orig_xml) {
 947         free_xml(rsc->xml);
 948         rsc->xml = NULL;
 949     }
 950     if (rsc->running_on) {
 951         g_list_free(rsc->running_on);
 952         rsc->running_on = NULL;
 953     }
 954     if (rsc->known_on) {
 955         g_hash_table_destroy(rsc->known_on);
 956         rsc->known_on = NULL;
 957     }
 958     if (rsc->actions) {
 959         g_list_free(rsc->actions);
 960         rsc->actions = NULL;
 961     }
 962     if (rsc->allowed_nodes) {
 963         g_hash_table_destroy(rsc->allowed_nodes);
 964         rsc->allowed_nodes = NULL;
 965     }
 966     g_list_free(rsc->fillers);
 967     g_list_free(rsc->rsc_location);
 968     pe_rsc_trace(rsc, "Resource freed");
 969     free(rsc->id);
 970     free(rsc->clone_name);
 971     free(rsc->allocated_to);
 972     free(rsc->variant_opaque);
 973     free(rsc->pending_task);
 974     free(rsc);
 975 }

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