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