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