This source file includes following definitions.
- action_flags_for_ordering
 
- action_uuid_for_ordering
 
- action_for_ordering
 
- update
 
- update_action_for_ordering_flags
 
- pcmk__update_action_for_orderings
 
- is_primitive_action
 
- handle_asymmetric_ordering
 
- handle_restart_ordering
 
- pcmk__update_ordered_actions
 
- pcmk__log_action
 
- pcmk__new_shutdown_action
 
- add_op_digest_to_xml
 
- pcmk__create_history_xml
 
- pcmk__action_locks_rsc_to_node
 
- sort_action_id
 
- pcmk__deduplicate_action_inputs
 
- pcmk__output_actions
 
- task_for_digest
 
- only_sanitized_changed
 
- force_restart
 
- schedule_reload
 
- pcmk__check_action_config
 
- rsc_history_as_list
 
- process_rsc_history
 
- process_node_history
 
- pcmk__handle_rsc_config_changes
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <stdio.h>
  13 #include <sys/param.h>
  14 #include <glib.h>
  15 
  16 #include <crm/lrmd_internal.h>
  17 #include <crm/common/scheduler_internal.h>
  18 #include <pacemaker-internal.h>
  19 #include "libpacemaker_private.h"
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 static uint32_t
  32 action_flags_for_ordering(pcmk_action_t *action, const pcmk_node_t *node)
     
  33 {
  34     bool runnable = false;
  35     uint32_t flags;
  36 
  37     
  38     if (action->rsc == NULL) {
  39         return action->flags;
  40     }
  41 
  42     
  43 
  44 
  45 
  46     flags = action->rsc->cmds->action_flags(action, NULL);
  47     if ((node == NULL) || !pcmk__is_clone(action->rsc)) {
  48         return flags;
  49     }
  50 
  51     
  52 
  53 
  54     runnable = pcmk_is_set(flags, pcmk_action_runnable);
  55 
  56     
  57     flags = action->rsc->cmds->action_flags(action, node);
  58 
  59     
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67     if (runnable && !pcmk_is_set(flags, pcmk_action_runnable)) {
  68         pcmk__set_raw_action_flags(flags, action->rsc->id,
  69                                    pcmk_action_runnable);
  70     }
  71     return flags;
  72 }
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 static char *
  93 action_uuid_for_ordering(const char *first_uuid,
     
  94                          const pcmk_resource_t *first_rsc)
  95 {
  96     guint interval_ms = 0;
  97     char *uuid = NULL;
  98     char *rid = NULL;
  99     char *first_task_str = NULL;
 100     enum action_tasks first_task = pcmk_action_unspecified;
 101     enum action_tasks remapped_task = pcmk_action_unspecified;
 102 
 103     
 104     if ((strstr(first_uuid, PCMK_ACTION_NOTIFY) != NULL)
 105         || (first_rsc->variant < pcmk_rsc_variant_group)) {
 106         goto done;
 107     }
 108 
 109     
 110     CRM_ASSERT(parse_op_key(first_uuid, &rid, &first_task_str, &interval_ms));
 111     if (interval_ms > 0) {
 112         goto done;
 113     }
 114 
 115     first_task = pcmk_parse_action(first_task_str);
 116     switch (first_task) {
 117         case pcmk_action_stop:
 118         case pcmk_action_start:
 119         case pcmk_action_notify:
 120         case pcmk_action_promote:
 121         case pcmk_action_demote:
 122             remapped_task = first_task + 1;
 123             break;
 124         case pcmk_action_stopped:
 125         case pcmk_action_started:
 126         case pcmk_action_notified:
 127         case pcmk_action_promoted:
 128         case pcmk_action_demoted:
 129             remapped_task = first_task;
 130             break;
 131         case pcmk_action_monitor:
 132         case pcmk_action_shutdown:
 133         case pcmk_action_fence:
 134             break;
 135         default:
 136             crm_err("Unknown action '%s' in ordering", first_task_str);
 137             break;
 138     }
 139 
 140     if (remapped_task != pcmk_action_unspecified) {
 141         
 142 
 143 
 144         if (pcmk_is_set(first_rsc->flags, pcmk_rsc_notify)
 145             && (pcmk__is_clone(first_rsc) || pcmk__is_bundled(first_rsc))) {
 146             uuid = pcmk__notify_key(rid, "confirmed-post",
 147                                     pcmk_action_text(remapped_task));
 148         } else {
 149             uuid = pcmk__op_key(rid, pcmk_action_text(remapped_task), 0);
 150         }
 151         pcmk__rsc_trace(first_rsc,
 152                         "Remapped action UUID %s to %s for ordering purposes",
 153                         first_uuid, uuid);
 154     }
 155 
 156 done:
 157     free(first_task_str);
 158     free(rid);
 159     return (uuid != NULL)? uuid : pcmk__str_copy(first_uuid);
 160 }
 161 
 162 
 163 
 164 
 165 
 166 
 167 
 168 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 
 178 static pcmk_action_t *
 179 action_for_ordering(pcmk_action_t *action)
     
 180 {
 181     pcmk_action_t *result = action;
 182     pcmk_resource_t *rsc = action->rsc;
 183 
 184     if ((rsc != NULL) && (rsc->variant >= pcmk_rsc_variant_group)
 185         && (action->uuid != NULL)) {
 186         char *uuid = action_uuid_for_ordering(action->uuid, rsc);
 187 
 188         result = find_first_action(rsc->actions, uuid, NULL, NULL);
 189         if (result == NULL) {
 190             crm_warn("Not remapping %s to %s because %s does not have "
 191                      "remapped action", action->uuid, uuid, rsc->id);
 192             result = action;
 193         }
 194         free(uuid);
 195     }
 196     return result;
 197 }
 198 
 199 
 200 
 201 
 202 
 203 
 204 
 205 
 206 
 207 
 208 
 209 
 210 
 211 
 212 
 213 
 214 
 215 
 216 
 217 
 218 static inline uint32_t
 219 update(pcmk_resource_t *rsc, pcmk_action_t *first, pcmk_action_t *then,
     
 220        const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type,
 221        pcmk_scheduler_t *scheduler)
 222 {
 223     return rsc->cmds->update_ordered_actions(first, then, node, flags, filter,
 224                                              type, scheduler);
 225 }
 226 
 227 
 228 
 229 
 230 
 231 
 232 
 233 
 234 
 235 
 236 
 237 
 238 
 239 
 240 static uint32_t
 241 update_action_for_ordering_flags(pcmk_action_t *first, pcmk_action_t *then,
     
 242                                  uint32_t first_flags, uint32_t then_flags,
 243                                  pcmk__related_action_t *order,
 244                                  pcmk_scheduler_t *scheduler)
 245 {
 246     uint32_t changed = pcmk__updated_none;
 247 
 248     
 249 
 250 
 251 
 252 
 253     pcmk_node_t *node = then->node;
 254 
 255     if (pcmk_is_set(order->type, pcmk__ar_first_implies_same_node_then)) {
 256         
 257 
 258 
 259 
 260 
 261         pcmk__clear_relation_flags(order->type,
 262                                    pcmk__ar_first_implies_same_node_then);
 263         pcmk__set_relation_flags(order->type, pcmk__ar_first_implies_then);
 264         node = first->node;
 265         pcmk__rsc_trace(then->rsc,
 266                         "%s then %s: mapped "
 267                         "pcmk__ar_first_implies_same_node_then to "
 268                         "pcmk__ar_first_implies_then on %s",
 269                         first->uuid, then->uuid, pcmk__node_name(node));
 270     }
 271 
 272     if (pcmk_is_set(order->type, pcmk__ar_first_implies_then)) {
 273         if (then->rsc != NULL) {
 274             changed |= update(then->rsc, first, then, node,
 275                               first_flags & pcmk_action_optional,
 276                               pcmk_action_optional, pcmk__ar_first_implies_then,
 277                               scheduler);
 278         } else if (!pcmk_is_set(first_flags, pcmk_action_optional)
 279                    && pcmk_is_set(then->flags, pcmk_action_optional)) {
 280             pcmk__clear_action_flags(then, pcmk_action_optional);
 281             pcmk__set_updated_flags(changed, first, pcmk__updated_then);
 282         }
 283         pcmk__rsc_trace(then->rsc,
 284                         "%s then %s: %s after pcmk__ar_first_implies_then",
 285                         first->uuid, then->uuid,
 286                         (changed? "changed" : "unchanged"));
 287     }
 288 
 289     if (pcmk_is_set(order->type, pcmk__ar_intermediate_stop)
 290         && (then->rsc != NULL)) {
 291         enum pe_action_flags restart = pcmk_action_optional
 292                                        |pcmk_action_runnable;
 293 
 294         changed |= update(then->rsc, first, then, node, first_flags, restart,
 295                           pcmk__ar_intermediate_stop, scheduler);
 296         pcmk__rsc_trace(then->rsc,
 297                         "%s then %s: %s after pcmk__ar_intermediate_stop",
 298                         first->uuid, then->uuid,
 299                         (changed? "changed" : "unchanged"));
 300     }
 301 
 302     if (pcmk_is_set(order->type, pcmk__ar_then_implies_first)) {
 303         if (first->rsc != NULL) {
 304             changed |= update(first->rsc, first, then, node, first_flags,
 305                               pcmk_action_optional, pcmk__ar_then_implies_first,
 306                               scheduler);
 307         } else if (!pcmk_is_set(first_flags, pcmk_action_optional)
 308                    && pcmk_is_set(first->flags, pcmk_action_runnable)) {
 309             pcmk__clear_action_flags(first, pcmk_action_runnable);
 310             pcmk__set_updated_flags(changed, first, pcmk__updated_first);
 311         }
 312         pcmk__rsc_trace(then->rsc,
 313                         "%s then %s: %s after pcmk__ar_then_implies_first",
 314                         first->uuid, then->uuid,
 315                         (changed? "changed" : "unchanged"));
 316     }
 317 
 318     if (pcmk_is_set(order->type, pcmk__ar_promoted_then_implies_first)) {
 319         if (then->rsc != NULL) {
 320             changed |= update(then->rsc, first, then, node,
 321                               first_flags & pcmk_action_optional,
 322                               pcmk_action_optional,
 323                               pcmk__ar_promoted_then_implies_first, scheduler);
 324         }
 325         pcmk__rsc_trace(then->rsc,
 326                         "%s then %s: %s after "
 327                         "pcmk__ar_promoted_then_implies_first",
 328                         first->uuid, then->uuid,
 329                         (changed? "changed" : "unchanged"));
 330     }
 331 
 332     if (pcmk_is_set(order->type, pcmk__ar_min_runnable)) {
 333         if (then->rsc != NULL) {
 334             changed |= update(then->rsc, first, then, node, first_flags,
 335                               pcmk_action_runnable, pcmk__ar_min_runnable,
 336                               scheduler);
 337 
 338         } else if (pcmk_is_set(first_flags, pcmk_action_runnable)) {
 339             
 340             then->runnable_before++;
 341 
 342             
 343 
 344 
 345             if ((then->runnable_before >= then->required_runnable_before)
 346                 && !pcmk_is_set(then->flags, pcmk_action_runnable)) {
 347 
 348                 pcmk__set_action_flags(then, pcmk_action_runnable);
 349                 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
 350             }
 351         }
 352         pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_min_runnable",
 353                         first->uuid, then->uuid,
 354                         (changed? "changed" : "unchanged"));
 355     }
 356 
 357     if (pcmk_is_set(order->type, pcmk__ar_nested_remote_probe)
 358         && (then->rsc != NULL)) {
 359 
 360         if (!pcmk_is_set(first_flags, pcmk_action_runnable)
 361             && (first->rsc != NULL) && (first->rsc->running_on != NULL)) {
 362 
 363             pcmk__rsc_trace(then->rsc,
 364                             "%s then %s: ignoring because first is stopping",
 365                             first->uuid, then->uuid);
 366             order->type = (enum pe_ordering) pcmk__ar_none;
 367         } else {
 368             changed |= update(then->rsc, first, then, node, first_flags,
 369                               pcmk_action_runnable,
 370                               pcmk__ar_unrunnable_first_blocks, scheduler);
 371         }
 372         pcmk__rsc_trace(then->rsc,
 373                         "%s then %s: %s after pcmk__ar_nested_remote_probe",
 374                         first->uuid, then->uuid,
 375                         (changed? "changed" : "unchanged"));
 376     }
 377 
 378     if (pcmk_is_set(order->type, pcmk__ar_unrunnable_first_blocks)) {
 379         if (then->rsc != NULL) {
 380             changed |= update(then->rsc, first, then, node, first_flags,
 381                               pcmk_action_runnable,
 382                               pcmk__ar_unrunnable_first_blocks, scheduler);
 383 
 384         } else if (!pcmk_is_set(first_flags, pcmk_action_runnable)
 385                    && pcmk_is_set(then->flags, pcmk_action_runnable)) {
 386 
 387             pcmk__clear_action_flags(then, pcmk_action_runnable);
 388             pcmk__set_updated_flags(changed, first, pcmk__updated_then);
 389         }
 390         pcmk__rsc_trace(then->rsc,
 391                         "%s then %s: %s after pcmk__ar_unrunnable_first_blocks",
 392                         first->uuid, then->uuid,
 393                         (changed? "changed" : "unchanged"));
 394     }
 395 
 396     if (pcmk_is_set(order->type, pcmk__ar_unmigratable_then_blocks)) {
 397         if (then->rsc != NULL) {
 398             changed |= update(then->rsc, first, then, node, first_flags,
 399                               pcmk_action_optional,
 400                               pcmk__ar_unmigratable_then_blocks, scheduler);
 401         }
 402         pcmk__rsc_trace(then->rsc,
 403                         "%s then %s: %s after "
 404                         "pcmk__ar_unmigratable_then_blocks",
 405                         first->uuid, then->uuid,
 406                         (changed? "changed" : "unchanged"));
 407     }
 408 
 409     if (pcmk_is_set(order->type, pcmk__ar_first_else_then)) {
 410         if (then->rsc != NULL) {
 411             changed |= update(then->rsc, first, then, node, first_flags,
 412                               pcmk_action_optional, pcmk__ar_first_else_then,
 413                               scheduler);
 414         }
 415         pcmk__rsc_trace(then->rsc,
 416                         "%s then %s: %s after pcmk__ar_first_else_then",
 417                         first->uuid, then->uuid,
 418                         (changed? "changed" : "unchanged"));
 419     }
 420 
 421     if (pcmk_is_set(order->type, pcmk__ar_ordered)) {
 422         if (then->rsc != NULL) {
 423             changed |= update(then->rsc, first, then, node, first_flags,
 424                               pcmk_action_runnable, pcmk__ar_ordered,
 425                               scheduler);
 426         }
 427         pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_ordered",
 428                         first->uuid, then->uuid,
 429                         (changed? "changed" : "unchanged"));
 430     }
 431 
 432     if (pcmk_is_set(order->type, pcmk__ar_asymmetric)) {
 433         if (then->rsc != NULL) {
 434             changed |= update(then->rsc, first, then, node, first_flags,
 435                               pcmk_action_runnable, pcmk__ar_asymmetric,
 436                               scheduler);
 437         }
 438         pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_asymmetric",
 439                         first->uuid, then->uuid,
 440                         (changed? "changed" : "unchanged"));
 441     }
 442 
 443     if (pcmk_is_set(first->flags, pcmk_action_runnable)
 444         && pcmk_is_set(order->type, pcmk__ar_first_implies_then_graphed)
 445         && !pcmk_is_set(first_flags, pcmk_action_optional)) {
 446 
 447         pcmk__rsc_trace(then->rsc, "%s will be in graph because %s is required",
 448                         then->uuid, first->uuid);
 449         pcmk__set_action_flags(then, pcmk_action_always_in_graph);
 450         
 451     }
 452 
 453     if (pcmk_is_set(order->type, pcmk__ar_then_implies_first_graphed)
 454         && !pcmk_is_set(then_flags, pcmk_action_optional)) {
 455 
 456         pcmk__rsc_trace(then->rsc, "%s will be in graph because %s is required",
 457                         first->uuid, then->uuid);
 458         pcmk__set_action_flags(first, pcmk_action_always_in_graph);
 459         
 460     }
 461 
 462     if (pcmk_any_flags_set(order->type, pcmk__ar_first_implies_then
 463                                         |pcmk__ar_then_implies_first
 464                                         |pcmk__ar_intermediate_stop)
 465         && (first->rsc != NULL)
 466         && !pcmk_is_set(first->rsc->flags, pcmk_rsc_managed)
 467         && pcmk_is_set(first->rsc->flags, pcmk_rsc_blocked)
 468         && !pcmk_is_set(first->flags, pcmk_action_runnable)
 469         && pcmk__str_eq(first->task, PCMK_ACTION_STOP, pcmk__str_none)) {
 470 
 471         if (pcmk_is_set(then->flags, pcmk_action_runnable)) {
 472             pcmk__clear_action_flags(then, pcmk_action_runnable);
 473             pcmk__set_updated_flags(changed, first, pcmk__updated_then);
 474         }
 475         pcmk__rsc_trace(then->rsc,
 476                         "%s then %s: %s after checking whether first "
 477                         "is blocked, unmanaged, unrunnable stop",
 478                         first->uuid, then->uuid,
 479                         (changed? "changed" : "unchanged"));
 480     }
 481 
 482     return changed;
 483 }
 484 
 485 
 486 
 487 #define action_type_str(flags) \
 488     (pcmk_is_set((flags), pcmk_action_pseudo)? "pseudo-action" : "action")
 489 
 490 #define action_optional_str(flags) \
 491     (pcmk_is_set((flags), pcmk_action_optional)? "optional" : "required")
 492 
 493 #define action_runnable_str(flags) \
 494     (pcmk_is_set((flags), pcmk_action_runnable)? "runnable" : "unrunnable")
 495 
 496 #define action_node_str(a) \
 497     (((a)->node == NULL)? "no node" : (a)->node->details->uname)
 498 
 499 
 500 
 501 
 502 
 503 
 504 
 505 
 506 void
 507 pcmk__update_action_for_orderings(pcmk_action_t *then,
     
 508                                   pcmk_scheduler_t *scheduler)
 509 {
 510     GList *lpc = NULL;
 511     uint32_t changed = pcmk__updated_none;
 512     int last_flags = then->flags;
 513 
 514     pcmk__rsc_trace(then->rsc, "Updating %s %s (%s %s) on %s",
 515                     action_type_str(then->flags), then->uuid,
 516                     action_optional_str(then->flags),
 517                     action_runnable_str(then->flags), action_node_str(then));
 518 
 519     if (pcmk_is_set(then->flags, pcmk_action_min_runnable)) {
 520         
 521 
 522 
 523 
 524 
 525         then->runnable_before = 0;
 526 
 527         if (then->required_runnable_before == 0) {
 528             
 529 
 530 
 531 
 532             then->required_runnable_before = 1;
 533         }
 534 
 535         
 536 
 537 
 538 
 539         pcmk__clear_action_flags(then, pcmk_action_runnable);
 540     }
 541 
 542     for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
 543         pcmk__related_action_t *other = lpc->data;
 544         pcmk_action_t *first = other->action;
 545 
 546         pcmk_node_t *then_node = then->node;
 547         pcmk_node_t *first_node = first->node;
 548 
 549         if ((first->rsc != NULL)
 550             && pcmk__is_group(first->rsc)
 551             && pcmk__str_eq(first->task, PCMK_ACTION_START, pcmk__str_none)) {
 552 
 553             first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
 554             if (first_node != NULL) {
 555                 pcmk__rsc_trace(first->rsc, "Found %s for 'first' %s",
 556                                 pcmk__node_name(first_node), first->uuid);
 557             }
 558         }
 559 
 560         if (pcmk__is_group(then->rsc)
 561             && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)) {
 562 
 563             then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
 564             if (then_node != NULL) {
 565                 pcmk__rsc_trace(then->rsc, "Found %s for 'then' %s",
 566                                 pcmk__node_name(then_node), then->uuid);
 567             }
 568         }
 569 
 570         
 571         if (pcmk_is_set(other->type, pcmk__ar_if_on_same_node)
 572             && (first_node != NULL) && (then_node != NULL)
 573             && !pcmk__same_node(first_node, then_node)) {
 574 
 575             pcmk__rsc_trace(then->rsc,
 576                             "Disabled ordering %s on %s then %s on %s: "
 577                             "not same node",
 578                             other->action->uuid, pcmk__node_name(first_node),
 579                             then->uuid, pcmk__node_name(then_node));
 580             other->type = (enum pe_ordering) pcmk__ar_none;
 581             continue;
 582         }
 583 
 584         pcmk__clear_updated_flags(changed, then, pcmk__updated_first);
 585 
 586         if ((first->rsc != NULL)
 587             && pcmk_is_set(other->type, pcmk__ar_then_cancels_first)
 588             && !pcmk_is_set(then->flags, pcmk_action_optional)) {
 589 
 590             
 591 
 592 
 593             pcmk__set_action_flags(other->action, pcmk_action_optional);
 594             if (!strcmp(first->task, PCMK_ACTION_RELOAD_AGENT)) {
 595                 pcmk__clear_rsc_flags(first->rsc, pcmk_rsc_reload);
 596             }
 597         }
 598 
 599         if ((first->rsc != NULL) && (then->rsc != NULL)
 600             && (first->rsc != then->rsc) && !is_parent(then->rsc, first->rsc)) {
 601             first = action_for_ordering(first);
 602         }
 603         if (first != other->action) {
 604             pcmk__rsc_trace(then->rsc, "Ordering %s after %s instead of %s",
 605                             then->uuid, first->uuid, other->action->uuid);
 606         }
 607 
 608         pcmk__rsc_trace(then->rsc,
 609                         "%s (%#.6x) then %s (%#.6x): type=%#.6x node=%s",
 610                         first->uuid, first->flags, then->uuid, then->flags,
 611                         other->type, action_node_str(first));
 612 
 613         if (first == other->action) {
 614             
 615 
 616 
 617 
 618             uint32_t first_flags, then_flags;
 619 
 620             first_flags = action_flags_for_ordering(first, then_node);
 621             then_flags = action_flags_for_ordering(then, first_node);
 622 
 623             changed |= update_action_for_ordering_flags(first, then,
 624                                                         first_flags, then_flags,
 625                                                         other, scheduler);
 626 
 627             
 628 
 629 
 630         } else if (order_actions(first, then, other->type)) {
 631             
 632 
 633 
 634             pcmk__set_updated_flags(changed, then, pcmk__updated_then);
 635             pcmk__rsc_trace(then->rsc,
 636                             "Disabled ordering %s then %s in favor of %s "
 637                             "then %s",
 638                             other->action->uuid, then->uuid, first->uuid,
 639                             then->uuid);
 640             other->type = (enum pe_ordering) pcmk__ar_none;
 641         }
 642 
 643 
 644         if (pcmk_is_set(changed, pcmk__updated_first)) {
 645             crm_trace("Re-processing %s and its 'after' actions "
 646                       "because it changed", first->uuid);
 647             for (GList *lpc2 = first->actions_after; lpc2 != NULL;
 648                  lpc2 = lpc2->next) {
 649                 pcmk__related_action_t *other = lpc2->data;
 650 
 651                 pcmk__update_action_for_orderings(other->action, scheduler);
 652             }
 653             pcmk__update_action_for_orderings(first, scheduler);
 654         }
 655     }
 656 
 657     if (pcmk_is_set(then->flags, pcmk_action_min_runnable)) {
 658         if (last_flags == then->flags) {
 659             pcmk__clear_updated_flags(changed, then, pcmk__updated_then);
 660         } else {
 661             pcmk__set_updated_flags(changed, then, pcmk__updated_then);
 662         }
 663     }
 664 
 665     if (pcmk_is_set(changed, pcmk__updated_then)) {
 666         crm_trace("Re-processing %s and its 'after' actions because it changed",
 667                   then->uuid);
 668         if (pcmk_is_set(last_flags, pcmk_action_runnable)
 669             && !pcmk_is_set(then->flags, pcmk_action_runnable)) {
 670             pcmk__block_colocation_dependents(then);
 671         }
 672         pcmk__update_action_for_orderings(then, scheduler);
 673         for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
 674             pcmk__related_action_t *other = lpc->data;
 675 
 676             pcmk__update_action_for_orderings(other->action, scheduler);
 677         }
 678     }
 679 }
 680 
 681 static inline bool
 682 is_primitive_action(const pcmk_action_t *action)
     
 683 {
 684     return (action != NULL) && pcmk__is_primitive(action->rsc);
 685 }
 686 
 687 
 688 
 689 
 690 
 691 
 692 
 693 
 694 
 695 #define clear_action_flag_because(action, flag, reason) do {                \
 696         if (pcmk_is_set((action)->flags, (flag))) {                         \
 697             pcmk__clear_action_flags(action, flag);                         \
 698             if ((action)->rsc != (reason)->rsc) {                           \
 699                 char *reason_text = pe__action2reason((reason), (flag));    \
 700                 pe_action_set_reason((action), reason_text, false);         \
 701                 free(reason_text);                                          \
 702             }                                                               \
 703         }                                                                   \
 704     } while (0)
 705 
 706 
 707 
 708 
 709 
 710 
 711 
 712 
 713 
 714 
 715 
 716 static void
 717 handle_asymmetric_ordering(const pcmk_action_t *first, pcmk_action_t *then)
     
 718 {
 719     
 720 
 721 
 722     if ((then->rsc == NULL)
 723         || pcmk_is_set(first->flags, pcmk_action_runnable)) {
 724         return;
 725     }
 726 
 727     
 728     if (pcmk_is_set(then->flags, pcmk_action_optional)) {
 729         enum rsc_role_e then_rsc_role = then->rsc->fns->state(then->rsc, TRUE);
 730 
 731         if ((then_rsc_role == pcmk_role_stopped)
 732             && pcmk__str_eq(then->task, PCMK_ACTION_STOP, pcmk__str_none)) {
 733             
 734 
 735 
 736             return;
 737         } else if ((then_rsc_role >= pcmk_role_started)
 738             && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)
 739             && pe__rsc_running_on_only(then->rsc, then->node)) {
 740             
 741 
 742 
 743             return;
 744         }
 745     }
 746 
 747     
 748     clear_action_flag_because(then, pcmk_action_optional, first);
 749     clear_action_flag_because(then, pcmk_action_runnable, first);
 750 }
 751 
 752 
 753 
 754 
 755 
 756 
 757 
 758 
 759 
 760 
 761 
 762 
 763 static void
 764 handle_restart_ordering(pcmk_action_t *first, pcmk_action_t *then,
     
 765                         uint32_t filter)
 766 {
 767     const char *reason = NULL;
 768 
 769     CRM_ASSERT(is_primitive_action(first));
 770     CRM_ASSERT(is_primitive_action(then));
 771 
 772     
 773 
 774     
 775     if (pcmk_is_set(filter, pcmk_action_optional)
 776         && !pcmk_is_set(then->flags, pcmk_action_optional)) {
 777         reason = "restart";
 778     }
 779 
 780     
 781 
 782 
 783     if (pcmk_is_set(filter, pcmk_action_runnable)
 784         && !pcmk_is_set(then->flags, pcmk_action_runnable)
 785         && pcmk_is_set(then->rsc->flags, pcmk_rsc_managed)
 786         && (first->rsc == then->rsc)) {
 787         reason = "stop";
 788     }
 789 
 790     if (reason == NULL) {
 791         return;
 792     }
 793 
 794     pcmk__rsc_trace(first->rsc, "Handling %s -> %s for %s",
 795                     first->uuid, then->uuid, reason);
 796 
 797     
 798     if (pcmk_is_set(first->flags, pcmk_action_runnable)) {
 799         clear_action_flag_because(first, pcmk_action_optional, then);
 800     }
 801 
 802     
 803     if (!pcmk_is_set(then->flags, pcmk_action_optional)) {
 804         clear_action_flag_because(first, pcmk_action_optional, then);
 805     }
 806 
 807     
 808     if (!pcmk_is_set(then->flags, pcmk_action_migratable)) {
 809         clear_action_flag_because(first, pcmk_action_migratable, then);
 810     }
 811 
 812     
 813     if (!pcmk_is_set(first->flags, pcmk_action_optional)
 814         && !pcmk_is_set(first->flags, pcmk_action_runnable)) {
 815         clear_action_flag_because(then, pcmk_action_runnable, first);
 816     }
 817 }
 818 
 819 
 820 
 821 
 822 
 823 
 824 
 825 
 826 
 827 
 828 
 829 
 830 
 831 
 832 
 833 
 834 
 835 
 836 
 837 
 838 
 839 
 840 
 841 uint32_t
 842 pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then,
     
 843                              const pcmk_node_t *node, uint32_t flags,
 844                              uint32_t filter, uint32_t type,
 845                              pcmk_scheduler_t *scheduler)
 846 {
 847     uint32_t changed = pcmk__updated_none;
 848     uint32_t then_flags = 0U;
 849     uint32_t first_flags = 0U;
 850 
 851     CRM_ASSERT((first != NULL) && (then != NULL) && (scheduler != NULL));
 852 
 853     then_flags = then->flags;
 854     first_flags = first->flags;
 855     if (pcmk_is_set(type, pcmk__ar_asymmetric)) {
 856         handle_asymmetric_ordering(first, then);
 857     }
 858 
 859     if (pcmk_is_set(type, pcmk__ar_then_implies_first)
 860         && !pcmk_is_set(then_flags, pcmk_action_optional)) {
 861         
 862 
 863         if (pcmk_is_set(filter, pcmk_action_optional)
 864             && !pcmk_is_set(flags, pcmk_action_optional)
 865             && pcmk_is_set(first_flags, pcmk_action_optional)) {
 866             clear_action_flag_because(first, pcmk_action_optional, then);
 867         }
 868 
 869         if (pcmk_is_set(flags, pcmk_action_migratable)
 870             && !pcmk_is_set(then->flags, pcmk_action_migratable)) {
 871             clear_action_flag_because(first, pcmk_action_migratable, then);
 872         }
 873     }
 874 
 875     if (pcmk_is_set(type, pcmk__ar_promoted_then_implies_first)
 876         && (then->rsc != NULL) && (then->rsc->role == pcmk_role_promoted)
 877         && pcmk_is_set(filter, pcmk_action_optional)
 878         && !pcmk_is_set(then->flags, pcmk_action_optional)) {
 879 
 880         clear_action_flag_because(first, pcmk_action_optional, then);
 881 
 882         if (pcmk_is_set(first->flags, pcmk_action_migratable)
 883             && !pcmk_is_set(then->flags, pcmk_action_migratable)) {
 884             clear_action_flag_because(first, pcmk_action_migratable, then);
 885         }
 886     }
 887 
 888     if (pcmk_is_set(type, pcmk__ar_unmigratable_then_blocks)
 889         && pcmk_is_set(filter, pcmk_action_optional)) {
 890 
 891         if (!pcmk_all_flags_set(then->flags, pcmk_action_migratable
 892                                              |pcmk_action_runnable)) {
 893             clear_action_flag_because(first, pcmk_action_runnable, then);
 894         }
 895 
 896         if (!pcmk_is_set(then->flags, pcmk_action_optional)) {
 897             clear_action_flag_because(first, pcmk_action_optional, then);
 898         }
 899     }
 900 
 901     if (pcmk_is_set(type, pcmk__ar_first_else_then)
 902         && pcmk_is_set(filter, pcmk_action_optional)
 903         && !pcmk_is_set(first->flags, pcmk_action_runnable)) {
 904 
 905         clear_action_flag_because(then, pcmk_action_migratable, first);
 906         pcmk__clear_action_flags(then, pcmk_action_pseudo);
 907     }
 908 
 909     if (pcmk_is_set(type, pcmk__ar_unrunnable_first_blocks)
 910         && pcmk_is_set(filter, pcmk_action_runnable)
 911         && pcmk_is_set(then->flags, pcmk_action_runnable)
 912         && !pcmk_is_set(flags, pcmk_action_runnable)) {
 913 
 914         clear_action_flag_because(then, pcmk_action_runnable, first);
 915         clear_action_flag_because(then, pcmk_action_migratable, first);
 916     }
 917 
 918     if (pcmk_is_set(type, pcmk__ar_first_implies_then)
 919         && pcmk_is_set(filter, pcmk_action_optional)
 920         && pcmk_is_set(then->flags, pcmk_action_optional)
 921         && !pcmk_is_set(flags, pcmk_action_optional)
 922         && !pcmk_is_set(first->flags, pcmk_action_migratable)) {
 923 
 924         clear_action_flag_because(then, pcmk_action_optional, first);
 925     }
 926 
 927     if (pcmk_is_set(type, pcmk__ar_intermediate_stop)) {
 928         handle_restart_ordering(first, then, filter);
 929     }
 930 
 931     if (then_flags != then->flags) {
 932         pcmk__set_updated_flags(changed, first, pcmk__updated_then);
 933         pcmk__rsc_trace(then->rsc,
 934                         "%s on %s: flags are now %#.6x (was %#.6x) "
 935                         "because of 'first' %s (%#.6x)",
 936                         then->uuid, pcmk__node_name(then->node),
 937                         then->flags, then_flags, first->uuid, first->flags);
 938 
 939         if ((then->rsc != NULL) && (then->rsc->parent != NULL)) {
 940             
 941             pcmk__update_action_for_orderings(then, scheduler);
 942         }
 943     }
 944 
 945     if (first_flags != first->flags) {
 946         pcmk__set_updated_flags(changed, first, pcmk__updated_first);
 947         pcmk__rsc_trace(first->rsc,
 948                         "%s on %s: flags are now %#.6x (was %#.6x) "
 949                         "because of 'then' %s (%#.6x)",
 950                         first->uuid, pcmk__node_name(first->node),
 951                         first->flags, first_flags, then->uuid, then->flags);
 952     }
 953 
 954     return changed;
 955 }
 956 
 957 
 958 
 959 
 960 
 961 
 962 
 963 
 964 
 965 void
 966 pcmk__log_action(const char *pre_text, const pcmk_action_t *action,
     
 967                  bool details)
 968 {
 969     const char *node_uname = NULL;
 970     const char *node_uuid = NULL;
 971     const char *desc = NULL;
 972 
 973     CRM_CHECK(action != NULL, return);
 974 
 975     if (!pcmk_is_set(action->flags, pcmk_action_pseudo)) {
 976         if (action->node != NULL) {
 977             node_uname = action->node->details->uname;
 978             node_uuid = action->node->details->id;
 979         } else {
 980             node_uname = "<none>";
 981         }
 982     }
 983 
 984     switch (pcmk_parse_action(action->task)) {
 985         case pcmk_action_fence:
 986         case pcmk_action_shutdown:
 987             if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
 988                 desc = "Pseudo ";
 989             } else if (pcmk_is_set(action->flags, pcmk_action_optional)) {
 990                 desc = "Optional ";
 991             } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
 992                 desc = "!!Non-Startable!! ";
 993             } else {
 994                desc = "(Provisional) ";
 995             }
 996             crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
 997                       ((pre_text == NULL)? "" : pre_text),
 998                       ((pre_text == NULL)? "" : ": "),
 999                       desc, action->id, action->uuid,
