This source file includes following definitions.
- state2text
- order_start_then_action
- order_action_then_stop
- get_remote_node_state
- is_recurring_action
- apply_remote_ordering
- apply_container_ordering
- pcmk__order_remote_connection_actions
- pcmk__is_failed_remote_node
- pcmk__rsc_corresponds_to_guest
- pcmk__connection_host_for_action
- pcmk__substitute_remote_addr
- pcmk__add_bundle_meta_to_xml
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13
14 #include <crm/crm.h>
15 #include <crm/cib.h>
16 #include <crm/msg_xml.h>
17 #include <crm/common/xml.h>
18 #include <crm/common/xml_internal.h>
19
20 #include <glib.h>
21
22 #include <crm/pengine/status.h>
23 #include <pacemaker-internal.h>
24 #include "libpacemaker_private.h"
25
26 enum remote_connection_state {
27 remote_state_unknown = 0,
28 remote_state_alive = 1,
29 remote_state_resting = 2,
30 remote_state_failed = 3,
31 remote_state_stopped = 4
32 };
33
34 static const char *
35 state2text(enum remote_connection_state state)
36 {
37 switch (state) {
38 case remote_state_unknown:
39 return "unknown";
40 case remote_state_alive:
41 return "alive";
42 case remote_state_resting:
43 return "resting";
44 case remote_state_failed:
45 return "failed";
46 case remote_state_stopped:
47 return "stopped";
48 }
49
50 return "impossible";
51 }
52
53
54
55
56
57
58
59
60
61 static inline void
62 order_start_then_action(pe_resource_t *lh_rsc, pe_action_t *rh_action,
63 enum pe_ordering extra, pe_working_set_t *data_set)
64 {
65 if ((lh_rsc != NULL) && (rh_action != NULL) && (data_set != NULL)) {
66 pcmk__new_ordering(lh_rsc, start_key(lh_rsc), NULL,
67 rh_action->rsc, NULL, rh_action,
68 pe_order_preserve|pe_order_runnable_left|extra,
69 data_set);
70 }
71 }
72
73 static inline void
74 order_action_then_stop(pe_action_t *lh_action, pe_resource_t *rh_rsc,
75 enum pe_ordering extra, pe_working_set_t *data_set)
76 {
77 if ((lh_action != NULL) && (rh_rsc != NULL) && (data_set != NULL)) {
78 pcmk__new_ordering(lh_action->rsc, NULL, lh_action,
79 rh_rsc, stop_key(rh_rsc), NULL,
80 pe_order_preserve|extra, data_set);
81 }
82 }
83
84 static enum remote_connection_state
85 get_remote_node_state(pe_node_t *node)
86 {
87 pe_resource_t *remote_rsc = NULL;
88 pe_node_t *cluster_node = NULL;
89
90 CRM_ASSERT(node != NULL);
91
92 remote_rsc = node->details->remote_rsc;
93 CRM_ASSERT(remote_rsc != NULL);
94
95 cluster_node = pe__current_node(remote_rsc);
96
97
98
99
100
101 if ((remote_rsc->next_role == RSC_ROLE_STOPPED)
102 || (remote_rsc->allocated_to == NULL)) {
103
104
105
106 if ((cluster_node != NULL) && cluster_node->details->unclean) {
107
108
109
110 return remote_state_failed;
111 }
112
113 if (!pcmk_is_set(remote_rsc->flags, pe_rsc_failed)) {
114
115 return remote_state_stopped;
116 }
117
118
119
120 if ((remote_rsc->next_role == RSC_ROLE_STOPPED)
121 && remote_rsc->remote_reconnect_ms
122 && node->details->remote_was_fenced
123 && !pe__shutdown_requested(node)) {
124
125
126
127
128 return remote_state_unknown;
129 }
130
131
132
133
134
135 return remote_state_failed;
136
137 } else if (cluster_node == NULL) {
138
139
140
141 return remote_state_unknown;
142
143 } else if (cluster_node->details->unclean
144 || !(cluster_node->details->online)) {
145
146 return remote_state_resting;
147
148 } else if (pcmk__list_of_multiple(remote_rsc->running_on)
149 && (remote_rsc->partial_migration_source != NULL)
150 && (remote_rsc->partial_migration_target != NULL)) {
151
152
153
154 return remote_state_resting;
155
156 }
157 return remote_state_alive;
158 }
159
160 static int
161 is_recurring_action(pe_action_t *action)
162 {
163 guint interval_ms;
164
165 if (pcmk__guint_from_hash(action->meta,
166 XML_LRM_ATTR_INTERVAL_MS, 0,
167 &interval_ms) != pcmk_rc_ok) {
168 return 0;
169 }
170 return (interval_ms > 0);
171 }
172
173
174
175
176
177 static void
178 apply_remote_ordering(pe_action_t *action, pe_working_set_t *data_set)
179 {
180 pe_resource_t *remote_rsc = NULL;
181 enum action_tasks task = text2task(action->task);
182 enum remote_connection_state state = get_remote_node_state(action->node);
183
184 enum pe_ordering order_opts = pe_order_none;
185
186 if (action->rsc == NULL) {
187 return;
188 }
189
190 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
191
192 remote_rsc = action->node->details->remote_rsc;
193 CRM_ASSERT(remote_rsc != NULL);
194
195 crm_trace("Order %s action %s relative to %s%s (state: %s)",
196 action->task, action->uuid,
197 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
198 remote_rsc->id, state2text(state));
199
200 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE,
201 CRMD_ACTION_MIGRATED, NULL)) {
202
203
204
205 task = stop_rsc;
206 }
207
208 switch (task) {
209 case start_rsc:
210 case action_promote:
211 order_opts = pe_order_none;
212
213 if (state == remote_state_failed) {
214
215 pe__set_order_flags(order_opts, pe_order_implies_then);
216 }
217
218
219 order_start_then_action(remote_rsc, action, order_opts, data_set);
220 break;
221
222 case stop_rsc:
223 if (state == remote_state_alive) {
224 order_action_then_stop(action, remote_rsc,
225 pe_order_implies_first, data_set);
226
227 } else if (state == remote_state_failed) {
228
229
230
231
232
233
234 pe_fence_node(data_set, action->node,
235 "resources are active but connection is unrecoverable",
236 FALSE);
237
238 } else if (remote_rsc->next_role == RSC_ROLE_STOPPED) {
239
240
241
242
243 order_action_then_stop(action, remote_rsc,
244 pe_order_implies_first, data_set);
245
246 } else {
247
248
249
250 order_start_then_action(remote_rsc, action, pe_order_none,
251 data_set);
252 }
253 break;
254
255 case action_demote:
256
257
258
259
260 if ((state == remote_state_resting)
261 || (state == remote_state_unknown)) {
262
263 order_start_then_action(remote_rsc, action, pe_order_none,
264 data_set);
265 }
266 break;
267
268 default:
269
270 if (is_recurring_action(action)) {
271
272
273
274
275 order_start_then_action(remote_rsc, action,
276 pe_order_implies_then, data_set);
277
278 } else {
279 pe_node_t *cluster_node = pe__current_node(remote_rsc);
280
281 if ((task == monitor_rsc) && (state == remote_state_failed)) {
282
283
284
285
286 pe_fence_node(data_set, action->node,
287 "resources are in unknown state "
288 "and connection is unrecoverable", FALSE);
289 }
290
291 if ((cluster_node != NULL) && (state == remote_state_stopped)) {
292
293
294
295
296 order_action_then_stop(action, remote_rsc,
297 pe_order_runnable_left, data_set);
298
299 } else {
300 order_start_then_action(remote_rsc, action, pe_order_none,
301 data_set);
302 }
303 }
304 break;
305 }
306 }
307
308 static void
309 apply_container_ordering(pe_action_t *action, pe_working_set_t *data_set)
310 {
311
312
313
314
315
316
317
318 pe_resource_t *remote_rsc = NULL;
319 pe_resource_t *container = NULL;
320 enum action_tasks task = text2task(action->task);
321
322 CRM_ASSERT(action->rsc != NULL);
323 CRM_ASSERT(action->node != NULL);
324 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
325
326 remote_rsc = action->node->details->remote_rsc;
327 CRM_ASSERT(remote_rsc != NULL);
328
329 container = remote_rsc->container;
330 CRM_ASSERT(container != NULL);
331
332 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
333 pe_fence_node(data_set, action->node, "container failed", FALSE);
334 }
335
336 crm_trace("Order %s action %s relative to %s%s for %s%s",
337 action->task, action->uuid,
338 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
339 remote_rsc->id,
340 pcmk_is_set(container->flags, pe_rsc_failed)? "failed " : "",
341 container->id);
342
343 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE,
344 CRMD_ACTION_MIGRATED, NULL)) {
345
346
347
348 task = stop_rsc;
349 }
350
351 switch (task) {
352 case start_rsc:
353 case action_promote:
354
355 order_start_then_action(container, action, pe_order_implies_then,
356 data_set);
357
358
359 order_start_then_action(remote_rsc, action, pe_order_none,
360 data_set);
361 break;
362
363 case stop_rsc:
364 case action_demote:
365 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
366
367
368
369
370
371
372 } else {
373
374
375
376
377
378
379
380
381 order_action_then_stop(action, remote_rsc, pe_order_none,
382 data_set);
383 }
384 break;
385
386 default:
387
388 if (is_recurring_action(action)) {
389
390
391
392
393 if(task != no_action) {
394 order_start_then_action(remote_rsc, action,
395 pe_order_implies_then, data_set);
396 }
397 } else {
398 order_start_then_action(remote_rsc, action, pe_order_none,
399 data_set);
400 }
401 break;
402 }
403 }
404
405
406
407
408
409
410
411 void
412 pcmk__order_remote_connection_actions(pe_working_set_t *data_set)
413 {
414 if (!pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
415 return;
416 }
417
418 crm_trace("Creating remote connection orderings");
419
420 for (GList *gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
421 pe_action_t *action = (pe_action_t *) gIter->data;
422 pe_resource_t *remote = NULL;
423
424
425 if (action->rsc == NULL) {
426 continue;
427 }
428
429
430
431
432
433 if (action->rsc->is_remote_node &&
434 pcmk__str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT, pcmk__str_casei)) {
435
436 pcmk__new_ordering(action->rsc, NULL, action, action->rsc,
437 pcmk__op_key(action->rsc->id, RSC_START, 0),
438 NULL, pe_order_optional, data_set);
439
440 continue;
441 }
442
443
444 if (action->node == NULL) {
445 continue;
446 }
447
448 if (!pe__is_guest_or_remote_node(action->node)) {
449 continue;
450 }
451
452
453
454
455
456
457
458 if (pcmk_is_set(action->flags, pe_action_pseudo)) {
459 continue;
460 }
461
462 remote = action->node->details->remote_rsc;
463 if (remote == NULL) {
464
465 continue;
466 }
467
468
469
470
471
472
473 if (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)) {
474 for (GList *item = action->rsc->actions; item != NULL;
475 item = item->next) {
476 pe_action_t *rsc_action = item->data;
477
478 if ((rsc_action->node->details != action->node->details)
479 && pcmk__str_eq(rsc_action->task, RSC_STOP, pcmk__str_casei)) {
480 pcmk__new_ordering(remote, start_key(remote), NULL,
481 action->rsc, NULL, rsc_action,
482 pe_order_optional, data_set);
483 }
484 }
485 }
486
487
488
489
490
491
492
493
494
495
496 if (remote->container) {
497 crm_trace("Container ordering for %s", action->uuid);
498 apply_container_ordering(action, data_set);
499
500 } else {
501 crm_trace("Remote ordering for %s", action->uuid);
502 apply_remote_ordering(action, data_set);
503 }
504 }
505 }
506
507
508
509
510
511
512
513
514
515 bool
516 pcmk__is_failed_remote_node(pe_node_t *node)
517 {
518 return pe__is_remote_node(node) && (node->details->remote_rsc != NULL)
519 && (get_remote_node_state(node) == remote_state_failed);
520 }
521
522
523
524
525
526
527
528
529
530
531
532 bool
533 pcmk__rsc_corresponds_to_guest(pe_resource_t *rsc, pe_node_t *node)
534 {
535 return (rsc != NULL) && (rsc->fillers != NULL) && (node != NULL)
536 && (node->details->remote_rsc != NULL)
537 && (node->details->remote_rsc->container == rsc);
538 }
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554 pe_node_t *
555 pcmk__connection_host_for_action(pe_action_t *action)
556 {
557 pe_node_t *began_on = NULL;
558 pe_node_t *ended_on = NULL;
559 bool partial_migration = false;
560 const char *task = action->task;
561
562 if (pcmk__str_eq(task, CRM_OP_FENCE, pcmk__str_casei)
563 || !pe__is_guest_or_remote_node(action->node)) {
564 return NULL;
565 }
566
567 CRM_ASSERT(action->node->details->remote_rsc != NULL);
568
569 began_on = pe__current_node(action->node->details->remote_rsc);
570 ended_on = action->node->details->remote_rsc->allocated_to;
571 if (action->node->details->remote_rsc
572 && (action->node->details->remote_rsc->container == NULL)
573 && action->node->details->remote_rsc->partial_migration_target) {
574 partial_migration = true;
575 }
576
577 if (began_on == NULL) {
578 crm_trace("Routing %s for %s through remote connection's "
579 "next node %s (starting)%s",
580 action->task, (action->rsc? action->rsc->id : "no resource"),
581 (ended_on? ended_on->details->uname : "none"),
582 partial_migration? " (partial migration)" : "");
583 return ended_on;
584 }
585
586 if (ended_on == NULL) {
587 crm_trace("Routing %s for %s through remote connection's "
588 "current node %s (stopping)%s",
589 action->task, (action->rsc? action->rsc->id : "no resource"),
590 (began_on? began_on->details->uname : "none"),
591 partial_migration? " (partial migration)" : "");
592 return began_on;
593 }
594
595 if (began_on->details == ended_on->details) {
596 crm_trace("Routing %s for %s through remote connection's "
597 "current node %s (not moving)%s",
598 action->task, (action->rsc? action->rsc->id : "no resource"),
599 (began_on? began_on->details->uname : "none"),
600 partial_migration? " (partial migration)" : "");
601 return began_on;
602 }
603
604
605
606
607
608
609
610
611 if (pcmk__str_eq(task, "notify", pcmk__str_casei)) {
612 task = g_hash_table_lookup(action->meta, "notify_operation");
613 }
614
615
616
617
618
619
620
621
622
623
624
625
626
627 if (pcmk__strcase_any_of(task, "cancel", "stop", "demote", "migrate_from",
628 "migrate_to", NULL) && !partial_migration) {
629 crm_trace("Routing %s for %s through remote connection's "
630 "current node %s (moving)%s",
631 action->task, (action->rsc? action->rsc->id : "no resource"),
632 (began_on? began_on->details->uname : "none"),
633 partial_migration? " (partial migration)" : "");
634 return began_on;
635 }
636
637
638
639
640
641 crm_trace("Routing %s for %s through remote connection's "
642 "next node %s (moving)%s",
643 action->task, (action->rsc? action->rsc->id : "no resource"),
644 (ended_on? ended_on->details->uname : "none"),
645 partial_migration? " (partial migration)" : "");
646 return ended_on;
647 }
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662 void
663 pcmk__substitute_remote_addr(pe_resource_t *rsc, GHashTable *params,
664 pe_working_set_t *data_set)
665 {
666 const char *remote_addr = g_hash_table_lookup(params,
667 XML_RSC_ATTR_REMOTE_RA_ADDR);
668
669 if (pcmk__str_eq(remote_addr, "#uname", pcmk__str_none)) {
670 GHashTable *base = pe_rsc_params(rsc, NULL, data_set);
671
672 remote_addr = g_hash_table_lookup(base, XML_RSC_ATTR_REMOTE_RA_ADDR);
673 if (remote_addr != NULL) {
674 g_hash_table_insert(params, strdup(XML_RSC_ATTR_REMOTE_RA_ADDR),
675 strdup(remote_addr));
676 }
677 }
678 }
679
680
681
682
683
684
685
686
687
688
689
690
691 void
692 pcmk__add_bundle_meta_to_xml(xmlNode *args_xml, pe_action_t *action)
693 {
694 pe_node_t *host = NULL;
695 enum action_tasks task;
696
697 if (!pe__is_guest_node(action->node)) {
698 return;
699 }
700
701 task = text2task(action->task);
702 if ((task == action_notify) || (task == action_notified)) {
703 task = text2task(g_hash_table_lookup(action->meta, "notify_operation"));
704 }
705
706 switch (task) {
707 case stop_rsc:
708 case stopped_rsc:
709 case action_demote:
710 case action_demoted:
711
712 host = pe__current_node(action->node->details->remote_rsc->container);
713 break;
714
715 case start_rsc:
716 case started_rsc:
717 case monitor_rsc:
718 case action_promote:
719 case action_promoted:
720
721 host = action->node->details->remote_rsc->container->allocated_to;
722 break;
723
724 default:
725 break;
726 }
727
728 if (host != NULL) {
729 hash2metafield((gpointer) XML_RSC_ATTR_TARGET,
730 (gpointer) g_hash_table_lookup(action->rsc->meta,
731 XML_RSC_ATTR_TARGET),
732 (gpointer) args_xml);
733 hash2metafield((gpointer) PCMK__ENV_PHYSICAL_HOST,
734 (gpointer) host->details->uname,
735 (gpointer) args_xml);
736 }
737 }