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(pcmk_resource_t *first_rsc, pcmk_action_t *then_action,
63 uint32_t extra)
64 {
65 if ((first_rsc != NULL) && (then_action != NULL)) {
66 pcmk__new_ordering(first_rsc, start_key(first_rsc), NULL,
67 then_action->rsc, NULL, then_action,
68 pcmk__ar_guest_allowed
69 |pcmk__ar_unrunnable_first_blocks
70 |extra,
71 first_rsc->cluster);
72 }
73 }
74
75 static inline void
76 order_action_then_stop(pcmk_action_t *first_action, pcmk_resource_t *then_rsc,
77 uint32_t extra)
78 {
79 if ((first_action != NULL) && (then_rsc != NULL)) {
80 pcmk__new_ordering(first_action->rsc, NULL, first_action,
81 then_rsc, stop_key(then_rsc), NULL,
82 pcmk__ar_guest_allowed|extra, then_rsc->cluster);
83 }
84 }
85
86 static enum remote_connection_state
87 get_remote_node_state(const pcmk_node_t *node)
88 {
89 const pcmk_resource_t *remote_rsc = NULL;
90 const pcmk_node_t *cluster_node = NULL;
91
92 CRM_ASSERT(node != NULL);
93
94 remote_rsc = node->details->remote_rsc;
95 CRM_ASSERT(remote_rsc != NULL);
96
97 cluster_node = pe__current_node(remote_rsc);
98
99
100
101
102
103 if ((remote_rsc->next_role == pcmk_role_stopped)
104 || (remote_rsc->allocated_to == NULL)) {
105
106
107
108 if ((cluster_node != NULL) && cluster_node->details->unclean) {
109
110
111
112 return remote_state_failed;
113 }
114
115 if (!pcmk_is_set(remote_rsc->flags, pcmk_rsc_failed)) {
116
117 return remote_state_stopped;
118 }
119
120
121
122 if ((remote_rsc->next_role == pcmk_role_stopped)
123 && remote_rsc->remote_reconnect_ms
124 && node->details->remote_was_fenced
125 && !pe__shutdown_requested(node)) {
126
127
128
129
130 return remote_state_unknown;
131 }
132
133
134
135
136
137 return remote_state_failed;
138
139 } else if (cluster_node == NULL) {
140
141
142
143 return remote_state_unknown;
144
145 } else if (cluster_node->details->unclean
146 || !(cluster_node->details->online)) {
147
148 return remote_state_resting;
149
150 } else if (pcmk__list_of_multiple(remote_rsc->running_on)
151 && (remote_rsc->partial_migration_source != NULL)
152 && (remote_rsc->partial_migration_target != NULL)) {
153
154
155
156 return remote_state_resting;
157
158 }
159 return remote_state_alive;
160 }
161
162
163
164
165
166
167
168 static void
169 apply_remote_ordering(pcmk_action_t *action)
170 {
171 pcmk_resource_t *remote_rsc = NULL;
172 enum action_tasks task = text2task(action->task);
173 enum remote_connection_state state = get_remote_node_state(action->node);
174
175 uint32_t order_opts = pcmk__ar_none;
176
177 if (action->rsc == NULL) {
178 return;
179 }
180
181 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
182
183 remote_rsc = action->node->details->remote_rsc;
184 CRM_ASSERT(remote_rsc != NULL);
185
186 crm_trace("Order %s action %s relative to %s%s (state: %s)",
187 action->task, action->uuid,
188 pcmk_is_set(remote_rsc->flags, pcmk_rsc_failed)? "failed " : "",
189 remote_rsc->id, state2text(state));
190
191 if (pcmk__strcase_any_of(action->task, PCMK_ACTION_MIGRATE_TO,
192 PCMK_ACTION_MIGRATE_FROM, NULL)) {
193
194
195
196 task = pcmk_action_stop;
197 }
198
199 switch (task) {
200 case pcmk_action_start:
201 case pcmk_action_promote:
202 order_opts = pcmk__ar_none;
203
204 if (state == remote_state_failed) {
205
206 pe__set_order_flags(order_opts, pcmk__ar_first_implies_then);
207 }
208
209
210 order_start_then_action(remote_rsc, action, order_opts);
211 break;
212
213 case pcmk_action_stop:
214 if (state == remote_state_alive) {
215 order_action_then_stop(action, remote_rsc,
216 pcmk__ar_then_implies_first);
217
218 } else if (state == remote_state_failed) {
219
220
221
222
223
224
225 pe_fence_node(remote_rsc->cluster, action->node,
226 "resources are active but "
227 "connection is unrecoverable",
228 FALSE);
229
230 } else if (remote_rsc->next_role == pcmk_role_stopped) {
231
232
233
234
235 order_action_then_stop(action, remote_rsc,
236 pcmk__ar_then_implies_first);
237
238 } else {
239
240
241
242 order_start_then_action(remote_rsc, action, pcmk__ar_none);
243 }
244 break;
245
246 case pcmk_action_demote:
247
248
249
250
251 if ((state == remote_state_resting)
252 || (state == remote_state_unknown)) {
253
254 order_start_then_action(remote_rsc, action, pcmk__ar_none);
255 }
256 break;
257
258 default:
259
260 if (pcmk__action_is_recurring(action)) {
261
262
263
264
265 order_start_then_action(remote_rsc, action,
266 pcmk__ar_first_implies_then);
267
268 } else {
269 pcmk_node_t *cluster_node = pe__current_node(remote_rsc);
270
271 if ((task == pcmk_action_monitor) && (state == remote_state_failed)) {
272
273
274
275
276 pe_fence_node(remote_rsc->cluster, action->node,
277 "resources are in unknown state "
278 "and connection is unrecoverable", FALSE);
279 }
280
281 if ((cluster_node != NULL) && (state == remote_state_stopped)) {
282
283
284
285
286 order_action_then_stop(action, remote_rsc,
287 pcmk__ar_unrunnable_first_blocks);
288
289 } else {
290 order_start_then_action(remote_rsc, action, pcmk__ar_none);
291 }
292 }
293 break;
294 }
295 }
296
297 static void
298 apply_container_ordering(pcmk_action_t *action)
299 {
300
301
302
303
304
305
306
307 pcmk_resource_t *remote_rsc = NULL;
308 pcmk_resource_t *container = NULL;
309 enum action_tasks task = text2task(action->task);
310
311 CRM_ASSERT(action->rsc != NULL);
312 CRM_ASSERT(action->node != NULL);
313 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
314
315 remote_rsc = action->node->details->remote_rsc;
316 CRM_ASSERT(remote_rsc != NULL);
317
318 container = remote_rsc->container;
319 CRM_ASSERT(container != NULL);
320
321 if (pcmk_is_set(container->flags, pcmk_rsc_failed)) {
322 pe_fence_node(action->rsc->cluster, action->node, "container failed",
323 FALSE);
324 }
325
326 crm_trace("Order %s action %s relative to %s%s for %s%s",
327 action->task, action->uuid,
328 pcmk_is_set(remote_rsc->flags, pcmk_rsc_failed)? "failed " : "",
329 remote_rsc->id,
330 pcmk_is_set(container->flags, pcmk_rsc_failed)? "failed " : "",
331 container->id);
332
333 if (pcmk__strcase_any_of(action->task, PCMK_ACTION_MIGRATE_TO,
334 PCMK_ACTION_MIGRATE_FROM, NULL)) {
335
336
337
338 task = pcmk_action_stop;
339 }
340
341 switch (task) {
342 case pcmk_action_start:
343 case pcmk_action_promote:
344
345 order_start_then_action(container, action,
346 pcmk__ar_first_implies_then);
347
348
349 order_start_then_action(remote_rsc, action, pcmk__ar_none);
350 break;
351
352 case pcmk_action_stop:
353 case pcmk_action_demote:
354 if (pcmk_is_set(container->flags, pcmk_rsc_failed)) {
355
356
357
358
359
360
361 } else {
362
363
364
365
366
367
368
369
370 order_action_then_stop(action, remote_rsc, pcmk__ar_none);
371 }
372 break;
373
374 default:
375
376 if (pcmk__action_is_recurring(action)) {
377
378
379
380
381 if (task != pcmk_action_unspecified) {
382 order_start_then_action(remote_rsc, action,
383 pcmk__ar_first_implies_then);
384 }
385 } else {
386 order_start_then_action(remote_rsc, action, pcmk__ar_none);
387 }
388 break;
389 }
390 }
391
392
393
394
395
396
397
398 void
399 pcmk__order_remote_connection_actions(pcmk_scheduler_t *scheduler)
400 {
401 if (!pcmk_is_set(scheduler->flags, pcmk_sched_have_remote_nodes)) {
402 return;
403 }
404
405 crm_trace("Creating remote connection orderings");
406
407 for (GList *iter = scheduler->actions; iter != NULL; iter = iter->next) {
408 pcmk_action_t *action = iter->data;
409 pcmk_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, PCMK_ACTION_CLEAR_FAILCOUNT,
422 pcmk__str_none)) {
423
424 pcmk__new_ordering(action->rsc, NULL, action, action->rsc,
425 pcmk__op_key(action->rsc->id, PCMK_ACTION_START,
426 0),
427 NULL, pcmk__ar_ordered, scheduler);
428
429 continue;
430 }
431
432
433 if (action->node == NULL) {
434 continue;
435 }
436
437 if (!pe__is_guest_or_remote_node(action->node)) {
438 continue;
439 }
440
441
442
443
444
445
446
447 if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
448 continue;
449 }
450
451 remote = action->node->details->remote_rsc;
452 if (remote == NULL) {
453
454 continue;
455 }
456
457
458
459
460
461
462 if (pcmk__str_eq(action->task, PCMK_ACTION_START, pcmk__str_none)) {
463 for (GList *item = action->rsc->actions; item != NULL;
464 item = item->next) {
465 pcmk_action_t *rsc_action = item->data;
466
467 if (!pe__same_node(rsc_action->node, action->node)
468 && pcmk__str_eq(rsc_action->task, PCMK_ACTION_STOP,
469 pcmk__str_none)) {
470 pcmk__new_ordering(remote, start_key(remote), NULL,
471 action->rsc, NULL, rsc_action,
472 pcmk__ar_ordered, scheduler);
473 }
474 }
475 }
476
477
478
479
480
481
482
483
484
485
486 if (remote->container) {
487 crm_trace("Container ordering for %s", action->uuid);
488 apply_container_ordering(action);
489
490 } else {
491 crm_trace("Remote ordering for %s", action->uuid);
492 apply_remote_ordering(action);
493 }
494 }
495 }
496
497
498
499
500
501
502
503
504
505 bool
506 pcmk__is_failed_remote_node(const pcmk_node_t *node)
507 {
508 return pe__is_remote_node(node) && (node->details->remote_rsc != NULL)
509 && (get_remote_node_state(node) == remote_state_failed);
510 }
511
512
513
514
515
516
517
518
519
520
521
522 bool
523 pcmk__rsc_corresponds_to_guest(const pcmk_resource_t *rsc,
524 const pcmk_node_t *node)
525 {
526 return (rsc != NULL) && (rsc->fillers != NULL) && (node != NULL)
527 && (node->details->remote_rsc != NULL)
528 && (node->details->remote_rsc->container == rsc);
529 }
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545 pcmk_node_t *
546 pcmk__connection_host_for_action(const pcmk_action_t *action)
547 {
548 pcmk_node_t *began_on = NULL;
549 pcmk_node_t *ended_on = NULL;
550 bool partial_migration = false;
551 const char *task = action->task;
552
553 if (pcmk__str_eq(task, PCMK_ACTION_STONITH, pcmk__str_none)
554 || !pe__is_guest_or_remote_node(action->node)) {
555 return NULL;
556 }
557
558 CRM_ASSERT(action->node->details->remote_rsc != NULL);
559
560 began_on = pe__current_node(action->node->details->remote_rsc);
561 ended_on = action->node->details->remote_rsc->allocated_to;
562 if (action->node->details->remote_rsc
563 && (action->node->details->remote_rsc->container == NULL)
564 && action->node->details->remote_rsc->partial_migration_target) {
565 partial_migration = true;
566 }
567
568 if (began_on == NULL) {
569 crm_trace("Routing %s for %s through remote connection's "
570 "next node %s (starting)%s",
571 action->task, (action->rsc? action->rsc->id : "no resource"),
572 (ended_on? ended_on->details->uname : "none"),
573 partial_migration? " (partial migration)" : "");
574 return ended_on;
575 }
576
577 if (ended_on == NULL) {
578 crm_trace("Routing %s for %s through remote connection's "
579 "current node %s (stopping)%s",
580 action->task, (action->rsc? action->rsc->id : "no resource"),
581 (began_on? began_on->details->uname : "none"),
582 partial_migration? " (partial migration)" : "");
583 return began_on;
584 }
585
586 if (pe__same_node(began_on, ended_on)) {
587 crm_trace("Routing %s for %s through remote connection's "
588 "current node %s (not moving)%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
596
597
598
599
600
601
602 if (pcmk__str_eq(task, PCMK_ACTION_NOTIFY, pcmk__str_none)) {
603 task = g_hash_table_lookup(action->meta, "notify_operation");
604 }
605
606
607
608
609
610
611
612
613
614
615
616
617
618 if (pcmk__strcase_any_of(task, PCMK_ACTION_CANCEL, PCMK_ACTION_STOP,
619 PCMK_ACTION_DEMOTE, PCMK_ACTION_MIGRATE_FROM,
620 PCMK_ACTION_MIGRATE_TO, NULL)
621 && !partial_migration) {
622 crm_trace("Routing %s for %s through remote connection's "
623 "current node %s (moving)%s",
624 action->task, (action->rsc? action->rsc->id : "no resource"),
625 (began_on? began_on->details->uname : "none"),
626 partial_migration? " (partial migration)" : "");
627 return began_on;
628 }
629
630
631
632
633
634 crm_trace("Routing %s for %s through remote connection's "
635 "next node %s (moving)%s",
636 action->task, (action->rsc? action->rsc->id : "no resource"),
637 (ended_on? ended_on->details->uname : "none"),
638 partial_migration? " (partial migration)" : "");
639 return ended_on;
640 }
641
642
643
644
645
646
647
648
649
650
651
652
653
654 void
655 pcmk__substitute_remote_addr(pcmk_resource_t *rsc, GHashTable *params)
656 {
657 const char *remote_addr = g_hash_table_lookup(params,
658 XML_RSC_ATTR_REMOTE_RA_ADDR);
659
660 if (pcmk__str_eq(remote_addr, "#uname", pcmk__str_none)) {
661 GHashTable *base = pe_rsc_params(rsc, NULL, rsc->cluster);
662
663 remote_addr = g_hash_table_lookup(base, XML_RSC_ATTR_REMOTE_RA_ADDR);
664 if (remote_addr != NULL) {
665 g_hash_table_insert(params, strdup(XML_RSC_ATTR_REMOTE_RA_ADDR),
666 strdup(remote_addr));
667 }
668 }
669 }
670
671
672
673
674
675
676
677
678
679
680
681
682 void
683 pcmk__add_bundle_meta_to_xml(xmlNode *args_xml, const pcmk_action_t *action)
684 {
685 const pcmk_node_t *guest = action->node;
686 const pcmk_node_t *host = NULL;
687 enum action_tasks task;
688
689 if (!pe__is_guest_node(guest)) {
690 return;
691 }
692
693 task = text2task(action->task);
694 if ((task == pcmk_action_notify) || (task == pcmk_action_notified)) {
695 task = text2task(g_hash_table_lookup(action->meta, "notify_operation"));
696 }
697
698 switch (task) {
699 case pcmk_action_stop:
700 case pcmk_action_stopped:
701 case pcmk_action_demote:
702 case pcmk_action_demoted:
703
704 host = pe__current_node(guest->details->remote_rsc->container);
705 break;
706
707 case pcmk_action_start:
708 case pcmk_action_started:
709 case pcmk_action_monitor:
710 case pcmk_action_promote:
711 case pcmk_action_promoted:
712
713 host = guest->details->remote_rsc->container->allocated_to;
714 break;
715
716 default:
717 break;
718 }
719
720 if (host != NULL) {
721 hash2metafield((gpointer) XML_RSC_ATTR_TARGET,
722 (gpointer) g_hash_table_lookup(action->rsc->meta,
723 XML_RSC_ATTR_TARGET),
724 (gpointer) args_xml);
725 hash2metafield((gpointer) PCMK__ENV_PHYSICAL_HOST,
726 (gpointer) host->details->uname,
727 (gpointer) args_xml);
728 }
729 }