1000                       (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1001                       (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1002                       (node_uuid? ")" : ""));
1003             break;
1004         default:
1005             if (pcmk_is_set(action->flags, pcmk_action_optional)) {
1006                 desc = "Optional ";
1007             } else if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
1008                 desc = "Pseudo ";
1009             } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
1010                 desc = "!!Non-Startable!! ";
1011             } else {
1012                desc = "(Provisional) ";
1013             }
1014             crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
1015                       ((pre_text == NULL)? "" : pre_text),
1016                       ((pre_text == NULL)? "" : ": "),
1017                       desc, action->id, action->uuid,
1018                       (action->rsc? action->rsc->id : "<none>"),
1019                       (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1020                       (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1021                       (node_uuid? ")" : ""));
1022             break;
1023     }
1024 
1025     if (details) {
1026         const GList *iter = NULL;
1027         const pcmk__related_action_t *other = NULL;
1028 
1029         crm_trace("\t\t====== Preceding Actions");
1030         for (iter = action->actions_before; iter != NULL; iter = iter->next) {
1031             other = (const pcmk__related_action_t *) iter->data;
1032             pcmk__log_action("\t\t", other->action, false);
1033         }
1034         crm_trace("\t\t====== Subsequent Actions");
1035         for (iter = action->actions_after; iter != NULL; iter = iter->next) {
1036             other = (const pcmk__related_action_t *) iter->data;
1037             pcmk__log_action("\t\t", other->action, false);
1038         }
1039         crm_trace("\t\t====== End");
1040 
1041     } else {
1042         crm_trace("\t\t(before=%d, after=%d)",
1043                   g_list_length(action->actions_before),
1044                   g_list_length(action->actions_after));
1045     }
1046 }
1047 
1048 
1049 
1050 
1051 
1052 
1053 
1054 
1055 
1056 pcmk_action_t *
1057 pcmk__new_shutdown_action(pcmk_node_t *node)
     
