This source file includes following definitions.
- native_choose_node
- node_list_attr_score
- node_hash_update
- node_hash_dup
- native_merge_weights
- rsc_merge_weights
- native_color
- is_op_dup
- RecurringOp
- Recurring
- RecurringOp_Stopped
- Recurring_Stopped
- handle_migration_actions
- native_create_actions
- rsc_avoids_remote_nodes
- native_internal_constraints
- native_rsc_colocation_lh
- filter_colocation_constraint
- influence_priority
- colocation_match
- native_rsc_colocation_rh
- filter_rsc_ticket
- rsc_ticket_constraint
- native_action_flags
- native_update_actions
- native_rsc_location
- native_expand
- LogAction
- LogActions
- StopRsc
- StartRsc
- PromoteRsc
- DemoteRsc
- RoleError
- NullOp
- DeleteRsc
- increment_clone
- probe_anon_group_member
- native_create_probe
- native_start_constraints
- native_stop_constraints
- rsc_stonith_ordering
- ReloadRsc
- native_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/pengine/rules.h>
23 #include <crm/msg_xml.h>
24 #include <allocate.h>
25 #include <notif.h>
26 #include <utils.h>
27 #include <crm/services.h>
28
29
30 #define INFINITY_HACK (INFINITY * -100)
31
32 #define VARIANT_NATIVE 1
33 #include <lib/pengine/variant.h>
34
35 gboolean update_action(action_t * then);
36 void native_rsc_colocation_rh_must(resource_t * rsc_lh, gboolean update_lh,
37 resource_t * rsc_rh, gboolean update_rh);
38
39 void native_rsc_colocation_rh_mustnot(resource_t * rsc_lh, gboolean update_lh,
40 resource_t * rsc_rh, gboolean update_rh);
41
42 void Recurring(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set);
43 void RecurringOp(resource_t * rsc, action_t * start, node_t * node,
44 xmlNode * operation, pe_working_set_t * data_set);
45 void Recurring_Stopped(resource_t * rsc, action_t * start, node_t * node,
46 pe_working_set_t * data_set);
47 void RecurringOp_Stopped(resource_t * rsc, action_t * start, node_t * node,
48 xmlNode * operation, pe_working_set_t * data_set);
49
50 void ReloadRsc(resource_t * rsc, node_t *node, pe_working_set_t * data_set);
51 gboolean DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set);
52 gboolean StopRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
53 gboolean StartRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
54 gboolean DemoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
55 gboolean PromoteRsc(resource_t * rsc, node_t * next, gboolean optional,
56 pe_working_set_t * data_set);
57 gboolean RoleError(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
58 gboolean NullOp(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
59
60
61 enum rsc_role_e rsc_state_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX] = {
62
63
64 { RSC_ROLE_UNKNOWN, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, },
65 { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_SLAVE, },
66 { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, },
67 { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, },
68 { RSC_ROLE_STOPPED, RSC_ROLE_SLAVE, RSC_ROLE_SLAVE, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, },
69 };
70
71 gboolean (*rsc_action_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX])(resource_t*,node_t*,gboolean,pe_working_set_t*) = {
72
73
74 { RoleError, StopRsc, RoleError, RoleError, RoleError, },
75 { RoleError, NullOp, StartRsc, StartRsc, RoleError, },
76 { RoleError, StopRsc, NullOp, NullOp, PromoteRsc, },
77 { RoleError, StopRsc, StopRsc, NullOp, PromoteRsc, },
78 { RoleError, DemoteRsc, DemoteRsc, DemoteRsc, NullOp, },
79 };
80
81
82 static gboolean
83 native_choose_node(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
84 {
85 GListPtr nodes = NULL;
86 node_t *chosen = NULL;
87 node_t *best = NULL;
88 int multiple = 1;
89 int length = 0;
90 gboolean result = FALSE;
91
92 process_utilization(rsc, &prefer, data_set);
93
94 if (is_not_set(rsc->flags, pe_rsc_provisional)) {
95 return rsc->allocated_to ? TRUE : FALSE;
96 }
97
98
99 if (rsc->allowed_nodes) {
100 length = g_hash_table_size(rsc->allowed_nodes);
101 }
102 if (length > 0) {
103 nodes = g_hash_table_get_values(rsc->allowed_nodes);
104 nodes = g_list_sort_with_data(nodes, sort_node_weight,
105 g_list_nth_data(rsc->running_on, 0));
106
107
108 best = g_list_nth_data(nodes, 0);
109 }
110
111 if (prefer && nodes) {
112 chosen = g_hash_table_lookup(rsc->allowed_nodes, prefer->details->id);
113
114 if (chosen == NULL) {
115 pe_rsc_trace(rsc, "Preferred node %s for %s was unknown",
116 prefer->details->uname, rsc->id);
117
118
119
120
121
122
123
124 } else if ((chosen->weight < 0) || (chosen->weight < best->weight)) {
125 pe_rsc_trace(rsc, "Preferred node %s for %s was unsuitable",
126 chosen->details->uname, rsc->id);
127 chosen = NULL;
128
129 } else if (!can_run_resources(chosen)) {
130 pe_rsc_trace(rsc, "Preferred node %s for %s was unavailable",
131 chosen->details->uname, rsc->id);
132 chosen = NULL;
133
134 } else {
135 pe_rsc_trace(rsc,
136 "Chose preferred node %s for %s (ignoring %d candidates)",
137 chosen->details->uname, rsc->id, length);
138 }
139 }
140
141 if ((chosen == NULL) && nodes) {
142
143
144
145
146 chosen = best;
147 pe_rsc_trace(rsc, "Chose node %s for %s from %d candidates",
148 chosen ? chosen->details->uname : "<none>", rsc->id, length);
149
150 if (!pe_rsc_is_unique_clone(rsc->parent)
151 && chosen && (chosen->weight > 0) && can_run_resources(chosen)) {
152
153
154
155
156
157
158
159
160
161 node_t *running = g_list_nth_data(rsc->running_on, 0);
162
163 if (running && (can_run_resources(running) == FALSE)) {
164 pe_rsc_trace(rsc, "Current node for %s (%s) can't run resources",
165 rsc->id, running->details->uname);
166 } else if (running) {
167 for (GList *iter = nodes->next; iter; iter = iter->next) {
168 node_t *tmp = (node_t *) iter->data;
169
170 if (tmp->weight != chosen->weight) {
171
172 break;
173 }
174 if (tmp->details == running->details) {
175
176 chosen = tmp;
177 }
178 multiple++;
179 }
180 }
181 }
182 }
183
184 if (multiple > 1) {
185 static char score[33];
186 int log_level = (chosen->weight >= INFINITY)? LOG_WARNING : LOG_INFO;
187
188 score2char_stack(chosen->weight, score, sizeof(score));
189 do_crm_log(log_level,
190 "Chose node %s for %s from %d nodes with score %s",
191 chosen->details->uname, rsc->id, multiple, score);
192 }
193
194 result = native_assign_node(rsc, nodes, chosen, FALSE);
195 g_list_free(nodes);
196 return result;
197 }
198
199 static int
200 node_list_attr_score(GHashTable * list, const char *attr, const char *value)
201 {
202 GHashTableIter iter;
203 node_t *node = NULL;
204 int best_score = -INFINITY;
205 const char *best_node = NULL;
206
207 if (attr == NULL) {
208 attr = CRM_ATTR_UNAME;
209 }
210
211 g_hash_table_iter_init(&iter, list);
212 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
213 int weight = node->weight;
214
215 if (can_run_resources(node) == FALSE) {
216 weight = -INFINITY;
217 }
218 if (weight > best_score || best_node == NULL) {
219 const char *tmp = pe_node_attribute_raw(node, attr);
220
221 if (safe_str_eq(value, tmp)) {
222 best_score = weight;
223 best_node = node->details->uname;
224 }
225 }
226 }
227
228 if (safe_str_neq(attr, CRM_ATTR_UNAME)) {
229 crm_info("Best score for %s=%s was %s with %d",
230 attr, value, best_node ? best_node : "<none>", best_score);
231 }
232
233 return best_score;
234 }
235
236 static void
237 node_hash_update(GHashTable * list1, GHashTable * list2, const char *attr, float factor,
238 gboolean only_positive)
239 {
240 int score = 0;
241 int new_score = 0;
242 GHashTableIter iter;
243 node_t *node = NULL;
244
245 if (attr == NULL) {
246 attr = CRM_ATTR_UNAME;
247 }
248
249 g_hash_table_iter_init(&iter, list1);
250 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
251 float weight_f = 0;
252 int weight = 0;
253
254 CRM_LOG_ASSERT(node != NULL);
255 if(node == NULL) { continue; };
256
257 score = node_list_attr_score(list2, attr, pe_node_attribute_raw(node, attr));
258
259 weight_f = factor * score;
260
261
262 weight = (int)(weight_f < 0 ? weight_f - 0.5 : weight_f + 0.5);
263
264 new_score = merge_weights(weight, node->weight);
265
266 if (factor < 0 && score < 0) {
267
268
269
270
271
272
273 crm_trace("%s: Filtering %d + %f*%d (factor * score)",
274 node->details->uname, node->weight, factor, score);
275
276 } else if (node->weight == INFINITY_HACK) {
277 crm_trace("%s: Filtering %d + %f*%d (node < 0)",
278 node->details->uname, node->weight, factor, score);
279
280 } else if (only_positive && new_score < 0 && node->weight > 0) {
281 node->weight = INFINITY_HACK;
282 crm_trace("%s: Filtering %d + %f*%d (score > 0)",
283 node->details->uname, node->weight, factor, score);
284
285 } else if (only_positive && new_score < 0 && node->weight == 0) {
286 crm_trace("%s: Filtering %d + %f*%d (score == 0)",
287 node->details->uname, node->weight, factor, score);
288
289 } else {
290 crm_trace("%s: %d + %f*%d", node->details->uname, node->weight, factor, score);
291 node->weight = new_score;
292 }
293 }
294 }
295
296 GHashTable *
297 node_hash_dup(GHashTable * hash)
298 {
299
300 GListPtr list = g_hash_table_get_values(hash);
301 GHashTable *result = node_hash_from_list(list);
302
303 g_list_free(list);
304 return result;
305 }
306
307 GHashTable *
308 native_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr,
309 float factor, enum pe_weights flags)
310 {
311 return rsc_merge_weights(rsc, rhs, nodes, attr, factor, flags);
312 }
313
314 GHashTable *
315 rsc_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr,
316 float factor, enum pe_weights flags)
317 {
318 GHashTable *work = NULL;
319 int multiplier = 1;
320
321 if (factor < 0) {
322 multiplier = -1;
323 }
324
325 if (is_set(rsc->flags, pe_rsc_merging)) {
326 pe_rsc_info(rsc, "%s: Breaking dependency loop at %s", rhs, rsc->id);
327 return nodes;
328 }
329
330 set_bit(rsc->flags, pe_rsc_merging);
331
332 if (is_set(flags, pe_weights_init)) {
333 if (rsc->variant == pe_group && rsc->children) {
334 GListPtr last = rsc->children;
335
336 while (last->next != NULL) {
337 last = last->next;
338 }
339
340 pe_rsc_trace(rsc, "Merging %s as a group %p %p", rsc->id, rsc->children, last);
341 work = rsc_merge_weights(last->data, rhs, NULL, attr, factor, flags);
342
343 } else {
344 work = node_hash_dup(rsc->allowed_nodes);
345 }
346 clear_bit(flags, pe_weights_init);
347
348 } else if (rsc->variant == pe_group && rsc->children) {
349 GListPtr iter = rsc->children;
350
351 pe_rsc_trace(rsc, "%s: Combining scores from %d children of %s", rhs, g_list_length(iter), rsc->id);
352 work = node_hash_dup(nodes);
353 for(iter = rsc->children; iter->next != NULL; iter = iter->next) {
354 work = rsc_merge_weights(iter->data, rhs, work, attr, factor, flags);
355 }
356
357 } else {
358 pe_rsc_trace(rsc, "%s: Combining scores from %s", rhs, rsc->id);
359 work = node_hash_dup(nodes);
360 node_hash_update(work, rsc->allowed_nodes, attr, factor,
361 is_set(flags, pe_weights_positive));
362 }
363
364 if (is_set(flags, pe_weights_rollback) && can_run_any(work) == FALSE) {
365 pe_rsc_info(rsc, "%s: Rolling back scores from %s", rhs, rsc->id);
366 g_hash_table_destroy(work);
367 clear_bit(rsc->flags, pe_rsc_merging);
368 return nodes;
369 }
370
371 if (can_run_any(work)) {
372 GListPtr gIter = NULL;
373
374 if (is_set(flags, pe_weights_forward)) {
375 gIter = rsc->rsc_cons;
376 crm_trace("Checking %d additional colocation constraints", g_list_length(gIter));
377
378 } else if(rsc->variant == pe_group && rsc->children) {
379 GListPtr last = rsc->children;
380
381 while (last->next != NULL) {
382 last = last->next;
383 }
384
385 gIter = ((resource_t*)last->data)->rsc_cons_lhs;
386 crm_trace("Checking %d additional optional group colocation constraints from %s",
387 g_list_length(gIter), ((resource_t*)last->data)->id);
388
389 } else {
390 gIter = rsc->rsc_cons_lhs;
391 crm_trace("Checking %d additional optional colocation constraints %s", g_list_length(gIter), rsc->id);
392 }
393
394 for (; gIter != NULL; gIter = gIter->next) {
395 resource_t *other = NULL;
396 rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
397
398 if (is_set(flags, pe_weights_forward)) {
399 other = constraint->rsc_rh;
400 } else {
401 other = constraint->rsc_lh;
402 }
403
404 pe_rsc_trace(rsc, "Applying %s (%s)", constraint->id, other->id);
405 work = rsc_merge_weights(other, rhs, work, constraint->node_attribute,
406 multiplier * (float)constraint->score / INFINITY, flags|pe_weights_rollback);
407 dump_node_scores(LOG_TRACE, NULL, rhs, work);
408 }
409
410 }
411
412 if (is_set(flags, pe_weights_positive)) {
413 node_t *node = NULL;
414 GHashTableIter iter;
415
416 g_hash_table_iter_init(&iter, work);
417 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
418 if (node->weight == INFINITY_HACK) {
419 node->weight = 1;
420 }
421 }
422 }
423
424 if (nodes) {
425 g_hash_table_destroy(nodes);
426 }
427
428 clear_bit(rsc->flags, pe_rsc_merging);
429 return work;
430 }
431
432 node_t *
433 native_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
434 {
435 GListPtr gIter = NULL;
436 int alloc_details = scores_log_level + 1;
437
438 if (rsc->parent && is_not_set(rsc->parent->flags, pe_rsc_allocating)) {
439
440 pe_rsc_debug(rsc, "Escalating allocation of %s to its parent: %s", rsc->id,
441 rsc->parent->id);
442 rsc->parent->cmds->allocate(rsc->parent, prefer, data_set);
443 }
444
445 if (is_not_set(rsc->flags, pe_rsc_provisional)) {
446 return rsc->allocated_to;
447 }
448
449 if (is_set(rsc->flags, pe_rsc_allocating)) {
450 pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
451 return NULL;
452 }
453
454 set_bit(rsc->flags, pe_rsc_allocating);
455 print_resource(alloc_details, "Allocating: ", rsc, FALSE);
456 dump_node_scores(alloc_details, rsc, "Pre-alloc", rsc->allowed_nodes);
457
458 for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) {
459 rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
460
461 GHashTable *archive = NULL;
462 resource_t *rsc_rh = constraint->rsc_rh;
463
464 pe_rsc_trace(rsc, "%s: Pre-Processing %s (%s, %d, %s)",
465 rsc->id, constraint->id, rsc_rh->id,
466 constraint->score, role2text(constraint->role_lh));
467 if (constraint->role_lh >= RSC_ROLE_MASTER
468 || (constraint->score < 0 && constraint->score > -INFINITY)) {
469 archive = node_hash_dup(rsc->allowed_nodes);
470 }
471 rsc_rh->cmds->allocate(rsc_rh, NULL, data_set);
472 rsc->cmds->rsc_colocation_lh(rsc, rsc_rh, constraint);
473 if (archive && can_run_any(rsc->allowed_nodes) == FALSE) {
474 pe_rsc_info(rsc, "%s: Rolling back scores from %s", rsc->id, rsc_rh->id);
475 g_hash_table_destroy(rsc->allowed_nodes);
476 rsc->allowed_nodes = archive;
477 archive = NULL;
478 }
479 if (archive) {
480 g_hash_table_destroy(archive);
481 }
482 }
483
484 dump_node_scores(alloc_details, rsc, "Post-coloc", rsc->allowed_nodes);
485
486 for (gIter = rsc->rsc_cons_lhs; gIter != NULL; gIter = gIter->next) {
487 rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
488
489 rsc->allowed_nodes =
490 constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id, rsc->allowed_nodes,
491 constraint->node_attribute,
492 (float)constraint->score / INFINITY,
493 pe_weights_rollback);
494 }
495
496 print_resource(LOG_DEBUG_2, "Allocating: ", rsc, FALSE);
497 if (rsc->next_role == RSC_ROLE_STOPPED) {
498 pe_rsc_trace(rsc, "Making sure %s doesn't get allocated", rsc->id);
499
500 resource_location(rsc, NULL, -INFINITY, XML_RSC_ATTR_TARGET_ROLE, data_set);
501
502 } else if(rsc->next_role > rsc->role
503 && is_set(data_set->flags, pe_flag_have_quorum) == FALSE
504 && data_set->no_quorum_policy == no_quorum_freeze) {
505 crm_notice("Resource %s cannot be elevated from %s to %s: no-quorum-policy=freeze",
506 rsc->id, role2text(rsc->role), role2text(rsc->next_role));
507 rsc->next_role = rsc->role;
508 }
509
510 dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__,
511 rsc->allowed_nodes);
512 if (is_set(data_set->flags, pe_flag_stonith_enabled)
513 && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) {
514 clear_bit(rsc->flags, pe_rsc_managed);
515 }
516
517 if (is_not_set(rsc->flags, pe_rsc_managed)) {
518 const char *reason = NULL;
519 node_t *assign_to = NULL;
520
521 rsc->next_role = rsc->role;
522 if (rsc->running_on == NULL) {
523 reason = "inactive";
524 } else if (rsc->role == RSC_ROLE_MASTER) {
525 assign_to = rsc->running_on->data;
526 reason = "master";
527 } else if (is_set(rsc->flags, pe_rsc_failed)) {
528 assign_to = rsc->running_on->data;
529 reason = "failed";
530 } else {
531 assign_to = rsc->running_on->data;
532 reason = "active";
533 }
534 pe_rsc_info(rsc, "Unmanaged resource %s allocated to %s: %s", rsc->id,
535 (assign_to? assign_to->details->uname : "no node"), reason);
536 native_assign_node(rsc, NULL, assign_to, TRUE);
537
538 } else if (is_set(data_set->flags, pe_flag_stop_everything)) {
539 pe_rsc_debug(rsc, "Forcing %s to stop", rsc->id);
540 native_assign_node(rsc, NULL, NULL, TRUE);
541
542 } else if (is_set(rsc->flags, pe_rsc_provisional)
543 && native_choose_node(rsc, prefer, data_set)) {
544 pe_rsc_trace(rsc, "Allocated resource %s to %s", rsc->id,
545 rsc->allocated_to->details->uname);
546
547 } else if (rsc->allocated_to == NULL) {
548 if (is_not_set(rsc->flags, pe_rsc_orphan)) {
549 pe_rsc_info(rsc, "Resource %s cannot run anywhere", rsc->id);
550 } else if (rsc->running_on != NULL) {
551 pe_rsc_info(rsc, "Stopping orphan resource %s", rsc->id);
552 }
553
554 } else {
555 pe_rsc_debug(rsc, "Pre-Allocated resource %s to %s", rsc->id,
556 rsc->allocated_to->details->uname);
557 }
558
559 clear_bit(rsc->flags, pe_rsc_allocating);
560 print_resource(LOG_DEBUG_3, "Allocated ", rsc, TRUE);
561
562 if (rsc->is_remote_node) {
563 node_t *remote_node = pe_find_node(data_set->nodes, rsc->id);
564
565 CRM_ASSERT(remote_node != NULL);
566 if (rsc->allocated_to && rsc->next_role != RSC_ROLE_STOPPED) {
567 crm_trace("Setting Pacemaker Remote node %s to ONLINE",
568 remote_node->details->id);
569 remote_node->details->online = TRUE;
570
571
572 if (remote_node->details->unseen == TRUE) {
573 remote_node->details->unclean = FALSE;
574 }
575
576 } else {
577 crm_trace("Setting Pacemaker Remote node %s to SHUTDOWN (next role %s, %sallocated)",
578 remote_node->details->id, role2text(rsc->next_role),
579 (rsc->allocated_to? "" : "un"));
580 remote_node->details->shutdown = TRUE;
581 }
582 }
583
584 return rsc->allocated_to;
585 }
586
587 static gboolean
588 is_op_dup(resource_t * rsc, const char *name, const char *interval)
589 {
590 gboolean dup = FALSE;
591 const char *id = NULL;
592 const char *value = NULL;
593 xmlNode *operation = NULL;
594
595 CRM_ASSERT(rsc);
596 for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
597 operation = __xml_next_element(operation)) {
598 if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
599 value = crm_element_value(operation, "name");
600 if (safe_str_neq(value, name)) {
601 continue;
602 }
603
604 value = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
605 if (value == NULL) {
606 value = "0";
607 }
608
609 if (safe_str_neq(value, interval)) {
610 continue;
611 }
612
613 if (id == NULL) {
614 id = ID(operation);
615
616 } else {
617 crm_config_err("Operation %s is a duplicate of %s", ID(operation), id);
618 crm_config_err
619 ("Do not use the same (name, interval) combination more than once per resource");
620 dup = TRUE;
621 }
622 }
623 }
624
625 return dup;
626 }
627
628 void
629 RecurringOp(resource_t * rsc, action_t * start, node_t * node,
630 xmlNode * operation, pe_working_set_t * data_set)
631 {
632 char *key = NULL;
633 const char *name = NULL;
634 const char *value = NULL;
635 const char *interval = NULL;
636 const char *node_uname = NULL;
637
638 unsigned long long interval_ms = 0;
639 action_t *mon = NULL;
640 gboolean is_optional = TRUE;
641 GListPtr possible_matches = NULL;
642
643
644 value = crm_element_value(operation, "role");
645 if (value && text2role(value) == RSC_ROLE_STOPPED) {
646 return;
647 }
648
649 CRM_ASSERT(rsc);
650 pe_rsc_trace(rsc, "Creating recurring action %s for %s in role %s on %s",
651 ID(operation), rsc->id, role2text(rsc->next_role),
652 node ? node->details->uname : "n/a");
653
654 if (node != NULL) {
655 node_uname = node->details->uname;
656 }
657
658 interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
659 interval_ms = crm_get_interval(interval);
660
661 if (interval_ms == 0) {
662 return;
663 }
664
665 name = crm_element_value(operation, "name");
666 if (is_op_dup(rsc, name, interval)) {
667 return;
668 }
669
670 if (safe_str_eq(name, RSC_STOP)
671 || safe_str_eq(name, RSC_START)
672 || safe_str_eq(name, RSC_DEMOTE)
673 || safe_str_eq(name, RSC_PROMOTE)
674 ) {
675 crm_config_err("Invalid recurring action %s wth name: '%s'", ID(operation), name);
676 return;
677 }
678
679 key = generate_op_key(rsc->id, name, interval_ms);
680 if (find_rsc_op_entry(rsc, key) == NULL) {
681
682 free(key);
683 return;
684 }
685
686 if (start != NULL) {
687 pe_rsc_trace(rsc, "Marking %s %s due to %s",
688 key, is_set(start->flags, pe_action_optional) ? "optional" : "mandatory",
689 start->uuid);
690 is_optional = (rsc->cmds->action_flags(start, NULL) & pe_action_optional);
691 } else {
692 pe_rsc_trace(rsc, "Marking %s optional", key);
693 is_optional = TRUE;
694 }
695
696
697 possible_matches = find_actions_exact(rsc->actions, key, node);
698 if (possible_matches == NULL) {
699 is_optional = FALSE;
700 pe_rsc_trace(rsc, "Marking %s mandatory: not active", key);
701
702 } else {
703 GListPtr gIter = NULL;
704
705 for (gIter = possible_matches; gIter != NULL; gIter = gIter->next) {
706 action_t *op = (action_t *) gIter->data;
707
708 if (is_set(op->flags, pe_action_reschedule)) {
709 is_optional = FALSE;
710 break;
711 }
712 }
713 g_list_free(possible_matches);
714 }
715
716 if ((rsc->next_role == RSC_ROLE_MASTER && value == NULL)
717 || (value != NULL && text2role(value) != rsc->next_role)) {
718 int log_level = LOG_DEBUG_2;
719 const char *result = "Ignoring";
720
721 if (is_optional) {
722 char *local_key = strdup(key);
723
724 log_level = LOG_INFO;
725 result = "Cancelling";
726
727
728 mon = custom_action(rsc, local_key, RSC_CANCEL, node, FALSE, TRUE, data_set);
729
730 free(mon->task);
731 free(mon->cancel_task);
732 mon->task = strdup(RSC_CANCEL);
733 mon->cancel_task = strdup(name);
734 add_hash_param(mon->meta, XML_LRM_ATTR_INTERVAL, interval);
735 add_hash_param(mon->meta, XML_LRM_ATTR_TASK, name);
736
737 local_key = NULL;
738
739 switch (rsc->role) {
740 case RSC_ROLE_SLAVE:
741 case RSC_ROLE_STARTED:
742 if (rsc->next_role == RSC_ROLE_MASTER) {
743 local_key = promote_key(rsc);
744
745 } else if (rsc->next_role == RSC_ROLE_STOPPED) {
746 local_key = stop_key(rsc);
747 }
748
749 break;
750 case RSC_ROLE_MASTER:
751 local_key = demote_key(rsc);
752 break;
753 default:
754 break;
755 }
756
757 if (local_key) {
758 custom_action_order(rsc, NULL, mon, rsc, local_key, NULL,
759 pe_order_runnable_left, data_set);
760 }
761
762 mon = NULL;
763 }
764
765 do_crm_log(log_level, "%s action %s (%s vs. %s)",
766 result, key, value ? value : role2text(RSC_ROLE_SLAVE),
767 role2text(rsc->next_role));
768
769 free(key);
770 return;
771 }
772
773 mon = custom_action(rsc, key, name, node, is_optional, TRUE, data_set);
774 key = mon->uuid;
775 if (is_optional) {
776 pe_rsc_trace(rsc, "%s\t %s (optional)", crm_str(node_uname), mon->uuid);
777 }
778
779 if (start == NULL || is_set(start->flags, pe_action_runnable) == FALSE) {
780 pe_rsc_debug(rsc, "%s\t %s (cancelled : start un-runnable)", crm_str(node_uname),
781 mon->uuid);
782 update_action_flags(mon, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
783
784 } else if (node == NULL || node->details->online == FALSE || node->details->unclean) {
785 pe_rsc_debug(rsc, "%s\t %s (cancelled : no node available)", crm_str(node_uname),
786 mon->uuid);
787 update_action_flags(mon, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
788
789 } else if (is_set(mon->flags, pe_action_optional) == FALSE) {
790 pe_rsc_info(rsc, " Start recurring %s (%llus) for %s on %s", mon->task, interval_ms / 1000,
791 rsc->id, crm_str(node_uname));
792 }
793
794 if (rsc->next_role == RSC_ROLE_MASTER) {
795 char *running_master = crm_itoa(PCMK_OCF_RUNNING_MASTER);
796
797 add_hash_param(mon->meta, XML_ATTR_TE_TARGET_RC, running_master);
798 free(running_master);
799 }
800
801 if (node == NULL || is_set(rsc->flags, pe_rsc_managed)) {
802 custom_action_order(rsc, start_key(rsc), NULL,
803 NULL, strdup(key), mon,
804 pe_order_implies_then | pe_order_runnable_left, data_set);
805
806 custom_action_order(rsc, reload_key(rsc), NULL,
807 NULL, strdup(key), mon,
808 pe_order_implies_then | pe_order_runnable_left, data_set);
809
810 if (rsc->next_role == RSC_ROLE_MASTER) {
811 custom_action_order(rsc, promote_key(rsc), NULL,
812 rsc, NULL, mon,
813 pe_order_optional | pe_order_runnable_left, data_set);
814
815 } else if (rsc->role == RSC_ROLE_MASTER) {
816 custom_action_order(rsc, demote_key(rsc), NULL,
817 rsc, NULL, mon,
818 pe_order_optional | pe_order_runnable_left, data_set);
819 }
820 }
821 }
822
823 void
824 Recurring(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set)
825 {
826 if (is_not_set(rsc->flags, pe_rsc_maintenance) &&
827 (node == NULL || node->details->maintenance == FALSE)) {
828 xmlNode *operation = NULL;
829
830 for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
831 operation = __xml_next_element(operation)) {
832 if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
833 RecurringOp(rsc, start, node, operation, data_set);
834 }
835 }
836 }
837 }
838
839 void
840 RecurringOp_Stopped(resource_t * rsc, action_t * start, node_t * node,
841 xmlNode * operation, pe_working_set_t * data_set)
842 {
843 char *key = NULL;
844 const char *name = NULL;
845 const char *role = NULL;
846 const char *interval = NULL;
847 const char *node_uname = NULL;
848
849 unsigned long long interval_ms = 0;
850 GListPtr possible_matches = NULL;
851 GListPtr gIter = NULL;
852
853
854 if (is_set(rsc->flags, pe_rsc_unique) == FALSE) {
855 return;
856 }
857
858
859 role = crm_element_value(operation, "role");
860 if (role == NULL || text2role(role) != RSC_ROLE_STOPPED) {
861 return;
862 }
863
864 pe_rsc_trace(rsc,
865 "Creating recurring actions %s for %s in role %s on nodes where it'll not be running",
866 ID(operation), rsc->id, role2text(rsc->next_role));
867
868 if (node != NULL) {
869 node_uname = node->details->uname;
870 }
871
872 interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
873 interval_ms = crm_get_interval(interval);
874
875 if (interval_ms == 0) {
876 return;
877 }
878
879 name = crm_element_value(operation, "name");
880 if (is_op_dup(rsc, name, interval)) {
881 return;
882 }
883
884 if (safe_str_eq(name, RSC_STOP)
885 || safe_str_eq(name, RSC_START)
886 || safe_str_eq(name, RSC_DEMOTE)
887 || safe_str_eq(name, RSC_PROMOTE)
888 ) {
889 crm_config_err("Invalid recurring action %s wth name: '%s'", ID(operation), name);
890 return;
891 }
892
893 key = generate_op_key(rsc->id, name, interval_ms);
894 if (find_rsc_op_entry(rsc, key) == NULL) {
895
896 free(key);
897 return;
898 }
899
900
901 if (node != NULL) {
902 possible_matches = find_actions_exact(rsc->actions, key, node);
903 if (possible_matches) {
904 action_t *cancel_op = NULL;
905 char *local_key = strdup(key);
906
907 g_list_free(possible_matches);
908
909 cancel_op = custom_action(rsc, local_key, RSC_CANCEL, node, FALSE, TRUE, data_set);
910
911 free(cancel_op->task);
912 free(cancel_op->cancel_task);
913 cancel_op->task = strdup(RSC_CANCEL);
914 cancel_op->cancel_task = strdup(name);
915 add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL, interval);
916 add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, name);
917
918 local_key = NULL;
919
920 if (rsc->next_role == RSC_ROLE_STARTED || rsc->next_role == RSC_ROLE_SLAVE) {
921
922
923 custom_action_order(rsc, NULL, cancel_op, rsc, start_key(rsc), NULL,
924 pe_order_runnable_left, data_set);
925 }
926
927 pe_rsc_info(rsc, "Cancel action %s (%s vs. %s) on %s",
928 key, role, role2text(rsc->next_role), crm_str(node_uname));
929 }
930 }
931
932 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
933 node_t *stop_node = (node_t *) gIter->data;
934 const char *stop_node_uname = stop_node->details->uname;
935 gboolean is_optional = TRUE;
936 gboolean probe_is_optional = TRUE;
937 gboolean stop_is_optional = TRUE;
938 action_t *stopped_mon = NULL;
939 char *rc_inactive = NULL;
940 GListPtr probe_complete_ops = NULL;
941 GListPtr stop_ops = NULL;
942 GListPtr local_gIter = NULL;
943 char *stop_op_key = NULL;
944
945 if (node_uname && safe_str_eq(stop_node_uname, node_uname)) {
946 continue;
947 }
948
949 pe_rsc_trace(rsc, "Creating recurring action %s for %s on %s",
950 ID(operation), rsc->id, crm_str(stop_node_uname));
951
952
953 possible_matches = find_actions_exact(rsc->actions, key, stop_node);
954 if (possible_matches == NULL) {
955 pe_rsc_trace(rsc, "Marking %s mandatory on %s: not active", key,
956 crm_str(stop_node_uname));
957 is_optional = FALSE;
958 } else {
959 pe_rsc_trace(rsc, "Marking %s optional on %s: already active", key,
960 crm_str(stop_node_uname));
961 is_optional = TRUE;
962 g_list_free(possible_matches);
963 }
964
965 stopped_mon = custom_action(rsc, strdup(key), name, stop_node, is_optional, TRUE, data_set);
966
967 rc_inactive = crm_itoa(PCMK_OCF_NOT_RUNNING);
968 add_hash_param(stopped_mon->meta, XML_ATTR_TE_TARGET_RC, rc_inactive);
969 free(rc_inactive);
970
971 if (is_set(rsc->flags, pe_rsc_managed)) {
972 char *probe_key = generate_op_key(rsc->id, CRMD_ACTION_STATUS, 0);
973 GListPtr probes = find_actions(rsc->actions, probe_key, stop_node);
974 GListPtr pIter = NULL;
975
976 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
977 action_t *probe = (action_t *) pIter->data;
978
979 order_actions(probe, stopped_mon, pe_order_runnable_left);
980 crm_trace("%s then %s on %s", probe->uuid, stopped_mon->uuid, stop_node->details->uname);
981 }
982
983 g_list_free(probes);
984 free(probe_key);
985 }
986
987 if (probe_complete_ops) {
988 g_list_free(probe_complete_ops);
989 }
990
991 stop_op_key = stop_key(rsc);
992 stop_ops = find_actions_exact(rsc->actions, stop_op_key, stop_node);
993
994 for (local_gIter = stop_ops; local_gIter != NULL; local_gIter = local_gIter->next) {
995 action_t *stop = (action_t *) local_gIter->data;
996
997 if (is_set(stop->flags, pe_action_optional) == FALSE) {
998 stop_is_optional = FALSE;
999 }
1000
1001 if (is_set(stop->flags, pe_action_runnable) == FALSE) {
1002 crm_debug("%s\t %s (cancelled : stop un-runnable)",
1003 crm_str(stop_node_uname), stopped_mon->uuid);
1004 update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
1005 }
1006
1007 if (is_set(rsc->flags, pe_rsc_managed)) {
1008 custom_action_order(rsc, strdup(stop_op_key), stop,
1009 NULL, strdup(key), stopped_mon,
1010 pe_order_implies_then | pe_order_runnable_left, data_set);
1011 }
1012
1013 }
1014
1015 if (stop_ops) {
1016 g_list_free(stop_ops);
1017 }
1018 free(stop_op_key);
1019
1020 if (is_optional == FALSE && probe_is_optional && stop_is_optional
1021 && is_set(rsc->flags, pe_rsc_managed) == FALSE) {
1022 pe_rsc_trace(rsc, "Marking %s optional on %s due to unmanaged",
1023 key, crm_str(stop_node_uname));
1024 update_action_flags(stopped_mon, pe_action_optional, __FUNCTION__, __LINE__);
1025 }
1026
1027 if (is_set(stopped_mon->flags, pe_action_optional)) {
1028 pe_rsc_trace(rsc, "%s\t %s (optional)", crm_str(stop_node_uname), stopped_mon->uuid);
1029 }
1030
1031 if (stop_node->details->online == FALSE || stop_node->details->unclean) {
1032 pe_rsc_debug(rsc, "%s\t %s (cancelled : no node available)",
1033 crm_str(stop_node_uname), stopped_mon->uuid);
1034 update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
1035 }
1036
1037 if (is_set(stopped_mon->flags, pe_action_runnable)
1038 && is_set(stopped_mon->flags, pe_action_optional) == FALSE) {
1039 crm_notice(" Start recurring %s (%llus) for %s on %s", stopped_mon->task,
1040 interval_ms / 1000, rsc->id, crm_str(stop_node_uname));
1041 }
1042 }
1043
1044 free(key);
1045 }
1046
1047 void
1048 Recurring_Stopped(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set)
1049 {
1050 if (is_not_set(rsc->flags, pe_rsc_maintenance) &&
1051 (node == NULL || node->details->maintenance == FALSE)) {
1052 xmlNode *operation = NULL;
1053
1054 for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
1055 operation = __xml_next_element(operation)) {
1056 if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
1057 RecurringOp_Stopped(rsc, start, node, operation, data_set);
1058 }
1059 }
1060 }
1061 }
1062
1063 static void
1064 handle_migration_actions(resource_t * rsc, node_t *current, node_t *chosen, pe_working_set_t * data_set)
1065 {
1066 action_t *migrate_to = NULL;
1067 action_t *migrate_from = NULL;
1068 action_t *start = NULL;
1069 action_t *stop = NULL;
1070 gboolean partial = rsc->partial_migration_target ? TRUE : FALSE;
1071
1072 pe_rsc_trace(rsc, "Processing migration actions %s moving from %s to %s . partial migration = %s",
1073 rsc->id, current->details->id, chosen->details->id, partial ? "TRUE" : "FALSE");
1074 start = start_action(rsc, chosen, TRUE);
1075 stop = stop_action(rsc, current, TRUE);
1076
1077 if (partial == FALSE) {
1078 migrate_to = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), RSC_MIGRATE, current, TRUE, TRUE, data_set);
1079 }
1080
1081 migrate_from = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), RSC_MIGRATED, chosen, TRUE, TRUE, data_set);
1082
1083 if ((migrate_to && migrate_from) || (migrate_from && partial)) {
1084
1085 set_bit(start->flags, pe_action_migrate_runnable);
1086 set_bit(stop->flags, pe_action_migrate_runnable);
1087
1088 update_action_flags(start, pe_action_pseudo, __FUNCTION__, __LINE__);
1089
1090
1091 if (partial) {
1092 set_bit(migrate_from->flags, pe_action_migrate_runnable);
1093 migrate_from->needs = start->needs;
1094
1095 custom_action_order(rsc, generate_op_key(rsc->id, RSC_STATUS, 0), NULL,
1096 rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), NULL, pe_order_optional, data_set);
1097
1098 } else {
1099 set_bit(migrate_from->flags, pe_action_migrate_runnable);
1100 set_bit(migrate_to->flags, pe_action_migrate_runnable);
1101 migrate_to->needs = start->needs;
1102
1103 custom_action_order(rsc, generate_op_key(rsc->id, RSC_STATUS, 0), NULL,
1104 rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), NULL, pe_order_optional, data_set);
1105 custom_action_order(rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), NULL,
1106 rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), NULL, pe_order_optional | pe_order_implies_first_migratable, data_set);
1107 }
1108
1109 custom_action_order(rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), NULL,
1110 rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL, pe_order_optional | pe_order_implies_first_migratable, data_set);
1111 custom_action_order(rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), NULL,
1112 rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, pe_order_optional | pe_order_implies_first_migratable | pe_order_pseudo_left, data_set);
1113
1114 }
1115
1116 if (migrate_to) {
1117 add_hash_param(migrate_to->meta, XML_LRM_ATTR_MIGRATE_SOURCE, current->details->uname);
1118 add_hash_param(migrate_to->meta, XML_LRM_ATTR_MIGRATE_TARGET, chosen->details->uname);
1119
1120
1121
1122
1123 if (rsc->is_remote_node == FALSE) {
1124
1125
1126
1127
1128
1129
1130 add_hash_param(migrate_to->meta, XML_OP_ATTR_PENDING, "true");
1131 }
1132 }
1133
1134 if (migrate_from) {
1135 add_hash_param(migrate_from->meta, XML_LRM_ATTR_MIGRATE_SOURCE, current->details->uname);
1136 add_hash_param(migrate_from->meta, XML_LRM_ATTR_MIGRATE_TARGET, chosen->details->uname);
1137 }
1138 }
1139
1140 void
1141 native_create_actions(resource_t * rsc, pe_working_set_t * data_set)
1142 {
1143 action_t *start = NULL;
1144 node_t *chosen = NULL;
1145 node_t *current = NULL;
1146 gboolean need_stop = FALSE;
1147 gboolean is_moving = FALSE;
1148 gboolean allow_migrate = is_set(rsc->flags, pe_rsc_allow_migrate) ? TRUE : FALSE;
1149
1150 GListPtr gIter = NULL;
1151 int num_active_nodes = 0;
1152 enum rsc_role_e role = RSC_ROLE_UNKNOWN;
1153 enum rsc_role_e next_role = RSC_ROLE_UNKNOWN;
1154
1155 CRM_ASSERT(rsc);
1156 chosen = rsc->allocated_to;
1157 if (chosen != NULL && rsc->next_role == RSC_ROLE_UNKNOWN) {
1158 rsc->next_role = RSC_ROLE_STARTED;
1159 pe_rsc_trace(rsc, "Fixed next_role: unknown -> %s", role2text(rsc->next_role));
1160
1161 } else if (rsc->next_role == RSC_ROLE_UNKNOWN) {
1162 rsc->next_role = RSC_ROLE_STOPPED;
1163 pe_rsc_trace(rsc, "Fixed next_role: unknown -> %s", role2text(rsc->next_role));
1164 }
1165
1166 pe_rsc_trace(rsc, "Processing state transition for %s %p: %s->%s", rsc->id, rsc,
1167 role2text(rsc->role), role2text(rsc->next_role));
1168
1169 if (rsc->running_on) {
1170 current = rsc->running_on->data;
1171 }
1172
1173 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
1174 node_t *n = (node_t *) gIter->data;
1175 if (rsc->partial_migration_source &&
1176 (n->details == rsc->partial_migration_source->details)) {
1177 current = rsc->partial_migration_source;
1178 }
1179 num_active_nodes++;
1180 }
1181
1182 for (gIter = rsc->dangling_migrations; gIter != NULL; gIter = gIter->next) {
1183 node_t *current = (node_t *) gIter->data;
1184
1185 action_t *stop = stop_action(rsc, current, FALSE);
1186
1187 set_bit(stop->flags, pe_action_dangle);
1188 pe_rsc_trace(rsc, "Forcing a cleanup of %s on %s", rsc->id, current->details->uname);
1189
1190 if (is_set(data_set->flags, pe_flag_remove_after_stop)) {
1191 DeleteRsc(rsc, current, FALSE, data_set);
1192 }
1193 }
1194
1195 if (num_active_nodes > 1) {
1196
1197 if (num_active_nodes == 2
1198 && chosen
1199 && rsc->partial_migration_target
1200 && rsc->partial_migration_source
1201 && (current->details == rsc->partial_migration_source->details)
1202 && (chosen->details == rsc->partial_migration_target->details)) {
1203
1204
1205
1206 pe_rsc_trace(rsc,
1207 "Will attempt to continue with a partial migration to target %s from %s",
1208 rsc->partial_migration_target->details->id,
1209 rsc->partial_migration_source->details->id);
1210 } else {
1211 const char *type = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1212 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1213
1214 if(rsc->partial_migration_target && rsc->partial_migration_source) {
1215 crm_notice("Resource %s can no longer migrate to %s. Stopping on %s too", rsc->id,
1216 rsc->partial_migration_target->details->uname,
1217 rsc->partial_migration_source->details->uname);
1218
1219 } else {
1220 pe_proc_err("Resource %s (%s::%s) is active on %d nodes %s",
1221 rsc->id, class, type, num_active_nodes, recovery2text(rsc->recovery_type));
1222 crm_warn("See %s for more information.",
1223 "http://clusterlabs.org/wiki/FAQ#Resource_is_Too_Active");
1224 }
1225
1226 if (rsc->recovery_type == recovery_stop_start) {
1227 need_stop = TRUE;
1228 }
1229
1230
1231
1232
1233 rsc->partial_migration_source = rsc->partial_migration_target = NULL;
1234 allow_migrate = FALSE;
1235 }
1236 }
1237
1238 if (is_set(rsc->flags, pe_rsc_start_pending)) {
1239 start = start_action(rsc, chosen, TRUE);
1240 set_bit(start->flags, pe_action_print_always);
1241 }
1242
1243 if (current && chosen && current->details != chosen->details) {
1244 pe_rsc_trace(rsc, "Moving %s", rsc->id);
1245 is_moving = TRUE;
1246 need_stop = TRUE;
1247
1248 } else if (is_set(rsc->flags, pe_rsc_failed)) {
1249 pe_rsc_trace(rsc, "Recovering %s", rsc->id);
1250 need_stop = TRUE;
1251
1252 } else if (is_set(rsc->flags, pe_rsc_block)) {
1253 pe_rsc_trace(rsc, "Block %s", rsc->id);
1254 need_stop = TRUE;
1255
1256 } else if (rsc->role > RSC_ROLE_STARTED && current != NULL && chosen != NULL) {
1257
1258 start = start_action(rsc, chosen, TRUE);
1259 if (is_set(start->flags, pe_action_optional) == FALSE) {
1260 pe_rsc_trace(rsc, "Forced start %s", rsc->id);
1261 need_stop = TRUE;
1262 }
1263 }
1264
1265 pe_rsc_trace(rsc, "Creating actions for %s: %s->%s", rsc->id,
1266 role2text(rsc->role), role2text(rsc->next_role));
1267
1268
1269
1270
1271 role = rsc->role;
1272 while (role != RSC_ROLE_STOPPED) {
1273 next_role = rsc_state_matrix[role][RSC_ROLE_STOPPED];
1274 pe_rsc_trace(rsc, "Down: Executing: %s->%s (%s)%s", role2text(role), role2text(next_role),
1275 rsc->id, need_stop ? " required" : "");
1276 if (rsc_action_matrix[role][next_role] (rsc, current, !need_stop, data_set) == FALSE) {
1277 break;
1278 }
1279 role = next_role;
1280 }
1281
1282
1283 while (rsc->role <= rsc->next_role && role != rsc->role && is_not_set(rsc->flags, pe_rsc_block)) {
1284 next_role = rsc_state_matrix[role][rsc->role];
1285 pe_rsc_trace(rsc, "Up: Executing: %s->%s (%s)%s", role2text(role), role2text(next_role),
1286 rsc->id, need_stop ? " required" : "");
1287 if (rsc_action_matrix[role][next_role] (rsc, chosen, !need_stop, data_set) == FALSE) {
1288 break;
1289 }
1290 role = next_role;
1291 }
1292 role = rsc->role;
1293
1294
1295 while (role != rsc->next_role) {
1296 next_role = rsc_state_matrix[role][rsc->next_role];
1297 pe_rsc_trace(rsc, "Role: Executing: %s->%s = (%s on %s)", role2text(role), role2text(next_role), rsc->id, chosen?chosen->details->uname:"NA");
1298 if (rsc_action_matrix[role][next_role] (rsc, chosen, FALSE, data_set) == FALSE) {
1299 break;
1300 }
1301 role = next_role;
1302 }
1303
1304 if(is_set(rsc->flags, pe_rsc_block)) {
1305 pe_rsc_trace(rsc, "No monitor additional ops for blocked resource");
1306
1307 } else if (rsc->next_role != RSC_ROLE_STOPPED || is_set(rsc->flags, pe_rsc_managed) == FALSE) {
1308 pe_rsc_trace(rsc, "Monitor ops for active resource");
1309 start = start_action(rsc, chosen, TRUE);
1310 Recurring(rsc, start, chosen, data_set);
1311 Recurring_Stopped(rsc, start, chosen, data_set);
1312 } else {
1313 pe_rsc_trace(rsc, "Monitor ops for in-active resource");
1314 Recurring_Stopped(rsc, NULL, NULL, data_set);
1315 }
1316
1317
1318
1319
1320 if (rsc->partial_migration_target && (chosen == NULL || rsc->partial_migration_target->details != chosen->details)) {
1321 pe_rsc_trace(rsc, "Not allowing partial migration to continue. %s", rsc->id);
1322 allow_migrate = FALSE;
1323
1324 } else if (is_moving == FALSE ||
1325 is_not_set(rsc->flags, pe_rsc_managed) ||
1326 is_set(rsc->flags, pe_rsc_failed) ||
1327 is_set(rsc->flags, pe_rsc_start_pending) ||
1328 (current->details->unclean == TRUE) ||
1329 rsc->next_role < RSC_ROLE_STARTED) {
1330
1331 allow_migrate = FALSE;
1332 }
1333
1334 if (allow_migrate) {
1335 handle_migration_actions(rsc, current, chosen, data_set);
1336 }
1337 }
1338
1339 static void
1340 rsc_avoids_remote_nodes(resource_t *rsc)
1341 {
1342 GHashTableIter iter;
1343 node_t *node = NULL;
1344 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1345 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1346 if (node->details->remote_rsc) {
1347 node->weight = -INFINITY;
1348 }
1349 }
1350 }
1351
1352 void
1353 native_internal_constraints(resource_t * rsc, pe_working_set_t * data_set)
1354 {
1355
1356
1357 resource_t *top = uber_parent(rsc);
1358 int type = pe_order_optional | pe_order_implies_then | pe_order_restart;
1359 gboolean is_stonith = is_set(rsc->flags, pe_rsc_fence_device);
1360
1361 custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
1362 rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, type, data_set);
1363
1364 if (top->variant == pe_master || rsc->role > RSC_ROLE_SLAVE) {
1365 custom_action_order(rsc, generate_op_key(rsc->id, RSC_DEMOTE, 0), NULL,
1366 rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
1367 pe_order_implies_first_master, data_set);
1368
1369 custom_action_order(rsc, generate_op_key(rsc->id, RSC_START, 0), NULL,
1370 rsc, generate_op_key(rsc->id, RSC_PROMOTE, 0), NULL,
1371 pe_order_runnable_left, data_set);
1372 }
1373
1374 if (is_stonith == FALSE
1375 && is_set(data_set->flags, pe_flag_enable_unfencing)
1376 && is_set(rsc->flags, pe_rsc_needs_unfencing)) {
1377
1378 node_t *node = NULL;
1379 GHashTableIter iter;
1380
1381 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1382 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1383 action_t *unfence = pe_fence_op(node, "on", TRUE, NULL, data_set);
1384
1385 crm_debug("Ordering any stops of %s before %s, and any starts after",
1386 rsc->id, unfence->uuid);
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403 custom_action_order(rsc, stop_key(rsc), NULL,
1404 NULL, strdup(unfence->uuid), unfence,
1405 pe_order_optional|pe_order_same_node, data_set);
1406
1407 custom_action_order(NULL, strdup(unfence->uuid), unfence,
1408 rsc, start_key(rsc), NULL,
1409 pe_order_implies_then_on_node|pe_order_same_node,
1410 data_set);
1411 }
1412 }
1413
1414 if (is_not_set(rsc->flags, pe_rsc_managed)) {
1415 pe_rsc_trace(rsc, "Skipping fencing constraints for unmanaged resource: %s", rsc->id);
1416 return;
1417 }
1418
1419 {
1420 action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set);
1421
1422 custom_action_order(rsc, stop_key(rsc), NULL,
1423 NULL, strdup(all_stopped->task), all_stopped,
1424 pe_order_implies_then | pe_order_runnable_left, data_set);
1425 }
1426
1427 if (g_hash_table_size(rsc->utilization) > 0
1428 && safe_str_neq(data_set->placement_strategy, "default")) {
1429 GHashTableIter iter;
1430 node_t *next = NULL;
1431 GListPtr gIter = NULL;
1432
1433 pe_rsc_trace(rsc, "Creating utilization constraints for %s - strategy: %s",
1434 rsc->id, data_set->placement_strategy);
1435
1436 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
1437 node_t *current = (node_t *) gIter->data;
1438
1439 char *load_stopped_task = crm_concat(LOAD_STOPPED, current->details->uname, '_');
1440 action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set);
1441
1442 if (load_stopped->node == NULL) {
1443 load_stopped->node = node_copy(current);
1444 update_action_flags(load_stopped, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__);
1445 }
1446
1447 custom_action_order(rsc, stop_key(rsc), NULL,
1448 NULL, load_stopped_task, load_stopped, pe_order_load, data_set);
1449 }
1450
1451 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1452 while (g_hash_table_iter_next(&iter, NULL, (void **)&next)) {
1453 char *load_stopped_task = crm_concat(LOAD_STOPPED, next->details->uname, '_');
1454 action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set);
1455
1456 if (load_stopped->node == NULL) {
1457 load_stopped->node = node_copy(next);
1458 update_action_flags(load_stopped, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__);
1459 }
1460
1461 custom_action_order(NULL, strdup(load_stopped_task), load_stopped,
1462 rsc, start_key(rsc), NULL, pe_order_load, data_set);
1463
1464 custom_action_order(NULL, strdup(load_stopped_task), load_stopped,
1465 rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), NULL,
1466 pe_order_load, data_set);
1467
1468 free(load_stopped_task);
1469 }
1470 }
1471
1472 if (rsc->container) {
1473 resource_t *remote_rsc = NULL;
1474
1475
1476
1477
1478
1479
1480
1481
1482 if (rsc->container->is_remote_node) {
1483 remote_rsc = rsc->container;
1484 } else if (rsc->is_remote_node == FALSE) {
1485 remote_rsc = rsc_contains_remote_node(data_set, rsc->container);
1486 }
1487
1488 if (remote_rsc) {
1489
1490
1491
1492
1493 GHashTableIter iter;
1494 node_t *node = NULL;
1495 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1496 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1497 if (node->details->remote_rsc != remote_rsc) {
1498 node->weight = -INFINITY;
1499 }
1500 }
1501 } else {
1502
1503
1504
1505
1506 int score;
1507
1508 crm_trace("Order and colocate %s relative to its container %s",
1509 rsc->id, rsc->container->id);
1510
1511 custom_action_order(rsc->container, generate_op_key(rsc->container->id, RSC_START, 0), NULL,
1512 rsc, generate_op_key(rsc->id, RSC_START, 0), NULL,
1513 pe_order_implies_then | pe_order_runnable_left, data_set);
1514
1515 custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
1516 rsc->container, generate_op_key(rsc->container->id, RSC_STOP, 0), NULL,
1517 pe_order_implies_first, data_set);
1518
1519 if (is_set(rsc->flags, pe_rsc_allow_remote_remotes)) {
1520 score = 10000;
1521 } else {
1522 score = INFINITY;
1523 }
1524 rsc_colocation_new("resource-with-container", NULL, score, rsc,
1525 rsc->container, NULL, NULL, data_set);
1526 }
1527 }
1528
1529 if (rsc->is_remote_node || is_stonith) {
1530
1531
1532 rsc_avoids_remote_nodes(rsc);
1533 }
1534
1535
1536
1537
1538
1539 if (rsc->is_remote_node && rsc->container
1540 && is_not_set(rsc->flags, pe_rsc_allow_remote_remotes)) {
1541 rsc_avoids_remote_nodes(rsc->container);
1542 }
1543 }
1544
1545 void
1546 native_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
1547 {
1548 if (rsc_lh == NULL) {
1549 pe_err("rsc_lh was NULL for %s", constraint->id);
1550 return;
1551
1552 } else if (constraint->rsc_rh == NULL) {
1553 pe_err("rsc_rh was NULL for %s", constraint->id);
1554 return;
1555 }
1556
1557 pe_rsc_trace(rsc_lh, "Processing colocation constraint between %s and %s", rsc_lh->id,
1558 rsc_rh->id);
1559
1560 rsc_rh->cmds->rsc_colocation_rh(rsc_lh, rsc_rh, constraint);
1561 }
1562
1563 enum filter_colocation_res
1564 filter_colocation_constraint(resource_t * rsc_lh, resource_t * rsc_rh,
1565 rsc_colocation_t * constraint, gboolean preview)
1566 {
1567 if (constraint->score == 0) {
1568 return influence_nothing;
1569 }
1570
1571
1572 if (preview == FALSE && is_set(rsc_rh->flags, pe_rsc_provisional)) {
1573 return influence_nothing;
1574 }
1575
1576 if ((constraint->role_lh >= RSC_ROLE_SLAVE) &&
1577 rsc_lh->parent &&
1578 rsc_lh->parent->variant == pe_master && is_not_set(rsc_lh->flags, pe_rsc_provisional)) {
1579
1580
1581
1582 return influence_rsc_priority;
1583 }
1584
1585 if (preview == FALSE && is_not_set(rsc_lh->flags, pe_rsc_provisional)) {
1586
1587 struct node_shared_s *details_lh;
1588 struct node_shared_s *details_rh;
1589
1590 if ((constraint->score > -INFINITY) && (constraint->score < INFINITY)) {
1591 return influence_nothing;
1592 }
1593
1594 details_rh = rsc_rh->allocated_to ? rsc_rh->allocated_to->details : NULL;
1595 details_lh = rsc_lh->allocated_to ? rsc_lh->allocated_to->details : NULL;
1596
1597 if (constraint->score == INFINITY && details_lh != details_rh) {
1598 crm_err("%s and %s are both allocated"
1599 " but to different nodes: %s vs. %s",
1600 rsc_lh->id, rsc_rh->id,
1601 details_lh ? details_lh->uname : "n/a", details_rh ? details_rh->uname : "n/a");
1602
1603 } else if (constraint->score == -INFINITY && details_lh == details_rh) {
1604 crm_err("%s and %s are both allocated"
1605 " but to the SAME node: %s",
1606 rsc_lh->id, rsc_rh->id, details_rh ? details_rh->uname : "n/a");
1607 }
1608
1609 return influence_nothing;
1610 }
1611
1612 if (constraint->score > 0
1613 && constraint->role_lh != RSC_ROLE_UNKNOWN && constraint->role_lh != rsc_lh->next_role) {
1614 crm_trace("LH: Skipping constraint: \"%s\" state filter nextrole is %s",
1615 role2text(constraint->role_lh), role2text(rsc_lh->next_role));
1616 return influence_nothing;
1617 }
1618
1619 if (constraint->score > 0
1620 && constraint->role_rh != RSC_ROLE_UNKNOWN && constraint->role_rh != rsc_rh->next_role) {
1621 crm_trace("RH: Skipping constraint: \"%s\" state filter", role2text(constraint->role_rh));
1622 return FALSE;
1623 }
1624
1625 if (constraint->score < 0
1626 && constraint->role_lh != RSC_ROLE_UNKNOWN && constraint->role_lh == rsc_lh->next_role) {
1627 crm_trace("LH: Skipping -ve constraint: \"%s\" state filter",
1628 role2text(constraint->role_lh));
1629 return influence_nothing;
1630 }
1631
1632 if (constraint->score < 0
1633 && constraint->role_rh != RSC_ROLE_UNKNOWN && constraint->role_rh == rsc_rh->next_role) {
1634 crm_trace("RH: Skipping -ve constraint: \"%s\" state filter",
1635 role2text(constraint->role_rh));
1636 return influence_nothing;
1637 }
1638
1639 return influence_rsc_location;
1640 }
1641
1642 static void
1643 influence_priority(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
1644 {
1645 const char *rh_value = NULL;
1646 const char *lh_value = NULL;
1647 const char *attribute = CRM_ATTR_ID;
1648 int score_multiplier = 1;
1649
1650 if (constraint->node_attribute != NULL) {
1651 attribute = constraint->node_attribute;
1652 }
1653
1654 if (!rsc_rh->allocated_to || !rsc_lh->allocated_to) {
1655 return;
1656 }
1657
1658 lh_value = pe_node_attribute_raw(rsc_lh->allocated_to, attribute);
1659 rh_value = pe_node_attribute_raw(rsc_rh->allocated_to, attribute);
1660
1661 if (!safe_str_eq(lh_value, rh_value)) {
1662 if(constraint->score == INFINITY && constraint->role_lh == RSC_ROLE_MASTER) {
1663 rsc_lh->priority = -INFINITY;
1664 }
1665 return;
1666 }
1667
1668 if (constraint->role_rh && (constraint->role_rh != rsc_rh->next_role)) {
1669 return;
1670 }
1671
1672 if (constraint->role_lh == RSC_ROLE_SLAVE) {
1673 score_multiplier = -1;
1674 }
1675
1676 rsc_lh->priority = merge_weights(score_multiplier * constraint->score, rsc_lh->priority);
1677 }
1678
1679 static void
1680 colocation_match(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
1681 {
1682 const char *tmp = NULL;
1683 const char *value = NULL;
1684 const char *attribute = CRM_ATTR_ID;
1685
1686 GHashTable *work = NULL;
1687 gboolean do_check = FALSE;
1688
1689 GHashTableIter iter;
1690 node_t *node = NULL;
1691
1692 if (constraint->node_attribute != NULL) {
1693 attribute = constraint->node_attribute;
1694 }
1695
1696 if (rsc_rh->allocated_to) {
1697 value = pe_node_attribute_raw(rsc_rh->allocated_to, attribute);
1698 do_check = TRUE;
1699
1700 } else if (constraint->score < 0) {
1701
1702
1703
1704 return;
1705 }
1706
1707 work = node_hash_dup(rsc_lh->allowed_nodes);
1708
1709 g_hash_table_iter_init(&iter, work);
1710 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1711 tmp = pe_node_attribute_raw(node, attribute);
1712 if (do_check && safe_str_eq(tmp, value)) {
1713 if (constraint->score < INFINITY) {
1714 pe_rsc_trace(rsc_lh, "%s: %s.%s += %d", constraint->id, rsc_lh->id,
1715 node->details->uname, constraint->score);
1716 node->weight = merge_weights(constraint->score, node->weight);
1717 }
1718
1719 } else if (do_check == FALSE || constraint->score >= INFINITY) {
1720 pe_rsc_trace(rsc_lh, "%s: %s.%s -= %d (%s)", constraint->id, rsc_lh->id,
1721 node->details->uname, constraint->score,
1722 do_check ? "failed" : "unallocated");
1723 node->weight = merge_weights(-constraint->score, node->weight);
1724 }
1725 }
1726
1727 if (can_run_any(work)
1728 || constraint->score <= -INFINITY || constraint->score >= INFINITY) {
1729 g_hash_table_destroy(rsc_lh->allowed_nodes);
1730 rsc_lh->allowed_nodes = work;
1731 work = NULL;
1732
1733 } else {
1734 static char score[33];
1735
1736 score2char_stack(constraint->score, score, sizeof(score));
1737
1738 pe_rsc_info(rsc_lh, "%s: Rolling back scores from %s (%d, %s)",
1739 rsc_lh->id, rsc_rh->id, do_check, score);
1740 }
1741
1742 if (work) {
1743 g_hash_table_destroy(work);
1744 }
1745 }
1746
1747 void
1748 native_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
1749 {
1750 enum filter_colocation_res filter_results;
1751
1752 CRM_ASSERT(rsc_lh);
1753 CRM_ASSERT(rsc_rh);
1754 filter_results = filter_colocation_constraint(rsc_lh, rsc_rh, constraint, FALSE);
1755 pe_rsc_trace(rsc_lh, "%sColocating %s with %s (%s, weight=%d, filter=%d)",
1756 constraint->score >= 0 ? "" : "Anti-",
1757 rsc_lh->id, rsc_rh->id, constraint->id, constraint->score, filter_results);
1758
1759 switch (filter_results) {
1760 case influence_rsc_priority:
1761 influence_priority(rsc_lh, rsc_rh, constraint);
1762 break;
1763 case influence_rsc_location:
1764 pe_rsc_trace(rsc_lh, "%sColocating %s with %s (%s, weight=%d)",
1765 constraint->score >= 0 ? "" : "Anti-",
1766 rsc_lh->id, rsc_rh->id, constraint->id, constraint->score);
1767 colocation_match(rsc_lh, rsc_rh, constraint);
1768 break;
1769 case influence_nothing:
1770 default:
1771 return;
1772 }
1773 }
1774
1775 static gboolean
1776 filter_rsc_ticket(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket)
1777 {
1778 if (rsc_ticket->role_lh != RSC_ROLE_UNKNOWN && rsc_ticket->role_lh != rsc_lh->role) {
1779 pe_rsc_trace(rsc_lh, "LH: Skipping constraint: \"%s\" state filter",
1780 role2text(rsc_ticket->role_lh));
1781 return FALSE;
1782 }
1783
1784 return TRUE;
1785 }
1786
1787 void
1788 rsc_ticket_constraint(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket, pe_working_set_t * data_set)
1789 {
1790 if (rsc_ticket == NULL) {
1791 pe_err("rsc_ticket was NULL");
1792 return;
1793 }
1794
1795 if (rsc_lh == NULL) {
1796 pe_err("rsc_lh was NULL for %s", rsc_ticket->id);
1797 return;
1798 }
1799
1800 if (rsc_ticket->ticket->granted && rsc_ticket->ticket->standby == FALSE) {
1801 return;
1802 }
1803
1804 if (rsc_lh->children) {
1805 GListPtr gIter = rsc_lh->children;
1806
1807 pe_rsc_trace(rsc_lh, "Processing ticket dependencies from %s", rsc_lh->id);
1808
1809 for (; gIter != NULL; gIter = gIter->next) {
1810 resource_t *child_rsc = (resource_t *) gIter->data;
1811
1812 rsc_ticket_constraint(child_rsc, rsc_ticket, data_set);
1813 }
1814 return;
1815 }
1816
1817 pe_rsc_trace(rsc_lh, "%s: Processing ticket dependency on %s (%s, %s)",
1818 rsc_lh->id, rsc_ticket->ticket->id, rsc_ticket->id,
1819 role2text(rsc_ticket->role_lh));
1820
1821 if (rsc_ticket->ticket->granted == FALSE && g_list_length(rsc_lh->running_on) > 0) {
1822 GListPtr gIter = NULL;
1823
1824 switch (rsc_ticket->loss_policy) {
1825 case loss_ticket_stop:
1826 resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set);
1827 break;
1828
1829 case loss_ticket_demote:
1830
1831 if (rsc_ticket->role_lh != RSC_ROLE_MASTER) {
1832 resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set);
1833 }
1834 break;
1835
1836 case loss_ticket_fence:
1837 if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) {
1838 return;
1839 }
1840
1841 resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set);
1842
1843 for (gIter = rsc_lh->running_on; gIter != NULL; gIter = gIter->next) {
1844 node_t *node = (node_t *) gIter->data;
1845
1846 pe_fence_node(data_set, node, "deadman ticket was lost");
1847 }
1848 break;
1849
1850 case loss_ticket_freeze:
1851 if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) {
1852 return;
1853 }
1854 if (g_list_length(rsc_lh->running_on) > 0) {
1855 clear_bit(rsc_lh->flags, pe_rsc_managed);
1856 set_bit(rsc_lh->flags, pe_rsc_block);
1857 }
1858 break;
1859 }
1860
1861 } else if (rsc_ticket->ticket->granted == FALSE) {
1862
1863 if (rsc_ticket->role_lh != RSC_ROLE_MASTER || rsc_ticket->loss_policy == loss_ticket_stop) {
1864 resource_location(rsc_lh, NULL, -INFINITY, "__no_ticket__", data_set);
1865 }
1866
1867 } else if (rsc_ticket->ticket->standby) {
1868
1869 if (rsc_ticket->role_lh != RSC_ROLE_MASTER || rsc_ticket->loss_policy == loss_ticket_stop) {
1870 resource_location(rsc_lh, NULL, -INFINITY, "__ticket_standby__", data_set);
1871 }
1872 }
1873 }
1874
1875 enum pe_action_flags
1876 native_action_flags(action_t * action, node_t * node)
1877 {
1878 return action->flags;
1879 }
1880
1881 enum pe_graph_flags
1882 native_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags,
1883 enum pe_action_flags filter, enum pe_ordering type)
1884 {
1885
1886 enum pe_graph_flags changed = pe_graph_none;
1887 enum pe_action_flags then_flags = then->flags;
1888 enum pe_action_flags first_flags = first->flags;
1889
1890 crm_trace( "Testing %s on %s (0x%.6x) with %s 0x%.6x",
1891 first->uuid, first->node ? first->node->details->uname : "[none]",
1892 first->flags, then->uuid, then->flags);
1893
1894 if (type & pe_order_asymmetrical) {
1895 resource_t *then_rsc = then->rsc;
1896 enum rsc_role_e then_rsc_role = then_rsc ? then_rsc->fns->state(then_rsc, TRUE) : 0;
1897
1898 if (!then_rsc) {
1899
1900 } else if ((then_rsc_role == RSC_ROLE_STOPPED) && safe_str_eq(then->task, RSC_STOP)) {
1901
1902
1903 } else if ((then_rsc_role >= RSC_ROLE_STARTED)
1904 && safe_str_eq(then->task, RSC_START)
1905 && then->node
1906 && then_rsc->running_on
1907 && g_list_length(then_rsc->running_on) == 1
1908 && then->node->details == ((node_t *) then_rsc->running_on->data)->details) {
1909
1910
1911 } else if (!(first->flags & pe_action_runnable)) {
1912
1913
1914 pe_action_implies(then, first, pe_action_optional);
1915 pe_action_implies(then, first, pe_action_runnable);
1916
1917 pe_rsc_trace(then->rsc, "Unset optional and runnable on %s", then->uuid);
1918 } else {
1919
1920 }
1921 }
1922
1923 if (type & pe_order_implies_first) {
1924 if (is_set(filter, pe_action_optional) && is_not_set(flags , pe_action_optional)) {
1925
1926 pe_rsc_trace(first->rsc, "Unset optional on %s because of %s", first->uuid, then->uuid);
1927 pe_action_implies(first, then, pe_action_optional);
1928 }
1929
1930 if (is_set(flags, pe_action_migrate_runnable) &&
1931 is_set(then->flags, pe_action_migrate_runnable) == FALSE &&
1932 is_set(then->flags, pe_action_optional) == FALSE) {
1933
1934 pe_rsc_trace(first->rsc, "Unset migrate runnable on %s because of %s",
1935 first->uuid, then->uuid);
1936 pe_action_implies(first, then, pe_action_migrate_runnable);
1937 }
1938 }
1939
1940 if (type & pe_order_implies_first_master) {
1941 if ((filter & pe_action_optional) &&
1942 ((then->flags & pe_action_optional) == FALSE) &&
1943 then->rsc && (then->rsc->role == RSC_ROLE_MASTER)) {
1944 pe_action_implies(first, then, pe_action_optional);
1945
1946 if (is_set(first->flags, pe_action_migrate_runnable) &&
1947 is_set(then->flags, pe_action_migrate_runnable) == FALSE) {
1948
1949 pe_rsc_trace(first->rsc, "Unset migrate runnable on %s because of %s", first->uuid, then->uuid);
1950 pe_action_implies(first, then, pe_action_migrate_runnable);
1951 }
1952 pe_rsc_trace(then->rsc, "Unset optional on %s because of %s", first->uuid, then->uuid);
1953 }
1954 }
1955
1956 if ((type & pe_order_implies_first_migratable)
1957 && is_set(filter, pe_action_optional)) {
1958
1959 if (((then->flags & pe_action_migrate_runnable) == FALSE) ||
1960 ((then->flags & pe_action_runnable) == FALSE)) {
1961
1962 pe_rsc_trace(then->rsc, "Unset runnable on %s because %s is neither runnable or migratable", first->uuid, then->uuid);
1963 pe_action_implies(first, then, pe_action_runnable);
1964 }
1965
1966 if ((then->flags & pe_action_optional) == 0) {
1967 pe_rsc_trace(then->rsc, "Unset optional on %s because %s is not optional", first->uuid, then->uuid);
1968 pe_action_implies(first, then, pe_action_optional);
1969 }
1970 }
1971
1972 if ((type & pe_order_pseudo_left)
1973 && is_set(filter, pe_action_optional)) {
1974
1975 if ((first->flags & pe_action_runnable) == FALSE) {
1976 pe_action_implies(then, first, pe_action_migrate_runnable);
1977 pe_clear_action_bit(then, pe_action_pseudo);
1978 pe_rsc_trace(then->rsc, "Unset pseudo on %s because %s is not runnable", then->uuid, first->uuid);
1979 }
1980
1981 }
1982
1983 if (is_set(type, pe_order_runnable_left)
1984 && is_set(filter, pe_action_runnable)
1985 && is_set(then->flags, pe_action_runnable)
1986 && is_set(flags, pe_action_runnable) == FALSE) {
1987 pe_rsc_trace(then->rsc, "Unset runnable on %s because of %s", then->uuid, first->uuid);
1988 pe_action_implies(then, first, pe_action_runnable);
1989 pe_action_implies(then, first, pe_action_migrate_runnable);
1990 }
1991
1992 if (is_set(type, pe_order_implies_then)
1993 && is_set(filter, pe_action_optional)
1994 && is_set(then->flags, pe_action_optional)
1995 && is_set(flags, pe_action_optional) == FALSE) {
1996
1997
1998 if (is_set(first->flags, pe_action_migrate_runnable) == FALSE) {
1999 pe_rsc_trace(then->rsc, "Unset optional on %s because of %s", then->uuid, first->uuid);
2000 pe_action_implies(then, first, pe_action_optional);
2001 }
2002 }
2003
2004 if (is_set(type, pe_order_restart)) {
2005 const char *reason = NULL;
2006
2007 CRM_ASSERT(first->rsc && first->rsc->variant == pe_native);
2008 CRM_ASSERT(then->rsc && then->rsc->variant == pe_native);
2009
2010 if ((filter & pe_action_runnable)
2011 && (then->flags & pe_action_runnable) == 0
2012 && (then->rsc->flags & pe_rsc_managed)) {
2013 reason = "shutdown";
2014 }
2015
2016 if ((filter & pe_action_optional) && (then->flags & pe_action_optional) == 0) {
2017 reason = "recover";
2018 }
2019
2020 if (reason && is_set(first->flags, pe_action_optional)) {
2021 if (is_set(first->flags, pe_action_runnable)
2022 || is_not_set(then->flags, pe_action_optional)) {
2023 pe_rsc_trace(first->rsc, "Handling %s: %s -> %s", reason, first->uuid, then->uuid);
2024 pe_action_implies(first, then, pe_action_optional);
2025 }
2026 }
2027
2028 if (reason && is_not_set(first->flags, pe_action_optional)
2029 && is_not_set(first->flags, pe_action_runnable)) {
2030 pe_rsc_trace(then->rsc, "Handling %s: %s -> %s", reason, first->uuid, then->uuid);
2031 pe_action_implies(then, first, pe_action_runnable);
2032 }
2033
2034 if (reason &&
2035 is_not_set(first->flags, pe_action_optional) &&
2036 is_set(first->flags, pe_action_migrate_runnable) &&
2037 is_not_set(then->flags, pe_action_migrate_runnable)) {
2038
2039 pe_action_implies(first, then, pe_action_migrate_runnable);
2040 }
2041
2042 }
2043
2044 if (then_flags != then->flags) {
2045 changed |= pe_graph_updated_then;
2046 pe_rsc_trace(then->rsc,
2047 "Then: Flags for %s on %s are now 0x%.6x (was 0x%.6x) because of %s 0x%.6x",
2048 then->uuid, then->node ? then->node->details->uname : "[none]", then->flags,
2049 then_flags, first->uuid, first->flags);
2050
2051 if(then->rsc && then->rsc->parent) {
2052
2053 update_action(then);
2054 }
2055 }
2056
2057 if (first_flags != first->flags) {
2058 changed |= pe_graph_updated_first;
2059 pe_rsc_trace(first->rsc,
2060 "First: Flags for %s on %s are now 0x%.6x (was 0x%.6x) because of %s 0x%.6x",
2061 first->uuid, first->node ? first->node->details->uname : "[none]",
2062 first->flags, first_flags, then->uuid, then->flags);
2063 }
2064
2065 return changed;
2066 }
2067
2068 void
2069 native_rsc_location(resource_t * rsc, rsc_to_node_t * constraint)
2070 {
2071 GListPtr gIter = NULL;
2072 GHashTableIter iter;
2073 node_t *node = NULL;
2074
2075 if (constraint == NULL) {
2076 pe_err("Constraint is NULL");
2077 return;
2078
2079 } else if (rsc == NULL) {
2080 pe_err("LHS of rsc_to_node (%s) is NULL", constraint->id);
2081 return;
2082 }
2083
2084 pe_rsc_trace(rsc, "Applying %s (%s) to %s", constraint->id,
2085 role2text(constraint->role_filter), rsc->id);
2086
2087
2088 if (constraint->role_filter > RSC_ROLE_UNKNOWN && constraint->role_filter != rsc->next_role) {
2089 pe_rsc_debug(rsc, "Constraint (%s) is not active (role : %s vs. %s)",
2090 constraint->id, role2text(constraint->role_filter), role2text(rsc->next_role));
2091 return;
2092
2093 } else if (is_active(constraint) == FALSE) {
2094 pe_rsc_trace(rsc, "Constraint (%s) is not active", constraint->id);
2095 return;
2096 }
2097
2098 if (constraint->node_list_rh == NULL) {
2099 pe_rsc_trace(rsc, "RHS of constraint %s is NULL", constraint->id);
2100 return;
2101 }
2102
2103 for (gIter = constraint->node_list_rh; gIter != NULL; gIter = gIter->next) {
2104 node_t *node = (node_t *) gIter->data;
2105 node_t *other_node = NULL;
2106
2107 other_node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
2108
2109 if (other_node != NULL) {
2110 pe_rsc_trace(rsc, "%s + %s: %d + %d",
2111 node->details->uname,
2112 other_node->details->uname, node->weight, other_node->weight);
2113 other_node->weight = merge_weights(other_node->weight, node->weight);
2114
2115 } else {
2116 other_node = node_copy(node);
2117
2118 pe_rsc_trace(rsc, "%s: %d (insert %d)", other_node->details->uname, other_node->weight, constraint->discover_mode);
2119 g_hash_table_insert(rsc->allowed_nodes, (gpointer) other_node->details->id, other_node);
2120 }
2121
2122 if (other_node->rsc_discover_mode < constraint->discover_mode) {
2123 if (constraint->discover_mode == pe_discover_exclusive) {
2124 rsc->exclusive_discover = TRUE;
2125 }
2126
2127 other_node->rsc_discover_mode = constraint->discover_mode;
2128 }
2129 }
2130
2131 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
2132 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
2133 pe_rsc_trace(rsc, "%s + %s : %d", rsc->id, node->details->uname, node->weight);
2134 }
2135 }
2136
2137 void
2138 native_expand(resource_t * rsc, pe_working_set_t * data_set)
2139 {
2140 GListPtr gIter = NULL;
2141
2142 CRM_ASSERT(rsc);
2143 pe_rsc_trace(rsc, "Processing actions from %s", rsc->id);
2144
2145 for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
2146 action_t *action = (action_t *) gIter->data;
2147
2148 crm_trace("processing action %d for rsc=%s", action->id, rsc->id);
2149 graph_element_from_action(action, data_set);
2150 }
2151
2152 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2153 resource_t *child_rsc = (resource_t *) gIter->data;
2154
2155 child_rsc->cmds->expand(child_rsc, data_set);
2156 }
2157 }
2158
2159 #define log_change(a, fmt, args...) do { \
2160 if(a && a->reason && terminal) { \
2161 printf(" * "fmt" \tdue to %s\n", ##args, a->reason); \
2162 } else if(a && a->reason) { \
2163 crm_notice(fmt" \tdue to %s", ##args, a->reason); \
2164 } else if(terminal) { \
2165 printf(" * "fmt"\n", ##args); \
2166 } else { \
2167 crm_notice(fmt, ##args); \
2168 } \
2169 } while(0)
2170
2171 #define STOP_SANITY_ASSERT(lineno) do { \
2172 if(current && current->details->unclean) { \
2173 \
2174 } else if(stop == NULL) { \
2175 crm_err("%s:%d: No stop action exists for %s", __FUNCTION__, lineno, rsc->id); \
2176 CRM_ASSERT(stop != NULL); \
2177 } else if(is_set(stop->flags, pe_action_optional)) { \
2178 crm_err("%s:%d: Action %s is still optional", __FUNCTION__, lineno, stop->uuid); \
2179 CRM_ASSERT(is_not_set(stop->flags, pe_action_optional)); \
2180 } \
2181 } while(0)
2182
2183 static int rsc_width = 5;
2184 static int detail_width = 5;
2185 static void
2186 LogAction(const char *change, resource_t *rsc, pe_node_t *origin, pe_node_t *destination, pe_action_t *action, pe_action_t *source, gboolean terminal)
2187 {
2188 int len = 0;
2189 char *reason = NULL;
2190 char *details = NULL;
2191 bool same_host = FALSE;
2192 bool same_role = FALSE;
2193 bool need_role = FALSE;
2194
2195 CRM_ASSERT(action);
2196 CRM_ASSERT(destination != NULL || origin != NULL);
2197
2198 if(source == NULL) {
2199 source = action;
2200 }
2201
2202 len = strlen(rsc->id);
2203 if(len > rsc_width) {
2204 rsc_width = len + 2;
2205 }
2206
2207 if(rsc->role > RSC_ROLE_STARTED || rsc->next_role > RSC_ROLE_SLAVE) {
2208 need_role = TRUE;
2209 }
2210
2211 if(origin != NULL && destination != NULL && origin->details == destination->details) {
2212 same_host = TRUE;
2213 }
2214
2215 if(rsc->role == rsc->next_role) {
2216 same_role = TRUE;
2217 }
2218
2219 if(need_role && origin == NULL) {
2220
2221 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), destination->details->uname);
2222
2223 } else if(need_role && destination == NULL) {
2224
2225 details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
2226
2227 } else if(origin == NULL || destination == NULL) {
2228
2229 details = crm_strdup_printf("%s", origin?origin->details->uname:destination->details->uname);
2230
2231 } else if(need_role && same_role && same_host) {
2232
2233 details = crm_strdup_printf("%s %s", role2text(rsc->role), origin->details->uname);
2234
2235 } else if(same_role && same_host) {
2236
2237 details = crm_strdup_printf("%s", origin->details->uname);
2238
2239 } else if(same_role && need_role) {
2240
2241 details = crm_strdup_printf("%s -> %s %s", origin->details->uname, destination->details->uname, role2text(rsc->role));
2242
2243 } else if(same_role) {
2244
2245 details = crm_strdup_printf("%s -> %s", origin->details->uname, destination->details->uname);
2246
2247 } else if(same_host) {
2248
2249 details = crm_strdup_printf("%s -> %s %s", role2text(rsc->role), role2text(rsc->next_role), origin->details->uname);
2250
2251 } else {
2252
2253 details = crm_strdup_printf("%s %s -> %s %s", role2text(rsc->role), origin->details->uname, role2text(rsc->next_role), destination->details->uname);
2254 }
2255
2256 len = strlen(details);
2257 if(len > detail_width) {
2258 detail_width = len;
2259 }
2260
2261 if(source->reason && is_not_set(action->flags, pe_action_runnable)) {
2262 reason = crm_strdup_printf(" due to %s (blocked)", source->reason);
2263
2264 } else if(source->reason) {
2265 reason = crm_strdup_printf(" due to %s", source->reason);
2266
2267 } else if(is_not_set(action->flags, pe_action_runnable)) {
2268 reason = strdup(" blocked");
2269
2270 } else {
2271 reason = strdup("");
2272 }
2273
2274 if(terminal) {
2275 printf(" * %-8s %-*s ( %*s ) %s\n", change, rsc_width, rsc->id, detail_width, details, reason);
2276 } else {
2277 crm_notice(" * %-8s %-*s ( %*s ) %s", change, rsc_width, rsc->id, detail_width, details, reason);
2278 }
2279
2280 free(details);
2281 free(reason);
2282 }
2283
2284
2285 void
2286 LogActions(resource_t * rsc, pe_working_set_t * data_set, gboolean terminal)
2287 {
2288 node_t *next = NULL;
2289 node_t *current = NULL;
2290
2291 action_t *stop = NULL;
2292 action_t *start = NULL;
2293 action_t *demote = NULL;
2294 action_t *promote = NULL;
2295
2296 char *key = NULL;
2297 gboolean moving = FALSE;
2298 GListPtr possible_matches = NULL;
2299
2300 if(rsc->variant == pe_container) {
2301 container_LogActions(rsc, data_set, terminal);
2302 return;
2303 }
2304
2305 if (rsc->children) {
2306 GListPtr gIter = NULL;
2307
2308 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2309 resource_t *child_rsc = (resource_t *) gIter->data;
2310
2311 LogActions(child_rsc, data_set, terminal);
2312 }
2313 return;
2314 }
2315
2316 next = rsc->allocated_to;
2317 if (rsc->running_on) {
2318 if (g_list_length(rsc->running_on) > 1 && rsc->partial_migration_source) {
2319 current = rsc->partial_migration_source;
2320 } else {
2321 current = rsc->running_on->data;
2322 }
2323
2324 if (rsc->role == RSC_ROLE_STOPPED) {
2325
2326
2327
2328
2329 rsc->role = RSC_ROLE_STARTED;
2330 }
2331 }
2332
2333 if (current == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
2334
2335 return;
2336 }
2337
2338 if (is_not_set(rsc->flags, pe_rsc_managed)
2339 || (current == NULL && next == NULL)) {
2340 pe_rsc_info(rsc, "Leave %s\t(%s%s)",
2341 rsc->id, role2text(rsc->role), is_not_set(rsc->flags,
2342 pe_rsc_managed) ? " unmanaged" : "");
2343 return;
2344 }
2345
2346 if (current != NULL && next != NULL && safe_str_neq(current->details->id, next->details->id)) {
2347 moving = TRUE;
2348 }
2349
2350 key = start_key(rsc);
2351 possible_matches = find_actions(rsc->actions, key, next);
2352 free(key);
2353 if (possible_matches) {
2354 start = possible_matches->data;
2355 g_list_free(possible_matches);
2356 }
2357
2358 key = stop_key(rsc);
2359 if(start == NULL || is_set(start->flags, pe_action_runnable) == FALSE) {
2360 possible_matches = find_actions(rsc->actions, key, NULL);
2361 } else {
2362 possible_matches = find_actions(rsc->actions, key, current);
2363 }
2364 if (possible_matches) {
2365 stop = possible_matches->data;
2366 g_list_free(possible_matches);
2367 }
2368 free(key);
2369
2370 key = promote_key(rsc);
2371 possible_matches = find_actions(rsc->actions, key, next);
2372 free(key);
2373 if (possible_matches) {
2374 promote = possible_matches->data;
2375 g_list_free(possible_matches);
2376 }
2377
2378 key = demote_key(rsc);
2379 possible_matches = find_actions(rsc->actions, key, next);
2380 free(key);
2381 if (possible_matches) {
2382 demote = possible_matches->data;
2383 g_list_free(possible_matches);
2384 }
2385
2386 if (rsc->role == rsc->next_role) {
2387 action_t *migrate_op = NULL;
2388
2389 key = generate_op_key(rsc->id, RSC_MIGRATED, 0);
2390 possible_matches = find_actions(rsc->actions, key, next);
2391 free(key);
2392
2393 if (possible_matches) {
2394 migrate_op = possible_matches->data;
2395 }
2396
2397 CRM_CHECK(next != NULL,);
2398 if (next == NULL) {
2399 } else if (migrate_op && is_set(migrate_op->flags, pe_action_runnable) && current) {
2400 LogAction("Migrate", rsc, current, next, start, NULL, terminal);
2401
2402 } else if (is_set(rsc->flags, pe_rsc_reload)) {
2403 LogAction("Reload", rsc, current, next, start, NULL, terminal);
2404
2405 } else if (start == NULL || is_set(start->flags, pe_action_optional)) {
2406 pe_rsc_info(rsc, "Leave %s\t(%s %s)", rsc->id, role2text(rsc->role),
2407 next->details->uname);
2408
2409 } else if (start && is_set(start->flags, pe_action_runnable) == FALSE) {
2410 LogAction("Stop", rsc, current, NULL, stop,
2411 (stop && stop->reason)? stop : start, terminal);
2412 STOP_SANITY_ASSERT(__LINE__);
2413
2414 } else if (moving && current) {
2415 LogAction(is_set(rsc->flags, pe_rsc_failed) ? "Recover" : "Move",
2416 rsc, current, next, stop, NULL, terminal);
2417
2418 } else if (is_set(rsc->flags, pe_rsc_failed)) {
2419 LogAction("Recover", rsc, current, NULL, stop, NULL, terminal);
2420 STOP_SANITY_ASSERT(__LINE__);
2421
2422 } else {
2423 LogAction("Restart", rsc, current, next, start, NULL, terminal);
2424
2425 }
2426
2427 g_list_free(possible_matches);
2428 return;
2429 }
2430
2431 if(stop
2432 && (rsc->next_role == RSC_ROLE_STOPPED
2433 || (start && is_not_set(start->flags, pe_action_runnable)))) {
2434
2435 GListPtr gIter = NULL;
2436
2437 key = stop_key(rsc);
2438 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
2439 node_t *node = (node_t *) gIter->data;
2440 action_t *stop_op = NULL;
2441
2442 possible_matches = find_actions(rsc->actions, key, node);
2443 if (possible_matches) {
2444 stop_op = possible_matches->data;
2445 g_list_free(possible_matches);
2446 }
2447
2448 if (stop_op && (stop_op->flags & pe_action_runnable)) {
2449 STOP_SANITY_ASSERT(__LINE__);
2450 }
2451
2452 LogAction("Stop", rsc, node, NULL, stop_op,
2453 (stop_op && stop_op->reason)? stop_op : start, terminal);
2454 }
2455
2456 free(key);
2457
2458 } else if (stop && is_set(rsc->flags, pe_rsc_failed)) {
2459
2460 LogAction("Recover", rsc, current, next, stop, start, terminal);
2461 STOP_SANITY_ASSERT(__LINE__);
2462
2463 } else if (moving) {
2464 LogAction("Move", rsc, current, next, stop, NULL, terminal);
2465 STOP_SANITY_ASSERT(__LINE__);
2466
2467 } else if (is_set(rsc->flags, pe_rsc_reload)) {
2468 LogAction("Reload", rsc, current, next, start, NULL, terminal);
2469
2470 } else if (stop != NULL && is_not_set(stop->flags, pe_action_optional)) {
2471 LogAction("Restart", rsc, current, next, start, NULL, terminal);
2472 STOP_SANITY_ASSERT(__LINE__);
2473
2474 } else if (rsc->role == RSC_ROLE_MASTER) {
2475 CRM_LOG_ASSERT(current != NULL);
2476 LogAction("Demote", rsc, current, next, demote, NULL, terminal);
2477
2478 } else if(rsc->next_role == RSC_ROLE_MASTER) {
2479 CRM_LOG_ASSERT(next);
2480 LogAction("Promote", rsc, current, next, promote, NULL, terminal);
2481
2482 } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role > RSC_ROLE_STOPPED) {
2483 LogAction("Start", rsc, current, next, start, NULL, terminal);
2484 }
2485 }
2486
2487 gboolean
2488 StopRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
2489 {
2490 GListPtr gIter = NULL;
2491
2492 CRM_ASSERT(rsc);
2493 pe_rsc_trace(rsc, "%s", rsc->id);
2494
2495 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
2496 node_t *current = (node_t *) gIter->data;
2497 action_t *stop;
2498
2499 if (rsc->partial_migration_target) {
2500 if (rsc->partial_migration_target->details == current->details) {
2501 pe_rsc_trace(rsc, "Filtered %s -> %s %s", current->details->uname,
2502 next->details->uname, rsc->id);
2503 continue;
2504 } else {
2505 pe_rsc_trace(rsc, "Forced on %s %s", current->details->uname, rsc->id);
2506 optional = FALSE;
2507 }
2508 }
2509
2510 pe_rsc_trace(rsc, "%s on %s", rsc->id, current->details->uname);
2511 stop = stop_action(rsc, current, optional);
2512
2513 if(rsc->allocated_to == NULL) {
2514 pe_action_set_reason(stop, "node availability", TRUE);
2515 }
2516
2517 if (is_not_set(rsc->flags, pe_rsc_managed)) {
2518 update_action_flags(stop, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
2519 }
2520
2521 if (is_set(data_set->flags, pe_flag_remove_after_stop)) {
2522 DeleteRsc(rsc, current, optional, data_set);
2523 }
2524
2525 if(is_set(rsc->flags, pe_rsc_needs_unfencing)) {
2526 action_t *unfence = pe_fence_op(current, "on", TRUE, NULL, data_set);
2527 const char *unfenced = pe_node_attribute_raw(current, CRM_ATTR_UNFENCED);
2528
2529 order_actions(stop, unfence, pe_order_implies_first);
2530 if (unfenced == NULL || safe_str_eq("0", unfenced)) {
2531 pe_proc_err("Stopping %s until %s can be unfenced", rsc->id, current->details->uname);
2532 }
2533 }
2534 }
2535
2536 return TRUE;
2537 }
2538
2539 gboolean
2540 StartRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
2541 {
2542 action_t *start = NULL;
2543
2544 CRM_ASSERT(rsc);
2545 pe_rsc_trace(rsc, "%s on %s %d %d", rsc->id, next ? next->details->uname : "N/A", optional, next ? next->weight : 0);
2546 start = start_action(rsc, next, TRUE);
2547
2548 if(is_set(rsc->flags, pe_rsc_needs_unfencing)) {
2549 action_t *unfence = pe_fence_op(next, "on", TRUE, NULL, data_set);
2550 const char *unfenced = pe_node_attribute_raw(next, CRM_ATTR_UNFENCED);
2551
2552 order_actions(unfence, start, pe_order_implies_then);
2553
2554 if (unfenced == NULL || safe_str_eq("0", unfenced)) {
2555 char *reason = crm_strdup_printf("Required by %s", rsc->id);
2556 trigger_unfencing(NULL, next, reason, NULL, data_set);
2557 free(reason);
2558 }
2559 }
2560
2561 if (is_set(start->flags, pe_action_runnable) && optional == FALSE) {
2562 update_action_flags(start, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__);
2563 }
2564
2565
2566 return TRUE;
2567 }
2568
2569 gboolean
2570 PromoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
2571 {
2572 char *key = NULL;
2573 GListPtr gIter = NULL;
2574 gboolean runnable = TRUE;
2575 GListPtr action_list = NULL;
2576
2577 CRM_ASSERT(rsc);
2578 CRM_CHECK(next != NULL, return FALSE);
2579 pe_rsc_trace(rsc, "%s on %s", rsc->id, next->details->uname);
2580
2581 key = start_key(rsc);
2582 action_list = find_actions_exact(rsc->actions, key, next);
2583 free(key);
2584
2585 for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
2586 action_t *start = (action_t *) gIter->data;
2587
2588 if (is_set(start->flags, pe_action_runnable) == FALSE) {
2589 runnable = FALSE;
2590 }
2591 }
2592 g_list_free(action_list);
2593
2594 if (runnable) {
2595 promote_action(rsc, next, optional);
2596 return TRUE;
2597 }
2598
2599 pe_rsc_debug(rsc, "%s\tPromote %s (canceled)", next->details->uname, rsc->id);
2600
2601 key = promote_key(rsc);
2602 action_list = find_actions_exact(rsc->actions, key, next);
2603 free(key);
2604
2605 for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
2606 action_t *promote = (action_t *) gIter->data;
2607
2608 update_action_flags(promote, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
2609 }
2610
2611 g_list_free(action_list);
2612 return TRUE;
2613 }
2614
2615 gboolean
2616 DemoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
2617 {
2618 GListPtr gIter = NULL;
2619
2620 CRM_ASSERT(rsc);
2621 pe_rsc_trace(rsc, "%s", rsc->id);
2622
2623
2624 for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
2625 node_t *current = (node_t *) gIter->data;
2626
2627 pe_rsc_trace(rsc, "%s on %s", rsc->id, next ? next->details->uname : "N/A");
2628 demote_action(rsc, current, optional);
2629 }
2630 return TRUE;
2631 }
2632
2633 gboolean
2634 RoleError(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
2635 {
2636 CRM_ASSERT(rsc);
2637 crm_err("%s on %s", rsc->id, next ? next->details->uname : "N/A");
2638 CRM_CHECK(FALSE, return FALSE);
2639 return FALSE;
2640 }
2641
2642 gboolean
2643 NullOp(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
2644 {
2645 CRM_ASSERT(rsc);
2646 pe_rsc_trace(rsc, "%s", rsc->id);
2647 return FALSE;
2648 }
2649
2650 gboolean
2651 DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set)
2652 {
2653 if (is_set(rsc->flags, pe_rsc_failed)) {
2654 pe_rsc_trace(rsc, "Resource %s not deleted from %s: failed", rsc->id, node->details->uname);
2655 return FALSE;
2656
2657 } else if (node == NULL) {
2658 pe_rsc_trace(rsc, "Resource %s not deleted: NULL node", rsc->id);
2659 return FALSE;
2660
2661 } else if (node->details->unclean || node->details->online == FALSE) {
2662 pe_rsc_trace(rsc, "Resource %s not deleted from %s: unrunnable", rsc->id,
2663 node->details->uname);
2664 return FALSE;
2665 }
2666
2667 crm_notice("Removing %s from %s", rsc->id, node->details->uname);
2668
2669 delete_action(rsc, node, optional);
2670
2671 new_rsc_order(rsc, RSC_STOP, rsc, RSC_DELETE,
2672 optional ? pe_order_implies_then : pe_order_optional, data_set);
2673
2674 new_rsc_order(rsc, RSC_DELETE, rsc, RSC_START,
2675 optional ? pe_order_implies_then : pe_order_optional, data_set);
2676
2677 return TRUE;
2678 }
2679
2680 #include <../lib/pengine/unpack.h>
2681 #define set_char(x) last_rsc_id[lpc] = x; complete = TRUE;
2682 static char *
2683 increment_clone(char *last_rsc_id)
2684 {
2685 int lpc = 0;
2686 int len = 0;
2687 char *tmp = NULL;
2688 gboolean complete = FALSE;
2689
2690 CRM_CHECK(last_rsc_id != NULL, return NULL);
2691 if (last_rsc_id != NULL) {
2692 len = strlen(last_rsc_id);
2693 }
2694
2695 lpc = len - 1;
2696 while (complete == FALSE && lpc > 0) {
2697 switch (last_rsc_id[lpc]) {
2698 case 0:
2699 lpc--;
2700 break;
2701 case '0':
2702 set_char('1');
2703 break;
2704 case '1':
2705 set_char('2');
2706 break;
2707 case '2':
2708 set_char('3');
2709 break;
2710 case '3':
2711 set_char('4');
2712 break;
2713 case '4':
2714 set_char('5');
2715 break;
2716 case '5':
2717 set_char('6');
2718 break;
2719 case '6':
2720 set_char('7');
2721 break;
2722 case '7':
2723 set_char('8');
2724 break;
2725 case '8':
2726 set_char('9');
2727 break;
2728 case '9':
2729 last_rsc_id[lpc] = '0';
2730 lpc--;
2731 break;
2732 case ':':
2733 tmp = last_rsc_id;
2734 last_rsc_id = calloc(1, len + 2);
2735 memcpy(last_rsc_id, tmp, len);
2736 last_rsc_id[++lpc] = '1';
2737 last_rsc_id[len] = '0';
2738 last_rsc_id[len + 1] = 0;
2739 complete = TRUE;
2740 free(tmp);
2741 break;
2742 default:
2743 crm_err("Unexpected char: %c (%d)", last_rsc_id[lpc], lpc);
2744 return NULL;
2745 break;
2746 }
2747 }
2748 return last_rsc_id;
2749 }
2750
2751 static node_t *
2752 probe_anon_group_member(resource_t *rsc, node_t *node,
2753 pe_working_set_t *data_set)
2754 {
2755 resource_t *top = uber_parent(rsc);
2756
2757 if (is_not_set(top->flags, pe_rsc_unique)) {
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776 char *clone_id = clone_zero(rsc->id);
2777 resource_t *peer = pe_find_resource(top->children, clone_id);
2778 node_t *running = NULL;
2779
2780 while (peer) {
2781 running = pe_hash_table_lookup(peer->known_on, node->details->id);
2782 if (running != NULL) {
2783
2784 pe_rsc_trace(rsc, "Skipping active clone: %s", rsc->id);
2785 free(clone_id);
2786 return running;
2787 }
2788 clone_id = increment_clone(clone_id);
2789 peer = pe_find_resource(data_set->resources, clone_id);
2790 }
2791
2792 free(clone_id);
2793 }
2794 return NULL;
2795 }
2796
2797 gboolean
2798 native_create_probe(resource_t * rsc, node_t * node, action_t * complete,
2799 gboolean force, pe_working_set_t * data_set)
2800 {
2801 enum pe_ordering flags = pe_order_optional;
2802 char *key = NULL;
2803 action_t *probe = NULL;
2804 node_t *running = NULL;
2805 node_t *allowed = NULL;
2806 resource_t *top = uber_parent(rsc);
2807
2808 static const char *rc_master = NULL;
2809 static const char *rc_inactive = NULL;
2810
2811 if (rc_inactive == NULL) {
2812 rc_inactive = crm_itoa(PCMK_OCF_NOT_RUNNING);
2813 rc_master = crm_itoa(PCMK_OCF_RUNNING_MASTER);
2814 }
2815
2816 CRM_CHECK(node != NULL, return FALSE);
2817 if (force == FALSE && is_not_set(data_set->flags, pe_flag_startup_probes)) {
2818 pe_rsc_trace(rsc, "Skipping active resource detection for %s", rsc->id);
2819 return FALSE;
2820 }
2821
2822 if (is_remote_node(node)) {
2823 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
2824
2825 if (safe_str_eq(class, PCMK_RESOURCE_CLASS_STONITH)) {
2826 pe_rsc_trace(rsc,
2827 "Skipping probe for %s on %s because Pacemaker Remote nodes cannot run stonith agents",
2828 rsc->id, node->details->id);
2829 return FALSE;
2830 } else if (is_container_remote_node(node) && rsc_contains_remote_node(data_set, rsc)) {
2831 pe_rsc_trace(rsc,
2832 "Skipping probe for %s on %s because guest nodes cannot run resources containing guest nodes",
2833 rsc->id, node->details->id);
2834 return FALSE;
2835 } else if (rsc->is_remote_node) {
2836 pe_rsc_trace(rsc,
2837 "Skipping probe for %s on %s because Pacemaker Remote nodes cannot host remote connections",
2838 rsc->id, node->details->id);
2839 return FALSE;
2840 }
2841 }
2842
2843 if (rsc->children) {
2844 GListPtr gIter = NULL;
2845 gboolean any_created = FALSE;
2846
2847 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2848 resource_t *child_rsc = (resource_t *) gIter->data;
2849
2850 any_created = child_rsc->cmds->create_probe(child_rsc, node, complete, force, data_set)
2851 || any_created;
2852 }
2853
2854 return any_created;
2855
2856 } else if ((rsc->container) && (!rsc->is_remote_node)) {
2857 pe_rsc_trace(rsc, "Skipping %s: it is within container %s", rsc->id, rsc->container->id);
2858 return FALSE;
2859 }
2860
2861 if (is_set(rsc->flags, pe_rsc_orphan)) {
2862 pe_rsc_trace(rsc, "Skipping orphan: %s", rsc->id);
2863 return FALSE;
2864 }
2865
2866 running = g_hash_table_lookup(rsc->known_on, node->details->id);
2867 if (running == NULL && is_set(rsc->flags, pe_rsc_unique) == FALSE) {
2868
2869 if (rsc->parent == top) {
2870 running = g_hash_table_lookup(rsc->parent->known_on, node->details->id);
2871
2872 } else {
2873
2874 running = probe_anon_group_member(rsc, node, data_set);
2875 }
2876 }
2877
2878 if (force == FALSE && running != NULL) {
2879
2880 pe_rsc_trace(rsc, "Skipping known: %s on %s", rsc->id, node->details->uname);
2881 return FALSE;
2882 }
2883
2884 allowed = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
2885
2886 if (rsc->exclusive_discover || top->exclusive_discover) {
2887 if (allowed == NULL) {
2888
2889 pe_rsc_trace(rsc, "Skipping probe for %s on node %s, A", rsc->id, node->details->id);
2890 return FALSE;
2891 } else if (allowed->rsc_discover_mode != pe_discover_exclusive) {
2892
2893
2894 pe_rsc_trace(rsc, "Skipping probe for %s on node %s, B", rsc->id, node->details->id);
2895 return FALSE;
2896 }
2897 }
2898
2899 if(allowed == NULL && node->rsc_discover_mode == pe_discover_never) {
2900
2901
2902
2903
2904
2905 pe_rsc_trace(rsc, "Skipping probe for %s on node %s, C", rsc->id, node->details->id);
2906 return FALSE;
2907 }
2908
2909 if (allowed && allowed->rsc_discover_mode == pe_discover_never) {
2910
2911 pe_rsc_trace(rsc, "Skipping probe for %s on node %s, discovery mode", rsc->id, node->details->id);
2912 return FALSE;
2913 }
2914
2915 if(is_container_remote_node(node)) {
2916 resource_t *remote = node->details->remote_rsc->container;
2917
2918 if(remote->role == RSC_ROLE_STOPPED) {
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934 if(remote->allocated_to
2935 && g_hash_table_lookup(remote->known_on, remote->allocated_to->details->id) == NULL) {
2936
2937
2938
2939
2940
2941
2942 custom_action_order(remote, generate_op_key(remote->id, RSC_STATUS, 0), NULL,
2943 top, generate_op_key(top->id, RSC_START, 0), NULL,
2944 pe_order_optional, data_set);
2945 }
2946 pe_rsc_trace(rsc, "Skipping probe for %s on node %s, %s is stopped",
2947 rsc->id, node->details->id, remote->id);
2948 return FALSE;
2949
2950
2951
2952
2953 } else if(node->details->remote_requires_reset
2954 || node->details->unclean
2955 || is_set(remote->flags, pe_rsc_failed)
2956 || remote->next_role == RSC_ROLE_STOPPED
2957 || (remote->allocated_to
2958 && pe_find_node(remote->running_on, remote->allocated_to->details->uname) == NULL)
2959 ) {
2960
2961
2962
2963
2964 custom_action_order(remote, generate_op_key(remote->id, RSC_STOP, 0), NULL,
2965 top, generate_op_key(top->id, RSC_START, 0), NULL,
2966 pe_order_optional, data_set);
2967 pe_rsc_trace(rsc, "Skipping probe for %s on node %s, %s is stopping, restarting or moving",
2968 rsc->id, node->details->id, remote->id);
2969 return FALSE;
2970
2971
2972
2973 }
2974 }
2975
2976 key = generate_op_key(rsc->id, RSC_STATUS, 0);
2977 probe = custom_action(rsc, key, RSC_STATUS, node, FALSE, TRUE, data_set);
2978 update_action_flags(probe, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__);
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993 if(is_set(rsc->flags, pe_rsc_needs_unfencing)) {
2994 action_t *unfence = pe_fence_op(node, "on", TRUE, NULL, data_set);
2995 order_actions(unfence, probe, pe_order_optional);
2996 }
2997
2998
2999
3000
3001
3002 running = pe_find_node_id(rsc->running_on, node->details->id);
3003 if (running == NULL) {
3004 add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_inactive);
3005
3006 } else if (rsc->role == RSC_ROLE_MASTER) {
3007 add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_master);
3008 }
3009
3010 crm_debug("Probing %s on %s (%s) %d %p", rsc->id, node->details->uname, role2text(rsc->role),
3011 is_set(probe->flags, pe_action_runnable), rsc->running_on);
3012
3013 if(is_set(rsc->flags, pe_rsc_fence_device) && is_set(data_set->flags, pe_flag_enable_unfencing)) {
3014 top = rsc;
3015
3016 } else if (pe_rsc_is_clone(top) == FALSE) {
3017 top = rsc;
3018
3019 } else {
3020 crm_trace("Probing %s on %s (%s) as %s", rsc->id, node->details->uname, role2text(rsc->role), top->id);
3021 }
3022
3023 if(is_not_set(probe->flags, pe_action_runnable) && rsc->running_on == NULL) {
3024
3025
3026
3027 flags |= pe_order_runnable_left;
3028 }
3029
3030 custom_action_order(rsc, NULL, probe,
3031 top, generate_op_key(top->id, RSC_START, 0), NULL,
3032 flags, data_set);
3033
3034
3035 custom_action_order(rsc, NULL, probe,
3036 top, reload_key(rsc), NULL,
3037 pe_order_optional, data_set);
3038
3039 if(is_set(rsc->flags, pe_rsc_fence_device) && is_set(data_set->flags, pe_flag_enable_unfencing)) {
3040
3041
3042
3043
3044
3045
3046
3047 } else {
3048 order_actions(probe, complete, pe_order_implies_then);
3049 }
3050 return TRUE;
3051 }
3052
3053 static void
3054 native_start_constraints(resource_t * rsc, action_t * stonith_op, pe_working_set_t * data_set)
3055 {
3056 node_t *target;
3057 GListPtr gIter = NULL;
3058 action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set);
3059 action_t *stonith_done = get_pseudo_op(STONITH_DONE, data_set);
3060
3061 CRM_CHECK(stonith_op && stonith_op->node, return);
3062 target = stonith_op->node;
3063
3064 for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
3065 action_t *action = (action_t *) gIter->data;
3066
3067 if(action->needs == rsc_req_nothing) {
3068
3069
3070 } else if (action->needs == rsc_req_stonith) {
3071 order_actions(stonith_done, action, pe_order_optional);
3072
3073 } else if (safe_str_eq(action->task, RSC_START)
3074 && NULL == pe_hash_table_lookup(rsc->known_on, target->details->id)) {
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091 pe_rsc_debug(rsc, "Ordering %s after %s recovery", action->uuid,
3092 target->details->uname);
3093 order_actions(all_stopped, action, pe_order_optional | pe_order_runnable_left);
3094 }
3095 }
3096 }
3097
3098 static void
3099 native_stop_constraints(resource_t * rsc, action_t * stonith_op, pe_working_set_t * data_set)
3100 {
3101 char *key = NULL;
3102 GListPtr gIter = NULL;
3103 GListPtr action_list = NULL;
3104
3105 action_t *start = NULL;
3106 resource_t *top = uber_parent(rsc);
3107 node_t *target;
3108
3109 CRM_CHECK(stonith_op && stonith_op->node, return);
3110 target = stonith_op->node;
3111
3112
3113 start = find_first_action(rsc->actions, NULL, CRMD_ACTION_START, NULL);
3114
3115
3116 key = stop_key(rsc);
3117 action_list = find_actions(rsc->actions, key, target);
3118 free(key);
3119
3120 for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
3121 action_t *action = (action_t *) gIter->data;
3122
3123 if (is_set(rsc->flags, pe_rsc_failed)) {
3124 crm_notice("Stop of failed resource %s is implicit after %s is fenced",
3125 rsc->id, target->details->uname);
3126 } else {
3127 crm_info("%s is implicit after %s is fenced",
3128 action->uuid, target->details->uname);
3129 }
3130
3131
3132
3133
3134 update_action_flags(action, pe_action_pseudo, __FUNCTION__, __LINE__);
3135 update_action_flags(action, pe_action_runnable, __FUNCTION__, __LINE__);
3136 update_action_flags(action, pe_action_implied_by_stonith, __FUNCTION__, __LINE__);
3137
3138 if(start == NULL || start->needs > rsc_req_quorum) {
3139 enum pe_ordering flags = pe_order_optional;
3140 action_t *parent_stop = find_first_action(top->actions, NULL, RSC_STOP, NULL);
3141
3142 if (target->details->remote_rsc) {
3143
3144
3145
3146
3147
3148 flags |= pe_order_preserve;
3149 }
3150 order_actions(stonith_op, action, flags);
3151 order_actions(stonith_op, parent_stop, flags);
3152 }
3153
3154 if (is_set(rsc->flags, pe_rsc_notify)) {
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175 create_secondary_notification(action, rsc, stonith_op, data_set);
3176 }
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208 }
3209
3210 g_list_free(action_list);
3211
3212
3213 key = demote_key(rsc);
3214 action_list = find_actions(rsc->actions, key, target);
3215 free(key);
3216
3217 for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
3218 action_t *action = (action_t *) gIter->data;
3219
3220 if (action->node->details->online == FALSE || action->node->details->unclean == TRUE
3221 || is_set(rsc->flags, pe_rsc_failed)) {
3222
3223 if (is_set(rsc->flags, pe_rsc_failed)) {
3224 pe_rsc_info(rsc,
3225 "Demote of failed resource %s is implicit after %s is fenced",
3226 rsc->id, target->details->uname);
3227 } else {
3228 pe_rsc_info(rsc, "%s is implicit after %s is fenced",
3229 action->uuid, target->details->uname);
3230 }
3231
3232
3233
3234
3235 update_action_flags(action, pe_action_pseudo, __FUNCTION__, __LINE__);
3236 update_action_flags(action, pe_action_runnable, __FUNCTION__, __LINE__);
3237
3238 if (start == NULL || start->needs > rsc_req_quorum) {
3239 order_actions(stonith_op, action, pe_order_preserve|pe_order_optional);
3240 }
3241 }
3242 }
3243
3244 g_list_free(action_list);
3245 }
3246
3247 void
3248 rsc_stonith_ordering(resource_t * rsc, action_t * stonith_op, pe_working_set_t * data_set)
3249 {
3250 if (rsc->children) {
3251 GListPtr gIter = NULL;
3252
3253 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
3254 resource_t *child_rsc = (resource_t *) gIter->data;
3255
3256 rsc_stonith_ordering(child_rsc, stonith_op, data_set);
3257 }
3258
3259 } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
3260 pe_rsc_trace(rsc, "Skipping fencing constraints for unmanaged resource: %s", rsc->id);
3261
3262 } else {
3263 native_start_constraints(rsc, stonith_op, data_set);
3264 native_stop_constraints(rsc, stonith_op, data_set);
3265 }
3266 }
3267
3268 enum stack_activity {
3269 stack_stable = 0,
3270 stack_starting = 1,
3271 stack_stopping = 2,
3272 stack_middle = 4,
3273 };
3274
3275 void
3276 ReloadRsc(resource_t * rsc, node_t *node, pe_working_set_t * data_set)
3277 {
3278 GListPtr gIter = NULL;
3279 action_t *reload = NULL;
3280
3281 if (rsc->children) {
3282 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
3283 resource_t *child_rsc = (resource_t *) gIter->data;
3284
3285 ReloadRsc(child_rsc, node, data_set);
3286 }
3287 return;
3288
3289 } else if (rsc->variant > pe_native) {
3290
3291 return;
3292
3293 } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
3294 pe_rsc_trace(rsc, "%s: unmanaged", rsc->id);
3295 return;
3296
3297 } else if (is_set(rsc->flags, pe_rsc_failed) || is_set(rsc->flags, pe_rsc_start_pending)) {
3298 pe_rsc_trace(rsc, "%s: general resource state: flags=0x%.16llx", rsc->id, rsc->flags);
3299 stop_action(rsc, node, FALSE);
3300 return;
3301
3302 } else if (node == NULL) {
3303 pe_rsc_trace(rsc, "%s: not active", rsc->id);
3304 return;
3305 }
3306
3307 pe_rsc_trace(rsc, "Processing %s", rsc->id);
3308 set_bit(rsc->flags, pe_rsc_reload);
3309
3310 reload = custom_action(
3311 rsc, reload_key(rsc), CRMD_ACTION_RELOAD, node, FALSE, TRUE, data_set);
3312 pe_action_set_reason(reload, "resource definition change", FALSE);
3313
3314 custom_action_order(NULL, NULL, reload, rsc, stop_key(rsc), NULL,
3315 pe_order_optional|pe_order_then_cancels_first,
3316 data_set);
3317 custom_action_order(NULL, NULL, reload, rsc, demote_key(rsc), NULL,
3318 pe_order_optional|pe_order_then_cancels_first,
3319 data_set);
3320 }
3321
3322 void
3323 native_append_meta(resource_t * rsc, xmlNode * xml)
3324 {
3325 char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION);
3326 resource_t *iso_parent, *last_parent, *parent;
3327
3328 if (value) {
3329 char *name = NULL;
3330
3331 name = crm_meta_name(XML_RSC_ATTR_INCARNATION);
3332 crm_xml_add(xml, name, value);
3333 free(name);
3334 }
3335
3336 value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_REMOTE_NODE);
3337 if (value) {
3338 char *name = NULL;
3339
3340 name = crm_meta_name(XML_RSC_ATTR_REMOTE_NODE);
3341 crm_xml_add(xml, name, value);
3342 free(name);
3343 }
3344
3345 for (parent = rsc; parent != NULL; parent = parent->parent) {
3346 if (parent->container) {
3347 crm_xml_add(xml, CRM_META"_"XML_RSC_ATTR_CONTAINER, parent->container->id);
3348 }
3349 }
3350
3351 last_parent = iso_parent = rsc;
3352 while (iso_parent != NULL) {
3353 char *name = NULL;
3354 char *iso = NULL;
3355
3356 if (iso_parent->isolation_wrapper == NULL) {
3357 last_parent = iso_parent;
3358 iso_parent = iso_parent->parent;
3359 continue;
3360 }
3361
3362
3363 name = crm_meta_name(XML_RSC_ATTR_ISOLATION_WRAPPER);
3364 crm_xml_add(xml, name, iso_parent->isolation_wrapper);
3365 free(name);
3366
3367
3368 name = crm_meta_name(XML_RSC_ATTR_ISOLATION_INSTANCE);
3369 if (pe_rsc_is_clone(iso_parent)) {
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387 value = g_hash_table_lookup(last_parent->meta, XML_RSC_ATTR_INCARNATION);
3388 CRM_ASSERT(value != NULL);
3389
3390 iso = crm_concat(crm_element_value(last_parent->xml, XML_ATTR_ID), value, '_');
3391 crm_xml_add(xml, name, iso);
3392 free(iso);
3393 } else {
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414 value = g_hash_table_lookup(iso_parent->meta, XML_RSC_ATTR_INCARNATION);
3415 if (value) {
3416 crm_xml_add(xml, name, iso_parent->id);
3417 iso = crm_concat(crm_element_value(iso_parent->xml, XML_ATTR_ID), value, '_');
3418 crm_xml_add(xml, name, iso);
3419 free(iso);
3420 } else {
3421 crm_xml_add(xml, name, iso_parent->id);
3422 }
3423 }
3424 free(name);
3425
3426 break;
3427 }
3428 }