This source file includes following definitions.
- state2text
- order_start_then_action
- order_action_then_stop
- get_remote_node_state
- 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 *first_rsc, pe_action_t *then_action,
63 uint32_t extra, pe_working_set_t *data_set)
64 {
65 if ((first_rsc != NULL) && (then_action != NULL) && (data_set != NULL)) {
66 pcmk__new_ordering(first_rsc, start_key(first_rsc), NULL,
67 then_action->rsc, NULL, then_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 *first_action, pe_resource_t *then_rsc,
75 uint32_t extra, pe_working_set_t *data_set)
76 {
77 if ((first_action != NULL) && (then_rsc != NULL) && (data_set != NULL)) {
78 pcmk__new_ordering(first_action->rsc, NULL, first_action,
79 then_rsc, stop_key(then_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
161
162
163
164 static void
165 apply_remote_ordering(pe_action_t *action, pe_working_set_t *data_set)
166 {
167 pe_resource_t *remote_rsc = NULL;
168 enum action_tasks task = text2task(action->task);
169 enum remote_connection_state state = get_remote_node_state(action->node);
170
171 uint32_t order_opts = pe_order_none;
172
173 if (action->rsc == NULL) {
174 return;
175 }
176
177 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
178
179 remote_rsc = action->node->details->remote_rsc;
180 CRM_ASSERT(remote_rsc != NULL);
181
182 crm_trace("Order %s action %s relative to %s%s (state: %s)",
183 action->task, action->uuid,
184 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
185 remote_rsc->id, state2text(state));
186
187 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE,
188 CRMD_ACTION_MIGRATED, NULL)) {
189
190
191
192 task = stop_rsc;
193 }
194
195 switch (task) {
196 case start_rsc:
197 case action_promote:
198 order_opts = pe_order_none;
199
200 if (state == remote_state_failed) {
201
202 pe__set_order_flags(order_opts, pe_order_implies_then);
203 }
204
205
206 order_start_then_action(remote_rsc, action, order_opts, data_set);
207 break;
208
209 case stop_rsc:
210 if (state == remote_state_alive) {
211 order_action_then_stop(action, remote_rsc,
212 pe_order_implies_first, data_set);
213
214 } else if (state == remote_state_failed) {
215
216
217
218
219
220
221 pe_fence_node(data_set, action->node,
222 "resources are active but connection is unrecoverable",
223 FALSE);
224
225 } else if (remote_rsc->next_role == RSC_ROLE_STOPPED) {
226
227
228
229
230 order_action_then_stop(action, remote_rsc,
231 pe_order_implies_first, data_set);
232
233 } else {
234
235
236
237 order_start_then_action(remote_rsc, action, pe_order_none,
238 data_set);
239 }
240 break;
241
242 case action_demote:
243
244
245
246
247 if ((state == remote_state_resting)
248 || (state == remote_state_unknown)) {
249
250 order_start_then_action(remote_rsc, action, pe_order_none,
251 data_set);
252 }
253 break;
254
255 default:
256
257 if (pcmk__action_is_recurring(action)) {
258
259
260
261
262 order_start_then_action(remote_rsc, action,
263 pe_order_implies_then, data_set);
264
265 } else {
266 pe_node_t *cluster_node = pe__current_node(remote_rsc);
267
268 if ((task == monitor_rsc) && (state == remote_state_failed)) {
269
270
271
272
273 pe_fence_node(data_set, action->node,
274 "resources are in unknown state "
275 "and connection is unrecoverable", FALSE);
276 }
277
278 if ((cluster_node != NULL) && (state == remote_state_stopped)) {
279
280
281
282
283 order_action_then_stop(action, remote_rsc,
284 pe_order_runnable_left, data_set);
285
286 } else {
287 order_start_then_action(remote_rsc, action, pe_order_none,
288 data_set);
289 }
290 }
291 break;
292 }
293 }
294
295 static void
296 apply_container_ordering(pe_action_t *action, pe_working_set_t *data_set)
297 {
298
299
300
301
302
303
304
305 pe_resource_t *remote_rsc = NULL;
306 pe_resource_t *container = NULL;
307 enum action_tasks task = text2task(action->task);
308
309 CRM_ASSERT(action->rsc != NULL);
310 CRM_ASSERT(action->node != NULL);
311 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
312
313 remote_rsc = action->node->details->remote_rsc;
314 CRM_ASSERT(remote_rsc != NULL);
315
316 container = remote_rsc->container;
317 CRM_ASSERT(container != NULL);
318
319 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
320 pe_fence_node(data_set, action->node, "container failed", FALSE);
321 }
322
323 crm_trace("Order %s action %s relative to %s%s for %s%s",
324 action->task, action->uuid,
325 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
326 remote_rsc->id,
327 pcmk_is_set(container->flags, pe_rsc_failed)? "failed " : "",
328 container->id);
329
330 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE,
331 CRMD_ACTION_MIGRATED, NULL)) {
332
333
334
335 task = stop_rsc;
336 }
337
338 switch (task) {
339 case start_rsc:
340 case action_promote:
341
342 order_start_then_action(container, action, pe_order_implies_then,
343 data_set);
344
345
346 order_start_then_action(remote_rsc, action, pe_order_none,
347 data_set);
348 break;
349
350 case stop_rsc:
351 case action_demote:
352 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
353
354
355
356
357
358
359 } else {
360
361
362
363
364
365
366
367
368 order_action_then_stop(action, remote_rsc, pe_order_none,
369 data_set);
370 }
371 break;
372
373 default:
374
375 if (pcmk__action_is_recurring(action)) {
376
377
378
379
380 if(task != no_action) {
381 order_start_then_action(remote_rsc, action,
382 pe_order_implies_then, data_set);
383 }
384 } else {
385 order_start_then_action(remote_rsc, action, pe_order_none,
386 data_set);
387 }
388 break;
389 }
390 }
391
392
393
394
395
396
397
398 void
399 pcmk__order_remote_connection_actions(pe_working_set_t *data_set)
400 {
401 if (!pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
402 return;
403 }
404
405 crm_trace("Creating remote connection orderings");
406
407 for (GList *gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
408 pe_action_t *action = (pe_action_t *) gIter->data;
409 pe_resource_t *remote = NULL;
410
411
412 if (action->rsc == NULL) {
413 continue;
414 }
415
416
417
418
419
420 if (action->rsc->is_remote_node &&
421 pcmk__str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT, pcmk__str_casei)) {
422
423 pcmk__new_ordering(action->rsc, NULL, action, action->rsc,
424 pcmk__op_key(action->rsc->id, RSC_START, 0),
425 NULL, pe_order_optional, data_set);
426
427 continue;
428 }
429
430
431 if (action->node == NULL) {
432 continue;
433 }
434
435 if (!pe__is_guest_or_remote_node(action->node)) {
436 continue;
437 }
438
439
440
441
442
443
444
445 if (pcmk_is_set(action->flags, pe_action_pseudo)) {
446 continue;
447 }
448
449 remote = action->node->details->remote_rsc;
450 if (remote == NULL) {
451
452 continue;
453 }
454
455
456
457
458
459
460 if (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)) {
461 for (GList *item = action->rsc->actions; item != NULL;
462 item = item->next) {
463 pe_action_t *rsc_action = item->data;
464
465 if ((rsc_action->node->details != action->node->details)
466 && pcmk__str_eq(rsc_action->task, RSC_STOP, pcmk__str_casei)) {
467 pcmk__new_ordering(remote, start_key(remote), NULL,
468 action->rsc, NULL, rsc_action,
469 pe_order_optional, data_set);
470 }
471 }
472 }
473
474
475
476
477
478
479
480
481
482
483 if (remote->container) {
484 crm_trace("Container ordering for %s", action->uuid);
485 apply_container_ordering(action, data_set);
486
487 } else {
488 crm_trace("Remote ordering for %s", action->uuid);
489 apply_remote_ordering(action, data_set);
490 }
491 }
492 }
493
494
495
496
497
498
499
500
501
502 bool
503 pcmk__is_failed_remote_node(pe_node_t *node)
504 {
505 return pe__is_remote_node(node) && (node->details->remote_rsc != NULL)
506 && (get_remote_node_state(node) == remote_state_failed);
507 }
508
509
510
511
512
513
514
515
516
517
518
519 bool
520 pcmk__rsc_corresponds_to_guest(pe_resource_t *rsc, pe_node_t *node)
521 {
522 return (rsc != NULL) && (rsc->fillers != NULL) && (node != NULL)
523 && (node->details->remote_rsc != NULL)
524 && (node->details->remote_rsc->container == rsc);
525 }
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541 pe_node_t *
542 pcmk__connection_host_for_action(pe_action_t *action)
543 {
544 pe_node_t *began_on = NULL;
545 pe_node_t *ended_on = NULL;
546 bool partial_migration = false;
547 const char *task = action->task;
548
549 if (pcmk__str_eq(task, CRM_OP_FENCE, pcmk__str_casei)
550 || !pe__is_guest_or_remote_node(action->node)) {
551 return NULL;
552 }
553
554 CRM_ASSERT(action->node->details->remote_rsc != NULL);
555
556 began_on = pe__current_node(action->node->details->remote_rsc);
557 ended_on = action->node->details->remote_rsc->allocated_to;
558 if (action->node->details->remote_rsc
559 && (action->node->details->remote_rsc->container == NULL)
560 && action->node->details->remote_rsc->partial_migration_target) {
561 partial_migration = true;
562 }
563
564 if (began_on == NULL) {
565 crm_trace("Routing %s for %s through remote connection's "
566 "next node %s (starting)%s",
567 action->task, (action->rsc? action->rsc->id : "no resource"),
568 (ended_on? ended_on->details->uname : "none"),
569 partial_migration? " (partial migration)" : "");
570 return ended_on;
571 }
572
573 if (ended_on == NULL) {
574 crm_trace("Routing %s for %s through remote connection's "
575 "current node %s (stopping)%s",
576 action->task, (action->rsc? action->rsc->id : "no resource"),
577 (began_on? began_on->details->uname : "none"),
578 partial_migration? " (partial migration)" : "");
579 return began_on;
580 }
581
582 if (began_on->details == ended_on->details) {
583 crm_trace("Routing %s for %s through remote connection's "
584 "current node %s (not moving)%s",
585 action->task, (action->rsc? action->rsc->id : "no resource"),
586 (began_on? began_on->details->uname : "none"),
587 partial_migration? " (partial migration)" : "");
588 return began_on;
589 }
590
591
592
593
594
595
596
597
598 if (pcmk__str_eq(task, "notify", pcmk__str_casei)) {
599 task = g_hash_table_lookup(action->meta, "notify_operation");
600 }
601
602
603
604
605
606
607
608
609
610
611
612
613
614 if (pcmk__strcase_any_of(task, "cancel", "stop", "demote", "migrate_from",
615 "migrate_to", NULL) && !partial_migration) {
616 crm_trace("Routing %s for %s through remote connection's "
617 "current node %s (moving)%s",
618 action->task, (action->rsc? action->rsc->id : "no resource"),
619 (began_on? began_on->details->uname : "none"),
620 partial_migration? " (partial migration)" : "");
621 return began_on;
622 }
623
624
625
626
627
628 crm_trace("Routing %s for %s through remote connection's "
629 "next node %s (moving)%s",
630 action->task, (action->rsc? action->rsc->id : "no resource"),
631 (ended_on? ended_on->details->uname : "none"),
632 partial_migration? " (partial migration)" : "");
633 return ended_on;
634 }
635
636
637
638
639
640
641
642
643
644
645
646
647
648 void
649 pcmk__substitute_remote_addr(pe_resource_t *rsc, GHashTable *params)
650 {
651 const char *remote_addr = g_hash_table_lookup(params,
652 XML_RSC_ATTR_REMOTE_RA_ADDR);
653
654 if (pcmk__str_eq(remote_addr, "#uname", pcmk__str_none)) {
655 GHashTable *base = pe_rsc_params(rsc, NULL, rsc->cluster);
656
657 remote_addr = g_hash_table_lookup(base, XML_RSC_ATTR_REMOTE_RA_ADDR);
658 if (remote_addr != NULL) {
659 g_hash_table_insert(params, strdup(XML_RSC_ATTR_REMOTE_RA_ADDR),
660 strdup(remote_addr));
661 }
662 }
663 }
664
665
666
667
668
669
670
671
672
673
674
675
676 void
677 pcmk__add_bundle_meta_to_xml(xmlNode *args_xml, pe_action_t *action)
678 {
679 pe_node_t *host = NULL;
680 enum action_tasks task;
681
682 if (!pe__is_guest_node(action->node)) {
683 return;
684 }
685
686 task = text2task(action->task);
687 if ((task == action_notify) || (task == action_notified)) {
688 task = text2task(g_hash_table_lookup(action->meta, "notify_operation"));
689 }
690
691 switch (task) {
692 case stop_rsc:
693 case stopped_rsc:
694 case action_demote:
695 case action_demoted:
696
697 host = pe__current_node(action->node->details->remote_rsc->container);
698 break;
699
700 case start_rsc:
701 case started_rsc:
702 case monitor_rsc:
703 case action_promote:
704 case action_promoted:
705
706 host = action->node->details->remote_rsc->container->allocated_to;
707 break;
708
709 default:
710 break;
711 }
712
713 if (host != NULL) {
714 hash2metafield((gpointer) XML_RSC_ATTR_TARGET,
715 (gpointer) g_hash_table_lookup(action->rsc->meta,
716 XML_RSC_ATTR_TARGET),
717 (gpointer) args_xml);
718 hash2metafield((gpointer) PCMK__ENV_PHYSICAL_HOST,
719 (gpointer) host->details->uname,
720 (gpointer) args_xml);
721 }
722 }