1058 {
1059     char *shutdown_id = NULL;
1060     pcmk_action_t *shutdown_op = NULL;
1061 
1062     CRM_ASSERT(node != NULL);
1063 
1064     shutdown_id = crm_strdup_printf("%s-%s", PCMK_ACTION_DO_SHUTDOWN,
1065                                     node->details->uname);
1066 
1067     shutdown_op = custom_action(NULL, shutdown_id, PCMK_ACTION_DO_SHUTDOWN,
1068                                 node, FALSE, node->details->data_set);
1069 
1070     pcmk__order_stops_before_shutdown(node, shutdown_op);
1071     pcmk__insert_meta(shutdown_op, PCMK__META_OP_NO_WAIT, PCMK_VALUE_TRUE);
1072     return shutdown_op;
1073 }
1074 
1075 
1076 
1077 
1078 
1079 
1080 
1081 
1082 
1083 
1084 
1085 
1086 static void
1087 add_op_digest_to_xml(const lrmd_event_data_t *op, xmlNode *update)
     
1088 {
1089     char *digest = NULL;
1090     xmlNode *args_xml = NULL;
1091 
1092     if (op->params == NULL) {
1093         return;
1094     }
1095     args_xml = pcmk__xe_create(NULL, PCMK_XE_PARAMETERS);
1096     g_hash_table_foreach(op->params, hash2field, args_xml);
1097     pcmk__filter_op_for_digest(args_xml);
1098     digest = calculate_operation_digest(args_xml, NULL);
1099     crm_xml_add(update, PCMK__XA_OP_DIGEST, digest);
1100     free_xml(args_xml);
1101     free(digest);
1102 }
1103 
1104 #define FAKE_TE_ID     "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
1105 
1106 
1107 
1108 
1109 
1110 
1111 
1112 
1113 
1114 
1115 
1116 
1117 
1118 
1119 xmlNode *
1120 pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *op,
     
