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   	struct assign_data {
20   	    const pcmk_node_t *prefer;
21   	    bool stop_if_fail;
22   	};
23   	
24   	/*!
25   	 * \internal
26   	 * \brief Assign a single bundle replica's resources (other than container)
27   	 *
28   	 * \param[in,out] replica    Replica to assign
29   	 * \param[in]     user_data  Preferred node, if any
30   	 *
31   	 * \return true (to indicate that any further replicas should be processed)
32   	 */
33   	static bool
34   	assign_replica(pe__bundle_replica_t *replica, void *user_data)
35   	{
36   	    pcmk_node_t *container_host = NULL;
37   	
38   	    struct assign_data *assign_data = user_data;
39   	    const pcmk_node_t *prefer = assign_data->prefer;
40   	    bool stop_if_fail = assign_data->stop_if_fail;
41   	
42   	    const pcmk_resource_t *bundle = pe__const_top_resource(replica->container,
43   	                                                           true);
44   	
45   	    if (replica->ip != NULL) {
46   	        pe_rsc_trace(bundle, "Assigning bundle %s IP %s",
47   	                     bundle->id, replica->ip->id);
48   	        replica->ip->cmds->assign(replica->ip, prefer, stop_if_fail);
49   	    }
50   	
51   	    container_host = replica->container->allocated_to;
52   	    if (replica->remote != NULL) {
53   	        if (pe__is_guest_or_remote_node(container_host)) {
54   	            /* REMOTE_CONTAINER_HACK: "Nested" connection resources must be on
55   	             * the same host because Pacemaker Remote only supports a single
56   	             * active connection.
57   	             */
58   	            pcmk__new_colocation("#replica-remote-with-host-remote", NULL,
59   	                                 INFINITY, replica->remote,
60   	                                 container_host->details->remote_rsc, NULL,
61   	                                 NULL, pcmk__coloc_influence);
62   	        }
63   	        pe_rsc_trace(bundle, "Assigning bundle %s connection %s",
64   	                     bundle->id, replica->remote->id);
65   	        replica->remote->cmds->assign(replica->remote, prefer, stop_if_fail);
66   	    }
67   	
(51) Event example_checked: Example 1: "replica->child" has its value checked in "replica->child != NULL".
Also see events: [null_field][dereference][example_checked][example_checked][example_checked][example_checked]
68   	    if (replica->child != NULL) {
69   	        pcmk_node_t *node = NULL;
70   	        GHashTableIter iter;
71   	
72   	        g_hash_table_iter_init(&iter, replica->child->allowed_nodes);
73   	        while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
74   	            if (!pe__same_node(node, replica->node)) {
75   	                node->weight = -INFINITY;
76   	            } else if (!pcmk__threshold_reached(replica->child, node, NULL)) {
77   	                node->weight = INFINITY;
78   	            }
79   	        }
80   	
81   	        pe__set_resource_flags(replica->child->parent, pcmk_rsc_assigning);
82   	        pe_rsc_trace(bundle, "Assigning bundle %s replica child %s",
83   	                     bundle->id, replica->child->id);
84   	        replica->child->cmds->assign(replica->child, replica->node,
85   	                                     stop_if_fail);
86   	        pe__clear_resource_flags(replica->child->parent, pcmk_rsc_assigning);
87   	    }
88   	    return true;
89   	}
90   	
91   	/*!
92   	 * \internal
93   	 * \brief Assign a bundle resource to a node
94   	 *
95   	 * \param[in,out] rsc           Resource to assign to a node
96   	 * \param[in]     prefer        Node to prefer, if all else is equal
97   	 * \param[in]     stop_if_fail  If \c true and a primitive descendant of \p rsc
98   	 *                              can't be assigned to a node, set the
99   	 *                              descendant's next role to stopped and update
100  	 *                              existing actions
101  	 *
102  	 * \return Node that \p rsc is assigned to, if assigned entirely to one node
103  	 *
104  	 * \note If \p stop_if_fail is \c false, then \c pcmk__unassign_resource() can
105  	 *       completely undo the assignment. A successful assignment can be either
106  	 *       undone or left alone as final. A failed assignment has the same effect
107  	 *       as calling pcmk__unassign_resource(); there are no side effects on
108  	 *       roles or actions.
109  	 */
110  	pcmk_node_t *
111  	pcmk__bundle_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer,
112  	                    bool stop_if_fail)
113  	{
114  	    GList *containers = NULL;
115  	    pcmk_resource_t *bundled_resource = NULL;
116  	    struct assign_data assign_data = { prefer, stop_if_fail };
117  	
118  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
119  	
120  	    pe_rsc_trace(rsc, "Assigning bundle %s", rsc->id);
121  	    pe__set_resource_flags(rsc, pcmk_rsc_assigning);
122  	
123  	    pe__show_node_scores(!pcmk_is_set(rsc->cluster->flags,
124  	                                      pcmk_sched_output_scores),
125  	                         rsc, __func__, rsc->allowed_nodes, rsc->cluster);
126  	
127  	    // Assign all containers first, so we know what nodes the bundle will be on
128  	    containers = g_list_sort(pe__bundle_containers(rsc), pcmk__cmp_instance);
129  	    pcmk__assign_instances(rsc, containers, pe__bundle_max(rsc),
130  	                           rsc->fns->max_per_node(rsc));
131  	    g_list_free(containers);
132  	
133  	    // Then assign remaining replica resources
134  	    pe__foreach_bundle_replica(rsc, assign_replica, (void *) &assign_data);
135  	
136  	    // Finally, assign the bundled resources to each bundle node
137  	    bundled_resource = pe__bundled_resource(rsc);
138  	    if (bundled_resource != NULL) {
139  	        pcmk_node_t *node = NULL;
140  	        GHashTableIter iter;
141  	
142  	        g_hash_table_iter_init(&iter, bundled_resource->allowed_nodes);
143  	        while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
144  	            if (pe__node_is_bundle_instance(rsc, node)) {
145  	                node->weight = 0;
146  	            } else {
147  	                node->weight = -INFINITY;
148  	            }
149  	        }
150  	        bundled_resource->cmds->assign(bundled_resource, prefer, stop_if_fail);
151  	    }
152  	
153  	    pe__clear_resource_flags(rsc, pcmk_rsc_assigning|pcmk_rsc_unassigned);
154  	    return NULL;
155  	}
156  	
157  	/*!
158  	 * \internal
159  	 * \brief Create actions for a bundle replica's resources (other than child)
160  	 *
161  	 * \param[in,out] replica    Replica to create actions for
162  	 * \param[in]     user_data  Unused
163  	 *
164  	 * \return true (to indicate that any further replicas should be processed)
165  	 */
166  	static bool
167  	create_replica_actions(pe__bundle_replica_t *replica, void *user_data)
168  	{
169  	    if (replica->ip != NULL) {
170  	        replica->ip->cmds->create_actions(replica->ip);
171  	    }
172  	    if (replica->container != NULL) {
173  	        replica->container->cmds->create_actions(replica->container);
174  	    }
175  	    if (replica->remote != NULL) {
176  	        replica->remote->cmds->create_actions(replica->remote);
177  	    }
178  	    return true;
179  	}
180  	
181  	/*!
182  	 * \internal
183  	 * \brief Create all actions needed for a given bundle resource
184  	 *
185  	 * \param[in,out] rsc  Bundle resource to create actions for
186  	 */
187  	void
188  	pcmk__bundle_create_actions(pcmk_resource_t *rsc)
189  	{
190  	    pcmk_action_t *action = NULL;
191  	    GList *containers = NULL;
192  	    pcmk_resource_t *bundled_resource = NULL;
193  	
194  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
195  	
196  	    pe__foreach_bundle_replica(rsc, create_replica_actions, NULL);
197  	
198  	    containers = pe__bundle_containers(rsc);
199  	    pcmk__create_instance_actions(rsc, containers);
200  	    g_list_free(containers);
201  	
202  	    bundled_resource = pe__bundled_resource(rsc);
203  	    if (bundled_resource != NULL) {
204  	        bundled_resource->cmds->create_actions(bundled_resource);
205  	
206  	        if (pcmk_is_set(bundled_resource->flags, pcmk_rsc_promotable)) {
207  	            pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_PROMOTE, true, true);
208  	            action = pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_PROMOTED,
209  	                                               true, true);
210  	            action->priority = INFINITY;
211  	
212  	            pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_DEMOTE, true, true);
213  	            action = pe__new_rsc_pseudo_action(rsc, PCMK_ACTION_DEMOTED,
214  	                                               true, true);
215  	            action->priority = INFINITY;
216  	        }
217  	    }
218  	}
219  	
220  	/*!
221  	 * \internal
222  	 * \brief Create internal constraints for a bundle replica's resources
223  	 *
224  	 * \param[in,out] replica    Replica to create internal constraints for
225  	 * \param[in,out] user_data  Replica's parent bundle
226  	 *
227  	 * \return true (to indicate that any further replicas should be processed)
228  	 */
229  	static bool
230  	replica_internal_constraints(pe__bundle_replica_t *replica, void *user_data)
231  	{
232  	    pcmk_resource_t *bundle = user_data;
233  	
234  	    replica->container->cmds->internal_constraints(replica->container);
235  	
236  	    // Start bundle -> start replica container
237  	    pcmk__order_starts(bundle, replica->container,
238  	                       pcmk__ar_unrunnable_first_blocks
239  	                       |pcmk__ar_then_implies_first_graphed);
240  	
241  	    // Stop bundle -> stop replica child and container
(54) Event example_checked: Example 4: "replica->child" has its value checked in "replica->child != NULL".
Also see events: [null_field][dereference][example_checked][example_checked][example_checked][example_checked]
242  	    if (replica->child != NULL) {
243  	        pcmk__order_stops(bundle, replica->child,
244  	                          pcmk__ar_then_implies_first_graphed);
245  	    }
246  	    pcmk__order_stops(bundle, replica->container,
247  	                      pcmk__ar_then_implies_first_graphed);
248  	
249  	    // Start replica container -> bundle is started
250  	    pcmk__order_resource_actions(replica->container, PCMK_ACTION_START, bundle,
251  	                                 PCMK_ACTION_RUNNING,
252  	                                 pcmk__ar_first_implies_then_graphed);
253  	
254  	    // Stop replica container -> bundle is stopped
255  	    pcmk__order_resource_actions(replica->container, PCMK_ACTION_STOP, bundle,
256  	                                 PCMK_ACTION_STOPPED,
257  	                                 pcmk__ar_first_implies_then_graphed);
258  	
259  	    if (replica->ip != NULL) {
260  	        replica->ip->cmds->internal_constraints(replica->ip);
261  	
262  	        // Replica IP address -> replica container (symmetric)
263  	        pcmk__order_starts(replica->ip, replica->container,
264  	                           pcmk__ar_unrunnable_first_blocks
265  	                           |pcmk__ar_guest_allowed);
266  	        pcmk__order_stops(replica->container, replica->ip,
267  	                          pcmk__ar_then_implies_first|pcmk__ar_guest_allowed);
268  	
269  	        pcmk__new_colocation("#ip-with-container", NULL, INFINITY, replica->ip,
270  	                             replica->container, NULL, NULL,
271  	                             pcmk__coloc_influence);
272  	    }
273  	
274  	    if (replica->remote != NULL) {
275  	        /* This handles ordering and colocating remote relative to container
276  	         * (via "#resource-with-container"). Since IP is also ordered and
277  	         * colocated relative to the container, we don't need to do anything
278  	         * explicit here with IP.
279  	         */
280  	        replica->remote->cmds->internal_constraints(replica->remote);
281  	    }
282  	
(55) Event example_checked: Example 5: "replica->child" has its value checked in "replica->child != NULL".
Also see events: [null_field][dereference][example_checked][example_checked][example_checked][example_checked]
283  	    if (replica->child != NULL) {
284  	        CRM_ASSERT(replica->remote != NULL);
285  	        // "Start remote then child" is implicit in scheduler's remote logic
286  	    }
287  	    return true;
288  	}
289  	
290  	/*!
291  	 * \internal
292  	 * \brief Create implicit constraints needed for a bundle resource
293  	 *
294  	 * \param[in,out] rsc  Bundle resource to create implicit constraints for
295  	 */
296  	void
297  	pcmk__bundle_internal_constraints(pcmk_resource_t *rsc)
298  	{
299  	    pcmk_resource_t *bundled_resource = NULL;
300  	
301  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
302  	
303  	    pe__foreach_bundle_replica(rsc, replica_internal_constraints, rsc);
304  	
305  	    bundled_resource = pe__bundled_resource(rsc);
306  	    if (bundled_resource == NULL) {
307  	        return;
308  	    }
309  	
310  	    // Start bundle -> start bundled clone
311  	    pcmk__order_resource_actions(rsc, PCMK_ACTION_START, bundled_resource,
312  	                                 PCMK_ACTION_START,
313  	                                 pcmk__ar_then_implies_first_graphed);
314  	
315  	    // Bundled clone is started -> bundle is started
316  	    pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_RUNNING,
317  	                                 rsc, PCMK_ACTION_RUNNING,
318  	                                 pcmk__ar_first_implies_then_graphed);
319  	
320  	    // Stop bundle -> stop bundled clone
321  	    pcmk__order_resource_actions(rsc, PCMK_ACTION_STOP, bundled_resource,
322  	                                 PCMK_ACTION_STOP,
323  	                                 pcmk__ar_then_implies_first_graphed);
324  	
325  	    // Bundled clone is stopped -> bundle is stopped
326  	    pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_STOPPED,
327  	                                 rsc, PCMK_ACTION_STOPPED,
328  	                                 pcmk__ar_first_implies_then_graphed);
329  	
330  	    bundled_resource->cmds->internal_constraints(bundled_resource);
331  	
332  	    if (!pcmk_is_set(bundled_resource->flags, pcmk_rsc_promotable)) {
333  	        return;
334  	    }
335  	    pcmk__promotable_restart_ordering(rsc);
336  	
337  	    // Demote bundle -> demote bundled clone
338  	    pcmk__order_resource_actions(rsc, PCMK_ACTION_DEMOTE, bundled_resource,
339  	                                 PCMK_ACTION_DEMOTE,
340  	                                 pcmk__ar_then_implies_first_graphed);
341  	
342  	    // Bundled clone is demoted -> bundle is demoted
343  	    pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_DEMOTED,
344  	                                 rsc, PCMK_ACTION_DEMOTED,
345  	                                 pcmk__ar_first_implies_then_graphed);
346  	
347  	    // Promote bundle -> promote bundled clone
348  	    pcmk__order_resource_actions(rsc, PCMK_ACTION_PROMOTE,
349  	                                 bundled_resource, PCMK_ACTION_PROMOTE,
350  	                                 pcmk__ar_then_implies_first_graphed);
351  	
352  	    // Bundled clone is promoted -> bundle is promoted
353  	    pcmk__order_resource_actions(bundled_resource, PCMK_ACTION_PROMOTED,
354  	                                 rsc, PCMK_ACTION_PROMOTED,
355  	                                 pcmk__ar_first_implies_then_graphed);
356  	}
357  	
358  	struct match_data {
359  	    const pcmk_node_t *node;    // Node to compare against replica
360  	    pcmk_resource_t *container; // Replica container corresponding to node
361  	};
362  	
363  	/*!
364  	 * \internal
365  	 * \brief Check whether a replica container is assigned to a given node
366  	 *
367  	 * \param[in]     replica    Replica to check
368  	 * \param[in,out] user_data  struct match_data with node to compare against
369  	 *
370  	 * \return true if the replica does not match (to indicate further replicas
371  	 *         should be processed), otherwise false
372  	 */
373  	static bool
374  	match_replica_container(const pe__bundle_replica_t *replica, void *user_data)
375  	{
376  	    struct match_data *match_data = user_data;
377  	
378  	    if (pcmk__instance_matches(replica->container, match_data->node,
379  	                               pcmk_role_unknown, false)) {
380  	        match_data->container = replica->container;
381  	        return false; // Match found, don't bother searching further replicas
382  	    }
383  	    return true; // No match, keep searching
384  	}
385  	
386  	/*!
387  	 * \internal
388  	 * \brief Get the host to which a bundle node is assigned
389  	 *
390  	 * \param[in] node  Possible bundle node to check
391  	 *
392  	 * \return Node to which the container for \p node is assigned if \p node is a
393  	 *         bundle node, otherwise \p node itself
394  	 */
395  	static const pcmk_node_t *
396  	get_bundle_node_host(const pcmk_node_t *node)
397  	{
398  	    if (pe__is_bundle_node(node)) {
399  	        const pcmk_resource_t *container = node->details->remote_rsc->container;
400  	
401  	        return container->fns->location(container, NULL, 0);
402  	    }
403  	    return node;
404  	}
405  	
406  	/*!
407  	 * \internal
408  	 * \brief Find a bundle container compatible with a dependent resource
409  	 *
410  	 * \param[in] dependent  Dependent resource in colocation with bundle
411  	 * \param[in] bundle     Bundle that \p dependent is colocated with
412  	 *
413  	 * \return A container from \p bundle assigned to the same node as \p dependent
414  	 *         if assigned, otherwise assigned to any of dependent's allowed nodes,
415  	 *         otherwise NULL.
416  	 */
417  	static pcmk_resource_t *
418  	compatible_container(const pcmk_resource_t *dependent,
419  	                     const pcmk_resource_t *bundle)
420  	{
421  	    GList *scratch = NULL;
422  	    struct match_data match_data = { NULL, NULL };
423  	
424  	    // If dependent is assigned, only check there
425  	    match_data.node = dependent->fns->location(dependent, NULL, 0);
426  	    match_data.node = get_bundle_node_host(match_data.node);
427  	    if (match_data.node != NULL) {
428  	        pe__foreach_const_bundle_replica(bundle, match_replica_container,
429  	                                         &match_data);
430  	        return match_data.container;
431  	    }
432  	
433  	    // Otherwise, check for any of the dependent's allowed nodes
434  	    scratch = g_hash_table_get_values(dependent->allowed_nodes);
435  	    scratch = pcmk__sort_nodes(scratch, NULL);
436  	    for (const GList *iter = scratch; iter != NULL; iter = iter->next) {
437  	        match_data.node = iter->data;
438  	        match_data.node = get_bundle_node_host(match_data.node);
439  	        if (match_data.node == NULL) {
440  	            continue;
441  	        }
442  	
443  	        pe__foreach_const_bundle_replica(bundle, match_replica_container,
444  	                                         &match_data);
445  	        if (match_data.container != NULL) {
446  	            break;
447  	        }
448  	    }
449  	    g_list_free(scratch);
450  	    return match_data.container;
451  	}
452  	
453  	struct coloc_data {
454  	    const pcmk__colocation_t *colocation;
455  	    pcmk_resource_t *dependent;
456  	    GList *container_hosts;
457  	};
458  	
459  	/*!
460  	 * \internal
461  	 * \brief Apply a colocation score to replica node scores or resource priority
462  	 *
463  	 * \param[in]     replica    Replica of primary bundle resource in colocation
464  	 * \param[in,out] user_data  struct coloc_data for colocation being applied
465  	 *
466  	 * \return true (to indicate that any further replicas should be processed)
467  	 */
468  	static bool
469  	replica_apply_coloc_score(const pe__bundle_replica_t *replica, void *user_data)
470  	{
471  	    struct coloc_data *coloc_data = user_data;
472  	    pcmk_node_t *chosen = NULL;
473  	
474  	    if (coloc_data->colocation->score < INFINITY) {
475  	        replica->container->cmds->apply_coloc_score(coloc_data->dependent,
476  	                                                    replica->container,
477  	                                                    coloc_data->colocation,
478  	                                                    false);
479  	        return true;
480  	    }
481  	
482  	    chosen = replica->container->fns->location(replica->container, NULL, 0);
483  	    if ((chosen == NULL)
484  	        || is_set_recursive(replica->container, pcmk_rsc_blocked, true)) {
485  	        return true;
486  	    }
487  	
(53) Event example_checked: Example 3: "replica->child" has its value checked in "replica->child == NULL".
Also see events: [null_field][dereference][example_checked][example_checked][example_checked][example_checked]
488  	    if ((coloc_data->colocation->primary_role >= pcmk_role_promoted)
489  	        && ((replica->child == NULL)
490  	            || (replica->child->next_role < pcmk_role_promoted))) {
491  	        return true;
492  	    }
493  	
494  	    pe_rsc_trace(pe__const_top_resource(replica->container, true),
495  	                 "Allowing mandatory colocation %s using %s @%d",
496  	                 coloc_data->colocation->id, pe__node_name(chosen),
497  	                 chosen->weight);
498  	    coloc_data->container_hosts = g_list_prepend(coloc_data->container_hosts,
499  	                                                 chosen);
500  	    return true;
501  	}
502  	
503  	/*!
504  	 * \internal
505  	 * \brief Apply a colocation's score to node scores or resource priority
506  	 *
507  	 * Given a colocation constraint, apply its score to the dependent's
508  	 * allowed node scores (if we are still placing resources) or priority (if
509  	 * we are choosing promotable clone instance roles).
510  	 *
511  	 * \param[in,out] dependent      Dependent resource in colocation
512  	 * \param[in]     primary        Primary resource in colocation
513  	 * \param[in]     colocation     Colocation constraint to apply
514  	 * \param[in]     for_dependent  true if called on behalf of dependent
515  	 */
516  	void
517  	pcmk__bundle_apply_coloc_score(pcmk_resource_t *dependent,
518  	                               const pcmk_resource_t *primary,
519  	                               const pcmk__colocation_t *colocation,
520  	                               bool for_dependent)
521  	{
522  	    struct coloc_data coloc_data = { colocation, dependent, NULL };
523  	
524  	    /* This should never be called for the bundle itself as a dependent.
525  	     * Instead, we add its colocation constraints to its containers and bundled
526  	     * primitive and call the apply_coloc_score() method for them as dependents.
527  	     */
528  	    CRM_ASSERT((primary != NULL)
529  	               && (primary->variant == pcmk_rsc_variant_bundle)
530  	               && (dependent != NULL)
531  	               && (dependent->variant == pcmk_rsc_variant_primitive)
532  	               && (colocation != NULL) && !for_dependent);
533  	
534  	    if (pcmk_is_set(primary->flags, pcmk_rsc_unassigned)) {
535  	        pe_rsc_trace(primary,
536  	                     "Skipping applying colocation %s "
537  	                     "because %s is still provisional",
538  	                     colocation->id, primary->id);
539  	        return;
540  	    }
541  	    pe_rsc_trace(primary, "Applying colocation %s (%s with %s at %s)",
542  	                 colocation->id, dependent->id, primary->id,
543  	                 pcmk_readable_score(colocation->score));
544  	
545  	    /* If the constraint dependent is a clone or bundle, "dependent" here is one
546  	     * of its instances. Look for a compatible instance of this bundle.
547  	     */
548  	    if (colocation->dependent->variant > pcmk_rsc_variant_group) {
549  	        const pcmk_resource_t *primary_container = NULL;
550  	
551  	        primary_container = compatible_container(dependent, primary);
552  	        if (primary_container != NULL) { // Success, we found one
553  	            pe_rsc_debug(primary, "Pairing %s with %s",
554  	                         dependent->id, primary_container->id);
555  	            dependent->cmds->apply_coloc_score(dependent, primary_container,
556  	                                               colocation, true);
557  	
558  	        } else if (colocation->score >= INFINITY) { // Failure, and it's fatal
559  	            crm_notice("%s cannot run because there is no compatible "
560  	                       "instance of %s to colocate with",
561  	                       dependent->id, primary->id);
562  	            pcmk__assign_resource(dependent, NULL, true, true);
563  	
564  	        } else { // Failure, but we can ignore it
565  	            pe_rsc_debug(primary,
566  	                         "%s cannot be colocated with any instance of %s",
567  	                         dependent->id, primary->id);
568  	        }
569  	        return;
570  	    }
571  	
572  	    pe__foreach_const_bundle_replica(primary, replica_apply_coloc_score,
573  	                                     &coloc_data);
574  	
575  	    if (colocation->score >= INFINITY) {
576  	        pcmk__colocation_intersect_nodes(dependent, primary, colocation,
577  	                                         coloc_data.container_hosts, false);
578  	    }
579  	    g_list_free(coloc_data.container_hosts);
580  	}
581  	
582  	// Bundle implementation of pcmk_assignment_methods_t:with_this_colocations()
583  	void
584  	pcmk__with_bundle_colocations(const pcmk_resource_t *rsc,
585  	                              const pcmk_resource_t *orig_rsc, GList **list)
586  	{
587  	    const pcmk_resource_t *bundled_rsc = NULL;
588  	
589  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle)
590  	               && (orig_rsc != NULL) && (list != NULL));
591  	
592  	    // The bundle itself and its containers always get its colocations
593  	    if ((orig_rsc == rsc)
594  	        || pcmk_is_set(orig_rsc->flags, pcmk_rsc_replica_container)) {
595  	
596  	        pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
597  	        return;
598  	    }
599  	
600  	    /* The bundled resource gets the colocations if it's promotable and we've
601  	     * begun choosing roles
602  	     */
603  	    bundled_rsc = pe__bundled_resource(rsc);
604  	    if ((bundled_rsc == NULL)
605  	        || !pcmk_is_set(bundled_rsc->flags, pcmk_rsc_promotable)
606  	        || (pe__const_top_resource(orig_rsc, false) != bundled_rsc)) {
607  	        return;
608  	    }
609  	
610  	    if (orig_rsc == bundled_rsc) {
611  	        if (pe__clone_flag_is_set(orig_rsc,
612  	                                  pcmk__clone_promotion_constrained)) {
613  	            /* orig_rsc is the clone and we're setting roles (or have already
614  	             * done so)
615  	             */
616  	            pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
617  	        }
618  	
619  	    } else if (!pcmk_is_set(orig_rsc->flags, pcmk_rsc_unassigned)) {
620  	        /* orig_rsc is an instance and is already assigned. If something
621  	         * requests colocations for orig_rsc now, it's for setting roles.
622  	         */
623  	        pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
624  	    }
625  	}
626  	
627  	// Bundle implementation of pcmk_assignment_methods_t:this_with_colocations()
628  	void
629  	pcmk__bundle_with_colocations(const pcmk_resource_t *rsc,
630  	                              const pcmk_resource_t *orig_rsc, GList **list)
631  	{
632  	    const pcmk_resource_t *bundled_rsc = NULL;
633  	
634  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle)
635  	               && (orig_rsc != NULL) && (list != NULL));
636  	
637  	    // The bundle itself and its containers always get its colocations
638  	    if ((orig_rsc == rsc)
639  	        || pcmk_is_set(orig_rsc->flags, pcmk_rsc_replica_container)) {
640  	
641  	        pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
642  	        return;
643  	    }
644  	
645  	    /* The bundled resource gets the colocations if it's promotable and we've
646  	     * begun choosing roles
647  	     */
648  	    bundled_rsc = pe__bundled_resource(rsc);
649  	    if ((bundled_rsc == NULL)
650  	        || !pcmk_is_set(bundled_rsc->flags, pcmk_rsc_promotable)
651  	        || (pe__const_top_resource(orig_rsc, false) != bundled_rsc)) {
652  	        return;
653  	    }
654  	
655  	    if (orig_rsc == bundled_rsc) {
656  	        if (pe__clone_flag_is_set(orig_rsc,
657  	                                  pcmk__clone_promotion_constrained)) {
658  	            /* orig_rsc is the clone and we're setting roles (or have already
659  	             * done so)
660  	             */
661  	            pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
662  	        }
663  	
664  	    } else if (!pcmk_is_set(orig_rsc->flags, pcmk_rsc_unassigned)) {
665  	        /* orig_rsc is an instance and is already assigned. If something
666  	         * requests colocations for orig_rsc now, it's for setting roles.
667  	         */
668  	        pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
669  	    }
670  	}
671  	
672  	/*!
673  	 * \internal
674  	 * \brief Return action flags for a given bundle resource action
675  	 *
676  	 * \param[in,out] action  Bundle resource action to get flags for
677  	 * \param[in]     node    If not NULL, limit effects to this node
678  	 *
679  	 * \return Flags appropriate to \p action on \p node
680  	 */
681  	uint32_t
682  	pcmk__bundle_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
683  	{
684  	    GList *containers = NULL;
685  	    uint32_t flags = 0;
686  	    pcmk_resource_t *bundled_resource = NULL;
687  	
688  	    CRM_ASSERT((action != NULL) && (action->rsc != NULL)
689  	               && (action->rsc->variant == pcmk_rsc_variant_bundle));
690  	
691  	    bundled_resource = pe__bundled_resource(action->rsc);
692  	    if (bundled_resource != NULL) {
693  	        // Clone actions are done on the bundled clone resource, not container
694  	        switch (get_complex_task(bundled_resource, action->task)) {
695  	            case pcmk_action_unspecified:
696  	            case pcmk_action_notify:
697  	            case pcmk_action_notified:
698  	            case pcmk_action_promote:
699  	            case pcmk_action_promoted:
700  	            case pcmk_action_demote:
701  	            case pcmk_action_demoted:
702  	                return pcmk__collective_action_flags(action,
703  	                                                     bundled_resource->children,
704  	                                                     node);
705  	            default:
706  	                break;
707  	        }
708  	    }
709  	
710  	    containers = pe__bundle_containers(action->rsc);
711  	    flags = pcmk__collective_action_flags(action, containers, node);
712  	    g_list_free(containers);
713  	    return flags;
714  	}
715  	
716  	/*!
717  	 * \internal
718  	 * \brief Apply a location constraint to a bundle replica
719  	 *
720  	 * \param[in,out] replica    Replica to apply constraint to
721  	 * \param[in,out] user_data  Location constraint to apply
722  	 *
723  	 * \return true (to indicate that any further replicas should be processed)
724  	 */
725  	static bool
726  	apply_location_to_replica(pe__bundle_replica_t *replica, void *user_data)
727  	{
728  	    pe__location_t *location = user_data;
729  	
730  	    if (replica->container != NULL) {
731  	        replica->container->cmds->apply_location(replica->container, location);
732  	    }
733  	    if (replica->ip != NULL) {
734  	        replica->ip->cmds->apply_location(replica->ip, location);
735  	    }
736  	    return true;
737  	}
738  	
739  	/*!
740  	 * \internal
741  	 * \brief Apply a location constraint to a bundle resource's allowed node scores
742  	 *
743  	 * \param[in,out] rsc       Bundle resource to apply constraint to
744  	 * \param[in,out] location  Location constraint to apply
745  	 */
746  	void
747  	pcmk__bundle_apply_location(pcmk_resource_t *rsc, pe__location_t *location)
748  	{
749  	    pcmk_resource_t *bundled_resource = NULL;
750  	
751  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle)
752  	               && (location != NULL));
753  	
754  	    pcmk__apply_location(rsc, location);
755  	    pe__foreach_bundle_replica(rsc, apply_location_to_replica, location);
756  	
757  	    bundled_resource = pe__bundled_resource(rsc);
758  	    if ((bundled_resource != NULL)
759  	        && ((location->role_filter == pcmk_role_unpromoted)
760  	            || (location->role_filter == pcmk_role_promoted))) {
761  	        bundled_resource->cmds->apply_location(bundled_resource, location);
762  	        bundled_resource->rsc_location = g_list_prepend(
763  	            bundled_resource->rsc_location, location);
764  	    }
765  	}
766  	
767  	#define XPATH_REMOTE "//nvpair[@name='" XML_RSC_ATTR_REMOTE_RA_ADDR "']"
768  	
769  	/*!
770  	 * \internal
771  	 * \brief Add a bundle replica's actions to transition graph
772  	 *
773  	 * \param[in,out] replica    Replica to add to graph
774  	 * \param[in]     user_data  Bundle that replica belongs to (for logging only)
775  	 *
776  	 * \return true (to indicate that any further replicas should be processed)
777  	 */
778  	static bool
779  	add_replica_actions_to_graph(pe__bundle_replica_t *replica, void *user_data)
780  	{
781  	    if ((replica->remote != NULL) && (replica->container != NULL)
782  	        && pe__bundle_needs_remote_name(replica->remote)) {
783  	
784  	        /* REMOTE_CONTAINER_HACK: Allow remote nodes to run containers that
785  	         * run pacemaker-remoted inside, without needing a separate IP for
786  	         * the container. This is done by configuring the inner remote's
787  	         * connection host as the magic string "#uname", then
788  	         * replacing it with the underlying host when needed.
789  	         */
790  	        xmlNode *nvpair = get_xpath_object(XPATH_REMOTE, replica->remote->xml,
791  	                                           LOG_ERR);
792  	        const char *calculated_addr = NULL;
793  	
794  	        // Replace the value in replica->remote->xml (if appropriate)
795  	        calculated_addr = pe__add_bundle_remote_name(replica->remote,
796  	                                                     replica->remote->cluster,
797  	                                                     nvpair, "value");
798  	        if (calculated_addr != NULL) {
799  	            /* Since this is for the bundle as a resource, and not any
800  	             * particular action, replace the value in the default
801  	             * parameters (not evaluated for node). create_graph_action()
802  	             * will grab it from there to replace it in node-evaluated
803  	             * parameters.
804  	             */
805  	            GHashTable *params = pe_rsc_params(replica->remote,
806  	                                               NULL, replica->remote->cluster);
807  	
808  	            g_hash_table_replace(params,
809  	                                 strdup(XML_RSC_ATTR_REMOTE_RA_ADDR),
810  	                                 strdup(calculated_addr));
811  	        } else {
812  	            pcmk_resource_t *bundle = user_data;
813  	
814  	            /* The only way to get here is if the remote connection is
815  	             * neither currently running nor scheduled to run. That means we
816  	             * won't be doing any operations that require addr (only start
817  	             * requires it; we additionally use it to compare digests when
818  	             * unpacking status, promote, and migrate_from history, but
819  	             * that's already happened by this point).
820  	             */
821  	            pe_rsc_info(bundle,
822  	                        "Unable to determine address for bundle %s "
823  	                        "remote connection", bundle->id);
824  	        }
825  	    }
826  	    if (replica->ip != NULL) {
827  	        replica->ip->cmds->add_actions_to_graph(replica->ip);
828  	    }
829  	    if (replica->container != NULL) {
830  	        replica->container->cmds->add_actions_to_graph(replica->container);
831  	    }
832  	    if (replica->remote != NULL) {
833  	        replica->remote->cmds->add_actions_to_graph(replica->remote);
834  	    }
835  	    return true;
836  	}
837  	
838  	/*!
839  	 * \internal
840  	 * \brief Add a bundle resource's actions to the transition graph
841  	 *
842  	 * \param[in,out] rsc  Bundle resource whose actions should be added
843  	 */
844  	void
845  	pcmk__bundle_add_actions_to_graph(pcmk_resource_t *rsc)
846  	{
847  	    pcmk_resource_t *bundled_resource = NULL;
848  	
849  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
850  	
851  	    bundled_resource = pe__bundled_resource(rsc);
852  	    if (bundled_resource != NULL) {
853  	        bundled_resource->cmds->add_actions_to_graph(bundled_resource);
854  	    }
855  	    pe__foreach_bundle_replica(rsc, add_replica_actions_to_graph, rsc);
856  	}
857  	
858  	struct probe_data {
859  	    pcmk_resource_t *bundle;    // Bundle being probed
860  	    pcmk_node_t *node;          // Node to create probes on
861  	    bool any_created;           // Whether any probes have been created
862  	};
863  	
864  	/*!
865  	 * \internal
866  	 * \brief Order a bundle replica's start after another replica's probe
867  	 *
868  	 * \param[in,out] replica    Replica to order start for
869  	 * \param[in,out] user_data  Replica with probe to order after
870  	 *
871  	 * \return true (to indicate that any further replicas should be processed)
872  	 */
873  	static bool
874  	order_replica_start_after(pe__bundle_replica_t *replica, void *user_data)
875  	{
876  	    pe__bundle_replica_t *probed_replica = user_data;
877  	
878  	    if ((replica == probed_replica) || (replica->container == NULL)) {
879  	        return true;
880  	    }
881  	    pcmk__new_ordering(probed_replica->container,
882  	                       pcmk__op_key(probed_replica->container->id,
883  	                                    PCMK_ACTION_MONITOR, 0),
884  	                       NULL, replica->container,
885  	                       pcmk__op_key(replica->container->id, PCMK_ACTION_START,
886  	                                    0),
887  	                       NULL, pcmk__ar_ordered|pcmk__ar_if_on_same_node,
888  	                       replica->container->cluster);
889  	    return true;
890  	}
891  	
892  	/*!
893  	 * \internal
894  	 * \brief Create probes for a bundle replica's resources
895  	 *
896  	 * \param[in,out] replica    Replica to create probes for
897  	 * \param[in,out] user_data  struct probe_data
898  	 *
899  	 * \return true (to indicate that any further replicas should be processed)
900  	 */
901  	static bool
902  	create_replica_probes(pe__bundle_replica_t *replica, void *user_data)
903  	{
904  	    struct probe_data *probe_data = user_data;
905  	
906  	    if ((replica->ip != NULL)
907  	        && replica->ip->cmds->create_probe(replica->ip, probe_data->node)) {
908  	        probe_data->any_created = true;
909  	    }
(52) Event example_checked: Example 2: "replica->child" has its value checked in "replica->child != NULL".
Also see events: [null_field][dereference][example_checked][example_checked][example_checked][example_checked]
910  	    if ((replica->child != NULL)
911  	        && pe__same_node(probe_data->node, replica->node)
912  	        && replica->child->cmds->create_probe(replica->child,
913  	                                              probe_data->node)) {
914  	        probe_data->any_created = true;
915  	    }
916  	    if ((replica->container != NULL)
917  	        && replica->container->cmds->create_probe(replica->container,
918  	                                                  probe_data->node)) {
919  	        probe_data->any_created = true;
920  	
921  	        /* If we're limited to one replica per host (due to
922  	         * the lack of an IP range probably), then we don't
923  	         * want any of our peer containers starting until
924  	         * we've established that no other copies are already
925  	         * running.
926  	         *
927  	         * Partly this is to ensure that the maximum replicas per host is
928  	         * observed, but also to ensure that the containers
929  	         * don't fail to start because the necessary port
930  	         * mappings (which won't include an IP for uniqueness)
931  	         * are already taken
932  	         */
933  	        if (probe_data->bundle->fns->max_per_node(probe_data->bundle) == 1) {
934  	            pe__foreach_bundle_replica(probe_data->bundle,
935  	                                       order_replica_start_after, replica);
936  	        }
937  	    }
938  	    if ((replica->container != NULL) && (replica->remote != NULL)
939  	        && replica->remote->cmds->create_probe(replica->remote,
940  	                                               probe_data->node)) {
941  	        /* Do not probe the remote resource until we know where the container is
942  	         * running. This is required for REMOTE_CONTAINER_HACK to correctly
943  	         * probe remote resources.
944  	         */
945  	        char *probe_uuid = pcmk__op_key(replica->remote->id,
946  	                                        PCMK_ACTION_MONITOR, 0);
947  	        pcmk_action_t *probe = find_first_action(replica->remote->actions,
948  	                                                 probe_uuid, NULL,
949  	                                                 probe_data->node);
950  	
951  	        free(probe_uuid);
952  	        if (probe != NULL) {
953  	            probe_data->any_created = true;
954  	            pe_rsc_trace(probe_data->bundle, "Ordering %s probe on %s",
955  	                         replica->remote->id, pe__node_name(probe_data->node));
956  	            pcmk__new_ordering(replica->container,
957  	                               pcmk__op_key(replica->container->id,
958  	                                            PCMK_ACTION_START, 0),
959  	                               NULL, replica->remote, NULL, probe,
960  	                               pcmk__ar_nested_remote_probe,
961  	                               probe_data->bundle->cluster);
962  	        }
963  	    }
964  	    return true;
965  	}
966  	
967  	/*!
968  	 * \internal
969  	 *
970  	 * \brief Schedule any probes needed for a bundle resource on a node
971  	 *
972  	 * \param[in,out] rsc   Bundle resource to create probes for
973  	 * \param[in,out] node  Node to create probe on
974  	 *
975  	 * \return true if any probe was created, otherwise false
976  	 */
977  	bool
978  	pcmk__bundle_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
979  	{
980  	    struct probe_data probe_data = { rsc, node, false };
981  	
982  	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
983  	    pe__foreach_bundle_replica(rsc, create_replica_probes, &probe_data);
984  	    return probe_data.any_created;
985  	}
986  	
987  	/*!
988  	 * \internal
989  	 * \brief Output actions for one bundle replica
990  	 *
991  	 * \param[in,out] replica    Replica to output actions for
992  	 * \param[in]     user_data  Unused
993  	 *
994  	 * \return true (to indicate that any further replicas should be processed)
995  	 */
996  	static bool
997  	output_replica_actions(pe__bundle_replica_t *replica, void *user_data)
998  	{
999  	    if (replica->ip != NULL) {
1000 	        replica->ip->cmds->output_actions(replica->ip);
1001 	    }
1002 	    if (replica->container != NULL) {
1003 	        replica->container->cmds->output_actions(replica->container);
1004 	    }
1005 	    if (replica->remote != NULL) {
1006 	        replica->remote->cmds->output_actions(replica->remote);
1007 	    }
1008 	    if (replica->child != NULL) {
1009 	        replica->child->cmds->output_actions(replica->child);
1010 	    }
1011 	    return true;
1012 	}
1013 	
1014 	/*!
1015 	 * \internal
1016 	 * \brief Output a summary of scheduled actions for a bundle resource
1017 	 *
1018 	 * \param[in,out] rsc  Bundle resource to output actions for
1019 	 */
1020 	void
1021 	pcmk__output_bundle_actions(pcmk_resource_t *rsc)
1022 	{
1023 	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
1024 	    pe__foreach_bundle_replica(rsc, output_replica_actions, NULL);
1025 	}
1026 	
1027 	// Bundle implementation of pcmk_assignment_methods_t:add_utilization()
1028 	void
1029 	pcmk__bundle_add_utilization(const pcmk_resource_t *rsc,
1030 	                             const pcmk_resource_t *orig_rsc, GList *all_rscs,
1031 	                             GHashTable *utilization)
1032 	{
1033 	    pcmk_resource_t *container = NULL;
1034 	
1035 	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
1036 	
1037 	    if (!pcmk_is_set(rsc->flags, pcmk_rsc_unassigned)) {
1038 	        return;
1039 	    }
1040 	
1041 	    /* All bundle replicas are identical, so using the utilization of the first
1042 	     * is sufficient for any. Only the implicit container resource can have
1043 	     * utilization values.
1044 	     */
1045 	    container = pe__first_container(rsc);
1046 	    if (container != NULL) {
1047 	        container->cmds->add_utilization(container, orig_rsc, all_rscs,
1048 	                                         utilization);
1049 	    }
1050 	}
1051 	
1052 	// Bundle implementation of pcmk_assignment_methods_t:shutdown_lock()
1053 	void
1054 	pcmk__bundle_shutdown_lock(pcmk_resource_t *rsc)
1055 	{
1056 	    CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle));
1057 	    // Bundles currently don't support shutdown locks
1058 	}
1059