This source file includes following definitions.
- group_color
- group_create_actions
- group_update_pseudo_status
- group_internal_constraints
- group_rsc_colocation_lh
- group_rsc_colocation_rh
- group_action_flags
- group_update_actions
- group_rsc_location
- group_expand
- group_merge_weights
- group_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 <pengine.h>
22 #include <crm/msg_xml.h>
23
24 #include <allocate.h>
25 #include <utils.h>
26
27 #define VARIANT_GROUP 1
28 #include <lib/pengine/variant.h>
29
30 node_t *
31 group_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
32 {
33 node_t *node = NULL;
34 node_t *group_node = NULL;
35 GListPtr gIter = NULL;
36 group_variant_data_t *group_data = NULL;
37
38 get_group_variant_data(group_data, rsc);
39
40 if (is_not_set(rsc->flags, pe_rsc_provisional)) {
41 return rsc->allocated_to;
42 }
43 pe_rsc_trace(rsc, "Processing %s", rsc->id);
44 if (is_set(rsc->flags, pe_rsc_allocating)) {
45 pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
46 return NULL;
47 }
48
49 if (group_data->first_child == NULL) {
50
51 clear_bit(rsc->flags, pe_rsc_provisional);
52 return NULL;
53 }
54
55 set_bit(rsc->flags, pe_rsc_allocating);
56 rsc->role = group_data->first_child->role;
57
58 group_data->first_child->rsc_cons =
59 g_list_concat(group_data->first_child->rsc_cons, rsc->rsc_cons);
60 rsc->rsc_cons = NULL;
61
62 group_data->last_child->rsc_cons_lhs =
63 g_list_concat(group_data->last_child->rsc_cons_lhs, rsc->rsc_cons_lhs);
64 rsc->rsc_cons_lhs = NULL;
65
66 dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__,
67 rsc->allowed_nodes);
68
69 gIter = rsc->children;
70 for (; gIter != NULL; gIter = gIter->next) {
71 resource_t *child_rsc = (resource_t *) gIter->data;
72
73 node = child_rsc->cmds->allocate(child_rsc, prefer, data_set);
74 if (group_node == NULL) {
75 group_node = node;
76 }
77 }
78
79 rsc->next_role = group_data->first_child->next_role;
80 clear_bit(rsc->flags, pe_rsc_allocating);
81 clear_bit(rsc->flags, pe_rsc_provisional);
82
83 if (group_data->colocated) {
84 return group_node;
85 }
86 return NULL;
87 }
88
89 void group_update_pseudo_status(resource_t * parent, resource_t * child);
90
91 void
92 group_create_actions(resource_t * rsc, pe_working_set_t * data_set)
93 {
94 action_t *op = NULL;
95 const char *value = NULL;
96 GListPtr gIter = rsc->children;
97
98 pe_rsc_trace(rsc, "Creating actions for %s", rsc->id);
99
100 for (; gIter != NULL; gIter = gIter->next) {
101 resource_t *child_rsc = (resource_t *) gIter->data;
102
103 child_rsc->cmds->create_actions(child_rsc, data_set);
104 group_update_pseudo_status(rsc, child_rsc);
105 }
106
107 op = start_action(rsc, NULL, TRUE );
108 set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
109
110 op = custom_action(rsc, started_key(rsc),
111 RSC_STARTED, NULL, TRUE , TRUE, data_set);
112 set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
113
114 op = stop_action(rsc, NULL, TRUE );
115 set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
116
117 op = custom_action(rsc, stopped_key(rsc),
118 RSC_STOPPED, NULL, TRUE , TRUE, data_set);
119 set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
120
121 value = g_hash_table_lookup(rsc->meta, "stateful");
122 if (crm_is_true(value)) {
123 op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set);
124 set_bit(op->flags, pe_action_pseudo);
125 set_bit(op->flags, pe_action_runnable);
126 op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set);
127 set_bit(op->flags, pe_action_pseudo);
128 set_bit(op->flags, pe_action_runnable);
129
130 op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set);
131 set_bit(op->flags, pe_action_pseudo);
132 set_bit(op->flags, pe_action_runnable);
133 op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set);
134 set_bit(op->flags, pe_action_pseudo);
135 set_bit(op->flags, pe_action_runnable);
136 }
137 }
138
139 void
140 group_update_pseudo_status(resource_t * parent, resource_t * child)
141 {
142 GListPtr gIter = child->actions;
143 group_variant_data_t *group_data = NULL;
144
145 get_group_variant_data(group_data, parent);
146
147 if (group_data->ordered == FALSE) {
148
149 return;
150 }
151
152 if (group_data->child_stopping && group_data->child_starting) {
153 return;
154 }
155
156 for (; gIter != NULL; gIter = gIter->next) {
157 action_t *action = (action_t *) gIter->data;
158
159 if (is_set(action->flags, pe_action_optional)) {
160 continue;
161 }
162 if (safe_str_eq(RSC_STOP, action->task) && is_set(action->flags, pe_action_runnable)) {
163 group_data->child_stopping = TRUE;
164 pe_rsc_trace(action->rsc, "Based on %s the group is stopping", action->uuid);
165
166 } else if (safe_str_eq(RSC_START, action->task)
167 && is_set(action->flags, pe_action_runnable)) {
168 group_data->child_starting = TRUE;
169 pe_rsc_trace(action->rsc, "Based on %s the group is starting", action->uuid);
170 }
171 }
172 }
173
174 void
175 group_internal_constraints(resource_t * rsc, pe_working_set_t * data_set)
176 {
177 GListPtr gIter = rsc->children;
178 resource_t *last_rsc = NULL;
179 resource_t *last_active = NULL;
180 resource_t *top = uber_parent(rsc);
181 group_variant_data_t *group_data = NULL;
182
183 get_group_variant_data(group_data, rsc);
184
185 new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set);
186 new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set);
187 new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set);
188
189 for (; gIter != NULL; gIter = gIter->next) {
190 resource_t *child_rsc = (resource_t *) gIter->data;
191 int stop = pe_order_none;
192 int stopped = pe_order_implies_then_printed;
193 int start = pe_order_implies_then | pe_order_runnable_left;
194 int started =
195 pe_order_runnable_left | pe_order_implies_then | pe_order_implies_then_printed;
196
197 child_rsc->cmds->internal_constraints(child_rsc, data_set);
198
199 if (last_rsc == NULL) {
200 if (group_data->ordered) {
201 stop |= pe_order_optional;
202 stopped = pe_order_implies_then;
203 }
204
205 } else if (group_data->colocated) {
206 rsc_colocation_new("group:internal_colocation", NULL, INFINITY,
207 child_rsc, last_rsc, NULL, NULL, data_set);
208 }
209
210 if (top->variant == pe_master) {
211 new_rsc_order(rsc, RSC_DEMOTE, child_rsc, RSC_DEMOTE,
212 stop | pe_order_implies_first_printed, data_set);
213
214 new_rsc_order(child_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stopped, data_set);
215
216 new_rsc_order(child_rsc, RSC_PROMOTE, rsc, RSC_PROMOTED, started, data_set);
217
218 new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
219 pe_order_implies_first_printed, data_set);
220
221 }
222
223 order_start_start(rsc, child_rsc, pe_order_implies_first_printed);
224 order_stop_stop(rsc, child_rsc, stop | pe_order_implies_first_printed);
225
226 new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, stopped, data_set);
227
228 new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, started, data_set);
229
230 if (group_data->ordered == FALSE) {
231 order_start_start(rsc, child_rsc, start | pe_order_implies_first_printed);
232 if (top->variant == pe_master) {
233 new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
234 start | pe_order_implies_first_printed, data_set);
235 }
236
237 } else if (last_rsc != NULL) {
238 child_rsc->restart_type = pe_restart_restart;
239
240 order_start_start(last_rsc, child_rsc, start);
241 order_stop_stop(child_rsc, last_rsc, pe_order_optional | pe_order_restart);
242
243 if (top->variant == pe_master) {
244 new_rsc_order(last_rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, start, data_set);
245 new_rsc_order(child_rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, pe_order_optional,
246 data_set);
247 }
248
249 } else {
250
251
252
253
254
255
256 int flags = pe_order_none;
257
258 order_start_start(rsc, child_rsc, flags);
259 if (top->variant == pe_master) {
260 new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, flags, data_set);
261 }
262
263 }
264
265
266
267
268 if (child_rsc->running_on) {
269 if (group_data->ordered
270 && last_rsc
271 && last_rsc->running_on == NULL && last_active && last_active->running_on) {
272 order_stop_stop(child_rsc, last_active, pe_order_optional);
273 }
274 last_active = child_rsc;
275 }
276
277 last_rsc = child_rsc;
278 }
279
280 if (group_data->ordered && last_rsc != NULL) {
281 int stop_stop_flags = pe_order_implies_then;
282 int stop_stopped_flags = pe_order_optional;
283
284 order_stop_stop(rsc, last_rsc, stop_stop_flags);
285 new_rsc_order(last_rsc, RSC_STOP, rsc, RSC_STOPPED, stop_stopped_flags, data_set);
286
287 if (top->variant == pe_master) {
288 new_rsc_order(rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, stop_stop_flags, data_set);
289 new_rsc_order(last_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stop_stopped_flags, data_set);
290 }
291 }
292 }
293
294 void
295 group_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
296 {
297 GListPtr gIter = NULL;
298 group_variant_data_t *group_data = NULL;
299
300 if (rsc_lh == NULL) {
301 pe_err("rsc_lh was NULL for %s", constraint->id);
302 return;
303
304 } else if (rsc_rh == NULL) {
305 pe_err("rsc_rh was NULL for %s", constraint->id);
306 return;
307 }
308
309 gIter = rsc_lh->children;
310 pe_rsc_trace(rsc_lh, "Processing constraints from %s", rsc_lh->id);
311
312 get_group_variant_data(group_data, rsc_lh);
313
314 if (group_data->colocated) {
315 group_data->first_child->cmds->rsc_colocation_lh(group_data->first_child, rsc_rh,
316 constraint);
317 return;
318
319 } else if (constraint->score >= INFINITY) {
320 crm_config_err("%s: Cannot perform mandatory colocation"
321 " between non-colocated group and %s", rsc_lh->id, rsc_rh->id);
322 return;
323 }
324
325 for (; gIter != NULL; gIter = gIter->next) {
326 resource_t *child_rsc = (resource_t *) gIter->data;
327
328 child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint);
329 }
330 }
331
332 void
333 group_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
334 {
335 GListPtr gIter = rsc_rh->children;
336 group_variant_data_t *group_data = NULL;
337
338 get_group_variant_data(group_data, rsc_rh);
339 CRM_CHECK(rsc_lh->variant == pe_native, return);
340
341 pe_rsc_trace(rsc_rh, "Processing RH of constraint %s", constraint->id);
342 print_resource(LOG_DEBUG_3, "LHS", rsc_lh, TRUE);
343
344 if (is_set(rsc_rh->flags, pe_rsc_provisional)) {
345 return;
346
347 } else if (group_data->colocated && group_data->first_child) {
348 if (constraint->score >= INFINITY) {
349
350 group_data->last_child->cmds->rsc_colocation_rh(rsc_lh, group_data->last_child,
351 constraint);
352 } else {
353
354 group_data->first_child->cmds->rsc_colocation_rh(rsc_lh, group_data->first_child,
355 constraint);
356 }
357
358 return;
359
360 } else if (constraint->score >= INFINITY) {
361 crm_config_err("%s: Cannot perform mandatory colocation with"
362 " non-colocated group: %s", rsc_lh->id, rsc_rh->id);
363 return;
364 }
365
366 for (; gIter != NULL; gIter = gIter->next) {
367 resource_t *child_rsc = (resource_t *) gIter->data;
368
369 child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint);
370 }
371 }
372
373 enum pe_action_flags
374 group_action_flags(action_t * action, node_t * node)
375 {
376 GListPtr gIter = NULL;
377 enum pe_action_flags flags = (pe_action_optional | pe_action_runnable | pe_action_pseudo);
378
379 for (gIter = action->rsc->children; gIter != NULL; gIter = gIter->next) {
380 resource_t *child = (resource_t *) gIter->data;
381 enum action_tasks task = get_complex_task(child, action->task, TRUE);
382 const char *task_s = task2text(task);
383 action_t *child_action = find_first_action(child->actions, NULL, task_s, node);
384
385 if (child_action) {
386 enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node);
387
388 if (is_set(flags, pe_action_optional)
389 && is_set(child_flags, pe_action_optional) == FALSE) {
390 pe_rsc_trace(action->rsc, "%s is mandatory because of %s", action->uuid,
391 child_action->uuid);
392 clear_bit(flags, pe_action_optional);
393 pe_clear_action_bit(action, pe_action_optional);
394 }
395 if (safe_str_neq(task_s, action->task)
396 && is_set(flags, pe_action_runnable)
397 && is_set(child_flags, pe_action_runnable) == FALSE) {
398 pe_rsc_trace(action->rsc, "%s is not runnable because of %s", action->uuid,
399 child_action->uuid);
400 clear_bit(flags, pe_action_runnable);
401 pe_clear_action_bit(action, pe_action_runnable);
402 }
403
404 } else if (task != stop_rsc && task != action_demote) {
405 pe_rsc_trace(action->rsc, "%s is not runnable because of %s (not found in %s)",
406 action->uuid, task_s, child->id);
407 clear_bit(flags, pe_action_runnable);
408 }
409 }
410
411 return flags;
412 }
413
414 enum pe_graph_flags
415 group_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags,
416 enum pe_action_flags filter, enum pe_ordering type)
417 {
418 GListPtr gIter = then->rsc->children;
419 enum pe_graph_flags changed = pe_graph_none;
420
421 CRM_ASSERT(then->rsc != NULL);
422 changed |= native_update_actions(first, then, node, flags, filter, type);
423
424 for (; gIter != NULL; gIter = gIter->next) {
425 resource_t *child = (resource_t *) gIter->data;
426 action_t *child_action = find_first_action(child->actions, NULL, then->task, node);
427
428 if (child_action) {
429 changed |= child->cmds->update_actions(first, child_action, node, flags, filter, type);
430 }
431 }
432
433 return changed;
434 }
435
436 void
437 group_rsc_location(resource_t * rsc, rsc_to_node_t * constraint)
438 {
439 GListPtr gIter = rsc->children;
440 GListPtr saved = constraint->node_list_rh;
441 GListPtr zero = node_list_dup(constraint->node_list_rh, TRUE, FALSE);
442 gboolean reset_scores = TRUE;
443 group_variant_data_t *group_data = NULL;
444
445 get_group_variant_data(group_data, rsc);
446
447 pe_rsc_debug(rsc, "Processing rsc_location %s for %s", constraint->id, rsc->id);
448
449 native_rsc_location(rsc, constraint);
450
451 for (; gIter != NULL; gIter = gIter->next) {
452 resource_t *child_rsc = (resource_t *) gIter->data;
453
454 child_rsc->cmds->rsc_location(child_rsc, constraint);
455 if (group_data->colocated && reset_scores) {
456 reset_scores = FALSE;
457 constraint->node_list_rh = zero;
458 }
459 }
460
461 constraint->node_list_rh = saved;
462 g_list_free_full(zero, free);
463 }
464
465 void
466 group_expand(resource_t * rsc, pe_working_set_t * data_set)
467 {
468 GListPtr gIter = rsc->children;
469
470 pe_rsc_trace(rsc, "Processing actions from %s", rsc->id);
471
472 CRM_CHECK(rsc != NULL, return);
473 native_expand(rsc, data_set);
474
475 for (; gIter != NULL; gIter = gIter->next) {
476 resource_t *child_rsc = (resource_t *) gIter->data;
477
478 child_rsc->cmds->expand(child_rsc, data_set);
479 }
480 }
481
482 GHashTable *
483 group_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr,
484 float factor, enum pe_weights flags)
485 {
486 GListPtr gIter = rsc->rsc_cons_lhs;
487 group_variant_data_t *group_data = NULL;
488
489 get_group_variant_data(group_data, rsc);
490
491 if (is_set(rsc->flags, pe_rsc_merging)) {
492 pe_rsc_info(rsc, "Breaking dependency loop with %s at %s", rsc->id, rhs);
493 return nodes;
494 }
495
496 set_bit(rsc->flags, pe_rsc_merging);
497
498 nodes =
499 group_data->first_child->cmds->merge_weights(group_data->first_child, rhs, nodes, attr,
500 factor, flags);
501
502 for (; gIter != NULL; gIter = gIter->next) {
503 rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
504
505 nodes = native_merge_weights(constraint->rsc_lh, rsc->id, nodes,
506 constraint->node_attribute,
507 (float)constraint->score / INFINITY, flags);
508 }
509
510 clear_bit(rsc->flags, pe_rsc_merging);
511 return nodes;
512 }
513
514 void
515 group_append_meta(resource_t * rsc, xmlNode * xml)
516 {
517 }