1121                          const char *caller_version, int target_rc,
1122                          const char *node, const char *origin)
1123 {
1124     char *key = NULL;
1125     char *magic = NULL;
1126     char *op_id = NULL;
1127     char *op_id_additional = NULL;
1128     char *local_user_data = NULL;
1129     const char *exit_reason = NULL;
1130 
1131     xmlNode *xml_op = NULL;
1132     const char *task = NULL;
1133 
1134     CRM_CHECK(op != NULL, return NULL);
1135     crm_trace("Creating history XML for %s-interval %s action for %s on %s "
1136               "(DC version: %s, origin: %s)",
1137               pcmk__readable_interval(op->interval_ms), op->op_type, op->rsc_id,
1138               ((node == NULL)? "no node" : node), caller_version, origin);
1139 
1140     task = op->op_type;
1141 
1142     
1143 
1144 
1145 
1146 
1147 
1148 
1149 
1150 
1151     if (pcmk__str_any_of(task, PCMK_ACTION_RELOAD, PCMK_ACTION_RELOAD_AGENT,
1152                          NULL)) {
1153         if (op->op_status == PCMK_EXEC_DONE) {
1154             task = PCMK_ACTION_START;
1155         } else {
1156             task = PCMK_ACTION_MONITOR;
1157         }
1158     }
1159 
1160     key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
1161     if (pcmk__str_eq(task, PCMK_ACTION_NOTIFY, pcmk__str_none)) {
1162         const char *n_type = crm_meta_value(op->params, "notify_type");
1163         const char *n_task = crm_meta_value(op->params, "notify_operation");
1164 
1165         CRM_LOG_ASSERT(n_type != NULL);
1166         CRM_LOG_ASSERT(n_task != NULL);
1167         op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
1168 
1169         if (op->op_status != PCMK_EXEC_PENDING) {
1170             
1171 
1172 
1173 
1174 
1175             lrmd__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE, NULL);
1176         }
1177 
1178     
1179 
1180 
1181     } else if (pcmk__str_any_of(op->op_type, PCMK_ACTION_MIGRATE_TO,
1182                                 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1183         op_id = strdup(key);
1184 
1185     } else if (did_rsc_op_fail(op, target_rc)) {
1186         op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
1187         if (op->interval_ms == 0) {
1188             
1189 
1190 
1191             op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
1192         }
1193         exit_reason = op->exit_reason;
1194 
1195     } else if (op->interval_ms > 0) {
1196         op_id = strdup(key);
1197 
1198     } else {
1199         op_id = pcmk__op_key(op->rsc_id, "last", 0);
1200     }
1201 
1202   again:
1203     xml_op = pcmk__xe_first_child(parent, PCMK__XE_LRM_RSC_OP, PCMK_XA_ID,
1204                                   op_id);
1205     if (xml_op == NULL) {
1206         xml_op = pcmk__xe_create(parent, PCMK__XE_LRM_RSC_OP);
1207     }
1208 
1209     if (op->user_data == NULL) {
1210         crm_debug("Generating fake transition key for: " PCMK__OP_FMT
1211                   " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
1212                   op->call_id, origin);
1213         local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
1214                                                FAKE_TE_ID);
1215         op->user_data = local_user_data;
1216     }
1217 
1218     if (magic == NULL) {
1219         magic = crm_strdup_printf("%d:%d;%s", op->op_status, op->rc,
1220                                   (const char *) op->user_data);
1221     }
1222 
1223     crm_xml_add(xml_op, PCMK_XA_ID, op_id);
1224     crm_xml_add(xml_op, PCMK__XA_OPERATION_KEY, key);
1225     crm_xml_add(xml_op, PCMK_XA_OPERATION, task);
1226     crm_xml_add(xml_op, PCMK_XA_CRM_DEBUG_ORIGIN, origin);
1227     crm_xml_add(xml_op, PCMK_XA_CRM_FEATURE_SET, caller_version);
1228     crm_xml_add(xml_op, PCMK__XA_TRANSITION_KEY, op->user_data);
1229     crm_xml_add(xml_op, PCMK__XA_TRANSITION_MAGIC, magic);
1230     crm_xml_add(xml_op, PCMK_XA_EXIT_REASON, pcmk__s(exit_reason, ""));
1231     crm_xml_add(xml_op, PCMK__META_ON_NODE, node); 
1232 
1233     crm_xml_add_int(xml_op, PCMK__XA_CALL_ID, op->call_id);
1234     crm_xml_add_int(xml_op, PCMK__XA_RC_CODE, op->rc);
1235     crm_xml_add_int(xml_op, PCMK__XA_OP_STATUS, op->op_status);
1236     crm_xml_add_ms(xml_op, PCMK_META_INTERVAL, op->interval_ms);
1237 
1238     if (compare_version("2.1", caller_version) <= 0) {
1239         if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
1240             crm_trace("Timing data (" PCMK__OP_FMT
1241                       "): last=%u change=%u exec=%u queue=%u",
1242                       op->rsc_id, op->op_type, op->interval_ms,
1243                       op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
1244 
1245             if ((op->interval_ms != 0) && (op->t_rcchange != 0)) {
1246                 
1247                 crm_xml_add_ll(xml_op, PCMK_XA_LAST_RC_CHANGE,
1248                                (long long) op->t_rcchange);
1249             } else {
1250                 crm_xml_add_ll(xml_op, PCMK_XA_LAST_RC_CHANGE,
1251                                (long long) op->t_run);
1252             }
1253 
1254             crm_xml_add_int(xml_op, PCMK_XA_EXEC_TIME, op->exec_time);
1255             crm_xml_add_int(xml_op, PCMK_XA_QUEUE_TIME, op->queue_time);
1256         }
1257     }
1258 
1259     if (pcmk__str_any_of(op->op_type, PCMK_ACTION_MIGRATE_TO,
1260                          PCMK_ACTION_MIGRATE_FROM, NULL)) {
1261         
1262 
1263 
1264         const char *name = PCMK__META_MIGRATE_SOURCE;
1265 
1266         crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1267 
1268         name = PCMK__META_MIGRATE_TARGET;
1269         crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1270     }
1271 
1272     add_op_digest_to_xml(op, xml_op);
1273 
1274     if (op_id_additional) {
1275         free(op_id);
1276         op_id = op_id_additional;
1277         op_id_additional = NULL;
1278         goto again;
1279     }
1280 
1281     if (local_user_data) {
1282         free(local_user_data);
1283         op->user_data = NULL;
1284     }
1285     free(magic);
1286     free(op_id);
1287     free(key);
1288     return xml_op;
1289 }
1290 
1291 
1292 
1293 
1294 
1295 
1296 
1297 
1298 
1299 
1300 
1301 
1302 
1303 
1304 
1305 bool
1306 pcmk__action_locks_rsc_to_node(const pcmk_action_t *action)
     
