1    	/*
2    	 * Copyright 2004-2023 the Pacemaker project contributors
3    	 *
4    	 * The version control history for this file may have further details.
5    	 *
6    	 * This source code is licensed under the GNU General Public License version 2
7    	 * or later (GPLv2+) WITHOUT ANY WARRANTY.
8    	 */
9    	
10   	#include <crm_internal.h>
11   	
12   	#include <stdbool.h>
13   	
14   	#include <crm/msg_xml.h>
15   	#include <pacemaker-internal.h>
16   	
17   	#include "libpacemaker_private.h"
18   	
19   	/*!
20   	 * \internal
21   	 * \brief Add migration source and target meta-attributes to an action
22   	 *
23   	 * \param[in,out] action  Action to add meta-attributes to
24   	 * \param[in]     source  Node to add as migration source
25   	 * \param[in]     target  Node to add as migration target
26   	 */
27   	static void
28   	add_migration_meta(pcmk_action_t *action, const pcmk_node_t *source,
29   	                   const pcmk_node_t *target)
30   	{
31   	    add_hash_param(action->meta, XML_LRM_ATTR_MIGRATE_SOURCE,
32   	                   source->details->uname);
33   	
34   	    add_hash_param(action->meta, XML_LRM_ATTR_MIGRATE_TARGET,
35   	                   target->details->uname);
36   	}
37   	
38   	/*!
39   	 * \internal
40   	 * \brief Create internal migration actions for a migrateable resource
41   	 *
42   	 * \param[in,out] rsc      Resource to create migration actions for
43   	 * \param[in]     current  Node that resource is originally active on
44   	 */
45   	void
46   	pcmk__create_migration_actions(pcmk_resource_t *rsc, const pcmk_node_t *current)
47   	{
48   	    pcmk_action_t *migrate_to = NULL;
49   	    pcmk_action_t *migrate_from = NULL;
50   	    pcmk_action_t *start = NULL;
51   	    pcmk_action_t *stop = NULL;
52   	
53   	    pe_rsc_trace(rsc, "Creating actions to %smigrate %s from %s to %s",
54   	                 ((rsc->partial_migration_target == NULL)? "" : "partially "),
55   	                 rsc->id, pe__node_name(current),
56   	                 pe__node_name(rsc->allocated_to));
57   	    start = start_action(rsc, rsc->allocated_to, TRUE);
58   	    stop = stop_action(rsc, current, TRUE);
59   	
60   	    if (rsc->partial_migration_target == NULL) {
61   	        migrate_to = custom_action(rsc, pcmk__op_key(rsc->id,
62   	                                                     PCMK_ACTION_MIGRATE_TO, 0),
63   	                                   PCMK_ACTION_MIGRATE_TO, current, TRUE,
64   	                                   rsc->cluster);
65   	    }
66   	    migrate_from = custom_action(rsc, pcmk__op_key(rsc->id,
67   	                                                   PCMK_ACTION_MIGRATE_FROM, 0),
68   	                                 PCMK_ACTION_MIGRATE_FROM, rsc->allocated_to,
69   	                                 TRUE, rsc->cluster);
70   	
71   	    pe__set_action_flags(start, pcmk_action_migratable);
72   	    pe__set_action_flags(stop, pcmk_action_migratable);
73   	
74   	    // This is easier than trying to delete it from the graph
75   	    pe__set_action_flags(start, pcmk_action_pseudo);
76   	
77   	    if (rsc->partial_migration_target == NULL) {
78   	        pe__set_action_flags(migrate_from, pcmk_action_migratable);
79   	        pe__set_action_flags(migrate_to, pcmk_action_migratable);
80   	        migrate_to->needs = start->needs;
81   	
82   	        // Probe -> migrate_to -> migrate_from
83   	        pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0),
84   	                           NULL,
85   	                           rsc,
86   	                           pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_TO, 0),
87   	                           NULL, pcmk__ar_ordered, rsc->cluster);
88   	        pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_TO, 0),
89   	                           NULL,
90   	                           rsc,
91   	                           pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
92   	                           NULL,
93   	                           pcmk__ar_ordered|pcmk__ar_unmigratable_then_blocks,
94   	                           rsc->cluster);
95   	    } else {
96   	        pe__set_action_flags(migrate_from, pcmk_action_migratable);
97   	        migrate_from->needs = start->needs;
98   	
99   	        // Probe -> migrate_from (migrate_to already completed)
100  	        pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MONITOR, 0),
101  	                           NULL,
102  	                           rsc,
103  	                           pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
104  	                           NULL, pcmk__ar_ordered, rsc->cluster);
105  	    }
106  	
107  	    // migrate_from before stop or start
108  	    pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
109  	                       NULL,
110  	                       rsc, pcmk__op_key(rsc->id, PCMK_ACTION_STOP, 0),
111  	                       NULL,
112  	                       pcmk__ar_ordered|pcmk__ar_unmigratable_then_blocks,
113  	                       rsc->cluster);
114  	    pcmk__new_ordering(rsc, pcmk__op_key(rsc->id, PCMK_ACTION_MIGRATE_FROM, 0),
115  	                       NULL,
116  	                       rsc, pcmk__op_key(rsc->id, PCMK_ACTION_START, 0),
117  	                       NULL,
118  	                       pcmk__ar_ordered
119  	                       |pcmk__ar_unmigratable_then_blocks
120  	                       |pcmk__ar_first_else_then,
121  	                       rsc->cluster);
122  	
123  	    if (migrate_to != NULL) {
124  	        add_migration_meta(migrate_to, current, rsc->allocated_to);
125  	
126  	        if (!rsc->is_remote_node) {
127  	            /* migrate_to takes place on the source node, but can affect the
128  	             * target node depending on how the agent is written. Because of
129  	             * this, pending migrate_to actions must be recorded in the CIB,
130  	             * in case the source node loses membership while the migrate_to
131  	             * action is still in flight.
132  	             *
133  	             * However we know Pacemaker Remote connection resources don't
134  	             * require this, so we skip this for them. (Although it wouldn't
135  	             * hurt, and now that record-pending defaults to true, skipping it
136  	             * matters even less.)
137  	             */
138  	            add_hash_param(migrate_to->meta, XML_OP_ATTR_PENDING, "true");
139  	        }
140  	    }
141  	
142  	    add_migration_meta(migrate_from, current, rsc->allocated_to);
143  	}
144  	
145  	/*!
146  	 * \internal
147  	 * \brief Abort a dangling migration by scheduling a stop (and possibly cleanup)
148  	 *
149  	 * \param[in]     data       Source node of dangling migration
150  	 * \param[in,out] user_data  Resource involved in dangling migration
151  	 */
152  	void
153  	pcmk__abort_dangling_migration(void *data, void *user_data)
154  	{
155  	    const pcmk_node_t *dangling_source = (const pcmk_node_t *) data;
156  	    pcmk_resource_t *rsc = (pcmk_resource_t *) user_data;
157  	
158  	    pcmk_action_t *stop = NULL;
159  	    bool cleanup = pcmk_is_set(rsc->cluster->flags,
160  	                               pcmk_sched_remove_after_stop);
161  	
162  	    pe_rsc_trace(rsc,
163  	                 "Scheduling stop%s for %s on %s due to dangling migration",
164  	                 (cleanup? " and cleanup" : ""), rsc->id,
165  	                 pe__node_name(dangling_source));
166  	    stop = stop_action(rsc, dangling_source, FALSE);
167  	    pe__set_action_flags(stop, pcmk_action_migration_abort);
168  	    if (cleanup) {
169  	        pcmk__schedule_cleanup(rsc, dangling_source, false);
170  	    }
171  	}
172  	
173  	/*!
174  	 * \internal
175  	 * \brief Check whether a resource can migrate
176  	 *
177  	 * \param[in] rsc   Resource to check
178  	 * \param[in] node  Resource's current node
179  	 *
180  	 * \return true if \p rsc can migrate, otherwise false
181  	 */
182  	bool
183  	pcmk__rsc_can_migrate(const pcmk_resource_t *rsc, const pcmk_node_t *current)
184  	{
185  	    CRM_CHECK(rsc != NULL, return false);
186  	
187  	    if (!pcmk_is_set(rsc->flags, pcmk_rsc_migratable)) {
188  	        pe_rsc_trace(rsc, "%s cannot migrate because "
189  	                          "the configuration does not allow it",
190  	                     rsc->id);
191  	        return false;
192  	    }
193  	
194  	    if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
195  	        pe_rsc_trace(rsc, "%s cannot migrate because it is not managed",
196  	                     rsc->id);
197  	        return false;
198  	    }
199  	
200  	    if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
201  	        pe_rsc_trace(rsc, "%s cannot migrate because it is failed",
202  	                     rsc->id);
203  	        return false;
204  	    }
205  	
206  	    if (pcmk_is_set(rsc->flags, pcmk_rsc_start_pending)) {
207  	        pe_rsc_trace(rsc, "%s cannot migrate because it has a start pending",
208  	                     rsc->id);
209  	        return false;
210  	    }
211  	
212  	    if ((current == NULL) || current->details->unclean) {
213  	        pe_rsc_trace(rsc, "%s cannot migrate because "
214  	                          "its current node (%s) is unclean",
215  	                     rsc->id, pe__node_name(current));
216  	        return false;
217  	    }
218  	
219  	    if ((rsc->allocated_to == NULL) || rsc->allocated_to->details->unclean) {
220  	        pe_rsc_trace(rsc, "%s cannot migrate because "
221  	                          "its next node (%s) is unclean",
222  	                     rsc->id, pe__node_name(rsc->allocated_to));
223  	        return false;
224  	    }
225  	
226  	    return true;
227  	}
228  	
229  	/*!
230  	 * \internal
231  	 * \brief Get an action name from an action or operation key
232  	 *
233  	 * \param[in] action  If not NULL, get action name from here
234  	 * \param[in] key     If not NULL, get action name from here
235  	 *
236  	 * \return Newly allocated copy of action name (or NULL if none available)
237  	 */
238  	static char *
239  	task_from_action_or_key(const pcmk_action_t *action, const char *key)
240  	{
241  	    char *res = NULL;
242  	
243  	    if (action != NULL) {
244  	        res = strdup(action->task);
245  	        CRM_ASSERT(res != NULL);
246  	    } else if (key != NULL) {
247  	        parse_op_key(key, NULL, &res, NULL);
248  	    }
249  	    return res;
250  	}
251  	
252  	/*!
253  	 * \internal
254  	 * \brief Order migration actions equivalent to a given ordering
255  	 *
256  	 * Orderings involving start, stop, demote, and promote actions must be honored
257  	 * during a migration as well, so duplicate any such ordering for the
258  	 * corresponding migration actions.
259  	 *
260  	 * \param[in,out] order     Ordering constraint to check
261  	 */
262  	void
263  	pcmk__order_migration_equivalents(pe__ordering_t *order)
264  	{
265  	    char *first_task = NULL;
266  	    char *then_task = NULL;
267  	    bool then_migratable;
268  	    bool first_migratable;
269  	
270  	    // Only orderings between unrelated resources are relevant
(15) Event example_checked: Example 1: "order->lh_rsc" has its value checked in "order->lh_rsc == NULL".
Also see events: [null_field][dereference][example_checked][example_checked][example_checked]
271  	    if ((order->lh_rsc == NULL) || (order->rh_rsc == NULL)
272  	        || (order->lh_rsc == order->rh_rsc)
273  	        || is_parent(order->lh_rsc, order->rh_rsc)
274  	        || is_parent(order->rh_rsc, order->lh_rsc)) {
275  	        return;
276  	    }
277  	
278  	    // Only orderings involving at least one migratable resource are relevant
279  	    first_migratable = pcmk_is_set(order->lh_rsc->flags, pcmk_rsc_migratable);
280  	    then_migratable = pcmk_is_set(order->rh_rsc->flags, pcmk_rsc_migratable);
281  	    if (!first_migratable && !then_migratable) {
282  	        return;
283  	    }
284  	
285  	    // Check which actions are involved
286  	    first_task = task_from_action_or_key(order->lh_action,
287  	                                         order->lh_action_task);
288  	    then_task = task_from_action_or_key(order->rh_action,
289  	                                        order->rh_action_task);
290  	
291  	    if (pcmk__str_eq(first_task, PCMK_ACTION_START, pcmk__str_none)
292  	        && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
293  	
294  	        uint32_t flags = pcmk__ar_ordered;
295  	
296  	        if (first_migratable && then_migratable) {
297  	            /* A start then B start
298  	             * -> A migrate_from then B migrate_to */
299  	            pcmk__new_ordering(order->lh_rsc,
300  	                               pcmk__op_key(order->lh_rsc->id,
301  	                                            PCMK_ACTION_MIGRATE_FROM, 0),
302  	                               NULL, order->rh_rsc,
303  	                               pcmk__op_key(order->rh_rsc->id,
304  	                                            PCMK_ACTION_MIGRATE_TO, 0),
305  	                               NULL, flags, order->lh_rsc->cluster);
306  	        }
307  	
308  	        if (then_migratable) {
309  	            if (first_migratable) {
310  	                pe__set_order_flags(flags, pcmk__ar_if_first_unmigratable);
311  	            }
312  	
313  	            /* A start then B start
314  	             * -> A start then B migrate_to (if start is not part of a
315  	             *    migration)
316  	             */
317  	            pcmk__new_ordering(order->lh_rsc,
318  	                               pcmk__op_key(order->lh_rsc->id,
319  	                                            PCMK_ACTION_START, 0),
320  	                               NULL, order->rh_rsc,
321  	                               pcmk__op_key(order->rh_rsc->id,
322  	                                            PCMK_ACTION_MIGRATE_TO, 0),
323  	                               NULL, flags, order->lh_rsc->cluster);
324  	        }
325  	
326  	    } else if (then_migratable
327  	               && pcmk__str_eq(first_task, PCMK_ACTION_STOP, pcmk__str_none)
328  	               && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
329  	
330  	        uint32_t flags = pcmk__ar_ordered;
331  	
332  	        if (first_migratable) {
333  	            pe__set_order_flags(flags, pcmk__ar_if_first_unmigratable);
334  	        }
335  	
336  	        /* For an ordering "stop A then stop B", if A is moving via restart, and
337  	         * B is migrating, enforce that B's migrate_to occurs after A's stop.
338  	         */
339  	        pcmk__new_ordering(order->lh_rsc,
340  	                           pcmk__op_key(order->lh_rsc->id, PCMK_ACTION_STOP, 0),
341  	                           NULL,
342  	                           order->rh_rsc,
343  	                           pcmk__op_key(order->rh_rsc->id,
344  	                                        PCMK_ACTION_MIGRATE_TO, 0),
345  	                           NULL, flags, order->lh_rsc->cluster);
346  	
347  	        // Also order B's migrate_from after A's stop during partial migrations
348  	        if (order->rh_rsc->partial_migration_target) {
349  	            pcmk__new_ordering(order->lh_rsc,
350  	                               pcmk__op_key(order->lh_rsc->id, PCMK_ACTION_STOP,
351  	                                            0),
352  	                               NULL, order->rh_rsc,
353  	                               pcmk__op_key(order->rh_rsc->id,
354  	                                            PCMK_ACTION_MIGRATE_FROM, 0),
355  	                               NULL, flags, order->lh_rsc->cluster);
356  	        }
357  	
358  	    } else if (pcmk__str_eq(first_task, PCMK_ACTION_PROMOTE, pcmk__str_none)
359  	               && pcmk__str_eq(then_task, PCMK_ACTION_START, pcmk__str_none)) {
360  	
361  	        uint32_t flags = pcmk__ar_ordered;
362  	
363  	        if (then_migratable) {
364  	            /* A promote then B start
365  	             * -> A promote then B migrate_to */
366  	            pcmk__new_ordering(order->lh_rsc,
367  	                               pcmk__op_key(order->lh_rsc->id,
368  	                                            PCMK_ACTION_PROMOTE, 0),
369  	                               NULL, order->rh_rsc,
370  	                               pcmk__op_key(order->rh_rsc->id,
371  	                                            PCMK_ACTION_MIGRATE_TO, 0),
372  	                               NULL, flags, order->lh_rsc->cluster);
373  	        }
374  	
375  	    } else if (pcmk__str_eq(first_task, PCMK_ACTION_DEMOTE, pcmk__str_none)
376  	               && pcmk__str_eq(then_task, PCMK_ACTION_STOP, pcmk__str_none)) {
377  	
378  	        uint32_t flags = pcmk__ar_ordered;
379  	
380  	        if (then_migratable) {
381  	            /* A demote then B stop
382  	             * -> A demote then B migrate_to */
383  	            pcmk__new_ordering(order->lh_rsc,
384  	                               pcmk__op_key(order->lh_rsc->id,
385  	                                            PCMK_ACTION_DEMOTE, 0),
386  	                               NULL, order->rh_rsc,
387  	                               pcmk__op_key(order->rh_rsc->id,
388  	                                            PCMK_ACTION_MIGRATE_TO, 0),
389  	                               NULL, flags, order->lh_rsc->cluster);
390  	
391  	            // Order B migrate_from after A demote during partial migrations
392  	            if (order->rh_rsc->partial_migration_target) {
393  	                pcmk__new_ordering(order->lh_rsc,
394  	                                   pcmk__op_key(order->lh_rsc->id,
395  	                                                PCMK_ACTION_DEMOTE, 0),
396  	                                   NULL, order->rh_rsc,
397  	                                   pcmk__op_key(order->rh_rsc->id,
398  	                                                PCMK_ACTION_MIGRATE_FROM, 0),
399  	                                   NULL, flags, order->lh_rsc->cluster);
400  	            }
401  	        }
402  	    }
403  	
404  	    free(first_task);
405  	    free(then_task);
406  	}
407