This source file includes following definitions.
- child_promoting_constraints
- child_demoting_constraints
- check_promotable_actions
- apply_promoted_location
- guest_location
- node_to_be_promoted_on
- sort_promotable_instance
- promotion_order
- filter_anonymous_instance
- lookup_promotion_score
- promotion_score
- pcmk__add_promotion_scores
- set_role_unpromoted
- set_role_promoted
- pcmk__set_instance_roles
- create_promotable_actions
- promote_demote_constraints
- promotable_constraints
- node_hash_update_one
- promotable_colocation_rh
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/msg_xml.h>
13 #include <pacemaker-internal.h>
14
15 #include "libpacemaker_private.h"
16
17 #define VARIANT_CLONE 1
18 #include <lib/pengine/variant.h>
19
20 extern gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set);
21
22 extern bool pcmk__is_daemon;
23
24 static void
25 child_promoting_constraints(clone_variant_data_t * clone_data, enum pe_ordering type,
26 pe_resource_t * rsc, pe_resource_t * child, pe_resource_t * last,
27 pe_working_set_t * data_set)
28 {
29 if (child == NULL) {
30 if (clone_data->ordered && last != NULL) {
31 pe_rsc_trace(rsc, "Ordered version (last node)");
32
33 pcmk__order_resource_actions(last, RSC_PROMOTE, rsc, RSC_PROMOTED,
34 type, data_set);
35 }
36 return;
37 }
38
39
40 pcmk__order_resource_actions(child, RSC_PROMOTE, rsc, RSC_PROMOTED, type,
41 data_set);
42
43
44 pcmk__order_resource_actions(rsc, RSC_PROMOTE, child, RSC_PROMOTE, type,
45 data_set);
46
47 if (clone_data->ordered) {
48 pe_rsc_trace(rsc, "Ordered version");
49 if (last == NULL) {
50
51 last = rsc;
52
53 }
54
55 pcmk__order_starts(last, child, type, data_set);
56 pcmk__order_resource_actions(last, RSC_PROMOTE, child, RSC_PROMOTE,
57 type, data_set);
58
59 } else {
60 pe_rsc_trace(rsc, "Un-ordered version");
61 }
62 }
63
64 static void
65 child_demoting_constraints(clone_variant_data_t * clone_data, enum pe_ordering type,
66 pe_resource_t * rsc, pe_resource_t * child, pe_resource_t * last,
67 pe_working_set_t * data_set)
68 {
69 if (child == NULL) {
70 if (clone_data->ordered && last != NULL) {
71 pe_rsc_trace(rsc, "Ordered version (last node)");
72
73 pcmk__order_resource_actions(rsc, RSC_DEMOTE, last, RSC_DEMOTE,
74 pe_order_optional, data_set);
75 }
76 return;
77 }
78
79
80 pcmk__order_resource_actions(child, RSC_DEMOTE, rsc, RSC_DEMOTED,
81 pe_order_implies_then_printed, data_set);
82
83
84 pcmk__order_resource_actions(rsc, RSC_DEMOTE, child, RSC_DEMOTE,
85 pe_order_implies_first_printed, data_set);
86
87 if (clone_data->ordered && last != NULL) {
88 pe_rsc_trace(rsc, "Ordered version");
89
90
91 pcmk__order_resource_actions(child, RSC_DEMOTE, last, RSC_DEMOTE, type,
92 data_set);
93
94 } else if (clone_data->ordered) {
95 pe_rsc_trace(rsc, "Ordered version (1st node)");
96
97 pcmk__order_resource_actions(child, RSC_DEMOTE, rsc, RSC_DEMOTED, type,
98 data_set);
99
100 } else {
101 pe_rsc_trace(rsc, "Un-ordered version");
102 }
103 }
104
105 static void
106 check_promotable_actions(pe_resource_t *rsc, gboolean *demoting,
107 gboolean *promoting)
108 {
109 GList *gIter = NULL;
110
111 if (rsc->children) {
112 gIter = rsc->children;
113 for (; gIter != NULL; gIter = gIter->next) {
114 pe_resource_t *child = (pe_resource_t *) gIter->data;
115
116 check_promotable_actions(child, demoting, promoting);
117 }
118 return;
119 }
120
121 CRM_ASSERT(demoting != NULL);
122 CRM_ASSERT(promoting != NULL);
123
124 gIter = rsc->actions;
125 for (; gIter != NULL; gIter = gIter->next) {
126 pe_action_t *action = (pe_action_t *) gIter->data;
127
128 if (*promoting && *demoting) {
129 return;
130
131 } else if (pcmk_is_set(action->flags, pe_action_optional)) {
132 continue;
133
134 } else if (pcmk__str_eq(RSC_DEMOTE, action->task, pcmk__str_casei)) {
135 *demoting = TRUE;
136
137 } else if (pcmk__str_eq(RSC_PROMOTE, action->task, pcmk__str_casei)) {
138 *promoting = TRUE;
139 }
140 }
141 }
142
143 static void
144 apply_promoted_location(pe_resource_t *child, GList *location_constraints,
145 pe_node_t *chosen)
146 {
147 CRM_CHECK(child && chosen, return);
148 for (GList *gIter = location_constraints; gIter; gIter = gIter->next) {
149 pe_node_t *cons_node = NULL;
150 pe__location_t *cons = gIter->data;
151
152 if (cons->role_filter == RSC_ROLE_PROMOTED) {
153 pe_rsc_trace(child, "Applying %s to %s", cons->id, child->id);
154 cons_node = pe_find_node_id(cons->node_list_rh, chosen->details->id);
155 }
156 if (cons_node != NULL) {
157 int new_priority = pcmk__add_scores(child->priority,
158 cons_node->weight);
159
160 pe_rsc_trace(child, "\t%s[%s]: %d -> %d (%d)",
161 child->id, cons_node->details->uname, child->priority,
162 new_priority, cons_node->weight);
163 child->priority = new_priority;
164 }
165 }
166 }
167
168 static pe_node_t *
169 guest_location(pe_node_t *guest_node)
170 {
171 pe_resource_t *guest = guest_node->details->remote_rsc->container;
172
173 return guest->fns->location(guest, NULL, FALSE);
174 }
175
176 static pe_node_t *
177 node_to_be_promoted_on(pe_resource_t *rsc)
178 {
179 pe_node_t *node = NULL;
180 pe_node_t *local_node = NULL;
181 pe_resource_t *parent = uber_parent(rsc);
182 clone_variant_data_t *clone_data = NULL;
183
184 #if 0
185 enum rsc_role_e role = RSC_ROLE_UNKNOWN;
186
187 role = rsc->fns->state(rsc, FALSE);
188 crm_info("%s role: %s", rsc->id, role2text(role));
189 #endif
190
191 if (rsc->children) {
192 GList *gIter = rsc->children;
193
194 for (; gIter != NULL; gIter = gIter->next) {
195 pe_resource_t *child = (pe_resource_t *) gIter->data;
196
197 if (node_to_be_promoted_on(child) == NULL) {
198 pe_rsc_trace(rsc, "Child %s of %s can't be promoted", child->id, rsc->id);
199 return NULL;
200 }
201 }
202 }
203
204 node = rsc->fns->location(rsc, NULL, FALSE);
205 if (node == NULL) {
206 pe_rsc_trace(rsc, "%s cannot be promoted: not allocated", rsc->id);
207 return NULL;
208
209 } else if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
210 if (rsc->fns->state(rsc, TRUE) == RSC_ROLE_PROMOTED) {
211 crm_notice("Forcing unmanaged instance %s to remain promoted on %s",
212 rsc->id, node->details->uname);
213
214 } else {
215 return NULL;
216 }
217
218 } else if (rsc->priority < 0) {
219 pe_rsc_trace(rsc, "%s cannot be promoted: preference: %d",
220 rsc->id, rsc->priority);
221 return NULL;
222
223 } else if (!pcmk__node_available(node)) {
224 crm_trace("Node can't run any resources: %s", node->details->uname);
225 return NULL;
226
227
228
229
230
231 } else if (pe__is_guest_node(node) && (guest_location(node) == NULL)) {
232 pe_rsc_trace(rsc, "%s cannot be promoted: guest %s not allocated",
233 rsc->id, node->details->remote_rsc->container->id);
234 return NULL;
235 }
236
237 get_clone_variant_data(clone_data, parent);
238 local_node = pe_hash_table_lookup(parent->allowed_nodes, node->details->id);
239
240 if (local_node == NULL) {
241 crm_err("%s cannot run on %s: node not allowed", rsc->id, node->details->uname);
242 return NULL;
243
244 } else if ((local_node->count < clone_data->promoted_node_max)
245 || !pcmk_is_set(rsc->flags, pe_rsc_managed)) {
246 return local_node;
247
248 } else {
249 pe_rsc_trace(rsc, "%s cannot be promoted on %s: node full",
250 rsc->id, node->details->uname);
251 }
252
253 return NULL;
254 }
255
256 static gint
257 sort_promotable_instance(gconstpointer a, gconstpointer b, gpointer data_set)
258 {
259 int rc;
260 enum rsc_role_e role1 = RSC_ROLE_UNKNOWN;
261 enum rsc_role_e role2 = RSC_ROLE_UNKNOWN;
262
263 const pe_resource_t *resource1 = (const pe_resource_t *)a;
264 const pe_resource_t *resource2 = (const pe_resource_t *)b;
265
266 CRM_ASSERT(resource1 != NULL);
267 CRM_ASSERT(resource2 != NULL);
268
269 role1 = resource1->fns->state(resource1, TRUE);
270 role2 = resource2->fns->state(resource2, TRUE);
271
272 rc = sort_rsc_index(a, b);
273 if (rc != 0) {
274 crm_trace("%s %c %s (index)", resource1->id, rc < 0 ? '<' : '>', resource2->id);
275 return rc;
276 }
277
278 if (role1 > role2) {
279 crm_trace("%s %c %s (role)", resource1->id, '<', resource2->id);
280 return -1;
281
282 } else if (role1 < role2) {
283 crm_trace("%s %c %s (role)", resource1->id, '>', resource2->id);
284 return 1;
285 }
286
287 return sort_clone_instance(a, b, data_set);
288 }
289
290 static void
291 promotion_order(pe_resource_t *rsc, pe_working_set_t *data_set)
292 {
293 GList *gIter = NULL;
294 pe_node_t *node = NULL;
295 pe_node_t *chosen = NULL;
296 clone_variant_data_t *clone_data = NULL;
297 char score[33];
298 size_t len = sizeof(score);
299
300 get_clone_variant_data(clone_data, rsc);
301
302 if (clone_data->added_promoted_constraints) {
303 return;
304 }
305 clone_data->added_promoted_constraints = true;
306 pe_rsc_trace(rsc, "Merging weights for %s", rsc->id);
307 pe__set_resource_flags(rsc, pe_rsc_merging);
308
309 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
310 pe_resource_t *child = (pe_resource_t *) gIter->data;
311
312 pe_rsc_trace(rsc, "Sort index: %s = %d", child->id, child->sort_index);
313 }
314 pe__show_node_weights(true, rsc, "Before", rsc->allowed_nodes, data_set);
315
316 gIter = rsc->children;
317 for (; gIter != NULL; gIter = gIter->next) {
318 pe_resource_t *child = (pe_resource_t *) gIter->data;
319
320 chosen = child->fns->location(child, NULL, FALSE);
321 if (chosen == NULL || child->sort_index < 0) {
322 pe_rsc_trace(rsc, "Skipping %s", child->id);
323 continue;
324 }
325
326 node = (pe_node_t *) pe_hash_table_lookup(rsc->allowed_nodes, chosen->details->id);
327 CRM_ASSERT(node != NULL);
328
329 score2char_stack(child->sort_index, score, len);
330 pe_rsc_trace(rsc, "Adding %s to %s from %s", score,
331 node->details->uname, child->id);
332 node->weight = pcmk__add_scores(child->sort_index, node->weight);
333 }
334
335 pe__show_node_weights(true, rsc, "Middle", rsc->allowed_nodes, data_set);
336
337 gIter = rsc->rsc_cons;
338 for (; gIter != NULL; gIter = gIter->next) {
339 pcmk__colocation_t *constraint = (pcmk__colocation_t *) gIter->data;
340
341
342
343
344 if (constraint->dependent_role == RSC_ROLE_PROMOTED) {
345 enum pe_weights flags = constraint->score == INFINITY ? 0 : pe_weights_rollback;
346
347 pe_rsc_trace(rsc, "RHS: %s with %s: %d",
348 constraint->dependent->id, constraint->primary->id,
349 constraint->score);
350 rsc->allowed_nodes = constraint->primary->cmds->merge_weights(
351 constraint->primary, rsc->id, rsc->allowed_nodes,
352 constraint->node_attribute,
353 constraint->score / (float) INFINITY, flags);
354 }
355 }
356
357 gIter = rsc->rsc_cons_lhs;
358 for (; gIter != NULL; gIter = gIter->next) {
359 pcmk__colocation_t *constraint = (pcmk__colocation_t *) gIter->data;
360
361 if (!pcmk__colocation_has_influence(constraint, NULL)) {
362 continue;
363 }
364
365
366
367
368 if (constraint->primary_role == RSC_ROLE_PROMOTED) {
369 pe_rsc_trace(rsc, "LHS: %s with %s: %d",
370 constraint->dependent->id, constraint->primary->id,
371 constraint->score);
372 rsc->allowed_nodes = constraint->dependent->cmds->merge_weights(
373 constraint->dependent, rsc->id, rsc->allowed_nodes,
374 constraint->node_attribute,
375 constraint->score / (float) INFINITY,
376 pe_weights_rollback|pe_weights_positive);
377 }
378 }
379
380 gIter = rsc->rsc_tickets;
381 for (; gIter != NULL; gIter = gIter->next) {
382 rsc_ticket_t *rsc_ticket = (rsc_ticket_t *) gIter->data;
383
384 if ((rsc_ticket->role_lh == RSC_ROLE_PROMOTED)
385 && (rsc_ticket->ticket->granted == FALSE || rsc_ticket->ticket->standby)) {
386 resource_location(rsc, NULL, -INFINITY, "__stateful_without_ticket__", data_set);
387 }
388 }
389
390 pe__show_node_weights(true, rsc, "After", rsc->allowed_nodes, data_set);
391
392
393
394 gIter = rsc->children;
395 for (; gIter != NULL; gIter = gIter->next) {
396 pe_resource_t *child = (pe_resource_t *) gIter->data;
397
398 chosen = child->fns->location(child, NULL, FALSE);
399 if (!pcmk_is_set(child->flags, pe_rsc_managed)
400 && (child->next_role == RSC_ROLE_PROMOTED)) {
401 child->sort_index = INFINITY;
402
403 } else if (chosen == NULL || child->sort_index < 0) {
404 pe_rsc_trace(rsc, "%s: %d", child->id, child->sort_index);
405
406 } else {
407 node = (pe_node_t *) pe_hash_table_lookup(rsc->allowed_nodes, chosen->details->id);
408 CRM_ASSERT(node != NULL);
409
410 child->sort_index = node->weight;
411 }
412 pe_rsc_trace(rsc, "Set sort index: %s = %d", child->id, child->sort_index);
413 }
414
415 rsc->children = g_list_sort_with_data(rsc->children,
416 sort_promotable_instance, data_set);
417 pe__clear_resource_flags(rsc, pe_rsc_merging);
418 }
419
420 static gboolean
421 filter_anonymous_instance(pe_resource_t *rsc, const pe_node_t *node)
422 {
423 GList *rIter = NULL;
424 char *key = clone_strip(rsc->id);
425 pe_resource_t *parent = uber_parent(rsc);
426
427 for (rIter = parent->children; rIter; rIter = rIter->next) {
428
429
430
431 pe_resource_t *child = rIter->data;
432 pe_resource_t *active = parent->fns->find_rsc(child, key, node, pe_find_clone|pe_find_current);
433
434 if(rsc == active) {
435 pe_rsc_trace(rsc, "Found %s for %s active on %s: done", active->id, key, node->details->uname);
436 free(key);
437 return TRUE;
438 } else if(active) {
439 pe_rsc_trace(rsc, "Found %s for %s on %s: not %s", active->id, key, node->details->uname, rsc->id);
440 free(key);
441 return FALSE;
442 } else {
443 pe_rsc_trace(rsc, "%s on %s: not active", key, node->details->uname);
444 }
445 }
446
447 for (rIter = parent->children; rIter; rIter = rIter->next) {
448 pe_resource_t *child = rIter->data;
449
450
451
452
453
454
455
456
457
458 rsc = parent->fns->find_rsc(child, key, NULL, pe_find_clone);
459 CRM_LOG_ASSERT(rsc);
460 if(rsc) {
461 pe_rsc_trace(rsc, "Checking %s for %s on %s", rsc->id, key, node->details->uname);
462 if (g_hash_table_lookup(rsc->known_on, node->details->id)) {
463 free(key);
464 return TRUE;
465 }
466 }
467 }
468 free(key);
469 return FALSE;
470 }
471
472 static const char *
473 lookup_promotion_score(pe_resource_t *rsc, const pe_node_t *node, const char *name)
474 {
475 const char *attr_value = NULL;
476
477 if (node && name) {
478 char *attr_name = pcmk_promotion_score_name(name);
479
480 attr_value = pe_node_attribute_calculated(node, attr_name, rsc);
481 free(attr_name);
482 }
483 return attr_value;
484 }
485
486 static int
487 promotion_score(pe_resource_t *rsc, const pe_node_t *node, int not_set_value)
488 {
489 char *name = rsc->id;
490 const char *attr_value = NULL;
491 int score = not_set_value;
492 pe_node_t *match = NULL;
493
494 CRM_CHECK(node != NULL, return not_set_value);
495
496 if (rsc->children) {
497 GList *gIter = rsc->children;
498
499 for (; gIter != NULL; gIter = gIter->next) {
500 pe_resource_t *child = (pe_resource_t *) gIter->data;
501 int c_score = promotion_score(child, node, not_set_value);
502
503 if (score == not_set_value) {
504 score = c_score;
505 } else {
506 score += c_score;
507 }
508 }
509 return score;
510 }
511
512 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)
513 && filter_anonymous_instance(rsc, node)) {
514
515 pe_rsc_trace(rsc, "Anonymous clone %s is allowed on %s", rsc->id, node->details->uname);
516
517 } else if (rsc->running_on || g_hash_table_size(rsc->known_on)) {
518
519
520
521
522
523
524 pe_node_t *known = pe_hash_table_lookup(rsc->known_on, node->details->id);
525
526 match = pe_find_node_id(rsc->running_on, node->details->id);
527 if ((match == NULL) && (known == NULL)) {
528 pe_rsc_trace(rsc, "skipping %s (aka. %s) promotion score on %s because inactive",
529 rsc->id, rsc->clone_name, node->details->uname);
530 return score;
531 }
532 }
533
534 match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
535 if (match == NULL) {
536 return score;
537
538 } else if (match->weight < 0) {
539 pe_rsc_trace(rsc, "%s on %s has score: %d - ignoring",
540 rsc->id, match->details->uname, match->weight);
541 return score;
542 }
543
544 if (rsc->clone_name) {
545
546
547
548 name = rsc->clone_name;
549 }
550
551 attr_value = lookup_promotion_score(rsc, node, name);
552 pe_rsc_trace(rsc, "promotion score for %s on %s = %s",
553 name, node->details->uname, crm_str(attr_value));
554
555 if ((attr_value == NULL) && !pcmk_is_set(rsc->flags, pe_rsc_unique)) {
556
557
558
559
560 name = clone_strip(rsc->id);
561 if (strcmp(rsc->id, name)) {
562 attr_value = lookup_promotion_score(rsc, node, name);
563 pe_rsc_trace(rsc, "stripped promotion score for %s on %s = %s",
564 name, node->details->uname, crm_str(attr_value));
565 }
566 free(name);
567 }
568
569 if (attr_value != NULL) {
570 score = char2score(attr_value);
571 }
572
573 return score;
574 }
575
576 void
577 pcmk__add_promotion_scores(pe_resource_t *rsc)
578 {
579 int score, new_score;
580 GList *gIter = rsc->children;
581 clone_variant_data_t *clone_data = NULL;
582
583 get_clone_variant_data(clone_data, rsc);
584
585 if (clone_data->added_promotion_scores) {
586
587 return;
588 }
589
590 clone_data->added_promotion_scores = true;
591
592 for (; gIter != NULL; gIter = gIter->next) {
593 GHashTableIter iter;
594 pe_node_t *node = NULL;
595 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
596
597 g_hash_table_iter_init(&iter, child_rsc->allowed_nodes);
598 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
599 if (!pcmk__node_available(node)) {
600
601
602
603 continue;
604 }
605
606 score = promotion_score(child_rsc, node, 0);
607 if (score > 0) {
608 new_score = pcmk__add_scores(node->weight, score);
609 if (new_score != node->weight) {
610 pe_rsc_trace(rsc, "\t%s: Updating preference for %s (%d->%d)",
611 child_rsc->id, node->details->uname, node->weight, new_score);
612 node->weight = new_score;
613 }
614 }
615
616 new_score = QB_MAX(child_rsc->priority, score);
617 if (new_score != child_rsc->priority) {
618 pe_rsc_trace(rsc, "\t%s: Updating priority (%d->%d)",
619 child_rsc->id, child_rsc->priority, new_score);
620 child_rsc->priority = new_score;
621 }
622 }
623 }
624 }
625
626 static void
627 set_role_unpromoted(pe_resource_t *rsc, bool current)
628 {
629 GList *gIter = rsc->children;
630
631 if (current) {
632 if (rsc->role == RSC_ROLE_STARTED) {
633 rsc->role = RSC_ROLE_UNPROMOTED;
634 }
635
636 } else {
637 GList *allocated = NULL;
638
639 rsc->fns->location(rsc, &allocated, FALSE);
640 pe__set_next_role(rsc, (allocated? RSC_ROLE_UNPROMOTED : RSC_ROLE_STOPPED),
641 "unpromoted instance");
642 g_list_free(allocated);
643 }
644
645 for (; gIter != NULL; gIter = gIter->next) {
646 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
647
648 set_role_unpromoted(child_rsc, current);
649 }
650 }
651
652 static void
653 set_role_promoted(pe_resource_t *rsc, gpointer user_data)
654 {
655 if (rsc->next_role == RSC_ROLE_UNKNOWN) {
656 pe__set_next_role(rsc, RSC_ROLE_PROMOTED, "promoted instance");
657 }
658
659 g_list_foreach(rsc->children, (GFunc) set_role_promoted, NULL);
660 }
661
662 pe_node_t *
663 pcmk__set_instance_roles(pe_resource_t *rsc, pe_working_set_t *data_set)
664 {
665 int promoted = 0;
666 GList *gIter = NULL;
667 GList *gIter2 = NULL;
668 GHashTableIter iter;
669 pe_node_t *node = NULL;
670 pe_node_t *chosen = NULL;
671 enum rsc_role_e next_role = RSC_ROLE_UNKNOWN;
672 char score[33];
673 size_t len = sizeof(score);
674 clone_variant_data_t *clone_data = NULL;
675
676 get_clone_variant_data(clone_data, rsc);
677
678
679 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
680 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
681 node->count = 0;
682 }
683
684
685
686
687 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
688 GList *list = NULL;
689 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
690
691 pe_rsc_trace(rsc, "Assigning priority for %s: %s", child_rsc->id,
692 role2text(child_rsc->next_role));
693
694 if (child_rsc->fns->state(child_rsc, TRUE) == RSC_ROLE_STARTED) {
695 set_role_unpromoted(child_rsc, true);
696 }
697
698 chosen = child_rsc->fns->location(child_rsc, &list, FALSE);
699 if (pcmk__list_of_multiple(list)) {
700 pcmk__config_err("Cannot promote non-colocated child %s",
701 child_rsc->id);
702 }
703
704 g_list_free(list);
705 if (chosen == NULL) {
706 continue;
707 }
708
709 next_role = child_rsc->fns->state(child_rsc, FALSE);
710 switch (next_role) {
711 case RSC_ROLE_STARTED:
712 case RSC_ROLE_UNKNOWN:
713
714
715
716
717
718
719
720
721 child_rsc->priority = promotion_score(child_rsc, chosen, -1);
722 break;
723
724 case RSC_ROLE_UNPROMOTED:
725 case RSC_ROLE_STOPPED:
726 child_rsc->priority = -INFINITY;
727 break;
728 case RSC_ROLE_PROMOTED:
729
730
731 break;
732 default:
733 CRM_CHECK(FALSE ,
734 crm_err("Unknown resource role: %d for %s", next_role, child_rsc->id));
735 }
736
737 apply_promoted_location(child_rsc, child_rsc->rsc_location, chosen);
738 apply_promoted_location(child_rsc, rsc->rsc_location, chosen);
739
740 for (gIter2 = child_rsc->rsc_cons; gIter2 != NULL; gIter2 = gIter2->next) {
741 pcmk__colocation_t *cons = (pcmk__colocation_t *) gIter2->data;
742
743 child_rsc->cmds->rsc_colocation_lh(child_rsc, cons->primary, cons,
744 data_set);
745 }
746
747 child_rsc->sort_index = child_rsc->priority;
748 pe_rsc_trace(rsc, "Assigning priority for %s: %d", child_rsc->id, child_rsc->priority);
749
750 if (next_role == RSC_ROLE_PROMOTED) {
751 child_rsc->sort_index = INFINITY;
752 }
753 }
754
755 pe__show_node_weights(true, rsc, "Pre merge", rsc->allowed_nodes, data_set);
756 promotion_order(rsc, data_set);
757
758
759 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
760 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
761 score2char_stack(child_rsc->sort_index, score, len);
762
763 chosen = child_rsc->fns->location(child_rsc, NULL, FALSE);
764 if (pcmk_is_set(data_set->flags, pe_flag_show_scores) && !pcmk__is_daemon) {
765 if (data_set->priv != NULL) {
766 pcmk__output_t *out = data_set->priv;
767 out->message(out, "promotion-score", child_rsc, chosen, score);
768 }
769
770 } else {
771 pe_rsc_trace(rsc, "%s promotion score on %s: %s", child_rsc->id,
772 (chosen? chosen->details->uname : "none"), score);
773 }
774
775 chosen = NULL;
776
777
778
779 if (child_rsc->sort_index < 0) {
780 pe_rsc_trace(rsc, "Not supposed to promote child: %s", child_rsc->id);
781
782 } else if ((promoted < clone_data->promoted_max)
783 || !pcmk_is_set(rsc->flags, pe_rsc_managed)) {
784 chosen = node_to_be_promoted_on(child_rsc);
785 }
786
787 pe_rsc_debug(rsc, "%s promotion score: %d", child_rsc->id, child_rsc->priority);
788
789 if (chosen == NULL) {
790 set_role_unpromoted(child_rsc, false);
791 continue;
792
793 } else if ((child_rsc->role < RSC_ROLE_PROMOTED)
794 && !pcmk_is_set(data_set->flags, pe_flag_have_quorum)
795 && data_set->no_quorum_policy == no_quorum_freeze) {
796 crm_notice("Resource %s cannot be elevated from %s to %s: no-quorum-policy=freeze",
797 child_rsc->id, role2text(child_rsc->role), role2text(child_rsc->next_role));
798 set_role_unpromoted(child_rsc, false);
799 continue;
800 }
801
802 chosen->count++;
803 pe_rsc_info(rsc, "Promoting %s (%s %s)",
804 child_rsc->id, role2text(child_rsc->role), chosen->details->uname);
805 set_role_promoted(child_rsc, NULL);
806 promoted++;
807 }
808
809 pe_rsc_info(rsc, "%s: Promoted %d instances of a possible %d",
810 rsc->id, promoted, clone_data->promoted_max);
811
812 return NULL;
813 }
814
815 void
816 create_promotable_actions(pe_resource_t * rsc, pe_working_set_t * data_set)
817 {
818 pe_action_t *action = NULL;
819 GList *gIter = rsc->children;
820 pe_action_t *action_complete = NULL;
821 gboolean any_promoting = FALSE;
822 gboolean any_demoting = FALSE;
823 pe_resource_t *last_promote_rsc = NULL;
824 pe_resource_t *last_demote_rsc = NULL;
825
826 clone_variant_data_t *clone_data = NULL;
827
828 get_clone_variant_data(clone_data, rsc);
829
830 pe_rsc_debug(rsc, "Creating actions for %s", rsc->id);
831
832 for (; gIter != NULL; gIter = gIter->next) {
833 gboolean child_promoting = FALSE;
834 gboolean child_demoting = FALSE;
835 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
836
837 pe_rsc_trace(rsc, "Creating actions for %s", child_rsc->id);
838 child_rsc->cmds->create_actions(child_rsc, data_set);
839 check_promotable_actions(child_rsc, &child_demoting, &child_promoting);
840
841 any_demoting = any_demoting || child_demoting;
842 any_promoting = any_promoting || child_promoting;
843 pe_rsc_trace(rsc, "Created actions for %s: %d %d", child_rsc->id, child_promoting,
844 child_demoting);
845 }
846
847
848 action = pcmk__new_rsc_pseudo_action(rsc, RSC_PROMOTE, !any_promoting,
849 true);
850 action_complete = pcmk__new_rsc_pseudo_action(rsc, RSC_PROMOTED,
851 !any_promoting, true);
852 action_complete->priority = INFINITY;
853
854 child_promoting_constraints(clone_data, pe_order_optional,
855 rsc, NULL, last_promote_rsc, data_set);
856
857 if (clone_data->promote_notify == NULL) {
858 clone_data->promote_notify = pcmk__clone_notif_pseudo_ops(rsc,
859 RSC_PROMOTE,
860 action,
861 action_complete);
862 }
863
864
865 action = pcmk__new_rsc_pseudo_action(rsc, RSC_DEMOTE, !any_demoting, true);
866 action_complete = pcmk__new_rsc_pseudo_action(rsc, RSC_DEMOTED,
867 !any_demoting, true);
868 action_complete->priority = INFINITY;
869
870 child_demoting_constraints(clone_data, pe_order_optional, rsc, NULL, last_demote_rsc, data_set);
871
872 if (clone_data->demote_notify == NULL) {
873 clone_data->demote_notify = pcmk__clone_notif_pseudo_ops(rsc,
874 RSC_DEMOTE,
875 action,
876 action_complete);
877
878 if (clone_data->promote_notify) {
879
880
881
882 order_actions(clone_data->stop_notify->post_done, clone_data->promote_notify->pre,
883 pe_order_optional);
884 order_actions(clone_data->start_notify->post_done, clone_data->promote_notify->pre,
885 pe_order_optional);
886 order_actions(clone_data->demote_notify->post_done, clone_data->promote_notify->pre,
887 pe_order_optional);
888 order_actions(clone_data->demote_notify->post_done, clone_data->start_notify->pre,
889 pe_order_optional);
890 order_actions(clone_data->demote_notify->post_done, clone_data->stop_notify->pre,
891 pe_order_optional);
892 }
893 }
894
895
896
897 gIter = rsc->children;
898 for (; gIter != NULL; gIter = gIter->next) {
899 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
900
901 child_rsc->priority = rsc->priority;
902 }
903 }
904
905 void
906 promote_demote_constraints(pe_resource_t *rsc, pe_working_set_t *data_set)
907 {
908
909 pcmk__order_resource_actions(rsc, RSC_STOPPED, rsc, RSC_START,
910 pe_order_optional, data_set);
911
912
913 pcmk__order_resource_actions(rsc, RSC_STOPPED, rsc, RSC_PROMOTE,
914 pe_order_optional, data_set);
915
916
917 pcmk__order_resource_actions(rsc, RSC_DEMOTED, rsc, RSC_START,
918 pe_order_optional, data_set);
919
920
921 pcmk__order_resource_actions(rsc, RSC_STARTED, rsc, RSC_PROMOTE,
922 pe_order_optional, data_set);
923
924
925 pcmk__order_resource_actions(rsc, RSC_DEMOTED, rsc, RSC_STOP,
926 pe_order_optional, data_set);
927
928
929 pcmk__order_resource_actions(rsc, RSC_DEMOTE, rsc, RSC_DEMOTED,
930 pe_order_optional, data_set);
931
932
933 pcmk__order_resource_actions(rsc, RSC_DEMOTED, rsc, RSC_PROMOTE,
934 pe_order_optional, data_set);
935 }
936
937
938 void
939 promotable_constraints(pe_resource_t * rsc, pe_working_set_t * data_set)
940 {
941 GList *gIter = rsc->children;
942 pe_resource_t *last_rsc = NULL;
943 clone_variant_data_t *clone_data = NULL;
944
945 get_clone_variant_data(clone_data, rsc);
946
947 promote_demote_constraints(rsc, data_set);
948
949 for (; gIter != NULL; gIter = gIter->next) {
950 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
951
952
953 pcmk__order_resource_actions(child_rsc, RSC_DEMOTE, child_rsc,
954 RSC_PROMOTE, pe_order_optional, data_set);
955
956 child_promoting_constraints(clone_data, pe_order_optional,
957 rsc, child_rsc, last_rsc, data_set);
958
959 child_demoting_constraints(clone_data, pe_order_optional,
960 rsc, child_rsc, last_rsc, data_set);
961
962 last_rsc = child_rsc;
963 }
964 }
965
966 static void
967 node_hash_update_one(GHashTable * hash, pe_node_t * other, const char *attr, int score)
968 {
969 GHashTableIter iter;
970 pe_node_t *node = NULL;
971 const char *value = NULL;
972
973 if (other == NULL) {
974 return;
975
976 } else if (attr == NULL) {
977 attr = CRM_ATTR_UNAME;
978 }
979
980 value = pe_node_attribute_raw(other, attr);
981 g_hash_table_iter_init(&iter, hash);
982 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
983 const char *tmp = pe_node_attribute_raw(node, attr);
984
985 if (pcmk__str_eq(value, tmp, pcmk__str_casei)) {
986 crm_trace("%s: %d + %d", node->details->uname, node->weight, other->weight);
987 node->weight = pcmk__add_scores(node->weight, score);
988 }
989 }
990 }
991
992 void
993 promotable_colocation_rh(pe_resource_t *dependent, pe_resource_t *primary,
994 pcmk__colocation_t *constraint,
995 pe_working_set_t *data_set)
996 {
997 GList *gIter = NULL;
998
999 if (pcmk_is_set(dependent->flags, pe_rsc_provisional)) {
1000 GList *affected_nodes = NULL;
1001
1002 for (gIter = primary->children; gIter != NULL; gIter = gIter->next) {
1003 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
1004 pe_node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE);
1005 enum rsc_role_e next_role = child_rsc->fns->state(child_rsc, FALSE);
1006
1007 pe_rsc_trace(primary, "Processing: %s", child_rsc->id);
1008 if ((chosen != NULL) && (next_role == constraint->primary_role)) {
1009 pe_rsc_trace(primary, "Applying: %s %s %s %d", child_rsc->id,
1010 role2text(next_role), chosen->details->uname, constraint->score);
1011 if (constraint->score < INFINITY) {
1012 node_hash_update_one(dependent->allowed_nodes, chosen,
1013 constraint->node_attribute, constraint->score);
1014 }
1015 affected_nodes = g_list_prepend(affected_nodes, chosen);
1016 }
1017 }
1018
1019
1020
1021
1022
1023 if ((constraint->dependent_role != RSC_ROLE_PROMOTED)
1024 || (constraint->primary_role != RSC_ROLE_PROMOTED)) {
1025
1026 if (constraint->score >= INFINITY) {
1027 node_list_exclude(dependent->allowed_nodes, affected_nodes,
1028 TRUE);
1029 }
1030 }
1031 g_list_free(affected_nodes);
1032
1033 } else if (constraint->dependent_role == RSC_ROLE_PROMOTED) {
1034 pe_resource_t *primary_instance;
1035
1036 primary_instance = find_compatible_child(dependent, primary,
1037 constraint->primary_role,
1038 FALSE, data_set);
1039 if ((primary_instance == NULL) && (constraint->score >= INFINITY)) {
1040 pe_rsc_trace(dependent, "%s can't be promoted %s",
1041 dependent->id, constraint->id);
1042 dependent->priority = -INFINITY;
1043
1044 } else if (primary_instance != NULL) {
1045 int new_priority = pcmk__add_scores(dependent->priority,
1046 constraint->score);
1047
1048 pe_rsc_debug(dependent, "Applying %s to %s",
1049 constraint->id, dependent->id);
1050 pe_rsc_debug(dependent, "\t%s: %d->%d",
1051 dependent->id, dependent->priority, new_priority);
1052 dependent->priority = new_priority;
1053 }
1054 }
1055
1056 return;
1057 }