1307 {
1308     
1309     if ((action == NULL) || (action->rsc == NULL)
1310         || !pcmk__same_node(action->node, action->rsc->lock_node)) {
1311         return false;
1312     }
1313 
1314     
1315 
1316 
1317     if (action->node->details->shutdown && (action->task != NULL)
1318         && (strcmp(action->task, PCMK_ACTION_STOP) != 0)) {
1319         return false;
1320     }
1321 
1322     return true;
1323 }
1324 
1325 
1326 static gint
1327 sort_action_id(gconstpointer a, gconstpointer b)
     
1328 {
1329     const pcmk__related_action_t *action_wrapper2 = a;
1330     const pcmk__related_action_t *action_wrapper1 = b;
1331 
1332     if (a == NULL) {
1333         return 1;
1334     }
1335     if (b == NULL) {
1336         return -1;
1337     }
1338     if (action_wrapper1->action->id < action_wrapper2->action->id) {
1339         return 1;
1340     }
1341     if (action_wrapper1->action->id > action_wrapper2->action->id) {
1342         return -1;
1343     }
1344     return 0;
1345 }
1346 
1347 
1348 
1349 
1350 
1351 
1352 
1353 void
1354 pcmk__deduplicate_action_inputs(pcmk_action_t *action)
     
1355 {
1356     GList *item = NULL;
1357     GList *next = NULL;
1358     pcmk__related_action_t *last_input = NULL;
1359 
1360     action->actions_before = g_list_sort(action->actions_before,
1361                                          sort_action_id);
1362     for (item = action->actions_before; item != NULL; item = next) {
1363         pcmk__related_action_t *input = item->data;
1364 
1365         next = item->next;
1366         if ((last_input != NULL)
1367             && (input->action->id == last_input->action->id)) {
1368             crm_trace("Input %s (%d) duplicate skipped for action %s (%d)",
1369                       input->action->uuid, input->action->id,
1370                       action->uuid, action->id);
1371 
1372             
1373 
1374 
1375 
1376             last_input->type |= input->type;
1377             if (input->state == pe_link_dumped) {
1378                 last_input->state = pe_link_dumped;
1379             }
1380 
1381             free(item->data);
1382             action->actions_before = g_list_delete_link(action->actions_before,
1383                                                         item);
1384         } else {
1385             last_input = input;
1386             input->state = pe_link_not_dumped;
1387         }
1388     }
1389 }
1390 
1391 
1392 
1393 
1394 
1395 
1396 
1397 void
1398 pcmk__output_actions(pcmk_scheduler_t *scheduler)
     
