This source file includes following definitions.
- check_params
- failcount_clear_action_exists
- check_failure_threshold
- apply_exclusive_discovery
- apply_stickiness
- apply_shutdown_locks
- count_available_nodes
- apply_node_criteria
- allocate_resources
- clear_failcounts_if_orphaned
- schedule_resource_actions
- is_managed
- any_managed_resources
- needs_fencing
- needs_shutdown
- add_nondc_fencing
- schedule_fencing
- schedule_fencing_and_shutdowns
- log_resource_details
- log_all_actions
- log_unrunnable_actions
- unpack_cib
- pcmk__schedule_actions
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <crm/crm.h>
  13 #include <crm/cib.h>
  14 #include <crm/msg_xml.h>
  15 #include <crm/common/xml.h>
  16 #include <crm/common/xml_internal.h>
  17 
  18 #include <glib.h>
  19 
  20 #include <crm/pengine/status.h>
  21 #include <pacemaker-internal.h>
  22 #include "libpacemaker_private.h"
  23 
  24 CRM_TRACE_INIT_DATA(pacemaker);
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 static void
  42 check_params(pe_resource_t *rsc, pe_node_t *node, const xmlNode *rsc_op,
     
  43              enum pe_check_parameters check)
  44 {
  45     const char *reason = NULL;
  46     op_digest_cache_t *digest_data = NULL;
  47 
  48     switch (check) {
  49         case pe_check_active:
  50             if (pcmk__check_action_config(rsc, node, rsc_op)
  51                 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL)) {
  52                 reason = "action definition changed";
  53             }
  54             break;
  55 
  56         case pe_check_last_failure:
  57             digest_data = rsc_action_digest_cmp(rsc, rsc_op, node,
  58                                                 rsc->cluster);
  59             switch (digest_data->rc) {
  60                 case RSC_DIGEST_UNKNOWN:
  61                     crm_trace("Resource %s history entry %s on %s has "
  62                               "no digest to compare",
  63                               rsc->id, ID(rsc_op), node->details->id);
  64                     break;
  65                 case RSC_DIGEST_MATCH:
  66                     break;
  67                 default:
  68                     reason = "resource parameters have changed";
  69                     break;
  70             }
  71             break;
  72     }
  73     if (reason != NULL) {
  74         pe__clear_failcount(rsc, node, reason, rsc->cluster);
  75     }
  76 }
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 static bool
  89 failcount_clear_action_exists(const pe_node_t *node, const pe_resource_t *rsc)
     
  90 {
  91     GList *list = pe__resource_actions(rsc, node, CRM_OP_CLEAR_FAILCOUNT, TRUE);
  92 
  93     if (list != NULL) {
  94         g_list_free(list);
  95         return true;
  96     }
  97     return false;
  98 }
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 
 107 static void
 108 check_failure_threshold(pe_resource_t *rsc, const pe_node_t *node)
     
 109 {
 110     
 111     if (rsc->children != NULL) {
 112         g_list_foreach(rsc->children, (GFunc) check_failure_threshold,
 113                        (gpointer) node);
 114         return;
 115 
 116     } else if (failcount_clear_action_exists(node, rsc)) {
 117         
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127         return;
 128 
 129     } else {
 130         pe_resource_t *failed = NULL;
 131 
 132         if (pcmk__threshold_reached(rsc, node, &failed)) {
 133             resource_location(failed, node, -INFINITY, "__fail_limit__",
 134                               rsc->cluster);
 135         }
 136     }
 137 }
 138 
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 static void
 152 apply_exclusive_discovery(pe_resource_t *rsc, const pe_node_t *node)
     
 153 {
 154     if (rsc->exclusive_discover
 155         || pe__const_top_resource(rsc, false)->exclusive_discover) {
 156         pe_node_t *match = NULL;
 157 
 158         
 159         g_list_foreach(rsc->children, (GFunc) apply_exclusive_discovery,
 160                        (gpointer) node);
 161 
 162         match = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
 163         if ((match != NULL)
 164             && (match->rsc_discover_mode != pe_discover_exclusive)) {
 165             match->weight = -INFINITY;
 166         }
 167     }
 168 }
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 static void
 178 apply_stickiness(pe_resource_t *rsc, pe_working_set_t *data_set)
     
 179 {
 180     pe_node_t *node = NULL;
 181 
 182     
 183     if (rsc->children != NULL) {
 184         g_list_foreach(rsc->children, (GFunc) apply_stickiness, data_set);
 185         return;
 186     }
 187 
 188     
 189 
 190 
 191     if (!pcmk_is_set(rsc->flags, pe_rsc_managed)
 192         || (rsc->stickiness < 1) || !pcmk__list_of_1(rsc->running_on)) {
 193         return;
 194     }
 195 
 196     node = rsc->running_on->data;
 197 
 198     
 199 
 200 
 201 
 202 
 203     if (!pcmk_is_set(rsc->cluster->flags, pe_flag_symmetric_cluster)
 204         && (pe_hash_table_lookup(rsc->allowed_nodes,
 205                                  node->details->id) == NULL)) {
 206         pe_rsc_debug(rsc,
 207                      "Ignoring %s stickiness because the cluster is "
 208                      "asymmetric and %s is not explicitly allowed",
 209                      rsc->id, pe__node_name(node));
 210         return;
 211     }
 212 
 213     pe_rsc_debug(rsc, "Resource %s has %d stickiness on %s",
 214                  rsc->id, rsc->stickiness, pe__node_name(node));
 215     resource_location(rsc, node, rsc->stickiness, "stickiness", data_set);
 216 }
 217 
 218 
 219 
 220 
 221 
 222 
 223 
 224 static void
 225 apply_shutdown_locks(pe_working_set_t *data_set)
     
 226 {
 227     if (!pcmk_is_set(data_set->flags, pe_flag_shutdown_lock)) {
 228         return;
 229     }
 230     for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
 231         pe_resource_t *rsc = (pe_resource_t *) iter->data;
 232 
 233         rsc->cmds->shutdown_lock(rsc);
 234     }
 235 }
 236 
 237 
 238 
 239 
 240 
 241 
 242 
 243 static void
 244 count_available_nodes(pe_working_set_t *data_set)
     
 245 {
 246     if (pcmk_is_set(data_set->flags, pe_flag_no_compat)) {
 247         return;
 248     }
 249 
 250     
 251     for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
 252         pe_node_t *node = (pe_node_t *) iter->data;
 253 
 254         if ((node != NULL) && (node->weight >= 0) && node->details->online
 255             && (node->details->type != node_ping)) {
 256             data_set->max_valid_nodes++;
 257         }
 258     }
 259     crm_trace("Online node count: %d", data_set->max_valid_nodes);
 260 }
 261 
 262 
 263 
 264 
 265 
 266 
 267 
 268 
 269 
 270 static void
 271 apply_node_criteria(pe_working_set_t *data_set)
     
 272 {
 273     crm_trace("Applying node-specific scheduling criteria");
 274     apply_shutdown_locks(data_set);
 275     count_available_nodes(data_set);
 276     pcmk__apply_locations(data_set);
 277     g_list_foreach(data_set->resources, (GFunc) apply_stickiness, data_set);
 278 
 279     for (GList *node_iter = data_set->nodes; node_iter != NULL;
 280          node_iter = node_iter->next) {
 281         for (GList *rsc_iter = data_set->resources; rsc_iter != NULL;
 282              rsc_iter = rsc_iter->next) {
 283             pe_node_t *node = (pe_node_t *) node_iter->data;
 284             pe_resource_t *rsc = (pe_resource_t *) rsc_iter->data;
 285 
 286             check_failure_threshold(rsc, node);
 287             apply_exclusive_discovery(rsc, node);
 288         }
 289     }
 290 }
 291 
 292 
 293 
 294 
 295 
 296 
 297 
 298 static void
 299 allocate_resources(pe_working_set_t *data_set)
     
 300 {
 301     GList *iter = NULL;
 302 
 303     crm_trace("Allocating resources to nodes");
 304 
 305     if (!pcmk__str_eq(data_set->placement_strategy, "default", pcmk__str_casei)) {
 306         pcmk__sort_resources(data_set);
 307     }
 308     pcmk__show_node_capacities("Original", data_set);
 309 
 310     if (pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
 311         
 312 
 313 
 314 
 315         for (iter = data_set->resources; iter != NULL; iter = iter->next) {
 316             pe_resource_t *rsc = (pe_resource_t *) iter->data;
 317 
 318             if (rsc->is_remote_node) {
 319                 pe_rsc_trace(rsc, "Allocating remote connection resource '%s'",
 320                              rsc->id);
 321                 rsc->cmds->assign(rsc, rsc->partial_migration_target);
 322             }
 323         }
 324     }
 325 
 326     
 327     for (iter = data_set->resources; iter != NULL; iter = iter->next) {
 328         pe_resource_t *rsc = (pe_resource_t *) iter->data;
 329 
 330         if (!rsc->is_remote_node) {
 331             pe_rsc_trace(rsc, "Allocating %s resource '%s'",
 332                          crm_element_name(rsc->xml), rsc->id);
 333             rsc->cmds->assign(rsc, NULL);
 334         }
 335     }
 336 
 337     pcmk__show_node_capacities("Remaining", data_set);
 338 }
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 static void
 348 clear_failcounts_if_orphaned(pe_resource_t *rsc, pe_working_set_t *data_set)
     
 349 {
 350     if (!pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
 351         return;
 352     }
 353     crm_trace("Clear fail counts for orphaned resource %s", rsc->id);
 354 
 355     
 356 
 357 
 358 
 359     for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
 360         pe_node_t *node = (pe_node_t *) iter->data;
 361         pe_action_t *clear_op = NULL;
 362 
 363         if (!node->details->online) {
 364             continue;
 365         }
 366         if (pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL) == 0) {
 367             continue;
 368         }
 369 
 370         clear_op = pe__clear_failcount(rsc, node, "it is orphaned", data_set);
 371 
 372         
 373 
 374 
 375         pcmk__new_ordering(clear_op->rsc, NULL, clear_op, rsc, stop_key(rsc),
 376                            NULL, pe_order_optional, data_set);
 377     }
 378 }
 379 
 380 
 381 
 382 
 383 
 384 
 385 
 386 static void
 387 schedule_resource_actions(pe_working_set_t *data_set)
     
 388 {
 389     
 390     pe__foreach_param_check(data_set, check_params);
 391     pe__free_param_checks(data_set);
 392 
 393     if (pcmk_is_set(data_set->flags, pe_flag_startup_probes)) {
 394         crm_trace("Scheduling probes");
 395         pcmk__schedule_probes(data_set);
 396     }
 397 
 398     if (pcmk_is_set(data_set->flags, pe_flag_stop_rsc_orphans)) {
 399         g_list_foreach(data_set->resources,
 400                        (GFunc) clear_failcounts_if_orphaned, data_set);
 401     }
 402 
 403     crm_trace("Scheduling resource actions");
 404     for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
 405         pe_resource_t *rsc = (pe_resource_t *) iter->data;
 406 
 407         rsc->cmds->create_actions(rsc);
 408     }
 409 }
 410 
 411 
 412 
 413 
 414 
 415 
 416 
 417 
 418 
 419 static bool
 420 is_managed(const pe_resource_t *rsc)
     
 421 {
 422     if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
 423         return true;
 424     }
 425     for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
 426         if (is_managed((pe_resource_t *) iter->data)) {
 427             return true;
 428         }
 429     }
 430     return false;
 431 }
 432 
 433 
 434 
 435 
 436 
 437 
 438 
 439 
 440 
 441 static bool
 442 any_managed_resources(const pe_working_set_t *data_set)
     
 443 {
 444     for (const GList *iter = data_set->resources;
 445          iter != NULL; iter = iter->next) {
 446         if (is_managed((const pe_resource_t *) iter->data)) {
 447             return true;
 448         }
 449     }
 450     return false;
 451 }
 452 
 453 
 454 
 455 
 456 
 457 
 458 
 459 
 460 
 461 
 462 
 463 static bool
 464 needs_fencing(const pe_node_t *node, bool have_managed,
     
 465               const pe_working_set_t *data_set)
 466 {
 467     return have_managed && node->details->unclean
 468            && pe_can_fence(data_set, node);
 469 }
 470 
 471 
 472 
 473 
 474 
 475 
 476 
 477 
 478 
 479 static bool
 480 needs_shutdown(const pe_node_t *node)
     
 481 {
 482     if (pe__is_guest_or_remote_node(node)) {
 483        
 484 
 485 
 486         return false;
 487     }
 488     return node->details->online && node->details->shutdown;
 489 }
 490 
 491 
 492 
 493 
 494 
 495 
 496 
 497 
 498 
 499 
 500 
 501 static GList *
 502 add_nondc_fencing(GList *list, pe_action_t *action,
     
 503                   const pe_working_set_t *data_set)
 504 {
 505     if (!pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)
 506         && (list != NULL)) {
 507         
 508 
 509 
 510 
 511 
 512         order_actions((pe_action_t *) list->data, action, pe_order_optional);
 513     }
 514     return g_list_prepend(list, action);
 515 }
 516 
 517 
 518 
 519 
 520 
 521 
 522 
 523 
 524 static pe_action_t *
 525 schedule_fencing(pe_node_t *node, pe_working_set_t *data_set)
     
 526 {
 527     pe_action_t *fencing = pe_fence_op(node, NULL, FALSE, "node is unclean",
 528                                        FALSE, data_set);
 529 
 530     pe_warn("Scheduling node %s for fencing", pe__node_name(node));
 531     pcmk__order_vs_fence(fencing, data_set);
 532     return fencing;
 533 }
 534 
 535 
 536 
 537 
 538 
 539 
 540 
 541 static void
 542 schedule_fencing_and_shutdowns(pe_working_set_t *data_set)
     
 543 {
 544     pe_action_t *dc_down = NULL;
 545     bool integrity_lost = false;
 546     bool have_managed = any_managed_resources(data_set);
 547     GList *fencing_ops = NULL;
 548     GList *shutdown_ops = NULL;
 549 
 550     crm_trace("Scheduling fencing and shutdowns as needed");
 551     if (!have_managed) {
 552         crm_notice("No fencing will be done until there are resources to manage");
 553     }
 554 
 555     
 556     for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
 557         pe_node_t *node = (pe_node_t *) iter->data;
 558         pe_action_t *fencing = NULL;
 559 
 560         
 561 
 562 
 563         if (pe__is_guest_node(node)) {
 564             if (node->details->remote_requires_reset && have_managed
 565                 && pe_can_fence(data_set, node)) {
 566                 pcmk__fence_guest(node);
 567             }
 568             continue;
 569         }
 570 
 571         if (needs_fencing(node, have_managed, data_set)) {
 572             fencing = schedule_fencing(node, data_set);
 573 
 574             
 575             if (node->details->is_dc) {
 576                 dc_down = fencing;
 577             } else {
 578                 fencing_ops = add_nondc_fencing(fencing_ops, fencing, data_set);
 579             }
 580 
 581         } else if (needs_shutdown(node)) {
 582             pe_action_t *down_op = pcmk__new_shutdown_action(node);
 583 
 584             
 585             if (node->details->is_dc) {
 586                 dc_down = down_op;
 587             } else {
 588                 shutdown_ops = g_list_prepend(shutdown_ops, down_op);
 589             }
 590         }
 591 
 592         if ((fencing == NULL) && node->details->unclean) {
 593             integrity_lost = true;
 594             pe_warn("Node %s is unclean but cannot be fenced",
 595                     pe__node_name(node));
 596         }
 597     }
 598 
 599     if (integrity_lost) {
 600         if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
 601             pe_warn("Resource functionality and data integrity cannot be "
 602                     "guaranteed (configure, enable, and test fencing to "
 603                     "correct this)");
 604 
 605         } else if (!pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
 606             crm_notice("Unclean nodes will not be fenced until quorum is "
 607                        "attained or no-quorum-policy is set to ignore");
 608         }
 609     }
 610 
 611     if (dc_down != NULL) {
 612         
 613 
 614 
 615 
 616 
 617 
 618 
 619         if (pcmk__str_eq(dc_down->task, CRM_OP_SHUTDOWN, pcmk__str_none)) {
 620             pcmk__order_after_each(dc_down, shutdown_ops);
 621         }
 622 
 623         
 624 
 625         if (pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)) {
 626             
 627 
 628 
 629             pcmk__order_after_each(dc_down, fencing_ops);
 630         } else if (fencing_ops != NULL) {
 631             
 632 
 633 
 634 
 635 
 636             order_actions((pe_action_t *) fencing_ops->data, dc_down,
 637                           pe_order_optional);
 638         }
 639     }
 640     g_list_free(fencing_ops);
 641     g_list_free(shutdown_ops);
 642 }
 643 
 644 static void
 645 log_resource_details(pe_working_set_t *data_set)
     
 646 {
 647     pcmk__output_t *out = data_set->priv;
 648     GList *all = NULL;
 649 
 650     
 651 
 652 
 653 
 654 
 655     all = g_list_prepend(all, (gpointer) "*");
 656 
 657     for (GList *item = data_set->resources; item != NULL; item = item->next) {
 658         pe_resource_t *rsc = (pe_resource_t *) item->data;
 659 
 660         
 661         if (!pcmk_is_set(rsc->flags, pe_rsc_orphan)
 662             || (rsc->role != RSC_ROLE_STOPPED)) {
 663             out->message(out, crm_map_element_name(rsc->xml), 0, rsc, all, all);
 664         }
 665     }
 666 
 667     g_list_free(all);
 668 }
 669 
 670 static void
 671 log_all_actions(pe_working_set_t *data_set)
     
 672 {
 673     
 674 
 675 
 676     pcmk__output_t *prev_out = data_set->priv;
 677     pcmk__output_t *out = NULL;
 678 
 679     if (pcmk__log_output_new(&out) != pcmk_rc_ok) {
 680         return;
 681     }
 682 
 683     pe__register_messages(out);
 684     pcmk__register_lib_messages(out);
 685     pcmk__output_set_log_level(out, LOG_NOTICE);
 686     data_set->priv = out;
 687 
 688     out->begin_list(out, NULL, NULL, "Actions");
 689     pcmk__output_actions(data_set);
 690     out->end_list(out);
 691     out->finish(out, CRM_EX_OK, true, NULL);
 692     pcmk__output_free(out);
 693 
 694     data_set->priv = prev_out;
 695 }
 696 
 697 
 698 
 699 
 700 
 701 
 702 
 703 static void
 704 log_unrunnable_actions(const pe_working_set_t *data_set)
     
 705 {
 706     const uint64_t flags = pe_action_optional|pe_action_runnable|pe_action_pseudo;
 707 
 708     crm_trace("Required but unrunnable actions:");
 709     for (const GList *iter = data_set->actions;
 710          iter != NULL; iter = iter->next) {
 711 
 712         const pe_action_t *action = (const pe_action_t *) iter->data;
 713 
 714         if (!pcmk_any_flags_set(action->flags, flags)) {
 715             pcmk__log_action("\t", action, true);
 716         }
 717     }
 718 }
 719 
 720 
 721 
 722 
 723 
 724 
 725 
 726 
 727 
 728 static void
 729 unpack_cib(xmlNode *cib, unsigned long long flags, pe_working_set_t *data_set)
     
 730 {
 731     const char* localhost_save = NULL;
 732 
 733     if (pcmk_is_set(data_set->flags, pe_flag_have_status)) {
 734         crm_trace("Reusing previously calculated cluster status");
 735         pe__set_working_set_flags(data_set, flags);
 736         return;
 737     }
 738 
 739     if (data_set->localhost) {
 740         localhost_save = data_set->localhost;
 741     }
 742 
 743     CRM_ASSERT(cib != NULL);
 744     crm_trace("Calculating cluster status");
 745 
 746     
 747 
 748 
 749 
 750 
 751     set_working_set_defaults(data_set);
 752 
 753     if (localhost_save) {
 754         data_set->localhost = localhost_save;
 755     }
 756 
 757     pe__set_working_set_flags(data_set, flags);
 758     data_set->input = cib;
 759     cluster_status(data_set); 
 760 }
 761 
 762 
 763 
 764 
 765 
 766 
 767 
 768 
 769 
 770 void
 771 pcmk__schedule_actions(xmlNode *cib, unsigned long long flags,
     
 772                        pe_working_set_t *data_set)
 773 {
 774     unpack_cib(cib, flags, data_set);
 775     pcmk__set_allocation_methods(data_set);
 776     pcmk__apply_node_health(data_set);
 777     pcmk__unpack_constraints(data_set);
 778     if (pcmk_is_set(data_set->flags, pe_flag_check_config)) {
 779         return;
 780     }
 781 
 782     if (!pcmk_is_set(data_set->flags, pe_flag_quick_location) &&
 783          pcmk__is_daemon) {
 784         log_resource_details(data_set);
 785     }
 786 
 787     apply_node_criteria(data_set);
 788 
 789     if (pcmk_is_set(data_set->flags, pe_flag_quick_location)) {
 790         return;
 791     }
 792 
 793     pcmk__create_internal_constraints(data_set);
 794     pcmk__handle_rsc_config_changes(data_set);
 795     allocate_resources(data_set);
 796     schedule_resource_actions(data_set);
 797 
 798     
 799 
 800 
 801     pcmk__order_remote_connection_actions(data_set);
 802 
 803     schedule_fencing_and_shutdowns(data_set);
 804     pcmk__apply_orderings(data_set);
 805     log_all_actions(data_set);
 806     pcmk__create_graph(data_set);
 807 
 808     if (get_crm_log_level() == LOG_TRACE) {
 809         log_unrunnable_actions(data_set);
 810     }
 811 }