1399 {
1400     pcmk__output_t *out = scheduler->priv;
1401 
1402     
1403     for (GList *iter = scheduler->actions; iter != NULL; iter = iter->next) {
1404         char *node_name = NULL;
1405         char *task = NULL;
1406         pcmk_action_t *action = (pcmk_action_t *) iter->data;
1407 
1408         if (action->rsc != NULL) {
1409             continue; 
1410 
1411         } else if (pcmk_is_set(action->flags, pcmk_action_optional)) {
1412             continue; 
1413         }
1414 
1415         if (pcmk__str_eq(action->task, PCMK_ACTION_DO_SHUTDOWN,
1416                          pcmk__str_none)) {
1417             task = strdup("Shutdown");
1418 
1419         } else if (pcmk__str_eq(action->task, PCMK_ACTION_STONITH,
1420                                 pcmk__str_none)) {
1421             const char *op = g_hash_table_lookup(action->meta,
1422                                                  PCMK__META_STONITH_ACTION);
1423 
1424             task = crm_strdup_printf("Fence (%s)", op);
1425 
1426         } else {
1427             continue; 
1428         }
1429 
1430         if (pcmk__is_guest_or_bundle_node(action->node)) {
1431             const pcmk_resource_t *remote = action->node->details->remote_rsc;
1432 
1433             node_name = crm_strdup_printf("%s (resource: %s)",
1434                                           pcmk__node_name(action->node),
1435                                           remote->container->id);
1436         } else if (action->node != NULL) {
1437             node_name = crm_strdup_printf("%s", pcmk__node_name(action->node));
1438         }
1439 
1440         out->message(out, "node-action", task, node_name, action->reason);
1441 
1442         free(node_name);
1443         free(task);
1444     }
1445 
1446     
1447     for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
1448         pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1449 
1450         rsc->cmds->output_actions(rsc);
1451     }
1452 }
1453 
1454 
1455 
1456 
1457 
1458 
1459 
1460 
1461 
1462 
1463 static const char *
1464 task_for_digest(const char *task, guint interval_ms)
     
1465 {
1466     
1467 
1468 
1469     if ((interval_ms == 0)
1470         && pcmk__str_any_of(task, PCMK_ACTION_MONITOR, PCMK_ACTION_MIGRATE_FROM,
1471                             PCMK_ACTION_PROMOTE, NULL)) {
1472         task = PCMK_ACTION_START;
1473     }
1474     return task;
1475 }
1476 
1477 
1478 
1479 
1480 
1481 
1482 
1483 
1484 
1485 
1486 
1487 
1488 
1489 
1490 
1491 
1492 
1493 
1494 static bool
1495 only_sanitized_changed(const xmlNode *xml_op,
     
1496                        const pcmk__op_digest_t *digest_data,
1497                        const pcmk_scheduler_t *scheduler)
1498 {
1499     const char *digest_secure = NULL;
1500 
1501     if (!pcmk_is_set(scheduler->flags, pcmk_sched_sanitized)) {
1502         
1503         return false;
1504     }
1505 
1506     digest_secure = crm_element_value(xml_op, PCMK__XA_OP_SECURE_DIGEST);
1507 
1508     return (digest_data->rc != pcmk__digest_match) && (digest_secure != NULL)
1509            && (digest_data->digest_secure_calc != NULL)
1510            && (strcmp(digest_data->digest_secure_calc, digest_secure) == 0);
1511 }
1512 
1513 
1514 
1515 
1516 
1517 
1518 
1519 
1520 
1521 
1522 static void
1523 force_restart(pcmk_resource_t *rsc, const char *task, guint interval_ms,
     
1524               pcmk_node_t *node)
1525 {
1526     char *key = pcmk__op_key(rsc->id, task, interval_ms);
1527     pcmk_action_t *required = custom_action(rsc, key, task, NULL, FALSE,
1528                                             rsc->cluster);
1529 
1530     pe_action_set_reason(required, "resource definition change", true);
1531     trigger_unfencing(rsc, node, "Device parameters changed", NULL,
1532                       rsc->cluster);
1533 }
1534 
1535 
1536 
1537 
1538 
1539 
1540 
1541 
1542 static void
1543 schedule_reload(gpointer data, gpointer user_data)
     
1544 {
1545     pcmk_resource_t *rsc = data;
1546     const pcmk_node_t *node = user_data;
1547     pcmk_action_t *reload = NULL;
1548 
1549     
1550     if (rsc->variant > pcmk_rsc_variant_primitive) {
1551         g_list_foreach(rsc->children, schedule_reload, user_data);
1552         return;
1553     }
1554 
1555     
1556     if ((node == NULL)
1557         || !pcmk_is_set(rsc->flags, pcmk_rsc_managed)
1558         || pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
1559         pcmk__rsc_trace(rsc, "Skip reload of %s:%s%s %s",
1560                         rsc->id,
1561                         pcmk_is_set(rsc->flags, pcmk_rsc_managed)? "" : " unmanaged",
1562                         pcmk_is_set(rsc->flags, pcmk_rsc_failed)? " failed" : "",
1563                         (node == NULL)? "inactive" : node->details->uname);
1564         return;
1565     }
1566 
1567     
1568 
1569 
1570     if (pcmk_is_set(rsc->flags, pcmk_rsc_start_pending)) {
1571         pcmk__rsc_trace(rsc,
1572                         "%s: preventing agent reload because start pending",
1573                         rsc->id);
1574         custom_action(rsc, stop_key(rsc), PCMK_ACTION_STOP, node, FALSE,
1575                       rsc->cluster);
1576         return;
1577     }
1578 
1579     
1580     pcmk__set_rsc_flags(rsc, pcmk_rsc_reload);
1581     reload = custom_action(rsc, reload_key(rsc), PCMK_ACTION_RELOAD_AGENT, node,
1582                            FALSE, rsc->cluster);
1583     pe_action_set_reason(reload, "resource definition change", FALSE);
1584 
1585     
1586     pcmk__new_ordering(NULL, NULL, reload, rsc, stop_key(rsc), NULL,
1587                        pcmk__ar_ordered|pcmk__ar_then_cancels_first,
1588                        rsc->cluster);
1589     pcmk__new_ordering(NULL, NULL, reload, rsc, demote_key(rsc), NULL,
1590                        pcmk__ar_ordered|pcmk__ar_then_cancels_first,
1591                        rsc->cluster);
1592 }
1593 
1594 
1595 
1596 
1597 
1598 
1599 
1600 
1601 
1602 
1603 
1604 
1605 
1606 
1607 
1608 bool
1609 pcmk__check_action_config(pcmk_resource_t *rsc, pcmk_node_t *node,
     
1610                           const xmlNode *xml_op)
1611 {
1612     guint interval_ms = 0;
1613     const char *task = NULL;
1614     const pcmk__op_digest_t *digest_data = NULL;
1615 
1616     CRM_CHECK((rsc != NULL) && (node != NULL) && (xml_op != NULL),
1617               return false);
1618 
1619     task = crm_element_value(xml_op, PCMK_XA_OPERATION);
1620     CRM_CHECK(task != NULL, return false);
1621 
1622     crm_element_value_ms(xml_op, PCMK_META_INTERVAL, &interval_ms);
1623 
1624     
1625     if (interval_ms > 0) {
1626         if (pcmk__find_action_config(rsc, task, interval_ms, false) != NULL) {
1627             pcmk__rsc_trace(rsc,
1628                             "%s-interval %s for %s on %s is in configuration",
1629                             pcmk__readable_interval(interval_ms), task, rsc->id,
1630                             pcmk__node_name(node));
1631         } else if (pcmk_is_set(rsc->cluster->flags,
1632                                pcmk_sched_cancel_removed_actions)) {
1633             pcmk__schedule_cancel(rsc,
1634                                   crm_element_value(xml_op, PCMK__XA_CALL_ID),
1635                                   task, interval_ms, node, "orphan");
1636             return true;
1637         } else {
1638             pcmk__rsc_debug(rsc, "%s-interval %s for %s on %s is orphaned",
1639                             pcmk__readable_interval(interval_ms), task, rsc->id,
1640                             pcmk__node_name(node));
1641             return true;
1642         }
1643     }
1644 
1645     crm_trace("Checking %s-interval %s for %s on %s for configuration changes",
1646               pcmk__readable_interval(interval_ms), task, rsc->id,
1647               pcmk__node_name(node));
1648     task = task_for_digest(task, interval_ms);
1649     digest_data = rsc_action_digest_cmp(rsc, xml_op, node, rsc->cluster);
1650 
1651     if (only_sanitized_changed(xml_op, digest_data, rsc->cluster)) {
1652         if (!pcmk__is_daemon && (rsc->cluster->priv != NULL)) {
1653             pcmk__output_t *out = rsc->cluster->priv;
1654 
1655             out->info(out,
1656                       "Only 'private' parameters to %s-interval %s for %s "
1657                       "on %s changed: %s",
1658                       pcmk__readable_interval(interval_ms), task, rsc->id,
1659                       pcmk__node_name(node),
1660                       crm_element_value(xml_op, PCMK__XA_TRANSITION_MAGIC));
1661         }
1662         return false;
1663     }
1664 
1665     switch (digest_data->rc) {
1666         case pcmk__digest_restart:
1667             crm_log_xml_debug(digest_data->params_restart, "params:restart");
1668             force_restart(rsc, task, interval_ms, node);
1669             return true;
1670 
1671         case pcmk__digest_unknown:
1672         case pcmk__digest_mismatch:
1673             
1674 
1675             if (interval_ms > 0) {
1676                 
1677 
1678 
1679 
1680                 crm_log_xml_debug(digest_data->params_all, "params:reschedule");
1681                 pcmk__reschedule_recurring(rsc, task, interval_ms, node);
1682 
1683             } else if (crm_element_value(xml_op,
1684                                          PCMK__XA_OP_RESTART_DIGEST) != NULL) {
1685                 
1686                 trigger_unfencing(rsc, node,
1687                                   "Device parameters changed (reload)", NULL,
1688                                   rsc->cluster);
1689                 crm_log_xml_debug(digest_data->params_all, "params:reload");
1690                 schedule_reload((gpointer) rsc, (gpointer) node);
1691 
1692             } else {
1693                 pcmk__rsc_trace(rsc,
1694                                 "Restarting %s "
1695                                 "because agent doesn't support reload",
1696                                 rsc->id);
1697                 crm_log_xml_debug(digest_data->params_restart,
1698                                   "params:restart");
1699                 force_restart(rsc, task, interval_ms, node);
1700             }
1701             return true;
1702 
1703         default:
1704             break;
1705     }
1706     return false;
1707 }
1708 
1709 
1710 
1711 
1712 
1713 
1714 
1715 
1716 
1717 static GList *
1718 rsc_history_as_list(const xmlNode *rsc_entry, int *start_index, int *stop_index)
     
1719 {
1720     GList *ops = NULL;
1721 
1722     for (xmlNode *rsc_op = pcmk__xe_first_child(rsc_entry, PCMK__XE_LRM_RSC_OP,
1723                                                 NULL, NULL);
1724          rsc_op != NULL; rsc_op = pcmk__xe_next_same(rsc_op)) {
1725 
1726         ops = g_list_prepend(ops, rsc_op);
1727     }
1728     ops = g_list_sort(ops, sort_op_by_callid);
1729     calculate_active_ops(ops, start_index, stop_index);
1730     return ops;
1731 }
1732 
1733 
1734 
1735 
1736 
1737 
1738 
1739 
1740 
1741 
1742 
1743 
1744 
1745 
1746 
1747 static void
1748 process_rsc_history(const xmlNode *rsc_entry, pcmk_resource_t *rsc,
     
1749                     pcmk_node_t *node)
1750 {
1751     int offset = -1;
1752     int stop_index = 0;
1753     int start_index = 0;
1754     GList *sorted_op_list = NULL;
1755 
1756     if (pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
1757         if (pcmk__is_anonymous_clone(pe__const_top_resource(rsc, false))) {
1758             pcmk__rsc_trace(rsc,
1759                             "Skipping configuration check "
1760                             "for orphaned clone instance %s",
1761                             rsc->id);
1762         } else {
1763             pcmk__rsc_trace(rsc,
1764                             "Skipping configuration check and scheduling "
1765                             "clean-up for orphaned resource %s", rsc->id);
1766             pcmk__schedule_cleanup(rsc, node, false);
1767         }
1768         return;
1769     }
1770 
1771     if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
1772         if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, false)) {
1773             pcmk__schedule_cleanup(rsc, node, false);
1774         }
1775         pcmk__rsc_trace(rsc,
1776                         "Skipping configuration check for %s "
1777                         "because no longer active on %s",
1778                         rsc->id, pcmk__node_name(node));
1779         return;
1780     }
1781 
1782     pcmk__rsc_trace(rsc, "Checking for configuration changes for %s on %s",
1783                     rsc->id, pcmk__node_name(node));
1784 
1785     if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, true)) {
1786         pcmk__schedule_cleanup(rsc, node, false);
1787     }
1788 
1789     sorted_op_list = rsc_history_as_list(rsc_entry, &start_index, &stop_index);
1790     if (start_index < stop_index) {
1791         return; 
1792     }
1793 
1794     for (GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
1795         xmlNode *rsc_op = (xmlNode *) iter->data;
1796         const char *task = NULL;
1797         guint interval_ms = 0;
1798 
1799         if (++offset < start_index) {
1800             
1801             continue;
1802         }
1803 
1804         task = crm_element_value(rsc_op, PCMK_XA_OPERATION);
1805         crm_element_value_ms(rsc_op, PCMK_META_INTERVAL, &interval_ms);
1806 
1807         if ((interval_ms > 0)
1808             && (pcmk_is_set(rsc->flags, pcmk_rsc_maintenance)
1809                 || node->details->maintenance)) {
1810             
1811             pcmk__schedule_cancel(rsc,
1812                                   crm_element_value(rsc_op, PCMK__XA_CALL_ID),
1813                                   task, interval_ms, node, "maintenance mode");
1814 
1815         } else if ((interval_ms > 0)
1816                    || pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
1817                                            PCMK_ACTION_START,
1818                                            PCMK_ACTION_PROMOTE,
1819                                            PCMK_ACTION_MIGRATE_FROM, NULL)) {
1820             
1821 
1822 
1823 
1824             if (pe__bundle_needs_remote_name(rsc)) {
1825                 
1826 
1827 
1828 
1829 
1830 
1831 
1832                 pe__add_param_check(rsc_op, rsc, node, pcmk__check_active,
1833                                     rsc->cluster);
1834 
1835             } else if (pcmk__check_action_config(rsc, node, rsc_op)
1836                        && (pe_get_failcount(node, rsc, NULL, pcmk__fc_effective,
1837                                             NULL) != 0)) {
1838                 pe__clear_failcount(rsc, node, "action definition changed",
1839                                     rsc->cluster);
1840             }
1841         }
1842     }
1843     g_list_free(sorted_op_list);
1844 }
1845 
1846 
1847 
1848 
1849 
1850 
1851 
1852 
1853 
1854 
1855 
1856 
1857 
1858 
1859 static void
1860 process_node_history(pcmk_node_t *node, const xmlNode *lrm_rscs)
     
1861 {
1862     crm_trace("Processing node history for %s", pcmk__node_name(node));
1863     for (const xmlNode *rsc_entry = pcmk__xe_first_child(lrm_rscs,
1864                                                          PCMK__XE_LRM_RESOURCE,
1865                                                          NULL, NULL);
1866          rsc_entry != NULL; rsc_entry = pcmk__xe_next_same(rsc_entry)) {
1867 
1868         if (rsc_entry->children != NULL) {
1869             GList *result = pcmk__rscs_matching_id(pcmk__xe_id(rsc_entry),
1870                                                    node->details->data_set);
1871 
1872             for (GList *iter = result; iter != NULL; iter = iter->next) {
1873                 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1874 
1875                 if (pcmk__is_primitive(rsc)) {
1876                     process_rsc_history(rsc_entry, rsc, node);
1877                 }
1878             }
1879             g_list_free(result);
1880         }
1881     }
1882 }
1883 
1884 
1885 #define XPATH_NODE_HISTORY "/" PCMK_XE_CIB "/" PCMK_XE_STATUS   \
1886                            "/" PCMK__XE_NODE_STATE              \
1887                            "[@" PCMK_XA_UNAME "='%s']"          \
1888                            "/" PCMK__XE_LRM "/" PCMK__XE_LRM_RESOURCES
1889 
1890 
1891 
1892 
1893 
1894 
1895 
1896 
1897 
1898 
1899 
1900 
1901 
1902 void
1903 pcmk__handle_rsc_config_changes(pcmk_scheduler_t *scheduler)
     
1904 {
1905     crm_trace("Check resource and action configuration for changes");
1906 
1907     
1908 
1909 
1910 
1911     for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
1912         pcmk_node_t *node = (pcmk_node_t *) iter->data;
1913 
1914         
1915 
1916 
1917 
1918         if (node->details->maintenance
1919             || pcmk__node_available(node, false, false)) {
1920 
1921             char *xpath = NULL;
1922             xmlNode *history = NULL;
1923 
1924             xpath = crm_strdup_printf(XPATH_NODE_HISTORY, node->details->uname);
1925             history = get_xpath_object(xpath, scheduler->input, LOG_NEVER);
1926             free(xpath);
1927 
1928             process_node_history(node, history);
1929         }
1930     }
1931 }